diff --git a/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro
index b63c75c0700d2950c7372330c6cf702a8d5f3f1f..ce16a3a391120289f241740c3708301887b7773f 100644
--- a/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro
+++ b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro
@@ -4,4 +4,8 @@ CONFIG -= qt
 
 INCLUDEPATH += $$QMAKE_INCDIR_EGL
 
-LIBS += -L$$QMAKE_LIBDIR_EGL -lEGL -lGLESv2 -lbcm_host
+for(p, QMAKE_LIBDIR_EGL) {
+    exists($$p):LIBS += -L$$p
+}
+
+LIBS += -lEGL -lGLESv2 -lbcm_host
diff --git a/configure b/configure
index 6b59a888d49cbfd9d20a0ed1dc07910052d845f4..7251e8e673bb776eb900a13d322438a8130e1784 100755
--- a/configure
+++ b/configure
@@ -728,6 +728,7 @@ CFG_EVENTFD=auto
 CFG_RPATH=yes
 CFG_FRAMEWORK=auto
 CFG_USE_GOLD_LINKER=auto
+CFG_ENABLE_NEW_DTAGS=auto
 DEFINES=
 INCLUDES=
 D_FLAGS=
@@ -2961,8 +2962,20 @@ if [ -f "$relpath"/LICENSE.PREVIEW.COMMERCIAL ] && [ $COMMERCIAL_USER = "yes" ];
     Edition="Preview"
     EditionString="Technology Preview"
 elif [ $COMMERCIAL_USER = "yes" ]; then
-    if test -x "$relpath/bin/licheck"; then
-        LicheckOutput=`$relpath/bin/licheck $OPT_CONFIRM_LICENSE $relpath $outpath\
+    if [ $UNAME_SYSTEM = "Linux" ]; then
+        if file -L /bin/sh | grep -q "64-bit" ; then
+            Licheck=licheck64
+        else
+            Licheck=licheck32
+        fi
+    elif [ $UNAME_SYSTEM = "Darwin" ]; then
+        Licheck=licheck_mac
+    else
+        echo >&2 "Host operating system not supported by this edition of Qt."
+        exit 1
+    fi
+    if [ -x "$relpath/bin/$Licheck" ]; then
+        LicheckOutput=`$relpath/bin/$Licheck $OPT_CONFIRM_LICENSE $relpath $outpath\
                        $PLATFORM $XPLATFORM`
         if [ $? -ne 0 ]; then
             exit 1
@@ -2973,7 +2986,7 @@ elif [ $COMMERCIAL_USER = "yes" ]; then
         echo
         echo "Error: This is the Open Source version of Qt."
         echo "If you want to use Enterprise features of Qt,"
-        echo "information use the contact form at http://www.qt.io/contact-us"
+        echo "use the contact form at http://www.qt.io/contact-us"
         echo "to purchase a license."
         echo
         exit 1
@@ -3305,7 +3318,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
     CFG_RPATH="no"
     CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples"
     CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store
-    CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples"
+    CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples"
     CFG_PRECOMPILE="no" # Precompiled headers not supported with multiple -arch arguments
 
     # If the user passes -sdk on the command line we build a SDK-specific Qt build.
@@ -3442,6 +3455,13 @@ if [ "$CFG_USE_GOLD_LINKER" != "no" ]; then
     fi
 fi
 
+# auto-detect --enable-new-dtags support
+if linkerSupportsFlag $TEST_COMPILER --enable-new-dtags; then
+    CFG_ENABLE_NEW_DTAGS=yes
+else
+    CFG_ENABLE_NEW_DTAGS=no
+fi
+
 # auto-detect -fstack-protector-strong support (for QNX only currently)
 if [ "$XPLATFORM_QNX" = "yes" ]; then
     if compilerSupportsFlag $TEST_COMPILER -fstack-protector-strong; then
@@ -5338,6 +5358,14 @@ fi
 # auto-detect XInput2 support
 if [ "$CFG_XINPUT2" != "no" ]; then
     if compileTest x11/xinput2 "XInput2"; then
+        if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists xi 2>/dev/null; then
+            QMAKE_LIBXI_VERSION_MAJOR=`$PKG_CONFIG --modversion xi 2>/dev/null | cut -d . -f 1`
+            QMAKE_LIBXI_VERSION_MINOR=`$PKG_CONFIG --modversion xi 2>/dev/null | cut -d . -f 2`
+            QMAKE_LIBXI_VERSION_PATCH=`$PKG_CONFIG --modversion xi 2>/dev/null | cut -d . -f 3`
+            QMakeVar set QMAKE_LIBXI_VERSION_MAJOR "$QMAKE_LIBXI_VERSION_MAJOR"
+            QMakeVar set QMAKE_LIBXI_VERSION_MINOR "$QMAKE_LIBXI_VERSION_MINOR"
+            QMakeVar set QMAKE_LIBXI_VERSION_PATCH "$QMAKE_LIBXI_VERSION_PATCH"
+        fi
         CFG_XINPUT2=yes
         CFG_XINPUT=no
     else
@@ -6067,6 +6095,7 @@ fi
 [ "$CFG_STRIP" = "no" ] && QMAKE_CONFIG="$QMAKE_CONFIG nostrip"
 [ "$CFG_PRECOMPILE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG precompile_header"
 [ "$CFG_USE_GOLD_LINKER" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG use_gold_linker"
+[ "$CFG_ENABLE_NEW_DTAGS" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG enable_new_dtags"
 if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then
     QT_CONFIG="$QT_CONFIG separate_debug_info"
 fi
@@ -6196,11 +6225,7 @@ fi
 [ '!' -z "$INCLUDES" ] && QMakeVar add INCLUDEPATH "$INCLUDES"
 [ '!' -z "$L_FLAGS" ] && QMakeVar add LIBS "$L_FLAGS"
 
-if [ "$XPLATFORM_MAC" = "yes" ] && [ "$QT_CROSS_COMPILE" = "no" ]; then
-    if [ "$CFG_RPATH" = "yes" ]; then
-       QMAKE_CONFIG="$QMAKE_CONFIG absolute_library_soname"
-    fi
-elif [ -z "`getXQMakeConf 'QMAKE_(LFLAGS_)?RPATH'`" ]; then
+if [ -z "`getXQMakeConf 'QMAKE_(LFLAGS_)?RPATH'`" ]; then
     if [ -n "$RPATH_FLAGS" ]; then
         echo
         echo "ERROR: -R cannot be used on this platform as \$QMAKE_LFLAGS_RPATH is"
@@ -6758,8 +6783,15 @@ QT_PATCH_VERSION = $QT_PATCH_VERSION
 QT_LIBINFIX = $QT_LIBINFIX
 QT_NAMESPACE = $QT_NAMESPACE
 
+QT_EDITION = $Edition
 EOF
 
+if [ "$Edition" != "OpenSource" ] && [ "$Edition" != "Preview" ]; then
+    echo "QT_LICHECK = $Licheck" >> "$QTCONFIG.tmp"
+    echo "QT_RELEASE_DATE = $ReleaseDate" >> "$QTCONFIG.tmp"
+fi
+echo >> "$QTCONFIG.tmp"
+
 if [ "$CFG_SHARED" = "no" ]; then
     echo "QT_DEFAULT_QPA_PLUGIN = q$QT_QPA_DEFAULT_PLATFORM" >> "$QTCONFIG.tmp"
     echo >> "$QTCONFIG.tmp"
@@ -6980,6 +7012,7 @@ unset build_mode release
 echo "  Using sanitizer(s)...... $CFG_SANITIZERS"
 echo "  Using C++11 ............ $CFG_CXX11"
 echo "  Using gold linker....... $CFG_USE_GOLD_LINKER"
+echo "  Using new DTAGS ........ $CFG_ENABLE_NEW_DTAGS"
 echo "  Using PCH .............. $CFG_PRECOMPILE"
 echo "  Target compiler supports:"
 if [ "$CFG_ARCH" = "i386" -o "$CFG_ARCH" = "x86_64" ]; then
diff --git a/dist/changes-5.4.2 b/dist/changes-5.4.2
new file mode 100644
index 0000000000000000000000000000000000000000..1a3489801153489aa0994c4fbe1d48a03672b4be
--- /dev/null
+++ b/dist/changes-5.4.2
@@ -0,0 +1,124 @@
+Qt 5.4.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.4.1. Compatibility with Qt
+5.4.0 is also retained, except on Windows when using MSVC 2012 or MSVC
+2013. See note below.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+  http://doc.qt.io/qt-5.4/
+
+The Qt version 5.4 series is binary compatible with the 5.3.x series.
+Applications compiled for 5.3 will continue to run with 5.4 with the
+exception of on Windows when using MSVC 2012 or MSVC 2013. See note
+below.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+  http://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+*                        Important Behavior Changes                        *
+****************************************************************************
+- Restored binary compatibility with Qt 5.3.2 on Windows when using MSVC
+  2012 or MSVC 2013. This means that Qt 5.4.1 and 5.4.2 are no longer
+  binary compatible with Qt 5.4.0 when using either of those compilers.
+- [QTBUG-42594] OS X binary package: fixed incorrect linking to libraries in
+  /opt/local/lib
+- EXIF orientation is no longer applied to JPEG images on read. EXIF
+  orientation on JPEG was introduced in 5.4.0, but due to a bug the most
+  common EXIF-format (big-endian) was not working until 5.4.1. 5.4.2 restores the
+  behavior of 5.4.0 and earlier for most EXIF-tagged JPEGs.
+  EXIF orientation will be an opt-in starting with Qt 5.5.
+- On x86 and x86-64 systems with ELF binaries (especially Linux), due to
+  a new optimization in GCC 5.x in combination with a recent version of
+  GNU binutils, compiling Qt applications with -fPIE is no longer
+  enough with GCC 5.x. Applications now need to be compiled with
+  the -fPIC option if Qt's option "reduce relocations" is active. For
+  backward compatibility only, Qt accepts the use of -fPIE for GCC 4.x
+  versions.
+  Note that Clang is known to generate incompatible code even with -fPIC if
+  the -flto option is active.
+  Applications using qmake or cmake >= 2.8.12 as their build system will
+  adapt automatically. Applications using an older release of cmake in
+  combination with GCC 5.x need to change their CMakeLists.txt to add
+  Qt5Core_EXECUTABLE_COMPILE_FLAGS to CMAKE_CXX_FLAGS. In particular,
+  applications using cmake >= 2.8.9 and < 2.8.11 will continue to build
+  with the -fPIE option and invoke the special compatibility mode if using
+  GCC 4.x.
+
+
+****************************************************************************
+*                               Library                                    *
+****************************************************************************
+
+QtCore
+------
+ - [QTBUG-43893] Fixed memory leak in qSetMessagePattern
+ - [QTBUG-43513] QXmlStreamReader: Correctly parse XML containing NUL bytes
+   in the input stream
+ - [QTBUG-43352] QTemporaryDirectory: Properly clean up in case of a failure
+ - [QTBUG-43827] Fixed regression in QSortFilterProxyModel which crashed when
+   sorting a tree model
+
+QtGui
+-----
+ - [QTBUG-44273] Fixed misplacement of outlined text with native text rendering
+ - [QTBUG-44147] Fixed VNC not working on some VNC servers
+ - [QTBUG-43850] Fixed crash with multi-threaded font usage
+ - [QTBUG-43850] Made the old harfbuzz fallback available at runtime
+ - Improvements to the experimental high-dpi support
+ - [QTBUG-43318] Better resolution of GLES 3 functions to avoid issues when
+   deploying on systems with GLES 2.0 only
+
+QtWidgets
+---------
+ - [QTBUG-43830] Fixed crash in stylesheets when styling QProgressBar
+ - [QTBUG-43663] QColorDialog: Don't lose focus while color picking
+
+QtNetwork
+---------
+ - [QTBUG-43793] Fixed disconnects of QSSLSocket after starting encryption
+
+QtPrintSupport
+--------------
+ - [QTBUG-43124] Fixed QPrinter::{width,height} return values
+
+****************************************************************************
+*                      Platform Specific Changes                           *
+****************************************************************************
+
+Android
+-------
+
+ - [QTBUG-44648] Fixed rendering Chinese text on Android 5
+
+Linux/XCB
+---------
+
+ - [QTBUG-45071] Don't crash when resizing windows to bigger than 3840x2160
+
+****************************************************************************
+*                                Tools                                     *
+****************************************************************************
+
+configure & build system
+------------------------
+
+ - CMake-based projects using Qt will now always be built with -fPIE,
+   which fixes function pointer based QObject::connect() on ARM. This
+   is consistent with qmake
+ - [Android] Fixed compilation on armv5 with 4.9 toolchain
+
+qmake
+-----
+
+ - [VS] Fixed handling of files that are excluded from build
+ - [QTBUG-44413][VS] Fixed vcxproj generation for CONFIG-=flat, again
+ - [QTBUG-44595] Restored Qt 4 behavior of qtLibraryTarget()
+ - [QTBUG-45118][Windows] Fixed parallel build when using TYPELIBS
+ - [OS X/iOS] Fixed QMAKE_INFO_PLIST path resolution for shadow builds
diff --git a/doc/global/externalsites/qt-webpages.qdoc b/doc/global/externalsites/qt-webpages.qdoc
index 057f0259e98357226d1e87f54dbcd0a55efa2932..386573e526811caf616d4dffa45cb7b2c9b2ede4 100644
--- a/doc/global/externalsites/qt-webpages.qdoc
+++ b/doc/global/externalsites/qt-webpages.qdoc
@@ -110,3 +110,7 @@
     \externalpage http://wiki.qt.io/BlackBerry
     \title Qt for BlackBerry
 */
+/*!
+    \externalpage http://wiki.qt.io/Qt_Multimedia_Backends
+    \title Qt Multimedia Backends
+*/
diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index 3491e004021458254fb06854a7d6fd51a52d2d30..5f309d2a6194a5901196f18aa7adc1181f3104fa 100644
--- a/doc/global/qt-cpp-defines.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -66,6 +66,7 @@ Cpp.ignoretokens        += \
                           Q_POSITIONING_EXPORT \
                           Q_MULTIMEDIA_EXPORT \
                           Q_NETWORK_EXPORT \
+                          Q_NEVER_INLINE \
                           Q_NORETURN \
                           Q_OPENGL_EXPORT \
                           Q_OPENVG_EXPORT \
diff --git a/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro b/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro
index e0067cf27f9fcc79ff67d155e611c7177d25ad3d..78fc6b1a638804d784be42662f87aec9e4c60069 100644
--- a/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro
+++ b/examples/opengl/legacy/framebufferobject2/framebufferobject2.pro
@@ -5,11 +5,7 @@ RESOURCES += framebufferobject2.qrc
 QT += opengl widgets
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/framebufferobject2
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/framebufferobject2
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/grabber/grabber.pro b/examples/opengl/legacy/grabber/grabber.pro
index b8567580f0363c66968354fcb4f8b081671582b0..1db0e23156ba3d268a729ffce5fc054d85b722af 100644
--- a/examples/opengl/legacy/grabber/grabber.pro
+++ b/examples/opengl/legacy/grabber/grabber.pro
@@ -6,11 +6,7 @@ SOURCES       = glwidget.cpp \
 QT           += opengl widgets
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/grabber
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/grabber
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/hellogl/glwidget.cpp b/examples/opengl/legacy/hellogl/glwidget.cpp
index 02501cd99e3de2890257f0dc375f1f7fbeaea109..122f7ddfe1659aacc2eaadd26a44bcd1916a45a9 100644
--- a/examples/opengl/legacy/hellogl/glwidget.cpp
+++ b/examples/opengl/legacy/hellogl/glwidget.cpp
@@ -128,6 +128,8 @@ void GLWidget::setZRotation(int angle)
 //! [6]
 void GLWidget::initializeGL()
 {
+    initializeOpenGLFunctions();
+
     qglClearColor(qtPurple.dark());
 
     logo = new QtLogo(this, 64);
@@ -153,7 +155,7 @@ void GLWidget::paintGL()
     glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
     glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
     glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
-    logo->draw();
+    logo->draw(static_cast<QOpenGLFunctions_1_1 *>(this));
 }
 //! [7]
 
diff --git a/examples/opengl/legacy/hellogl/glwidget.h b/examples/opengl/legacy/hellogl/glwidget.h
index 994e38e13dcb33bb8efa3c5c629c2502b67bb2f7..9aca4451dfc83d8b9c40e5aaa913b4e7c4014de8 100644
--- a/examples/opengl/legacy/hellogl/glwidget.h
+++ b/examples/opengl/legacy/hellogl/glwidget.h
@@ -42,11 +42,12 @@
 #define GLWIDGET_H
 
 #include <QGLWidget>
+#include <QOpenGLFunctions_1_1>
 
 class QtLogo;
 
 //! [0]
-class GLWidget : public QGLWidget
+class GLWidget : public QGLWidget, public QOpenGLFunctions_1_1
 {
     Q_OBJECT
 
diff --git a/examples/opengl/legacy/hellogl/hellogl.pro b/examples/opengl/legacy/hellogl/hellogl.pro
index 500bd85b3c98fa50506ec9f4da054d3273bc3858..c211242fd2f4b66298eab84f083090b00d666c79 100644
--- a/examples/opengl/legacy/hellogl/hellogl.pro
+++ b/examples/opengl/legacy/hellogl/hellogl.pro
@@ -11,11 +11,7 @@ SOURCES       = glwidget.cpp \
 QT           += opengl widgets
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/hellogl
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/hellogl
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/overpainting/glwidget.cpp b/examples/opengl/legacy/overpainting/glwidget.cpp
index b41bc311265c54a31bf1ef9fd107ac9ab3d5501c..52b6c35801513646ed990e8a084fcdfe9fcc276a 100644
--- a/examples/opengl/legacy/overpainting/glwidget.cpp
+++ b/examples/opengl/legacy/overpainting/glwidget.cpp
@@ -115,6 +115,8 @@ void GLWidget::setZRotation(int angle)
 //! [2]
 void GLWidget::initializeGL()
 {
+    initializeOpenGLFunctions();
+
     glEnable(GL_MULTISAMPLE);
 
     logo = new QtLogo(this);
@@ -173,7 +175,7 @@ void GLWidget::paintEvent(QPaintEvent *event)
     glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
     glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
 
-    logo->draw();
+    logo->draw(static_cast<QOpenGLFunctions_1_1 *>(this));
 //! [7]
 
 //! [8]
diff --git a/examples/opengl/legacy/overpainting/glwidget.h b/examples/opengl/legacy/overpainting/glwidget.h
index dd5c0ba9ff4efff49e2f6223675a644263ab2f02..7e62a00170792a6269b68c4b7670714c97797f37 100644
--- a/examples/opengl/legacy/overpainting/glwidget.h
+++ b/examples/opengl/legacy/overpainting/glwidget.h
@@ -42,13 +42,14 @@
 #define GLWIDGET_H
 
 #include <QGLWidget>
+#include <QOpenGLFunctions_1_1>
 #include <QTimer>
 
 class Bubble;
 class QtLogo;
 
 //! [0]
-class GLWidget : public QGLWidget
+class GLWidget : public QGLWidget, public QOpenGLFunctions_1_1
 {
     Q_OBJECT
 
diff --git a/examples/opengl/legacy/overpainting/overpainting.pro b/examples/opengl/legacy/overpainting/overpainting.pro
index c1bda7853d8504605d9efa8d74ea593ef5566ddc..cc46f1888997b3095b217b3ec74aabf925b0cdbd 100644
--- a/examples/opengl/legacy/overpainting/overpainting.pro
+++ b/examples/opengl/legacy/overpainting/overpainting.pro
@@ -13,11 +13,7 @@ SOURCES = bubble.cpp \
     qtlogo.cpp
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/overpainting
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/overpainting
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/pbuffers/pbuffers.pro b/examples/opengl/legacy/pbuffers/pbuffers.pro
index a349e39f68f75a681ec52454f55bd803d06f18b2..d779a2a2dc935310828c1d98ae4b8c181b258e4e 100644
--- a/examples/opengl/legacy/pbuffers/pbuffers.pro
+++ b/examples/opengl/legacy/pbuffers/pbuffers.pro
@@ -7,11 +7,7 @@ RESOURCES += pbuffers.qrc
 QT += opengl widgets
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/pbuffers
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/pbuffers
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/pbuffers2/pbuffers2.pro b/examples/opengl/legacy/pbuffers2/pbuffers2.pro
index f9dd269eeafd1531292cb99093d7c032aa0c45ff..2ba40a6f746a33aef1e77dd0e8af837f03e7398f 100644
--- a/examples/opengl/legacy/pbuffers2/pbuffers2.pro
+++ b/examples/opengl/legacy/pbuffers2/pbuffers2.pro
@@ -5,11 +5,7 @@ SOURCES += glwidget.cpp main.cpp
 RESOURCES += pbuffers2.qrc
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/pbuffers2
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/pbuffers2
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/samplebuffers/samplebuffers.pro b/examples/opengl/legacy/samplebuffers/samplebuffers.pro
index b57599aae4c3378c04c7e8931ff1c9fa77851c37..3719f5039d5dc3e0830332effdf512b351ab0e17 100644
--- a/examples/opengl/legacy/samplebuffers/samplebuffers.pro
+++ b/examples/opengl/legacy/samplebuffers/samplebuffers.pro
@@ -4,11 +4,7 @@ SOURCES += glwidget.cpp main.cpp
 QT += opengl widgets
 
 # install
-target.path = $$[QT_INSTALL_EXAMPLES]/opengl/samplebuffers
+target.path = $$[QT_INSTALL_EXAMPLES]/opengl/legacy/samplebuffers
 INSTALLS += target
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/opengl/legacy/shared/qtlogo.cpp b/examples/opengl/legacy/shared/qtlogo.cpp
index efe3fb0201a0fb83757b13730325d02d92bd458f..0d960dd4b6ee3438f7b894ece2d783defbe42c42 100644
--- a/examples/opengl/legacy/shared/qtlogo.cpp
+++ b/examples/opengl/legacy/shared/qtlogo.cpp
@@ -43,6 +43,7 @@
 #include <QGLWidget>
 #include <QMatrix4x4>
 #include <QVector3D>
+#include <QOpenGLFunctions_1_1>
 
 #include <qmath.h>
 
@@ -60,7 +61,7 @@ struct Geometry
     void appendSmooth(const QVector3D &a, const QVector3D &n, int from);
     void appendFaceted(const QVector3D &a, const QVector3D &n);
     void finalize();
-    void loadArrays() const;
+    void loadArrays(QOpenGLFunctions_1_1 *functions) const;
 };
 //! [0]
 
@@ -73,7 +74,7 @@ public:
     void setSmoothing(Smoothing s) { sm = s; }
     void translate(const QVector3D &t);
     void rotate(qreal deg, QVector3D axis);
-    void draw() const;
+    void draw(QOpenGLFunctions_1_1 *functions) const;
     void addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &n);
     void addQuad(const QVector3D &a, const QVector3D &b,  const QVector3D &c, const QVector3D &d);
 
@@ -96,10 +97,10 @@ static inline void qSetColor(float colorVec[], QColor c)
     colorVec[3] = c.alphaF();
 }
 
-void Geometry::loadArrays() const
+void Geometry::loadArrays(QOpenGLFunctions_1_1 *functions) const
 {
-    glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
-    glNormalPointer(GL_FLOAT, 0, normals.constData());
+    functions->glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
+    functions->glNormalPointer(GL_FLOAT, 0, normals.constData());
 }
 
 void Geometry::finalize()
@@ -170,15 +171,15 @@ void Patch::translate(const QVector3D &t)
 }
 
 //! [2]
-void Patch::draw() const
+void Patch::draw(QOpenGLFunctions_1_1 *functions) const
 {
-    glPushMatrix();
-    glMultMatrixf(mat.constData());
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor);
+    functions->glPushMatrix();
+    functions->glMultMatrixf(mat.constData());
+    functions->glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor);
 
     const GLushort *indices = geom->faces.constData();
-    glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indices + start);
-    glPopMatrix();
+    functions->glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indices + start);
+    functions->glPopMatrix();
 }
 //! [2]
 
@@ -371,17 +372,17 @@ void QtLogo::buildGeometry(int divisions, qreal scale)
 //! [3]
 
 //! [4]
-void QtLogo::draw() const
+void QtLogo::draw(QOpenGLFunctions_1_1 *functions) const
 {
-    geom->loadArrays();
+    geom->loadArrays(functions);
 
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glEnableClientState(GL_NORMAL_ARRAY);
+    functions->glEnableClientState(GL_VERTEX_ARRAY);
+    functions->glEnableClientState(GL_NORMAL_ARRAY);
 
     for (int i = 0; i < parts.count(); ++i)
-        parts[i]->draw();
+        parts[i]->draw(functions);
 
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_NORMAL_ARRAY);
+    functions->glDisableClientState(GL_VERTEX_ARRAY);
+    functions->glDisableClientState(GL_NORMAL_ARRAY);
 }
 //! [4]
diff --git a/examples/opengl/legacy/shared/qtlogo.h b/examples/opengl/legacy/shared/qtlogo.h
index 562435daed392dd2c312dacf4c85e6234f493952..9bd15a1431091431cd3284934ba62c34bb2f5b63 100644
--- a/examples/opengl/legacy/shared/qtlogo.h
+++ b/examples/opengl/legacy/shared/qtlogo.h
@@ -44,6 +44,7 @@
 #include <QObject>
 #include <QColor>
 
+class QOpenGLFunctions_1_1;
 class Patch;
 struct Geometry;
 
@@ -54,7 +55,7 @@ public:
     explicit QtLogo(QObject *parent, int d = 64, qreal s = 1.0);
     ~QtLogo();
     void setColor(QColor c);
-    void draw() const;
+    void draw(QOpenGLFunctions_1_1 *functions) const;
 private:
     void buildGeometry(int d, qreal s);
 
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp
index f93e66761550e579d94829d707a1f07d1a90c704..df52e3efbf83d92faa5c1dcb7da86e9a6c36ca9c 100644
--- a/examples/opengl/qopenglwidget/glwidget.cpp
+++ b/examples/opengl/qopenglwidget/glwidget.cpp
@@ -537,14 +537,14 @@ void GLWidget::setTransparent(bool transparent)
     window()->update();
 }
 
-void GLWidget::resizeGL(int w, int h)
+void GLWidget::resizeGL(int, int)
 {
     if (m_hasButton) {
         if (!m_btn) {
-            m_btn = new QPushButton("A widget on top.\nPress me!", this);
+            m_btn = new QPushButton("A widget on top.\nPress for more widgets.", this);
             connect(m_btn, &QPushButton::clicked, this, &GLWidget::handleButtonPress);
         }
-        m_btn->move(w / 2, h / 2);
+        m_btn->move(20, 80);
     }
 }
 
diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp
index 6cf1d5d6e2d21b3e2dda11ece89af0eb321a8a74..22111afdcbf6f02ec24b759613a7ab50180d1a59 100644
--- a/examples/opengl/qopenglwidget/mainwindow.cpp
+++ b/examples/opengl/qopenglwidget/mainwindow.cpp
@@ -47,6 +47,7 @@
 #include <QLabel>
 #include <QCheckBox>
 #include <QSpinBox>
+#include <QScrollArea>
 
 #include "glwidget.h"
 
@@ -69,7 +70,7 @@ MainWindow::MainWindow()
                                "and therefore an interval < 16 ms will likely lead to a 60 FPS update rate.");
     QGroupBox *updateGroupBox = new QGroupBox(this);
     QCheckBox *timerBased = new QCheckBox("Use timer", this);
-    timerBased->setChecked(true);
+    timerBased->setChecked(false);
     timerBased->setToolTip("Toggles using a timer to trigger update().\n"
                            "When not set, each paintGL() schedules the next update immediately,\n"
                            "expecting the blocking swap to throttle the thread.\n"
@@ -87,7 +88,7 @@ MainWindow::MainWindow()
     slider->setRange(0, 50);
     slider->setSliderPosition(30);
     m_timer->setInterval(10);
-    label->setText("A QOpenGLWidget");
+    label->setText("A scrollable QOpenGLWidget");
     label->setAlignment(Qt::AlignHCenter);
 
     QGroupBox * groupBox = new QGroupBox(this);
@@ -96,7 +97,10 @@ MainWindow::MainWindow()
 
     m_layout = new QGridLayout(groupBox);
 
-    m_layout->addWidget(glwidget,1,0,8,1);
+    QScrollArea *scrollArea = new QScrollArea;
+    scrollArea->setWidget(glwidget);
+
+    m_layout->addWidget(scrollArea,1,0,8,1);
     m_layout->addWidget(label,9,0,1,1);
     m_layout->addWidget(updateGroupBox, 10, 0, 1, 1);
     m_layout->addWidget(slider, 11,0,1,1);
@@ -134,7 +138,10 @@ MainWindow::MainWindow()
     connect(timerBased, &QCheckBox::toggled, this, &MainWindow::timerUsageChanged);
     connect(timerBased, &QCheckBox::toggled, updateInterval, &QWidget::setEnabled);
 
-    m_timer->start();
+    if (timerBased->isChecked())
+        m_timer->start();
+    else
+        updateInterval->setEnabled(false);
 }
 
 void MainWindow::updateIntervalChanged(int value)
@@ -170,3 +177,8 @@ void MainWindow::timerUsageChanged(bool enabled)
             w->update();
     }
 }
+
+void MainWindow::resizeEvent(QResizeEvent *)
+{
+     m_glWidgets[0]->setMinimumSize(size() + QSize(128, 128));
+}
diff --git a/examples/opengl/qopenglwidget/mainwindow.h b/examples/opengl/qopenglwidget/mainwindow.h
index f1b2c51e53f81bb2544a22770e4bcb15e29e286d..9ad8a013392d3713add1125d481de0c7db040244 100644
--- a/examples/opengl/qopenglwidget/mainwindow.h
+++ b/examples/opengl/qopenglwidget/mainwindow.h
@@ -56,6 +56,8 @@ public:
     void addNew();
     bool timerEnabled() const { return m_timer->isActive(); }
 
+    void resizeEvent(QResizeEvent *);
+
 private slots:
     void updateIntervalChanged(int value);
     void timerUsageChanged(bool enabled);
diff --git a/examples/sql/books/books.pro b/examples/sql/books/books.pro
index 31c47ba04f1384c48dccc723c6fdfec771d0abd8..1cdcaff8705d1b2c2950a5c26493c897e79edd09 100644
--- a/examples/sql/books/books.pro
+++ b/examples/sql/books/books.pro
@@ -16,5 +16,5 @@ wince*: {
     CONFIG(debug, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*d4.dll
     CONFIG(release, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*[^d]4.dll
     sqlPlugins.path = sqldrivers
-    DEPLOYMENT += sqlPlugins
+    INSTALLS += sqlPlugins
 }
diff --git a/examples/touch/fingerpaint/scribblearea.cpp b/examples/touch/fingerpaint/scribblearea.cpp
index 469c6b1a70d5795d2f8b4da75a5d1d2a189a90f0..05598c134cb8df6d2624f1d626ce7da90f669a28 100644
--- a/examples/touch/fingerpaint/scribblearea.cpp
+++ b/examples/touch/fingerpaint/scribblearea.cpp
@@ -187,13 +187,14 @@ bool ScribbleArea::event(QEvent *event)
         foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
             switch (touchPoint.state()) {
             case Qt::TouchPointStationary:
-                // don't do anything if this touch point hasn't moved
+            case Qt::TouchPointReleased:
+                // don't do anything if this touch point hasn't moved or has been released
                 continue;
             default:
                 {
                     QRectF rect = touchPoint.rect();
                     if (rect.isEmpty()) {
-                        qreal diameter = MinimumDiameter;
+                        qreal diameter = MaximumDiameter;
                         if (touch->device()->capabilities() & QTouchDevice::Pressure)
                             diameter = MinimumDiameter + (MaximumDiameter - MinimumDiameter) * touchPoint.pressure();
                         rect.setSize(QSizeF(diameter, diameter));
diff --git a/examples/webkit/webkit-guide/js/anim_accord.js b/examples/webkit/webkit-guide/js/anim_accord.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/anim_gallery.js b/examples/webkit/webkit-guide/js/anim_gallery.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/anim_panel.js b/examples/webkit/webkit-guide/js/anim_panel.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/anim_skew.js b/examples/webkit/webkit-guide/js/anim_skew.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_backgrounds.js b/examples/webkit/webkit-guide/js/css3_backgrounds.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_border-img.js b/examples/webkit/webkit-guide/js/css3_border-img.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_grad-radial.js b/examples/webkit/webkit-guide/js/css3_grad-radial.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_mask-grad.js b/examples/webkit/webkit-guide/js/css3_mask-grad.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_mask-img.js b/examples/webkit/webkit-guide/js/css3_mask-img.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/css3_text-overflow.js b/examples/webkit/webkit-guide/js/css3_text-overflow.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/form_tapper.js b/examples/webkit/webkit-guide/js/form_tapper.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/mob_condjs.js b/examples/webkit/webkit-guide/js/mob_condjs.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/mobile.js b/examples/webkit/webkit-guide/js/mobile.js
old mode 100755
new mode 100644
diff --git a/examples/webkit/webkit-guide/js/storage.js b/examples/webkit/webkit-guide/js/storage.js
old mode 100755
new mode 100644
diff --git a/examples/widgets/doc/images/imagegestures-example.jpg b/examples/widgets/doc/images/imagegestures-example.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c8484b4a71999b9f98e449a3a0a48c951e9f8253
Binary files /dev/null and b/examples/widgets/doc/images/imagegestures-example.jpg differ
diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc
index 7a8a2cf2fc35d1c2542c6a5875b15425de8dcf8e..a1e26272bc9234268053c127e7071bcbb1167282 100644
--- a/examples/widgets/doc/src/plugandpaint.qdoc
+++ b/examples/widgets/doc/src/plugandpaint.qdoc
@@ -30,8 +30,7 @@
     \title Plug & Paint Example
     \ingroup examples-widgets-tools
 
-    \brief The Plug & Paint example demonstrates how to write Qt
-    applications that can be extended through plugins.
+    \brief Demonstrates how to extend Qt applications using plugins.
 
     \image plugandpaint.png Screenshot of the Plug & Paint example
 
@@ -314,6 +313,9 @@
 /*!
     \example tools/plugandpaintplugins/basictools
     \title Plug & Paint Basic Tools Example
+    \brief A plugin providing the basic tools for painting functionality.
+
+    \image plugandpaint.png Screenshot of the Plug & Paint example
 
     The Basic Tools example is a static plugin for the
     \l{tools/plugandpaint}{Plug & Paint} example. It provides a set
@@ -499,6 +501,9 @@
 /*!
     \example tools/plugandpaintplugins/extrafilters
     \title Plug & Paint Extra Filters Example
+    \brief A plugin providing the extra filters.
+
+    \image plugandpaint.png Screenshot of the Plug & Paint example
 
     The Extra Filters example is a plugin for the
     \l{tools/plugandpaint}{Plug & Paint} example. It provides a set
diff --git a/examples/widgets/draganddrop/puzzle/puzzle.pro b/examples/widgets/draganddrop/puzzle/puzzle.pro
index 95008fc29bc22fcc8fcf12ba03372adcfc5cfb6a..b310f1f776ff10b1e6cb64f2f46bdd0bd75ec323 100644
--- a/examples/widgets/draganddrop/puzzle/puzzle.pro
+++ b/examples/widgets/draganddrop/puzzle/puzzle.pro
@@ -18,5 +18,5 @@ INSTALLS += target
 wince*: {
    addFile.files = example.jpg
    addFile.path = .
-   DEPLOYMENT += addFile
+   INSTALLS += addFile
 }
diff --git a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
index 07acef6b4d63310c8f02a86ddf46c02f6b629ea7..2751c64e76d1b7455b9d69ee2f89a569d78cb8a0 100644
--- a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
+++ b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
@@ -28,10 +28,13 @@
 /*!
     \example gestures/imagegestures
     \title Image Gestures Example
+    \brief Demonstrates the use of simple gestures in a widget
 
     This example shows how to enable gestures for a widget and use gesture input
     to perform actions.
 
+    \image imagegestures-example.jpg
+
     We use two classes to create the user interface for the application: \c MainWidget
     and \c ImageWidget. The \c MainWidget class is simply used as a container for the
     \c ImageWidget class, which we will configure to accept gesture input. Since we
diff --git a/examples/widgets/graphicsview/boxes/boxes.pro b/examples/widgets/graphicsview/boxes/boxes.pro
index e608b1c8455cd0fba7c61ac6b8efd5ae68d5cb81..15d26f02f07331126125d264379fc228502154c2 100644
--- a/examples/widgets/graphicsview/boxes/boxes.pro
+++ b/examples/widgets/graphicsview/boxes/boxes.pro
@@ -1,10 +1,6 @@
 QT += opengl widgets
 
-contains(QT_CONFIG, opengles.) {
-    contains(QT_CONFIG, angle): \
-        warning("Qt was built with ANGLE, which provides only OpenGL ES 2.0 on top of DirectX 9.0c")
-    error("This example requires Qt to be configured with -opengl desktop")
-}
+contains(QT_CONFIG, opengles.|angle|dynamicgl):error("This example requires Qt to be configured with -opengl desktop")
 
 HEADERS += 3rdparty/fbm.h \
            glbuffers.h \
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
index 408f6c4b0f70f100535a23491c4b2c7c3d162fd9..7499389dc30e68a25cfea37278c1a1f4571f2dc4 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
@@ -248,8 +248,8 @@ void ColorDock::setCustomSizeHint(const QSize &size)
     updateGeometry();
 }
 
-ColorSwatch::ColorSwatch(const QString &colorName, QWidget *parent, Qt::WindowFlags flags)
-    : QDockWidget(parent, flags)
+ColorSwatch::ColorSwatch(const QString &colorName, QMainWindow *parent, Qt::WindowFlags flags)
+    : QDockWidget(parent, flags), mainWindow(parent)
 {
     setObjectName(colorName + QLatin1String(" Dock Widget"));
     setWindowTitle(objectName() + QLatin1String(" [*]"));
@@ -390,7 +390,6 @@ ColorSwatch::ColorSwatch(const QString &colorName, QWidget *parent, Qt::WindowFl
 
 void ColorSwatch::updateContextMenu()
 {
-    QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
     const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(this);
     const Qt::DockWidgetAreas areas = allowedAreas();
 
@@ -458,7 +457,6 @@ void ColorSwatch::updateContextMenu()
 
 void ColorSwatch::splitInto(QAction *action)
 {
-    QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
     QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>();
     ColorSwatch *target = 0;
     foreach (ColorSwatch *dock, dock_list) {
@@ -477,7 +475,6 @@ void ColorSwatch::splitInto(QAction *action)
 
 void ColorSwatch::tabInto(QAction *action)
 {
-    QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
     QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>();
     ColorSwatch *target = 0;
     foreach (ColorSwatch *dock, dock_list) {
@@ -525,7 +522,6 @@ void ColorSwatch::place(Qt::DockWidgetArea area, bool p)
 {
     if (!p) return;
 
-    QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
     mainWindow->addDockWidget(area, this);
 
     if (allowedAreasActions->isEnabled()) {
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.h b/examples/widgets/mainwindows/mainwindow/colorswatch.h
index 6d02592b22dd27912330ba583e37e96d26994d64..78f267c3202c6b606268c1953105e4c7bd1fbe27 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.h
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.h
@@ -70,8 +70,10 @@ class ColorSwatch : public QDockWidget
 
     QAction *windowModifiedAction;
 
+    QMainWindow *mainWindow;
+
 public:
-    explicit ColorSwatch(const QString &colorName, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+    explicit ColorSwatch(const QString &colorName, QMainWindow *parent = 0, Qt::WindowFlags flags = 0);
 
     QMenu *menu;
     void setCustomSizeHint(const QSize &size);
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index 70a8644b47432b0e740d01ddec13ac90d899f3b7..ea557c7aa97e45b9c4f86d84fbf6cf243ba87e5c 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -156,6 +156,11 @@ void MainWindow::setupMenuBar()
     action->setChecked(dockOptions() & VerticalTabs);
     connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));
 
+    action = mainWindowMenu->addAction(tr("Grouped dragging"));
+    action->setCheckable(true);
+    action->setChecked(dockOptions() & GroupedDragging);
+    connect(action, SIGNAL(toggled(bool)), this, SLOT(setDockOptions()));
+
     QMenu *toolBarMenu = menuBar()->addMenu(tr("Tool bars"));
     for (int i = 0; i < toolBars.count(); ++i)
         toolBarMenu->addMenu(toolBars.at(i)->menu);
@@ -187,6 +192,8 @@ void MainWindow::setDockOptions()
         opts |= ForceTabbedDocks;
     if (actions.at(4)->isChecked())
         opts |= VerticalTabs;
+    if (actions.at(5)->isChecked())
+        opts |= GroupedDragging;
 
     QMainWindow::setDockOptions(opts);
 }
diff --git a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
index 640f36f9b89f961b6efff9de7f4d89f061936c69..809667b2ad9df02156305f83bba187be7a26a6e3 100644
--- a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
+++ b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
@@ -14,5 +14,5 @@ INSTALLS += target
 wince*: {
    addFiles.files = main.cpp mainwindow.cpp
    addFiles.path = .
-   DEPLOYMENT += addFiles
+   INSTALLS += addFiles
 }
diff --git a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
index 45ded876a7214700f041b16a4f3bbd5004d3823f..6764423d7130fd04ba855c563130e78fb41c6744 100644
--- a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
@@ -370,7 +370,6 @@ void AddressBook::loadFromFile()
 
         QDataStream in(&file);
         in.setVersion(QDataStream::Qt_4_3);
-        contacts.empty();   // empty existing contacts
         in >> contacts;
 
         QMap<QString, QString>::iterator i = contacts.begin();
diff --git a/examples/widgets/widgets/icons/icons.pro b/examples/widgets/widgets/icons/icons.pro
index 51d8b79ba93fab74bc2d40dd2155f996a764e38e..58e6c2137c9a50e07547d95c8ae548673a2c5d0c 100644
--- a/examples/widgets/widgets/icons/icons.pro
+++ b/examples/widgets/widgets/icons/icons.pro
@@ -24,5 +24,5 @@ wince*: {
     } else {
         imageFiles.path    = images
     }
-    DEPLOYMENT += imageFiles
+    INSTALLS += imageFiles
 }
diff --git a/examples/widgets/widgets/imageviewer/imageviewer.cpp b/examples/widgets/widgets/imageviewer/imageviewer.cpp
index c32f21e7f33c14d6a484a83a68dd0fc7642c3607..0b8513f0907381226bb2b2bb67093568c46cbeb3 100644
--- a/examples/widgets/widgets/imageviewer/imageviewer.cpp
+++ b/examples/widgets/widgets/imageviewer/imageviewer.cpp
@@ -107,7 +107,7 @@ void ImageViewer::open()
     mimeTypeFilters.sort();
     const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
     QFileDialog dialog(this, tr("Open File"),
-                       picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.first());
+                       picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
     dialog.setAcceptMode(QFileDialog::AcceptOpen);
     dialog.setMimeTypeFilters(mimeTypeFilters);
     dialog.selectMimeTypeFilter("image/jpeg");
diff --git a/examples/widgets/widgets/movie/movie.pro b/examples/widgets/widgets/movie/movie.pro
index 6d333edfa8e4ebb9297be003829c5c5794e923fe..58925c98a02acad5ff3568f18e62c17e4eba0be6 100644
--- a/examples/widgets/widgets/movie/movie.pro
+++ b/examples/widgets/widgets/movie/movie.pro
@@ -14,5 +14,5 @@ INSTALLS += target
 wince*: {
    addFiles.files += *.gif
    addFiles.path = .
-   DEPLOYMENT += addFiles
+   INSTALLS += addFiles
 }
diff --git a/examples/widgets/windowcontainer/windowcontainer.cpp b/examples/widgets/windowcontainer/windowcontainer.cpp
index 022b6dafc4bda12528a22667cab65e2d9a94056a..a38a10e6f6fbf36351ab18ea343ea31619a4b72e 100644
--- a/examples/widgets/windowcontainer/windowcontainer.cpp
+++ b/examples/widgets/windowcontainer/windowcontainer.cpp
@@ -92,10 +92,12 @@ public:
     }
 
     void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE {
-        m_mouseDown = true;
-        m_polygon.clear();
-        m_polygon.append(e->pos());
-        renderLater();
+        if (!m_mouseDown) {
+            m_mouseDown = true;
+            m_polygon.clear();
+            m_polygon.append(e->pos());
+            renderLater();
+        }
     }
 
     void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE {
@@ -106,9 +108,11 @@ public:
     }
 
     void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE {
-        m_mouseDown = false;
-        m_polygon.append(e->pos());
-        renderLater();
+        if (m_mouseDown) {
+            m_mouseDown = false;
+            m_polygon.append(e->pos());
+            renderLater();
+        }
     }
 
     void focusInEvent(QFocusEvent *) Q_DECL_OVERRIDE {
diff --git a/examples/xml/dombookmarks/dombookmarks.pro b/examples/xml/dombookmarks/dombookmarks.pro
index 93a5fb9ac99ebb7811ad0ad2ee02ea32cdad0f67..a16cdadcfab11243d8d03151fb99307db9d2d37a 100644
--- a/examples/xml/dombookmarks/dombookmarks.pro
+++ b/examples/xml/dombookmarks/dombookmarks.pro
@@ -14,6 +14,6 @@ INSTALLS += target
 wince*: {
     addFiles.files = frank.xbel jennifer.xbel
     addFiles.path = "\\My Documents"
-    DEPLOYMENT += addFiles
+    INSTALLS += addFiles
 }
 
diff --git a/examples/xml/htmlinfo/htmlinfo.pro b/examples/xml/htmlinfo/htmlinfo.pro
index 9e58973db68e9efac5ab240998ffa250d921d7eb..4ad40213fe5d8dd5163c78178f801731d10421e5 100644
--- a/examples/xml/htmlinfo/htmlinfo.pro
+++ b/examples/xml/htmlinfo/htmlinfo.pro
@@ -9,7 +9,7 @@ win32: CONFIG += console
 wince*:{
    htmlfiles.files = *.html
    htmlfiles.path = .
-   DEPLOYMENT += htmlfiles
+   INSTALLS += htmlfiles
 }
 
 # install
diff --git a/examples/xml/saxbookmarks/saxbookmarks.pro b/examples/xml/saxbookmarks/saxbookmarks.pro
index 6723b0c6fc86690e5b42a4b325676e2ce1069dca..aa84ee4f3ed13f1667e9466fe9747961ba2d6809 100644
--- a/examples/xml/saxbookmarks/saxbookmarks.pro
+++ b/examples/xml/saxbookmarks/saxbookmarks.pro
@@ -16,5 +16,5 @@ INSTALLS += target
 wince*: {
      addFiles.files = frank.xbel jennifer.xbel
      addFiles.path = "\\My Documents"
-     DEPLOYMENT += addFiles
+     INSTALLS += addFiles
 }
diff --git a/mkspecs/common/gcc-base-unix.conf b/mkspecs/common/gcc-base-unix.conf
index 29e052192754835c51987a9d26056137f33b1053..f82c8a843062d6591713160d865b51264cc9cb5b 100644
--- a/mkspecs/common/gcc-base-unix.conf
+++ b/mkspecs/common/gcc-base-unix.conf
@@ -16,6 +16,7 @@ QMAKE_LFLAGS_SONAME    += -Wl,-soname,
 QMAKE_LFLAGS_THREAD    +=
 QMAKE_LFLAGS_RPATH      = -Wl,-rpath,
 QMAKE_LFLAGS_RPATHLINK  = -Wl,-rpath-link,
+QMAKE_LFLAGS_NEW_DTAGS  = -Wl,--enable-new-dtags
 QMAKE_LFLAGS_USE_GOLD   = -fuse-ld=gold
 
 # -Bsymbolic-functions (ld) support
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index dc0aa4b4a962818c8d107756c3ae987e4bbf2ca4..27e812b3a1541342a35ccf1ae8ef16bb13aaad18 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -43,7 +43,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
 QMAKE_CFLAGS_DEBUG         += -g
 QMAKE_CFLAGS_SHLIB         += -fPIC
 QMAKE_CFLAGS_STATIC_LIB    += -fPIC
-QMAKE_CFLAGS_APP           += -fPIE
+QMAKE_CFLAGS_APP           += -fPIC
 QMAKE_CFLAGS_ISYSTEM        = -isystem
 QMAKE_CFLAGS_YACC          += -Wno-unused -Wno-parentheses
 QMAKE_CFLAGS_HIDESYMS      += -fvisibility=hidden
diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf
index 09fdabce439b45d756710fcad7ec2052a4f2dfcf..4ef03d8587b8cc6133276c5f66cdfe30f9c6f19d 100644
--- a/mkspecs/common/qcc-base.conf
+++ b/mkspecs/common/qcc-base.conf
@@ -23,7 +23,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
 QMAKE_CFLAGS_DEBUG     += -g
 QMAKE_CFLAGS_SHLIB     += -fPIC -shared
 QMAKE_CFLAGS_STATIC_LIB += -fPIC
-QMAKE_CFLAGS_APP       += -fPIE
+QMAKE_CFLAGS_APP       += -fPIC
 QMAKE_CFLAGS_YACC      += -Wno-unused -Wno-parentheses
 QMAKE_CFLAGS_HIDESYMS  += -fvisibility=hidden
 QMAKE_CFLAGS_SSE2      += -msse2
diff --git a/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
new file mode 100644
index 0000000000000000000000000000000000000000..c6419660c10a6b7d1ea2b96af356bf6e31ba3a20
--- /dev/null
+++ b/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
@@ -0,0 +1,49 @@
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+
+<Package
+  xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\"
+  xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"
+  xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\"
+  IgnorableNamespaces=\"uap mp\">
+
+  <Identity
+    Name=\"$${WINRT_MANIFEST.identity}\"
+    Publisher=\"$${WINRT_MANIFEST.publisherid}\"
+    Version=\"$${WINRT_MANIFEST.version}\" />
+
+  <mp:PhoneIdentity PhoneProductId=\"$${WINRT_MANIFEST.identity}\" PhonePublisherId=\"$${WINRT_MANIFEST.phone_publisher_id}\"/>
+
+  <Properties>
+    <DisplayName>$${WINRT_MANIFEST.name}</DisplayName>
+    <PublisherDisplayName>$${WINRT_MANIFEST.publisher}</PublisherDisplayName>
+    <Logo>$${WINRT_MANIFEST.logo_store}</Logo>
+  </Properties>
+
+  <Dependencies>
+    <TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10069.0\" MaxVersionTested=\"10.0.10069.0\" />
+  </Dependencies>
+
+  <Resources>
+    <Resource Language=\"en\"/>
+  </Resources>
+
+  <Applications>
+    <Application Id=\"App\"
+      Executable=\"$${WINRT_MANIFEST.target}.exe\"
+      EntryPoint=\"$${WINRT_MANIFEST.target}.App\">
+      <uap:VisualElements
+        DisplayName=\"$${WINRT_MANIFEST.name}\"
+        Description=\"$${WINRT_MANIFEST.description}\"
+        BackgroundColor=\"$${WINRT_MANIFEST.background}\"
+        Square150x150Logo=\"$${WINRT_MANIFEST.logo_150x150}\"
+        Square44x44Logo=\"$${WINRT_MANIFEST.logo_44x44}\">
+
+        <uap:SplashScreen Image=\"$${WINRT_MANIFEST.logo_620x300}\" />
+      </uap:VisualElements>
+    </Application>
+  </Applications>
+
+  <Capabilities>
+    <Capability Name=\"internetClient\" />
+  </Capabilities>
+</Package>
diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf
index d71915408de8db3ab7ef2cbde43cf0c4be387d01..97ef66123097f57bb613b7a625c15bf6abe64af2 100644
--- a/mkspecs/common/winrt_winphone/qmake.conf
+++ b/mkspecs/common/winrt_winphone/qmake.conf
@@ -50,7 +50,7 @@ QMAKE_CXXFLAGS_STL_OFF  =
 QMAKE_CXXFLAGS_RTTI_ON  = -GR
 QMAKE_CXXFLAGS_RTTI_OFF =
 QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc
-QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
+QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -D_HAS_EXCEPTIONS=0
 
 QMAKE_INCDIR            =
 
diff --git a/mkspecs/devices/linux-beagleboard-g++/qmake.conf b/mkspecs/devices/linux-beagleboard-g++/qmake.conf
index 3b9ca66306cef0e135252e0fb19033f85d5d54c6..1d32d374c6ea97b8ddc2dae03e9fc75e395df707 100644
--- a/mkspecs/devices/linux-beagleboard-g++/qmake.conf
+++ b/mkspecs/devices/linux-beagleboard-g++/qmake.conf
@@ -36,8 +36,8 @@ QMAKE_CXXFLAGS_RELEASE += -O3
 QMAKE_LIBS             += -lrt -lpthread -ldl
 
 # Extra stuff (OpenGL, DirectFB, ...)
-QMAKE_INCDIR_EGL        = $$[QT_SYSROOT]/usr/include
-QMAKE_LIBDIR_EGL        = $$[QT_SYSROOT]/usr/lib
+QMAKE_INCDIR_EGL        =
+QMAKE_LIBDIR_EGL        =
 QMAKE_INCDIR_OPENGL_ES2 = $${QMAKE_INCDIR_EGL}
 QMAKE_LIBDIR_OPENGL_ES2 = $${QMAKE_LIBDIR_EGL}
 QMAKE_INCDIR_OPENVG     = $${QMAKE_INCDIR_EGL}
diff --git a/mkspecs/devices/linux-imx53qsb-g++/qmake.conf b/mkspecs/devices/linux-imx53qsb-g++/qmake.conf
index 937bbf24160c909afe87a082ce43c416a264c475..39462d83d9454073a4037d15bd7f8b3fd3e6c54c 100644
--- a/mkspecs/devices/linux-imx53qsb-g++/qmake.conf
+++ b/mkspecs/devices/linux-imx53qsb-g++/qmake.conf
@@ -16,15 +16,10 @@
 
 include(../common/linux_device_pre.conf)
 
-QMAKE_INCDIR           += $$[QT_SYSROOT]/usr/include
-QMAKE_LIBDIR           += $$[QT_SYSROOT]/usr/lib
-
 QMAKE_LIBS_EGL         += -lEGL
 QMAKE_LIBS_OPENGL_ES2  += -lGLESv2 -lEGL
 QMAKE_LIBS_OPENVG      += -lOpenVG -lEGL
 
-QMAKE_LFLAGS           += -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib
-
 IMX5_CFLAGS             = -march=armv7-a -mfpu=neon -DLINUX=1 -DEGL_API_FB=1 -Wno-psabi
 QMAKE_CFLAGS           += $$IMX5_CFLAGS
 QMAKE_CXXFLAGS         += $$IMX5_CFLAGS
diff --git a/mkspecs/devices/linux-imx6-g++/qmake.conf b/mkspecs/devices/linux-imx6-g++/qmake.conf
index 1646c5fe7744df7ee893898242222b7556eebdfc..71e37845c378a2ac4034537d88a83281463e23dd 100644
--- a/mkspecs/devices/linux-imx6-g++/qmake.conf
+++ b/mkspecs/devices/linux-imx6-g++/qmake.conf
@@ -4,15 +4,10 @@
 
 include(../common/linux_device_pre.conf)
 
-QMAKE_INCDIR           += $$[QT_SYSROOT]/usr/include
-QMAKE_LIBDIR           += $$[QT_SYSROOT]/usr/lib
-
 QMAKE_LIBS_EGL         += -lEGL
 QMAKE_LIBS_OPENGL_ES2  += -lGLESv2 -lEGL -lGAL
 QMAKE_LIBS_OPENVG      += -lOpenVG -lEGL -lGAL
 
-QMAKE_LFLAGS           += -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib
-
 IMX6_CFLAGS             = -march=armv7-a -mfpu=neon -DLINUX=1 -DEGL_API_FB=1
 QMAKE_CFLAGS           += $$IMX6_CFLAGS
 QMAKE_CXXFLAGS         += $$IMX6_CFLAGS
diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf
index e967399258ada3a32d7ef6c505615967df65921f..8e68b95dd56097f7ad9a00340e45b6056a038989 100644
--- a/mkspecs/features/default_post.prf
+++ b/mkspecs/features/default_post.prf
@@ -63,6 +63,7 @@ debug {
 }
 
 use_gold_linker: QMAKE_LFLAGS += $$QMAKE_LFLAGS_USE_GOLD
+enable_new_dtags: QMAKE_LFLAGS += $$QMAKE_LFLAGS_NEW_DTAGS
 
 dll:win32: QMAKE_LFLAGS += $$QMAKE_LFLAGS_DLL
 static:mac: QMAKE_LFLAGS += $$QMAKE_LFLAGS_STATIC_LIB
diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf
index b06b9d6cfce198bc58839458267c93a0e7648adb..eb3281ea1d14e182e3cf5f0e274675391bf8ac7d 100644
--- a/mkspecs/features/default_pre.prf
+++ b/mkspecs/features/default_pre.prf
@@ -7,3 +7,18 @@ CONFIG = \
     lex yacc debug exceptions depend_includepath \
     testcase_targets import_plugins import_qpa_plugin \
     $$CONFIG
+
+!build_pass:defined(QT_EDITION, var):!equals(QT_EDITION, "OpenSource"):!equals(QT_EDITION, "Preview") {
+    #
+    # call license checker (but cache result for one day)
+    #
+    today = $$section(_DATE_, " ", 0, 2)
+    !isEqual(QMAKE_LICHECK_TIMESTAMP, $$today) {
+        !system("$$system_quote($$system_path($$[QT_HOST_BINS/src]/$$QT_LICHECK)) check" \
+                "$$QT_RELEASE_DATE $$[QMAKE_SPEC] $$[QMAKE_XSPEC]"): \
+            error("License check failed! Giving up ...")
+
+        cache(QMAKE_LICHECK_TIMESTAMP, set stash, today)
+    }
+    unset(today)
+}
diff --git a/mkspecs/features/plugin_bundle.prf b/mkspecs/features/plugin_bundle.prf
new file mode 100644
index 0000000000000000000000000000000000000000..f3e7294c90a481293ea7a1be9111628538818bc8
--- /dev/null
+++ b/mkspecs/features/plugin_bundle.prf
@@ -0,0 +1,2 @@
+# Override mkspec default which creates a shared library
+mac: QMAKE_LFLAGS_PLUGIN = -bundle
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 264641b5b30e3ee6514ed7704d9f3c298ac9905c..8e7b8bca0a32bafc7204bcee1258d62aa53c5d19 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -257,10 +257,10 @@ for(QT_CURRENT_VERIFY, $$list($$QT_PLUGIN_VERIFY)) {
             debug: QT_ITEM = $${QTPLUG}d4.dll
             else: QT_ITEM = $${QTPLUG}4.dll
 
-            eval(qt_additional_plugin_$${QTPLUG}.files = $$[QT_INSTALL_PLUGINS/get]/$${QT_PLUGINPATH}/$${QT_ITEM})
-            eval(qt_additional_plugin_$${QTPLUG}.path = $${QT_PLUGINPATH})
+            qt_additional_plugin_$${QTPLUG}.files = $$[QT_INSTALL_PLUGINS/get]/$${QT_PLUGINPATH}/$${QT_ITEM}
+            qt_additional_plugin_$${QTPLUG}.path = $${QT_PLUGINPATH}
 
-            DEPLOYMENT *= qt_additional_plugin_$${QTPLUG}
+            INSTALLS *= qt_additional_plugin_$${QTPLUG}
         }
     }
 }
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 42046c238a7d26a6e6b9014be040bac19bc5ae60..7197f84c9a755188377061738f5ccc61e74c1a68 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -52,12 +52,6 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
     unset(modpath)
 }
 
-mac {
-   !isEmpty(QMAKE_RPATHDIR){
-       CONFIG += absolute_library_soname
-   }
-}
-
 cross_compile: \
     CONFIG += force_bootstrap
 
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index 6a66b7630508bf507c6ba79d631c0e8169e6baeb..5861941848b85b386cbebfbd988b76ab2d4628d6 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -79,6 +79,9 @@ warnings_are_errors:warning_clean {
             # Work-around for bug https://code.google.com/p/android/issues/detail?id=58135
             android: QMAKE_CXXFLAGS_WARN_ON += -Wno-error=literal-suffix
         }
+    } else:msvc {
+        # enable for MSVC 2012, MSVC 2013
+        equals(MSVC_VER, "11.0")|equals(MSVC_VER, "12.0"): QMAKE_CXXFLAGS_WARN_ON += -WX
     }
     unset(ver)
 }
diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf
index 78be2e847325d58b674a0aecb49e02a4138d3cad..a1c499610b5dccfd70beaedcb58c13dec05a3180 100644
--- a/mkspecs/features/qt_functions.prf
+++ b/mkspecs/features/qt_functions.prf
@@ -185,7 +185,7 @@ defineTest(qtAddRpathLink) {
     # paths OTOH need to be put there.
     pubqt = $$replace(1, -private$, _private)
     pubdep = $$resolve_depends(pubqt, "QT.")
-    privdep = $$resolve_depends(pubqt, "QT.", ".depends" ".private_depends" ".run_depends")
+    privdep = $$resolve_depends(pubqt, "QT.", ".depends" ".run_depends")
     privdep -= $$pubdep
     rpaths =
     for(dep, privdep): \
@@ -259,7 +259,7 @@ defineTest(qtAddToolEnv) {
 # target variable, dependency var name, [non-empty: prepare for system(), not make]
 defineTest(qtAddTargetEnv) {
     deps = $$replace($$2, -private$, _private)
-    deps = $$resolve_depends(deps, "QT.", ".depends" ".private_depends" ".run_depends")
+    deps = $$resolve_depends(deps, "QT.", ".depends" ".run_depends")
     !isEmpty(deps) {
         ptypes =
         for(dep, deps) {
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 66a7598597d7f7ce5e3fc91837675c27addf6700..5412f3778a018309f3aa416ab674d6fda83b7607 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -60,7 +60,7 @@ MODULE_DEFINES = $$MODULE_DEFINE $$MODULE_DEFINES
 
 load(qt_build_paths)
 
-qt_no_install_library {
+header_module {
     TEMPLATE     = aux
     CONFIG      += force_qt  # Needed for the headers_clean tests.
 } else {
@@ -104,7 +104,7 @@ mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) {
    QMAKE_TARGET_BUNDLE_PREFIX = org.qt-project
    #QMAKE_FRAMEWORK_VERSION = 4.0
    CONFIG += sliced_bundle qt_framework
-   qt_no_install_library {
+   header_module {
         CONFIG += bundle
         QMAKE_BUNDLE_EXTENSION = .framework
         QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib
@@ -132,6 +132,9 @@ mac {
        QMAKE_CFLAGS += -fconstant-cfstrings
        QMAKE_CXXFLAGS += -fconstant-cfstrings
    }
+
+   contains(QT_CONFIG, rpath): \
+       QMAKE_SONAME_PREFIX = @rpath
 }
 
 DEFINES += QT_BUILDING_QT
diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf
index 4ce03f4327283799c30022bb0cdf9216bccb57ff..1d727847e2e1bcfdac03e37b7af75c2467eb1d6e 100644
--- a/mkspecs/features/qt_module_pris.prf
+++ b/mkspecs/features/qt_module_pris.prf
@@ -91,15 +91,22 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
         MODULE_PRIVATE_INCLUDES = \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME/$$VERSION \
                                   \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME/$$VERSION/$$MODULE_INCNAME
     }
-    split_incpath: \
+    split_incpath {
         MODULE_SHADOW_INCLUDES = $$replace(MODULE_INCLUDES, ^\\\$\\\$QT_MODULE_INCLUDE_BASE, \
                                                             $$MODULE_BASE_OUTDIR/include)
+        generated_privates: \
+            MODULE_SHADOW_PRIVATE_INCLUDES = $$replace(MODULE_PRIVATE_INCLUDES, ^\\\$\\\$QT_MODULE_INCLUDE_BASE, \
+                                                                                $$MODULE_BASE_OUTDIR/include)
+    }
     MODULE_INCLUDES += $$MODULE_AUX_INCLUDES
     MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES
     internal_module: \
         MODULE_INCLUDES += $$MODULE_PRIVATE_INCLUDES
-    split_incpath: \
+    split_incpath {
         MODULE_FWD_PRI_CONT_SUFFIX += "QT.$${MODULE_ID}.includes += $$val_escape(MODULE_SHADOW_INCLUDES)"
+        generated_privates: \
+            MODULE_FWD_PRI_CONT_SUFFIX += "QT.$${MODULE}_private.includes += $$val_escape(MODULE_SHADOW_PRIVATE_INCLUDES)"
+    }
     MODULE_PRI_CONT = \
         "QT.$${MODULE_ID}.VERSION = $${VERSION}" \
         "QT.$${MODULE_ID}.MAJOR_VERSION = $$section(VERSION, ., 0, 0)" \
diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf
index 8564731a2221e0248460440cf6eacf1ddb8c423a..7a38ff8f3809789a58f8e9325410270c6e2ad5ab 100644
--- a/mkspecs/features/resources.prf
+++ b/mkspecs/features/resources.prf
@@ -6,6 +6,66 @@ isEmpty(QMAKE_MOD_RCC):QMAKE_MOD_RCC = qrc
 !contains(QMAKE_RESOURCE_FLAGS, -root):!isEmpty(QMAKE_RESOURCE_ROOT):QMAKE_RESOURCE_FLAGS += -root $$QMAKE_RESOURCE_ROOT
 !contains(QMAKE_RESOURCE_FLAGS, -name): QMAKE_RESOURCE_FLAGS += -name ${QMAKE_FILE_BASE}
 
+# http://www.w3.org/TR/xml/#syntax
+defineReplace(xml_escape) {
+    1 ~= s,&,&amp;,
+    1 ~= s,\',&apos;,
+    1 ~= s,\",&quot;,
+    1 ~= s,<,&lt;,
+    1 ~= s,>,&gt;,
+    return($$1)
+}
+
+RESOURCES += qmake_immediate
+for(resource, RESOURCES) {
+    # Regular case of user qrc file
+    contains(resource, ".*\.qrc$"): \
+        next()
+
+    # Fallback for stand-alone files/directories
+    !defined($${resource}.files, var) {
+        !equals(resource, qmake_immediate) {
+            !exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
+                warning("Failure to find: $$resource")
+            qmake_immediate.files += $$resource
+        }
+        RESOURCES -= $$resource
+        next()
+    }
+
+    resource_file = $$RCC_DIR/qmake_$${resource}.qrc
+
+    !debug_and_release|build_pass {
+        # Collection of files, generate qrc file
+        prefix = $$eval($${resource}.prefix)
+        isEmpty(prefix): \
+            prefix = "/"
+
+        resource_file_content = \
+            "<!DOCTYPE RCC><RCC version=\"1.0\">" \
+            "<qresource prefix=\"$$xml_escape($$prefix)\">"
+
+        abs_base = $$absolute_path($$eval($${resource}.base), $$_PRO_FILE_PWD_)
+
+        for(file, $${resource}.files) {
+            abs_path = $$absolute_path($$file, $$_PRO_FILE_PWD_)
+            alias = $$relative_path($$abs_path, $$abs_base)
+            resource_file_content += \
+                "<file alias=\"$$xml_escape($$alias)\">$$xml_escape($$abs_path)</file>"
+        }
+
+        resource_file_content += \
+            "</qresource>" \
+            "</RCC>"
+
+        !write_file($$OUT_PWD/$$resource_file, resource_file_content): \
+            error("Aborting.")
+    }
+
+    RESOURCES -= $$resource
+    RESOURCES += $$resource_file
+}
+
 rcc.input = RESOURCES
 rcc.name = RCC ${QMAKE_FILE_IN}
 rcc.depend_command = $$QMAKE_RCC_DEP -list $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN}
diff --git a/mkspecs/features/spec_post.prf b/mkspecs/features/spec_post.prf
index c9578773fe80e0d44f9f9c9ac64fa9649aca770e..4d398059b2ea3d218c41d22fd6c694778b6d3076 100644
--- a/mkspecs/features/spec_post.prf
+++ b/mkspecs/features/spec_post.prf
@@ -109,9 +109,8 @@ equals(MAKEFILE_GENERATOR, MSBUILD) \
 }
 QMAKE_INSTALL_DIR = $$QMAKE_COPY_DIR
 equals(QMAKE_HOST.os, Windows) {
-    # Ugly (and broken for relative paths) hack to support cross-building for Unix.
-    QMAKE_SYMBOLIC_LINK     = $$QMAKE_COPY
-    QMAKE_LN_SHLIB          = $$QMAKE_SYMBOLIC_LINK
+    QMAKE_SYMBOLIC_LINK     = $(QMAKE) -install ln -f -s
+    QMAKE_LN_SHLIB          = $(QMAKE) -install ln -s
 } else {
     QMAKE_SYMBOLIC_LINK     = ln -f -s
     QMAKE_LN_SHLIB          = ln -s
diff --git a/mkspecs/features/testlib_defines.prf b/mkspecs/features/testlib_defines.prf
index 9176beb9ddafd13687b66f4be445dc4b7c488897..901e03a91d135be8486b2cf51f6ec3e1c5409ac2 100644
--- a/mkspecs/features/testlib_defines.prf
+++ b/mkspecs/features/testlib_defines.prf
@@ -1 +1,2 @@
-DEFINES += QT_TESTCASE_BUILDDIR=$$shell_quote(\"$$OUT_PWD\")
+contains(TEMPLATE, vc.*): DEFINES += QT_TESTCASE_BUILDDIR=\"$$OUT_PWD\"
+else: DEFINES += QT_TESTCASE_BUILDDIR=$$shell_quote(\"$$OUT_PWD\")
diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf
index 8119c8aa09dc9b991942618b1f8954dc180978c6..9190aa9f28cf6b38455a718afd6851d341ca57b5 100644
--- a/mkspecs/linux-icc/qmake.conf
+++ b/mkspecs/linux-icc/qmake.conf
@@ -12,7 +12,7 @@ QMAKE_LEXFLAGS          =
 QMAKE_YACC              = yacc
 QMAKE_YACCFLAGS         = -d
 QMAKE_CFLAGS            =
-QMAKE_CFLAGS_APP        = -fPIE
+QMAKE_CFLAGS_APP        = -fPIC
 QMAKE_CFLAGS_DEPS       = -M
 QMAKE_CFLAGS_WARN_ON    = -w1 -Wall -Wcheck -wd1572,873,2259,2261
 QMAKE_CFLAGS_WARN_OFF   = -w
diff --git a/mkspecs/macx-ios-clang/Info.plist.app b/mkspecs/macx-ios-clang/Info.plist.app
old mode 100755
new mode 100644
diff --git a/mkspecs/winrt-arm-msvc2015/qmake.conf b/mkspecs/winrt-arm-msvc2015/qmake.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fcb6d99aa9aa49db0a363fa03401712361deed91
--- /dev/null
+++ b/mkspecs/winrt-arm-msvc2015/qmake.conf
@@ -0,0 +1,32 @@
+#
+# qmake configuration for winrt-arm-msvc2015
+#
+# Written for Microsoft Visual C++ 2015
+#
+
+include(../common/winrt_winphone/qmake.conf)
+QMAKE_COMPILER_DEFINES += _MSC_VER=1900
+DEFINES                += WINAPI_FAMILY=WINAPI_FAMILY_APP ARM __ARM__ __arm__
+
+QMAKE_CFLAGS           += -FS
+QMAKE_CXXFLAGS         += -FS
+QMAKE_LFLAGS           += /MACHINE:ARM /NODEFAULTLIB:kernel32.lib
+
+QMAKE_LIBS             += windowscodecs.lib WindowsApp.lib runtimeobject.lib
+
+# Note that the order is important, ucrt(d) has to be first
+# Otherwise the linker might use malloc from a different library
+# but free_dbg() from the runtime, causing assert when deleting
+# items from different heaps
+CONFIG(debug, debug|release) {
+    QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
+} else {
+    QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
+}
+
+VCPROJ_ARCH             = ARM
+MSVC_VER                = 14.0
+WINSDK_VER              = 10.0
+WINTARGET_VER           = winv10.0
+WINRT_MANIFEST          = $$PWD/../common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = arm
diff --git a/tests/auto/tools/qmake/testdata/functions/2.cpp b/mkspecs/winrt-arm-msvc2015/qplatformdefs.h
similarity index 93%
rename from tests/auto/tools/qmake/testdata/functions/2.cpp
rename to mkspecs/winrt-arm-msvc2015/qplatformdefs.h
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..c8f88524d99560e06248818881b42cbdd03cb2c2 100644
--- a/tests/auto/tools/qmake/testdata/functions/2.cpp
+++ b/mkspecs/winrt-arm-msvc2015/qplatformdefs.h
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -30,3 +30,5 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
+
+#include "../common/winrt_winphone/qplatformdefs.h"
diff --git a/mkspecs/winrt-x64-msvc2015/qmake.conf b/mkspecs/winrt-x64-msvc2015/qmake.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e8062f536416563fe3f963ef8873dfcb4b5072ff
--- /dev/null
+++ b/mkspecs/winrt-x64-msvc2015/qmake.conf
@@ -0,0 +1,32 @@
+#
+# qmake configuration for winrt-x64-msvc2015
+#
+# Written for Microsoft Visual C++ 2015
+#
+
+include(../common/winrt_winphone/qmake.conf)
+QMAKE_COMPILER_DEFINES += _MSC_VER=1900 _WIN32
+DEFINES                += WINAPI_FAMILY=WINAPI_FAMILY_APP X64 __X64__ __x64__
+
+QMAKE_CFLAGS           += -FS
+QMAKE_CXXFLAGS         += -FS
+QMAKE_LFLAGS           += /MACHINE:X64 /NODEFAULTLIB:kernel32.lib
+
+QMAKE_LIBS             += windowscodecs.lib WindowsApp.lib runtimeobject.lib
+
+# Note that the order is important, ucrt(d) has to be first
+# Otherwise the linker might use malloc from a different library
+# but free_dbg() from the runtime, causing assert when deleting
+# items from different heaps
+CONFIG(debug, debug|release) {
+    QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
+} else {
+    QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
+}
+
+VCPROJ_ARCH             = x64
+MSVC_VER                = 14.0
+WINSDK_VER              = 10.0
+WINTARGET_VER           = winv10.0
+WINRT_MANIFEST          = $$PWD/../common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x64
diff --git a/tests/auto/tools/qmake/testdata/functions/one/1.cpp b/mkspecs/winrt-x64-msvc2015/qplatformdefs.h
similarity index 93%
rename from tests/auto/tools/qmake/testdata/functions/one/1.cpp
rename to mkspecs/winrt-x64-msvc2015/qplatformdefs.h
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..c8f88524d99560e06248818881b42cbdd03cb2c2 100644
--- a/tests/auto/tools/qmake/testdata/functions/one/1.cpp
+++ b/mkspecs/winrt-x64-msvc2015/qplatformdefs.h
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -30,3 +30,5 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
+
+#include "../common/winrt_winphone/qplatformdefs.h"
diff --git a/mkspecs/winrt-x86-msvc2015/qmake.conf b/mkspecs/winrt-x86-msvc2015/qmake.conf
new file mode 100644
index 0000000000000000000000000000000000000000..5b44a97e8ddb60c6366aabb763aa9c157a46bae6
--- /dev/null
+++ b/mkspecs/winrt-x86-msvc2015/qmake.conf
@@ -0,0 +1,32 @@
+#
+# qmake configuration for winrt-x86-msvc2015
+#
+# Written for Microsoft Visual C++ 2015
+#
+
+include(../common/winrt_winphone/qmake.conf)
+QMAKE_COMPILER_DEFINES += _MSC_VER=1900 _WIN32
+DEFINES                += WINAPI_FAMILY=WINAPI_FAMILY_APP X86 __X86__ __x86__
+
+QMAKE_CFLAGS           += -FS
+QMAKE_CXXFLAGS         += -FS
+QMAKE_LFLAGS           += /SAFESEH /MACHINE:X86 /NODEFAULTLIB:kernel32.lib
+
+QMAKE_LIBS             += windowscodecs.lib WindowsApp.lib runtimeobject.lib
+
+# Note that the order is important, ucrt(d) has to be first
+# Otherwise the linker might use malloc from a different library
+# but free_dbg() from the runtime, causing assert when deleting
+# items from different heaps
+CONFIG(debug, debug|release) {
+    QMAKE_LIBS = ucrtd.lib $$QMAKE_LIBS
+} else {
+    QMAKE_LIBS = ucrt.lib $$QMAKE_LIBS
+}
+
+VCPROJ_ARCH             = Win32
+MSVC_VER                = 14.0
+WINSDK_VER              = 10.0
+WINTARGET_VER           = winv10.0
+WINRT_MANIFEST          = $$PWD/../common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x86
diff --git a/tests/auto/tools/qmake/testdata/functions/one/2.cpp b/mkspecs/winrt-x86-msvc2015/qplatformdefs.h
similarity index 93%
rename from tests/auto/tools/qmake/testdata/functions/one/2.cpp
rename to mkspecs/winrt-x86-msvc2015/qplatformdefs.h
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..c8f88524d99560e06248818881b42cbdd03cb2c2 100644
--- a/tests/auto/tools/qmake/testdata/functions/one/2.cpp
+++ b/mkspecs/winrt-x86-msvc2015/qplatformdefs.h
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -30,3 +30,5 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
+
+#include "../common/winrt_winphone/qplatformdefs.h"
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 86f884fe209195d814e8037fd8e9352e3e585ad0..520ae667e9461fcd105e76850e541184bf856b61 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -13,7 +13,7 @@ OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
 
 #qt code
 QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
-      qdebug.o qmalloc.o qglobal.o \
+      qringbuffer.o qdebug.o qmalloc.o qglobal.o \
       qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
       qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o qvector.o \
       qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \
@@ -44,6 +44,7 @@ DEPEND_SRC = \
 	   $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
 	   $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
 	   $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
+	   $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
 	   $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
 	   $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
 	   $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
@@ -242,6 +243,9 @@ qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
 qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
 	$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
 
+qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+	$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+
 qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
 	$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
 
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 9dda6ca1e7b7399e6179732b677824d624e745d0..272a0c09b19265fd89ca7288659f3e428696ea8c 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -88,6 +88,7 @@ QTOBJS= \
 	qglobal.obj \
 	qhash.obj \
 	qiodevice.obj \
+	qringbuffer.obj \
 	qdebug.obj \
 	qlist.obj \
 	qlinkedlist.obj \
diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
index 335fa6f97e262d9b2f9d7f32fcbd92d46ec59ab3..7609a98111a5546780411708be00be416cab4873 100644
--- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro
+++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
@@ -186,21 +186,6 @@ DEFINES += USE_MY_STUFF
 #! [27]
 
 
-#! [28]
-myFiles.files = path\*.png
-DEPLOYMENT += myFiles
-#! [28]
-
-
-#! [29]
-myFiles.files = path\file1.ext1 path2\file2.ext1 path3\*
-myFiles.path = \some\path\on\device
-someother.files = C:\additional\files\*
-someother.path = \myFiles\path2
-DEPLOYMENT += myFiles someother
-#! [29]
-
-
 #! [30]
 DESTDIR = ../../lib
 #! [30]
@@ -987,3 +972,8 @@ QMAKE_SONAME_PREFIX = /Library/Frameworks
 #! [185]
 VERSION_PE_HEADER = 1.2
 #! [185]
+
+#! [186]
+RC_DEFINES += USE_MY_STUFF
+#! [186]
+
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index 56d9dd35ae786dcc590de82e83a7a5408dfd4055..6f855ba9ca63b8dfd57d2c4f0235503a51001e3f 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -1120,38 +1120,6 @@
     Specifies a list of all directories to look in to resolve dependencies. This
     variable is used when crawling through \c included files.
 
-    \target DEPLOYMENT
-    \section1 DEPLOYMENT
-
-    \note This variable is used only on the Windows CE platform.
-
-    Specifies which additional files will be deployed. Deployment means the
-    transfer of files from the development system to the target device or
-    emulator.
-
-    Files can be deployed by either creating a Visual Studio project or using
-    the \l {Using Qt Test remotely on Windows CE}{cetest} executable.
-
-    For example, the following definition uploads all PNG images in \c path to
-    the directory where the build target is deployed:
-
-    \snippet code/doc_src_qmake-manual.pro 28
-
-    The default deployment target path for Windows CE is
-    \c{%CSIDL_PROGRAM_FILES%\target}, which usually gets expanded to
-    \c{\Program Files\target}.
-
-    It is also possible to specify multiple \c sources to be deployed on
-    target \c paths. In addition, different variables can be used for
-    deployment to different directories.
-
-    For example:
-
-    \snippet code/doc_src_qmake-manual.pro 29
-
-    \note In Windows CE all linked Qt libraries will be deployed to the path
-    specified by \c{myFiles.path}.
-
     \target DEPLOYMENT_PLUGIN
     \section1 DEPLOYMENT_PLUGIN
 
@@ -1276,6 +1244,13 @@
 
     For more information, see \l{Installing Files}.
 
+    This variable is also used to specify which additional files will be
+    deployed to embedded devices.
+
+    For Windows CE, the default deployment target path is
+    \c{%CSIDL_PROGRAM_FILES%\target}, which usually gets expanded to
+    \c{\Program Files\target}.
+
     \target LEXIMPLS
     \section1 LEXIMPLS
 
@@ -2314,6 +2289,14 @@
     .rc file. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable
     is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
 
+    \target RC_DEFINES
+    \section1 RC_DEFINES
+
+    Windows only. qmake adds the values of this variable as RC preprocessor macros
+    (/d option). If this variable is not set, the \l{DEFINES} variable is used instead.
+
+    \snippet code/doc_src_qmake-manual.pro 186
+
     \target RC_ICONS
     \section1 RC_ICONS
 
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index fcd6bf8308d2aa539d079110f393e825c0c29144..deacac2c8378af18fb835b02f852757e71f5dfec 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -810,7 +810,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
     if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
         ProStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"),
               &frameworkdirs = project->values("QMAKE_FRAMEWORKPATH");
-        static const char * const libs[] = { "QMAKE_LFLAGS", "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+        static const char * const libs[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
         for (int i = 0; libs[i]; i++) {
             tmp = project->values(libs[i]);
             for(int x = 0; x < tmp.count();) {
@@ -821,9 +821,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
                     QString r = opt.mid(2).toQString();
                     fixForOutput(r);
                     libdirs.append(r);
-                } else if(opt == "-prebind") {
-                    project->values("QMAKE_DO_PREBINDING").append("TRUE");
-                    remove = true;
                 } else if(opt.startsWith("-l")) {
                     name = opt.mid(2).toQString();
                     QString lib("lib" + name);
@@ -921,7 +918,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
                         if(!path.isEmpty() && !libdirs.contains(path))
                             libdirs += path;
                     }
-                    library = fileFixify(library, FileFixifyFromOutdir);
+                    library = fileFixify(library, FileFixifyFromOutdir | FileFixifyAbsolute);
                     QString key = keyFor(library);
                     if (!project->values("QMAKE_PBX_LIBRARIES").contains(key)) {
                         bool is_frmwrk = (library.endsWith(".framework"));
@@ -1812,11 +1809,14 @@ ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) c
         }
         output += QString("project.pbxproj");
         file.setFileName(output);
+        bool ret = UnixMakefileGenerator::openOutput(file, build);
+        ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
+        Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
+        return ret;
     }
-    bool ret = UnixMakefileGenerator::openOutput(file, build);
-    ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
-    Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
-    return ret;
+
+    ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir;
+    return UnixMakefileGenerator::openOutput(file, build);
 }
 
 /* This function is such a hack it is almost pointless, but it
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index f5e8248af573c54678cbcb753afe7b6d1b44f766..4a03fafd77b5f90e5e275072f39d13d6029fac90 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -2019,7 +2019,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
                 for(int i = 0; i < pre_deps.size(); ++i)
                    deps << replaceExtraCompilerVariables(pre_deps.at(i), inpf, out, NoShell);
             }
-            QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out, LocalShell);
+            QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out, TargetShell);
             // NOTE: The var -> QMAKE_COMP_var replace feature is unsupported, do not use!
             for (ProStringList::ConstIterator it3 = vars.constBegin(); it3 != vars.constEnd(); ++it3)
                 cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
@@ -2240,7 +2240,7 @@ QString MakefileGenerator::buildArgs()
     QString ret;
 
     foreach (const QString &arg, Option::globals->qmake_args)
-        ret += " " + escapeFilePath(arg);
+        ret += " " + shellQuote(arg);
     return ret;
 }
 
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index efea807209bf250a7d85513f68c1ff0710f117b6..c4750cb8a495bed2b06ffb2971a2c5229c486040 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -612,7 +612,7 @@ UnixMakefileGenerator::processPrlFiles()
             ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
             if(!prl_libs.isEmpty()) {
                 for(int prl = 0; prl < prl_libs.size(); ++prl)
-                    l.insert(lit+prl+1, prl_libs.at(prl).toQString());
+                    l.insert(++lit, prl_libs.at(prl));
                 prl_libs.clear();
             }
         }
@@ -699,6 +699,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
         return QString();
 
     enum { NoBundle, SolidBundle, SlicedBundle } bundle = NoBundle;
+    bool isAux = (project->first("TEMPLATE") == "aux");
     const QString root = "$(INSTALL_ROOT)";
     ProStringList &uninst = project->values(ProKey(t + ".uninstall"));
     QString ret, destdir = project->first("DESTDIR").toQString();
@@ -773,21 +774,21 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
         }
         src_targ = escapeFilePath(src_targ);
         dst_targ = escapeFilePath(dst_targ);
-        if(!ret.isEmpty())
-            ret += "\n\t";
 
-        QString copy_cmd("-");
+        QString copy_cmd;
         if (bundle == SolidBundle) {
-            copy_cmd += "$(INSTALL_DIR) " + src_targ + ' ' + plain_targ;
+            copy_cmd += "-$(INSTALL_DIR) " + src_targ + ' ' + plain_targ;
         } else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
-            copy_cmd += "$(INSTALL_FILE) " + src_targ + ' ' + dst_targ;
-        } else {
+            copy_cmd += "-$(INSTALL_FILE) " + src_targ + ' ' + dst_targ;
+        } else if (!isAux) {
             if (bundle == SlicedBundle)
                 ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false) + "\n\t";
-            copy_cmd += "$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
+            copy_cmd += "-$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
         }
         if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib")
            && project->values(ProKey(t + ".CONFIG")).indexOf("fix_rpath") != -1) {
+            if (!ret.isEmpty())
+                ret += "\n\t";
             if(!project->isEmpty("QMAKE_FIX_RPATH")) {
                 ret += copy_cmd;
                 ret += "\n\t-" + var("QMAKE_FIX_RPATH") + ' ' + dst_targ + ' ' + dst_targ;
@@ -797,11 +798,14 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
             } else {
                 ret += copy_cmd;
             }
-        } else {
+        } else if (!copy_cmd.isEmpty()) {
+            if (!ret.isEmpty())
+                ret += "\n\t";
             ret += copy_cmd;
         }
 
-        if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
+        if (isAux) {
+        } else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
             if(!project->isEmpty("QMAKE_RANLIB"))
                 ret += QString("\n\t$(RANLIB) ") + dst_targ;
         } else if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip")
@@ -820,7 +824,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
             uninst.append("\n\t");
         if (bundle == SolidBundle)
             uninst.append("-$(DEL_FILE) -r " + plain_targ);
-        else
+        else if (!isAux)
             uninst.append("-$(DEL_FILE) " + dst_targ);
         if (bundle == SlicedBundle) {
             int dstlen = project->first("DESTDIR").length();
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 9b9e54c4616f63029b9e626c26fdd227ccd59039..5cde7c4ac2739f6a71afe87453b6cec0b84fa845 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -807,11 +807,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
             } else {
                 info_plist = escapeFilePath(fileFixify(info_plist));
             }
-            bool isApp = (project->first("TEMPLATE") == "app");
-            QString info_plist_out =
-                    bundle_dir + (isApp ? "Contents/Info.plist"
-                                        : "Versions/" + project->first("QMAKE_FRAMEWORK_VERSION")
-                                          + "/Resources/Info.plist");
+            bool isFramework = project->first("TEMPLATE") == "lib" && project->isActiveConfig("lib_bundle");
+            QString info_plist_out = bundle_dir +
+                (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/Info.plist")
+                             : "Contents/Info.plist");
             bundledFiles << info_plist_out;
             alldeps << info_plist_out;
             QString destdir = info_plist_out.section(Option::dir_sep, 0, -2);
@@ -842,7 +841,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
                 bundleIdentifier.chop(10);
             commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" ";
 
-            if (isApp) {
+            if (!isFramework) {
                 QString icon = fileFixify(var("ICON"));
                 t << "@$(DEL_FILE) " << info_plist_out << "\n\t"
                   << "@sed ";
@@ -850,6 +849,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
                     t << arg;
                 t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" "
                   << "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" "
+                  << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" "
                   << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ?
                              QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "
                   << "" << info_plist << " >" << info_plist_out << endl;
@@ -922,17 +922,18 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
                 }
             }
         }
-        QString bundle_dir_f = escapeFilePath(bundle_dir);
-        QHash<QString, QString>::ConstIterator symIt = symlinks.constBegin(),
-                                               symEnd = symlinks.constEnd();
-        for (; symIt != symEnd; ++symIt) {
-            bundledFiles << symIt.key();
-            alldeps << symIt.key();
-            t << escapeDependencyPath(symIt.key()) << ":\n\t"
-              << mkdir_p_asstring(bundle_dir) << "\n\t"
-              << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl;
-        }
-        if (!project->first("QMAKE_FRAMEWORK_VERSION").isEmpty()) {
+        if (!symlinks.isEmpty()) {
+            QString bundle_dir_f = escapeFilePath(bundle_dir);
+            QHash<QString, QString>::ConstIterator symIt = symlinks.constBegin(),
+                                                   symEnd = symlinks.constEnd();
+            for (; symIt != symEnd; ++symIt) {
+                bundledFiles << symIt.key();
+                alldeps << symIt.key();
+                t << escapeDependencyPath(symIt.key()) << ":\n\t"
+                  << mkdir_p_asstring(bundle_dir) << "\n\t"
+                  << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl;
+            }
+
             QString currentLink = bundle_dir + "Versions/Current";
             QString currentLink_f = escapeDependencyPath(currentLink);
             bundledFiles << currentLink;
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index c19e17bc0e249e0825b81c4ecba259dcafbb4306..57955dc456bd447e27d64a6c5a9d3e1af2d93a46 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -405,9 +405,14 @@ void MingwMakefileGenerator::writeRcFilePart(QTextStream &t)
     }
 
     if (!rc_file.isEmpty()) {
+
+        ProString defines = varGlue("RC_DEFINES", " -D", " -D", "");
+        if (defines.isEmpty())
+            defines = ProString(" $(DEFINES)");
+
         t << escapeDependencyPath(var("RES_FILE")) << ": " << escapeDependencyPath(rc_file) << "\n\t"
           << var("QMAKE_RC") << " -i " << escapeFilePath(rc_file) << " -o " << fileVar("RES_FILE")
-          << incPathStr << " $(DEFINES)\n\n";
+          << incPathStr << defines << "\n\n";
     }
 }
 
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 6c2d2c62060a7fea3461db639fa0a7dbe31d789b..cbf7cf26dccc0d6f9115046c6d1cd53edbeaac0d 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -608,10 +608,13 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
 
     xml.setIndentString("  ");
 
+    const QString toolsVersion = (tool.SdkVersion == QStringLiteral("10.0")) ? QStringLiteral("14.0")
+                                                                             : QStringLiteral("4.0");
+
     xml << decl("1.0", "utf-8")
         << tag("Project")
         << attrTag("DefaultTargets","Build")
-        << attrTag("ToolsVersion", "4.0")
+        << attrTag("ToolsVersion", toolsVersion)
         << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
         << tag("ItemGroup")
         << attrTag("Label", "ProjectConfigurations");
@@ -640,7 +643,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
             << tagValue("DefaultLanguage", "en")
             << tagValue("AppContainerApplication", "true")
             << tagValue("ApplicationType", isWinPhone ? "Windows Phone" : "Windows Store")
-            << tagValue("ApplicationTypeRevision", tool.SdkVersion);
+            << tagValue("ApplicationTypeRevision", tool.SdkVersion == "10.0" ? "8.2" : tool.SdkVersion);
     }
 
     xml << closetag();
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index eb8ae233840d689878a1687d9522062541ef146b..dfa8f8837b7d133022bcfdd7b872977e1224cf2d 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -176,11 +176,34 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
                 const QString vcInstallDir = "/fake/vc_install_dir";
                 const QString kitDir = "/fake/sdk_install_dir";
 #endif // Q_OS_WIN
-
                 QStringList incDirs;
                 QStringList libDirs;
                 QStringList binDirs;
-                if (isPhone) {
+                if (msvcVer == QStringLiteral("14.0")) {
+                    binDirs << vcInstallDir + QStringLiteral("bin/") + compiler;
+                    binDirs << vcInstallDir + QStringLiteral("bin/"); // Maybe remove for x86 again?
+                    binDirs << kitDir + QStringLiteral("bin/") + (arch == QStringLiteral("arm") ? QStringLiteral("x86") : arch);
+                    binDirs << vcInstallDir + QStringLiteral("../Common7/Tools/bin");
+                    binDirs << vcInstallDir + QStringLiteral("../Common7/Tools");
+                    binDirs << vcInstallDir + QStringLiteral("../Common7/ide");
+                    binDirs << kitDir + QStringLiteral("Windows Performance Toolkit/");
+
+                    incDirs << vcInstallDir + QStringLiteral("include");
+                    incDirs << vcInstallDir + QStringLiteral("atlmfc/include");
+                    // ### Investigate why VS uses 10056 first
+                    incDirs << kitDir + QStringLiteral("Include/10.0.10056.0/ucrt");
+                    incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/ucrt");
+                    incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/um");
+                    incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/shared");
+                    incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/winrt");
+
+                    libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
+                    libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;
+                    // ### Investigate why VS uses 10056 first
+                    libDirs << kitDir + QStringLiteral("lib/10.0.10056.0/ucrt/") + arch;
+                    libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/ucrt/") + arch;
+                    libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/um/") + arch;
+                } else if (isPhone) {
                     QString sdkDir = vcInstallDir;
                     if (!QDir(sdkDir).exists()) {
                         fprintf(stderr, "Failed to find the Windows Phone SDK in %s.\n"
@@ -208,7 +231,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
                             << kitDir + QStringLiteral("/include/shared")
                             << kitDir + QStringLiteral("/include/winrt");
                 }
-
                 // Inherit PATH
                 binDirs << QString::fromLocal8Bit(qgetenv("PATH")).split(QLatin1Char(';'));
 
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 59136b16c869b8387a992ef5af6996e9785332d9..7092da3e5965921ba6081cc7077fc2ac66a8a325 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -56,7 +56,8 @@ enum DotNET {
     NET2008 = 0x90,
     NET2010 = 0xa0,
     NET2012 = 0xb0,
-    NET2013 = 0xc0
+    NET2013 = 0xc0,
+    NET2015 = 0xd0
 };
 
 /*
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 1fa117afdaf3f69958027b434e9b4e58854595a5..b8f9c8135d2ff324ad9eb06808de80c19dd9f583 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -71,6 +71,7 @@ struct DotNetCombo {
     const char *regKey;
 } dotNetCombo[] = {
 #ifdef Q_OS_WIN64
+    {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
     {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
     {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
     {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
@@ -84,6 +85,7 @@ struct DotNetCombo {
     {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
     {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
 #else
+    {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
     {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
     {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
     {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
@@ -175,6 +177,8 @@ const char _slnHeader110[]      = "Microsoft Visual Studio Solution File, Format
                                   "\n# Visual Studio 2012";
 const char _slnHeader120[]      = "Microsoft Visual Studio Solution File, Format Version 12.00"
                                   "\n# Visual Studio 2013";
+const char _slnHeader140[]      = "Microsoft Visual Studio Solution File, Format Version 12.00"
+                                  "\n# Visual Studio 2015";
                                   // The following UUID _may_ change for later servicepacks...
                                   // If so we need to search through the registry at
                                   // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects
@@ -401,6 +405,8 @@ QString VcprojGenerator::retrievePlatformToolSet() const
         return QStringLiteral("v110") + suffix;
     case NET2013:
         return QStringLiteral("v120") + suffix;
+    case NET2015:
+        return QStringLiteral("v140") + suffix;
     default:
         return QString();
     }
@@ -647,6 +653,8 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
     }
 
     switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
+    case NET2015:
+        t << _slnHeader140;
     case NET2013:
         t << _slnHeader120;
         break;
@@ -972,6 +980,9 @@ void VcprojGenerator::initProject()
     // Own elements -----------------------------
     vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString();
     switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
+    case NET2015:
+        vcProject.Version = "14.00";
+        break;
     case NET2013:
         vcProject.Version = "12.00";
         break;
@@ -1213,7 +1224,12 @@ void VcprojGenerator::initLinkerTool()
 void VcprojGenerator::initResourceTool()
 {
     VCConfiguration &conf = vcProject.Configuration;
-    conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions;
+
+    ProStringList rcDefines = project->values("RC_DEFINES");
+    if (rcDefines.size() > 0)
+        conf.resource.PreprocessorDefinitions = rcDefines.toQStringList();
+    else
+        conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions;
 
     foreach (const ProString &path, project->values("RC_INCLUDEPATH")) {
         QString fixedPath = fileFixify(path.toQString());
@@ -1369,8 +1385,7 @@ void VcprojGenerator::initDeploymentTool()
         }
     }
 
-    // foreach item in DEPLOYMENT
-    foreach (const ProString &item, project->values("DEPLOYMENT")) {
+    foreach (const ProString &item, project->values("INSTALLS")) {
         // get item.path
         QString devicePath = project->first(ProKey(item + ".path")).toQString();
         if (!conf.WinRT) {
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index 6ea129f82c3226f4ead6061bad80fa29d51edc27..0d761b08a2e172b1f4dedf9e674fd778e93d8d51 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -100,10 +100,13 @@ ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib)
 {
     if (lib.startsWith('/')) {
         if (lib.startsWith("/LIBPATH:"))
-            return QStringLiteral("/LIBPATH:") + escapeFilePath(lib.mid(9));
+            return QLatin1String("/LIBPATH:")
+                    + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false));
+        // This appears to be a user-supplied flag. Assume sufficient quoting.
         return lib;
     }
-    return escapeFilePath(lib);
+    // This must be a fully resolved library path.
+    return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false));
 }
 
 bool
@@ -231,7 +234,7 @@ Win32MakefileGenerator::processPrlFiles()
             }
             ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
             for (int prl = 0; prl < prl_libs.size(); ++prl)
-                l.insert(lit + prl + 1, prl_libs.at(prl));
+                l.insert(++lit, prl_libs.at(prl));
             prl_libs.clear();
         }
 
@@ -752,10 +755,6 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
     if(!project->values("RC_FILE").isEmpty()) {
         const ProString res_file = project->first("RES_FILE");
         const QString rc_file = fileFixify(project->first("RC_FILE").toQString());
-        // The resource tool needs to have the same defines passed in as the compiler, since you may
-        // use these defines in the .rc file itself. Also, we need to add the _DEBUG define manually
-        // since the compiler defines this symbol by itself, and we use it in the automatically
-        // created rc file when VERSION is define the .pro file.
 
         const ProStringList rcIncPaths = project->values("RC_INCLUDEPATH");
         QString incPathStr;
@@ -767,9 +766,20 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
             incPathStr += escapeFilePath(path);
         }
 
+        // The resource tool may use defines. This might be the same defines passed in as the
+        // compiler, since you may use these defines in the .rc file itself.
+        // As the escape syntax for the command line defines for RC is different from that for CL,
+        // we might have to set specific defines for RC.
+        ProString defines = varGlue("RC_DEFINES", " -D", " -D", "");
+        if (defines.isEmpty())
+            defines = ProString(" $(DEFINES)");
+
+        // Also, we need to add the _DEBUG define manually since the compiler defines this symbol
+        // by itself, and we use it in the automatically created rc file when VERSION is defined
+        // in the .pro file.
         t << escapeDependencyPath(res_file) << ": " << escapeDependencyPath(rc_file) << "\n\t"
           << var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "")
-          << " $(DEFINES)" << incPathStr << " -fo " << escapeFilePath(res_file)
+          << defines << incPathStr << " -fo " << escapeFilePath(res_file)
           << ' ' << escapeFilePath(rc_file);
         t << endl << endl;
     }
@@ -784,7 +794,7 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t)
 {
     if((t != "target" && t != "dlltarget") ||
        (t == "dlltarget" && (project->first("TEMPLATE") != "lib" || !project->isActiveConfig("shared"))) ||
-        project->first("TEMPLATE") == "subdirs")
+        project->first("TEMPLATE") == "subdirs" || project->first("TEMPLATE") == "aux")
        return QString();
 
     const QString root = "$(INSTALL_ROOT)";
diff --git a/qmake/library/proitems.cpp b/qmake/library/proitems.cpp
index e780259417a17e095d2c148cb731297c5f13a506..a610da6b690dbba0cf1e29f89b9c7912e78bac89 100644
--- a/qmake/library/proitems.cpp
+++ b/qmake/library/proitems.cpp
@@ -159,6 +159,18 @@ QString &ProString::toQString(QString &tmp) const
     return tmp.setRawData(m_string.constData() + m_offset, m_length);
 }
 
+/*!
+ * \brief ProString::prepareExtend
+ * \param extraLen number of new characters to be added
+ * \param thisTarget offset to which current contents should be moved
+ * \param extraTarget offset at which new characters will be added
+ * \return pointer to storage location for new characters
+ *
+ * Prepares the string for adding new characters.
+ * If the string is detached and has enough space, it will be changed in place.
+ * Otherwise, it will be replaced with a new string object, thus detaching.
+ * In either case, the hash will be reset.
+ */
 QChar *ProString::prepareExtend(int extraLen, int thisTarget, int extraTarget)
 {
     if (m_string.isDetached() && m_length + extraLen <= m_string.capacity()) {
@@ -473,4 +485,23 @@ ProFile::~ProFile()
 {
 }
 
+ProString ProFile::getStr(const ushort *&tPtr)
+{
+    uint len = *tPtr++;
+    ProString ret(items(), tPtr - tokPtr(), len);
+    ret.setSource(this);
+    tPtr += len;
+    return ret;
+}
+
+ProKey ProFile::getHashStr(const ushort *&tPtr)
+{
+    uint hash = *tPtr++;
+    hash |= (uint)*tPtr++ << 16;
+    uint len = *tPtr++;
+    ProKey ret(items(), tPtr - tokPtr(), len, hash);
+    tPtr += len;
+    return ret;
+}
+
 QT_END_NAMESPACE
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index d31367361d3015541618fb5da5381c557392d79b..9430d285211fb0752e1043dfcc6918b73830753d 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -352,6 +352,9 @@ public:
     bool isHostBuild() const { return m_hostBuild; }
     void setHostBuild(bool host_build) { m_hostBuild = host_build; }
 
+    ProString getStr(const ushort *&tPtr);
+    ProKey getHashStr(const ushort *&tPtr);
+
 private:
     ProItemRefCount m_refCount;
     QString m_proitems;
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index e384d26f4c3ec60d1f9ad8264634507b4fef884c..02d5d5dd316c99aaa026baec9b155f57d74fa5c7 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -214,7 +214,7 @@ static QString windowsErrorCode()
                   NULL);
     QString ret = QString::fromWCharArray(string);
     LocalFree((HLOCAL)string);
-    return ret;
+    return ret.trimmed();
 }
 #endif
 
@@ -362,7 +362,7 @@ QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::Open
 {
     QString errStr;
     if (!m_vfs->writeFile(fn, mode, contents, &errStr)) {
-        evalError(fL1S("Cannot write %1file %2: %3.")
+        evalError(fL1S("Cannot write %1file %2: %3")
                   .arg(ctx, QDir::toNativeSeparators(fn), errStr));
         return ReturnFalse;
     }
@@ -1121,7 +1121,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
     switch (func_t) {
     case T_DEFINED: {
         if (args.count() < 1 || args.count() > 2) {
-            evalError(fL1S("defined(function, [\"test\"|\"replace\"])"
+            evalError(fL1S("defined(function, [\"test\"|\"replace\"|\"var\"])"
                            " requires one or two arguments."));
             return ReturnFalse;
         }
@@ -1582,7 +1582,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                                   GENERIC_READ, FILE_SHARE_READ,
                                   NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
         if (rHand == INVALID_HANDLE_VALUE) {
-            evalError(fL1S("Cannot open() reference file %1: %2.").arg(rfn, windowsErrorCode()));
+            evalError(fL1S("Cannot open reference file %1: %2").arg(rfn, windowsErrorCode()));
             return ReturnFalse;
         }
         FILETIME ft;
@@ -1592,7 +1592,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                                   GENERIC_WRITE, FILE_SHARE_READ,
                                   NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
         if (wHand == INVALID_HANDLE_VALUE) {
-            evalError(fL1S("Cannot open() %1: %2.").arg(tfn, windowsErrorCode()));
+            evalError(fL1S("Cannot open %1: %2").arg(tfn, windowsErrorCode()));
             return ReturnFalse;
         }
         SetFileTime(wHand, 0, 0, &ft);
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 5c9dc45f3aedfcfe82fa8bd35bb63c796a95dcf6..8e247d9afab0a78128635d20b47e176f802b32c2 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -188,7 +188,8 @@ void QMakeEvaluator::initStatics()
         { "QMAKE_RPATH", "QMAKE_LFLAGS_RPATH" },
         { "QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH" },
         { "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" },
-        { "IN_PWD", "PWD" }
+        { "IN_PWD", "PWD" },
+        { "DEPLOYMENT", "INSTALLS" }
     };
     for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
         statics.varMap.insert(ProKey(mapInits[i].oldname), ProKey(mapInits[i].newname));
@@ -258,24 +259,6 @@ uint QMakeEvaluator::getBlockLen(const ushort *&tokPtr)
     return len;
 }
 
-ProString QMakeEvaluator::getStr(const ushort *&tokPtr)
-{
-    uint len = *tokPtr++;
-    ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len);
-    ret.setSource(m_current.pro);
-    tokPtr += len;
-    return ret;
-}
-
-ProKey QMakeEvaluator::getHashStr(const ushort *&tokPtr)
-{
-    uint hash = getBlockLen(tokPtr);
-    uint len = *tokPtr++;
-    ProKey ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, hash);
-    tokPtr += len;
-    return ret;
-}
-
 void QMakeEvaluator::skipStr(const ushort *&tokPtr)
 {
     uint len = *tokPtr++;
@@ -314,7 +297,8 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
         switch (unicode) {
         case '"':
         case '\'':
-            quote = unicode;
+            if (!quote)
+                quote = unicode;
             hadWord = true;
             break;
         case ' ':
@@ -429,6 +413,7 @@ void QMakeEvaluator::evaluateExpression(
         const ushort *&tokPtr, ProStringList *ret, bool joined)
 {
     debugMsg(2, joined ? "evaluating joined expression" : "evaluating expression");
+    ProFile *pro = m_current.pro;
     if (joined)
         *ret << ProString();
     bool pending = false;
@@ -444,35 +429,35 @@ void QMakeEvaluator::evaluateExpression(
             m_current.line = *tokPtr++;
             break;
         case TokLiteral: {
-            const ProString &val = getStr(tokPtr);
+            const ProString &val = pro->getStr(tokPtr);
             debugMsg(2, "literal %s", dbgStr(val));
             addStr(val, ret, pending, joined);
             break; }
         case TokHashLiteral: {
-            const ProKey &val = getHashStr(tokPtr);
+            const ProKey &val = pro->getHashStr(tokPtr);
             debugMsg(2, "hashed literal %s", dbgStr(val.toString()));
             addStr(val, ret, pending, joined);
             break; }
         case TokVariable: {
-            const ProKey &var = getHashStr(tokPtr);
+            const ProKey &var = pro->getHashStr(tokPtr);
             const ProStringList &val = values(map(var));
             debugMsg(2, "variable %s => %s", dbgKey(var), dbgStrList(val));
             addStrList(val, tok, ret, pending, joined);
             break; }
         case TokProperty: {
-            const ProKey &var = getHashStr(tokPtr);
+            const ProKey &var = pro->getHashStr(tokPtr);
             const ProString &val = propertyValue(var);
             debugMsg(2, "property %s => %s", dbgKey(var), dbgStr(val));
             addStr(val, ret, pending, joined);
             break; }
         case TokEnvVar: {
-            const ProString &var = getStr(tokPtr);
+            const ProString &var = pro->getStr(tokPtr);
             const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
             debugMsg(2, "env var %s => %s", dbgStr(var), dbgStr(val));
             addStr(val, ret, pending, joined);
             break; }
         case TokFuncName: {
-            const ProKey &func = getHashStr(tokPtr);
+            const ProKey &func = pro->getHashStr(tokPtr);
             debugMsg(2, "function %s", dbgKey(func));
             addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined);
             break; }
@@ -537,6 +522,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
 {
     traceMsg("entering block");
     ProStringList curr;
+    ProFile *pro = m_current.pro;
     bool okey = true, or_op = false, invert = false;
     uint blockLen;
     while (ushort tok = *tokPtr++) {
@@ -596,7 +582,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
                 blockLen = getBlockLen(tokPtr);
                 ret = visitProBlock(tokPtr);
             } else if (okey != or_op) {
-                const ProKey &variable = getHashStr(tokPtr);
+                const ProKey &variable = pro->getHashStr(tokPtr);
                 uint exprLen = getBlockLen(tokPtr);
                 const ushort *exprPtr = tokPtr;
                 tokPtr += exprLen;
@@ -616,7 +602,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
         case TokTestDef:
         case TokReplaceDef:
             if (m_cumulative || okey != or_op) {
-                const ProKey &name = getHashStr(tokPtr);
+                const ProKey &name = pro->getHashStr(tokPtr);
                 blockLen = getBlockLen(tokPtr);
                 visitProFunctionDef(tok, name, tokPtr);
                 traceMsg("defined %s function %s",
@@ -796,8 +782,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
     forever {
         if (infinite) {
             if (!variable.isEmpty())
-                m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++)));
-            if (index > 1000) {
+                m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index)));
+            if (++index > 1000) {
                 evalError(fL1S("Ran into infinite loop (> 1000 iterations)."));
                 break;
             }
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index 4f2acf25eeffda1e5cc4c96b1c6634a3335d2e50..a60adde84e524d5ffa5471a9040c2e4c2f1a7369 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -150,8 +150,6 @@ public:
         { return b ? ReturnTrue : ReturnFalse; }
 
     static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
-    ProString getStr(const ushort *&tokPtr);
-    ProKey getHashStr(const ushort *&tokPtr);
     void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
     static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
     static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h
index 7c77450523973704f44f0abc2b2b7f7d685e302c..de46ebbe747eca07165a69512af8a0ac9617b521 100644
--- a/qmake/library/qmakeglobals.h
+++ b/qmake/library/qmakeglobals.h
@@ -135,6 +135,7 @@ public:
     bool initProperties();
 #  else
     void setProperties(const QHash<QString, QString> &props);
+    void setProperties(const QHash<ProKey, ProString> &props) { properties = props; }
 #  endif
     ProString propertyValue(const ProKey &name) const { return properties.value(name); }
 #endif
diff --git a/qmake/main.cpp b/qmake/main.cpp
index 27969932bc0807273ccd92b9f83068c1d3aed65e..bde537dcca5642324d5f44476a475d68e2ef4a95 100644
--- a/qmake/main.cpp
+++ b/qmake/main.cpp
@@ -163,6 +163,75 @@ static int doSed(int argc, char **argv)
     return 0;
 }
 
+static int doLink(int argc, char **argv)
+{
+    bool isSymlink = false;
+    bool force = false;
+    QList<const char *> inFiles;
+    for (int i = 0; i < argc; i++) {
+        if (!strcmp(argv[i], "-s")) {
+            isSymlink = true;
+        } else if (!strcmp(argv[i], "-f")) {
+            force = true;
+        } else if (argv[i][0] == '-') {
+            fprintf(stderr, "Error: unrecognized ln option '%s'\n", argv[i]);
+            return 3;
+        } else {
+            inFiles << argv[i];
+        }
+    }
+    if (inFiles.size() != 2) {
+        fprintf(stderr, "Error: this ln requires exactly two file arguments\n");
+        return 3;
+    }
+    if (!isSymlink) {
+        fprintf(stderr, "Error: this ln supports faking symlinks only\n");
+        return 3;
+    }
+    QString target = QString::fromLocal8Bit(inFiles[0]);
+    QString linkname = QString::fromLocal8Bit(inFiles[1]);
+
+    QDir destdir;
+    QFileInfo tfi(target);
+    QFileInfo lfi(linkname);
+    if (lfi.isDir()) {
+        destdir.setPath(linkname);
+        lfi.setFile(destdir, tfi.fileName());
+    } else {
+        destdir.setPath(lfi.path());
+    }
+    if (!destdir.exists()) {
+        fprintf(stderr, "Error: destination directory %s does not exist\n", qPrintable(destdir.path()));
+        return 1;
+    }
+    tfi.setFile(destdir.absoluteFilePath(tfi.filePath()));
+    if (!tfi.exists()) {
+        fprintf(stderr, "Error: this ln does not support symlinking non-existing targets\n");
+        return 3;
+    }
+    if (tfi.isDir()) {
+        fprintf(stderr, "Error: this ln does not support symlinking directories\n");
+        return 3;
+    }
+    if (lfi.exists()) {
+        if (!force) {
+            fprintf(stderr, "Error: %s exists\n", qPrintable(lfi.filePath()));
+            return 1;
+        }
+        if (!QFile::remove(lfi.filePath())) {
+            fprintf(stderr, "Error: cannot overwrite %s\n", qPrintable(lfi.filePath()));
+            return 1;
+        }
+    }
+    if (!QFile::copy(tfi.filePath(), lfi.filePath())) {
+        fprintf(stderr, "Error: cannot copy %s to %s\n",
+                qPrintable(tfi.filePath()), qPrintable(lfi.filePath()));
+        return 1;
+    }
+
+    return 0;
+}
+
 static int doInstall(int argc, char **argv)
 {
     if (!argc) {
@@ -171,6 +240,8 @@ static int doInstall(int argc, char **argv)
     }
     if (!strcmp(argv[0], "sed"))
         return doSed(argc - 1, argv + 1);
+    if (!strcmp(argv[0], "ln"))
+        return doLink(argc - 1, argv + 1);
     fprintf(stderr, "Error: unrecognized -install subcommand '%s'\n", argv[0]);
     return 3;
 }
diff --git a/qtbase.pro b/qtbase.pro
index bae26414046e549c5766a95952d09fda27270d8a..51e8fb8760b5c37cdaa4d29d0e19f8fcf0149a6b 100644
--- a/qtbase.pro
+++ b/qtbase.pro
@@ -46,6 +46,11 @@ equals(QMAKE_HOST.os, Windows) {
 }
 INSTALLS += qmake
 
+#licheck
+licheck.path = $$[QT_HOST_BINS]
+licheck.files = $$PWD/bin/$$QT_LICHECK
+exists($$licheck.files): INSTALLS += licheck
+
 #syncqt
 syncqt.path = $$[QT_HOST_BINS]
 syncqt.files = $$PWD/bin/syncqt.pl
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index 4fde295443081528b692531ad14b3242374fb2d0..4a87488014972cd9b20cf9354963fa46749804eb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -189,6 +189,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
         return egl::Error(EGL_SUCCESS);
     }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: eglPostSubBufferNV comes here
     if (x + width > mWidth)
     {
         width = mWidth - x;
@@ -198,6 +199,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
     {
         height = mHeight - y;
     }
+#endif
 
     if (width == 0 || height == 0)
     {
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
index 81b9ea748dc2397261c79aafb3a9b220c30643d0..0f70fe46152e455c4d66ad0e22655eee05b8e4ff 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
@@ -38,7 +38,7 @@ class InspectableNativeWindow;
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
 
-#else
+#elif defined(ANGLE_ENABLE_D3D11)
 typedef IDXGISwapChain DXGISwapChain;
 typedef IDXGIFactory DXGIFactory;
 #endif
@@ -60,9 +60,11 @@ class NativeWindow
 #endif
     static bool isValidNativeWindow(EGLNativeWindowType window);
 
+#if defined(ANGLE_ENABLE_D3D11)
     HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
                             DXGI_FORMAT format, UINT width, UINT height,
                             DXGISwapChain** swapChain);
+#endif
 
     inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
 
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 298f3ccbd2e3cc84f957487e7dca471080043332..dc539cf66e0a2a714659deb21b546ca232cb6c0e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -552,18 +552,18 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 
     d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
 
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
     // Create a quad in homogeneous coordinates
-    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
-    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
-    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+    float x1 = -1.0f;
+    float y1 = -1.0f;
+    float x2 = 1.0f;
+    float y2 = 1.0f;
 
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
     const float dim = std::max(mWidth, mHeight);
-    float u1 = x / dim;
-    float v1 = y / dim;
-    float u2 = (x + width) / dim;
-    float v2 = (y + height) / dim;
+    float u1 = 0;
+    float v1 = 0;
+    float u2 = float(width) / dim;
+    float v2 = float(height) / dim;
 
     const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
     const bool rotateL = flags == NativeWindow::RotateLeft;
@@ -573,6 +573,12 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
     d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
     d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
 #else
+    // Create a quad in homogeneous coordinates
+    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
     float u1 = x / float(mWidth);
     float v1 = y / float(mHeight);
     float u2 = (x + width) / float(mWidth);
@@ -613,8 +619,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
     viewport.TopLeftX = 0;
     viewport.TopLeftY = 0;
 #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-    viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
-    viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
+    viewport.Width = (rotateL || rotateR) ? height : width;
+    viewport.Height = (rotateL || rotateR) ? width : height;
 #else
     viewport.Width = mWidth;
     viewport.Height = mHeight;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
index 9d8f0bb96cedd9748eebd1d605502a36c65957cd..0a4f45b5b75ac02a5b85c0516d9619b77e02bfff 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
@@ -37,6 +37,7 @@ bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
     return IsWindow(window) == TRUE;
 }
 
+#if defined(ANGLE_ENABLE_D3D11)
 HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
                                       DXGI_FORMAT format, unsigned int width, unsigned int height,
                                       DXGISwapChain** swapChain)
@@ -65,4 +66,5 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
 
     return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
 }
+#endif
 }
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
index 350526c867e815a33ff9369483d2573c0b59de7b..fa9a69c5a1f91f35cafd65858445c7c7a9911b18 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -100,6 +100,7 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
     if (SUCCEEDED(result))
     {
         result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
+        orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr);
     }
 #endif
 
@@ -135,8 +136,8 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
     }
 
     DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
-    swapChainDesc.Width = width;
-    swapChainDesc.Height = height;
+    swapChainDesc.Width = mRotationFlags ? height : width;
+    swapChainDesc.Height = mRotationFlags ? width : height;
     swapChainDesc.Format = format;
     swapChainDesc.Stereo = FALSE;
     swapChainDesc.SampleDesc.Count = 1;
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
index ded73dbb485bb808f613f95af753918d067fbfe5..62f3ca1207a19d61f62e55a90c0b451d25c1d9c8 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
@@ -101,12 +101,14 @@ EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLin
         return EGL_FALSE;
     }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: Allow this entry point as a workaround
     if (!display->getExtensions().postSubBuffer)
     {
         // Spec is not clear about how this should be handled.
         SetGlobalError(Error(EGL_SUCCESS));
         return EGL_TRUE;
     }
+#endif
 
     error = eglSurface->postSubBuffer(x, y, width, height);
     if (error.isError())
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index 017ae0741e0cca34030d95760092cfa0c14b9f87..8d08f403ecb8bed7839176c6bd7678282c8ba654 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -63,7 +63,7 @@
 #  include <Availability.h>
 #  include <AvailabilityMacros.h>
 #  if MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
-#    define HAVE_BROKEN_WAITID_ALL 1
+#    define HAVE_BROKEN_WAITID 1
 #  endif
 #endif
 
@@ -109,10 +109,10 @@ static struct sigaction old_sigaction;
 static pthread_once_t forkfd_initialization = PTHREAD_ONCE_INIT;
 static ffd_atomic_int forkfd_status = FFD_ATOMIC_INIT(0);
 
-#ifdef HAVE_BROKEN_WAITID_ALL
-static int waitid_p_all_works = 0;
+#ifdef HAVE_BROKEN_WAITID
+static int waitid_works = 0;
 #else
-static const int waitid_p_all_works = 1;
+static const int waitid_works = 1;
 #endif
 
 static ProcessInfo *tryAllocateInSection(Header *header, ProcessInfo entries[], int maxCount)
@@ -183,10 +183,13 @@ static int tryReaping(pid_t pid, siginfo_t *info)
 {
     /* reap the child */
 #ifdef HAVE_WAITID
-    // we have waitid(2), which fills in siginfo_t for us
-    info->si_pid = 0;
-    return waitid(P_PID, pid, info, WEXITED | WNOHANG) == 0 && info->si_pid == pid;
-#else
+    if (waitid_works) {
+        // we have waitid(2), which fills in siginfo_t for us
+        info->si_pid = 0;
+        return waitid(P_PID, pid, info, WEXITED | WNOHANG) == 0 && info->si_pid == pid;
+    }
+#endif
+
     int status;
     if (waitpid(pid, &status, WNOHANG) <= 0)
         return 0;     // child did not change state
@@ -206,7 +209,6 @@ static int tryReaping(pid_t pid, siginfo_t *info)
     }
 
     return 1;
-#endif
 }
 
 static void freeInfo(Header *header, ProcessInfo *entry)
@@ -246,7 +248,7 @@ static void sigchld_handler(int signum)
         memset(&info, 0, sizeof info);
 
 #ifdef HAVE_WAITID
-        if (!waitid_p_all_works)
+        if (!waitid_works)
             goto search_arrays;
 
         /* be optimistic: try to see if we can get the child that exited */
@@ -310,12 +312,14 @@ search_arrays:
             if (pid <= 0)
                 continue;
 #ifdef HAVE_WAITID
-            /* The child might have been reaped by the block above in another thread,
-             * so first check if it's ready and, if it is, lock it */
-            if (!isChildReady(pid, &info) ||
-                    !ffd_atomic_compare_exchange(&children.entries[i].pid, &pid, -1,
-                                                 FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
-                continue;
+            if (waitid_works) {
+                /* The child might have been reaped by the block above in another thread,
+                 * so first check if it's ready and, if it is, lock it */
+                if (!isChildReady(pid, &info) ||
+                        !ffd_atomic_compare_exchange(&children.entries[i].pid, &pid, -1,
+                                                     FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
+                    continue;
+            }
 #endif
             if (tryReaping(pid, &info)) {
                 /* this is our child, send notification and free up this entry */
@@ -331,12 +335,14 @@ search_arrays:
                 if (pid <= 0)
                     continue;
 #ifdef HAVE_WAITID
-                /* The child might have been reaped by the block above in another thread,
-                 * so first check if it's ready and, if it is, lock it */
-                if (!isChildReady(pid, &info) ||
-                        !ffd_atomic_compare_exchange(&array->entries[i].pid, &pid, -1,
-                                                     FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
-                    continue;
+                if (waitid_works) {
+                    /* The child might have been reaped by the block above in another thread,
+                     * so first check if it's ready and, if it is, lock it */
+                    if (!isChildReady(pid, &info) ||
+                            !ffd_atomic_compare_exchange(&array->entries[i].pid, &pid, -1,
+                                                         FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
+                        continue;
+                }
 #endif
                 if (tryReaping(pid, &info)) {
                     /* this is our child, send notification and free up this entry */
@@ -357,17 +363,19 @@ chain_handler:
 
 static void forkfd_initialize()
 {
-#if defined(HAVE_BROKEN_WAITID_ALL)
+#if defined(HAVE_BROKEN_WAITID)
     pid_t pid = fork();
     if (pid == 0) {
         _exit(0);
     } else if (pid > 0) {
         siginfo_t info;
         waitid(P_ALL, 0, &info, WNOWAIT | WEXITED);
-        waitid_p_all_works = (info.si_pid != 0);
+        waitid_works = (info.si_pid != 0);
+        info.si_pid = 0;
 
         // now really reap the child
         waitid(P_PID, pid, &info, WEXITED);
+        waitid_works = waitid_works && (info.si_pid != 0);
     }
 #endif
 
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
index 7438d5994c83fb72ab1113d19bd1ca58aa277830..2d4627e4f7c5eea5341056e40bfecff8fb12e827 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
@@ -241,7 +241,7 @@ static HB_Bool HB_ThaiConvertStringToGlyphIndices (HB_ShaperItem *item)
         int lgn = 0;
         HB_Bool haveSaraAm = false;
 
-        cell_length = th_next_cell ((const unsigned char *)cstr + i, len - i, &tis_cell, true); /* !item->fixedPitch); */
+        cell_length = (int)(th_next_cell ((const unsigned char *)cstr + i, len - i, &tis_cell, true)); /* !item->fixedPitch); */
         haveSaraAm  = (cstr[i + cell_length - 1] == (char)0xd3);
 
         /* set shaper item's log_clusters */
@@ -432,7 +432,7 @@ static void HB_ThaiAssignAttributes(const HB_UChar16 *string, hb_uint32 len, HB_
     /* manage grapheme boundaries */
     i = 0;
     while (i < len) {
-        cell_length = th_next_cell((const unsigned char *)cstr + i, len - i, &tis_cell, true);
+        cell_length = (hb_uint32)(th_next_cell((const unsigned char *)cstr + i, len - i, &tis_cell, true));
 
         attributes[i].graphemeBoundary = true;
         for (j = 1; j < cell_length; j++)
diff --git a/src/3rdparty/md4/md4.cpp b/src/3rdparty/md4/md4.cpp
index 94ac6adf58b106de8609fbe012f447e79aa1a2ea..ec74958d690a3ed1935352cf36e186ebe8e4f212 100644
--- a/src/3rdparty/md4/md4.cpp
+++ b/src/3rdparty/md4/md4.cpp
@@ -180,7 +180,7 @@ static void md4_update(struct md4_context *ctx, const unsigned char *data, size_
 	saved_lo = ctx->lo;
 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
 		ctx->hi++;
-	ctx->hi += size >> 29;
+	ctx->hi += (quint32)(size >> 29);
 
 	used = saved_lo & 0x3f;
 
diff --git a/src/3rdparty/pcre/AUTHORS b/src/3rdparty/pcre/AUTHORS
index 5eee1af4c6fd252594ccc538d121c13e4ac5e431..d33723f198a836d094709c868dce2ec6bab2de0b 100644
--- a/src/3rdparty/pcre/AUTHORS
+++ b/src/3rdparty/pcre/AUTHORS
@@ -8,7 +8,7 @@ Email domain:     cam.ac.uk
 University of Cambridge Computing Service,
 Cambridge, England.
 
-Copyright (c) 1997-2014 University of Cambridge
+Copyright (c) 1997-2015 University of Cambridge
 All rights reserved
 
 
@@ -19,7 +19,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2010-2014 Zoltan Herczeg
+Copyright(c) 2010-2015 Zoltan Herczeg
 All rights reserved.
 
 
@@ -30,7 +30,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2009-2014 Zoltan Herczeg
+Copyright(c) 2009-2015 Zoltan Herczeg
 All rights reserved.
 
 
diff --git a/src/3rdparty/pcre/LICENCE b/src/3rdparty/pcre/LICENCE
index 602e4ae680467f9db3260f16ae0f65fcfa01544a..9f6f98e477f474520aad41ac52c54797ca614ad2 100644
--- a/src/3rdparty/pcre/LICENCE
+++ b/src/3rdparty/pcre/LICENCE
@@ -6,7 +6,8 @@ and semantics are as close as possible to those of the Perl 5 language.
 
 Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
 specified below. The documentation for PCRE, supplied in the "doc"
-directory, is distributed under the same terms as the software itself.
+directory, is distributed under the same terms as the software itself. The data
+in the testdata directory is not copyrighted and is in the public domain.
 
 The basic library functions are written in C and are freestanding. Also
 included in the distribution is a set of C++ wrapper functions, and a
@@ -24,7 +25,7 @@ Email domain:     cam.ac.uk
 University of Cambridge Computing Service,
 Cambridge, England.
 
-Copyright (c) 1997-2014 University of Cambridge
+Copyright (c) 1997-2015 University of Cambridge
 All rights reserved.
 
 
@@ -35,7 +36,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2010-2014 Zoltan Herczeg
+Copyright(c) 2010-2015 Zoltan Herczeg
 All rights reserved.
 
 
@@ -46,7 +47,7 @@ Written by:       Zoltan Herczeg
 Email local part: hzmester
 Emain domain:     freemail.hu
 
-Copyright(c) 2009-2014 Zoltan Herczeg
+Copyright(c) 2009-2015 Zoltan Herczeg
 All rights reserved.
 
 
diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h
index 20f04ebed4338a7a9fcd2673b5be4165cd0abdf7..58ed46a2a31322bd312379358c08f777df4a7a4b 100644
--- a/src/3rdparty/pcre/pcre.h
+++ b/src/3rdparty/pcre/pcre.h
@@ -43,8 +43,8 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #define PCRE_MAJOR          8
 #define PCRE_MINOR          37
-#define PCRE_PRERELEASE     -RC1
-#define PCRE_DATE           2015-02-03
+#define PCRE_PRERELEASE     
+#define PCRE_DATE           2015-04-28
 
 /* When an application links to a PCRE DLL in Windows, the symbols that are
 imported have to be identified as such. When building PCRE, the appropriate
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
index 6510835c172f53b9c676fabd316bfd531113b2bc..0efad2645d9d0164b56c3bd279348299997969bc 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre/pcre_compile.c
@@ -866,14 +866,6 @@ static const pcre_uint8 opcode_possessify[] = {
 };
 
 
-/* Structure for mutual recursion detection. */
-
-typedef struct recurse_check {
-  struct recurse_check *prev;
-  const pcre_uchar *group;
-} recurse_check;
-
-
 
 /*************************************************
 *            Find an error text                  *
@@ -5532,13 +5524,13 @@ for (;; ptr++)
       PUT(previous, 1, (int)(code - previous));
       break;   /* End of class handling */
       }
-#endif
 
     /* Even though any XCLASS list is now discarded, we must allow for
     its memory. */
 
     if (lengthptr != NULL)
       *lengthptr += (int)(class_uchardata - class_uchardata_base);
+#endif
 
     /* If there are no characters > 255, or they are all to be included or
     excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h
index 1c5f4cefd69692a428f1ac51a829e0d623e473b5..dd0ac7fc912eaa13ddb60c553ddabf7865d30d8c 100644
--- a/src/3rdparty/pcre/pcre_internal.h
+++ b/src/3rdparty/pcre/pcre_internal.h
@@ -2446,7 +2446,7 @@ typedef struct compile_data {
   BOOL had_pruneorskip;             /* (*PRUNE) or (*SKIP) encountered */
   BOOL check_lookbehind;            /* Lookbehinds need later checking */
   BOOL dupnames;                    /* Duplicate names exist */
-  BOOL iscondassert;                /* Next assert is a condition */ 
+  BOOL iscondassert;                /* Next assert is a condition */
   int  nltype;                      /* Newline type */
   int  nllen;                       /* Newline string length */
   pcre_uchar nl[4];                 /* Newline string when fixed length */
@@ -2460,6 +2460,13 @@ typedef struct branch_chain {
   pcre_uchar *current_branch;
 } branch_chain;
 
+/* Structure for mutual recursion detection. */
+
+typedef struct recurse_check {
+  struct recurse_check *prev;
+  const pcre_uchar *group;
+} recurse_check;
+
 /* Structure for items in a linked list that represents an explicit recursive
 call within the pattern; used by pcre_exec(). */
 
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c
index dd378e097b4a5cc89a1c1c2c2c2f44bb36bbcfce..debdf6ef45e3a7480780b7f1ef9bf994ef713ce4 100644
--- a/src/3rdparty/pcre/pcre_jit_compile.c
+++ b/src/3rdparty/pcre/pcre_jit_compile.c
@@ -1533,7 +1533,11 @@ while (cc < ccend)
     {
     case OP_KET:
     if (PRIVATE_DATA(cc) != 0)
+      {
       private_data_length++;
+      SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
+      cc += PRIVATE_DATA(cc + 1);
+      }
     cc += 1 + LINK_SIZE;
     break;
 
@@ -1548,6 +1552,7 @@ while (cc < ccend)
     case OP_SBRAPOS:
     case OP_SCOND:
     private_data_length++;
+    SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);
     cc += 1 + LINK_SIZE;
     break;
 
@@ -1710,6 +1715,8 @@ do
         {
         count = 1;
         srcw[0] = PRIVATE_DATA(cc);
+        SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
+        cc += PRIVATE_DATA(cc + 1);
         }
       cc += 1 + LINK_SIZE;
       break;
diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c
index a2458c4c96c0db25e1821fb891a74b44efb36548..998fe2325ef240905aba0bf722dbbcdf3d01b0e1 100644
--- a/src/3rdparty/pcre/pcre_study.c
+++ b/src/3rdparty/pcre/pcre_study.c
@@ -70,7 +70,7 @@ Arguments:
   code            pointer to start of group (the bracket)
   startcode       pointer to start of the whole pattern's code
   options         the compiling options
-  int             RECURSE depth
+  recurses        chain of recurse_check to catch mutual recursion
 
 Returns:   the minimum length
            -1 if \C in UTF-8 mode or (*ACCEPT) was encountered
@@ -80,12 +80,13 @@ Returns:   the minimum length
 
 static int
 find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
-  const pcre_uchar *startcode, int options, int recurse_depth)
+  const pcre_uchar *startcode, int options, recurse_check *recurses)
 {
 int length = -1;
 /* PCRE_UTF16 has the same value as PCRE_UTF8. */
 BOOL utf = (options & PCRE_UTF8) != 0;
 BOOL had_recurse = FALSE;
+recurse_check this_recurse;
 register int branchlength = 0;
 register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
 
@@ -130,7 +131,7 @@ for (;;)
     case OP_SBRAPOS:
     case OP_ONCE:
     case OP_ONCE_NC:
-    d = find_minlength(re, cc, startcode, options, recurse_depth);
+    d = find_minlength(re, cc, startcode, options, recurses);
     if (d < 0) return d;
     branchlength += d;
     do cc += GET(cc, 1); while (*cc == OP_ALT);
@@ -393,7 +394,7 @@ for (;;)
         ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
         if (cs == NULL) return -2;
         do ce += GET(ce, 1); while (*ce == OP_ALT);
-        if ((cc > cs && cc < ce) || recurse_depth > 10)
+        if (cc > cs && cc < ce)     /* Simple recursion */
           {
           d = 0;
           had_recurse = TRUE;
@@ -401,8 +402,22 @@ for (;;)
           }
         else
           {
-          int dd = find_minlength(re, cs, startcode, options, recurse_depth+1);
-          if (dd < d) d = dd;
+          recurse_check *r = recurses;
+          for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+          if (r != NULL)           /* Mutual recursion */
+            {
+            d = 0;
+            had_recurse = TRUE;
+            break;
+            }
+          else
+            {
+            int dd;
+            this_recurse.prev = recurses;
+            this_recurse.group = cs;
+            dd = find_minlength(re, cs, startcode, options, &this_recurse);
+            if (dd < d) d = dd;
+            }
           }
         slot += re->name_entry_size;
         }
@@ -418,14 +433,26 @@ for (;;)
       ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
       if (cs == NULL) return -2;
       do ce += GET(ce, 1); while (*ce == OP_ALT);
-      if ((cc > cs && cc < ce) || recurse_depth > 10)
+      if (cc > cs && cc < ce)    /* Simple recursion */
         {
         d = 0;
         had_recurse = TRUE;
         }
       else
         {
-        d = find_minlength(re, cs, startcode, options, recurse_depth + 1);
+        recurse_check *r = recurses;
+        for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+        if (r != NULL)           /* Mutual recursion */
+          {
+          d = 0;
+          had_recurse = TRUE;
+          }
+        else
+          {
+          this_recurse.prev = recurses;
+          this_recurse.group = cs;
+          d = find_minlength(re, cs, startcode, options, &this_recurse);
+          }
         }
       }
     else d = 0;
@@ -474,12 +501,21 @@ for (;;)
     case OP_RECURSE:
     cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
     do ce += GET(ce, 1); while (*ce == OP_ALT);
-    if ((cc > cs && cc < ce) || recurse_depth > 10)
+    if (cc > cs && cc < ce)    /* Simple recursion */
       had_recurse = TRUE;
     else
       {
-      branchlength += find_minlength(re, cs, startcode, options,
-        recurse_depth + 1);
+      recurse_check *r = recurses;
+      for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+      if (r != NULL)           /* Mutual recursion */
+        had_recurse = TRUE;
+      else
+        {
+        this_recurse.prev = recurses;
+        this_recurse.group = cs;
+        branchlength += find_minlength(re, cs, startcode, options,
+          &this_recurse);
+        }
       }
     cc += 1 + LINK_SIZE;
     break;
@@ -1503,7 +1539,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
 
 /* Find the minimum length of subject string. */
 
-switch(min = find_minlength(re, code, code, re->options, 0))
+switch(min = find_minlength(re, code, code, re->options, NULL))
   {
   case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
   case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
index c5251be53da65e190585b5130a8682e9f4a2e71f..b66455f756980b3a3101997dcefc871310812477 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
@@ -1081,12 +1081,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 		FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
 		offs = (local_size - saved_regs_size) << (15 - 3);
 	} else {
-		compiler->local_size += 2 * sizeof(sljit_sw);
-		local_size -= saved_regs_size;
-		saved_regs_size += 2 * sizeof(sljit_sw);
-		FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
-			| RN(TMP_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15)));
-		offs = 2 << 15;
+		offs = 0 << 15;
+		if (saved_regs_size & 0x8) {
+			offs = 1 << 15;
+			saved_regs_size += sizeof(sljit_sw);
+		}
+		local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
+		FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
 	}
 
 	tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
@@ -1122,6 +1123,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
 		}
 		if (local_size)
 			FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
+		FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
+			| RN(TMP_SP) | ((-(16 >> 3) & 0x7f) << 15)));
 		FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
 	}
 
@@ -1145,8 +1148,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compi
 
 	local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0) + SLJIT_LOCALS_OFFSET;
 	local_size = (local_size + 15) & ~0xf;
-	if (local_size > (63 * sizeof(sljit_sw)))
-		local_size += 2 * sizeof(sljit_sw);
 	compiler->local_size = local_size;
 	return SLJIT_SUCCESS;
 }
@@ -1167,16 +1168,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 	if (local_size <= (63 * sizeof(sljit_sw)))
 		offs = (local_size - saved_regs_size) << (15 - 3);
 	else {
-		saved_regs_size += 2 * sizeof(sljit_sw);
-		local_size -= saved_regs_size;
+		FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
+			| RN(TMP_SP) | (((16 >> 3) & 0x7f) << 15)));
+		offs = 0 << 15;
+		if (saved_regs_size & 0x8) {
+			offs = 1 << 15;
+			saved_regs_size += sizeof(sljit_sw);
+		}
+		local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
 		if (local_size > 0xfff) {
 			FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
 			local_size &= 0xfff;
 		}
 		if (local_size)
 			FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
-		local_size = saved_regs_size;
-		offs = 2 << 15;
 	}
 
 	tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
@@ -1204,8 +1209,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
 	if (prev != -1)
 		FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
 
-	FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
-		| RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
+	if (compiler->local_size <= (63 * sizeof(sljit_sw))) {
+		FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
+			| RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
+	} else {
+		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
+	}
 
 	FAIL_IF(push_inst(compiler, RET | RN(TMP_LR)));
 	return SLJIT_SUCCESS;
diff --git a/src/3rdparty/sha3/KeccakF-1600-32-rvk.macros b/src/3rdparty/sha3/KeccakF-1600-32-rvk.macros
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-32.macros b/src/3rdparty/sha3/KeccakF-1600-32.macros
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-64.macros b/src/3rdparty/sha3/KeccakF-1600-64.macros
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-int-set.h b/src/3rdparty/sha3/KeccakF-1600-int-set.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-interface.h b/src/3rdparty/sha3/KeccakF-1600-interface.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-opt32-settings.h b/src/3rdparty/sha3/KeccakF-1600-opt32-settings.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-opt32.c b/src/3rdparty/sha3/KeccakF-1600-opt32.c
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-opt64-settings.h b/src/3rdparty/sha3/KeccakF-1600-opt64-settings.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakF-1600-unrolling.macros b/src/3rdparty/sha3/KeccakF-1600-unrolling.macros
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakNISTInterface.c b/src/3rdparty/sha3/KeccakNISTInterface.c
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakNISTInterface.h b/src/3rdparty/sha3/KeccakNISTInterface.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakSponge.c b/src/3rdparty/sha3/KeccakSponge.c
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/KeccakSponge.h b/src/3rdparty/sha3/KeccakSponge.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sha3/brg_endian.h b/src/3rdparty/sha3/brg_endian.h
old mode 100755
new mode 100644
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 086fb3bcd69320473deb794986ded23f543bd3f6..71f6c1036dfbc5436a90fc45c10c7993b261c328 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -34875,6 +34875,7 @@ static void winLogIoerr(int nRetry){
 ** create a substitute.
 */
 /* #include <time.h> */
+#  if _WIN32_WCE < 0x800
 struct tm *__cdecl localtime(const time_t *t)
 {
   static struct tm y;
@@ -34896,6 +34897,7 @@ struct tm *__cdecl localtime(const time_t *t)
   y.tm_sec = pTm.wSecond;
   return &y;
 }
+#  endif
 #endif
 
 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
index 4df70796bda22f882eb1211e0681ee89b04d4cd8..ff0032d6233c720f76ed752daa6b7fad2409dcf5 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
@@ -1111,7 +1111,9 @@ public class ExtractStyle {
                 {
                     try {
                         InsetDrawable d = (InsetDrawable)drawable;
-                        Object mInsetStateObject = getAccessibleField(InsetDrawable.class, "mInsetState").get(d);
+                        // mInsetState changed to mState in Android 5.1 (22)
+                        Object mInsetStateObject = getAccessibleField(InsetDrawable.class, (Build.VERSION.SDK_INT > 21) ? "mState"
+                                                                                                                        : "mInsetState").get(d);
                         Rect _padding = new Rect();
                         boolean hasPadding = d.getPadding(_padding);
                         return getDrawable(getAccessibleField(mInsetStateObject.getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null);
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index da52369de0f264f5c0b2d1f9b721c865dfa45dc7..18fa2f8fde7e24e0f276684da60fe2f5ddfb1b35 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -65,7 +65,6 @@ import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
-import android.widget.LinearLayout;
 
 import java.io.BufferedReader;
 import java.io.DataOutputStream;
@@ -790,29 +789,7 @@ public class QtActivityDelegate
                                                   metrics.xdpi, metrics.ydpi,
                                                   metrics.scaledDensity, metrics.density);
         }
-
-        ViewGroup layout = null;
         m_layout = new QtLayout(m_activity);
-        if (Build.VERSION.SDK_INT >= 14) {
-            try {
-                ActivityInfo activityInfo = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(),
-                                                                                           PackageManager.GET_META_DATA);
-                if (activityInfo.metaData == null
-                    || !activityInfo.metaData.containsKey("android.app.allow_overlapping_system_ui")
-                    || !activityInfo.metaData.getBoolean("android.app.allow_overlapping_system_ui")) {
-                        layout = new LinearLayout(m_activity);
-                        layout.setFitsSystemWindows(true);
-                        layout.addView(m_layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                                                                            ViewGroup.LayoutParams.MATCH_PARENT));
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-
-        if (layout == null)
-            layout = m_layout;
-
         m_editText = new QtEditText(m_activity, this);
         m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
         m_surfaces =  new HashMap<Integer, QtSurface>();
@@ -835,7 +812,7 @@ public class QtActivityDelegate
             Log.w("Qt A11y", "Unknown exception: " + e.toString());
         }
 
-        m_activity.setContentView(layout,
+        m_activity.setContentView(m_layout,
                                   new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                                              ViewGroup.LayoutParams.MATCH_PARENT));
 
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 6855a47554c2deaecb5b57ffd07f98dcf524353b..b7363e5d8739361f965415a4ee9f57fb376d4720 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -43,6 +43,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.text.ClipboardManager;
+import android.os.Build;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.Menu;
@@ -306,32 +307,49 @@ public class QtNative
 
     static public void sendTouchEvent(MotionEvent event, int id)
     {
-        //@ANDROID-5
-        touchBegin(id);
-        for (int i=0;i<event.getPointerCount();i++) {
-                touchAdd(id,
-                         event.getPointerId(i),
-                         getAction(i, event),
-                         i == 0,
-                         (int)event.getX(i),
-                         (int)event.getY(i),
-                         event.getSize(i),
-                         event.getPressure(i));
-        }
+        int pointerType = 0;
 
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                touchEnd(id,0);
+        if (Build.VERSION.SDK_INT >= 14) {
+            switch (event.getToolType(0)) {
+            case MotionEvent.TOOL_TYPE_STYLUS:
+                pointerType = 1; // QTabletEvent::Pen
                 break;
-
-            case MotionEvent.ACTION_UP:
-                touchEnd(id,2);
+            case MotionEvent.TOOL_TYPE_ERASER:
+                pointerType = 3; // QTabletEvent::Eraser
                 break;
+            // TODO TOOL_TYPE_MOUSE
+            }
+        }
 
-            default:
-                touchEnd(id,1);
+        if (pointerType != 0) {
+            tabletEvent(id, event.getDeviceId(), event.getEventTime(), event.getAction(), pointerType,
+                event.getButtonState(), event.getX(), event.getY(), event.getPressure());
+        } else {
+            touchBegin(id);
+            for (int i = 0; i < event.getPointerCount(); ++i) {
+                    touchAdd(id,
+                             event.getPointerId(i),
+                             getAction(i, event),
+                             i == 0,
+                             (int)event.getX(i),
+                             (int)event.getY(i),
+                             event.getSize(i),
+                             event.getPressure(i));
+            }
+
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    touchEnd(id, 0);
+                    break;
+
+                case MotionEvent.ACTION_UP:
+                    touchEnd(id, 2);
+                    break;
+
+                default:
+                    touchEnd(id, 1);
+            }
         }
-        //@ANDROID-5
     }
 
     static public void sendTrackballEvent(MotionEvent event, int id)
@@ -598,6 +616,10 @@ public class QtNative
     public static native void longPress(int winId, int x, int y);
     // pointer methods
 
+    // tablet methods
+    public static native void tabletEvent(int winId, int deviceId, long time, int action, int pointerType, int buttonState, float x, float y, float pressure);
+    // tablet methods
+
     // keyboard methods
     public static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat);
     public static native void keyUp(int key, int unicode, int modifier, boolean autoRepeat);
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 95af3c87adbfa17b81918780c9558859a02b0703..23e08f537a9faaf1552878678c11cbd8793d92bc 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -187,7 +187,7 @@ public class QtActivity extends Activity
             QT_ANDROID_THEMES = new String[] {"Theme_Light"};
             QT_ANDROID_DEFAULT_THEME = "Theme_Light";
         }
-        else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT == 21){
+        else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT >= 21){
             QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
             QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
         } else {
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index 779612cdafe61c66f32571de90a9d65e0baaa511..60c612976f97dec23177bfae09c586340c323e00 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -44,10 +44,6 @@
                           signal is sent! -->
             <meta-data android:name="android.app.background_running" android:value="false"/>
             <!-- Background running -->
-
-            <!-- Show translucent UI on top of Qt's surface when system theme mandates it -->
-            <meta-data android:name="android.app.allow_overlapping_system_ui" android:value="false"/>
-            <!-- Show translucent UI on top of Qt's surface when system theme mandates it -->
         </activity>
     </application>
     <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
diff --git a/src/angle/patches/0006-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch b/src/angle/patches/0006-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5c6ef7b0367055f347a78e4a43abe09253c25332
--- /dev/null
+++ b/src/angle/patches/0006-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch
@@ -0,0 +1,145 @@
+From f0fb8d75bd2c7a894df1cb7e7d3dcd1ad0fd88d0 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Sun, 3 May 2015 20:55:04 +0300
+Subject: [PATCH] ANGLE: Allow Windows Phone to communicate swap region
+
+eglPostSubBufferNV is used to communicate the size of the window, as
+otherwise there is no way for the renderer to know if the last frame was
+rendered in landscape or portrait, causing rendering glitches when the
+orientation changes. The rotation flags are utilized in a few additional
+places now to fix some corner cases where the rotation was not applied.
+
+This patch should be squashed into "ANGLE-Improve-Windows-Phone-Support"
+during the next ANGLE rebase.
+
+Task-number: QTBUG-44333
+Task-number: QTBUG-43502
+Change-Id: Iec37f7531854184819c30c87eab82d96d56ff133
+---
+ .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp |  2 ++
+ .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp    | 28 +++++++++++++---------
+ .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp     |  5 ++--
+ .../angle/src/libGLESv2/entry_points_egl_ext.cpp   |  2 ++
+ 4 files changed, 24 insertions(+), 13 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+index 4fde295..4a87488 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+@@ -189,6 +189,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+         return egl::Error(EGL_SUCCESS);
+     }
+ 
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: eglPostSubBufferNV comes here
+     if (x + width > mWidth)
+     {
+         width = mWidth - x;
+@@ -198,6 +199,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+     {
+         height = mHeight - y;
+     }
++#endif
+ 
+     if (width == 0 || height == 0)
+     {
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+index 298f3cc..dc539cf 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+@@ -552,18 +552,18 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+ 
+     d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+ 
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+     // Create a quad in homogeneous coordinates
+-    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+-    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+-    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+-    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
++    float x1 = -1.0f;
++    float y1 = -1.0f;
++    float x2 = 1.0f;
++    float y2 = 1.0f;
+ 
+-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+     const float dim = std::max(mWidth, mHeight);
+-    float u1 = x / dim;
+-    float v1 = y / dim;
+-    float u2 = (x + width) / dim;
+-    float v2 = (y + height) / dim;
++    float u1 = 0;
++    float v1 = 0;
++    float u2 = float(width) / dim;
++    float v2 = float(height) / dim;
+ 
+     const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
+     const bool rotateL = flags == NativeWindow::RotateLeft;
+@@ -573,6 +573,12 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+     d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
+     d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
+ #else
++    // Create a quad in homogeneous coordinates
++    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
++    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
++    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
++    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
++
+     float u1 = x / float(mWidth);
+     float v1 = y / float(mHeight);
+     float u2 = (x + width) / float(mWidth);
+@@ -613,8 +619,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+     viewport.TopLeftX = 0;
+     viewport.TopLeftY = 0;
+ #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+-    viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
+-    viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
++    viewport.Width = (rotateL || rotateR) ? height : width;
++    viewport.Height = (rotateL || rotateR) ? width : height;
+ #else
+     viewport.Width = mWidth;
+     viewport.Height = mHeight;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+index 350526c..fa9a69c 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+@@ -100,6 +100,7 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
+     if (SUCCEEDED(result))
+     {
+         result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
++        orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr);
+     }
+ #endif
+ 
+@@ -135,8 +136,8 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
+     }
+ 
+     DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+-    swapChainDesc.Width = width;
+-    swapChainDesc.Height = height;
++    swapChainDesc.Width = mRotationFlags ? height : width;
++    swapChainDesc.Height = mRotationFlags ? width : height;
+     swapChainDesc.Format = format;
+     swapChainDesc.Stereo = FALSE;
+     swapChainDesc.SampleDesc.Count = 1;
+diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+index ded73db..62f3ca1 100644
+--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+@@ -101,12 +101,14 @@ EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLin
+         return EGL_FALSE;
+     }
+ 
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: Allow this entry point as a workaround
+     if (!display->getExtensions().postSubBuffer)
+     {
+         // Spec is not clear about how this should be handled.
+         SetGlobalError(Error(EGL_SUCCESS));
+         return EGL_TRUE;
+     }
++#endif
+ 
+     error = eglSurface->postSubBuffer(x, y, width, height);
+     if (error.isError())
+-- 
+1.9.5.msysgit.0
+
diff --git a/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch b/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch
new file mode 100644
index 0000000000000000000000000000000000000000..eca7d0e162886c9a87404781eededcc526feddd1
--- /dev/null
+++ b/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch
@@ -0,0 +1,57 @@
+From 1f993a2492a618becd4bf89ef0d6cb5d2c9aa67a Mon Sep 17 00:00:00 2001
+From: Kai Koehne <kai.koehne@theqtcompany.com>
+Date: Mon, 11 May 2015 15:17:12 +0200
+Subject: [PATCH] ANGLE: Fix compilation without d3d11
+
+Change-Id: I0b772698cf521083e5ecf35a395af57100a50131
+---
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h     | 4 +++-
+ .../angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp      | 2 ++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+index 81b9ea7..0f70fe4 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+@@ -38,7 +38,7 @@ class InspectableNativeWindow;
+ using namespace Microsoft::WRL;
+ using namespace Microsoft::WRL::Wrappers;
+ 
+-#else
++#elif defined(ANGLE_ENABLE_D3D11)
+ typedef IDXGISwapChain DXGISwapChain;
+ typedef IDXGIFactory DXGIFactory;
+ #endif
+@@ -60,9 +60,11 @@ class NativeWindow
+ #endif
+     static bool isValidNativeWindow(EGLNativeWindowType window);
+ 
++#if defined(ANGLE_ENABLE_D3D11)
+     HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                             DXGI_FORMAT format, UINT width, UINT height,
+                             DXGISwapChain** swapChain);
++#endif
+ 
+     inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+ 
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+index 9d8f0bb..0a4f45b 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+@@ -37,6 +37,7 @@ bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
+     return IsWindow(window) == TRUE;
+ }
+ 
++#if defined(ANGLE_ENABLE_D3D11)
+ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                                       DXGI_FORMAT format, unsigned int width, unsigned int height,
+                                       DXGISwapChain** swapChain)
+@@ -65,4 +66,5 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
+ 
+     return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+ }
++#endif
+ }
+-- 
+1.9.5.msysgit.0
+
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
index 63b80347d10b67a685f61662a5044877891ec0fe..735c841ad8862054c7d902a823f1bae9611d5282 100644
--- a/src/angle/src/common/common.pri
+++ b/src/angle/src/common/common.pri
@@ -13,7 +13,7 @@ lib_replace.CONFIG = path
 QMAKE_PRL_INSTALL_REPLACE += lib_replace
 
 # DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK.
-win32-msvc2012|win32-msvc2013|winrt {
+winrt|if(msvc:!win32-msvc2005:!win32-msvc2008:!win32-msvc2010) {
     FXC = fxc.exe
 } else {
     DX_DIR = $$(DXSDK_DIR)
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index 1bf9af0436740372797c54cd3493d37d20a8690e..5979b680985576f4575118db7966313b09f5458e 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -329,6 +329,8 @@ angle_d3d11 {
 !static {
     DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${TARGET}.def
     mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${TARGET}_mingw32.def
+} else {
+    DEFINES += DllMain=DllMain_ANGLE # prevent symbol from conflicting with the user's DllMain
 }
 
 float_converter.target = float_converter
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
index 7213a844f5a564f8bf700ff302570ea2597214ea..65fd1f93838c1f7318cc97cb2a78192d9bddff27 100644
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
@@ -70,8 +70,14 @@ set(_qt5_corelib_extra_includes)
 # Qt5_POSITION_INDEPENDENT_CODE variable is used in the # qt5_use_module
 # macro to add it.
 set(Qt5_POSITION_INDEPENDENT_CODE True)
-set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
-set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIE\")
+set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
+if (CMAKE_VERSION VERSION_LESS 2.8.12
+        AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
+        OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
+    set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
+else()
+    set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP)
+endif()
 
 !!IF !isEmpty(QT_NAMESPACE)
 list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE)
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
index a94caf0d25e569e1a33cb3d424fe2c7389ea52aa..18563764ad4160d84dedbffbeaebcf4ce059a903 100644
--- a/src/corelib/Qt5CoreMacros.cmake
+++ b/src/corelib/Qt5CoreMacros.cmake
@@ -333,8 +333,10 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
             set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
             set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
             set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
-
-            if (Qt5_POSITION_INDEPENDENT_CODE)
+            if (Qt5_POSITION_INDEPENDENT_CODE
+                    AND (CMAKE_VERSION VERSION_LESS 2.8.12
+                        AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
+                        OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)))
                 set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
             endif()
         endforeach()
diff --git a/src/corelib/codecs/qicucodec.cpp b/src/corelib/codecs/qicucodec.cpp
index 65cc337708c989810398e8283609f274d907916e..b375999aebc956df3ddbc93c8acff9c22685d81b 100644
--- a/src/corelib/codecs/qicucodec.cpp
+++ b/src/corelib/codecs/qicucodec.cpp
@@ -121,7 +121,7 @@ struct MibToName {
     short index;
 };
 
-static MibToName mibToName[] = {
+static const MibToName mibToName[] = {
     { 3, 0 },
     { 4, 9 },
     { 5, 20 },
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 050f8f207fae10def8c6120831a23c491267627e..8fef333a77389129843eab1ecb3de8cc248d4676 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -1147,13 +1147,30 @@ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
     return codecForUtfText(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
 }
 
+/*!
+    \fn QTextCodec * QTextCodec::codecForTr ()
+    \obsolete
+
+    Returns the codec used by QObject::tr() on its argument. If this
+    function returns 0 (the default), tr() assumes Latin-1.
+
+    \sa  setCodecForTr()
+*/
+
+/*!
+    \fn QTextCodec::setCodecForTr ( QTextCodec * c )
+    \obsolete
+
+    Sets the codec used by QObject::tr() on its argument to c. If c
+    is 0 (the default), tr() assumes Latin-1.
+*/
 
 /*!
     \internal
     \since 4.3
-    Determines whether the decoder encountered a failure while decoding the input. If
-    an error was encountered, the produced result is undefined, and gets converted as according
-    to the conversion flags.
+    Determines whether the decoder encountered a failure while decoding the
+    input. If an error was encountered, the produced result is undefined, and
+    gets converted as according to the conversion flags.
  */
 bool QTextDecoder::hasFailure() const
 {
diff --git a/src/corelib/codecs/qwindowscodec.cpp b/src/corelib/codecs/qwindowscodec.cpp
index cf427c64b6f73585bc270c6f705dfaa5b494d149..dded93ccb54e1885337213f4bd7082fe8ac51b04 100644
--- a/src/corelib/codecs/qwindowscodec.cpp
+++ b/src/corelib/codecs/qwindowscodec.cpp
@@ -172,7 +172,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le
     }
 #else
     QString s;
-    int size = mbstowcs(NULL, mb, length);
+    size_t size = mbstowcs(NULL, mb, length);
     if (size < 0) {
         Q_ASSERT("Error in CE TextCodec");
         return QString();
@@ -181,7 +181,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le
     ws[size +1] = 0;
     ws[size] = 0;
     size = mbstowcs(ws, mb, length);
-    for (int i=0; i< size; i++)
+    for (size_t i = 0; i < size; i++)
         s.append(QChar(ws[i]));
     delete [] ws;
 #endif
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index df1ee4afeafc26eb302896ee8bd0a0da5a556d69..502689e4c2b2ad9b333ef11e8d5422baa62f3a81 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -43,5 +43,8 @@ imagedirs   += images
 
 excludedirs += snippets
 
+excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc \
+                ../../../examples/widgets/tools/codecs/doc/src/codecs.qdoc
+
 navigation.landingpage = "Qt Core"
 navigation.cppclassespage = "Qt Core C++ Classes"
diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp
index 430c0c92c183ae9d850b2d585f3b00b76b86445b..ab97f609ac1abb95ec18cfee86a677dcfb690063 100644
--- a/src/corelib/doc/snippets/code/doc_src_resources.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp
@@ -48,7 +48,7 @@ MyClass::MyClass() : BaseClass()
 {
     Q_INIT_RESOURCE(resources);
 
-    QFile file("qrc:/myfile.dat");
+    QFile file(":/myfile.dat");
     ...
 }
 //! [5]
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
     QApplication app(argc, argv);
     Q_INIT_RESOURCE(graphlib);
 
-    QFile file("qrc:/graph.png");
+    QFile file(":/graph.png");
     ...
     return app.exec();
 }
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
index 77ec85cc3635c66444a0c061da5a9b70b4c1fe98..e3d76453d0758b99a4651a732e5827ca5b73e35a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp
@@ -51,8 +51,9 @@ sem.release(2);              // resources available == 3
 
 //! [1]
 QSystemSemaphore sem("market", 5, QSystemSemaphore::Create);
-sem.acquire(5);           // acquire all 5 resources
-sem.release(5);           // release the 5 resources
+for (int i = 0; i < 5; ++i)  // acquire all 5 resources
+    sem.acquire();
+sem.release(5);              // release the 5 resources
 //! [1]
 
 
diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc
index 037b09810f7826cb83e88ea367f419b806f8356b..e44a6039599584edcfaae67c9eceb5f6e888e932 100644
--- a/src/corelib/doc/src/statemachine.qdoc
+++ b/src/corelib/doc/src/statemachine.qdoc
@@ -63,7 +63,7 @@
   used to effectively embed the elements and semantics of statecharts in Qt
   applications. The framework integrates tightly with Qt's meta-object system;
   for example, transitions between states can be triggered by signals, and
-  states can be configured to set properties and invoke methods on QObjects.
+  states can be configured to set properties and invoke methods on {QObject}s.
   Qt's event system is used to drive the state machines.
 
   The state graph in the State Machine framework is hierarchical. States can be nested inside of
@@ -126,9 +126,9 @@
 
   The QState::entered() signal is emitted when the state is entered, and the
   QState::exited() signal is emitted when the state is exited. In the
-  following snippet, the button's showMaximized() slot will be called when
-  state \c s3 is entered, and the button's showMinimized() slot will be called
-  when \c s3 is exited:
+  following snippet, the button's \l {QPushButton::}{showMaximized()} slot
+  will be called when state \c s3 is entered, and the button's \l {QPushButton::}{showMinimized()}
+  slot will be called when \c s3 is exited:
 
   \snippet statemachine/main.cpp 5
 
@@ -151,7 +151,7 @@
   Assume we wanted the user to be able to quit the application at any time by
   clicking a Quit button. In order to achieve this, we need to create a final
   state and make it the target of a transition associated with the Quit
-  button's clicked() signal. We could add a transition from each of \c s1, \c
+  button's \l{QPushButton::}{clicked()} signal. We could add a transition from each of \c s1, \c
   s2 and \c s3; however, this seems redundant, and one would also have to
   remember to add such a transition from every new state that is added in the
   future.
@@ -184,8 +184,8 @@
   \snippet statemachine/main2.cpp 1
 
   In this case we want the application to quit when the state machine is
-  finished, so the machine's finished() signal is connected to the
-  application's quit() slot.
+  finished, so the machine's \l {QStateMachine::}{finished()} signal is connected to the
+  application's \l {QCoreApplication::}{quit()} slot.
 
   A child state can override an inherited transition. For example, the
   following code adds a transition that effectively causes the Quit button to
@@ -290,7 +290,7 @@
     \endomit
 
   When \c s1 's final state is entered, \c s1 will automatically emit
-  finished(). We use a signal transition to cause this event to trigger a
+  \l {QState::}{finished()}. We use a signal transition to cause this event to trigger a
   state change:
 
   \snippet statemachine/main3.cpp 1
@@ -302,7 +302,7 @@
   encapsulation mechanism when building complex (deeply nested) state
   machines. (In the above example, you could of course create a transition
   directly from \c s1 's \c done state rather than relying on \c s1 's
-  finished() signal, but with the consequence that implementation details of
+  \l {QState::}{finished()} signal, but with the consequence that implementation details of
   \c s1 are exposed and depended on).
 
   For parallel state groups, the QState::finished() signal is emitted when \e
@@ -365,8 +365,8 @@
 
   \snippet statemachine/main4.cpp 1
 
-  In the eventTest() reimplementation, we first check if the event type is the
-  desired one; if so, we cast the event to a StringEvent and perform the
+  In the \l {QAbstractTransition::}{eventTest()} reimplementation, we first check if the event type is the
+  desired one; if so, we cast the event to a \c StringEvent and perform the
   string comparison.
 
   The following is a statechart that uses the custom event and transition:
@@ -486,7 +486,7 @@
   message box will pop up before the geometry of the button has actually been set.
 
   To ensure that the message box does not pop up until the geometry actually reaches its final
-  value, we can use the state's propertiesAssigned() signal. The propertiesAssigned() signal will be
+  value, we can use the state's \l {QState::}{propertiesAssigned()} signal. The \l {QState::}{propertiesAssigned()} signal will be
   emitted when the property is assigned its final value, whether this is done immediately or
   after the animation has finished playing.
 
@@ -503,14 +503,14 @@
   has been assigned the defined value.
 
   If the global restore policy is set to QStateMachine::RestoreProperties, the state will not emit
-  the propertiesAssigned() signal until these have been executed as well.
+  the \l {QState::}{propertiesAssigned()} signal until these have been executed as well.
 
   \section1 What Happens If A State Is Exited Before The Animation Has Finished
 
   If a state has property assignments, and the transition into the state has animations for the
   properties, the state can potentially be exited before the properties have been assigned to the
   values defines by the state. This is true in particular when there are transitions out from the
-  state that do not depend on the propertiesAssigned signal, as described in the previous section.
+  state that do not depend on the \l {QState::}{propertiesAssigned()} signal, as described in the previous section.
 
   The State Machine API guarantees that a property assigned by the state machine either:
   \list
@@ -563,13 +563,13 @@
 
   The parent state machine treats the child machine as an \e atomic state in the state machine
   algorithm. The child state machine is self-contained; it maintains its own event queue and
-  configuration. In particular, note that the \l{QStateMachine::configuration()}{configuration}
+  configuration. In particular, note that the \l{QStateMachine::}{configuration()}
   of the child machine is not part of the parent machine's configuration (only the child machine
   itself is).
 
   States of the child state machine cannot be specified as targets of transitions in the parent
   state machine; only the child state machine itself can. Conversely, states of the parent state
   machine cannot be specified as targets of transitions in the child state machine. The child
-  state machine's \l{QState::finished()}{finished}() signal can be used to trigger a transition
+  state machine's \l{QState::}{finished}() signal can be used to trigger a transition
   in the parent machine.
 */
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 2176a148b02d6b2d44a14d76534d86c925962045..91e869947236ec98457639ba8e1a8c2d7a2f2182 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2124,9 +2124,9 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion()
 #    define USE_ETC_OS_RELEASE
 struct QUnixOSVersion
 {
-                                    // from /etc/os-release         older /etc/lsb-release
-    QString productType;            // $ID                          $DISTRIB_ID
-    QString productVersion;         // $VERSION_ID                  $DISTRIB_RELEASE
+                                    // from /etc/os-release         older /etc/lsb-release         // redhat /etc/redhat-release         // debian /etc/debian_version
+    QString productType;            // $ID                          $DISTRIB_ID                    // single line file containing:       // Debian
+    QString productVersion;         // $VERSION_ID                  $DISTRIB_RELEASE               // <Vendor_ID release Version_ID>     // single line file <Release_ID/sid>
     QString prettyName;             // $PRETTY_NAME                 $DISTRIB_DESCRIPTION
 };
 
@@ -2138,24 +2138,32 @@ static QString unquote(const char *begin, const char *end)
     }
     return QString::fromLatin1(begin, end - begin);
 }
-
-static bool readEtcFile(QUnixOSVersion &v, const char *filename,
-                        const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
+static QByteArray getEtcFileContent(const char *filename)
 {
     // we're avoiding QFile here
     int fd = qt_safe_open(filename, O_RDONLY);
     if (fd == -1)
-        return false;
+        return QByteArray();
 
     QT_STATBUF sbuf;
     if (QT_FSTAT(fd, &sbuf) == -1) {
         qt_safe_close(fd);
-        return false;
+        return QByteArray();
     }
 
     QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
     buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
     qt_safe_close(fd);
+    return buffer;
+}
+
+static bool readEtcFile(QUnixOSVersion &v, const char *filename,
+                        const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
+{
+
+    QByteArray buffer = getEtcFileContent(filename);
+    if (buffer.isEmpty())
+        return false;
 
     const char *ptr = buffer.constData();
     const char *end = buffer.constEnd();
@@ -2219,14 +2227,72 @@ static bool readEtcLsbRelease(QUnixOSVersion &v)
         }
     }
 
-    return ok;
+    // some distributions have a /etc/lsb-release file that does not provide the values
+    // we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
+    // Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
+    // returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
+    return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
 }
 
+#if defined(Q_OS_LINUX)
+static QByteArray getEtcFileFirstLine(const char *fileName)
+{
+    QByteArray buffer = getEtcFileContent(fileName);
+    if (buffer.isEmpty())
+        return QByteArray();
+
+    const char *ptr = buffer.constData();
+    int eol = buffer.indexOf("\n");
+    return QByteArray(ptr, eol).trimmed();
+}
+
+static bool readEtcRedHatRelease(QUnixOSVersion &v)
+{
+    // /etc/redhat-release analysed should be a one line file
+    // the format of its content is <Vendor_ID release Version>
+    // i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
+    QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
+    if (line.isEmpty())
+        return false;
+
+    v.prettyName = QString::fromLatin1(line);
+
+    const char keyword[] = "release ";
+    int releaseIndex = line.indexOf(keyword);
+    v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(QLatin1Char(' '));
+    int spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
+    v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword), spaceIndex > -1 ? spaceIndex - releaseIndex - strlen(keyword) : -1));
+    return true;
+}
+
+static bool readEtcDebianVersion(QUnixOSVersion &v)
+{
+    // /etc/debian_version analysed should be a one line file
+    // the format of its content is <Release_ID/sid>
+    // i.e. "jessie/sid"
+    QByteArray line = getEtcFileFirstLine("/etc/debian_version");
+    if (line.isEmpty())
+        return false;
+
+    v.productType = QStringLiteral("Debian");
+    v.productVersion = QString::fromLatin1(line);
+    return true;
+}
+#endif
+
 static bool findUnixOsVersion(QUnixOSVersion &v)
 {
     if (readEtcOsRelease(v))
         return true;
-    return readEtcLsbRelease(v);
+    if (readEtcLsbRelease(v))
+        return true;
+#if defined(Q_OS_LINUX)
+    if (readEtcRedHatRelease(v))
+        return true;
+    if (readEtcDebianVersion(v))
+        return true;
+#endif
+    return false;
 }
 #  endif // USE_ETC_OS_RELEASE
 #endif // Q_OS_UNIX
@@ -2955,7 +3021,7 @@ namespace {
     // depending on the return type
     static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf)
     {
-        return QString::fromLocal8Bit(buf);
+        return QString::fromLocal8Bit(buf.constData());
     }
     static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &)
     {
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index c4e2f7609ca6a4e352df37851cce5ad2039a70b5..4eeee0fef4ff42db464ccd96fc3b83295989e5ed 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -321,6 +321,15 @@ typedef double qreal;
 #  define Q_NETWORK_EXPORT
 #endif
 
+/*
+   Some classes do not permit copies to be made of an object. These
+   classes contains a private copy constructor and assignment
+   operator to disable copying (the compiler gives an error message).
+*/
+#define Q_DISABLE_COPY(Class) \
+    Class(const Class &) Q_DECL_EQ_DELETE;\
+    Class &operator=(const Class &) Q_DECL_EQ_DELETE;
+
 /*
    No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
    for Qt's internal unit tests. If you want slower loading times and more
@@ -543,7 +552,21 @@ template <typename T>
 Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max)
 { return qMax(min, qMin(max, val)); }
 
-#ifdef Q_OS_DARWIN
+#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
+#  ifdef __OBJC__
+#    define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
+#  else
+#    define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
+#  endif
+#endif
+#ifndef Q_FORWARD_DECLARE_CF_TYPE
+#  define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
+#endif
+#ifndef Q_FORWARD_DECLARE_MUTABLE_CF_TYPE
+#  define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
+#endif
+
+#ifdef Q_OS_MAC
 #  define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) \
     ((defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && osx != __MAC_NA && __MAC_OS_X_VERSION_MAX_ALLOWED >= osx) || \
      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios))
@@ -561,7 +584,21 @@ Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max
       QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_NA, ios)
 #  define QT_OSX_DEPLOYMENT_TARGET_BELOW(osx) \
       QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, __IPHONE_NA)
-#endif
+
+Q_FORWARD_DECLARE_OBJC_CLASS(NSAutoreleasePool);
+
+// Implemented in qcore_mac_objc.mm
+class Q_CORE_EXPORT QMacAutoReleasePool
+{
+public:
+    QMacAutoReleasePool();
+    ~QMacAutoReleasePool();
+private:
+    Q_DISABLE_COPY(QMacAutoReleasePool);
+    NSAutoreleasePool *pool;
+};
+
+#endif // Q_OS_MAC
 
 /*
    Data stream functions are provided by many classes (defined in qdatastream.h)
@@ -1033,15 +1070,6 @@ Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1);
   { return T::dynamic_cast_will_always_fail_because_rtti_is_disabled; }
 #endif
 
-/*
-   Some classes do not permit copies to be made of an object. These
-   classes contains a private copy constructor and assignment
-   operator to disable copying (the compiler gives an error message).
-*/
-#define Q_DISABLE_COPY(Class) \
-    Class(const Class &) Q_DECL_EQ_DELETE;\
-    Class &operator=(const Class &) Q_DECL_EQ_DELETE;
-
 class QByteArray;
 Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
 Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
@@ -1062,9 +1090,10 @@ Q_CORE_EXPORT int qrand();
 
 #define QT_MODULE(x)
 
-#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
+#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && \
+    (!defined(__PIC__) || (defined(__PIE__) && defined(Q_CC_GNU) && Q_CC_GNU >= 500))
 #  error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
-         "Compile your code with -fPIC or -fPIE."
+         "Compile your code with -fPIC (-fPIE is not enough)."
 #endif
 
 namespace QtPrivate {
@@ -1076,20 +1105,6 @@ template <bool B, typename T, typename F> struct QConditional { typedef T Type;
 template <typename T, typename F> struct QConditional<false, T, F> { typedef F Type; };
 }
 
-#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
-#  ifdef __OBJC__
-#    define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname
-#  else
-#    define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname
-#  endif
-#endif
-#ifndef Q_FORWARD_DECLARE_CF_TYPE
-#  define Q_FORWARD_DECLARE_CF_TYPE(type) typedef const struct __ ## type * type ## Ref
-#endif
-#ifndef Q_FORWARD_DECLARE_MUTABLE_CF_TYPE
-#  define Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) typedef struct __ ## type * type ## Ref
-#endif
-
 QT_END_NAMESPACE
 
 // We need to keep QTypeInfo, QSysInfo, QFlags, qDebug & family in qglobal.h for compatibility with Qt 4.
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index d9d21c535c50a1b5d2df9076c882b84e89bb6980..88882bbe8f6c3e09376550927603ab37cc5c515c 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -972,8 +972,8 @@ struct QMessagePattern {
     QElapsedTimer timer;
 #endif
 #ifdef QLOGGING_HAVE_BACKTRACE
-    int backtraceDepth;
     QString backtraceSeparator;
+    int backtraceDepth;
 #endif
 
     bool fromEnvironment;
@@ -986,8 +986,8 @@ QMessagePattern::QMessagePattern()
     : literals(0)
     , tokens(0)
 #ifdef QLOGGING_HAVE_BACKTRACE
-    , backtraceDepth(5)
     , backtraceSeparator(QLatin1Char('|'))
+    , backtraceDepth(5)
 #endif
     , fromEnvironment(false)
 {
@@ -1737,7 +1737,7 @@ void qErrnoWarning(int code, const char *msg, ...)
 
     Example:
     \code
-    QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D{%endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
+    QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
     \endcode
 
     The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 123e2edf0ecf84a42aa5c7c3655fbf95851acdbf..fc5207fa257dd7824e0ae12e240b3e242d1610f3 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -294,10 +294,13 @@ public:
         WindowCloseButtonHint = 0x08000000,
         MacWindowToolBarButtonHint = 0x10000000,
         BypassGraphicsProxyWidget = 0x20000000,
-        WindowOkButtonHint = 0x00080000,
-        WindowCancelButtonHint = 0x00100000,
         NoDropShadowWindowHint = 0x40000000,
-        WindowFullscreenButtonHint = 0x80000000
+        WindowFullscreenButtonHint = 0x80000000,
+
+        // The following enums have overlapping values with other enums.
+        // This was not intentional, but it's too late to change now.
+        WindowOkButtonHint = 0x00080000, // WindowTransparentForInput
+        WindowCancelButtonHint = 0x00100000 // WindowOverridesSystemGestures
     };
 
     Q_DECLARE_FLAGS(WindowFlags, WindowType)
@@ -1323,7 +1326,7 @@ public:
         ImAbsolutePosition = 0x400,
         ImTextBeforeCursor = 0x800,
         ImTextAfterCursor = 0x1000,
-        ImReturnKeyType = 0x2000,
+        ImEnterKeyType = 0x2000,
 
         ImPlatformData = 0x80000000,
         ImQueryInput = ImCursorRectangle | ImCursorPosition | ImSurroundingText |
@@ -1363,15 +1366,15 @@ public:
     };
     Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint)
 
-    enum ReturnKeyType {
-        ReturnKeyDefault,
-        ReturnKeyEnter,
-        ReturnKeyDone,
-        ReturnKeyGo,
-        ReturnKeySend,
-        ReturnKeySearch,
-        ReturnKeyNext,
-        ReturnKeyPrevious
+    enum EnterKeyType {
+        EnterKeyDefault,
+        EnterKeyReturn,
+        EnterKeyDone,
+        EnterKeyGo,
+        EnterKeySend,
+        EnterKeySearch,
+        EnterKeyNext,
+        EnterKeyPrevious
     };
 
     enum ToolButtonStyle {
@@ -1697,7 +1700,7 @@ public:
     QT_Q_ENUM(InputMethodHint)
     QT_Q_ENUM(InputMethodQuery)
     QT_Q_FLAG(InputMethodHints)
-    QT_Q_ENUM(ReturnKeyType)
+    QT_Q_ENUM(EnterKeyType)
     QT_Q_FLAG(InputMethodQueries)
     QT_Q_FLAG(TouchPointStates)
     QT_Q_ENUM(ScreenOrientation)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index d4d7b631adf15ad6650e71497f9948dea73937c4..970e1b1f426dfceed64a6a94df8b1a24122d159b 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -2527,7 +2527,7 @@
                                 but \b{must} not return an empty string unless the cursor is at the start of the document.
     \value ImTextAfterCursor    The plain text after the cursor. The widget can decide how much text to return,
                                 but \b{must} not return an empty string unless the cursor is at the end of the document.
-    \value ImReturnKeyType      The return key type.
+    \value ImEnterKeyType       The Enter key type.
 
     Masks:
 
@@ -2538,31 +2538,32 @@
 */
 
 /*!
-    \enum Qt::ReturnKeyType
+    \enum Qt::EnterKeyType
 
     This can be used to alter the appearance of the Return key on an on screen keyboard.
 
-    Note that not all of these values are supported on all platforms.
-
-    \value ReturnKeyDefault     The default return key.
-                                This can either be a button closing the keyboard, or a Return button
-                                causing a new line in case of a multi-line input field.
-    \value ReturnKeyEnter       Show a Return button that inserts a new line.
-                                The keyboard will not close when this button is pressed.
-    \value ReturnKeyDone        Show a "Done" button.
-                                The keyboard will close when this button is pressed.
-    \value ReturnKeyGo          Show a "Go" button.
-                                Typically used in an address bar when entering an URL; the keyboard
-                                will close when this button is pressed.
-    \value ReturnKeySend        Show a "Send" button.
-                                The keyboard will close when this button is pressed.
-    \value ReturnKeySearch      Show a "Search" button.
-                                The keyboard will close when this button is pressed.
-    \value ReturnKeyNext        Show a "Next" button.
-                                Typically used in a form to allow navigating to the next input field;
-                                the keyboard will not close when this button is pressed.
-    \value ReturnKeyPrevious    Show a "Previous" button.
-                                The keyboard will not close when this button is pressed.
+    \note Not all of these values are supported on all platforms.
+    For unsuppoted values the default key will be used instead.
+
+    \value EnterKeyDefault     The default Enter key.
+                               This can either be a button closing the keyboard, or a Return button
+                               causing a new line in case of a multi-line input field.
+    \value EnterKeyReturn      Show a Return button that inserts a new line.
+                               The keyboard will not close when this button is pressed.
+    \value EnterKeyDone        Show a "Done" button.
+                               The keyboard will close when this button is pressed.
+    \value EnterKeyGo          Show a "Go" button.
+                               Typically used in an address bar when entering a URL; the keyboard
+                               will close when this button is pressed.
+    \value EnterKeySend        Show a "Send" button.
+                               The keyboard will close when this button is pressed.
+    \value EnterKeySearch      Show a "Search" button.
+                               The keyboard will close when this button is pressed.
+    \value EnterKeyNext        Show a "Next" button.
+                               Typically used in a form to allow navigating to the next input field;
+                               the keyboard will not close when this button is pressed.
+    \value EnterKeyPrevious    Show a "Previous" button.
+                               The keyboard will not close when this button is pressed.
 
     \since 5.6
 */
@@ -2955,15 +2956,19 @@
     \enum Qt::NativeGestureType
     \since 5.2
 
-    \value BeginNativeGesture
-    \value EndNativeGesture
-    \value PanNativeGesture
-    \value ZoomNativeGesture
-    \value SmartZoomNativeGesture
-    \value RotateNativeGesture
-    \value SwipeNativeGesture
+    This enum returns the gesture type.
+
+    \value BeginNativeGesture Sent before gesture event stream.
+    \value EndNativeGesture   Sent after gesture event stream.
+    \value PanNativeGesture   Sent after a panning gesture.
+                              Similar to a click-and-drag mouse movement.
+    \value ZoomNativeGesture  Specifies the magnification delta in percent.
+    \value SmartZoomNativeGesture Boolean magnification state.
+    \value RotateNativeGesture    Rotation delta in degrees.
+    \value SwipeNativeGesture     Sent after a swipe movements.
 
 */
+
 /*!
     \enum Qt::NavigationMode
     \since 4.6
diff --git a/src/corelib/global/qtypetraits.h b/src/corelib/global/qtypetraits.h
index 3a305713e6fbbbdf6b2d5286bbc4afbbe5522986..488e257e0f194c95f54339b5300d276940a14886 100644
--- a/src/corelib/global/qtypetraits.h
+++ b/src/corelib/global/qtypetraits.h
@@ -506,6 +506,27 @@ Q_STATIC_ASSERT((!is_unsigned<qint64>::value));
 Q_STATIC_ASSERT((!is_signed<quint64>::value));
 Q_STATIC_ASSERT(( is_signed<qint64>::value));
 
+template<class T = void> struct is_default_constructible;
+
+template<> struct is_default_constructible<void>
+{
+protected:
+    template<bool> struct test { typedef char type; };
+public:
+    static bool const value = false;
+};
+template<> struct is_default_constructible<>::test<true> { typedef double type; };
+
+template<class T> struct is_default_constructible : is_default_constructible<>
+{
+private:
+    template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
+    template<class U> static char sfinae(...);
+public:
+    static bool const value = sizeof(sfinae<T>(0)) > 1;
+};
+
+
 } // namespace QtPrivate
 
 QT_END_NAMESPACE
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 4c189bfe5795cf6e341010d77909e77fa4f02433..207de2a85b4d499a98fb38c2a97ec56a55afb6da 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -187,7 +187,7 @@ win32 {
         }
 
         !nacl {
-            freebsd-*|mac|darwin-*|openbsd-*:{
+            freebsd-*|mac|darwin-*|openbsd-*|netbsd-*:{
                 SOURCES += io/qfilesystemwatcher_kqueue.cpp
                 HEADERS += io/qfilesystemwatcher_kqueue_p.h
             }
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 9b1ec3917af609f760138c66f16937bc1ec933e5..8b3dd5d82f0ef091b9eee505b32da08028fc0c6c 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1826,6 +1826,8 @@ QFileInfoList QDir::drives()
     underlying operating system. If you want to display paths to the
     user using their operating system's separator use
     toNativeSeparators().
+
+    \sa listSeparator()
 */
 QChar QDir::separator()
 {
@@ -1836,6 +1838,16 @@ QChar QDir::separator()
 #endif
 }
 
+/*!
+    \fn QDir::listSeparator()
+    \since 5.6
+
+    Returns the native path list separator: ':' under Unix
+    and ';' under Windows.
+
+    \sa separator()
+*/
+
 /*!
     Sets the application's current working directory to \a path.
     Returns \c true if the directory was successfully changed; otherwise
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index e622011f98b298da8649518ec2bfdad445f83e44..b6946eba653a488ef45afb7015e34c8ed4744c50 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -177,7 +177,16 @@ public:
 
     static QFileInfoList drives();
 
-    static QChar separator();
+    Q_DECL_CONSTEXPR static inline QChar listSeparator() Q_DECL_NOTHROW
+    {
+#if defined(Q_OS_WIN)
+        return QLatin1Char(';');
+#else
+        return QLatin1Char(':');
+#endif
+    }
+
+    static QChar separator(); // ### Qt6: Make it inline
 
     static bool setCurrent(const QString &path);
     static inline QDir current() { return QDir(currentPath()); }
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 4ca07ba41db6e7c872c0a4d90752995ada6212e4..cddd70f908576e76731b290fa8a4147729e2f849 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -225,9 +225,13 @@ QString QFileSelector::select(const QString &filePath) const
     return d->select(filePath);
 }
 
-static QString qrcScheme()
+static bool isLocalScheme(const QString &file)
 {
-    return QStringLiteral("qrc");
+    bool local = file == QStringLiteral("qrc");
+#ifdef Q_OS_ANDROID
+    local |= file == QStringLiteral("assets");
+#endif
+    return local;
 }
 
 /*!
@@ -240,10 +244,10 @@ static QString qrcScheme()
 QUrl QFileSelector::select(const QUrl &filePath) const
 {
     Q_D(const QFileSelector);
-    if (filePath.scheme() != qrcScheme() && !filePath.isLocalFile())
+    if (!isLocalScheme(filePath.scheme()) && !filePath.isLocalFile())
         return filePath;
     QUrl ret(filePath);
-    if (filePath.scheme() == qrcScheme()) {
+    if (isLocalScheme(filePath.scheme())) {
         QString equivalentPath = QLatin1Char(':') + filePath.path();
         QString selectedPath = d->select(equivalentPath);
         ret.setPath(selectedPath.remove(0, 1));
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index faaf7a00afe99a1bc5945b394e15f334a1874506..79f16a083942fa7dc441b0dad86709da408fad8c 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -255,15 +255,15 @@ QString QFileSystemEntry::completeSuffix() const
 bool QFileSystemEntry::isRelative() const
 {
     resolveFilePath();
-    return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
-        && (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
+    return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() != '/')
+        && (!(m_filePath.length() >= 2 && m_filePath.at(1).unicode() == ':'))));
 }
 
 bool QFileSystemEntry::isAbsolute() const
 {
     resolveFilePath();
     return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
-                                       && (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
+                                       && (m_filePath.at(0).isLetter() && m_filePath.at(1).unicode() == ':' && m_filePath.at(2).unicode() == '/'))
                                       || (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
                                       ));
 }
@@ -276,7 +276,7 @@ bool QFileSystemEntry::isRelative() const
 bool QFileSystemEntry::isAbsolute() const
 {
     resolveFilePath();
-    return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
+    return (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() == '/'));
 }
 #endif
 
@@ -337,10 +337,10 @@ void QFileSystemEntry::findFileNameSeparators() const
 
         int i = m_filePath.size() - 1;
         for (; i >= stop; --i) {
-            if (m_filePath[i].unicode() == '.') {
+            if (m_filePath.at(i).unicode() == '.') {
                 firstDotInFileName = lastDotInFileName = i;
                 break;
-            } else if (m_filePath[i].unicode() == '/') {
+            } else if (m_filePath.at(i).unicode() == '/') {
                 lastSeparator = i;
                 break;
             }
@@ -348,9 +348,9 @@ void QFileSystemEntry::findFileNameSeparators() const
 
         if (lastSeparator != i) {
             for (--i; i >= stop; --i) {
-                if (m_filePath[i].unicode() == '.')
+                if (m_filePath.at(i).unicode() == '.')
                     firstDotInFileName = i;
-                else if (m_filePath[i].unicode() == '/') {
+                else if (m_filePath.at(i).unicode() == '/') {
                     lastSeparator = i;
                     break;
                 }
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 0bd46400d371cf248039cbf1b9f7ceec4b3fbd8c..3a8f7bd0a9ce5fb11df0c202b2229d6f6501387c 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -52,7 +52,7 @@
 #  include "qfilesystemwatcher_win_p.h"
 #elif defined(USE_INOTIFY)
 #  include "qfilesystemwatcher_inotify_p.h"
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_IOS)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
 #  include "qfilesystemwatcher_kqueue_p.h"
 #elif defined(Q_OS_OSX)
 #  include "qfilesystemwatcher_fsevents_p.h"
@@ -68,7 +68,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject
     // there is a chance that inotify may fail on Linux pre-2.6.13 (August
     // 2005), so we can't just new inotify directly.
     return QInotifyFileSystemWatcherEngine::create(parent);
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_IOS)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
     return QKqueueFileSystemWatcherEngine::create(parent);
 #elif defined(Q_OS_OSX)
     return QFseventsFileSystemWatcherEngine::create(parent);
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index 8a028c91e1403793b45e48a5053e80cf9f6f9531..7656530a46fdcb86072d12de94d877d6b0b81381 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -56,25 +56,6 @@
 
 QT_BEGIN_NAMESPACE
 
-namespace {
-class RaiiAutoreleasePool
-{
-    Q_DISABLE_COPY(RaiiAutoreleasePool)
-
-public:
-    RaiiAutoreleasePool()
-        : pool([[NSAutoreleasePool alloc] init])
-    {}
-
-    ~RaiiAutoreleasePool()
-    { [pool release]; }
-
-private:
-    NSAutoreleasePool *pool;
-};
-#define Q_AUTORELEASE_POOL(pool) RaiiAutoreleasePool pool; Q_UNUSED(pool);
-}
-
 static void callBackFunction(ConstFSEventStreamRef streamRef,
                              void *clientCallBackInfo,
                              size_t numEvents,
@@ -82,7 +63,7 @@ static void callBackFunction(ConstFSEventStreamRef streamRef,
                              const FSEventStreamEventFlags eventFlags[],
                              const FSEventStreamEventId eventIds[])
 {
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
 
     char **paths = static_cast<char **>(eventPaths);
     QFseventsFileSystemWatcherEngine *engine = static_cast<QFseventsFileSystemWatcherEngine *>(clientCallBackInfo);
@@ -297,7 +278,7 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString &pat
 
 void QFseventsFileSystemWatcherEngine::restartStream()
 {
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
     QMutexLocker locker(&lock);
     stopStream();
     startStream();
@@ -328,7 +309,7 @@ QFseventsFileSystemWatcherEngine::QFseventsFileSystemWatcherEngine(QObject *pare
 
 QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
 {
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
 
     if (stream)
         FSEventStreamStop(stream);
@@ -344,7 +325,7 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
                                                        QStringList *files,
                                                        QStringList *directories)
 {
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
 
     if (stream) {
         DEBUG("Flushing, last id is %llu", FSEventStreamGetLatestEventId(stream));
@@ -432,7 +413,7 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
                                                           QStringList *files,
                                                           QStringList *directories)
 {
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
 
     QMutexLocker locker(&lock);
 
@@ -489,7 +470,7 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
 bool QFseventsFileSystemWatcherEngine::startStream()
 {
     Q_ASSERT(stream == 0);
-    Q_AUTORELEASE_POOL(pool)
+    QMacAutoReleasePool pool;
     if (stream) // This shouldn't happen, but let's be nice and handle it.
         stopStream();
 
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index e73a200fb4ce825f410019ff00516df626d7d6bf..07a2ff8f6b398a862affeeab2f70318fbc49e2c7 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -38,9 +38,9 @@
 #include "qiodevice_p.h"
 #include "qfile.h"
 #include "qstringlist.h"
+#include "qdir.h"
 
 #include <algorithm>
-#include <limits.h>
 
 #ifdef QIODEVICE_DEBUG
 #  include <ctype.h>
@@ -80,10 +80,29 @@ void debugBinaryString(const char *data, qint64 maxlen)
 
 #define Q_VOID
 
+static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
+{
+    QDebug d = qWarning();
+    d.noquote();
+    d.nospace();
+    d << "QIODevice::" << function;
+#ifndef QT_NO_QOBJECT
+    d << " (" << device->metaObject()->className();
+    if (!device->objectName().isEmpty())
+        d << ", \"" << device->objectName() << '"';
+    if (const QFile *f = qobject_cast<const QFile *>(device))
+        d << ", \"" << QDir::toNativeSeparators(f->fileName()) << '"';
+    d << ')';
+#else
+    Q_UNUSED(device)
+#endif // !QT_NO_QOBJECT
+    d << ": " << what;
+}
+
 #define CHECK_MAXLEN(function, returnType) \
     do { \
         if (maxSize < 0) { \
-            qWarning("QIODevice::"#function": Called with maxSize < 0"); \
+            checkWarnMessage(this, #function, "Called with maxSize < 0"); \
             return returnType; \
         } \
     } while (0)
@@ -92,10 +111,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
    do { \
        if ((d->openMode & WriteOnly) == 0) { \
            if (d->openMode == NotOpen) { \
-               qWarning("QIODevice::"#function": device not open"); \
+               checkWarnMessage(this, #function, "device not open"); \
                return returnType; \
            } \
-           qWarning("QIODevice::"#function": ReadOnly device"); \
+           checkWarnMessage(this, #function, "ReadOnly device"); \
            return returnType; \
        } \
    } while (0)
@@ -104,10 +123,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
    do { \
        if ((d->openMode & ReadOnly) == 0) { \
            if (d->openMode == NotOpen) { \
-               qWarning("QIODevice::"#function": device not open"); \
+               checkWarnMessage(this, #function, "device not open"); \
                return returnType; \
            } \
-           qWarning("QIODevice::"#function": WriteOnly device"); \
+           checkWarnMessage(this, #function, "WriteOnly device"); \
            return returnType; \
        } \
    } while (0)
@@ -462,7 +481,7 @@ void QIODevice::setTextModeEnabled(bool enabled)
 {
     Q_D(QIODevice);
     if (!isOpen()) {
-        qWarning("QIODevice::setTextModeEnabled: The device is not open");
+        checkWarnMessage(this, "setTextModeEnabled", "The device is not open");
         return;
     }
     if (enabled)
@@ -621,11 +640,11 @@ bool QIODevice::seek(qint64 pos)
 {
     Q_D(QIODevice);
     if (d->isSequential()) {
-        qWarning("QIODevice::seek: Cannot call seek on a sequential device");
+        checkWarnMessage(this, "seek", "Cannot call seek on a sequential device");
         return false;
     }
     if (d->openMode == NotOpen) {
-        qWarning("QIODevice::seek: The device is not open");
+        checkWarnMessage(this, "seek", "The device is not open");
         return false;
     }
     if (pos < 0) {
@@ -922,9 +941,9 @@ QByteArray QIODevice::read(qint64 maxSize)
     Q_UNUSED(d);
 #endif
 
-    if (maxSize != qint64(int(maxSize))) {
-        qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
-        maxSize = INT_MAX;
+    if (quint64(maxSize) >= QByteArray::MaxSize) {
+        checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit");
+        maxSize = QByteArray::MaxSize - 1;
     }
 
     qint64 readBytes = 0;
@@ -976,7 +995,7 @@ QByteArray QIODevice::readAll()
 
     // flush internal read buffer
     if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
-        if (d->buffer.size() >= INT_MAX)
+        if (quint64(d->buffer.size()) >= QByteArray::MaxSize)
             return QByteArray();
         result = d->buffer.readAll();
         readBytes = result.size();
@@ -989,7 +1008,7 @@ QByteArray QIODevice::readAll()
         // Size is unknown, read incrementally.
         qint64 readResult;
         do {
-            if (quint64(readBytes) + QIODEVICE_BUFFERSIZE > QByteArray::MaxSize) {
+            if (quint64(readBytes) + QIODEVICE_BUFFERSIZE >= QByteArray::MaxSize) {
                 // If resize would fail, don't read more, return what we have.
                 break;
             }
@@ -1001,7 +1020,7 @@ QByteArray QIODevice::readAll()
     } else {
         // Read it all in one go.
         // If resize fails, don't read anything.
-        if (quint64(readBytes + theSize - d->pos) > QByteArray::MaxSize)
+        if (quint64(readBytes + theSize - d->pos) >= QByteArray::MaxSize)
             return QByteArray();
         result.resize(int(readBytes + theSize - d->pos));
         readBytes += read(result.data() + readBytes, result.size() - readBytes);
@@ -1055,7 +1074,7 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
 {
     Q_D(QIODevice);
     if (maxSize < 2) {
-        qWarning("QIODevice::readLine: Called with maxSize < 2");
+        checkWarnMessage(this, "readLine", "Called with maxSize < 2");
         return qint64(-1);
     }
 
@@ -1159,9 +1178,9 @@ QByteArray QIODevice::readLine(qint64 maxSize)
     Q_UNUSED(d);
 #endif
 
-    if (maxSize > INT_MAX) {
+    if (quint64(maxSize) >= QByteArray::MaxSize) {
         qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
-        maxSize = INT_MAX;
+        maxSize = QByteArray::MaxSize - 1;
     }
 
     result.resize(int(maxSize));
@@ -1169,7 +1188,7 @@ QByteArray QIODevice::readLine(qint64 maxSize)
     if (!result.size()) {
         // If resize fails or maxSize == 0, read incrementally
         if (maxSize == 0)
-            maxSize = INT_MAX;
+            maxSize = QByteArray::MaxSize - 1;
 
         // The first iteration needs to leave an extra byte for the terminating null
         result.resize(1);
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index 4f5aeff39534e8fd8984ac7ef92b79270b4557f0..2bd996d2139984c8c36a74dd500dc2b2a6b3d40e 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
@@ -66,9 +67,12 @@ QT_BEGIN_NAMESPACE
 
     If the process holding the lock crashes, the lock file stays on disk and can prevent
     any other process from accessing the shared resource, ever. For this reason, QLockFile
-    tries to detect such a "stale" lock file, based on the process ID written into the file,
-    and (in case that process ID got reused meanwhile), on the last modification time of
-    the lock file (30s by default, for the use case of a short-lived operation).
+    tries to detect such a "stale" lock file, based on the process ID written into the file.
+    To cover the situation that the process ID got reused meanwhile, the current process name is
+    compared to the name of the process that corresponds to the process ID from the lock file.
+    If the process names differ, the lock file is considered stale.
+    Additionally, the last modification time of the lock file (30s by default, for the use case of a
+    short-lived operation) is taken into account.
     If the lock file is found to be stale, it will be deleted.
 
     For the use case of protecting a resource over a long time, you should therefore call
@@ -122,7 +126,7 @@ QLockFile::~QLockFile()
     The value of \a staleLockTime is used by lock() and tryLock() in order
     to determine when an existing lock file is considered stale, i.e. left over
     by a crashed process. This is useful for the case where the PID got reused
-    meanwhile, so the only way to detect a stale lock file is by the fact that
+    meanwhile, so one way to detect a stale lock file is by the fact that
     it has been around for a long time.
 
     \sa staleLockTime()
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 0cfaa42849fa42fc8b4e59299504a19cba73d62e..168062f4674f8a68d3b2b56c6e36972849c1cd9b 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -75,6 +75,7 @@ public:
     // Returns \c true if the lock belongs to dead PID, or is old.
     // The attempt to delete it will tell us if it was really stale or not, though.
     bool isApparentlyStale() const;
+    static QString processNameByPid(qint64 pid);
 
 #ifdef Q_OS_UNIX
     static int checkFcntlWorksAfterFlock();
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index b817a24c74452af72b5ffcdff40e4016b10ad234..d6ea2f1f2db605696c1e89031fc7acab63ef1c69 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,6 +49,15 @@
 #include <signal.h>    // kill
 #include <unistd.h>    // gethostname
 
+#if defined(Q_OS_OSX)
+#   include <libproc.h>
+#elif defined(Q_OS_LINUX)
+#   include <unistd.h>
+#   include <cstdio>
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+#   include <sys/user.h>
+#endif
+
 QT_BEGIN_NAMESPACE
 
 static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
@@ -185,16 +195,54 @@ bool QLockFilePrivate::isApparentlyStale() const
 {
     qint64 pid;
     QString hostname, appname;
-    if (!getLockInfo(&pid, &hostname, &appname))
-        return false;
-    if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
-        if (::kill(pid, 0) == -1 && errno == ESRCH)
-            return true; // PID doesn't exist anymore
+    if (getLockInfo(&pid, &hostname, &appname)) {
+        if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+            if (::kill(pid, 0) == -1 && errno == ESRCH)
+                return true; // PID doesn't exist anymore
+            const QString processName = processNameByPid(pid);
+            if (!processName.isEmpty()) {
+                QFileInfo fi(appname);
+                if (fi.isSymLink())
+                    fi.setFile(fi.symLinkTarget());
+                if (processName != fi.fileName())
+                    return true; // PID got reused by a different application.
+            }
+        }
     }
     const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
     return staleLockTime > 0 && age > staleLockTime;
 }
 
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if defined(Q_OS_OSX)
+    char name[1024];
+    proc_name(pid, name, sizeof(name) / sizeof(char));
+    return QString::fromUtf8(name);
+#elif defined(Q_OS_LINUX)
+    if (!QFile::exists(QStringLiteral("/proc/version")))
+        return QString();
+    char exePath[64];
+    char buf[PATH_MAX];
+    memset(buf, 0, sizeof(buf));
+    sprintf(exePath, "/proc/%lld/exe", pid);
+    if (readlink(exePath, buf, sizeof(buf)) < 0) {
+        // The pid is gone. Return some invalid process name to fail the test.
+        return QStringLiteral("/ERROR/");
+    }
+    return QFileInfo(QString::fromUtf8(buf)).fileName();
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+    kinfo_proc *proc = kinfo_getproc(pid);
+    if (!proc)
+        return QString();
+    QString name = QString::fromUtf8(proc->ki_comm);
+    free(proc);
+    return name;
+#else
+    return QString();
+#endif
+}
+
 void QLockFile::unlock()
 {
     Q_D(QLockFile);
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 9fe86e1ad8dbc098cf65abafd0037ae987dfd212..5bd1ba04c911179229636b8938db26fa8ad0d978 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
@@ -126,27 +127,75 @@ bool QLockFilePrivate::isApparentlyStale() const
 {
     qint64 pid;
     QString hostname, appname;
-    if (!getLockInfo(&pid, &hostname, &appname))
-        return false;
 
     // On WinRT there seems to be no way of obtaining information about other
     // processes due to sandboxing
 #ifndef Q_OS_WINRT
-    if (hostname == QString::fromLocal8Bit(localHostName())) {
-        HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
-        if (!procHandle)
-            return true;
-        // We got a handle but check if process is still alive
-        DWORD dwR = ::WaitForSingleObject(procHandle, 0);
-        ::CloseHandle(procHandle);
-        if (dwR == WAIT_TIMEOUT)
-            return true;
+    if (getLockInfo(&pid, &hostname, &appname)) {
+        if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+            HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+            if (!procHandle)
+                return true;
+            // We got a handle but check if process is still alive
+            DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+            ::CloseHandle(procHandle);
+            if (dwR == WAIT_TIMEOUT)
+                return true;
+            const QString processName = processNameByPid(pid);
+            if (!processName.isEmpty() && processName != appname)
+                return true; // PID got reused by a different application.
+        }
     }
-#endif // !Q_OS_WINRT
+#else // !Q_OS_WINRT
+    Q_UNUSED(pid);
+    Q_UNUSED(hostname);
+    Q_UNUSED(appname);
+#endif // Q_OS_WINRT
     const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
     return staleLockTime > 0 && age > staleLockTime;
 }
 
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+    typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
+
+    HMODULE hPsapi = LoadLibraryA("psapi");
+    if (!hPsapi)
+        return QString();
+
+    GetModuleFileNameExFunc qGetModuleFileNameEx
+            = (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW");
+    if (!qGetModuleFileNameEx) {
+        FreeLibrary(hPsapi);
+        return QString();
+    }
+
+    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
+    if (!hProcess) {
+        FreeLibrary(hPsapi);
+        return QString();
+    }
+    wchar_t buf[MAX_PATH];
+    const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
+    CloseHandle(hProcess);
+    FreeLibrary(hPsapi);
+    if (!length)
+        return QString();
+    QString name = QString::fromWCharArray(buf, length);
+    int i = name.lastIndexOf(QLatin1Char('\\'));
+    if (i >= 0)
+        name.remove(0, i + 1);
+    i = name.lastIndexOf(QLatin1Char('.'));
+    if (i >= 0)
+        name.truncate(i);
+    return name;
+#else
+    Q_UNUSED(pid);
+    return QString();
+#endif
+}
+
 void QLockFile::unlock()
 {
     Q_D(QLockFile);
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index c17b42ef8120849ffaa809c8f8f98f293f994246..af1bb56fe99245c1a13bbae9a485f4d08293ccd4 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -216,6 +216,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size()
     return byteArray->size();
 }
 
+qint64 QNonContiguousByteDeviceByteArrayImpl::pos()
+{
+    return currentPosition;
+}
+
 QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
     : QNonContiguousByteDevice(), currentPosition(0)
 {
@@ -253,6 +258,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
     return currentPosition >= size();
 }
 
+qint64 QNonContiguousByteDeviceRingBufferImpl::pos()
+{
+    return currentPosition;
+}
+
 bool QNonContiguousByteDeviceRingBufferImpl::reset()
 {
     currentPosition = 0;
@@ -381,6 +391,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
     return device->size() - initialPosition;
 }
 
+qint64 QNonContiguousByteDeviceIoDeviceImpl::pos()
+{
+    if (device->isSequential())
+        return -1;
+
+    return device->pos();
+}
+
 QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
 {
     byteDevice = bd;
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index 8b5bf3080a487cca37e0c01891f09447fd764b6e..38089dedd721c7a8f44c90113976d8a364277f1c 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -61,6 +61,7 @@ public:
     virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
     virtual bool advanceReadPointer(qint64 amount) = 0;
     virtual bool atEnd() = 0;
+    virtual qint64 pos() { return -1; }
     virtual bool reset() = 0;
     virtual qint64 size() = 0;
 
@@ -103,6 +104,7 @@ public:
     bool atEnd() Q_DECL_OVERRIDE;
     bool reset() Q_DECL_OVERRIDE;
     qint64 size() Q_DECL_OVERRIDE;
+    qint64 pos() Q_DECL_OVERRIDE;
 protected:
     QByteArray* byteArray;
     qint64 currentPosition;
@@ -118,6 +120,7 @@ public:
     bool atEnd() Q_DECL_OVERRIDE;
     bool reset() Q_DECL_OVERRIDE;
     qint64 size() Q_DECL_OVERRIDE;
+    qint64 pos() Q_DECL_OVERRIDE;
 protected:
     QSharedPointer<QRingBuffer> ringBuffer;
     qint64 currentPosition;
@@ -135,6 +138,7 @@ public:
     bool atEnd() Q_DECL_OVERRIDE;
     bool reset() Q_DECL_OVERRIDE;
     qint64 size() Q_DECL_OVERRIDE;
+    qint64 pos() Q_DECL_OVERRIDE;
 protected:
     QIODevice* device;
     QByteArray* currentReadBuffer;
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 38bd588c377903e78b5bd9e2ff219abe3b3e939e..da6e0c87af1b0861ceace6441dfe0762ecef48e0 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -110,7 +110,6 @@ QT_BEGIN_NAMESPACE
     \ingroup io
     \ingroup misc
     \ingroup shared
-    \mainclass
     \reentrant
     \since 4.6
 
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 078217ea0b9e6d5c2994b64be61235bd377afb1a..32fa4aa866a3fc5e831480de858ce96ee479f4df 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -104,15 +104,21 @@ public:
         WriteError,
         UnknownError
     };
+    Q_ENUM(ProcessError)
+
     enum ProcessState {
         NotRunning,
         Starting,
         Running
     };
+    Q_ENUM(ProcessState)
+
     enum ProcessChannel {
         StandardOutput,
         StandardError
     };
+    Q_ENUM(ProcessChannel)
+
     enum ProcessChannelMode {
         SeparateChannels,
         MergedChannels,
@@ -120,14 +126,19 @@ public:
         ForwardedOutputChannel,
         ForwardedErrorChannel
     };
+    Q_ENUM(ProcessChannelMode)
+
     enum InputChannelMode {
         ManagedInputChannel,
         ForwardedInputChannel
     };
+    Q_ENUM(InputChannelMode)
+
     enum ExitStatus {
         NormalExit,
         CrashExit
     };
+    Q_ENUM(ExitStatus)
 
     explicit QProcess(QObject *parent = 0);
     virtual ~QProcess();
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index cb6de29532089a7b9487c14b5b8bb85875c324be..251b10ea89563f269474d34a00aefa4e8b0ae0cc 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -104,6 +104,10 @@ using namespace ABI::Windows::Storage;
 #define Q_XDG_PLATFORM
 #endif
 
+#if !defined(QT_NO_STANDARDPATHS) && (defined(Q_XDG_PLATFORM) || defined(Q_OS_IOS))
+#define QSETTINGS_USE_QSTANDARDPATHS
+#endif
+
 // ************************************************************************
 // QConfFile
 
@@ -1044,7 +1048,7 @@ static void initDefaultPaths(QMutexLocker *locker)
                          windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
 #else
 
-#if defined(QT_NO_STANDARDPATHS) || !defined(Q_XDG_PLATFORM)
+#ifndef QSETTINGS_USE_QSTANDARDPATHS
         // Non XDG platforms (OS X, iOS, Blackberry, Android...) have used this code path erroneously
         // for some time now. Moving away from that would require migrating existing settings.
         QString userPath;
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index 5f764549e0d3bcd23bed743659588baafee05082..04848a38e5299882cf4c5080a8701da185d04fd5 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -274,45 +274,67 @@ QT_BEGIN_NAMESPACE
     \endtable
 
     \table
-    \header \li Path type \li Android
+    \header \li Path type \li Android \li iOS
     \row \li DesktopLocation
          \li "<APPROOT>/files"
+         \li "<APPROOT>/<APPDIR>" (not writable)
     \row \li DocumentsLocation
          \li "<USER>/Documents", "<USER>/<APPNAME>/Documents"
+         \li "<APPROOT>/Documents"
     \row \li FontsLocation
          \li "/system/fonts" (not writable)
+         \li "<APPROOT>/Documents/.fonts"
     \row \li ApplicationsLocation
          \li not supported (directory not readable)
+         \li not supported
     \row \li MusicLocation
          \li "<USER>/Music", "<USER>/<APPNAME>/Music"
+         \li "<APPROOT>/Documents/Music"
     \row \li MoviesLocation
          \li "<USER>/Movies", "<USER>/<APPNAME>/Movies"
+         \li "<APPROOT>/Documents/Movies"
     \row \li PicturesLocation
          \li "<USER>/Pictures", "<USER>/<APPNAME>/Pictures"
+         \li "<APPROOT>/Documents/Pictures", "assets-library://"
     \row \li TempLocation
          \li "<APPROOT>/cache"
+         \li "<APPROOT>/tmp"
     \row \li HomeLocation
          \li "<APPROOT>/files"
+         \li "<APPROOT>/<APPDIR>" (not writable)
     \row \li DataLocation
          \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+         \li "<APPROOT>/Library/Application Support"
     \row \li CacheLocation
          \li "<APPROOT>/cache", "<USER>/<APPNAME>/cache"
+         \li "<APPROOT>/Library/Caches"
     \row \li GenericDataLocation
          \li "<USER>"
+         \li "<APPROOT>/Documents"
     \row \li RuntimeLocation
          \li "<APPROOT>/cache"
+         \li not supported
     \row \li ConfigLocation
          \li "<APPROOT>/files/settings"
+         \li "<APPROOT>/Documents"
     \row \li GenericConfigLocation
          \li "<APPROOT>/files/settings" (there is no shared settings)
+         \li "<APPROOT>/Documents"
     \row \li DownloadLocation
          \li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads"
+         \li "<APPROOT>/Documents/Download"
     \row \li GenericCacheLocation
          \li "<APPROOT>/cache" (there is no shared cache)
+         \li "<APPROOT>/Library/Caches"
     \row \li AppDataLocation
          \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+         \li "<APPROOT>/Library/Application Support"
     \row \li AppConfigLocation
          \li "<APPROOT>/files/settings"
+         \li "<APPROOT>/Documents"
+    \row \li AppLocalDataLocation
+         \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+         \li "<APPROOT>/Library/Application Support"
     \endtable
 
     In the table above, \c <APPNAME> is usually the organization name, the
@@ -327,6 +349,12 @@ QT_BEGIN_NAMESPACE
     \note On Android, applications with open files on the external storage (<USER> locations),
           will be killed if the external storage is unmounted.
 
+    \note On iOS, if you do pass \c {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()}
+        as argument to \l{QFileDialog::setDirectory()},
+        a native image picker dialog will be used for accessing the user's photo album.
+        The filename returned can be loaded using QFile and related APIs.
+        This feature was added in Qt 5.5.
+
     \sa writableLocation(), standardLocations(), displayName(), locate(), locateAll()
 */
 
@@ -494,13 +522,8 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
     QStringList searchPaths = paths;
     if (paths.isEmpty()) {
         QByteArray pEnv = qgetenv("PATH");
-#if defined(Q_OS_WIN)
-        const QLatin1Char pathSep(';');
-#else
-        const QLatin1Char pathSep(':');
-#endif
         // Remove trailing slashes, which occur on Windows.
-        const QStringList rawPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
+        const QStringList rawPaths = QString::fromLocal8Bit(pEnv.constData()).split(QDir::listSeparator(), QString::SkipEmptyParts);
         searchPaths.reserve(rawPaths.size());
         foreach (const QString &rawPath, rawPaths) {
             QString cleanPath = QDir::cleanPath(rawPath);
diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm
index 27d28526c2d30bed03f24f42665b2a1023cf73bf..eb85e2fd23b201e8d71166fee23b131e9dc20ed3 100644
--- a/src/corelib/io/qstandardpaths_ios.mm
+++ b/src/corelib/io/qstandardpaths_ios.mm
@@ -55,30 +55,31 @@ QString QStandardPaths::writableLocation(StandardLocation type)
     QString location;
 
     switch (type) {
-    case DesktopLocation:
-        location = pathForDirectory(NSDesktopDirectory);
-        break;
     case DocumentsLocation:
         location = pathForDirectory(NSDocumentDirectory);
         break;
     case FontsLocation:
-        location = bundlePath() + QLatin1String("/.fonts");
+        location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/.fonts");
         break;
     case ApplicationsLocation:
-        location = pathForDirectory(NSApplicationDirectory);
+        // NSApplicationDirectory points to a non-existing write-protected path.
         break;
     case MusicLocation:
-        location = pathForDirectory(NSMusicDirectory);
+        // NSMusicDirectory points to a non-existing write-protected path. Use sensible fallback.
+        location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Music");
         break;
     case MoviesLocation:
-        location = pathForDirectory(NSMoviesDirectory);
+        // NSMoviesDirectory points to a non-existing write-protected path. Use sensible fallback.
+        location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Movies");
         break;
     case PicturesLocation:
-        location = pathForDirectory(NSPicturesDirectory);
+        // NSPicturesDirectory points to a non-existing write-protected path. Use sensible fallback.
+        location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Pictures");
         break;
     case TempLocation:
         location = QString::fromNSString(NSTemporaryDirectory());
         break;
+    case DesktopLocation:
     case HomeLocation:
         location = bundlePath();
         break;
@@ -99,20 +100,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
         location = pathForDirectory(NSDocumentDirectory);
         break;
     case DownloadLocation:
-        location = pathForDirectory(NSDownloadsDirectory);
-        break;
-    default:
+        // NSDownloadsDirectory points to a non-existing write-protected path.
+        location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Download");
         break;
-    }
-
-    switch (type) {
     case RuntimeLocation:
         break;
     default:
-        // All other types must return something, so use the document directory
-        // as a reasonable fall-back (which will always exist).
-        if (location.isEmpty())
-            location = pathForDirectory(NSDocumentDirectory);
         break;
     }
 
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 78237877117bebe74687e7b543ce5cf59e93d1e2..f82d0ff0a18da7a682aa8546a074efe8ba2141c8 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -67,8 +67,20 @@
 #endif
 
 #if defined(Q_OS_BSD4)
-#  define QT_STATFSBUF struct statvfs
-#  define QT_STATFS    ::statvfs
+#  if defined(Q_OS_NETBSD)
+     define QT_STATFSBUF struct statvfs
+     define QT_STATFS    ::statvfs
+#  else
+#    define QT_STATFSBUF struct statfs
+#    define QT_STATFS    ::statfs
+#  endif
+
+#  if !defined(ST_RDONLY)
+#    define ST_RDONLY MNT_RDONLY
+#  endif
+#  if !defined(_STATFS_F_FLAGS)
+#    define _STATFS_F_FLAGS 1
+#  endif
 #elif defined(Q_OS_ANDROID)
 #  define QT_STATFS    ::statfs
 #  define QT_STATFSBUF struct statfs
@@ -122,11 +134,7 @@ public:
     inline QByteArray device() const;
 private:
 #if defined(Q_OS_BSD4)
-#  if defined(Q_OS_NETBSD)
-    struct statvfs *stat_buf;
-#  else
-    struct statfs *stat_buf;
-#  endif
+    QT_STATFSBUF *stat_buf;
     int entryCount;
     int currentIndex;
 #elif defined(Q_OS_SOLARIS)
@@ -502,7 +510,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
         bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
         bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
         bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
-#if defined(Q_OS_ANDROID)
+#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
 #if defined(_STATFS_F_FLAGS)
         readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
 #endif
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 556bc6e7607238093c69e57f3a497501e3d1ad47..bdf4392275a3c6dee82006a0648f0cd0a99e52a0 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -236,9 +236,9 @@ QTemporaryFileEngine::~QTemporaryFileEngine()
     QFSFileEngine::close();
 }
 
-bool QTemporaryFileEngine::isReallyOpen()
+bool QTemporaryFileEngine::isReallyOpen() const
 {
-    Q_D(QFSFileEngine);
+    Q_D(const QFSFileEngine);
 
     if (!((0 == d->fh) && (-1 == d->fd)
 #if defined Q_OS_WIN
diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h
index 475298f264f28054e46e711a701376c21f3d6c06..341ae9bd3f13736312b1fd82fde9695e5e2a2262 100644
--- a/src/corelib/io/qtemporaryfile_p.h
+++ b/src/corelib/io/qtemporaryfile_p.h
@@ -95,7 +95,7 @@ public:
 
     ~QTemporaryFileEngine();
 
-    bool isReallyOpen();
+    bool isReallyOpen() const;
     void setFileName(const QString &file);
     void setFileTemplate(const QString &fileTemplate);
 
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 5fe4cfef9d1c989f5a35a01ab54a5ab79ab0475b..47b96d708f8f17a39dd0ae508079a2a43175fd15 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -464,7 +464,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
     }
 #if defined (QTEXTSTREAM_DEBUG)
     qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec",
-           codec->name().constData());
+           codec ? codec->name().constData() : "no");
 #endif
 #endif
 
@@ -476,9 +476,10 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
     int oldReadBufferSize = readBuffer.size();
 #ifndef QT_NO_TEXTCODEC
     // convert to unicode
-    readBuffer += codec->toUnicode(buf, bytesRead, &readConverterState);
+    readBuffer += Q_LIKELY(codec) ? codec->toUnicode(buf, bytesRead, &readConverterState)
+                                  : QString::fromLatin1(buf, bytesRead);
 #else
-    readBuffer += QString::fromLatin1(QByteArray(buf, bytesRead).constData());
+    readBuffer += QString::fromLatin1(buf, bytesRead);
 #endif
 
     // reset the Text flag.
@@ -564,7 +565,8 @@ void QTextStreamPrivate::flushWriteBuffer()
         codec = QTextCodec::codecForLocale();
 #if defined (QTEXTSTREAM_DEBUG)
     qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)",
-           codec->name().constData(), writeConverterState.flags & QTextCodec::IgnoreHeader ? "not" : "");
+           codec ? codec->name().constData() : "no",
+           !codec || (writeConverterState.flags & QTextCodec::IgnoreHeader) ? "not" : "");
 #endif
 
     // convert from unicode to raw data
@@ -572,7 +574,7 @@ void QTextStreamPrivate::flushWriteBuffer()
     QByteArray data = Q_LIKELY(codec) ? codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState)
                                       : writeBuffer.toLatin1();
 #else
-    QByteArray data = writeBuffer.toLocal8Bit();
+    QByteArray data = writeBuffer.toLatin1();
 #endif
     writeBuffer.clear();
 
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 945b7df930bbe7b1b3c5aec68755291d8855ec9a..e6c570d1dbcf41da5f683312554e385c47390dfe 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -186,7 +186,7 @@ public:
     QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
     QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
     QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
-    QUrl adjusted(FormattingOptions options) const;
+    QUrl adjusted(FormattingOptions options) const Q_REQUIRED_RESULT;
 
     QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
     static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
@@ -243,7 +243,7 @@ public:
     QString fragment(ComponentFormattingOptions options = PrettyDecoded) const;
     void setFragment(const QString &fragment, ParsingMode mode = TolerantMode);
 
-    QUrl resolved(const QUrl &relative) const;
+    QUrl resolved(const QUrl &relative) const Q_REQUIRED_RESULT;
 
     bool isRelative() const;
     bool isParentOf(const QUrl &url) const;
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 1502e5dada933f37df7afda5c96b2f52796a950c..2cc57412505c5b174716f6f080c59033536ef4ac 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -36,7 +36,6 @@
 #include <qdebug.h>
 #include <qelapsedtimer.h>
 #include <qeventloop.h>
-#include <qtimer.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -45,13 +44,11 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
       handle(INVALID_HANDLE_VALUE),
       readBufferMaxSize(0),
       actualReadBufferSize(0),
-      emitReadyReadTimer(new QTimer(this)),
+      stopped(true),
       readSequenceStarted(false),
       pipeBroken(false),
       readyReadEmitted(false)
 {
-    emitReadyReadTimer->setSingleShot(true);
-    connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()));
     dataReadNotifier = new QWinOverlappedIoNotifier(this);
     connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
 }
@@ -73,12 +70,7 @@ static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
 
 QWindowsPipeReader::~QWindowsPipeReader()
 {
-    if (readSequenceStarted) {
-        if (qt_cancelIo(handle, &overlapped))
-            dataReadNotifier->waitForNotified(-1, &overlapped);
-        else
-            qErrnoWarning("QWindowsPipeReader: qt_cancelIo on handle %x failed.", handle);
-    }
+    stop();
 }
 
 /*!
@@ -89,9 +81,9 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
     readBuffer.clear();
     actualReadBufferSize = 0;
     handle = hPipeReadEnd;
-    ZeroMemory(&overlapped, sizeof(overlapped));
     pipeBroken = false;
     readyReadEmitted = false;
+    stopped = false;
     if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
         dataReadNotifier->setHandle(hPipeReadEnd);
         dataReadNotifier->setEnabled(true);
@@ -100,13 +92,24 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
 
 /*!
     Stops the asynchronous read sequence.
-    This function assumes that the file already has been closed.
-    It does not cancel any I/O operation.
+    If the read sequence is running then the I/O operation is canceled.
  */
 void QWindowsPipeReader::stop()
 {
-    dataReadNotifier->setEnabled(false);
+    stopped = true;
+    if (readSequenceStarted) {
+        if (qt_cancelIo(handle, &overlapped)) {
+            dataReadNotifier->waitForNotified(-1, &overlapped);
+        } else {
+            const DWORD dwError = GetLastError();
+            if (dwError != ERROR_NOT_FOUND) {
+                qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
+                              handle);
+            }
+        }
+    }
     readSequenceStarted = false;
+    dataReadNotifier->setEnabled(false);
     handle = INVALID_HANDLE_VALUE;
 }
 
@@ -119,7 +122,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
 }
 
 /*!
-    Stops the asynchronous read sequence.
+    Copies at most \c{maxlen} bytes from the internal read buffer to \c{data}.
  */
 qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
 {
@@ -147,9 +150,7 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
     }
 
     if (!pipeBroken) {
-        if (!actualReadBufferSize)
-            emitReadyReadTimer->stop();
-        if (!readSequenceStarted)
+        if (!readSequenceStarted && !stopped)
             startAsyncRead();
         if (readSoFar == 0)
             return -2;      // signal EWOULDBLOCK
@@ -172,13 +173,41 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
 {
     if (&overlapped != notifiedOverlapped)
         return;
-    if (!completeAsyncRead(numberOfBytesRead, errorCode)) {
+
+    switch (errorCode) {
+    case ERROR_SUCCESS:
+        break;
+    case ERROR_MORE_DATA:
+        // This is not an error. We're connected to a message mode
+        // pipe and the message didn't fit into the pipe's system
+        // buffer. We will read the remaining data in the next call.
+        break;
+    case ERROR_BROKEN_PIPE:
+    case ERROR_PIPE_NOT_CONNECTED:
         pipeBroken = true;
+        break;
+    default:
+        emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
+        pipeBroken = true;
+        break;
+    }
+
+    readSequenceStarted = false;
+
+    // After the reader was stopped, the only reason why this function can be called is the
+    // completion of a cancellation. No signals should be emitted, and no new read sequence should
+    // be started in this case.
+    if (stopped)
+        return;
+
+    if (pipeBroken) {
         emit pipeClosed();
         return;
     }
+
+    actualReadBufferSize += numberOfBytesRead;
+    readBuffer.truncate(actualReadBufferSize);
     startAsyncRead();
-    emitReadyReadTimer->stop();
     readyReadEmitted = true;
     emit readyRead();
 }
@@ -206,6 +235,7 @@ void QWindowsPipeReader::startAsyncRead()
     char *ptr = readBuffer.reserve(bytesToRead);
 
     readSequenceStarted = true;
+    ZeroMemory(&overlapped, sizeof(overlapped));
     if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
         // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
         return;
@@ -239,38 +269,6 @@ void QWindowsPipeReader::startAsyncRead()
     }
 }
 
-/*!
-    \internal
-    Sets the correct size of the read buffer after a read operation.
-    Returns \c false, if an error occurred or the connection dropped.
- */
-bool QWindowsPipeReader::completeAsyncRead(DWORD bytesRead, DWORD errorCode)
-{
-    readSequenceStarted = false;
-
-    switch (errorCode) {
-    case ERROR_SUCCESS:
-        break;
-    case ERROR_MORE_DATA:
-        // This is not an error. We're connected to a message mode
-        // pipe and the message didn't fit into the pipe's system
-        // buffer. We will read the remaining data in the next call.
-        break;
-    case ERROR_BROKEN_PIPE:
-    case ERROR_PIPE_NOT_CONNECTED:
-        return false;
-    default:
-        emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
-        return false;
-    }
-
-    actualReadBufferSize += bytesRead;
-    readBuffer.truncate(actualReadBufferSize);
-    if (!emitReadyReadTimer->isActive())
-        emitReadyReadTimer->start();
-    return true;
-}
-
 /*!
     \internal
     Returns the number of available bytes in the pipe.
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index 53872e255239cbad92cbb0ab169b293a5ef53393..c8a66d951191c49a39257a53d505a8008f0b2d02 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -47,7 +47,6 @@
 
 #include <qbytearray.h>
 #include <qobject.h>
-#include <qtimer.h>
 #include <private/qringbuffer_p.h>
 
 #include <qt_windows.h>
@@ -89,7 +88,6 @@ private Q_SLOTS:
     void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
 
 private:
-    bool completeAsyncRead(DWORD bytesRead, DWORD errorCode);
     DWORD checkPipeState();
 
 private:
@@ -99,7 +97,7 @@ private:
     qint64 readBufferMaxSize;
     QRingBuffer readBuffer;
     qint64 actualReadBufferSize;
-    QTimer *emitReadyReadTimer;
+    bool stopped;
     bool readSequenceStarted;
     bool pipeBroken;
     bool readyReadEmitted;
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 60ac75133c2c2d989f52320eed9b57c3b86f0f41..2f3cfc1c0ad11d7f8eece69c3ea4f0c8a6d81eb9 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -479,6 +479,11 @@ public:
 
 Q_GLOBAL_STATIC(QEmptyItemModel, qEmptyModel)
 
+
+QAbstractItemModelPrivate::~QAbstractItemModelPrivate()
+{
+}
+
 QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
 {
     return qEmptyModel();
diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h
index 075e6a901838c620d80b5a1264a4fb9408ee726a..acf376eff13fb7a32b8aae1b94f8dc7a48c630c8 100644
--- a/src/corelib/itemmodels/qabstractitemmodel_p.h
+++ b/src/corelib/itemmodels/qabstractitemmodel_p.h
@@ -71,6 +71,8 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate
 
 public:
     QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {}
+    ~QAbstractItemModelPrivate();
+
     void removePersistentIndexData(QPersistentModelIndexData *data);
     void movePersistentIndexes(const QVector<QPersistentModelIndexData *> &indexes, int change, const QModelIndex &parent, Qt::Orientation orientation);
     void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index a215557aedd138407fcda5c2989b1260028962cb..14c0f803b9e763ff38fff6e25bf94529e5661958 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -131,5 +131,22 @@ QAppleOperatingSystemVersion qt_apple_os_version()
     return v;
 }
 
+// -------------------------------------------------------------------------
+
+QMacAutoReleasePool::QMacAutoReleasePool()
+    : pool([[NSAutoreleasePool alloc] init])
+{
+}
+
+QMacAutoReleasePool::~QMacAutoReleasePool()
+{
+    // Drain behaves the same as release, with the advantage that
+    // if we're ever used in a garbage-collected environment, the
+    // drain acts as a hint to the garbage collector to collect.
+    [pool drain];
+}
+
+// -------------------------------------------------------------------------
+
 QT_END_NAMESPACE
 
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 05d58ac028ed87aed20cb5705db17c05d8e10c76..524bfd26cc92d6d6248bbb9b5eb5e34ef548d31d 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -325,6 +325,7 @@ struct QCoreApplicationData {
 #ifndef QT_NO_LIBRARY
         app_libpaths = 0;
 #endif
+        applicationNameSet = false;
     }
     ~QCoreApplicationData() {
 #ifndef QT_NO_LIBRARY
@@ -369,8 +370,8 @@ struct QCoreApplicationData {
 
     QString orgName, orgDomain;
     QString application; // application name, initially from argv[0], can then be modified.
-    QString applicationNameCompat; // for QDesktopServices. Only set explicitly.
     QString applicationVersion;
+    bool applicationNameSet; // true if setApplicationName was called
 
 #ifndef QT_NO_LIBRARY
     QStringList *app_libpaths;
@@ -752,7 +753,8 @@ void QCoreApplication::init()
     QCoreApplication::self = this;
 
     // Store app name (so it's still available after QCoreApplication is destroyed)
-    coreappdata()->application = d_func()->appName();
+    if (!coreappdata()->applicationNameSet)
+        coreappdata()->application = d_func()->appName();
 
     QLoggingRegistry::instance()->init();
 
@@ -2349,13 +2351,13 @@ QString QCoreApplication::organizationDomain()
 */
 void QCoreApplication::setApplicationName(const QString &application)
 {
+    coreappdata()->applicationNameSet = !application.isEmpty();
     QString newAppName = application;
     if (newAppName.isEmpty() && QCoreApplication::self)
         newAppName = QCoreApplication::self->d_func()->appName();
     if (coreappdata()->application == newAppName)
         return;
     coreappdata()->application = newAppName;
-    coreappdata()->applicationNameCompat = newAppName;
 #ifndef QT_NO_QOBJECT
     if (QCoreApplication::self)
         emit QCoreApplication::self->applicationNameChanged();
@@ -2373,7 +2375,7 @@ QString QCoreApplication::applicationName()
 // Exported for QDesktopServices (Qt4 behavior compatibility)
 Q_CORE_EXPORT QString qt_applicationName_noFallback()
 {
-    return coreappdata()->applicationNameCompat;
+    return coreappdata()->applicationNameSet ? coreappdata()->application : QString();
 }
 
 /*!
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index cc8e961be1161c77869a40d9fa0a147ea9b688bb..150999619974c623fac1c6a571ce3d902b876d5b 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -203,9 +203,9 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
             }
         }
 
-        // Dispatch accumulated user events
-        if (sendPostedEvents(flags))
-            return true;
+        // Additional user events have to be handled before timer events, but the function may not
+        // return yet.
+        const bool userEventsSent = sendPostedEvents(flags);
 
         emit aboutToBlock();
         const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
@@ -228,6 +228,9 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
             return true;
         }
         emit awake();
+
+        if (userEventsSent)
+            return true;
     } while (flags & QEventLoop::WaitForMoreEvents);
     return false;
 }
@@ -484,7 +487,8 @@ bool QEventDispatcherWinRT::event(QEvent *e)
 QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate()
 {
     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-    HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
+    HRESULT hr;
+    hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
     Q_ASSERT_SUCCEEDED(hr);
     HANDLE interruptHandle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE);
     timerIdToHandle.insert(INTERRUPT_HANDLE, interruptHandle);
diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h
index 3fff52a22c8794431e70b6e2cac68ac1d47b129e..7efd0424561bff2451a809d4c1a565f54f0d6b91 100644
--- a/src/corelib/kernel/qfunctions_winrt.h
+++ b/src/corelib/kernel/qfunctions_winrt.h
@@ -131,9 +131,13 @@ generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *)
 generate_inline_return_func0(tzset, void)
 generate_inline_return_func0(_tzset, void)
 
-QT_BEGIN_NAMESPACE
+namespace Microsoft {
+    namespace WRL {
+        template <typename T> class ComPtr;
+    }
+}
 
-namespace Microsoft { namespace WRL { template <typename T> class ComPtr; } }
+QT_BEGIN_NAMESPACE
 
 namespace QWinRTFunctions {
 
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp
index 097f641d19b457a7d90b7c30187b1896a45333f8..108a01aab79ecc8725d8d6dbb31cfe8276fe2b00 100644
--- a/src/corelib/kernel/qjni.cpp
+++ b/src/corelib/kernel/qjni.cpp
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
 
 static inline QString keyBase()
 {
-    return QStringLiteral("%1%2%3");
+    return QStringLiteral("%1%2:%3");
 }
 
 static QString qt_convertJString(jstring string)
@@ -72,15 +72,15 @@ typedef QHash<QString, jclass> JClassHash;
 Q_GLOBAL_STATIC(JClassHash, cachedClasses)
 Q_GLOBAL_STATIC(QReadWriteLock, cachedClassesLock)
 
-static QString toDotEncodedClassName(const char *className)
+static QByteArray toBinaryEncClassName(const QByteArray &className)
 {
-    return QString::fromLatin1(className).replace(QLatin1Char('/'), QLatin1Char('.'));
+    return QByteArray(className).replace('/', '.');
 }
 
-static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0)
+static jclass getCachedClass(const QByteArray &classBinEnc, bool *isCached = 0)
 {
     QReadLocker locker(cachedClassesLock);
-    const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(classDotEnc);
+    const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(QString::fromLatin1(classBinEnc));
     const bool found = (it != cachedClasses->constEnd());
 
     if (isCached != 0)
@@ -89,10 +89,12 @@ static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0)
     return found ? it.value() : 0;
 }
 
-static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env)
+inline static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false)
 {
+    const QByteArray &binEncClassName = binEncoded ? className : toBinaryEncClassName(className);
+
     bool isCached = false;
-    jclass clazz = getCachedClass(classDotEnc, &isCached);
+    jclass clazz = getCachedClass(binEncClassName, &isCached);
     if (clazz != 0 || isCached)
         return clazz;
 
@@ -102,11 +104,12 @@ static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env)
 
     QWriteLocker locker(cachedClassesLock);
     // did we lose the race?
-    const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(classDotEnc);
+    const QLatin1String key(binEncClassName);
+    const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(key);
     if (it != cachedClasses->constEnd())
         return it.value();
 
-    QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(classDotEnc);
+    QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(key);
     QJNIObjectPrivate classObject = classLoader.callObjectMethod("loadClass",
                                                                  "(Ljava/lang/String;)Ljava/lang/Class;",
                                                                  stringName.object());
@@ -114,27 +117,40 @@ static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env)
     if (!exceptionCheckAndClear(env) && classObject.isValid())
         clazz = static_cast<jclass>(env->NewGlobalRef(classObject.object()));
 
-    cachedClasses->insert(classDotEnc, clazz);
+    cachedClasses->insert(key, clazz);
     return clazz;
 }
 
-inline static jclass loadClass(const char *className, JNIEnv *env)
-{
-    return loadClassDotEnc(toDotEncodedClassName(className), env);
-}
-
 typedef QHash<QString, jmethodID> JMethodIDHash;
 Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID)
 Q_GLOBAL_STATIC(QReadWriteLock, cachedMethodIDLock)
 
+static inline jmethodID getMethodID(JNIEnv *env,
+                                    jclass clazz,
+                                    const char *name,
+                                    const char *sig,
+                                    bool isStatic = false)
+{
+    jmethodID id = isStatic ? env->GetStaticMethodID(clazz, name, sig)
+                            : env->GetMethodID(clazz, name, sig);
+
+    if (exceptionCheckAndClear(env))
+        return 0;
+
+    return id;
+}
+
 static jmethodID getCachedMethodID(JNIEnv *env,
                                    jclass clazz,
+                                   const QByteArray &className,
                                    const char *name,
                                    const char *sig,
                                    bool isStatic = false)
 {
-    // TODO: We need to use something else then the ref. from clazz to avoid collisions.
-    const QString key = keyBase().arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+    if (className.isEmpty())
+        return getMethodID(env, clazz, name, sig, isStatic);
+
+    const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
     QHash<QString, jmethodID>::const_iterator it;
 
     {
@@ -150,14 +166,7 @@ static jmethodID getCachedMethodID(JNIEnv *env,
         if (it != cachedMethodID->constEnd())
             return it.value();
 
-        jmethodID id = 0;
-        if (isStatic)
-            id = env->GetStaticMethodID(clazz, name, sig);
-        else
-            id = env->GetMethodID(clazz, name, sig);
-
-        if (exceptionCheckAndClear(env))
-            id = 0;
+        jmethodID id = getMethodID(env, clazz, name, sig, isStatic);
 
         cachedMethodID->insert(key, id);
         return id;
@@ -168,13 +177,32 @@ typedef QHash<QString, jfieldID> JFieldIDHash;
 Q_GLOBAL_STATIC(JFieldIDHash, cachedFieldID)
 Q_GLOBAL_STATIC(QReadWriteLock, cachedFieldIDLock)
 
+static inline jfieldID getFieldID(JNIEnv *env,
+                                  jclass clazz,
+                                  const char *name,
+                                  const char *sig,
+                                  bool isStatic = false)
+{
+    jfieldID id = isStatic ? env->GetStaticFieldID(clazz, name, sig)
+                           : env->GetFieldID(clazz, name, sig);
+
+    if (exceptionCheckAndClear(env))
+        return 0;
+
+    return id;
+}
+
 static jfieldID getCachedFieldID(JNIEnv *env,
                                  jclass clazz,
+                                 const QByteArray &className,
                                  const char *name,
                                  const char *sig,
                                  bool isStatic = false)
 {
-    const QString key = keyBase().arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+    if (className.isNull())
+        return getFieldID(env, clazz, name, sig, isStatic);
+
+    const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
     QHash<QString, jfieldID>::const_iterator it;
 
     {
@@ -190,14 +218,7 @@ static jfieldID getCachedFieldID(JNIEnv *env,
         if (it != cachedFieldID->constEnd())
             return it.value();
 
-        jfieldID id = 0;
-        if (isStatic)
-            id = env->GetStaticFieldID(clazz, name, sig);
-        else
-            id = env->GetFieldID(clazz, name, sig);
-
-        if (exceptionCheckAndClear(env))
-            id = 0;
+        jfieldID id = getFieldID(env, clazz, name, sig, isStatic);
 
         cachedFieldID->insert(key, id);
         return id;
@@ -251,7 +272,7 @@ JNIEnv *QJNIEnvironmentPrivate::operator->()
 
 jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env)
 {
-    const QString &classDotEnc = toDotEncodedClassName(className);
+    const QByteArray &classDotEnc = toBinaryEncClassName(className);
     bool isCached = false;
     jclass clazz = getCachedClass(classDotEnc, &isCached);
 
@@ -260,9 +281,10 @@ jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env)
     if (found)
         return clazz;
 
+    const QLatin1String key(classDotEnc);
     if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass())
         QWriteLocker locker(cachedClassesLock);
-        const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(classDotEnc);
+        const QHash<QString, jclass>::const_iterator &it = cachedClasses->constFind(key);
         // Did we lose the race?
         if (it != cachedClasses->constEnd())
             return it.value();
@@ -274,11 +296,11 @@ jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env)
         }
 
         if (clazz != 0)
-            cachedClasses->insert(classDotEnc, clazz);
+            cachedClasses->insert(key, clazz);
     }
 
     if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader...
-        clazz = loadClassDotEnc(classDotEnc, QJNIEnvironmentPrivate());
+        clazz = loadClass(classDotEnc, QJNIEnvironmentPrivate(), true);
 
     return clazz;
 }
@@ -319,11 +341,12 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className)
     : d(new QJNIObjectData())
 {
     QJNIEnvironmentPrivate env;
-    d->m_jclass = loadClass(className, env);
+    d->m_className = toBinaryEncClassName(className);
+    d->m_jclass = loadClass(d->m_className, env, true);
     d->m_own_jclass = false;
     if (d->m_jclass) {
         // get default constructor
-        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", "()V");
+        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", "()V");
         if (constructorId) {
             jobject obj = env->NewObject(d->m_jclass, constructorId);
             if (obj) {
@@ -338,10 +361,11 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, ...
     : d(new QJNIObjectData())
 {
     QJNIEnvironmentPrivate env;
-    d->m_jclass = loadClass(className, env);
+    d->m_className = toBinaryEncClassName(className);
+    d->m_jclass = loadClass(d->m_className, env, true);
     d->m_own_jclass = false;
     if (d->m_jclass) {
-        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", sig);
+        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", sig);
         if (constructorId) {
             va_list args;
             va_start(args, sig);
@@ -359,10 +383,11 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, con
     : d(new QJNIObjectData())
 {
     QJNIEnvironmentPrivate env;
-    d->m_jclass = loadClass(className, env);
+    d->m_className = toBinaryEncClassName(className);
+    d->m_jclass = loadClass(d->m_className, env, true);
     d->m_own_jclass = false;
     if (d->m_jclass) {
-        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", sig);
+        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "<init>", sig);
         if (constructorId) {
             jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
             if (obj) {
@@ -380,7 +405,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz)
     d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
     if (d->m_jclass) {
         // get default constructor
-        jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", "()V");
+        jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", "()V");
         if (constructorId) {
             jobject obj = env->NewObject(d->m_jclass, constructorId);
             if (obj) {
@@ -398,7 +423,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, ...)
     if (clazz) {
         d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
         if (d->m_jclass) {
-            jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", sig);
+            jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", sig);
             if (constructorId) {
                 va_list args;
                 va_start(args, sig);
@@ -420,7 +445,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, const QVaLis
     if (clazz) {
         d->m_jclass = static_cast<jclass>(env->NewGlobalRef(clazz));
         if (d->m_jclass) {
-            jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "<init>", sig);
+            jmethodID constructorId = getMethodID(env, d->m_jclass, "<init>", sig);
             if (constructorId) {
                 jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
                 if (obj) {
@@ -440,15 +465,15 @@ QJNIObjectPrivate::QJNIObjectPrivate(jobject obj)
 
     QJNIEnvironmentPrivate env;
     d->m_jobject = env->NewGlobalRef(obj);
-    jclass objectClass = env->GetObjectClass(d->m_jobject);
-    d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
-    env->DeleteLocalRef(objectClass);
+    jclass cls = env->GetObjectClass(obj);
+    d->m_jclass = static_cast<jclass>(env->NewGlobalRef(cls));
+    env->DeleteLocalRef(cls);
 }
 template <>
 void QJNIObjectPrivate::callMethodV<void>(const char *methodName, const char *sig, va_list args) const
 {
     QJNIEnvironmentPrivate env;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         env->CallVoidMethodV(d->m_jobject, id, args);
     }
@@ -468,7 +493,7 @@ jboolean QJNIObjectPrivate::callMethodV<jboolean>(const char *methodName, const
 {
     QJNIEnvironmentPrivate env;
     jboolean res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallBooleanMethodV(d->m_jobject, id, args);
     }
@@ -490,7 +515,7 @@ jbyte QJNIObjectPrivate::callMethodV<jbyte>(const char *methodName, const char *
 {
     QJNIEnvironmentPrivate env;
     jbyte res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallByteMethodV(d->m_jobject, id, args);
     }
@@ -512,7 +537,7 @@ jchar QJNIObjectPrivate::callMethodV<jchar>(const char *methodName, const char *
 {
     QJNIEnvironmentPrivate env;
     jchar res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallCharMethodV(d->m_jobject, id, args);
     }
@@ -534,7 +559,7 @@ jshort QJNIObjectPrivate::callMethodV<jshort>(const char *methodName, const char
 {
     QJNIEnvironmentPrivate env;
     jshort res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallShortMethodV(d->m_jobject, id, args);
     }
@@ -556,7 +581,7 @@ jint QJNIObjectPrivate::callMethodV<jint>(const char *methodName, const char *si
 {
     QJNIEnvironmentPrivate env;
     jint res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallIntMethodV(d->m_jobject, id, args);
     }
@@ -578,7 +603,7 @@ jlong QJNIObjectPrivate::callMethodV<jlong>(const char *methodName, const char *
 {
     QJNIEnvironmentPrivate env;
     jlong res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallLongMethodV(d->m_jobject, id, args);
     }
@@ -600,7 +625,7 @@ jfloat QJNIObjectPrivate::callMethodV<jfloat>(const char *methodName, const char
 {
     QJNIEnvironmentPrivate env;
     jfloat res = 0.f;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallFloatMethodV(d->m_jobject, id, args);
     }
@@ -622,7 +647,7 @@ jdouble QJNIObjectPrivate::callMethodV<jdouble>(const char *methodName, const ch
 {
     QJNIEnvironmentPrivate env;
     jdouble res = 0.;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallDoubleMethodV(d->m_jobject, id, args);
     }
@@ -702,7 +727,7 @@ void QJNIObjectPrivate::callStaticMethodV<void>(const char *className,
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             env->CallStaticVoidMethodV(clazz, id, args);
         }
@@ -728,7 +753,7 @@ void QJNIObjectPrivate::callStaticMethodV<void>(jclass clazz,
                                                 va_list args)
 {
     QJNIEnvironmentPrivate env;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         env->CallStaticVoidMethodV(clazz, id, args);
     }
@@ -756,7 +781,7 @@ jboolean QJNIObjectPrivate::callStaticMethodV<jboolean>(const char *className,
     jboolean res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticBooleanMethodV(clazz, id, args);
         }
@@ -786,7 +811,7 @@ jboolean QJNIObjectPrivate::callStaticMethodV<jboolean>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jboolean res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticBooleanMethodV(clazz, id, args);
     }
@@ -817,7 +842,7 @@ jbyte QJNIObjectPrivate::callStaticMethodV<jbyte>(const char *className,
     jbyte res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticByteMethodV(clazz, id, args);
         }
@@ -847,7 +872,7 @@ jbyte QJNIObjectPrivate::callStaticMethodV<jbyte>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jbyte res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticByteMethodV(clazz, id, args);
     }
@@ -878,7 +903,7 @@ jchar QJNIObjectPrivate::callStaticMethodV<jchar>(const char *className,
     jchar res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticCharMethodV(clazz, id, args);
         }
@@ -908,7 +933,7 @@ jchar QJNIObjectPrivate::callStaticMethodV<jchar>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jchar res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticCharMethodV(clazz, id, args);
     }
@@ -939,7 +964,7 @@ jshort QJNIObjectPrivate::callStaticMethodV<jshort>(const char *className,
     jshort res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticShortMethodV(clazz, id, args);
         }
@@ -969,7 +994,7 @@ jshort QJNIObjectPrivate::callStaticMethodV<jshort>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jshort res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticShortMethodV(clazz, id, args);
     }
@@ -1000,7 +1025,7 @@ jint QJNIObjectPrivate::callStaticMethodV<jint>(const char *className,
     jint res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticIntMethodV(clazz, id, args);
         }
@@ -1030,7 +1055,7 @@ jint QJNIObjectPrivate::callStaticMethodV<jint>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jint res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticIntMethodV(clazz, id, args);
     }
@@ -1061,7 +1086,7 @@ jlong QJNIObjectPrivate::callStaticMethodV<jlong>(const char *className,
     jlong res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticLongMethodV(clazz, id, args);
         }
@@ -1091,7 +1116,7 @@ jlong QJNIObjectPrivate::callStaticMethodV<jlong>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jlong res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticLongMethodV(clazz, id, args);
     }
@@ -1122,7 +1147,7 @@ jfloat QJNIObjectPrivate::callStaticMethodV<jfloat>(const char *className,
     jfloat res = 0.f;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticFloatMethodV(clazz, id, args);
         }
@@ -1152,7 +1177,7 @@ jfloat QJNIObjectPrivate::callStaticMethodV<jfloat>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jfloat res = 0.f;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticFloatMethodV(clazz, id, args);
     }
@@ -1183,7 +1208,7 @@ jdouble QJNIObjectPrivate::callStaticMethodV<jdouble>(const char *className,
     jdouble res = 0.;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticDoubleMethodV(clazz, id, args);
         }
@@ -1213,7 +1238,7 @@ jdouble QJNIObjectPrivate::callStaticMethodV<jdouble>(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jdouble res = 0.;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticDoubleMethodV(clazz, id, args);
     }
@@ -1348,7 +1373,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethodV(const char *methodName,
 {
     QJNIEnvironmentPrivate env;
     jobject res = 0;
-    jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig);
+    jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig);
     if (id) {
         res = env->CallObjectMethodV(d->m_jobject, id, args);
         if (res && env->ExceptionCheck())
@@ -1428,7 +1453,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(const char *classNa
     jobject res = 0;
     jclass clazz = loadClass(className, env);
     if (clazz) {
-        jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+        jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true);
         if (id) {
             res = env->CallStaticObjectMethodV(clazz, id, args);
             if (res && env->ExceptionCheck())
@@ -1460,7 +1485,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jobject res = 0;
-    jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true);
+    jmethodID id = getMethodID(env, clazz, methodName, sig, true);
     if (id) {
         res = env->CallStaticObjectMethodV(clazz, id, args);
         if (res && env->ExceptionCheck())
@@ -1489,7 +1514,7 @@ jboolean QJNIObjectPrivate::getField<jboolean>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jboolean res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Z");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z");
     if (id)
         res = env->GetBooleanField(d->m_jobject, id);
 
@@ -1501,7 +1526,7 @@ jbyte QJNIObjectPrivate::getField<jbyte>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jbyte res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "B");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B");
     if (id)
         res = env->GetByteField(d->m_jobject, id);
 
@@ -1513,7 +1538,7 @@ jchar QJNIObjectPrivate::getField<jchar>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jchar res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "C");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C");
     if (id)
         res = env->GetCharField(d->m_jobject, id);
 
@@ -1525,7 +1550,7 @@ jshort QJNIObjectPrivate::getField<jshort>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jshort res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "S");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S");
     if (id)
         res = env->GetShortField(d->m_jobject, id);
 
@@ -1537,7 +1562,7 @@ jint QJNIObjectPrivate::getField<jint>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jint res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "I");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I");
     if (id)
         res = env->GetIntField(d->m_jobject, id);
 
@@ -1549,7 +1574,7 @@ jlong QJNIObjectPrivate::getField<jlong>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jlong res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "J");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J");
     if (id)
         res = env->GetLongField(d->m_jobject, id);
 
@@ -1561,7 +1586,7 @@ jfloat QJNIObjectPrivate::getField<jfloat>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jfloat res = 0.f;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "F");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F");
     if (id)
         res = env->GetFloatField(d->m_jobject, id);
 
@@ -1573,7 +1598,7 @@ jdouble QJNIObjectPrivate::getField<jdouble>(const char *fieldName) const
 {
     QJNIEnvironmentPrivate env;
     jdouble res = 0.;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "D");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D");
     if (id)
         res = env->GetDoubleField(d->m_jobject, id);
 
@@ -1585,7 +1610,7 @@ jboolean QJNIObjectPrivate::getStaticField<jboolean>(jclass clazz, const char *f
 {
     QJNIEnvironmentPrivate env;
     jboolean res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "Z", true);
     if (id)
         res = env->GetStaticBooleanField(clazz, id);
 
@@ -1596,12 +1621,15 @@ template <>
 jboolean QJNIObjectPrivate::getStaticField<jboolean>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jboolean res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jboolean>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "Z", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticBooleanField(clazz, id);
 }
 
 template <>
@@ -1609,7 +1637,7 @@ jbyte QJNIObjectPrivate::getStaticField<jbyte>(jclass clazz, const char *fieldNa
 {
     QJNIEnvironmentPrivate env;
     jbyte res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "B", true);
     if (id)
         res = env->GetStaticByteField(clazz, id);
 
@@ -1620,12 +1648,15 @@ template <>
 jbyte QJNIObjectPrivate::getStaticField<jbyte>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jbyte res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jbyte>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "B", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticByteField(clazz, id);
 }
 
 template <>
@@ -1633,7 +1664,7 @@ jchar QJNIObjectPrivate::getStaticField<jchar>(jclass clazz, const char *fieldNa
 {
     QJNIEnvironmentPrivate env;
     jchar res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "C", true);
     if (id)
         res = env->GetStaticCharField(clazz, id);
 
@@ -1644,12 +1675,15 @@ template <>
 jchar QJNIObjectPrivate::getStaticField<jchar>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jchar res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jchar>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "C", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticCharField(clazz, id);
 }
 
 template <>
@@ -1657,7 +1691,7 @@ jshort QJNIObjectPrivate::getStaticField<jshort>(jclass clazz, const char *field
 {
     QJNIEnvironmentPrivate env;
     jshort res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "S", true);
     if (id)
         res = env->GetStaticShortField(clazz, id);
 
@@ -1668,12 +1702,15 @@ template <>
 jshort QJNIObjectPrivate::getStaticField<jshort>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jshort res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jshort>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "S", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticShortField(clazz, id);
 }
 
 template <>
@@ -1681,7 +1718,7 @@ jint QJNIObjectPrivate::getStaticField<jint>(jclass clazz, const char *fieldName
 {
     QJNIEnvironmentPrivate env;
     jint res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "I", true);
     if (id)
         res = env->GetStaticIntField(clazz, id);
 
@@ -1692,12 +1729,15 @@ template <>
 jint QJNIObjectPrivate::getStaticField<jint>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jint res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jint>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "I", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticIntField(clazz, id);
 }
 
 template <>
@@ -1705,7 +1745,7 @@ jlong QJNIObjectPrivate::getStaticField<jlong>(jclass clazz, const char *fieldNa
 {
     QJNIEnvironmentPrivate env;
     jlong res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "J", true);
     if (id)
         res = env->GetStaticLongField(clazz, id);
 
@@ -1716,12 +1756,15 @@ template <>
 jlong QJNIObjectPrivate::getStaticField<jlong>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jlong res = 0;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jlong>(clazz, fieldName);
+    if (clazz == 0)
+        return 0;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "J", true);
+    if (id == 0)
+        return 0;
+
+    return env->GetStaticLongField(clazz, id);
 }
 
 template <>
@@ -1729,7 +1772,7 @@ jfloat QJNIObjectPrivate::getStaticField<jfloat>(jclass clazz, const char *field
 {
     QJNIEnvironmentPrivate env;
     jfloat res = 0.f;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "F", true);
     if (id)
         res = env->GetStaticFloatField(clazz, id);
 
@@ -1740,12 +1783,15 @@ template <>
 jfloat QJNIObjectPrivate::getStaticField<jfloat>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jfloat res = 0.f;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jfloat>(clazz, fieldName);
+    if (clazz == 0)
+        return 0.f;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "F", true);
+    if (id == 0)
+        return 0.f;
+
+    return env->GetStaticFloatField(clazz, id);
 }
 
 template <>
@@ -1753,7 +1799,7 @@ jdouble QJNIObjectPrivate::getStaticField<jdouble>(jclass clazz, const char *fie
 {
     QJNIEnvironmentPrivate env;
     jdouble res = 0.;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "D", true);
     if (id)
         res = env->GetStaticDoubleField(clazz, id);
 
@@ -1764,12 +1810,15 @@ template <>
 jdouble QJNIObjectPrivate::getStaticField<jdouble>(const char *className, const char *fieldName)
 {
     QJNIEnvironmentPrivate env;
-    jdouble res = 0.;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticField<jdouble>(clazz, fieldName);
+    if (clazz == 0)
+        return 0.;
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "D", true);
+    if (id == 0)
+        return 0.;
+
+    return env->GetStaticDoubleField(clazz, id);
 }
 
 QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName,
@@ -1777,7 +1826,7 @@ QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName,
 {
     QJNIEnvironmentPrivate env;
     jobject res = 0;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig);
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
     if (id) {
         res = env->GetObjectField(d->m_jobject, id);
         if (res && env->ExceptionCheck())
@@ -1794,12 +1843,21 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(const char *className,
                                                           const char *sig)
 {
     QJNIEnvironmentPrivate env;
-    QJNIObjectPrivate res;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        res = getStaticObjectField(clazz, fieldName, sig);
+    if (clazz == 0)
+        return QJNIObjectPrivate();
 
-    return res;
+    jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, sig, true);
+    if (id == 0)
+        return QJNIObjectPrivate();
+
+    jobject res = env->GetStaticObjectField(clazz, id);
+    if (res && env->ExceptionCheck())
+        res = 0;
+
+    QJNIObjectPrivate obj(res);
+    env->DeleteLocalRef(res);
+    return obj;
 }
 
 QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz,
@@ -1808,7 +1866,7 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz,
 {
     QJNIEnvironmentPrivate env;
     jobject res = 0;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true);
+    jfieldID id = getFieldID(env, clazz, fieldName, sig, true);
     if (id) {
         res = env->GetStaticObjectField(clazz, id);
         if (res && env->ExceptionCheck())
@@ -1824,7 +1882,7 @@ template <>
 void QJNIObjectPrivate::setField<jboolean>(const char *fieldName, jboolean value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Z");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z");
     if (id)
         env->SetBooleanField(d->m_jobject, id, value);
 
@@ -1834,7 +1892,7 @@ template <>
 void QJNIObjectPrivate::setField<jbyte>(const char *fieldName, jbyte value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "B");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B");
     if (id)
         env->SetByteField(d->m_jobject, id, value);
 
@@ -1844,7 +1902,7 @@ template <>
 void QJNIObjectPrivate::setField<jchar>(const char *fieldName, jchar value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "C");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C");
     if (id)
         env->SetCharField(d->m_jobject, id, value);
 
@@ -1854,7 +1912,7 @@ template <>
 void QJNIObjectPrivate::setField<jshort>(const char *fieldName, jshort value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "S");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S");
     if (id)
         env->SetShortField(d->m_jobject, id, value);
 
@@ -1864,7 +1922,7 @@ template <>
 void QJNIObjectPrivate::setField<jint>(const char *fieldName, jint value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "I");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I");
     if (id)
         env->SetIntField(d->m_jobject, id, value);
 
@@ -1874,7 +1932,7 @@ template <>
 void QJNIObjectPrivate::setField<jlong>(const char *fieldName, jlong value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "J");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J");
     if (id)
         env->SetLongField(d->m_jobject, id, value);
 
@@ -1884,7 +1942,7 @@ template <>
 void QJNIObjectPrivate::setField<jfloat>(const char *fieldName, jfloat value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "F");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F");
     if (id)
         env->SetFloatField(d->m_jobject, id, value);
 
@@ -1894,7 +1952,7 @@ template <>
 void QJNIObjectPrivate::setField<jdouble>(const char *fieldName, jdouble value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "D");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D");
     if (id)
         env->SetDoubleField(d->m_jobject, id, value);
 
@@ -1904,7 +1962,7 @@ template <>
 void QJNIObjectPrivate::setField<jbooleanArray>(const char *fieldName, jbooleanArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[Z");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[Z");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1914,7 +1972,7 @@ template <>
 void QJNIObjectPrivate::setField<jbyteArray>(const char *fieldName, jbyteArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[B");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[B");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1924,7 +1982,7 @@ template <>
 void QJNIObjectPrivate::setField<jcharArray>(const char *fieldName, jcharArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[C");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[C");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1934,7 +1992,7 @@ template <>
 void QJNIObjectPrivate::setField<jshortArray>(const char *fieldName, jshortArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[S");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[S");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1944,7 +2002,7 @@ template <>
 void QJNIObjectPrivate::setField<jintArray>(const char *fieldName, jintArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[I");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[I");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1954,7 +2012,7 @@ template <>
 void QJNIObjectPrivate::setField<jlongArray>(const char *fieldName, jlongArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[J");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[J");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1964,7 +2022,7 @@ template <>
 void QJNIObjectPrivate::setField<jfloatArray>(const char *fieldName, jfloatArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[F");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[F");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1974,7 +2032,7 @@ template <>
 void QJNIObjectPrivate::setField<jdoubleArray>(const char *fieldName, jdoubleArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[D");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[D");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1984,7 +2042,7 @@ template <>
 void QJNIObjectPrivate::setField<jstring>(const char *fieldName, jstring value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Ljava/lang/String;");
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Ljava/lang/String;");
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -1996,7 +2054,7 @@ void QJNIObjectPrivate::setField<jobject>(const char *fieldName,
                                           jobject value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig);
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -2008,7 +2066,7 @@ void QJNIObjectPrivate::setField<jobjectArray>(const char *fieldName,
                                                jobjectArray value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig);
+    jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig);
     if (id)
         env->SetObjectField(d->m_jobject, id, value);
 
@@ -2020,7 +2078,7 @@ void QJNIObjectPrivate::setStaticField<jboolean>(jclass clazz,
                                                  jboolean value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "Z", true);
     if (id)
         env->SetStaticBooleanField(clazz, id, value);
 }
@@ -2032,8 +2090,14 @@ void QJNIObjectPrivate::setStaticField<jboolean>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jboolean>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "Z", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticBooleanField(clazz, id, value);
 }
 
 template <>
@@ -2042,7 +2106,7 @@ void QJNIObjectPrivate::setStaticField<jbyte>(jclass clazz,
                                               jbyte value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "B", true);
     if (id)
         env->SetStaticByteField(clazz, id, value);
 }
@@ -2054,8 +2118,14 @@ void QJNIObjectPrivate::setStaticField<jbyte>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jbyte>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "B", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticByteField(clazz, id, value);
 }
 
 template <>
@@ -2064,7 +2134,7 @@ void QJNIObjectPrivate::setStaticField<jchar>(jclass clazz,
                                               jchar value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "C", true);
     if (id)
         env->SetStaticCharField(clazz, id, value);
 }
@@ -2076,8 +2146,14 @@ void QJNIObjectPrivate::setStaticField<jchar>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jchar>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "C", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticCharField(clazz, id, value);
 }
 
 template <>
@@ -2086,7 +2162,7 @@ void QJNIObjectPrivate::setStaticField<jshort>(jclass clazz,
                                                jshort value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "S", true);
     if (id)
         env->SetStaticShortField(clazz, id, value);
 }
@@ -2098,8 +2174,14 @@ void QJNIObjectPrivate::setStaticField<jshort>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jshort>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "S", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticShortField(clazz, id, value);
 }
 
 template <>
@@ -2108,7 +2190,7 @@ void QJNIObjectPrivate::setStaticField<jint>(jclass clazz,
                                              jint value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "I", true);
     if (id)
         env->SetStaticIntField(clazz, id, value);
 }
@@ -2120,8 +2202,14 @@ void QJNIObjectPrivate::setStaticField<jint>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jint>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "I", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticIntField(clazz, id, value);
 }
 
 template <>
@@ -2130,7 +2218,7 @@ void QJNIObjectPrivate::setStaticField<jlong>(jclass clazz,
                                               jlong value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "J", true);
     if (id)
         env->SetStaticLongField(clazz, id, value);
 }
@@ -2142,8 +2230,14 @@ void QJNIObjectPrivate::setStaticField<jlong>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jlong>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "J", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticLongField(clazz, id, value);
 }
 
 template <>
@@ -2152,7 +2246,7 @@ void QJNIObjectPrivate::setStaticField<jfloat>(jclass clazz,
                                                jfloat value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "F", true);
     if (id)
         env->SetStaticFloatField(clazz, id, value);
 }
@@ -2164,8 +2258,14 @@ void QJNIObjectPrivate::setStaticField<jfloat>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jfloat>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "F", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticFloatField(clazz, id, value);
 }
 
 template <>
@@ -2174,7 +2274,7 @@ void QJNIObjectPrivate::setStaticField<jdouble>(jclass clazz,
                                                 jdouble value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true);
+    jfieldID id = getFieldID(env, clazz, fieldName, "D", true);
     if (id)
         env->SetStaticDoubleField(clazz, id, value);
 }
@@ -2186,8 +2286,14 @@ void QJNIObjectPrivate::setStaticField<jdouble>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jdouble>(clazz, fieldName, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "D", true);
+    if (id == 0)
+        return;
+
+    env->SetStaticDoubleField(clazz, id, value);
 }
 
 template <>
@@ -2197,7 +2303,7 @@ void QJNIObjectPrivate::setStaticField<jobject>(jclass clazz,
                                                 jobject value)
 {
     QJNIEnvironmentPrivate env;
-    jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true);
+    jfieldID id = getFieldID(env, clazz, fieldName, sig, true);
     if (id)
         env->SetStaticObjectField(clazz, id, value);
 }
@@ -2210,8 +2316,14 @@ void QJNIObjectPrivate::setStaticField<jobject>(const char *className,
 {
     QJNIEnvironmentPrivate env;
     jclass clazz = loadClass(className, env);
-    if (clazz)
-        setStaticField<jobject>(clazz, fieldName, sig, value);
+    if (clazz == 0)
+        return;
+
+    jfieldID id = getCachedFieldID(env, clazz, className, fieldName, sig, true);
+    if (id == 0)
+        return;
+
+    env->SetStaticObjectField(clazz, id, value);
 }
 
 QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string)
diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h
index ae9c7c3a7ed1ef15ebfc34b4fd6de0337f06bc88..1c23f2ab76865be3dc8930b8a9a1a202cd150a9b 100644
--- a/src/corelib/kernel/qjni_p.h
+++ b/src/corelib/kernel/qjni_p.h
@@ -82,6 +82,7 @@ public:
     jobject m_jobject;
     jclass m_jclass;
     bool m_own_jclass;
+    QByteArray m_className;
 };
 
 class Q_CORE_EXPORT QJNIObjectPrivate
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 1e2a860d8c23b5aaaad7fc0768927e181be8ed26..1b214e9f74830c766b798b8099689a52386ee482 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1357,12 +1357,16 @@ namespace QtPrivate
         enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(yes_type) };
     };
 
+    template<typename T, typename Enable = void>
+    struct IsGadgetHelper { enum { Value = false }; };
+
     template<typename T>
-    struct IsGadgetHelper
+    struct IsGadgetHelper<T, typename T::QtGadgetHelper>
     {
-        template<typename X> static typename X::QtGadgetHelper *checkType(X*);
-        static char checkType(void*);
-        enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(void*)  };
+        template <typename X>
+        static char checkType(void (X::*)());
+        static void *checkType(void (T::*)());
+        enum { Value =  sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
     };
 
 
@@ -1381,6 +1385,7 @@ QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args")
         // qt_getEnumMetaObject(T) which returns 'char'
         enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
     };
+    template<> struct IsQEnumHelper<void> { enum { Value = false }; };
 QT_WARNING_POP
 
     template<typename T, typename Enable = void>
@@ -1768,7 +1773,7 @@ template <typename T>
 struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
 {
     enum {
-        Defined = 1
+        Defined = QtPrivate::is_default_constructible<T>::value
     };
 
     static int qt_metatype_id()
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index fb4c5cceb9c670d5eb4ecacd7b17aeceb2260d0d..3ca9c890e8c765bb8400a1b3acd7443eaec7e106 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -65,6 +65,16 @@ QT_BEGIN_NAMESPACE
 
 static int DIRECT_CONNECTION_ONLY = 0;
 
+
+QDynamicMetaObjectData::~QDynamicMetaObjectData()
+{
+}
+
+QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
+{
+}
+
+
 struct QSlotObjectBaseDeleter { // for use with QScopedPointer<QSlotObjectBase,...>
     static void cleanup(QtPrivate::QSlotObjectBase *slot) {
         if (slot) slot->destroyIfLastRef();
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 1b64103e40c5a72eee4f0d234670d0ec8aea0d10..bd5ee006bf160bda58163e480951bcbeda7f3f35 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -406,7 +406,7 @@ void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
 struct QAbstractDynamicMetaObject;
 struct Q_CORE_EXPORT QDynamicMetaObjectData
 {
-    virtual ~QDynamicMetaObjectData() {}
+    virtual ~QDynamicMetaObjectData();
     virtual void objectDestroyed(QObject *) { delete this; }
 
     virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0;
@@ -415,6 +415,8 @@ struct Q_CORE_EXPORT QDynamicMetaObjectData
 
 struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject
 {
+    ~QAbstractDynamicMetaObject();
+
     virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) Q_DECL_OVERRIDE { return this; }
     virtual int createProperty(const char *, const char *) { return -1; }
     virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) Q_DECL_OVERRIDE
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 31e8a670e9c3b1ed2fff1686f6261ad50ed69591..4d0126490690703d595f50f2242a3f4f2319cd8b 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -172,6 +172,7 @@ private: \
 #define Q_GADGET \
 public: \
     static const QMetaObject staticMetaObject; \
+    void qt_check_for_QGADGET_macro(); \
     typedef void QtGadgetHelper; \
 private: \
     Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index 4d37368b2eaf92ea11cbb6c21dfb8f02ddff56b7..5cc54b1def0e90608a86894640437079c12ce214 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -163,6 +163,7 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
 #if defined(Q_OS_WINPHONE)
     Q_UNIMPLEMENTED();
     Q_UNUSED(mode)
+    Q_UNUSED(permissions)
     memory = 0;
 #elif defined(Q_OS_WINRT)
     memory = (void *)MapViewOfFileFromApp(handle(), permissions, 0, 0);
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index 19d84c2b3e55d604ae80ef00b92389035bbece4c..e333104add8993dd54457ca123bd7fd60ad7fd88 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -145,7 +145,7 @@ static QString standardLibraryErrorString(int errorCode)
     return ret.trimmed();
 }
 
-QString QSystemError::toString()
+QString QSystemError::toString() const
 {
     switch(errorScope) {
     case NativeError:
diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h
index e7efb9bbf3da19e8b7d5d4dea0525a60b97bdd38..29e9e440e4309fe669aad95b650793f50782cd98 100644
--- a/src/corelib/kernel/qsystemerror_p.h
+++ b/src/corelib/kernel/qsystemerror_p.h
@@ -62,9 +62,9 @@ public:
     inline QSystemError(int error, ErrorScope scope);
     inline QSystemError();
 
-    QString toString();
-    inline ErrorScope scope();
-    inline int error();
+    QString toString() const;
+    inline ErrorScope scope() const;
+    inline int error() const;
 
     //data members
     int errorCode;
@@ -83,12 +83,12 @@ QSystemError::QSystemError()
 
 }
 
-QSystemError::ErrorScope QSystemError::scope()
+QSystemError::ErrorScope QSystemError::scope() const
 {
     return errorScope;
 }
 
-int QSystemError::error()
+int QSystemError::error() const
 {
     return errorCode;
 }
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index ed856a538ce81ddabc4e60fe03d555e26c480e0d..3206ff66e3b6704a7a1d3e14153d1a8b854aab5e 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -54,12 +54,12 @@ QMimeTypePrivate::QMimeTypePrivate()
 {}
 
 QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
-        : name(other.d->name),
+      : loaded(other.d->loaded),
+        name(other.d->name),
         localeComments(other.d->localeComments),
         genericIconName(other.d->genericIconName),
         iconName(other.d->iconName),
-        globPatterns(other.d->globPatterns),
-        loaded(other.d->loaded)
+        globPatterns(other.d->globPatterns)
 {}
 
 void QMimeTypePrivate::clear()
diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h
index bf533bbcb0fa360d467e39d1209606be30415af5..2161dd89011d7a05f29ea2d3e28d1cec2175bc8e 100644
--- a/src/corelib/mimetypes/qmimetype_p.h
+++ b/src/corelib/mimetypes/qmimetype_p.h
@@ -66,12 +66,12 @@ public:
 
     void addGlobPattern(const QString &pattern);
 
+    bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first
     QString name;
     LocaleHash localeComments;
     QString genericIconName;
     QString iconName;
     QStringList globPatterns;
-    bool loaded;
 };
 
 QT_END_NAMESPACE
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
index 338b3d0972944ba7970c36e2299083b366fcd40b..8b64f934676ec1c91a3896339221278ded5cea26 100644
--- a/src/corelib/plugin/plugin.pri
+++ b/src/corelib/plugin/plugin.pri
@@ -13,6 +13,7 @@ HEADERS += \
         plugin/qmachparser_p.h
 
 SOURCES += \
+	plugin/qfactoryinterface.cpp \
 	plugin/qpluginloader.cpp \
 	plugin/qfactoryloader.cpp \
 	plugin/quuid.cpp \
diff --git a/tests/auto/tools/qmake/testdata/functions/1.cpp b/src/corelib/plugin/qfactoryinterface.cpp
similarity index 87%
rename from tests/auto/tools/qmake/testdata/functions/1.cpp
rename to src/corelib/plugin/qfactoryinterface.cpp
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0307d583153711b6a268e049e722b62608dd439b 100644
--- a/tests/auto/tools/qmake/testdata/functions/1.cpp
+++ b/src/corelib/plugin/qfactoryinterface.cpp
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -30,3 +30,14 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
+
+#include "qfactoryinterface.h"
+
+QT_BEGIN_NAMESPACE
+
+QFactoryInterface::~QFactoryInterface()
+{
+    // must be empty until ### Qt 6
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h
index e20864cd31a2c71c8572322ef57e8164373278a2..86a46fabfa90a17fd8a373e15801fb579158b1b5 100644
--- a/src/corelib/plugin/qfactoryinterface.h
+++ b/src/corelib/plugin/qfactoryinterface.h
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
 
 struct Q_CORE_EXPORT QFactoryInterface
 {
-    virtual ~QFactoryInterface() {}
+    virtual ~QFactoryInterface();
     virtual QStringList keys() const = 0;
 };
 
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index f128acd54e9926ecf09579b52564da5c0f2bfb65..81b38ea4c44c19b634338627ee9307a74602283d 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -101,7 +101,35 @@ QT_BEGIN_NAMESPACE
     parallel group state.
 */
 
+/*!
+    \property QAbstractTransition::transitionType
+
+    \brief indicates whether this transition is an internal transition, or an external transition.
+
+    Internal and external transitions behave the same, except for the case of a transition whose
+    source state is a compound state and whose target(s) is a descendant of the source. In such a
+    case, an internal transition will not exit and re-enter its source state, while an external one
+    will.
+
+    By default, the type is an external transition.
+*/
+
+/*!
+  \enum QAbstractTransition::TransitionType
+
+  This enum specifies the kind of transition. By default, the type is an external transition.
+
+  \value ExternalTransition Any state that is the source state of a transition (which is not a
+                            target-less transition) is left, and re-entered when necessary.
+  \value InternalTransition If the target state of a transition is a sub-state of a compound state,
+                            and that compound state is the source state, an internal transition will
+                            not leave the source state.
+
+  \sa QAbstractTransition::transitionType
+*/
+
 QAbstractTransitionPrivate::QAbstractTransitionPrivate()
+    : transitionType(QAbstractTransition::ExternalTransition)
 {
 }
 
@@ -248,6 +276,24 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
         emit targetStatesChanged(QPrivateSignal());
 }
 
+/*!
+  Returns the type of the transition.
+*/
+QAbstractTransition::TransitionType QAbstractTransition::transitionType() const
+{
+    Q_D(const QAbstractTransition);
+    return d->transitionType;
+}
+
+/*!
+  Sets the type of the transition to \a type.
+*/
+void QAbstractTransition::setTransitionType(TransitionType type)
+{
+    Q_D(QAbstractTransition);
+    d->transitionType = type;
+}
+
 /*!
   Returns the state machine that this transition is part of, or 0 if the
   transition is not part of a state machine.
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index 768a364a4b14c733d4203b399090f3a463ca85bf..bf32b3e825fc783628101d8cf34422a94d9a4d00 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -59,7 +59,14 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject
     Q_PROPERTY(QState* sourceState READ sourceState)
     Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged)
     Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged)
+    Q_PROPERTY(TransitionType transitionType READ transitionType WRITE setTransitionType)
 public:
+    enum TransitionType {
+        ExternalTransition,
+        InternalTransition
+    };
+    Q_ENUM(TransitionType)
+
     QAbstractTransition(QState *sourceState = 0);
     virtual ~QAbstractTransition();
 
@@ -69,6 +76,9 @@ public:
     QList<QAbstractState*> targetStates() const;
     void setTargetStates(const QList<QAbstractState*> &targets);
 
+    TransitionType transitionType() const;
+    void setTransitionType(TransitionType type);
+
     QStateMachine *machine() const;
 
 #ifndef QT_NO_ANIMATION
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
index d89d057497ba352f3bcaf8a99bcb2063d2a75ab2..4b0644acd99ca7516fad2e9bb32224ec38a9f315 100644
--- a/src/corelib/statemachine/qabstracttransition_p.h
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -73,6 +73,7 @@ public:
     void emitTriggered();
 
     QList<QPointer<QAbstractState> > targetStates;
+    QAbstractTransition::TransitionType transitionType;
 
 #ifndef QT_NO_ANIMATION
     QList<QAbstractAnimation*> animations;
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
index 096d667bc326b1234d26af596af49db29d3825de..c10127fa6896b7aa4c1e933e057befb25e632184 100644
--- a/src/corelib/statemachine/qeventtransition.cpp
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -102,6 +102,10 @@ QEventTransitionPrivate::QEventTransitionPrivate()
     registered = false;
 }
 
+QEventTransitionPrivate::~QEventTransitionPrivate()
+{
+}
+
 QEventTransitionPrivate *QEventTransitionPrivate::get(QEventTransition *q)
 {
     return q->d_func();
diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h
index 64ab94518728325e24a1b895cbf04d2afc13fccb..3e430d86a98b72dc4fe9301b36906f72cec7f426 100644
--- a/src/corelib/statemachine/qeventtransition_p.h
+++ b/src/corelib/statemachine/qeventtransition_p.h
@@ -55,14 +55,15 @@ class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate
     Q_DECLARE_PUBLIC(QEventTransition)
 public:
     QEventTransitionPrivate();
+    ~QEventTransitionPrivate();
 
     static QEventTransitionPrivate *get(QEventTransition *q);
 
     void unregister();
     void maybeRegister();
 
-    bool registered;
     QObject *object;
+    bool registered;
     QEvent::Type eventType;
 };
 
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
index 28bb176b56397d79d50740dd153bad15a3d6382c..2ce0c13522d757bab198f43f22a979e1da2a6c51 100644
--- a/src/corelib/statemachine/qstate_p.h
+++ b/src/corelib/statemachine/qstate_p.h
@@ -103,8 +103,8 @@ public:
     QAbstractState *initialState;
     QState::ChildMode childMode;
     mutable bool childStatesListNeedsRefresh;
-    mutable QList<QAbstractState*> childStatesList;
     mutable bool transitionsListNeedsRefresh;
+    mutable QList<QAbstractState*> childStatesList;
     mutable QList<QAbstractTransition*> transitionsList;
 
 #ifndef QT_NO_PROPERTIES
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 3d2da77390cbd132be7429b3a9b39c2eb7093c95..3a1a852ef5f4837af7a8de78b0a0ca7d6d7fc50f 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -177,6 +177,100 @@ QT_BEGIN_NAMESPACE
 // #define QSTATEMACHINE_DEBUG
 // #define QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
 
+struct CalculationCache {
+    struct TransitionInfo {
+        QList<QAbstractState*> effectiveTargetStates;
+        QSet<QAbstractState*> exitSet;
+        QAbstractState *transitionDomain;
+
+        bool effectiveTargetStatesIsKnown: 1;
+        bool exitSetIsKnown              : 1;
+        bool transitionDomainIsKnown     : 1;
+
+        TransitionInfo()
+            : transitionDomain(0)
+            , effectiveTargetStatesIsKnown(false)
+            , exitSetIsKnown(false)
+            , transitionDomainIsKnown(false)
+        {}
+    };
+
+    typedef QHash<QAbstractTransition *, TransitionInfo> TransitionInfoCache;
+    TransitionInfoCache cache;
+
+    bool effectiveTargetStates(QAbstractTransition *t, QList<QAbstractState *> *targets) const
+    {
+        Q_ASSERT(targets);
+
+        TransitionInfoCache::const_iterator cacheIt = cache.find(t);
+        if (cacheIt == cache.end() || !cacheIt->effectiveTargetStatesIsKnown)
+            return false;
+
+        *targets = cacheIt->effectiveTargetStates;
+        return true;
+    }
+
+    void insert(QAbstractTransition *t, const QList<QAbstractState *> &targets)
+    {
+        TransitionInfoCache::iterator cacheIt = cache.find(t);
+        TransitionInfo &ti = cacheIt == cache.end()
+                ? *cache.insert(t, TransitionInfo())
+                : *cacheIt;
+
+        Q_ASSERT(!ti.effectiveTargetStatesIsKnown);
+        ti.effectiveTargetStates = targets;
+        ti.effectiveTargetStatesIsKnown = true;
+    }
+
+    bool exitSet(QAbstractTransition *t, QSet<QAbstractState *> *exits) const
+    {
+        Q_ASSERT(exits);
+
+        TransitionInfoCache::const_iterator cacheIt = cache.find(t);
+        if (cacheIt == cache.end() || !cacheIt->exitSetIsKnown)
+            return false;
+
+        *exits = cacheIt->exitSet;
+        return true;
+    }
+
+    void insert(QAbstractTransition *t, const QSet<QAbstractState *> &exits)
+    {
+        TransitionInfoCache::iterator cacheIt = cache.find(t);
+        TransitionInfo &ti = cacheIt == cache.end()
+                ? *cache.insert(t, TransitionInfo())
+                : *cacheIt;
+
+        Q_ASSERT(!ti.exitSetIsKnown);
+        ti.exitSet = exits;
+        ti.exitSetIsKnown = true;
+    }
+
+    bool transitionDomain(QAbstractTransition *t, QAbstractState **domain) const
+    {
+        Q_ASSERT(domain);
+
+        TransitionInfoCache::const_iterator cacheIt = cache.find(t);
+        if (cacheIt == cache.end() || !cacheIt->transitionDomainIsKnown)
+            return false;
+
+        *domain = cacheIt->transitionDomain;
+        return true;
+    }
+
+    void insert(QAbstractTransition *t, QAbstractState *domain)
+    {
+        TransitionInfoCache::iterator cacheIt = cache.find(t);
+        TransitionInfo &ti = cacheIt == cache.end()
+                ? *cache.insert(t, TransitionInfo())
+                : *cacheIt;
+
+        Q_ASSERT(!ti.transitionDomainIsKnown);
+        ti.transitionDomain = domain;
+        ti.transitionDomainIsKnown = true;
+    }
+};
+
 /* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
 
 function isDescendant(state1, state2)
@@ -205,6 +299,17 @@ static bool containsDecendantOf(const QSet<QAbstractState *> &states, const QAbs
     return false;
 }
 
+static int descendantDepth(const QAbstractState *state, const QAbstractState *ancestor)
+{
+    int depth = 0;
+    for (const QAbstractState *it = state; it != 0; it = it->parentState()) {
+        if (it == ancestor)
+            break;
+        ++depth;
+    }
+    return depth;
+}
+
 /* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
 
 function getProperAncestors(state1, state2)
@@ -245,8 +350,14 @@ function getEffectiveTargetStates(transition)
             targets.add(s)
     return targets
 */
-static QSet<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *transition)
+static QList<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *transition, CalculationCache *cache)
 {
+    Q_ASSERT(cache);
+
+    QList<QAbstractState *> targetsList;
+    if (cache->effectiveTargetStates(transition, &targetsList))
+        return targetsList;
+
     QSet<QAbstractState *> targets;
     foreach (QAbstractState *s, transition->targetStates()) {
         if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) {
@@ -266,7 +377,10 @@ static QSet<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *tran
             targets.insert(s);
         }
     }
-    return targets;
+
+    targetsList = targets.toList();
+    cache->insert(transition, targetsList);
+    return targetsList;
 }
 
 template <class T>
@@ -348,10 +462,25 @@ static int indexOfDescendant(QState *s, QAbstractState *desc)
 bool QStateMachinePrivate::transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2)
 {
     QState *s1 = t1->sourceState(), *s2 = t2->sourceState();
-    if (s1 == s2)
-        return QStatePrivate::get(s1)->transitions().indexOf(t1) < QStatePrivate::get(s2)->transitions().indexOf(t2);
-    else
-        return stateEntryLessThan(t1->sourceState(), t2->sourceState());
+    if (s1 == s2) {
+        QList<QAbstractTransition*> transitions = QStatePrivate::get(s1)->transitions();
+        return transitions.indexOf(t1) < transitions.indexOf(t2);
+    } else if (isDescendant(s1, s2)) {
+        return true;
+    } else if (isDescendant(s2, s1)) {
+        return false;
+    } else {
+        Q_ASSERT(s1->machine() != 0);
+        QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
+        QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
+        Q_ASSERT(lca != 0);
+        int s1Depth = descendantDepth(s1, lca);
+        int s2Depth = descendantDepth(s2, lca);
+        if (s1Depth == s2Depth)
+            return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+        else
+            return s1Depth > s2Depth;
+    }
 }
 
 bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
@@ -417,8 +546,9 @@ QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states) con
     return findLCA(states, true);
 }
 
-QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event)
+QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event, CalculationCache *cache)
 {
+    Q_ASSERT(cache);
     Q_Q(const QStateMachine);
 
     QVarLengthArray<QAbstractState *> configuration_sorted;
@@ -453,7 +583,7 @@ QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *even
     }
 
     if (!enabledTransitions.isEmpty()) {
-        removeConflictingTransitions(enabledTransitions);
+        removeConflictingTransitions(enabledTransitions, cache);
 #ifdef QSTATEMACHINE_DEBUG
         qDebug() << q << ": enabled transitions after removing conflicts:" << enabledTransitions;
 #endif
@@ -486,15 +616,20 @@ function removeConflictingTransitions(enabledTransitions):
 
 Note: the implementation below does not build the transitionsToRemove, but removes them in-place.
 */
-void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions)
+void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache)
 {
+    Q_ASSERT(cache);
+
+    if (enabledTransitions.size() < 2)
+        return; // There is no transition to conflict with.
+
     QList<QAbstractTransition*> filteredTransitions;
     filteredTransitions.reserve(enabledTransitions.size());
     std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan);
 
     foreach (QAbstractTransition *t1, enabledTransitions) {
         bool t1Preempted = false;
-        QSet<QAbstractState*> exitSetT1 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t1);
+        QSet<QAbstractState*> exitSetT1 = computeExitSet_Unordered(t1, cache);
         QList<QAbstractTransition*>::iterator t2It = filteredTransitions.begin();
         while (t2It != filteredTransitions.end()) {
             QAbstractTransition *t2 = *t2It;
@@ -505,7 +640,7 @@ void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransitio
                 break;
             }
 
-            QSet<QAbstractState*> exitSetT2 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t2);
+            QSet<QAbstractState*> exitSetT2 = computeExitSet_Unordered(t2, cache);
             if (exitSetT1.intersect(exitSetT2).isEmpty()) {
                 // No conflict, no cry. Next patient please.
                 ++t2It;
@@ -529,17 +664,20 @@ void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransitio
     enabledTransitions = filteredTransitions;
 }
 
-void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions,
+                                     CalculationCache *cache)
 {
+    Q_ASSERT(cache);
+
 #ifdef QSTATEMACHINE_DEBUG
     qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
     qDebug() << q_func() << ": configuration before exiting states:" << configuration;
 #endif
-    QList<QAbstractState*> exitedStates = computeExitSet(enabledTransitions);
+    QList<QAbstractState*> exitedStates = computeExitSet(enabledTransitions, cache);
     QHash<RestorableId, QVariant> pendingRestorables = computePendingRestorables(exitedStates);
 
     QSet<QAbstractState*> statesForDefaultEntry;
-    QList<QAbstractState*> enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry);
+    QList<QAbstractState*> enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry, cache);
 
 #ifdef QSTATEMACHINE_DEBUG
     qDebug() << q_func() << ": computed exit set:" << exitedStates;
@@ -598,42 +736,61 @@ function computeExitSet(transitions)
                statesToExit.add(s)
    return statesToExit
 */
-QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstractTransition*> &enabledTransitions)
+QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstractTransition*> &enabledTransitions,
+                                                            CalculationCache *cache)
 {
-    QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions).toList();
+    Q_ASSERT(cache);
+
+    QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).toList();
     std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
     return statesToExit_sorted;
 }
 
-QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions)
+QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions,
+                                                                     CalculationCache *cache)
 {
+    Q_ASSERT(cache);
+
     QSet<QAbstractState*> statesToExit;
-    for (int i = 0; i < enabledTransitions.size(); ++i) {
-        QAbstractTransition *t = enabledTransitions.at(i);
-        QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList();
-        QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates);
-        if (domain == Q_NULLPTR && !t->targetStates().isEmpty()) {
-            // So we didn't find the least common ancestor for the source and target states of the
-            // transition. If there were not target states, that would be fine: then the transition
-            // will fire any events or signals, but not exit the state.
-            //
-            // However, there are target states, so it's either a node without a parent (or parent's
-            // parent, etc), or the state belongs to a different state machine. Either way, this
-            // makes the state machine invalid.
-            if (error == QStateMachine::NoError)
-                setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
-            QList<QAbstractState *> lst = pendingErrorStates.toList();
-            lst.prepend(t->sourceState());
-
-            domain = findLCCA(lst);
-            Q_ASSERT(domain != 0);
-        }
+    foreach (QAbstractTransition *t, enabledTransitions)
+        statesToExit.unite(computeExitSet_Unordered(t, cache));
+    return statesToExit;
+}
 
-        foreach (QAbstractState* s, configuration) {
-            if (isDescendant(s, domain))
-                statesToExit.insert(s);
-        }
-    }
+QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(QAbstractTransition *t,
+                                                                     CalculationCache *cache)
+{
+    Q_ASSERT(cache);
+
+    QSet<QAbstractState*> statesToExit;
+    if (cache->exitSet(t, &statesToExit))
+        return statesToExit;
+
+    QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t, cache);
+    QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates, cache);
+    if (domain == Q_NULLPTR && !t->targetStates().isEmpty()) {
+        // So we didn't find the least common ancestor for the source and target states of the
+        // transition. If there were not target states, that would be fine: then the transition
+        // will fire any events or signals, but not exit the state.
+        //
+        // However, there are target states, so it's either a node without a parent (or parent's
+        // parent, etc), or the state belongs to a different state machine. Either way, this
+        // makes the state machine invalid.
+        if (error == QStateMachine::NoError)
+            setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
+        QList<QAbstractState *> lst = pendingErrorStates.toList();
+        lst.prepend(t->sourceState());
+
+        domain = findLCCA(lst);
+        Q_ASSERT(domain != 0);
+    }
+
+    foreach (QAbstractState* s, configuration) {
+        if (isDescendant(s, domain))
+            statesToExit.insert(s);
+    }
+
+    cache->insert(t, statesToExit);
     return statesToExit;
 }
 
@@ -695,8 +852,11 @@ void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<Q
 }
 
 QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstractTransition *> &enabledTransitions,
-                                                             QSet<QAbstractState *> &statesForDefaultEntry)
+                                                             QSet<QAbstractState *> &statesForDefaultEntry,
+                                                             CalculationCache *cache)
 {
+    Q_ASSERT(cache);
+
     QSet<QAbstractState*> statesToEnter;
     if (pendingErrorStates.isEmpty()) {
         foreach (QAbstractTransition *t, enabledTransitions) {
@@ -704,8 +864,8 @@ QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstra
                 addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
             }
 
-            QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList();
-            QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates);
+            QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t, cache);
+            QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates, cache);
             foreach (QAbstractState *s, effectiveTargetStates) {
                 addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry);
             }
@@ -742,33 +902,42 @@ function getTransitionDomain(t)
   else:
       return findLCCA([t.source].append(tstates))
 */
-QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, const QList<QAbstractState *> &effectiveTargetStates) const
+QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t,
+                                                          const QList<QAbstractState *> &effectiveTargetStates,
+                                                          CalculationCache *cache) const
 {
+    Q_ASSERT(cache);
+
     if (effectiveTargetStates.isEmpty())
         return 0;
 
-#if 0
-    // Qt only has external transitions, so skip the special case for the internal transitions
-    if (QState *tSource = t->sourceState()) {
-        if (isCompound(tSource)) {
-            bool allDescendants = true;
-            foreach (QAbstractState *s, effectiveTargetStates) {
-                if (!isDescendant(s, tSource)) {
-                    allDescendants = false;
-                    break;
+    QAbstractState *domain = Q_NULLPTR;
+    if (cache->transitionDomain(t, &domain))
+        return domain;
+
+    if (t->transitionType() == QAbstractTransition::InternalTransition) {
+        if (QState *tSource = t->sourceState()) {
+            if (isCompound(tSource)) {
+                bool allDescendants = true;
+                foreach (QAbstractState *s, effectiveTargetStates) {
+                    if (!isDescendant(s, tSource)) {
+                        allDescendants = false;
+                        break;
+                    }
                 }
-            }
 
-            if (allDescendants)
-                return tSource;
+                if (allDescendants)
+                    return tSource;
+            }
         }
     }
-#endif
 
     QList<QAbstractState *> states(effectiveTargetStates);
     if (QAbstractState *src = t->sourceState())
         states.prepend(src);
-    return findLCCA(states);
+    domain = findLCCA(states);
+    cache->insert(t, domain);
+    return domain;
 }
 
 void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
@@ -1676,6 +1845,8 @@ void QStateMachinePrivate::_q_start()
 
     registerMultiThreadedSignalTransitions();
 
+    startupHook();
+
 #ifdef QSTATEMACHINE_DEBUG
     qDebug() << q << ": starting";
 #endif
@@ -1683,6 +1854,7 @@ void QStateMachinePrivate::_q_start()
     processingScheduled = true; // we call _q_process() below
 
     QList<QAbstractTransition*> transitions;
+    CalculationCache calculationCache;
     QAbstractTransition *initialTransition = createInitialTransition();
     transitions.append(initialTransition);
 
@@ -1690,7 +1862,7 @@ void QStateMachinePrivate::_q_start()
     executeTransitionContent(&nullEvent, transitions);
     QList<QAbstractState*> exitedStates = QList<QAbstractState*>();
     QSet<QAbstractState*> statesForDefaultEntry;
-    QList<QAbstractState*> enteredStates = computeEntrySet(transitions, statesForDefaultEntry);
+    QList<QAbstractState*> enteredStates = computeEntrySet(transitions, statesForDefaultEntry, &calculationCache);
     QHash<RestorableId, QVariant> pendingRestorables;
     QHash<QAbstractState*, QList<QPropertyAssignment> > assignmentsForEnteredStates =
             computePropertyAssignments(enteredStates, pendingRestorables);
@@ -1745,50 +1917,46 @@ void QStateMachinePrivate::_q_process()
             break;
         }
         QList<QAbstractTransition*> enabledTransitions;
+        CalculationCache calculationCache;
+
         QEvent *e = new QEvent(QEvent::None);
-        enabledTransitions = selectTransitions(e);
+        enabledTransitions = selectTransitions(e, &calculationCache);
         if (enabledTransitions.isEmpty()) {
             delete e;
             e = 0;
         }
-        if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) {
+        while (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) {
 #ifdef QSTATEMACHINE_DEBUG
             qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
 #endif
-            enabledTransitions = selectTransitions(e);
+            enabledTransitions = selectTransitions(e, &calculationCache);
             if (enabledTransitions.isEmpty()) {
                 delete e;
                 e = 0;
             }
         }
-        if (enabledTransitions.isEmpty()) {
-            if ((e = dequeueExternalEvent()) != 0) {
+        while (enabledTransitions.isEmpty() && ((e = dequeueExternalEvent()) != 0)) {
 #ifdef QSTATEMACHINE_DEBUG
                 qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
 #endif
-                enabledTransitions = selectTransitions(e);
+                enabledTransitions = selectTransitions(e, &calculationCache);
                 if (enabledTransitions.isEmpty()) {
                     delete e;
                     e = 0;
                 }
-            } else {
-                if (isInternalEventQueueEmpty()) {
-                    processing = false;
-                    stopProcessingReason = EventQueueEmpty;
-                }
-            }
         }
-        if (!enabledTransitions.isEmpty()) {
-            didChange = true;
-            q->beginMicrostep(e);
-            microstep(e, enabledTransitions);
-            q->endMicrostep(e);
-        }
-        else {
+        if (enabledTransitions.isEmpty()) {
+            processing = false;
+            stopProcessingReason = EventQueueEmpty;
             noMicrostep();
 #ifdef QSTATEMACHINE_DEBUG
             qDebug() << q << ": no transitions enabled";
 #endif
+        } else {
+            didChange = true;
+            q->beginMicrostep(e);
+            microstep(e, enabledTransitions, &calculationCache);
+            q->endMicrostep(e);
         }
         delete e;
     }
@@ -1976,12 +2144,17 @@ void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guil
     Q_ASSERT(guiltyState);
 
 #ifdef QSTATEMACHINE_DEBUG
+    Q_Q(QStateMachine);
     qDebug() << q << ": emitting finished signal for" << forState;
 #endif
 
     QStatePrivate::get(forState)->emitFinished();
 }
 
+void QStateMachinePrivate::startupHook()
+{
+}
+
 namespace _QStateMachine_Internal{
 
 class GoToStateTransition : public QAbstractTransition
@@ -2554,14 +2727,18 @@ void QStateMachine::setRunning(bool running)
   event queue. Events are processed in the order posted. The state machine
   takes ownership of the event and deletes it once it has been processed.
 
-  You can only post events when the state machine is running.
+  You can only post events when the state machine is running or when it is starting up.
 
   \sa postDelayedEvent()
 */
 void QStateMachine::postEvent(QEvent *event, EventPriority priority)
 {
     Q_D(QStateMachine);
-    if (d->state != QStateMachinePrivate::Running) {
+    switch (d->state) {
+    case QStateMachinePrivate::Running:
+    case QStateMachinePrivate::Starting:
+        break;
+    default:
         qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
         return;
     }
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index a66232ee88d2fc1dd90e773fbe94f7fa70aa7c0b..426f2732df16b956b92d9d3359a85295f18dfffc 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -75,6 +75,7 @@ class QState;
 class QAbstractAnimation;
 #endif
 
+struct CalculationCache;
 class QStateMachine;
 class Q_CORE_EXPORT QStateMachinePrivate : public QStatePrivate
 {
@@ -124,17 +125,18 @@ public:
     void clearHistory();
     QAbstractTransition *createInitialTransition() const;
 
-    void removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions);
-    void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+    void removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
+    void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList, CalculationCache *cache);
+    QList<QAbstractTransition *> selectTransitions(QEvent *event, CalculationCache *cache);
     virtual void noMicrostep();
     virtual void processedPendingEvents(bool didChange);
     virtual void beginMacrostep();
     virtual void endMacrostep(bool didChange);
-    QList<QAbstractTransition *> selectTransitions(QEvent *event);
     void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted,
                     const QHash<QAbstractState*, QList<QPropertyAssignment> > &assignmentsForEnteredStates);
-    QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions);
-    QSet<QAbstractState*> computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions);
+    QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
+    QSet<QAbstractState*> computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
+    QSet<QAbstractState*> computeExitSet_Unordered(QAbstractTransition *t, CalculationCache *cache);
     void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
     void enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
                      const QList<QAbstractState*> &statesToEnter_sorted,
@@ -145,9 +147,10 @@ public:
 #endif
                      );
     QList<QAbstractState*> computeEntrySet(const QList<QAbstractTransition*> &enabledTransitions,
-                                           QSet<QAbstractState*> &statesForDefaultEntry);
+                                           QSet<QAbstractState*> &statesForDefaultEntry, CalculationCache *cache);
     QAbstractState *getTransitionDomain(QAbstractTransition *t,
-                                        const QList<QAbstractState *> &effectiveTargetStates) const;
+                                        const QList<QAbstractState *> &effectiveTargetStates,
+                                        CalculationCache *cache) const;
     void addDescendantStatesToEnter(QAbstractState *state,
                                     QSet<QAbstractState*> &statesToEnter,
                                     QSet<QAbstractState*> &statesForDefaultEntry);
@@ -199,6 +202,7 @@ public:
     void cancelAllDelayedEvents();
 
     virtual void emitStateFinished(QState *forState, QFinalState *guiltyState);
+    virtual void startupHook();
 
 #ifndef QT_NO_PROPERTIES
     class RestorableId {
@@ -206,7 +210,8 @@ public:
         QObject *obj;
         QByteArray prop;
         // two overloads because friends can't have default arguments
-        friend uint qHash(const RestorableId &key, uint seed) Q_DECL_NOEXCEPT_EXPR(noexcept(std::declval<QByteArray>()))
+        friend uint qHash(const RestorableId &key, uint seed)
+            Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<QByteArray>())))
         { return qHash(qMakePair(key.obj, key.prop), seed); }
         friend uint qHash(const RestorableId &key) Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key, 0U)))
         { return qHash(key, 0U); }
diff --git a/src/corelib/thread/qexception.cpp b/src/corelib/thread/qexception.cpp
index acc3663936793b848eed2792716d734525de5c90..01bbe70c88a1287ea69fa1c49c58bde5816a7c15 100644
--- a/src/corelib/thread/qexception.cpp
+++ b/src/corelib/thread/qexception.cpp
@@ -107,6 +107,14 @@ QT_BEGIN_NAMESPACE
     \internal
 */
 
+QException::~QException()
+#ifndef Q_COMPILER_NOEXCEPT
+    throw()
+#endif
+{
+    // must stay empty until ### Qt 6
+}
+
 void QException::raise() const
 {
     QException e = *this;
@@ -118,6 +126,14 @@ QException *QException::clone() const
     return new QException(*this);
 }
 
+QUnhandledException::~QUnhandledException()
+#ifndef Q_COMPILER_NOEXCEPT
+    throw()
+#endif
+{
+    // must stay empty until ### Qt 6
+}
+
 void QUnhandledException::raise() const
 {
     QUnhandledException e = *this;
diff --git a/src/corelib/thread/qexception.h b/src/corelib/thread/qexception.h
index 55fc441020d88e3cbca85a87a24874cca6769303..edf361ebd35c69d8b8b02fb4d2148954df79733b 100644
--- a/src/corelib/thread/qexception.h
+++ b/src/corelib/thread/qexception.h
@@ -53,6 +53,11 @@ QT_BEGIN_NAMESPACE
 class Q_CORE_EXPORT QException : public std::exception
 {
 public:
+    ~QException()
+#ifndef Q_COMPILER_NOEXCEPT
+    throw()
+#endif
+    ;
     virtual void raise() const;
     virtual QException *clone() const;
 };
@@ -60,6 +65,11 @@ public:
 class Q_CORE_EXPORT QUnhandledException : public QException
 {
 public:
+    ~QUnhandledException()
+#ifndef Q_COMPILER_NOEXCEPT
+    throw()
+#endif
+;
     void raise() const Q_DECL_OVERRIDE;
     QUnhandledException *clone() const Q_DECL_OVERRIDE;
 };
diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp
index 64a2613d277bc7cf84e397c3323f8176b675b0ec..04aa39a81ee74c8b3274178db1c99e393c489d80 100644
--- a/src/corelib/thread/qrunnable.cpp
+++ b/src/corelib/thread/qrunnable.cpp
@@ -31,6 +31,15 @@
 **
 ****************************************************************************/
 
+#include "qrunnable.h"
+
+QT_BEGIN_NAMESPACE
+
+QRunnable::~QRunnable()
+{
+    // Must be empty until ### Qt 6
+}
+
 /*!
     \class QRunnable
     \inmodule QtCore
@@ -98,3 +107,5 @@
 
     \sa autoDelete(), QThreadPool
 */
+
+QT_END_NAMESPACE
diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h
index f00c58d51dfe4d40480b652eea9defa48abc4b62..28d14a46c0f02905fc1c26c14b217606501363fe 100644
--- a/src/corelib/thread/qrunnable.h
+++ b/src/corelib/thread/qrunnable.h
@@ -38,20 +38,21 @@
 
 QT_BEGIN_NAMESPACE
 
-
-class QRunnable
+class Q_CORE_EXPORT QRunnable
 {
     int ref;
 
     friend class QThreadPool;
     friend class QThreadPoolPrivate;
     friend class QThreadPoolThread;
-
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+    Q_DISABLE_COPY(QRunnable)
+#endif
 public:
     virtual void run() = 0;
 
     QRunnable() : ref(0) { }
-    virtual ~QRunnable() { }
+    virtual ~QRunnable();
 
     bool autoDelete() const { return ref != -1; }
     void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index b8544b1f0a1d77daa67e7be9a0ca06a159b6d5ca..2008f76621e3171ebbda2024d90c6d18da368961 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -57,6 +57,16 @@
 
 #include <algorithm>
 
+#ifdef Q_OS_WINRT
+namespace ABI {
+    namespace Windows {
+        namespace Foundation {
+            struct IAsyncAction;
+        }
+    }
+}
+#endif // Q_OS_WINRT
+
 QT_BEGIN_NAMESPACE
 
 class QAbstractEventDispatcher;
@@ -125,10 +135,6 @@ private:
 
 #ifndef QT_NO_THREAD
 
-#ifdef Q_OS_WINRT
-namespace ABI { namespace Windows { namespace Foundation { struct IAsyncAction; } } }
-#endif
-
 class QThreadPrivate : public QObjectPrivate
 {
     Q_DECLARE_PUBLIC(QThread)
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index da5d00311abe1959ca5da88bdd46856bf5240481..36c1f42995262c0fcd3ac2094e47ffe036630e93 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -124,7 +124,7 @@ int qFindByteArray(
 int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
 {
     Q_ASSERT(alloc >= 0 && extra >= 0);
-    Q_ASSERT_X(uint(alloc) < QByteArray::MaxSize, "qAllocMore", "Requested size is too large!");
+    Q_ASSERT_X(uint(alloc) <= QByteArray::MaxSize, "qAllocMore", "Requested size is too large!");
 
     unsigned nalloc = qNextPowerOfTwo(alloc + extra);
 
@@ -842,8 +842,9 @@ static inline char qToLower(char c)
     \internal
     \since 5.4
 
-    The maximum size of a QByteArray, in bytes. Also applies to a the maximum
-    storage size of QString and QVector, though not the number of elements.
+    The maximum size of a QByteArray (including a '\0' terminator), in bytes.
+    Also applies to the maximum storage size of QString and QVector, though
+    not the number of elements.
 */
 
 /*!
diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp
index 9148ecf6fc1038f9fa563758539d5d3ef9d76be4..615b7a4e3eb20dd3c78258b73a42fa6025a1ae9e 100644
--- a/src/corelib/tools/qcollator.cpp
+++ b/src/corelib/tools/qcollator.cpp
@@ -87,7 +87,7 @@ QCollator::QCollator(const QCollator &other)
 }
 
 /*!
-    Destroys the collator.
+   Destructor for QCollator.
  */
 QCollator::~QCollator()
 {
@@ -109,8 +109,8 @@ QCollator &QCollator::operator=(const QCollator &other)
     return *this;
 }
 
-/*
-    \fn void QCollator::QCollator(QCollator &&other)
+/*!
+    \fn QCollator::QCollator(QCollator &&other)
 
     Move constructor. Moves from \a other into this collator.
 
@@ -119,8 +119,8 @@ QCollator &QCollator::operator=(const QCollator &other)
     one of the assignment operators is undefined.
 */
 
-/*
-    \fn QCollator &QCollator::operator=(QCollator &&other)
+/*!
+    \fn QCollator & QCollator::operator=(QCollator && other)
 
     Move-assigns from \a other to this collator.
 
@@ -366,6 +366,12 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
     return *this;
 }
 
+/*!
+    \fn QCollatorSortKey &QCollatorSortKey::operator=(QCollatorSortKey && other)
+
+    Move-assigns \a other to this collator key.
+*/
+
 /*!
     \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
     \relates QCollatorSortKey
@@ -376,6 +382,12 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
     \sa QCollatorSortKey::compare()
  */
 
+/*!
+    \fn void QCollatorSortKey::swap(QCollatorSortKey & other)
+
+    Swaps this collator key with \a other.
+*/
+
 /*!
     \fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
 
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 7e49253f9be91bf34b4117bbae2895961dcbfa32..4cc3a2c2932523c1a48d77905c19cea254ac06d6 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -119,8 +119,8 @@ public:
 
 QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
 {
-    const NameHash_t::const_iterator it = nameHash.find(optionName);
-    if (it == nameHash.end()) {
+    const NameHash_t::const_iterator it = nameHash.constFind(optionName);
+    if (it == nameHash.cend()) {
         qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
         return QStringList();
     }
@@ -847,8 +847,8 @@ QString QCommandLineParser::value(const QString &optionName) const
 QStringList QCommandLineParser::values(const QString &optionName) const
 {
     d->checkParsed("values");
-    const NameHash_t::const_iterator it = d->nameHash.find(optionName);
-    if (it != d->nameHash.end()) {
+    const NameHash_t::const_iterator it = d->nameHash.constFind(optionName);
+    if (it != d->nameHash.cend()) {
         const int optionOffset = *it;
         QStringList values = d->optionValuesHash.value(optionOffset);
         if (values.isEmpty())
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index fc4fb1e7cbc7a2bc2733ef4744242bd992b67d34..41d198f9bc3684bef8f550542bcc50cba2861679 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -291,7 +291,7 @@ QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &o
 {
     other.d->ref.ref();
     if (!d->ref.deref())
-        freeData(d);
+        freeData(p);
     d = other.d;
     if (!d->sharable)
         detach_helper();
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index 255e9557e281210cf2b148001751235106c49b42..eaa695ef278f3f459a929dd7c57ba0fd1beaa188 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -1362,11 +1362,11 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
   \internal
 
   returns
-  0 if str == QDateTimeEdit::tr("AM")
-  1 if str == QDateTimeEdit::tr("PM")
-  2 if str can become QDateTimeEdit::tr("AM")
-  3 if str can become QDateTimeEdit::tr("PM")
-  4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
+  0 if str == tr("AM")
+  1 if str == tr("PM")
+  2 if str can become tr("AM")
+  3 if str can become tr("PM")
+  4 if str can become tr("PM") and can become tr("AM")
   -1 can't become anything sensible
 
 */
@@ -1737,9 +1737,9 @@ QDateTime QDateTimeParser::getMaximum() const
 QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
 {
     if (ap == AmText) {
-        return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
+        return (cs == UpperCase ? tr("AM") : tr("am"));
     } else {
-        return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
+        return (cs == UpperCase ? tr("PM") : tr("pm"));
     }
 }
 
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
index 55dc3bf7a06e14911bcea2a3129709de99f32805..9457e35ad5dd539e63e00612e1bb462eabebe7a1 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -54,7 +54,7 @@
 # include "QtCore/qvariant.h"
 #endif
 #include "QtCore/qvector.h"
-
+#include "QtCore/qcoreapplication.h"
 
 #define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
 #define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
@@ -72,6 +72,7 @@ QT_BEGIN_NAMESPACE
 
 class Q_CORE_EXPORT QDateTimeParser
 {
+    Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
 public:
     enum Context {
         FromString,
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index c4c8c8f3ccfbd4ea2c008a0a7df18206dbc0f4dd..2080a22e23bc883a658fa74a5a105914d8795334 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -353,6 +353,7 @@ public:
     class const_iterator
     {
         friend class iterator;
+        friend class QSet<Key>;
         QHashData::Node *i;
 
     public:
@@ -451,6 +452,7 @@ private:
     void detach_helper();
     void freeData(QHashData *d);
     Node **findNode(const Key &key, uint *hp = 0) const;
+    Node **findNode(const Key &key, uint h) const;
     Node *createNode(uint h, const Key &key, const T &value, Node **nextNode);
     void deleteNode(Node *node);
     static void deleteNode2(QHashData::Node *node);
@@ -846,17 +848,10 @@ Q_INLINE_TEMPLATE bool QHash<Key, T>::contains(const Key &akey) const
 }
 
 template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey,
-                                                                            uint *ahp) const
+Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, uint h) const
 {
     Node **node;
-    uint h = 0;
 
-    if (d->numBuckets || ahp) {
-        h = qHash(akey, d->seed);
-        if (ahp)
-            *ahp = h;
-    }
     if (d->numBuckets) {
         node = reinterpret_cast<Node **>(&d->buckets[h % d->numBuckets]);
         Q_ASSERT(*node == e || (*node)->next);
@@ -868,6 +863,20 @@ Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(cons
     return node;
 }
 
+template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey,
+                                                                            uint *ahp) const
+{
+    uint h = 0;
+
+    if (d->numBuckets || ahp) {
+        h = qHash(akey, d->seed);
+        if (ahp)
+            *ahp = h;
+    }
+    return findNode(akey, h);
+}
+
 template <class Key, class T>
 Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash &other) const
 {
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 1e002633df0465bd547d8e6cf7451bd81830ee7c..e446a6625b97a3488d08b515406ce44d91bdb01c 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -221,6 +221,11 @@ public:
 
         inline iterator() : i(0) {}
         inline iterator(Node *n) : i(n) {}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+        // can't remove it in Qt 5, since doing so would make the type trivial,
+        // which changes the way it's passed to functions by value.
+        inline iterator(const iterator &o): i(o.i){}
+#endif
         inline T &operator*() const { return i->t(); }
         inline T *operator->() const { return &i->t(); }
         inline T &operator[](difference_type j) const { return i[j].t(); }
@@ -268,6 +273,11 @@ public:
 
         inline const_iterator() : i(0) {}
         inline const_iterator(Node *n) : i(n) {}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+        // can't remove it in Qt 5, since doing so would make the type trivial,
+        // which changes the way it's passed to functions by value.
+        inline const_iterator(const const_iterator &o): i(o.i) {}
+#endif
 #ifdef QT_STRICT_ITERATORS
         inline explicit const_iterator(const iterator &o): i(o.i) {}
 #else
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
index 37a63a2ca4ef1a36190d1d3d35ebaff8e0605286..c0818f07d71ca68d586c8e6cd43df7b780d7de57 100644
--- a/src/corelib/tools/qlocale_mac.mm
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -44,18 +44,6 @@
 
 QT_BEGIN_NAMESPACE
 
-namespace {
-class AutoReleasePool
-{
-public:
-    AutoReleasePool(): pool([[NSAutoreleasePool alloc] init]) {}
-    ~AutoReleasePool() { [pool release]; }
-
-private:
-    NSAutoreleasePool *pool;
-};
-}
-
 /******************************************************************************
 ** Wrappers for Mac locale system functions
 */
@@ -426,7 +414,7 @@ QLocale QSystemLocale::fallbackUiLocale() const
 
 QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
 {
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
     switch(type) {
 //     case Name:
 //         return getMacLocaleName();
diff --git a/src/corelib/tools/qpair.qdoc b/src/corelib/tools/qpair.qdoc
index 48555ed6d13d4fc915abc3e9415ba64252715b05..4452d2f0b86215802de1aa539e4fd0c0e25f043f 100644
--- a/src/corelib/tools/qpair.qdoc
+++ b/src/corelib/tools/qpair.qdoc
@@ -96,6 +96,30 @@
     \sa qMakePair()
 */
 
+\fn void QPair::swap(QPair &other)
+
+    \since 5.5
+    Swaps this pair with \a other.
+
+    Equivalent to
+    \code
+        qSwap(this->first, other.first);
+        qSwap(this->second, other.second);
+    \endcode
+
+    Swap overloads are found in namespace \c std as well as via
+    argument-dependent lookup (ADL) in \c{T}'s namespace.
+*/
+
+/*!
+\fn void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs)
+    \overload
+    \relates QPair
+    \since 5.5
+
+    Swaps \a lhs with \a rhs.
+*/
+
 /*!
     \fn QPair::QPair(const QPair<TT1, TT2> &p)
     \since 5.2
@@ -108,37 +132,27 @@
 */
 
 /*!
-    \fn QPair &QPair::operator=(const QPair<TT1, TT2> &p)
+    \fn QPair::QPair(QPair<TT1, TT2> &&p)
     \since 5.2
 
-    Copies the pair \a p onto this pair.
-
-    \sa qMakePair()
+    Move-constructs a QPair instance, making it point to the same object that
+    \a p was pointing to.
 */
 
 /*!
-    \fn void QPair::swap(QPair &other)
-    \since 5.5
-
-    Swaps this pair with \a other.
+    \fn QPair & QPair::operator=(const QPair<TT1, TT2> &p)
+    \since 5.2
 
-    Equivalent to
-    \code
-    qSwap(this->first, other.first);
-    qSwap(this->second, other.second);
-    \endcode
+    Copies pair \a p into this pair.
 
-    Swap overloads are found in namespace \c std as well as via
-    argument-dependent lookup (ADL) in \c{T}'s namespace.
+    \sa qMakePair()
 */
 
 /*!
-    \fn void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs)
-    \overload
-    \relates QPair
-    \since 5.5
+    \fn QPair & QPair::operator=(QPair<TT1, TT2> &&p)
+    \since 5.2
 
-    Swaps \a lhs with \a rhs.
+    Move-assigns pair \a p into this pair instance.
 */
 
 /*! \fn bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 18dd2d12c218cb40d3660c743b6bcb49b6062ecd..47cad6349c4dcdb589b5fb56b93b538a07d41b73 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -1829,6 +1829,13 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const
            (d->pattern == re.d->pattern && d->patternOptions == re.d->patternOptions);
 }
 
+/*!
+    \fn QRegularExpression & QRegularExpression::operator=(QRegularExpression && re)
+
+    Move-assigns the regular expression \a re to this object, and returns a reference
+    to the copy.  Both the pattern and the pattern options are copied.
+*/
+
 /*!
     \fn bool QRegularExpression::operator!=(const QRegularExpression &re) const
 
@@ -1955,6 +1962,13 @@ QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpres
     return *this;
 }
 
+/*!
+    \fn QRegularExpressionMatch &QRegularExpressionMatch::operator=(QRegularExpressionMatch &&match)
+
+    Move-assigns the match result \a match to this object, and returns a reference
+    to the copy.
+*/
+
 /*!
     \fn void QRegularExpressionMatch::swap(QRegularExpressionMatch &other)
 
@@ -2319,6 +2333,12 @@ QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(cons
     return *this;
 }
 
+/*!
+    \fn QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(QRegularExpressionMatchIterator &&iterator)
+
+    Move-assigns the \a iterator to this object.
+*/
+
 /*!
     \fn void QRegularExpressionMatchIterator::swap(QRegularExpressionMatchIterator &other)
 
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bcf6d2646ea18a26cd201d4291e6240799ba9269
--- /dev/null
+++ b/src/corelib/tools/qringbuffer.cpp
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Alex Trotsenko <alex1973tr@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module 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$
+**
+****************************************************************************/
+
+#include "private/qringbuffer_p.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+    \internal
+
+    Access the bytes at a specified position the out-variable length will
+    contain the amount of bytes readable from there, e.g. the amount still
+    the same QByteArray
+*/
+const char *QRingBuffer::readPointerAtPosition(qint64 pos, qint64 &length) const
+{
+    if (pos >= 0) {
+        pos += head;
+        for (int i = 0; i < buffers.size(); ++i) {
+            length = (i == tailBuffer ? tail : buffers[i].size());
+            if (length > pos) {
+                length -= pos;
+                return buffers[i].constData() + pos;
+            }
+            pos -= length;
+        }
+    }
+
+    length = 0;
+    return 0;
+}
+
+void QRingBuffer::free(qint64 bytes)
+{
+    while (bytes > 0) {
+        const qint64 blockSize = buffers.first().size() - head;
+
+        if (tailBuffer == 0 || blockSize > bytes) {
+            // keep a single block around if it does not exceed
+            // the basic block size, to avoid repeated allocations
+            // between uses of the buffer
+            if (bufferSize <= bytes) {
+                if (buffers.first().size() <= basicBlockSize) {
+                    bufferSize = 0;
+                    head = tail = 0;
+                } else {
+                    clear(); // try to minify/squeeze us
+                }
+            } else {
+                Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
+                head += int(bytes);
+                bufferSize -= bytes;
+            }
+            return;
+        }
+
+        bufferSize -= blockSize;
+        bytes -= blockSize;
+        buffers.removeFirst();
+        --tailBuffer;
+        head = 0;
+    }
+}
+
+char *QRingBuffer::reserve(qint64 bytes)
+{
+    if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
+        return 0;
+
+    const qint64 newSize = bytes + tail;
+    // if need buffer reallocation
+    if (newSize > buffers.last().size()) {
+        if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
+                || quint64(newSize) >= QByteArray::MaxSize)) {
+            // shrink this buffer to its current size
+            buffers.last().resize(tail);
+
+            // create a new QByteArray
+            buffers.append(QByteArray());
+            ++tailBuffer;
+            tail = 0;
+        }
+        buffers.last().resize(qMax(basicBlockSize, tail + int(bytes)));
+    }
+
+    char *writePtr = buffers.last().data() + tail;
+    bufferSize += bytes;
+    Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
+    tail += int(bytes);
+    return writePtr;
+}
+
+/*!
+    \internal
+
+    Allocate data at buffer head
+*/
+char *QRingBuffer::reserveFront(qint64 bytes)
+{
+    if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
+        return 0;
+
+    if (head < bytes) {
+        buffers.first().remove(0, head);
+        if (tailBuffer == 0)
+            tail -= head;
+
+        buffers.prepend(QByteArray());
+        head = qMax(basicBlockSize, int(bytes));
+        buffers.first().resize(head);
+        ++tailBuffer;
+    }
+
+    head -= int(bytes);
+    bufferSize += bytes;
+    return buffers.first().data() + head;
+}
+
+void QRingBuffer::chop(qint64 bytes)
+{
+    while (bytes > 0) {
+        if (tailBuffer == 0 || tail > bytes) {
+            // keep a single block around if it does not exceed
+            // the basic block size, to avoid repeated allocations
+            // between uses of the buffer
+            if (bufferSize <= bytes) {
+                if (buffers.first().size() <= basicBlockSize) {
+                    bufferSize = 0;
+                    head = tail = 0;
+                } else {
+                    clear(); // try to minify/squeeze us
+                }
+            } else {
+                Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
+                tail -= int(bytes);
+                bufferSize -= bytes;
+            }
+            return;
+        }
+
+        bufferSize -= tail;
+        bytes -= tail;
+        buffers.removeLast();
+        --tailBuffer;
+        tail = buffers.last().size();
+    }
+}
+
+void QRingBuffer::clear()
+{
+    buffers.erase(buffers.begin() + 1, buffers.end());
+    buffers.first().clear();
+
+    head = tail = 0;
+    tailBuffer = 0;
+    bufferSize = 0;
+}
+
+qint64 QRingBuffer::indexOf(char c, qint64 maxLength) const
+{
+    qint64 index = 0;
+    qint64 j = head;
+    for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
+        const char *ptr = buffers[i].constData() + j;
+        j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
+
+        while (index < j) {
+            if (*ptr++ == c)
+                return index;
+            ++index;
+        }
+        j = 0;
+    }
+    return -1;
+}
+
+qint64 QRingBuffer::read(char *data, qint64 maxLength)
+{
+    const qint64 bytesToRead = qMin(size(), maxLength);
+    qint64 readSoFar = 0;
+    while (readSoFar < bytesToRead) {
+        const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
+                                                     nextDataBlockSize());
+        if (data)
+            memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
+        readSoFar += bytesToReadFromThisBlock;
+        free(bytesToReadFromThisBlock);
+    }
+    return readSoFar;
+}
+
+/*!
+    \internal
+
+    Read an unspecified amount (will read the first buffer)
+*/
+QByteArray QRingBuffer::read()
+{
+    if (bufferSize == 0)
+        return QByteArray();
+
+    QByteArray qba(buffers.takeFirst());
+
+    qba.reserve(0); // avoid that resizing needlessly reallocates
+    if (tailBuffer == 0) {
+        qba.resize(tail);
+        tail = 0;
+        buffers.append(QByteArray());
+    } else {
+        --tailBuffer;
+    }
+    qba.remove(0, head); // does nothing if head is 0
+    head = 0;
+    bufferSize -= qba.size();
+    return qba;
+}
+
+/*!
+    \internal
+
+    Peek the bytes from a specified position
+*/
+qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const
+{
+    qint64 readSoFar = 0;
+
+    if (pos >= 0) {
+        pos += head;
+        for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) {
+            qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size());
+
+            if (pos < blockLength) {
+                blockLength = qMin(blockLength - pos, maxLength - readSoFar);
+                memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength);
+                readSoFar += blockLength;
+                pos = 0;
+            } else {
+                pos -= blockLength;
+            }
+        }
+    }
+
+    return readSoFar;
+}
+
+/*!
+    \internal
+
+    Append a new buffer to the end
+*/
+void QRingBuffer::append(const QByteArray &qba)
+{
+    if (tail == 0) {
+        buffers.last() = qba;
+    } else {
+        buffers.last().resize(tail);
+        buffers.append(qba);
+        ++tailBuffer;
+    }
+    tail = qba.size();
+    bufferSize += tail;
+}
+
+qint64 QRingBuffer::readLine(char *data, qint64 maxLength)
+{
+    if (!data || --maxLength <= 0)
+        return -1;
+
+    qint64 i = indexOf('\n', maxLength);
+    i = read(data, i >= 0 ? (i + 1) : maxLength);
+
+    // Terminate it.
+    data[i] = '\0';
+    return i;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 9ca14d2987bb6433b7121518dfe80e4f712bd0b3..68509a6a80a9eefbc3e9692f409ab2584b9661c2 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -66,117 +66,17 @@ public:
         return bufferSize == 0 ? Q_NULLPTR : (buffers.first().constData() + head);
     }
 
-    // access the bytes at a specified position
-    // the out-variable length will contain the amount of bytes readable
-    // from there, e.g. the amount still the same QByteArray
-    inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
-        if (pos >= 0) {
-            pos += head;
-            for (int i = 0; i < buffers.size(); ++i) {
-                length = (i == tailBuffer ? tail : buffers[i].size());
-                if (length > pos) {
-                    length -= pos;
-                    return buffers[i].constData() + pos;
-                }
-                pos -= length;
-            }
-        }
-
-        length = 0;
-        return 0;
-    }
-
-    inline void free(qint64 bytes) {
-        while (bytes > 0) {
-            const qint64 blockSize = buffers.first().size() - head;
-
-            if (tailBuffer == 0 || blockSize > bytes) {
-                // keep a single block around if it does not exceed
-                // the basic block size, to avoid repeated allocations
-                // between uses of the buffer
-                if (bufferSize <= bytes) {
-                    if (buffers.first().size() <= basicBlockSize) {
-                        bufferSize = 0;
-                        head = tail = 0;
-                    } else {
-                        clear(); // try to minify/squeeze us
-                    }
-                } else {
-                    Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
-                    head += int(bytes);
-                    bufferSize -= bytes;
-                }
-                return;
-            }
-
-            bufferSize -= blockSize;
-            bytes -= blockSize;
-            buffers.removeFirst();
-            --tailBuffer;
-            head = 0;
-        }
-    }
-
-    inline char *reserve(qint64 bytes) {
-        if (bytes <= 0 || quint64(bytes) >= QByteArray::MaxSize)
-            return 0;
-
-        const qint64 newSize = bytes + tail;
-        // if need buffer reallocation
-        if (newSize > buffers.last().size()) {
-            if (newSize > buffers.last().capacity() && (tail >= basicBlockSize
-                    || quint64(newSize) >= QByteArray::MaxSize)) {
-                // shrink this buffer to its current size
-                buffers.last().resize(tail);
-
-                // create a new QByteArray
-                buffers.append(QByteArray());
-                ++tailBuffer;
-                tail = 0;
-            }
-            buffers.last().resize(qMax(basicBlockSize, tail + int(bytes)));
-        }
-
-        char *writePtr = buffers.last().data() + tail;
-        bufferSize += bytes;
-        Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
-        tail += int(bytes);
-        return writePtr;
-    }
+    Q_CORE_EXPORT const char *readPointerAtPosition(qint64 pos, qint64 &length) const;
+    Q_CORE_EXPORT void free(qint64 bytes);
+    Q_CORE_EXPORT char *reserve(qint64 bytes);
+    Q_CORE_EXPORT char *reserveFront(qint64 bytes);
 
     inline void truncate(qint64 pos) {
         if (pos < size())
             chop(size() - pos);
     }
 
-    inline void chop(qint64 bytes) {
-        while (bytes > 0) {
-            if (tailBuffer == 0 || tail > bytes) {
-                // keep a single block around if it does not exceed
-                // the basic block size, to avoid repeated allocations
-                // between uses of the buffer
-                if (bufferSize <= bytes) {
-                    if (buffers.first().size() <= basicBlockSize) {
-                        bufferSize = 0;
-                        head = tail = 0;
-                    } else {
-                        clear(); // try to minify/squeeze us
-                    }
-                } else {
-                    Q_ASSERT(quint64(bytes) < QByteArray::MaxSize);
-                    tail -= int(bytes);
-                    bufferSize -= bytes;
-                }
-                return;
-            }
-
-            bufferSize -= tail;
-            bytes -= tail;
-            buffers.removeLast();
-            --tailBuffer;
-            tail = buffers.last().size();
-        }
-    }
+    Q_CORE_EXPORT void chop(qint64 bytes);
 
     inline bool isEmpty() const {
         return bufferSize == 0;
@@ -195,156 +95,36 @@ public:
         *ptr = c;
     }
 
-    inline void ungetChar(char c) {
-        --head;
-        if (head < 0) {
-            if (bufferSize != 0) {
-                buffers.prepend(QByteArray());
-                ++tailBuffer;
-            } else {
-                tail = basicBlockSize;
-            }
-            buffers.first().resize(basicBlockSize);
-            head = basicBlockSize - 1;
-        }
-        buffers.first()[head] = c;
-        ++bufferSize;
-    }
-
-    inline qint64 size() const {
-        return bufferSize;
-    }
-
-    inline void clear() {
-        buffers.erase(buffers.begin() + 1, buffers.end());
-        buffers.first().clear();
-
-        head = tail = 0;
-        tailBuffer = 0;
-        bufferSize = 0;
-    }
-
-    inline qint64 indexOf(char c) const {
-        qint64 index = 0;
-        qint64 j = head;
-        for (int i = 0; i < buffers.size(); ++i) {
-            const char *ptr = buffers[i].constData() + j;
-            j = index + (i == tailBuffer ? tail : buffers[i].size()) - j;
-
-            while (index < j) {
-                if (*ptr++ == c)
-                    return index;
-                ++index;
-            }
-            j = 0;
-        }
-        return -1;
-    }
-
-    inline qint64 indexOf(char c, qint64 maxLength) const {
-        qint64 index = 0;
-        qint64 j = head;
-        for (int i = 0; index < maxLength && i < buffers.size(); ++i) {
-            const char *ptr = buffers[i].constData() + j;
-            j = qMin(index + (i == tailBuffer ? tail : buffers[i].size()) - j, maxLength);
-
-            while (index < j) {
-                if (*ptr++ == c)
-                    return index;
-                ++index;
-            }
-            j = 0;
-        }
-        return -1;
-    }
-
-    inline qint64 read(char *data, qint64 maxLength) {
-        const qint64 bytesToRead = qMin(size(), maxLength);
-        qint64 readSoFar = 0;
-        while (readSoFar < bytesToRead) {
-            const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
-                                                         nextDataBlockSize());
-            if (data)
-                memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock);
-            readSoFar += bytesToReadFromThisBlock;
-            free(bytesToReadFromThisBlock);
-        }
-        return readSoFar;
-    }
-
-    // read an unspecified amount (will read the first buffer)
-    inline QByteArray read() {
-        if (bufferSize == 0)
-            return QByteArray();
-
-        QByteArray qba(buffers.takeFirst());
-
-        qba.reserve(0); // avoid that resizing needlessly reallocates
-        if (tailBuffer == 0) {
-            qba.resize(tail);
-            tail = 0;
-            buffers.append(QByteArray());
+    void ungetChar(char c)
+    {
+        if (head > 0) {
+            --head;
+            buffers.first()[head] = c;
+            ++bufferSize;
         } else {
-            --tailBuffer;
+            char *ptr = reserveFront(1);
+            *ptr = c;
         }
-        qba.remove(0, head); // does nothing if head is 0
-        head = 0;
-        bufferSize -= qba.size();
-        return qba;
     }
 
-    // peek the bytes from a specified position
-    inline qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const
-    {
-        qint64 readSoFar = 0;
-
-        if (pos >= 0) {
-            pos += head;
-            for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) {
-                qint64 blockLength = (i == tailBuffer ? tail : buffers[i].size());
-
-                if (pos < blockLength) {
-                    blockLength = qMin(blockLength - pos, maxLength - readSoFar);
-                    memcpy(data + readSoFar, buffers[i].constData() + pos, blockLength);
-                    readSoFar += blockLength;
-                    pos = 0;
-                } else {
-                    pos -= blockLength;
-                }
-            }
-        }
 
-        return readSoFar;
+    inline qint64 size() const {
+        return bufferSize;
     }
 
-    // append a new buffer to the end
-    inline void append(const QByteArray &qba) {
-        if (tail == 0) {
-            buffers.last() = qba;
-        } else {
-            buffers.last().resize(tail);
-            buffers.append(qba);
-            ++tailBuffer;
-        }
-        tail = qba.size();
-        bufferSize += tail;
-    }
+    Q_CORE_EXPORT void clear();
+    inline qint64 indexOf(char c) const { return indexOf(c, size()); }
+    Q_CORE_EXPORT qint64 indexOf(char c, qint64 maxLength) const;
+    Q_CORE_EXPORT qint64 read(char *data, qint64 maxLength);
+    Q_CORE_EXPORT QByteArray read();
+    Q_CORE_EXPORT qint64 peek(char *data, qint64 maxLength, qint64 pos = 0) const;
+    Q_CORE_EXPORT void append(const QByteArray &qba);
 
     inline qint64 skip(qint64 length) {
         return read(0, length);
     }
 
-    inline qint64 readLine(char *data, qint64 maxLength) {
-        if (!data || --maxLength <= 0)
-            return -1;
-
-        qint64 i = indexOf('\n', maxLength);
-        i = read(data, i >= 0 ? (i + 1) : maxLength);
-
-        // Terminate it.
-        data[i] = '\0';
-        return i;
-    }
+    Q_CORE_EXPORT qint64 readLine(char *data, qint64 maxLength);
 
     inline bool canReadLine() const {
         return indexOf('\n') >= 0;
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
index 35551f406175bf9da72d6a1ad4cdda503fb97a1e..c113c38aa2475fca0018259c5ca2f6c4db868e71 100644
--- a/src/corelib/tools/qscopedpointer.cpp
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -254,6 +254,13 @@ QT_BEGIN_NAMESPACE
     Constructs a QScopedArrayPointer instance.
 */
 
+/*!
+    \fn QScopedArrayPointer::QScopedArrayPointer(D * p, QtPrivate::QScopedArrayEnsureSameType<T, D>::Type = 0)
+    \internal
+
+    Constructs a QScopedArrayPointer and stores the array of objects.
+*/
+
 /*!
     \fn T *QScopedArrayPointer::operator[](int i)
 
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index e4688711d60b5a03c8c07dbe2d2326c2f26d0367..5a9c75fe071b7afa62cadf78ffc670820021d9b0 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -137,6 +137,7 @@ public:
         typedef QHash<T, QHashDummyValue> Hash;
         typename Hash::const_iterator i;
         friend class iterator;
+        friend class QSet<T>;
 
     public:
         typedef std::bidirectional_iterator_tag iterator_category;
@@ -191,6 +192,7 @@ public:
     inline const_iterator constFind(const T &value) const { return find(value); }
     QSet<T> &unite(const QSet<T> &other);
     QSet<T> &intersect(const QSet<T> &other);
+    bool intersects(const QSet<T> &other) const;
     QSet<T> &subtract(const QSet<T> &other);
 
     // STL compatibility
@@ -283,6 +285,34 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other)
     return *this;
 }
 
+template <class T>
+Q_INLINE_TEMPLATE bool QSet<T>::intersects(const QSet<T> &other) const
+{
+    const bool otherIsBigger = other.size() > size();
+    const QSet &smallestSet = otherIsBigger ? *this : other;
+    const QSet &biggestSet = otherIsBigger ? other : *this;
+    const bool equalSeeds = q_hash.d->seed == other.q_hash.d->seed;
+    typename QSet::const_iterator i = smallestSet.cbegin();
+    typename QSet::const_iterator e = smallestSet.cend();
+
+    if (Q_LIKELY(equalSeeds)) {
+        // If seeds are equal we take the fast path so no hash is recalculated.
+        while (i != e) {
+            if (*biggestSet.q_hash.findNode(*i, i.i.i->h) != biggestSet.q_hash.e)
+                return true;
+            ++i;
+        }
+    } else {
+        while (i != e) {
+            if (biggestSet.contains(*i))
+                return true;
+            ++i;
+        }
+     }
+
+    return false;
+}
+
 template <class T>
 Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other)
 {
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
index 94cfa729f59dbcb827f4916afe24bf39dd3ef6f5..495329b90df2ae035c45f97c5bc5bceab6e35bc1 100644
--- a/src/corelib/tools/qset.qdoc
+++ b/src/corelib/tools/qset.qdoc
@@ -126,6 +126,13 @@
     \sa operator=()
 */
 
+/*!
+    \fn QSet::QSet(QSet && other)
+
+    Move-constructs a QSet instance, making it point to the same object that \a other was pointing to.
+*/
+
+
 /*!
     \fn QSet<T> &QSet::operator=(const QSet<T> &other)
 
@@ -133,6 +140,12 @@
     this set.
 */
 
+/*!
+    \fn QSet<T> &QSet::operator=(QSet<T> &&other)
+
+    Move-assigns the \a other set to this set.
+*/
+
 /*!
     \fn void QSet::swap(QSet<T> &other)
 
@@ -490,7 +503,17 @@
     Removes all items from this set that are not contained in the
     \a other set. A reference to this set is returned.
 
-    \sa operator&=(), unite(), subtract()
+    \sa intersects(), operator&=(), unite(), subtract()
+*/
+
+/*!
+    \fn bool QSet::intersects(const QSet<T> &other) const
+    \since 5.6
+
+    Returns \c true if this set has at least one item in common with
+    \a other.
+
+    \sa contains(), intersect()
 */
 
 /*!
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 52ffc161bf6eaaa0cd88e826006a20aadd922d74..d572dd209cce7eea0c2b6e030bbc917d45e8f4d7 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -39,7 +39,9 @@
 #if defined(Q_OS_WIN)
 #  if defined(Q_OS_WINCE)
 #    include <qt_windows.h>
-#    include <cmnintrin.h>
+#    if _WIN32_WCE < 0x800
+#      include <cmnintrin.h>
+#    endif
 #  endif
 #  if !defined(Q_CC_GNU)
 #    ifndef Q_OS_WINCE
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index 6e7ed40dff882671839c567e48d5246a97832c99..e71eeb607e41518e33be39ef062302025312960c 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -54,15 +54,15 @@ public:
     Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) Q_DECL_NOTHROW;
     Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) Q_DECL_NOTHROW;
     void transpose() Q_DECL_NOTHROW;
-    Q_DECL_CONSTEXPR inline QSize transposed() const Q_DECL_NOTHROW;
+    Q_DECL_CONSTEXPR inline QSize transposed() const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
     inline void scale(int w, int h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
     inline void scale(const QSize &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
-    QSize scaled(int w, int h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
-    QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
+    QSize scaled(int w, int h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+    QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
-    Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const Q_DECL_NOTHROW;
-    Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const Q_DECL_NOTHROW;
+    Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+    Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
     Q_DECL_RELAXED_CONSTEXPR inline int &rwidth() Q_DECL_NOTHROW;
     Q_DECL_RELAXED_CONSTEXPR inline int &rheight() Q_DECL_NOTHROW;
@@ -214,15 +214,15 @@ public:
     Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) Q_DECL_NOTHROW;
     Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) Q_DECL_NOTHROW;
     void transpose() Q_DECL_NOTHROW;
-    Q_DECL_CONSTEXPR inline QSizeF transposed() const Q_DECL_NOTHROW;
+    Q_DECL_CONSTEXPR inline QSizeF transposed() const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
     inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
     inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
-    QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
-    QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
+    QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+    QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
-    Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const Q_DECL_NOTHROW;
-    Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const Q_DECL_NOTHROW;
+    Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+    Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const Q_DECL_NOTHROW Q_REQUIRED_RESULT;
 
     Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth() Q_DECL_NOTHROW;
     Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight() Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 373d25c6ad1dcaeb5897a45e76bb70ed0140ed20..2585686156677b95b2866ac39d51c4ead29526b7 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -2721,6 +2721,8 @@ bool QString::operator<(QLatin1String other) const
 
 /*! \fn bool QString::operator<=(const QString &s1, const QString &s2)
 
+    \relates Qstring
+
     Returns \c true if string \a s1 is lexically less than or equal to
     string \a s2; otherwise returns \c false.
 
@@ -2766,9 +2768,10 @@ bool QString::operator<(QLatin1String other) const
 */
 
 /*! \fn bool QString::operator>(const QString &s1, const QString &s2)
+    \relates QString
 
-    Returns \c true if string \a s1 is lexically greater than string \a
-    s2; otherwise returns \c false.
+    Returns \c true if string \a s1 is lexically greater than string \a s2;
+    otherwise returns \c false.
 
     The comparison is based exclusively on the numeric Unicode values
     of the characters and is very fast, but is not what a human would
@@ -8922,6 +8925,110 @@ bool operator<(const QStringRef &s1,const QStringRef &s2)
     this string reference, returning the result.
 */
 
+/*!
+    \fn bool QStringRef::operator==(const char * s) const
+
+    \overload operator==()
+
+    The \a s byte array is converted to a QStringRef using the
+    fromUtf8() function. This function stops conversion at the
+    first NUL character found, or the end of the byte array.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is lexically equal to the parameter
+    string \a s. Otherwise returns \c false.
+
+*/
+
+/*!
+    \fn bool QStringRef::operator!=(const char * s) const
+
+    \overload operator!=()
+
+    The \a s const char pointer is converted to a QStringRef using
+    the fromUtf8() function.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is not lexically equal to the parameter
+    string \a s. Otherwise returns \c false.
+*/
+
+/*!
+    \fn bool QStringRef::operator<(const char * s) const
+
+    \overload operator<()
+
+    The \a s const char pointer is converted to a QStringRef using
+    the fromUtf8() function.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is lexically smaller than the parameter
+    string \a s. Otherwise returns \c false.
+*/
+
+/*!
+    \fn bool QStringRef::operator<=(const char * s) const
+
+    \overload operator<=()
+
+    The \a s const char pointer is converted to a QStringRef using
+    the fromUtf8() function.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is lexically smaller than or equal to the parameter
+    string \a s. Otherwise returns \c false.
+*/
+
+/*!
+    \fn bool QStringRef::operator>(const char * s) const
+
+
+    \overload operator>()
+
+    The \a s const char pointer is converted to a QStringRef using
+    the fromUtf8() function.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is lexically greater than the parameter
+    string \a s. Otherwise returns \c false.
+*/
+
+/*!
+    \fn bool QStringRef::operator>= (const char * s) const
+
+    \overload operator>=()
+
+    The \a s const char pointer is converted to a QStringRef using
+    the fromUtf8() function.
+
+    You can disable this operator by defining \c
+    QT_NO_CAST_FROM_ASCII when you compile your applications. This
+    can be useful if you want to ensure that all user-visible strings
+    go through QObject::tr(), for example.
+
+    Returns \c true if this string is lexically greater than or equal to the
+    parameter string \a s. Otherwise returns \c false.
+*/
 /*!
     \typedef QString::Data
     \internal
@@ -10332,7 +10439,6 @@ QString QString::toHtmlEscaped() const
   \endlist
 */
 
-
 /*!
     \internal
  */
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 532b294c2877cf271261d49bec049c5cc1cc6688..670d94279d8dabf47402d6603b826614c8dac08c 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -498,7 +498,7 @@ public:
     };
     QString normalized(NormalizationForm mode, QChar::UnicodeVersion version = QChar::Unicode_Unassigned) const Q_REQUIRED_RESULT;
 
-    QString repeated(int times) const;
+    QString repeated(int times) const Q_REQUIRED_RESULT;
 
     const ushort *utf16() const;
 
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 4f467646978e0a3f7649575f4ea023690b2bb3df..b57954dc03c2c64badfd800cd7c28f5f47a020bd 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -951,7 +951,7 @@
     Returns a reference to the first item in the vector. This
     function assumes that the vector isn't empty.
 
-    \sa last(), isEmpty()
+    \sa last(), isEmpty(), constFirst()
 */
 
 /*! \fn const T& QVector::first() const
@@ -959,12 +959,21 @@
     \overload
 */
 
+/*! \fn const T& QVector::constFirst() const
+    \since 5.6
+
+    Returns a const reference to the first item in the vector. This
+    function assumes that the vector isn't empty.
+
+    \sa constLast(), isEmpty(), first()
+*/
+
 /*! \fn T& QVector::last()
 
     Returns a reference to the last item in the vector. This function
     assumes that the vector isn't empty.
 
-    \sa first(), isEmpty()
+    \sa first(), isEmpty(), constLast()
 */
 
 /*! \fn const T& QVector::last() const
@@ -972,6 +981,15 @@
     \overload
 */
 
+/*! \fn const T& QVector::constLast() const
+    \since 5.6
+
+    Returns a const reference to the last item in the vector. This function
+    assumes that the vector isn't empty.
+
+    \sa constFirst(), isEmpty(), last()
+*/
+
 /*! \fn T QVector::value(int i) const
 
     Returns the value at index position \a i in the vector.
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 2eb2dc4550862dde6bf0621fa3ea79f471b59d2b..2adf2d4522bea14fae0cb57c8f0a6650e4dc43d1 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -212,8 +212,10 @@ public:
     inline int count() const { return d->size; }
     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
     inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
+    inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
     inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
     inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
+    inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
     inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
     inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
     QVector<T> mid(int pos, int len = -1) const;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 5e4a22e28398b261e46ff2709fc53d385af2ca21..1dba6784b6f1f55ea7f5273abb2454b933be8a50 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -106,6 +106,7 @@ SOURCES += \
         tools/qrect.cpp \
         tools/qregexp.cpp \
         tools/qrefcount.cpp \
+        tools/qringbuffer.cpp \
         tools/qshareddata.cpp \
         tools/qsharedpointer.cpp \
         tools/qsimd.cpp \
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index cec8ad62cb55c88937eeee8d3668dae9bf90b2d2..32b76ee5bd90ab908c43b8c5696e888d672a70bd 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -183,9 +183,6 @@ DEFINEFUNC(dbus_bool_t        , dbus_connection_add_filter, (DBusConnection
                                                              void                      *user_data,
                                                              DBusFreeFunction           free_data_function),
            (connection, function, user_data, free_data_function), return)
-DEFINEFUNC(dbus_bool_t        , dbus_connection_can_send_type, (DBusConnection             *connection,
-                                                                int                         type),
-           (connection, type), return)
 DEFINEFUNC(void               , dbus_connection_close,      (DBusConnection             *connection),
            (connection), return)
 DEFINEFUNC(DBusDispatchStatus , dbus_connection_dispatch,   (DBusConnection             *connection),
diff --git a/src/dbus/qdbusunixfiledescriptor.cpp b/src/dbus/qdbusunixfiledescriptor.cpp
index 96caa805498b3ceec951f8be138189d99a8ac388..77f48c03a4980c50346d645175d4ce2a48a53888 100644
--- a/src/dbus/qdbusunixfiledescriptor.cpp
+++ b/src/dbus/qdbusunixfiledescriptor.cpp
@@ -173,6 +173,12 @@ QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(const QDBusUnixFileD
     return *this;
 }
 
+/*!
+   \fn QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other)
+
+   Move-assigns  \a other to this QDBusUnixFileDescriptor.
+*/
+
 /*!
     Destroys this QDBusUnixFileDescriptor object and disposes of the Unix file descriptor that it contained.
 */
diff --git a/src/dbus/qdbusvirtualobject.cpp b/src/dbus/qdbusvirtualobject.cpp
index aeeb2a1f2b4e828b6817d138bfa22b7c1a2292af..b65e71eef754d41248474691e5808a6ef7e36728 100644
--- a/src/dbus/qdbusvirtualobject.cpp
+++ b/src/dbus/qdbusvirtualobject.cpp
@@ -37,11 +37,17 @@
 
 QT_BEGIN_NAMESPACE
 
+/*!
+    Constructs a QDBusVirtualObject with \a parent.
+*/
 QDBusVirtualObject::QDBusVirtualObject(QObject *parent) :
     QObject(parent)
 {
 }
 
+/*!
+    Destroys the object, deleting all of its child objects.
+*/
 QDBusVirtualObject::~QDBusVirtualObject()
 {
 }
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index cc9d789c6a801fba0ba9269d6c48928004f286f3..c1b586f87950b9dd5abbcd842aaa2256a7058593 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -443,10 +443,11 @@ QT_BEGIN_NAMESPACE
 */
 
 /*!
-    \fn QAccessibleInterface::~QAccessibleInterface()
-
-    Destroys the object.
+    Destroys the QAccessibleInterface.
 */
+QAccessibleInterface::~QAccessibleInterface()
+{
+}
 
 /*!
     \typedef QAccessible::Id
@@ -608,6 +609,11 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH
     \sa installActivationObserver()
 */
 
+QAccessible::ActivationObserver::~ActivationObserver()
+{
+    // must be empty until ### Qt 6
+}
+
 /*!
     \internal
 
@@ -1254,10 +1260,6 @@ QColor QAccessibleInterface::backgroundColor() const
     return QColor();
 }
 
-QAccessibleInterface::~QAccessibleInterface()
-{
-}
-
 /*!
     \fn QAccessibleTextInterface *QAccessibleInterface::textInterface()
 */
@@ -1329,9 +1331,13 @@ QAccessibleInterface::~QAccessibleInterface()
     the overload taking a \l QObject parameter as it might be cheaper.
 */
 
-/*! \fn QAccessibleEvent::~QAccessibleEvent()
+/*!
   Destroys the event.
 */
+QAccessibleEvent::~QAccessibleEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 /*! \fn QAccessible::Event QAccessibleEvent::type() const
   Returns the event type.
@@ -1392,6 +1398,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 
     Returns the new value of the accessible object of this event.
 */
+/*!
+    \internal
+*/
+QAccessibleValueChangeEvent::~QAccessibleValueChangeEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \class QAccessibleStateChangeEvent
@@ -1409,6 +1422,12 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
     Constructs a new QAccessibleStateChangeEvent for \a object.
     The difference to the object's previous state is in \a state.
 */
+/*!
+    \fn QAccessibleStateChangeEvent::QAccessibleStateChangeEvent(QAccessibleInterface *iface, QAccessible::State state)
+    Constructs a new QAccessibleStateChangeEvent.
+    \a iface is the interface associated with the event
+    \a state is the state of the accessible object.
+*/
 /*!
     \fn QAccessible::State QAccessibleStateChangeEvent::changedStates() const
     \brief Returns the states that have been changed.
@@ -1421,7 +1440,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
     other hand tells about the change and has focused set to \c true since
     the focus state is changed from \c true to \c false.
 */
-
+/*!
+    \internal
+*/
+QAccessibleStateChangeEvent::~QAccessibleStateChangeEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \class QAccessibleTableModelChangeEvent
@@ -1478,6 +1503,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn void QAccessibleTableModelChangeEvent::setModelChangeType(ModelChangeType changeType)
     Sets the type of change to \a changeType.
 */
+/*!
+    \internal
+*/
+QAccessibleTableModelChangeEvent::~QAccessibleTableModelChangeEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 
 /*!
@@ -1499,6 +1531,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn void QAccessibleTextCursorEvent::setCursorPosition(int position)
     Sets the cursor \a position for this event.
 */
+/*!
+    \internal
+*/
+QAccessibleTextCursorEvent::~QAccessibleTextCursorEvent()
+{
+    // must be empty until ### Qt 6
+}
+
 
 /*!
     \class QAccessibleTextInsertEvent
@@ -1522,6 +1562,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn QString QAccessibleTextInsertEvent::textInserted() const
     Returns the text that has been inserted.
 */
+/*!
+    \internal
+*/
+QAccessibleTextInsertEvent::~QAccessibleTextInsertEvent()
+{
+    // must be empty until ### Qt 6
+}
+
 
 /*!
     \class QAccessibleTextRemoveEvent
@@ -1546,6 +1594,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn QString QAccessibleTextRemoveEvent::textRemoved() const
     Returns the text that has been removed.
 */
+/*!
+    \internal
+*/
+QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \class QAccessibleTextUpdateEvent
@@ -1572,6 +1627,14 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn QString QAccessibleTextUpdateEvent::textRemoved() const
     Returns the removed text.
 */
+/*!
+    \internal
+*/
+QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent()
+{
+    // must be empty until ### Qt 6
+}
+
 
 /*!
     \class QAccessibleTextSelectionEvent
@@ -1595,6 +1658,13 @@ QAccessible::Id QAccessibleEvent::uniqueId() const
 /*! \fn void QAccessibleTextSelectionEvent::setSelection(int start, int end)
     Sets the selection for this event from position \a start to \a end.
 */
+/*!
+    \internal
+*/
+QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent()
+{
+    // must be empty until ### Qt 6
+}
 
 
 
@@ -1833,9 +1903,12 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
 */
 
 /*!
-    \fn QAccessibleTextInterface::~QAccessibleTextInterface()
     Destroys the QAccessibleTextInterface.
 */
+QAccessibleTextInterface::~QAccessibleTextInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn void QAccessibleTextInterface::addSelection(int startOffset, int endOffset)
@@ -2215,9 +2288,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
 */
 
 /*!
-    \fn QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface()
     Destroys the QAccessibleEditableTextInterface.
 */
+QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn void QAccessibleEditableTextInterface::deleteText(int startOffset, int endOffset)
@@ -2256,9 +2332,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
 */
 
 /*!
-    \fn QAccessibleValueInterface::~QAccessibleValueInterface()
-    Destructor.
+    Destroys the QAccessibleValueInterface.
 */
+QAccessibleValueInterface::~QAccessibleValueInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn QVariant QAccessibleValueInterface::currentValue() const
@@ -2316,6 +2395,14 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
     \l{IAccessible2 Specification}
 */
 
+/*!
+    Destroys the QAccessibleImageInterface.
+*/
+QAccessibleImageInterface::~QAccessibleImageInterface()
+{
+    // must be empty until ### Qt 6
+}
+
 /*!
     \class QAccessibleTableCellInterface
     \inmodule QtGui
@@ -2328,9 +2415,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
 */
 
 /*!
-    \fn virtual QAccessibleTableCellInterface::~QAccessibleTableCellInterface()
     Destroys the QAccessibleTableCellInterface.
 */
+QAccessibleTableCellInterface::~QAccessibleTableCellInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn virtual int QAccessibleTableCellInterface::columnExtent() const
@@ -2384,9 +2474,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
 */
 
 /*!
-    \fn virtual QAccessibleTableInterface::~QAccessibleTableInterface()
     Destroys the QAccessibleTableInterface.
 */
+QAccessibleTableInterface::~QAccessibleTableInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn virtual QAccessibleInterface *QAccessibleTableInterface::cellAt(int row, int column) const
@@ -2537,9 +2630,12 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
 */
 
 /*!
-    \fn QAccessibleActionInterface::~QAccessibleActionInterface()
     Destroys the QAccessibleActionInterface.
 */
+QAccessibleActionInterface::~QAccessibleActionInterface()
+{
+    // must be empty until ### Qt 6
+}
 
 /*!
     \fn QStringList QAccessibleActionInterface::actionNames() const
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index faa8cd719d300950cc4e937a8e05e1e94697670b..a0281d1c110a6dd2084c8148cad331d6f1fece68 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -396,10 +396,10 @@ public:
     static UpdateHandler installUpdateHandler(UpdateHandler);
     static RootObjectHandler installRootObjectHandler(RootObjectHandler);
 
-    class ActivationObserver
+    class Q_GUI_EXPORT ActivationObserver
     {
     public:
-        virtual ~ActivationObserver() {}
+        virtual ~ActivationObserver();
         virtual void accessibilityActiveChanged(bool active) = 0;
     };
     static void installActivationObserver(ActivationObserver *);
@@ -514,7 +514,7 @@ protected:
 class Q_GUI_EXPORT QAccessibleTextInterface
 {
 public:
-    virtual ~QAccessibleTextInterface() {}
+    virtual ~QAccessibleTextInterface();
     // selection
     virtual void selection(int selectionIndex, int *startOffset, int *endOffset) const = 0;
     virtual int selectionCount() const = 0;
@@ -547,7 +547,7 @@ public:
 class Q_GUI_EXPORT QAccessibleEditableTextInterface
 {
 public:
-    virtual ~QAccessibleEditableTextInterface() {}
+    virtual ~QAccessibleEditableTextInterface();
 
     virtual void deleteText(int startOffset, int endOffset) = 0;
     virtual void insertText(int offset, const QString &text) = 0;
@@ -557,8 +557,7 @@ public:
 class Q_GUI_EXPORT QAccessibleValueInterface
 {
 public:
-
-    virtual ~QAccessibleValueInterface() {}
+    virtual ~QAccessibleValueInterface();
 
     virtual QVariant currentValue() const = 0;
     virtual void setCurrentValue(const QVariant &value) = 0;
@@ -570,7 +569,7 @@ public:
 class Q_GUI_EXPORT QAccessibleTableCellInterface
 {
 public:
-    virtual ~QAccessibleTableCellInterface() {}
+    virtual ~QAccessibleTableCellInterface();
 
     virtual bool isSelected() const = 0;
 
@@ -587,7 +586,7 @@ public:
 class Q_GUI_EXPORT QAccessibleTableInterface
 {
 public:
-    virtual ~QAccessibleTableInterface() {}
+    virtual ~QAccessibleTableInterface();
 
     virtual QAccessibleInterface *caption() const = 0;
     virtual QAccessibleInterface *summary() const = 0;
@@ -622,7 +621,7 @@ class Q_GUI_EXPORT QAccessibleActionInterface
 {
     Q_DECLARE_TR_FUNCTIONS(QAccessibleActionInterface)
 public:
-    virtual ~QAccessibleActionInterface() {}
+    virtual ~QAccessibleActionInterface();
 
     virtual QStringList actionNames() const = 0;
     virtual QString localizedActionName(const QString &name) const;
@@ -647,7 +646,7 @@ public:
 class Q_GUI_EXPORT QAccessibleImageInterface
 {
 public:
-    virtual ~QAccessibleImageInterface() {}
+    virtual ~QAccessibleImageInterface();
 
     virtual QString imageDescription() const = 0;
     virtual QSize imageSize() const = 0;
@@ -691,8 +690,7 @@ public:
         m_uniqueId = QAccessible::uniqueId(iface);
     }
 
-    virtual ~QAccessibleEvent()
-    {}
+    virtual ~QAccessibleEvent();
 
     QAccessible::Event type() const { return m_type; }
     QObject *object() const { return m_object; }
@@ -726,6 +724,7 @@ public:
     {
         m_type = QAccessible::StateChanged;
     }
+    ~QAccessibleStateChangeEvent();
 
     QAccessible::State changedStates() const {
         return m_changedStates;
@@ -752,6 +751,8 @@ public:
         m_type = QAccessible::TextCaretMoved;
     }
 
+    ~QAccessibleTextCursorEvent();
+
     void setCursorPosition(int position) { m_cursorPosition = position; }
     int cursorPosition() const { return m_cursorPosition; }
 
@@ -776,6 +777,8 @@ public:
         m_type = QAccessible::TextSelectionChanged;
     }
 
+    ~QAccessibleTextSelectionEvent();
+
     void setSelection(int start, int end) {
         m_selectionStart = start;
         m_selectionEnd = end;
@@ -805,6 +808,8 @@ public:
         m_type = QAccessible::TextInserted;
     }
 
+    ~QAccessibleTextInsertEvent();
+
     QString textInserted() const {
         return m_text;
     }
@@ -833,6 +838,8 @@ public:
         m_type = QAccessible::TextRemoved;
     }
 
+    ~QAccessibleTextRemoveEvent();
+
     QString textRemoved() const {
         return m_text;
     }
@@ -860,6 +867,9 @@ public:
     {
         m_type = QAccessible::TextUpdated;
     }
+
+    ~QAccessibleTextUpdateEvent();
+
     QString textRemoved() const {
         return m_oldText;
     }
@@ -892,6 +902,8 @@ public:
         m_type = QAccessible::ValueChanged;
     }
 
+    ~QAccessibleValueChangeEvent();
+
     void setValue(const QVariant & val) { m_value= val; }
     QVariant value() const { return m_value; }
 
@@ -926,6 +938,8 @@ public:
         m_type = QAccessible::TableModelChanged;
     }
 
+    ~QAccessibleTableModelChangeEvent();
+
     void setModelChangeType(ModelChangeType changeType) { m_modelChangeType = changeType; }
     ModelChangeType modelChangeType() const { return m_modelChangeType; }
 
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 6d7a40c2ef6aacc19803b99cbc77303463ca8066..40ba84bb140831814a78c306e285f161d759b0c7 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -606,7 +606,7 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
 /*!
   Constructs a null icon.
 */
-QIcon::QIcon()
+QIcon::QIcon() Q_DECL_NOEXCEPT
     : d(0)
 {
 }
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index d87468b4f098a2ce2c4a2274da8440a80d8a8d3b..63e77eef9940d9afb787c0a9813b8a3e5b3d978a 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -51,22 +51,24 @@ public:
     enum Mode { Normal, Disabled, Active, Selected };
     enum State { On, Off };
 
-    QIcon();
+    QIcon() Q_DECL_NOEXCEPT;
     QIcon(const QPixmap &pixmap);
     QIcon(const QIcon &other);
 #ifdef Q_COMPILER_RVALUE_REFS
-    QIcon(QIcon &&other)
-        :d(0) { qSwap(d, other.d); }
+    QIcon(QIcon &&other) Q_DECL_NOEXCEPT
+        : d(0)
+    { qSwap(d, other.d); }
 #endif
     explicit QIcon(const QString &fileName); // file or resource name
     explicit QIcon(QIconEngine *engine);
     ~QIcon();
     QIcon &operator=(const QIcon &other);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QIcon &operator=(QIcon &&other)
+    inline QIcon &operator=(QIcon &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); return *this; }
 #endif
-    inline void swap(QIcon &other) { qSwap(d, other.d); }
+    inline void swap(QIcon &other) Q_DECL_NOEXCEPT
+    { qSwap(d, other.d); }
 
     operator QVariant() const;
 
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 046c01ad54cf2d5b568d625cc846140c0ff5d063..7aeba45b3bef2fffb7782df2c150e455ab678d49 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -738,7 +738,7 @@ bool QImageData::checkForAlphaPixels() const
     \sa isNull()
 */
 
-QImage::QImage()
+QImage::QImage() Q_DECL_NOEXCEPT
     : QPaintDevice()
 {
     d = 0;
@@ -5151,4 +5151,18 @@ QImage::Format QImage::toImageFormat(QPixelFormat format) Q_DECL_NOTHROW
     return Format_Invalid;
 }
 
+Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
+{
+    if (orient == QImageIOHandler::TransformationNone)
+        return;
+    if (orient == QImageIOHandler::TransformationRotate270) {
+        src = rotated270(src);
+    } else {
+        src = qMove(src).mirrored(orient & QImageIOHandler::TransformationMirror,
+                                  orient & QImageIOHandler::TransformationFlip);
+        if (orient & QImageIOHandler::TransformationRotate90)
+            src = rotated90(src);
+    }
+}
+
 QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 0ccbab819f64a6676c27f0793f595c2748b15ba2..26707021ea43d71df95ae2204f3333a7427daa14 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -122,7 +122,7 @@ public:
 #endif
     };
 
-    QImage();
+    QImage() Q_DECL_NOEXCEPT;
     QImage(const QSize &size, Format format);
     QImage(int width, int height, Format format);
     QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0);
@@ -137,7 +137,7 @@ public:
 
     QImage(const QImage &);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QImage(QImage &&other)
+    inline QImage(QImage &&other) Q_DECL_NOEXCEPT
         : QPaintDevice(), d(0)
     { qSwap(d, other.d); }
 #endif
@@ -145,10 +145,11 @@ public:
 
     QImage &operator=(const QImage &);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QImage &operator=(QImage &&other)
+    inline QImage &operator=(QImage &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); return *this; }
 #endif
-    inline void swap(QImage &other) { qSwap(d, other.d); }
+    inline void swap(QImage &other) Q_DECL_NOEXCEPT
+    { qSwap(d, other.d); }
 
     bool isNull() const;
 
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index cc9a6ae2a1ce9135fc54e25f5e8f2bb4a9d9100c..22b4bcf5602540ca8773dd784f12a72554582062 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -159,6 +159,43 @@
 
     \value ProgressiveScanWrite. A handler which supports
     this option is expected to write the image as a progressive scan image.
+
+    \value ImageTransformation. A handler which supports this option can read
+    the transformation metadata of an image. A handler that supports this option
+    should not apply the transformation itself.
+
+    \value TransformedByDefault. A handler that reports support for this feature
+    will have image transformation metadata applied by default on read.
+*/
+
+/*! \enum QImageIOHandler::Transformation
+    \since 5.5
+
+    This enum describes the different transformations or orientations
+    supported by some image formats, usually through EXIF.
+
+    \value TransformationNone No transformation should be applied.
+
+    \value TransformationMirror Mirror the image horizontally.
+
+    \value TransformationFlip Mirror the image vertically.
+
+    \value TransformationRotate180 Rotate the image 180 degrees.
+    This is the same as mirroring it both horizontally and vertically.
+
+    \value TransformationRotate90 Rotate the image 90 degrees.
+
+    \value TransformationMirrorAndRotate90 Mirror the image horizontally
+    and then rotate it 90 degrees.
+
+    \value TransformationFlipAndRotate90 Mirror the image vertically
+    and then rotate it 90 degrees.
+
+    \value TransformationRotate270 Rotate the image 270 degrees.
+    This is the same as mirroring it both horizontally, vertically and
+    then rotating it 90 degrees.
+
+    \sa QImageReader::transformation(), QImageReader::setAutoTransform(), QImageWriter::setTransformation()
 */
 
 /*!
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index b48226f6191f4a392c9d3644e085c76ee47ee3c1..80cd87c4c3751aeaa154a3ba32d7ead1df746cca 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -86,8 +86,25 @@ public:
         ImageFormat,
         SupportedSubTypes,
         OptimizedWrite,
-        ProgressiveScanWrite
+        ProgressiveScanWrite,
+        ImageTransformation
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+        , TransformedByDefault
+#endif
     };
+
+    enum Transformation {
+        TransformationNone = 0,
+        TransformationMirror = 1,
+        TransformationFlip = 2,
+        TransformationRotate180 = TransformationMirror | TransformationFlip,
+        TransformationRotate90 = 4,
+        TransformationMirrorAndRotate90 = TransformationMirror | TransformationRotate90,
+        TransformationFlipAndRotate90 = TransformationFlip | TransformationRotate90,
+        TransformationRotate270 = TransformationRotate180 | TransformationRotate90
+    };
+    Q_DECLARE_FLAGS(Transformations, Transformation)
+
     virtual QVariant option(ImageOption option) const;
     virtual void setOption(ImageOption option, const QVariant &value);
     virtual bool supportsOption(ImageOption option) const;
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index c2795cc38d45a2259e9e45479f597f616ca16234..ba79bf40e52936bb6734146ee5c2cad50b640894 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -533,6 +533,11 @@ public:
     int quality;
     QMap<QString, QString> text;
     void getText();
+    enum {
+        UsePluginDefault,
+        ApplyTransform,
+        DoNotApplyTransform
+    } autoTransform;
 
     // error
     QImageReader::ImageReaderError imageReaderError;
@@ -552,6 +557,7 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
     handler = 0;
     quality = -1;
     imageReaderError = QImageReader::UnknownError;
+    autoTransform = UsePluginDefault;
 
     q = qq;
 }
@@ -1143,6 +1149,59 @@ QList<QByteArray> QImageReader::supportedSubTypes() const
     return QList<QByteArray>();
 }
 
+/*!
+    \since 5.5
+
+    Returns the transformation metadata of the image, including image orientation. If the format
+    does not support transformation metadata \c QImageIOHandler::Transformation_None is returned.
+
+    \sa setAutoTransform(), autoTransform()
+*/
+QImageIOHandler::Transformations QImageReader::transformation() const
+{
+    int option = QImageIOHandler::TransformationNone;
+    if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::ImageTransformation))
+        option = d->handler->option(QImageIOHandler::ImageTransformation).toInt();
+    return QImageIOHandler::Transformations(option);
+}
+
+/*!
+    \since 5.5
+
+    Sets if images returned by read() should have transformation metadata automatically applied.
+
+    \sa autoTransform(), transform(), read()
+*/
+void QImageReader::setAutoTransform(bool enabled)
+{
+    d->autoTransform = enabled ? QImageReaderPrivate::ApplyTransform
+                               : QImageReaderPrivate::DoNotApplyTransform;
+}
+
+/*!
+    \since 5.5
+
+    Returns \c true if the image handler will apply transformation metadata on read().
+
+    \sa setAutoTransform(), transformation(), read()
+*/
+bool QImageReader::autoTransform() const
+{
+    switch (d->autoTransform) {
+    case QImageReaderPrivate::ApplyTransform:
+        return true;
+    case QImageReaderPrivate::DoNotApplyTransform:
+        return false;
+    case QImageReaderPrivate::UsePluginDefault:
+        if (d->initHandler())
+            return d->handler->supportsOption(QImageIOHandler::TransformedByDefault);
+        // no break
+    default:
+        break;
+    }
+    return false;
+}
+
 /*!
     Returns \c true if an image can be read for the device (i.e., the
     image format is supported, and the device seems to contain valid
@@ -1185,6 +1244,8 @@ QImage QImageReader::read()
     return read(&image) ? image : QImage();
 }
 
+extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
+
 /*!
     \overload
 
@@ -1294,6 +1355,8 @@ bool QImageReader::read(QImage *image)
     if (!disable2xImageLoading && QFileInfo(fileName()).baseName().endsWith(QLatin1String("@2x"))) {
            image->setDevicePixelRatio(2.0);
     }
+    if (autoTransform())
+        qt_imageTransform(*image, transformation());
 
     return true;
 }
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 34191ed657cd77b20a9999e0e565211114e0d066..27a29bed49fff6188b1cccf04bdcf5cab709463a 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -105,6 +105,11 @@ public:
 
     bool supportsAnimation() const;
 
+    QImageIOHandler::Transformations transformation() const;
+
+    void setAutoTransform(bool enabled);
+    bool autoTransform() const;
+
     QByteArray subType() const;
     QList<QByteArray> supportedSubTypes() const;
 
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index b41810116391fe468ee46b252b9736bf08813b84..e9de1db4b2d26d268c52a3d7dff07034d3fff912 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -91,6 +91,7 @@
 #include <qbytearray.h>
 #include <qfile.h>
 #include <qfileinfo.h>
+#include <qimage.h>
 #include <qimageiohandler.h>
 #include <qjsonarray.h>
 #include <qset.h>
@@ -254,6 +255,7 @@ public:
     QByteArray subType;
     bool optimizedWrite;
     bool progressiveScanWrite;
+    QImageIOHandler::Transformations transformation;
 
     // error
     QImageWriter::ImageWriterError imageWriterError;
@@ -277,6 +279,7 @@ QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
     progressiveScanWrite = false;
     imageWriterError = QImageWriter::UnknownError;
     errorString = QImageWriter::tr("Unknown error");
+    transformation = QImageIOHandler::TransformationNone;
 
     q = qq;
 }
@@ -615,6 +618,33 @@ bool QImageWriter::progressiveScanWrite() const
     return d->progressiveScanWrite;
 }
 
+/*!
+    \since 5.5
+
+    Sets the image transformations metadata including orientation.
+
+    If transformation metadata is not supported by the image format,
+    the transform is applied before writing.
+
+    \sa transformation(), write()
+*/
+void QImageWriter::setTransformation(QImageIOHandler::Transformations transform)
+{
+    d->transformation = transform;
+}
+
+/*!
+    \since 5.5
+
+    Returns the transformation and orientation the image has been set to written with.
+
+    \sa setTransformation()
+*/
+QImageIOHandler::Transformations QImageWriter::transformation() const
+{
+    return d->transformation;
+}
+
 /*!
     \obsolete
 
@@ -694,6 +724,8 @@ bool QImageWriter::canWrite() const
     return d->canWriteHelper();
 }
 
+extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
+
 /*!
     Writes the image \a image to the assigned device or file
     name. Returns \c true on success; otherwise returns \c false. If the
@@ -708,6 +740,7 @@ bool QImageWriter::write(const QImage &image)
     if (!canWrite())
         return false;
 
+    QImage img = image;
     if (d->handler->supportsOption(QImageIOHandler::Quality))
         d->handler->setOption(QImageIOHandler::Quality, d->quality);
     if (d->handler->supportsOption(QImageIOHandler::CompressionRatio))
@@ -722,8 +755,12 @@ bool QImageWriter::write(const QImage &image)
         d->handler->setOption(QImageIOHandler::OptimizedWrite, d->optimizedWrite);
     if (d->handler->supportsOption(QImageIOHandler::ProgressiveScanWrite))
         d->handler->setOption(QImageIOHandler::ProgressiveScanWrite, d->progressiveScanWrite);
+    if (d->handler->supportsOption(QImageIOHandler::ImageTransformation))
+        d->handler->setOption(QImageIOHandler::ImageTransformation, int(d->transformation));
+    else
+        qt_imageTransform(img, d->transformation);
 
-    if (!d->handler->write(image))
+    if (!d->handler->write(img))
         return false;
     if (QFile *file = qobject_cast<QFile *>(d->device))
         file->flush();
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 96d8f51b3a66e70d3a8b3f90078fdb960d4fce29..7f92595c5391f30db40a9cea30792232916b0dee 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -89,6 +89,9 @@ public:
     void setProgressiveScanWrite(bool progressive);
     bool progressiveScanWrite() const;
 
+    QImageIOHandler::Transformations transformation() const;
+    void setTransformation(QImageIOHandler::Transformations orientation);
+
     // Obsolete as of 4.1
     void setDescription(const QString &description);
     QString description() const;
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
index 839f90f17c390b80dfbd1cf68f827c3f208d1126..4ff3917fe6242579e2604542888d71a264a64e48 100644
--- a/src/gui/image/qjpeghandler.cpp
+++ b/src/gui/image/qjpeghandler.cpp
@@ -714,7 +714,7 @@ public:
     };
 
     QJpegHandlerPrivate(QJpegHandler *qq)
-        : quality(75), exifOrientation(1), iod_src(0),
+        : quality(75), transformation(QImageIOHandler::TransformationNone), iod_src(0),
           rgb888ToRgb32ConverterPtr(qt_convert_rgb888_to_rgb32), state(Ready), optimize(false), progressive(false), q(qq)
     {}
 
@@ -730,10 +730,9 @@ public:
 
     bool readJpegHeader(QIODevice*);
     bool read(QImage *image);
-    void applyExifOrientation(QImage *image);
 
     int quality;
-    int exifOrientation;
+    QImageIOHandler::Transformations transformation;
     QVariant size;
     QImage::Format format;
     QSize scaledSize;
@@ -761,9 +760,8 @@ static bool readExifHeader(QDataStream &stream)
     char prefix[6];
     if (stream.readRawData(prefix, sizeof(prefix)) != sizeof(prefix))
         return false;
-    if (prefix[0] != 'E' || prefix[1] != 'x' || prefix[2] != 'i' || prefix[3] != 'f' || prefix[4] != 0 || prefix[5] != 0)
-        return false;
-    return true;
+    static const char exifMagic[6] = {'E', 'x', 'i', 'f', 0, 0};
+    return memcmp(prefix, exifMagic, 6) == 0;
 }
 
 /*
@@ -787,6 +785,7 @@ static int getExifOrientation(QByteArray &exifData)
 
     quint16 val;
     quint32 offset;
+    const qint64 headerStart = stream.device()->pos();
 
     // read byte order marker
     stream >> val;
@@ -803,20 +802,20 @@ static int getExifOrientation(QByteArray &exifData)
         return -1;
 
     stream >> offset;
-    // we have already used 8 bytes of TIFF header
-    offset -= 8;
 
     // read IFD
     while (!stream.atEnd()) {
         quint16 numEntries;
 
         // skip offset bytes to get the next IFD
-        if (stream.skipRawData(offset) != (qint32)offset)
+        const qint64 bytesToSkip = offset - (stream.device()->pos() - headerStart);
+
+        if (stream.skipRawData(bytesToSkip) != bytesToSkip)
             return -1;
 
         stream >> numEntries;
 
-        for (;numEntries > 0; --numEntries) {
+        for (; numEntries > 0; --numEntries) {
             quint16 tag;
             quint16 type;
             quint32 components;
@@ -825,7 +824,7 @@ static int getExifOrientation(QByteArray &exifData)
 
             stream >> tag >> type >> components >> value >> dummy;
             if (tag == 0x0112) { // Tag Exif.Image.Orientation
-                if (components !=1)
+                if (components != 1)
                     return -1;
                 if (type != 3) // we are expecting it to be an unsigned short
                     return -1;
@@ -847,6 +846,31 @@ static int getExifOrientation(QByteArray &exifData)
     // No Exif orientation was found
     return 0;
 }
+
+static QImageIOHandler::Transformations exif2Qt(int exifOrientation)
+{
+    switch (exifOrientation) {
+    case 1: // normal
+        return QImageIOHandler::TransformationNone;
+    case 2: // mirror horizontal
+        return QImageIOHandler::TransformationMirror;
+    case 3: // rotate 180
+        return QImageIOHandler::TransformationRotate180;
+    case 4: // mirror vertical
+        return QImageIOHandler::TransformationFlip;
+    case 5: // mirror horizontal and rotate 270 CW
+        return QImageIOHandler::TransformationFlipAndRotate90;
+    case 6: // rotate 90 CW
+        return QImageIOHandler::TransformationRotate90;
+    case 7: // mirror horizontal and rotate 90 CW
+        return QImageIOHandler::TransformationMirrorAndRotate90;
+    case 8: // rotate 270 CW
+        return QImageIOHandler::TransformationRotate270;
+    }
+    qWarning("Invalid EXIF orientation");
+    return QImageIOHandler::TransformationNone;
+}
+
 /*!
     \internal
 */
@@ -866,7 +890,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
 
         if (!setjmp(err.setjmp_buffer)) {
             jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
-            jpeg_save_markers(&info, JPEG_APP0+1, 0xFFFF); // Exif uses APP1 marker
+            jpeg_save_markers(&info, JPEG_APP0 + 1, 0xFFFF); // Exif uses APP1 marker
 
             (void) jpeg_read_header(&info, TRUE);
 
@@ -897,16 +921,18 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
                     description += key + QLatin1String(": ") + value.simplified();
                     readTexts.append(key);
                     readTexts.append(value);
-                } else if (marker->marker == JPEG_APP0+1) {
+                } else if (marker->marker == JPEG_APP0 + 1) {
                     exifData.append((const char*)marker->data, marker->data_length);
                 }
             }
 
-            if (exifData.size()) {
+            if (!exifData.isEmpty()) {
                 // Exif data present
-                int orientation = getExifOrientation(exifData);
-                if (orientation > 0)
-                    exifOrientation = orientation;
+                int exifOrientation = getExifOrientation(exifData);
+                if (exifOrientation == -1)
+                    return false;
+                if (exifOrientation > 0)
+                    transformation = exif2Qt(exifOrientation);
             }
 
             state = ReadHeader;
@@ -922,48 +948,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
     return true;
 }
 
-void QJpegHandlerPrivate::applyExifOrientation(QImage *image)
-{
-    // This is not an optimized implementation, but easiest to maintain
-    QTransform transform;
-
-    switch (exifOrientation) {
-        case 1: // normal
-            break;
-        case 2: // mirror horizontal
-            *image = image->mirrored(true, false);
-            break;
-        case 3: // rotate 180
-            transform.rotate(180);
-            *image = image->transformed(transform);
-            break;
-        case 4: // mirror vertical
-            *image = image->mirrored(false, true);
-            break;
-        case 5: // mirror horizontal and rotate 270 CCW
-            *image = image->mirrored(true, false);
-            transform.rotate(270);
-            *image = image->transformed(transform);
-            break;
-        case 6: // rotate 90 CW
-            transform.rotate(90);
-            *image = image->transformed(transform);
-            break;
-        case 7: // mirror horizontal and rotate 90 CW
-            *image = image->mirrored(true, false);
-            transform.rotate(90);
-            *image = image->transformed(transform);
-            break;
-        case 8: // rotate 270 CW
-            transform.rotate(-90);
-            *image = image->transformed(transform);
-            break;
-        default:
-            qWarning("This should never happen");
-    }
-    exifOrientation = 1;
-}
-
 bool QJpegHandlerPrivate::read(QImage *image)
 {
     if(state == Ready)
@@ -975,7 +959,6 @@ bool QJpegHandlerPrivate::read(QImage *image)
         if (success) {
             for (int i = 0; i < readTexts.size()-1; i+=2)
                 image->setText(readTexts.at(i), readTexts.at(i+1));
-            applyExifOrientation(image);
 
             state = Ready;
             return true;
@@ -1053,8 +1036,16 @@ bool QJpegHandler::read(QImage *image)
     return d->read(image);
 }
 
+extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
+
 bool QJpegHandler::write(const QImage &image)
 {
+    if (d->transformation != QImageIOHandler::TransformationNone) {
+        // We don't support writing EXIF headers so apply the transform to the data.
+        QImage img = image;
+        qt_imageTransform(img, d->transformation);
+        return write_jpeg_image(img, device(), d->quality, d->description, d->optimize, d->progressive);
+    }
     return write_jpeg_image(image, device(), d->quality, d->description, d->optimize, d->progressive);
 }
 
@@ -1068,7 +1059,8 @@ bool QJpegHandler::supportsOption(ImageOption option) const
         || option == Size
         || option == ImageFormat
         || option == OptimizedWrite
-        || option == ProgressiveScanWrite;
+        || option == ProgressiveScanWrite
+        || option == ImageTransformation;
 }
 
 QVariant QJpegHandler::option(ImageOption option) const
@@ -1095,6 +1087,9 @@ QVariant QJpegHandler::option(ImageOption option) const
         return d->optimize;
     case ProgressiveScanWrite:
         return d->progressive;
+    case ImageTransformation:
+        d->readJpegHeader(device());
+        return int(d->transformation);
     default:
         break;
     }
@@ -1126,6 +1121,11 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
     case ProgressiveScanWrite:
         d->progressive = value.toBool();
         break;
+    case ImageTransformation: {
+        int transformation = value.toInt();
+        if (transformation > 0 && transformation < 8)
+            d->transformation = QImageIOHandler::Transformations(transformation);
+    }
     default:
         break;
     }
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 9bb193321b3315c042be6b6c71a27e1694f8d4d8..c3897a1935d9e0b9fec95fbed13094f4c43a770f 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -72,10 +72,11 @@ public:
 
     QPicture& operator=(const QPicture &p);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QPicture &operator=(QPicture &&other)
+    inline QPicture &operator=(QPicture &&other) Q_DECL_NOEXCEPT
     { qSwap(d_ptr, other.d_ptr); return *this; }
 #endif
-    inline void swap(QPicture &other) { d_ptr.swap(other.d_ptr); }
+    inline void swap(QPicture &other) Q_DECL_NOEXCEPT
+    { d_ptr.swap(other.d_ptr); }
     void detach();
     bool isDetached() const;
 
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 810883ea6cd2f1648352633a85f315b0b9922fb3..51b02acfcf31b4ec99df4a566e47fa573774796d 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -67,10 +67,11 @@ public:
 
     QPixmap &operator=(const QPixmap &);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QPixmap &operator=(QPixmap &&other)
+    inline QPixmap &operator=(QPixmap &&other) Q_DECL_NOEXCEPT
     { qSwap(data, other.data); return *this; }
 #endif
-    inline void swap(QPixmap &other) { qSwap(data, other.data); }
+    inline void swap(QPixmap &other) Q_DECL_NOEXCEPT
+    { qSwap(data, other.data); }
 
     operator QVariant() const;
 
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 0de47f55af97bd2ff2f273c02c11ddb0ea5201d7..12e19440dcef148e3d659bfd1c39d45b00d0e427 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -40,11 +40,6 @@
 #include <QScopedArrayPointer>
 #include <qt_windows.h>
 
-#ifdef Q_OS_WINCE
-#define UNDER_NT
-#include <wingdi.h>
-#endif
-
 QT_BEGIN_NAMESPACE
 
 #ifdef Q_OS_WINCE
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 3c88d2e9c16a3d087a66fe7ef7aad8ca7e520dbd..7fbd24787e2b88504cb1e4250034a8feed1ff869 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -676,16 +676,9 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
                    && num_palette <= 256)
         {
             // 1-bit and 8-bit color
-            if (bit_depth != 1)
-                png_set_packing(png_ptr);
-            png_read_update_info(png_ptr, info_ptr);
-            png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
             format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
         } else {
             // 32-bit
-            if (bit_depth == 16)
-                png_set_strip_16(png_ptr);
-
             format = QImage::Format_ARGB32;
             // Only add filler if no alpha, or we can get 5 channel data.
             if (!(color_type & PNG_COLOR_MASK_ALPHA)
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 11f7f135522c3c82e03c52eb235c00149d14ec2d..1dc3e69470b50cc21596d10779aaedfab4e7f8c1 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -262,6 +262,36 @@ QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, const QPointF &wind
     : QInputEvent(type, modifiers), l(localPos), w(windowPos), s(screenPos), b(button), mouseState(buttons), caps(0)
 {}
 
+/*!
+    \since 5.6
+
+    Constructs a mouse event object.
+
+    The \a type parameter must be QEvent::MouseButtonPress,
+    QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick,
+    or QEvent::MouseMove.
+
+    The points \a localPos, \a windowPos and \a screenPos specify the
+    mouse cursor's position relative to the receiving widget or item,
+    window, and screen, respectively.
+
+    The \a button that caused the event is given as a value from the
+    \l Qt::MouseButton enum. If the event \a type is \l MouseMove,
+    the appropriate button for this event is Qt::NoButton. \a buttons
+    is the state of all buttons at the time of the event, \a modifiers
+    is the state of all keyboard modifiers.
+
+    The source of the event is specified by \a source.
+
+*/
+QMouseEvent::QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
+                         Qt::MouseButton button, Qt::MouseButtons buttons,
+                         Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)
+    : QInputEvent(type, modifiers), l(localPos), w(windowPos), s(screenPos), b(button), mouseState(buttons), caps(0)
+{
+    QGuiApplicationPrivate::setMouseEventSource(this, source);
+}
+
 /*!
     \internal
 */
@@ -1941,6 +1971,11 @@ QInputMethodEvent::QInputMethodEvent(const QInputMethodEvent &other)
 {
 }
 
+QInputMethodEvent::~QInputMethodEvent()
+{
+    // must be empty until ### Qt 6
+}
+
 /*!
     Sets the commit string to \a commitString.
 
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index e931e28a2e1845a2161f83705a59359f5b5f7f03..dd7b35e2bbc64ab7c9fc557fe205495d2fcccf42 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -106,6 +106,9 @@ public:
     QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
                 Qt::MouseButton button, Qt::MouseButtons buttons,
                 Qt::KeyboardModifiers modifiers);
+    QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
+                Qt::MouseButton button, Qt::MouseButtons buttons,
+                Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
     ~QMouseEvent();
 
 #ifndef QT_NO_INTEGER_EVENT_COORDINATES
@@ -528,6 +531,8 @@ public:
     };
     QInputMethodEvent();
     QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes);
+    ~QInputMethodEvent();
+
     void setCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
     inline const QList<Attribute> &attributes() const { return attrs; }
     inline const QString &preeditString() const { return preedit; }
@@ -789,8 +794,10 @@ public:
         explicit TouchPoint(int id = -1);
         TouchPoint(const TouchPoint &other);
 #ifdef Q_COMPILER_RVALUE_REFS
-        TouchPoint(TouchPoint &&other) : d(other.d) { other.d = 0; }
-        TouchPoint &operator=(TouchPoint &&other)
+        TouchPoint(TouchPoint &&other) Q_DECL_NOEXCEPT
+            : d(0)
+        { qSwap(d, other.d); }
+        TouchPoint &operator=(TouchPoint &&other) Q_DECL_NOEXCEPT
         { qSwap(d, other.d); return *this; }
 #endif
         ~TouchPoint();
@@ -798,7 +805,8 @@ public:
         TouchPoint &operator=(const TouchPoint &other)
         { if ( d != other.d ) { TouchPoint copy(other); swap(copy); } return *this; }
 
-        void swap(TouchPoint &other) { qSwap(d, other.d); }
+        void swap(TouchPoint &other) Q_DECL_NOEXCEPT
+        { qSwap(d, other.d); }
 
         int id() const;
 
diff --git a/src/gui/kernel/qgenericpluginfactory.cpp b/src/gui/kernel/qgenericpluginfactory.cpp
index 7e4727df8c3fb61e2f700fa7c99b010484bf4fc1..d7b9bfba067840c51528feb0806ee49acf873f4e 100644
--- a/src/gui/kernel/qgenericpluginfactory.cpp
+++ b/src/gui/kernel/qgenericpluginfactory.cpp
@@ -69,13 +69,13 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
 */
 QObject *QGenericPluginFactory::create(const QString& key, const QString &specification)
 {
+#if (!defined(Q_OS_WIN32) || defined(QT_SHARED)) && !defined(QT_NO_LIBRARY)
     const QString driver = key.toLower();
-
-#if !defined(Q_OS_WIN32) || defined(QT_SHARED)
-#ifndef QT_NO_LIBRARY
     if (QObject *object = qLoadPlugin1<QObject, QGenericPlugin>(loader(), driver, specification))
         return object;
-#endif
+#else // (!Q_OS_WIN32 || QT_SHARED) && !QT_NO_LIBRARY
+    Q_UNUSED(key)
+    Q_UNUSED(specification)
 #endif
     return 0;
 }
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index fe0bbbc15a4bc3520e0b1ecd451ebd7a97c7935f..7866f65b7e5ece5e99c7eb0af29bfb75af1e35d1 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1334,6 +1334,9 @@ void QGuiApplicationPrivate::init()
 #endif
 
 #ifndef QT_NO_LIBRARY
+    if (qEnvironmentVariableIntValue("QT_LOAD_TESTABILITY") > 0)
+        loadTestability = true;
+
     if (loadTestability) {
         QLibrary testLib(QStringLiteral("qttestability"));
         if (testLib.load()) {
@@ -1697,12 +1700,14 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
         // A mouse event should not change both position and buttons at the same time. Instead we
         // should first send a move event followed by a button changed event. Since this is not the case
         // with the current event, we split it in two.
-        QWindowSystemInterfacePrivate::MouseEvent *mouseButtonEvent = new QWindowSystemInterfacePrivate::MouseEvent(
+        QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent(
                     e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers);
         if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic)
-            mouseButtonEvent->flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
-        QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(mouseButtonEvent);
-        stateChange = Qt::NoButton;
+            mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
+        e->buttons = buttons;
+        processMouseEvent(e);
+        processMouseEvent(&mouseButtonEvent);
+        return;
     }
 
     QWindow *window = e->window.data();
@@ -1771,9 +1776,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
     if (!window)
         return;
 
-    QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers);
+    QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source);
     ev.setTimestamp(e->timestamp);
-    setMouseEventSource(&ev, e->source);
 #ifndef QT_NO_CURSOR
     if (!e->synthetic()) {
         if (const QScreen *screen = window->screen())
@@ -1832,9 +1836,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
         if (!e->window.isNull() || e->nullWindow()) { // QTBUG-36364, check if window closed in response to press
             const QEvent::Type doubleClickType = frameStrut ? QEvent::NonClientAreaMouseButtonDblClick : QEvent::MouseButtonDblClick;
             QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint,
-                                      button, buttons, e->modifiers);
+                                      button, buttons, e->modifiers, e->source);
             dblClickEvent.setTimestamp(e->timestamp);
-            setMouseEventSource(&dblClickEvent, e->source);
             QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent);
         }
     }
diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp
index d0dd8a4e7c8a87a2111a2b00e748684c456d1320..dbdb03adbb2d7dab3cdf61977368d340ded90217 100644
--- a/src/gui/kernel/qinputdevicemanager.cpp
+++ b/src/gui/kernel/qinputdevicemanager.cpp
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
 QInputDeviceManager::QInputDeviceManager(QObject *parent)
     : QObject(*new QInputDeviceManagerPrivate, parent)
 {
+    qRegisterMetaType<DeviceType>();
 }
 
 int QInputDeviceManager::deviceCount(DeviceType type) const
diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h
index 15c84d1a8223cd375ae5665eedd0d8f7a4024949..d64793c23c56fc4752fbece35e06ae00daacc00d 100644
--- a/src/gui/kernel/qinputdevicemanager_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p.h
@@ -77,4 +77,6 @@ signals:
 
 QT_END_NAMESPACE
 
+Q_DECLARE_METATYPE(QInputDeviceManager::DeviceType)
+
 #endif // QINPUTDEVICEMANAGER_P_H
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 23d5f06aa2979d14900d8e13414d334eede02f99..ab846b63cbabfeecd41b5c95c16753fabca5e0cc 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -39,6 +39,7 @@
 #ifndef QT_NO_SHORTCUT
 
 #include "qdebug.h"
+#include <QtCore/qhashfunctions.h>
 #ifndef QT_NO_REGEXP
 # include "qregexp.h"
 #endif
@@ -1409,6 +1410,16 @@ bool QKeySequence::operator==(const QKeySequence &other) const
             d->key[3] == other.d->key[3]);
 }
 
+/*!
+    \since 5.6
+
+    Calculates the hash value of \a key, using
+    \a seed to seed the calculation.
+*/
+uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW
+{
+    return qHashRange(key.d->key, key.d->key + QKeySequencePrivate::MaxKeyCount, seed);
+}
 
 /*!
     Provides an arbitrary comparison of this key sequence and
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index cd7af5718f0a86854c14cf8f58b417d431937983..e6616dae11b5afe68ce8dfc31d94f1628e752e3c 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -43,11 +43,12 @@ QT_BEGIN_NAMESPACE
 
 #ifndef QT_NO_SHORTCUT
 
+class QKeySequence;
+
 /*****************************************************************************
   QKeySequence stream functions
  *****************************************************************************/
 #ifndef QT_NO_DATASTREAM
-class QKeySequence;
 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &out, QKeySequence &ks);
 #endif
@@ -59,6 +60,8 @@ void qt_set_sequence_auto_mnemonic(bool b);
 class QVariant;
 class QKeySequencePrivate;
 
+Q_GUI_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QKeySequence &key, uint seed = 0) Q_DECL_NOTHROW;
+
 class Q_GUI_EXPORT QKeySequence
 {
     Q_GADGET
@@ -204,6 +207,7 @@ private:
 
     friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
     friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QKeySequence &ks);
+    friend Q_GUI_EXPORT uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW;
     friend class QShortcutMap;
     friend class QShortcut;
 
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index 2853f05ef34e03522b643a307245e69f8b40b6c2..3a1126d318dea0571c032afb3ddc19986c29d9cc 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -175,140 +175,156 @@ public:
             this->shareContext = qt_gl_global_share_context();
     }
 
-    ~QOpenGLWindowPrivate()
-    {
-        Q_Q(QOpenGLWindow);
-        if (q->isValid()) {
-            q->makeCurrent(); // this works even when the platformwindow is destroyed
-            paintDevice.reset(0);
-            fbo.reset(0);
-            blitter.destroy();
-            q->doneCurrent();
-        }
-    }
+    ~QOpenGLWindowPrivate();
 
     static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); }
 
-    void bindFBO()
-    {
-        if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
-            fbo->bind();
-        else
-            QOpenGLFramebufferObject::bindDefault();
+    void bindFBO();
+    void initialize();
+
+    void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;
+    void endPaint() Q_DECL_OVERRIDE;
+    void flush(const QRegion &region) Q_DECL_OVERRIDE;
+
+    QOpenGLWindow::UpdateBehavior updateBehavior;
+    bool hasFboBlit;
+    QScopedPointer<QOpenGLContext> context;
+    QOpenGLContext *shareContext;
+    QScopedPointer<QOpenGLFramebufferObject> fbo;
+    QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;
+    QOpenGLTextureBlitter blitter;
+    QColor backgroundColor;
+    QScopedPointer<QOffscreenSurface> offscreenSurface;
+};
+
+QOpenGLWindowPrivate::~QOpenGLWindowPrivate()
+{
+    Q_Q(QOpenGLWindow);
+    if (q->isValid()) {
+        q->makeCurrent(); // this works even when the platformwindow is destroyed
+        paintDevice.reset(0);
+        fbo.reset(0);
+        blitter.destroy();
+        q->doneCurrent();
     }
+}
 
-    void beginPaint(const QRegion &region) Q_DECL_OVERRIDE
-    {
-        Q_UNUSED(region);
-        Q_Q(QOpenGLWindow);
-
-        if (!context) {
-            context.reset(new QOpenGLContext);
-            context->setShareContext(shareContext);
-            context->setFormat(q->requestedFormat());
-            if (!context->create())
-                qWarning("QOpenGLWindow::beginPaint: Failed to create context");
-            if (!context->makeCurrent(q))
-                qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
-
-            paintDevice.reset(new QOpenGLWindowPaintDevice(q));
-            if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
-                hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
-
-            q->initializeGL();
-        } else {
-            context->makeCurrent(q);
-        }
+void QOpenGLWindowPrivate::initialize()
+{
+    Q_Q(QOpenGLWindow);
 
-        const int deviceWidth = q->width() * q->devicePixelRatio();
-        const int deviceHeight = q->height() * q->devicePixelRatio();
-        const QSize deviceSize(deviceWidth, deviceHeight);
-        if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
-            if (!fbo || fbo->size() != deviceSize) {
-                QOpenGLFramebufferObjectFormat fboFormat;
-                fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
-                if (q->requestedFormat().samples() > 0) {
-                    if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
-                        fboFormat.setSamples(q->requestedFormat().samples());
-                    else
-                        qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
-                }
-                fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
-                markWindowAsDirty();
+    if (context)
+        return;
+
+    context.reset(new QOpenGLContext);
+    context->setShareContext(shareContext);
+    context->setFormat(q->requestedFormat());
+    if (!context->create())
+        qWarning("QOpenGLWindow::beginPaint: Failed to create context");
+    if (!context->makeCurrent(q))
+        qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
+
+    paintDevice.reset(new QOpenGLWindowPaintDevice(q));
+    if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
+        hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
+
+    q->initializeGL();
+}
+
+void QOpenGLWindowPrivate::beginPaint(const QRegion &region)
+{
+    Q_UNUSED(region);
+    Q_Q(QOpenGLWindow);
+
+    initialize();
+    context->makeCurrent(q);
+
+    const int deviceWidth = q->width() * q->devicePixelRatio();
+    const int deviceHeight = q->height() * q->devicePixelRatio();
+    const QSize deviceSize(deviceWidth, deviceHeight);
+    if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+        if (!fbo || fbo->size() != deviceSize) {
+            QOpenGLFramebufferObjectFormat fboFormat;
+            fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+            if (q->requestedFormat().samples() > 0) {
+                if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
+                    fboFormat.setSamples(q->requestedFormat().samples());
+                else
+                    qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
             }
-        } else {
+            fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
             markWindowAsDirty();
         }
+    } else {
+        markWindowAsDirty();
+    }
 
-        paintDevice->setSize(QSize(deviceWidth, deviceHeight));
-        paintDevice->setDevicePixelRatio(q->devicePixelRatio());
-        context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
+    paintDevice->setSize(QSize(deviceWidth, deviceHeight));
+    paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+    context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
 
-        context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
+    context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
 
-        q->paintUnderGL();
+    q->paintUnderGL();
 
-        if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
-            fbo->bind();
-    }
+    if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+        fbo->bind();
+}
 
-    void endPaint() Q_DECL_OVERRIDE
-    {
-        Q_Q(QOpenGLWindow);
-
-        if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
-            fbo->release();
-
-        context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
-
-        if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
-            const int deviceWidth = q->width() * q->devicePixelRatio();
-            const int deviceHeight = q->height() * q->devicePixelRatio();
-            QOpenGLExtensions extensions(context.data());
-            extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
-            extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
-            extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
-                                         0, 0, deviceWidth, deviceHeight,
-                                         GL_COLOR_BUFFER_BIT, GL_NEAREST);
-        } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
-            if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
-                context->functions()->glEnable(GL_BLEND);
-                context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-            }
-            if (!blitter.isCreated())
-                blitter.create();
+void QOpenGLWindowPrivate::endPaint()
+{
+    Q_Q(QOpenGLWindow);
+
+    if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+        fbo->release();
 
-            QRect windowRect(QPoint(0, 0), fbo->size());
-            QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
-            blitter.bind();
-            blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
-            blitter.release();
+    context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
 
-            if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
-                context->functions()->glDisable(GL_BLEND);
+    if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
+        const int deviceWidth = q->width() * q->devicePixelRatio();
+        const int deviceHeight = q->height() * q->devicePixelRatio();
+        QOpenGLExtensions extensions(context.data());
+        extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
+        extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
+        extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
+                                     0, 0, deviceWidth, deviceHeight,
+                                     GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+        if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
+            context->functions()->glEnable(GL_BLEND);
+            context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         }
+        if (!blitter.isCreated())
+            blitter.create();
 
-        q->paintOverGL();
-    }
+        QRect windowRect(QPoint(0, 0), fbo->size());
+        QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
+        blitter.bind();
+        blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
+        blitter.release();
 
-    void flush(const QRegion &region) Q_DECL_OVERRIDE
-    {
-        Q_UNUSED(region);
-        Q_Q(QOpenGLWindow);
-        context->swapBuffers(q);
-        emit q->frameSwapped();
+        if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
+            context->functions()->glDisable(GL_BLEND);
     }
 
-    QOpenGLWindow::UpdateBehavior updateBehavior;
-    bool hasFboBlit;
-    QScopedPointer<QOpenGLContext> context;
-    QOpenGLContext *shareContext;
-    QScopedPointer<QOpenGLFramebufferObject> fbo;
-    QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;
-    QOpenGLTextureBlitter blitter;
-    QColor backgroundColor;
-    QScopedPointer<QOffscreenSurface> offscreenSurface;
-};
+    q->paintOverGL();
+}
+
+void QOpenGLWindowPrivate::bindFBO()
+{
+    if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+        fbo->bind();
+    else
+        QOpenGLFramebufferObject::bindDefault();
+}
+
+void QOpenGLWindowPrivate::flush(const QRegion &region)
+{
+    Q_UNUSED(region);
+    Q_Q(QOpenGLWindow);
+    context->swapBuffers(q);
+    emit q->frameSwapped();
+}
 
 void QOpenGLWindowPaintDevice::ensureActiveTarget()
 {
@@ -631,6 +647,8 @@ void QOpenGLWindow::paintEvent(QPaintEvent *event)
 void QOpenGLWindow::resizeEvent(QResizeEvent *event)
 {
     Q_UNUSED(event);
+    Q_D(QOpenGLWindow);
+    d->initialize();
     resizeGL(width(), height());
 }
 
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
index e8b35aa82ad741c338153000fe963c00d98c97dd..66b3f039f478879543f275140416e8128891cc38 100644
--- a/src/gui/kernel/qpalette.h
+++ b/src/gui/kernel/qpalette.h
@@ -62,15 +62,17 @@ public:
     QPalette &operator=(const QPalette &palette);
 #ifdef Q_COMPILER_RVALUE_REFS
     QPalette(QPalette &&other) Q_DECL_NOTHROW
-        : d(other.d), data(other.data) { other.d = Q_NULLPTR; }
-    inline QPalette &operator=(QPalette &&other)
+        : d(other.d), data(other.data)
+    { other.d = Q_NULLPTR; }
+    inline QPalette &operator=(QPalette &&other) Q_DECL_NOEXCEPT
     {
         for_faster_swapping_dont_use = other.for_faster_swapping_dont_use;
         qSwap(d, other.d); return *this;
     }
 #endif
 
-    void swap(QPalette &other) {
+    void swap(QPalette &other) Q_DECL_NOEXCEPT
+    {
         qSwap(d, other.d);
         qSwap(for_faster_swapping_dont_use, other.for_faster_swapping_dont_use);
     }
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 2d0458f7054d003c866dd608b7ea4d7915af5e75..3d35c4dcba4a7700a1b4ac285e081bae96304050 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -136,6 +136,12 @@ QVariant  QPlatformDialogHelper::defaultStyleHint(QPlatformDialogHelper::StyleHi
     return QVariant();
 }
 
+void QPlatformDialogHelper::execModalForWindow(QWindow *parent)
+{
+    Q_UNUSED(parent);
+    exec();
+}
+
 // Font dialog
 
 class QFontDialogOptionsPrivate : public QSharedData
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index 8b2b9881b7f8ea99d8a7d6c7f59091de1b02b495..6d3a367e60316dbffc45a77f93ca719ae38cd5b7 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -145,6 +145,7 @@ public:
     virtual QVariant styleHint(StyleHint hint) const;
 
     virtual void exec() = 0;
+    virtual void execModalForWindow(QWindow *parent);
     virtual bool show(Qt::WindowFlags windowFlags,
                           Qt::WindowModality windowModality,
                           QWindow *parent) = 0;
diff --git a/src/gui/kernel/qplatforminputcontextplugin_p.h b/src/gui/kernel/qplatforminputcontextplugin_p.h
index 732eba3e06ba9a3a49aefb2d31f2a4939e02b82e..d05672558da9c69eccc56da1e90c8b8b1886dff0 100644
--- a/src/gui/kernel/qplatforminputcontextplugin_p.h
+++ b/src/gui/kernel/qplatforminputcontextplugin_p.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
 
 class QPlatformInputContext;
 
-#define QPlatformInputContextFactoryInterface_iid "org.qt-project.Qt.QPlatformInputContextFactoryInterface"
+#define QPlatformInputContextFactoryInterface_iid "org.qt-project.Qt.QPlatformInputContextFactoryInterface.5.1"
 
 class Q_GUI_EXPORT QPlatformInputContextPlugin : public QObject
 {
diff --git a/src/gui/kernel/qplatformintegrationplugin.h b/src/gui/kernel/qplatformintegrationplugin.h
index b5e0b1874c68948c05b43c65afbcc90d840ba929..89808cde5e9f83d9e647da410c9d23fc5736e2f5 100644
--- a/src/gui/kernel/qplatformintegrationplugin.h
+++ b/src/gui/kernel/qplatformintegrationplugin.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
 
 class QPlatformIntegration;
 
-#define QPlatformIntegrationFactoryInterface_iid "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2"
+#define QPlatformIntegrationFactoryInterface_iid "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3"
 
 class Q_GUI_EXPORT QPlatformIntegrationPlugin : public QObject
 {
diff --git a/src/gui/kernel/qplatformmenu.cpp b/src/gui/kernel/qplatformmenu.cpp
index cb311b8d132ff39134fa3f025f628e5fec64f2bc..da65381931495ea1ab61bf7ca3750805e3b4d490 100644
--- a/src/gui/kernel/qplatformmenu.cpp
+++ b/src/gui/kernel/qplatformmenu.cpp
@@ -44,4 +44,9 @@ QPlatformMenuItem *QPlatformMenu::createMenuItem() const
     return QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
 }
 
+QPlatformMenu *QPlatformMenu::createSubMenu() const
+{
+    return QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
+}
+
 QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index baa1e460d76e8033159aa652206550d30183f4ce..1022d0ed4a31677ee71a2866002f7896a1316495 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -123,6 +123,7 @@ public:
     virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const = 0;
 
     virtual QPlatformMenuItem *createMenuItem() const;
+    virtual QPlatformMenu *createSubMenu() const;
 Q_SIGNALS:
     void aboutToShow();
     void aboutToHide();
diff --git a/src/gui/kernel/qplatformopenglcontext.cpp b/src/gui/kernel/qplatformopenglcontext.cpp
index b9cf81b30e8886d6885e7445c336ccdd5d900ca1..f98f8a496cad0f7daaa7b3899d07329e914911d2 100644
--- a/src/gui/kernel/qplatformopenglcontext.cpp
+++ b/src/gui/kernel/qplatformopenglcontext.cpp
@@ -131,6 +131,10 @@ bool QPlatformOpenGLContext::parseOpenGLVersion(const QByteArray &versionString,
             if (versionParts.size() >= 2) {
                 major = versionParts.at(0).toInt(&majorOk);
                 minor = versionParts.at(1).toInt(&minorOk);
+                // Nexus 6 has "OpenGL ES 3.0V@95.0 (GIT@I86da836d38)"
+                if (!minorOk)
+                    if (int idx = versionParts.at(1).indexOf('V'))
+                        minor = versionParts.at(1).left(idx).toInt(&minorOk);
             } else {
                 qWarning("Unrecognized OpenGL ES version");
             }
diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp
index 253a09e407abd883770075d2c976123a44c4b123..8f80789fb0fcc04b1f5b85de8e9f901c4b48c633 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow.cpp
+++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp
@@ -47,7 +47,7 @@ QShapedPixmapWindow::QShapedPixmapWindow()
     setFormat(format);
     setSurfaceType(RasterSurface);
     setFlags(Qt::ToolTip | Qt::FramelessWindowHint |
-                   Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput);
+                   Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
     create();
     m_backingStore = new QBackingStore(this);
 }
@@ -86,16 +86,14 @@ void QShapedPixmapWindow::setHotspot(const QPoint &hotspot)
     m_hotSpot = hotspot;
 }
 
-void QShapedPixmapWindow::updateGeometry()
+void QShapedPixmapWindow::updateGeometry(const QPoint &pos)
 {
-#ifndef QT_NO_CURSOR
-    QRect rect(QCursor::pos() - m_hotSpot, m_pixmap.size());
     if (m_pixmap.isNull())
         m_backingStore->resize(QSize(1,1));
     else if (m_backingStore->size() != m_pixmap.size())
         m_backingStore->resize(m_pixmap.size());
-    setGeometry(rect);
-#endif
+
+    setGeometry(QRect(pos - m_hotSpot, m_backingStore->size()));
 }
 
 void QShapedPixmapWindow::exposeEvent(QExposeEvent *)
diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h
index ec56573195f02d3f6dd93fe79693ea30778eb022..fc311cff92123cb89dc3a7ca12369b6c46ed44cd 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow_p.h
+++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h
@@ -63,7 +63,7 @@ public:
     void setPixmap(const QPixmap &pixmap);
     void setHotspot(const QPoint &hotspot);
 
-    void updateGeometry();
+    void updateGeometry(const QPoint &pos);
 
 protected:
     void exposeEvent(QExposeEvent *) Q_DECL_OVERRIDE;
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index 517f3024aa1f932e5661bde3c6d72decf696b979..162dbfee20823fcb21e4c43329fac059a25f17d9 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -210,7 +210,16 @@ void QBasicDrag::startDrag()
 
     m_drag_icon_window->setPixmap(m_drag->pixmap());
     m_drag_icon_window->setHotspot(m_drag->hotSpot());
-    m_drag_icon_window->updateGeometry();
+
+#ifndef QT_NO_CURSOR
+    QPoint pos = QCursor::pos();
+    if (pos.x() == int(qInf())) {
+        // ### fixme: no mouse pos registered. Get pos from touch...
+        pos = QPoint();
+    }
+    m_drag_icon_window->updateGeometry(pos);
+#endif
+
     m_drag_icon_window->setVisible(true);
 
     enableEventFilter();
@@ -227,10 +236,10 @@ void QBasicDrag::cancel()
     m_drag_icon_window->setVisible(false);
 }
 
-void QBasicDrag::move(const QPoint &)
+void QBasicDrag::move(const QPoint &globalPos)
 {
     if (m_drag)
-        m_drag_icon_window->updateGeometry();
+        m_drag_icon_window->updateGeometry(globalPos);
 }
 
 void QBasicDrag::drop(const QPoint &)
diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp
index 8737825de0236f756ba711a7c774cec76403bd2d..1a6e9deba8ef689db4afecba1768b7a3a7c836a2 100644
--- a/src/gui/kernel/qtouchdevice.cpp
+++ b/src/gui/kernel/qtouchdevice.cpp
@@ -37,6 +37,8 @@
 #include <QMutex>
 #include <QCoreApplication>
 
+#include <private/qdebug_p.h>
+
 QT_BEGIN_NAMESPACE
 
 /*!
@@ -239,4 +241,25 @@ void QTouchDevicePrivate::registerDevice(QTouchDevice *dev)
     deviceList()->append(dev);
 }
 
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QTouchDevice *device)
+{
+    QDebugStateSaver saver(debug);
+    debug.nospace();
+    debug.noquote();
+    debug << "QTouchDevice(";
+    if (device) {
+        debug << '"' << device->name() << "\", type=";
+        QtDebugUtils::formatQEnum(debug, device->type());
+        debug << ", capabilities=";
+        QtDebugUtils::formatQFlags(debug, device->capabilities());
+        debug << ", maximumTouchPoints=" << device->maximumTouchPoints();
+    } else {
+        debug << '0';
+    }
+    debug << ')';
+    return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
 QT_END_NAMESPACE
diff --git a/src/gui/kernel/qtouchdevice.h b/src/gui/kernel/qtouchdevice.h
index f2157ce2d6c172c2fd2bec6a0d1ea79d6c2c4af3..1c1fcc63aaecc729f45e9ba61d9315b36afd9ba3 100644
--- a/src/gui/kernel/qtouchdevice.h
+++ b/src/gui/kernel/qtouchdevice.h
@@ -38,16 +38,18 @@
 
 QT_BEGIN_NAMESPACE
 
-
+class QDebug;
 class QTouchDevicePrivate;
 
 class Q_GUI_EXPORT QTouchDevice
 {
+    Q_GADGET
 public:
     enum DeviceType {
         TouchScreen,
         TouchPad
     };
+    Q_ENUM(DeviceType)
 
     enum CapabilityFlag {
         Position = 0x0001,
@@ -58,6 +60,7 @@ public:
         NormalizedPosition = 0x0020,
         MouseEmulation = 0x0040
     };
+    Q_FLAG(CapabilityFlag)
     Q_DECLARE_FLAGS(Capabilities, CapabilityFlag)
 
     QTouchDevice();
@@ -81,6 +84,10 @@ private:
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchDevice::Capabilities)
 
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QTouchDevice *);
+#endif
+
 QT_END_NAMESPACE
 
 #endif // QTOUCHDEVICE_H
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 13461e981ee67f4ef83b5c32fd5c710958ff2441..6f01f9a466c94e7fadf72731e670e19bc0c1c2b1 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -49,6 +49,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
 bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false;
 QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
 QMutex QWindowSystemInterfacePrivate::flushEventMutex;
+QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler;
 
 //------------------------------------------------------------
 //
@@ -630,14 +631,32 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla
                 QWindowSystemInterfacePrivate::getWindowSystemEvent();
         if (!event)
             break;
-        nevents++;
-        QGuiApplicationPrivate::processWindowSystemEvent(event);
+
+        if (QWindowSystemInterfacePrivate::eventHandler) {
+            if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event))
+                nevents++;
+        } else {
+            nevents++;
+            QGuiApplicationPrivate::processWindowSystemEvent(event);
+        }
         delete event;
     }
 
     return (nevents > 0);
 }
 
+void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler)
+{
+    if (!eventHandler)
+        eventHandler = handler;
+}
+
+void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler)
+{
+    if (eventHandler == handler)
+        eventHandler = 0;
+}
+
 void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable)
 {
     QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable;
@@ -819,14 +838,26 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
 }
 #endif
 
-Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) {
-
-    QWindowSystemInterface::handleMouseEvent(w, QHighDpi::toNativeLocalPosition(local, w), QHighDpi::toNativePixels(global, w),  b,  mods);
+Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
+{
+    QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized);
+    QGuiApplicationPrivate::processWindowSystemEvent(&e);
 }
 
 Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
 {
-    QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count);
+    unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
+
+    // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms
+    // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for
+    // shortcut overriding on other platforms.
+#if defined(Q_OS_OSX)
+    if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text))
+        return;
+#endif // Q_OS_OSX
+
+    QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count);
+    QGuiApplicationPrivate::processWindowSystemEvent(&e);
 }
 
 Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1)
@@ -834,11 +865,49 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int
     return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count);
 }
 
-Q_GUI_EXPORT  void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
+Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
                                 const QList<QTouchEvent::TouchPoint> &points,
                                 Qt::KeyboardModifiers mods = Qt::NoModifier)
 {
-    QWindowSystemInterface::handleTouchEvent(w, device, QWindowSystemInterfacePrivate::toNativeTouchPoints(points, w), mods);
+    unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
+
+    if (!points.size()) // Touch events must have at least one point
+        return;
+
+    if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices.
+        return;
+
+    QEvent::Type type;
+    Qt::TouchPointStates states;
+
+    QList<QTouchEvent::TouchPoint>::const_iterator point = points.constBegin();
+    QList<QTouchEvent::TouchPoint>::const_iterator end = points.constEnd();
+    while (point != end) {
+        states |= point->state();
+        ++point;
+    }
+
+    // Determine the event type based on the combined point states.
+    type = QEvent::TouchUpdate;
+    if (states == Qt::TouchPointPressed)
+        type = QEvent::TouchBegin;
+    else if (states == Qt::TouchPointReleased)
+        type = QEvent::TouchEnd;
+
+    QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods);
+    QGuiApplicationPrivate::processWindowSystemEvent(&e);
 }
 
+QWindowSystemEventHandler::~QWindowSystemEventHandler()
+{
+    QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this);
+}
+
+bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
+{
+    QGuiApplicationPrivate::processWindowSystemEvent(e);
+    return true;
+}
+
+
 QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 8073669dfabffb0a3fbe4ba40035e30531632cf5..cbc3bad7cda7f0767d7b4c25949402f21c505614 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -54,6 +54,8 @@
 
 QT_BEGIN_NAMESPACE
 
+class QWindowSystemEventHandler;
+
 class Q_GUI_EXPORT QWindowSystemInterfacePrivate {
 public:
     enum EventType {
@@ -492,6 +494,17 @@ public:
     static QList<QWindowSystemInterface::TouchPoint>
         toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
                             const QWindow *window);
+
+    static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler);
+    static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler);
+    static QWindowSystemEventHandler *eventHandler;
+};
+
+class Q_GUI_EXPORT QWindowSystemEventHandler
+{
+public:
+    virtual ~QWindowSystemEventHandler();
+    virtual bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *event);
 };
 
 QT_END_NAMESPACE
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index c08faaaa8ba3d9b603810f7f4c7a25d8557a5e4d..19809056fdd82214a35c0340d363e2628cd51edb 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -57,7 +57,7 @@ public:
 
     void fill(T value);
 
-    QGenericMatrix<M, N, T> transposed() const;
+    QGenericMatrix<M, N, T> transposed() const Q_REQUIRED_RESULT;
 
     QGenericMatrix<N, M, T>& operator+=(const QGenericMatrix<N, M, T>& other);
     QGenericMatrix<N, M, T>& operator-=(const QGenericMatrix<N, M, T>& other);
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index 4b35ee4e7936c421ca7bb0952b4132504b966b1a..0e73f79ac0b43b3a557ba0573701264a7d16bc75 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -301,12 +301,20 @@ void QQuaternion::normalize()
 */
 
 /*!
-    \fn QQuaternion QQuaternion::conjugate() const
+    \fn QQuaternion QQuaternion::conjugated() const
+    \since 5.5
 
     Returns the conjugate of this quaternion, which is
     (-x, -y, -z, scalar).
 */
 
+/*!
+    \fn QQuaternion QQuaternion::conjugate() const
+    \obsolete
+
+    Use conjugated() instead.
+*/
+
 /*!
     Rotates \a vector with this quaternion to produce a new vector
     in 3D space.  The following code:
@@ -318,12 +326,12 @@ void QQuaternion::normalize()
     is equivalent to the following:
 
     \code
-    QVector3D result = (q * QQuaternion(0, vector) * q.conjugate()).vector();
+    QVector3D result = (q * QQuaternion(0, vector) * q.conjugated()).vector();
     \endcode
 */
 QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
 {
-    return (*this * QQuaternion(0, vector) * conjugate()).vector();
+    return (*this * QQuaternion(0, vector) * conjugated()).vector();
 }
 
 /*!
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index 52c717072d3d28eff1c1828666aa4ba1a6bc8573..5b0006ac567ec587dcf71e7793a22c241236383c 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -83,12 +83,15 @@ public:
     float length() const;
     float lengthSquared() const;
 
-    QQuaternion normalized() const;
+    QQuaternion normalized() const Q_REQUIRED_RESULT;
     void normalize();
 
     inline QQuaternion inverted() const;
 
-    QQuaternion conjugate() const;
+    QQuaternion conjugated() const Q_REQUIRED_RESULT;
+#if QT_DEPRECATED_SINCE(5, 5)
+    QT_DEPRECATED QQuaternion conjugate() const Q_REQUIRED_RESULT;
+#endif
 
     QVector3D rotatedVector(const QVector3D& vector) const;
 
@@ -161,12 +164,12 @@ inline QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpo
 
 inline bool QQuaternion::isNull() const
 {
-    return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+    return xp == 0.0f && yp == 0.0f && zp == 0.0f && wp == 0.0f;
 }
 
 inline bool QQuaternion::isIdentity() const
 {
-    return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && wp == 1.0f;
+    return xp == 0.0f && yp == 0.0f && zp == 0.0f && wp == 1.0f;
 }
 
 inline float QQuaternion::x() const { return xp; }
@@ -196,11 +199,18 @@ inline QQuaternion QQuaternion::inverted() const
     return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
 }
 
-inline QQuaternion QQuaternion::conjugate() const
+inline QQuaternion QQuaternion::conjugated() const
 {
     return QQuaternion(wp, -xp, -yp, -zp);
 }
 
+#if QT_DEPRECATED_SINCE(5, 5)
+inline QQuaternion QQuaternion::conjugate() const
+{
+    return conjugated();
+}
+#endif
+
 inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
 {
     xp += quaternion.xp;
@@ -230,9 +240,9 @@ inline QQuaternion &QQuaternion::operator*=(float factor)
 
 inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
 {
-    float ww = (q1.zp + q1.xp) * (q2.xp + q2.yp);
     float yy = (q1.wp - q1.yp) * (q2.wp + q2.zp);
     float zz = (q1.wp + q1.yp) * (q2.wp - q2.zp);
+    float ww = (q1.zp + q1.xp) * (q2.xp + q2.yp);
     float xx = ww + yy + zz;
     float qq = 0.5 * (xx + (q1.zp - q1.xp) * (q2.xp - q2.yp));
 
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index 20264fa84f4106bc2fbdd3372cdec44a3646237e..137142f381860d5130b2a8011cbefac016ac99b7 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -75,7 +75,7 @@ public:
     float length() const;
     float lengthSquared() const; //In Qt 6 convert to inline and constexpr
 
-    QVector2D normalized() const;
+    QVector2D normalized() const Q_REQUIRED_RESULT;
     void normalize();
 
     float distanceToPoint(const QVector2D &point) const;
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index aa69104f55635daabdfb6347182d15ab16ededb6..72db8ac75484ab7a3871dff39bb34d3dd8008db3 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -81,7 +81,7 @@ public:
     float length() const;
     float lengthSquared() const; //In Qt 6 convert to inline and constexpr
 
-    QVector4D normalized() const;
+    QVector4D normalized() const Q_REQUIRED_RESULT;
     void normalize();
 
     QVector4D &operator+=(const QVector4D &vector);
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index c8d33df4baa90bf14ebdd7d47cb00f0ea05e853d..1c008ccb42c7b9d9e7aeb5f2242f9760d20d92c9 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -47,6 +47,8 @@
 #include <QtCore/QFile>
 #include <QtCore/QDir>
 
+#include <set>
+
 QT_BEGIN_NAMESPACE
 
 #if defined(QT_OPENGL_3)
@@ -128,7 +130,7 @@ QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g)
 }
 
 enum Operator { NotEqual, LessThan, LessEqualThan, Equals, GreaterThan, GreaterEqualThan };
-static const char *operators[] = {"!=", "<", "<=", "=", ">", ">="};
+static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="};
 
 static inline QString valueKey()         { return QStringLiteral("value"); }
 static inline QString opKey()            { return QStringLiteral("op"); }
@@ -474,4 +476,13 @@ QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext()
     return gpu;
 }
 
+Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &filename)
+{
+    const QSet<QString> features = QOpenGLConfig::gpuFeatures(QOpenGLConfig::Gpu::fromContext(), filename);
+    std::set<QByteArray> *result = new std::set<QByteArray>;
+    foreach (const QString &feature, features)
+        result->insert(feature.toUtf8());
+    return result;
+}
+
 QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
index 853ad8b71177eb39ee3e61a1eabed1b3d7ded9c3..7e53c01cba4d1697d77e0c6a33ed036ad39155b2 100644
--- a/src/gui/opengl/qopenglengineshadermanager.cpp
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -511,7 +511,7 @@ GLuint QOpenGLEngineShaderManager::getUniformLocation(Uniform id)
     if (uniformLocations.isEmpty())
         uniformLocations.fill(GLuint(-1), NumUniforms);
 
-    static const char *uniformNames[] = {
+    static const char *const uniformNames[] = {
         "imageTexture",
         "patternColor",
         "globalOpacity",
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index ff5d79566c9038c7f95785bb97780ab0aea2d453..7def687f49bc2608deca711ce0a560196f5b2894 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -76,6 +76,9 @@ public:
     void (QOPENGLF_APIENTRYP TexStorage2D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height);
 
 private:
+    bool init();
+    QFunctionPointer resolve(const char *name);
+
     QLibrary m_gl;
 };
 
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index c60532b90b2914c1addae4548eaa3daed6b0e700..b9d674fd3bc6ca6d3e96fa27be7630f28241ded9 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -39,6 +39,10 @@
 #include <QtGui/private/qguiapplication_p.h>
 #include <qpa/qplatformintegration.h>
 
+#ifdef Q_OS_IOS
+#include <dlfcn.h>
+#endif
+
 #ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT
 #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT   0x8DBA
 #endif
@@ -3202,35 +3206,53 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexAttribPointer(GLuint indx, GL
 
 Q_GLOBAL_STATIC(QOpenGLES3Helper, qgles3Helper)
 
-QOpenGLES3Helper::QOpenGLES3Helper()
+bool QOpenGLES3Helper::init()
 {
-#ifdef Q_OS_WIN
-#ifdef QT_DEBUG
+#ifndef Q_OS_IOS
+# ifdef Q_OS_WIN
+#  ifndef QT_DEBUG
     m_gl.setFileName(QStringLiteral("libGLESv2"));
-#else
+#  else
     m_gl.setFileName(QStringLiteral("libGLESv2d"));
-#endif
-#else
+#  endif
+# else
     m_gl.setFileName(QStringLiteral("GLESv2"));
+# endif // Q_OS_WIN
+    return m_gl.load();
+#else
+    return true;
+#endif // Q_OS_IOS
+}
+
+QFunctionPointer QOpenGLES3Helper::resolve(const char *name)
+{
+#ifdef Q_OS_IOS
+    return QFunctionPointer(dlsym(RTLD_DEFAULT, name));
+#else
+    return m_gl.resolve(name);
 #endif
-    if (m_gl.load()) {
-        MapBufferRange = (GLvoid* (QOPENGLF_APIENTRYP)(GLenum, qopengl_GLintptr, qopengl_GLsizeiptr, GLbitfield)) m_gl.resolve("glMapBufferRange");
-        UnmapBuffer = (GLboolean (QOPENGLF_APIENTRYP)(GLenum)) m_gl.resolve("glUnmapBuffer");
-        BlitFramebuffer = (void (QOPENGLF_APIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)) m_gl.resolve("glBlitFramebuffer");
-        RenderbufferStorageMultisample = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)) m_gl.resolve("glRenderbufferStorageMultisample");
+}
+
+QOpenGLES3Helper::QOpenGLES3Helper()
+{
+    if (init()) {
+        MapBufferRange = (GLvoid* (QOPENGLF_APIENTRYP)(GLenum, qopengl_GLintptr, qopengl_GLsizeiptr, GLbitfield)) resolve("glMapBufferRange");
+        UnmapBuffer = (GLboolean (QOPENGLF_APIENTRYP)(GLenum)) resolve("glUnmapBuffer");
+        BlitFramebuffer = (void (QOPENGLF_APIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)) resolve("glBlitFramebuffer");
+        RenderbufferStorageMultisample = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)) resolve("glRenderbufferStorageMultisample");
 
-        GenVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, GLuint *)) m_gl.resolve("glGenVertexArrays");
-        DeleteVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, const GLuint *)) m_gl.resolve("glDeleteVertexArrays");
-        BindVertexArray = (void (QOPENGLF_APIENTRYP)(GLuint)) m_gl.resolve("glBindVertexArray");
-        IsVertexArray = (GLboolean (QOPENGLF_APIENTRYP)(GLuint)) m_gl.resolve("glIsVertexArray");
+        GenVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, GLuint *)) resolve("glGenVertexArrays");
+        DeleteVertexArrays = (void (QOPENGLF_APIENTRYP)(GLsizei, const GLuint *)) resolve("glDeleteVertexArrays");
+        BindVertexArray = (void (QOPENGLF_APIENTRYP)(GLuint)) resolve("glBindVertexArray");
+        IsVertexArray = (GLboolean (QOPENGLF_APIENTRYP)(GLuint)) resolve("glIsVertexArray");
 
-        TexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) m_gl.resolve("glTexImage3D");
-        TexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) m_gl.resolve("glTexSubImage3D");
-        CompressedTexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) m_gl.resolve("glCompressedTexImage3D");
-        CompressedTexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) m_gl.resolve("glCompressedTexSubImage3D");
+        TexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) resolve("glTexImage3D");
+        TexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) resolve("glTexSubImage3D");
+        CompressedTexImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) resolve("glCompressedTexImage3D");
+        CompressedTexSubImage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) resolve("glCompressedTexSubImage3D");
 
-        TexStorage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei)) m_gl.resolve("glTexStorage3D");
-        TexStorage2D = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)) m_gl.resolve("glTexStorage2D");
+        TexStorage3D = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei)) resolve("glTexStorage3D");
+        TexStorage2D = (void (QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)) resolve("glTexStorage2D");
 
         if (!MapBufferRange || !GenVertexArrays || !TexImage3D || !TexStorage3D)
             qFatal("OpenGL ES 3.0 entry points not found");
@@ -3568,7 +3590,7 @@ void QOpenGLExtensions::flushShared()
         d->flushIsSufficientToSyncContexts = false; // default to false, not guaranteed by the spec
         const char *vendor = (const char *) glGetString(GL_VENDOR);
         if (vendor) {
-            static const char *flushEnough[] = { "Apple", "ATI", "Intel", "NVIDIA" };
+            static const char *const flushEnough[] = { "Apple", "ATI", "Intel", "NVIDIA" };
             for (size_t i = 0; i < sizeof(flushEnough) / sizeof(const char *); ++i) {
                 if (strstr(vendor, flushEnough[i])) {
                     d->flushIsSufficientToSyncContexts = true;
diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp
index 51086ffe65fdf44048993f26b5124e75a3719c37..62e016c475f96823877ea5fe988025eb3e0cb9bc 100644
--- a/src/gui/opengl/qopenglpaintdevice.cpp
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -169,6 +169,10 @@ QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz)
 {
 }
 
+QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate()
+{
+}
+
 class QOpenGLEngineThreadStorage
 {
 public:
diff --git a/src/gui/opengl/qopenglpaintdevice_p.h b/src/gui/opengl/qopenglpaintdevice_p.h
index 57d93ee80ad5952e69848eb0686b3ee9a84ba37d..54ea09240d738cbcc77f007ba9c9fbcd73ff2ad5 100644
--- a/src/gui/opengl/qopenglpaintdevice_p.h
+++ b/src/gui/opengl/qopenglpaintdevice_p.h
@@ -56,7 +56,7 @@ class Q_GUI_EXPORT QOpenGLPaintDevicePrivate
 {
 public:
     QOpenGLPaintDevicePrivate(const QSize &size);
-    virtual ~QOpenGLPaintDevicePrivate() { }
+    virtual ~QOpenGLPaintDevicePrivate();
 
     static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); }
 
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 5bf83874002ed18155a2a2bcaa8cb2e0b82ba1df..670717c5f186513355e6d34c410c4917d1a8aa2b 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -999,7 +999,7 @@ bool QBrush::operator==(const QBrush &b) const
 */
 QDebug operator<<(QDebug dbg, const QBrush &b)
 {
-    static const char *BRUSH_STYLES[] = {
+    static const char *const BRUSH_STYLES[] = {
      "NoBrush",
      "SolidPattern",
      "Dense1Pattern",
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index a3b88a50ef3ee2a259cbf1e2cf189a7966eb813d..ceb95f56760f57add417ff8f5ca91d2dc0e96c0a 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -73,10 +73,11 @@ public:
     ~QBrush();
     QBrush &operator=(const QBrush &brush);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QBrush &operator=(QBrush &&other)
+    inline QBrush &operator=(QBrush &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); return *this; }
 #endif
-    inline void swap(QBrush &other) { qSwap(d, other.d); }
+    inline void swap(QBrush &other) Q_DECL_NOEXCEPT
+    { qSwap(d, other.d); }
 
     operator QVariant() const;
 
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index b33d7a74fc7a15299747e90eebc8af5bf029a878..f1ceb464c8c557b1272d3d7889347072737b9e73 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -729,8 +729,8 @@ void QColor::setHsv(int h, int s, int v, int a)
     saturation, lightness, and alpha-channel (transparency) components of the
     color's HSL value.
 
-    These components can be retrieved individually using the hueHslF(),
-    saturationHslF(), lightnessF() and alphaF() functions.
+    These components can be retrieved individually using the hslHueF(),
+    hslSaturationF(), lightnessF() and alphaF() functions.
 
     \sa setHsl()
 */
@@ -759,8 +759,8 @@ void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const
     saturation, lightness, and alpha-channel (transparency) components of the
     color's HSL value.
 
-    These components can be retrieved individually using the hueHsl(),
-    saturationHsl(), lightness() and alpha() functions.
+    These components can be retrieved individually using the hslHue(),
+    hslSaturation(), lightness() and alpha() functions.
 
     \sa setHsl()
 */
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index e46e997f1d82d215c835fae80d5806fd4501d111..7b03cc00fff4c7b6a00d8a469faa422ad625d601 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -944,7 +944,7 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
     { 0, 0,  0, 0,  0, 0,  0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8
 };
 
-FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
+const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
     0, // BPPNone
     fetchPixels<QPixelLayout::BPP1MSB>, // BPP1MSB
     fetchPixels<QPixelLayout::BPP1LSB>, // BPP1LSB
@@ -954,7 +954,7 @@ FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
     fetchPixels<QPixelLayout::BPP32> // BPP32
 };
 
-StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
+const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
     0, // BPPNone
     storePixels<QPixelLayout::BPP1MSB>, // BPP1MSB
     storePixels<QPixelLayout::BPP1LSB>, // BPP1LSB
@@ -966,7 +966,7 @@ StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
 
 typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
 
-FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
+static const FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
     0, // BPPNone
     fetchPixel<QPixelLayout::BPP1MSB>, // BPP1MSB
     fetchPixel<QPixelLayout::BPP1LSB>, // BPP1LSB
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index f8865a6f7ea5b4af90b83893b0756a86d4fcdfe1..179900ddd2efc2a757678e160e313e44be278118 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1142,8 +1142,8 @@ typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *sr
 typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
 
 extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
-extern FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
-extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
+extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
+extern const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
 
 
 
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 5f1b25e1897b6f205b42ae9af4193f90cb4898f7..867c64c5e008a5ccf2486d7cf40f6a12fb5dae7f 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -38,22 +38,6 @@
 
 QT_BEGIN_NAMESPACE
 
-typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
-                                   int dxx, int dyy, int dx, int dy, int dw,
-                                   int dh, int dow, int sow);
-
-static void qt_qimageScaleAARGB(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
-                         int dxx, int dyy, int dx, int dy, int dw,
-                         int dh, int dow, int sow);
-
-static void qt_qimageScaleAARGBA(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
-                          int dxx, int dyy, int dx, int dy, int dw,
-                          int dh, int dow, int sow);
-
-qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
-qt_qimageScaleFunc qt_qimageScaleRgb  = qt_qimageScaleAARGB;
-
-
 /*
  * Copyright (C) 2004, 2005 Daniel M. Duley
  *
@@ -93,6 +77,8 @@ qt_qimageScaleFunc qt_qimageScaleRgb  = qt_qimageScaleAARGB;
  *
  * Changes include formatting, namespaces and other C++'ings, removal of old
  * #ifdef'ed code, and removal of unneeded border calculation code.
+ * Later the code has been refactored and an SSE4.1 optimizated path have been
+ * added instead of the removed MMX assembler.
  *
  * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
  * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
@@ -115,21 +101,14 @@ using namespace QImageScale;
 // Code ported from Imlib...
 //
 
-// FIXME: replace with qRed, etc... These work on pointers to pixels, not
-// pixel values
-#define A_VAL(p) (qAlpha(*p))
-#define R_VAL(p) (qRed(*p))
-#define G_VAL(p) (qGreen(*p))
-#define B_VAL(p) (qBlue(*p))
-
 const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
-                                              int sw, int sh, int dh)
+                                                    int sw, int sh, int dh)
 {
     const unsigned int **p;
     int j = 0, rv = 0;
     qint64 val, inc;
 
-    if(dh < 0){
+    if (dh < 0) {
         dh = -dh;
         rv = 1;
     }
@@ -157,7 +136,7 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
     int *p, j = 0, rv = 0;
     qint64 val, inc;
 
-    if(dw < 0){
+    if (dw < 0) {
         dw = -dw;
         rv = 1;
     }
@@ -178,25 +157,23 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
             p[dw - i - 1] = tmp;
         }
     }
-   return(p);
+   return p;
 }
 
 int* QImageScale::qimageCalcApoints(int s, int d, int up)
 {
     int *p, j = 0, rv = 0;
 
-    if(d < 0){
+    if (d < 0) {
         rv = 1;
         d = -d;
     }
     p = new int[d];
 
-    /* scaling up */
-    if(up){
-        qint64 val, inc;
-
-        val = 0x8000 * s / d - 0x8000;
-        inc = (((qint64)s) << 16) / d;
+    if (up) {
+        /* scaling up */
+        qint64 val = 0x8000 * s / d - 0x8000;
+        qint64 inc = (((qint64)s) << 16) / d;
         for (int i = 0; i < d; i++) {
             int pos = val >> 16;
             if (pos < 0)
@@ -207,9 +184,8 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
                 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
             val += inc;
         }
-    }
-    /* scaling down */
-    else {
+    } else {
+        /* scaling down */
         qint64 val = 0;
         qint64 inc = (((qint64)s) << 16) / d;
         int Cp = (((d << 14) + s - 1) / s);
@@ -220,7 +196,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
             val += inc;
         }
     }
-    if(rv){
+    if (rv) {
         int tmp;
         for (int i = d / 2; --i >= 0; ) {
             tmp = p[i];
@@ -233,7 +209,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
 
 QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
 {
-    if(isi){
+    if (isi) {
         delete[] isi->xpoints;
         delete[] isi->ypoints;
         delete[] isi->xapoints;
@@ -254,28 +230,28 @@ QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
     sch = dh * qlonglong(img.height()) / sh;
 
     isi = new QImageScaleInfo;
-    if(!isi)
+    if (!isi)
         return 0;
     memset(isi, 0, sizeof(QImageScaleInfo));
 
     isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
 
     isi->xpoints = qimageCalcXPoints(img.width(), scw);
-    if(!isi->xpoints)
-        return(qimageFreeScaleInfo(isi));
+    if (!isi->xpoints)
+        return qimageFreeScaleInfo(isi);
     isi->ypoints = qimageCalcYPoints((const unsigned int *)img.scanLine(0),
                                      img.bytesPerLine() / 4, img.height(), sch);
     if (!isi->ypoints)
-        return(qimageFreeScaleInfo(isi));
-    if(aa) {
+        return qimageFreeScaleInfo(isi);
+    if (aa) {
         isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
-        if(!isi->xapoints)
-            return(qimageFreeScaleInfo(isi));
+        if (!isi->xapoints)
+            return qimageFreeScaleInfo(isi);
         isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
-        if(!isi->yapoints)
-            return(qimageFreeScaleInfo(isi));
+        if (!isi->yapoints)
+            return qimageFreeScaleInfo(isi);
     }
-    return(isi);
+    return isi;
 }
 
 
@@ -349,7 +325,7 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
                                  int dh, int dow, int sow)
 {
     /* scaling up both ways */
-    if (isi->xup_yup == 3){
+    if (isi->xup_yup == 3) {
         qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
     }
     /* if we're scaling down vertically */
@@ -381,46 +357,25 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
     }
 }
 
-inline static void qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b, int &a)
+inline static void qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b, int &a)
 {
-    r = R_VAL(pix) * xap;
-    g = G_VAL(pix) * xap;
-    b = B_VAL(pix) * xap;
-    a = A_VAL(pix) * xap;
+    r = qRed(*pix)   * xyap;
+    g = qGreen(*pix) * xyap;
+    b = qBlue(*pix)  * xyap;
+    a = qAlpha(*pix) * xyap;
     int j;
-    for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
-        pix++;
-        r += R_VAL(pix) * Cx;
-        g += G_VAL(pix) * Cx;
-        b += B_VAL(pix) * Cx;
-        a += A_VAL(pix) * Cx;
-    }
-    pix++;
-    r += R_VAL(pix) * j;
-    g += G_VAL(pix) * j;
-    b += B_VAL(pix) * j;
-    a += A_VAL(pix) * j;
-}
-
-inline static void qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b, int &a)
-{
-    r = R_VAL(pix) * yap;
-    g = G_VAL(pix) * yap;
-    b = B_VAL(pix) * yap;
-    a = A_VAL(pix) * yap;
-    int j;
-    for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
-        pix += sow;
-        r += R_VAL(pix) * Cy;
-        g += G_VAL(pix) * Cy;
-        b += B_VAL(pix) * Cy;
-        a += A_VAL(pix) * Cy;
-    }
-    pix += sow;
-    r += R_VAL(pix) * j;
-    g += G_VAL(pix) * j;
-    b += B_VAL(pix) * j;
-    a += A_VAL(pix) * j;
+    for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
+        pix += step;
+        r += qRed(*pix)   * Cxy;
+        g += qGreen(*pix) * Cxy;
+        b += qBlue(*pix)  * Cxy;
+        a += qAlpha(*pix) * Cxy;
+    }
+    pix += step;
+    r += qRed(*pix)   * j;
+    g += qGreen(*pix) * j;
+    b += qBlue(*pix)  * j;
+    a += qAlpha(*pix) * j;
 }
 
 static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
@@ -443,12 +398,12 @@ static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int
         for (int x = dxx; x < end; x++) {
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int r, g, b, a;
-            qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, r, g, b, a);
+            qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a);
 
             int xap = xapoints[x];
             if (xap > 0) {
                 int rr, gg, bb, aa;
-                qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+                qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
 
                 r = r * (256 - xap);
                 g = g * (256 - xap);
@@ -484,12 +439,12 @@ static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int r, g, b, a;
-            qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, r, g, b, a);
+            qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a);
 
             int yap = yapoints[dyy + y];
             if (yap > 0) {
                 int rr, gg, bb, aa;
-                qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, rr, gg, bb, aa);
+                qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
 
                 r = r * (256 - yap);
                 g = g * (256 - yap);
@@ -528,7 +483,7 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int rx, gx, bx, ax;
-            qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+            qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
 
             int r = ((rx>>4) * yap);
             int g = ((gx>>4) * yap);
@@ -538,14 +493,14 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
             int j;
             for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
                 sptr += sow;
-                qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+                qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
                 r += ((rx>>4) * Cy);
                 g += ((gx>>4) * Cy);
                 b += ((bx>>4) * Cy);
                 a += ((ax>>4) * Cy);
             }
             sptr += sow;
-            qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+            qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
 
             r += ((rx>>4) * j);
             g += ((gx>>4) * j);
@@ -609,40 +564,22 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
 }
 
 
-inline static void qt_qimageScaleAARGB_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b)
+inline static void qt_qimageScaleAARGB_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b)
 {
-    r = R_VAL(pix) * xap;
-    g = G_VAL(pix) * xap;
-    b = B_VAL(pix) * xap;
+    r = qRed(*pix)   * xyap;
+    g = qGreen(*pix) * xyap;
+    b = qBlue(*pix)  * xyap;
     int j;
-    for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
-        pix++;
-        r += R_VAL(pix) * Cx;
-        g += G_VAL(pix) * Cx;
-        b += B_VAL(pix) * Cx;
-    }
-    pix++;
-    r += R_VAL(pix) * j;
-    g += G_VAL(pix) * j;
-    b += B_VAL(pix) * j;
-}
-
-inline static void qt_qimageScaleAARGB_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b)
-{
-    r = R_VAL(pix) * yap;
-    g = G_VAL(pix) * yap;
-    b = B_VAL(pix) * yap;
-    int j;
-    for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
-        pix += sow;
-        r += R_VAL(pix) * Cy;
-        g += G_VAL(pix) * Cy;
-        b += B_VAL(pix) * Cy;
-    }
-    pix += sow;
-    r += R_VAL(pix) * j;
-    g += G_VAL(pix) * j;
-    b += B_VAL(pix) * j;
+    for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
+        pix += step;
+        r += qRed(*pix)   * Cxy;
+        g += qGreen(*pix) * Cxy;
+        b += qBlue(*pix)  * Cxy;
+    }
+    pix += step;
+    r += qRed(*pix)   * j;
+    g += qGreen(*pix) * j;
+    b += qBlue(*pix)  * j;
 }
 
 static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
@@ -665,12 +602,12 @@ static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *
         for (int x = dxx; x < end; x++) {
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int r, g, b;
-            qt_qimageScaleAARGB_helper_y(sptr, yap, Cy, sow, r, g, b);
+            qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b);
 
             int xap = xapoints[x];
             if (xap > 0) {
                 int rr, bb, gg;
-                qt_qimageScaleAARGB_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb);
+                qt_qimageScaleAARGB_helper(sptr + 1, yap, Cy, sow, rr, gg, bb);
 
                 r = r * (256 - xap);
                 g = g * (256 - xap);
@@ -704,12 +641,12 @@ static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int r, g, b;
-            qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, r, g, b);
+            qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b);
 
             int yap = yapoints[dyy + y];
             if (yap > 0) {
                 int rr, bb, gg;
-                qt_qimageScaleAARGB_helper_x(sptr + sow, xap, Cx, rr, gg, bb);
+                qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb);
 
                 r = r * (256 - yap);
                 g = g * (256 - yap);
@@ -745,7 +682,7 @@ static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
             int rx, gx, bx;
-            qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+            qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
 
             int r = (rx >> 4) * yap;
             int g = (gx >> 4) * yap;
@@ -754,14 +691,14 @@ static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest
             int j;
             for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
                 sptr += sow;
-                qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+                qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
 
                 r += (rx >> 4) * Cy;
                 g += (gx >> 4) * Cy;
                 b += (bx >> 4) * Cy;
             }
             sptr += sow;
-            qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+            qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
 
             r += (rx >> 4) * j;
             g += (gx >> 4) * j;
@@ -794,11 +731,11 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
     }
 
     if (src.hasAlphaChannel())
-        qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
-                           0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
+        qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
+                             0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
     else
-        qt_qimageScaleRgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
-                          0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
+        qt_qimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0),
+                            0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
 
     qimageFreeScaleInfo(scaleinfo);
     return buffer;
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index 565ea4daa1df05c0d5b8bd1d52236baf0eb6d897..303e0fd98077f7f7bf984757f38a9cf933a775d7 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -41,33 +41,17 @@ QT_BEGIN_NAMESPACE
 
 using namespace QImageScale;
 
-inline static __m128i qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, const __m128i vxap, const __m128i vCx)
+inline static __m128i qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, const __m128i vxyap, const __m128i vCxy)
 {
     __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
-    __m128i vx = _mm_mullo_epi32(vpix, vxap);
+    __m128i vx = _mm_mullo_epi32(vpix, vxyap);
     int i;
-    for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
-        pix++;
+    for (i = (1 << 14) - xyap; i > Cxy; i -= Cxy) {
+        pix += step;
         vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
-        vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCx));
+        vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCxy));
     }
-    pix++;
-    vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
-    vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
-    return vx;
-}
-
-inline static __m128i qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, const __m128i vyap, const __m128i vCy)
-{
-    __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
-    __m128i vx = _mm_mullo_epi32(vpix, vyap);
-    int i;
-    for (i = (1 << 14) - yap; i > Cy; i -= Cy) {
-        pix += sow;
-        vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
-        vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCy));
-    }
-    pix += sow;
+    pix += step;
     vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
     vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
     return vx;
@@ -97,13 +81,13 @@ void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *d
         unsigned int *dptr = dest + dx + ((y + dy) * dow);
         for (int x = dxx; x < end; x++) {
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
-            __m128i vx = qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, vyap, vCy);
+            __m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy);
 
             int xap = xapoints[x];
             if (xap > 0) {
                 const __m128i vxap = _mm_set1_epi32(xap);
                 const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
-                __m128i vr = qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, vyap, vCy);
+                __m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy);
 
                 vx = _mm_mullo_epi32(vx, vinvxap);
                 vr = _mm_mullo_epi32(vr, vxap);
@@ -145,13 +129,13 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d
             const __m128i vxap = _mm_set1_epi32(xap);
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
-            __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+            __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
 
             int yap = yapoints[dyy + y];
             if (yap > 0) {
                 const __m128i vyap = _mm_set1_epi32(yap);
                 const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
-                __m128i vr = qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, vxap, vCx);
+                __m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx);
 
                 vx = _mm_mullo_epi32(vx, vinvyap);
                 vr = _mm_mullo_epi32(vr, vyap);
@@ -194,17 +178,17 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
             const __m128i vxap = _mm_set1_epi32(xap);
 
             const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
-            __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+            __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
             __m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
 
             int j;
             for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
                 sptr += sow;
-                vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+                vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
                 vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy));
             }
             sptr += sow;
-            vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+            vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
             vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
 
             vr = _mm_srli_epi32(vr, 24);
diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp
index 3adc5e94119ba7900903949e08ea50e321c7c8b9..547cedf51f2138a666ab016665d912362a339d9e 100644
--- a/src/gui/painting/qpagedpaintdevice.cpp
+++ b/src/gui/painting/qpagedpaintdevice.cpp
@@ -36,6 +36,10 @@
 
 QT_BEGIN_NAMESPACE
 
+QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate()
+{
+}
+
 /*!
     \class QPagedPaintDevice
     \inmodule QtGui
diff --git a/src/gui/painting/qpagedpaintdevice_p.h b/src/gui/painting/qpagedpaintdevice_p.h
index 62f69747dbf1942ded1a48be8c4894a8a4242529..30b1c0a1e6a82a483a4225aa5a517b2464920646 100644
--- a/src/gui/painting/qpagedpaintdevice_p.h
+++ b/src/gui/painting/qpagedpaintdevice_p.h
@@ -61,9 +61,7 @@ public:
     {
     }
 
-    virtual ~QPagedPaintDevicePrivate()
-    {
-    }
+    virtual ~QPagedPaintDevicePrivate();
 
     // ### Qt6 Remove these and make public class methods virtual
     virtual bool setPageLayout(const QPageLayout &newPageLayout)
diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp
index 4ee3d91ea3eb0898a4aa0261a09470fe668ad0ac..27d4bbcfd785407f9f9a6ae267a228616ec22100 100644
--- a/src/gui/painting/qpaintdevice.cpp
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -35,7 +35,7 @@
 
 QT_BEGIN_NAMESPACE
 
-QPaintDevice::QPaintDevice()
+QPaintDevice::QPaintDevice() Q_DECL_NOEXCEPT
 {
     reserved = 0;
     painters = 0;
diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h
index c4ef9db7662be05982872fbf7987fec4cb8a305c..b699956e998b21f79729c942f65ee21c3f53107b 100644
--- a/src/gui/painting/qpaintdevice.h
+++ b/src/gui/painting/qpaintdevice.h
@@ -85,7 +85,7 @@ public:
     // ### and need to access this constant. Add it here as a static constant for now
     static qreal devicePixelRatioFScale;
 protected:
-    QPaintDevice();
+    QPaintDevice() Q_DECL_NOEXCEPT;
     virtual int metric(PaintDeviceMetric metric) const;
     virtual void initPainter(QPainter *painter) const;
     virtual QPaintDevice *redirected(QPoint *offset) const;
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index 6271c8f9e6f6d6fb76dbeffc81b2cff7cf855c75..bf1f31a85bc997377d7d3d7304d62f0498294735 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -968,6 +968,10 @@ QRect QPaintEngine::systemRect() const
     return d_func()->systemRect;
 }
 
+QPaintEnginePrivate::~QPaintEnginePrivate()
+{
+}
+
 void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
 {
     if (!ti.glyphs.numGlyphs)
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index c58662ede48a0826ed7eeffa4827e823f71712c8..918c98997b83c02d65ed4d7fdad312528d4f2e8d 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -60,7 +60,8 @@ class Q_GUI_EXPORT QPaintEnginePrivate
 public:
     QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipDevice(0), hasSystemTransform(0),
                             hasSystemViewport(0) {}
-    virtual ~QPaintEnginePrivate() { }
+    virtual ~QPaintEnginePrivate();
+
     QPaintDevice *pdev;
     QPaintEngine *q_ptr;
     QRegion systemClip;
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 0f80cd18a017258b711f3a93fa98d1a6ca58f390..f00bc8d9df835648ce79480ac18369cb01debfd4 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -238,7 +238,7 @@ bool QPaintEngineExPrivate::hasClipOperations() const
  *
  */
 
-static QPainterPath::ElementType qpaintengineex_ellipse_types[] = {
+static const QPainterPath::ElementType qpaintengineex_ellipse_types[] = {
     QPainterPath::MoveToElement,
     QPainterPath::CurveToElement,
     QPainterPath::CurveToDataElement,
@@ -257,7 +257,7 @@ static QPainterPath::ElementType qpaintengineex_ellipse_types[] = {
     QPainterPath::CurveToDataElement
 };
 
-static QPainterPath::ElementType qpaintengineex_line_types_16[] = {
+static const QPainterPath::ElementType qpaintengineex_line_types_16[] = {
     QPainterPath::MoveToElement, QPainterPath::LineToElement,
     QPainterPath::MoveToElement, QPainterPath::LineToElement,
     QPainterPath::MoveToElement, QPainterPath::LineToElement,
@@ -276,7 +276,7 @@ static QPainterPath::ElementType qpaintengineex_line_types_16[] = {
     QPainterPath::MoveToElement, QPainterPath::LineToElement
 };
 
-static QPainterPath::ElementType qpaintengineex_rect4_types_32[] = {
+static const QPainterPath::ElementType qpaintengineex_rect4_types_32[] = {
     QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 1
     QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 2
     QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 3
@@ -312,7 +312,7 @@ static QPainterPath::ElementType qpaintengineex_rect4_types_32[] = {
 };
 
 
-static QPainterPath::ElementType qpaintengineex_roundedrect_types[] = {
+static const QPainterPath::ElementType qpaintengineex_roundedrect_types[] = {
     QPainterPath::MoveToElement,
     QPainterPath::LineToElement,
     QPainterPath::CurveToElement,
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index d3e8b542f0d872497e817f55c8fb727cd8ec674f..99a9f823a1b7f3f688d340b8e09f54499aac7431 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7441,7 +7441,7 @@ start_lengthVariant:
         }
     }
 
-    QList<QTextLayout::FormatRange> underlineFormats;
+    QVector<QTextLayout::FormatRange> underlineFormats;
     int length = offset - old_offset;
     if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
         QChar *cout = text.data() + old_offset;
@@ -7515,7 +7515,7 @@ start_lengthVariant:
         engine.forceJustification = true;
     QTextLayout textLayout(&engine);
     textLayout.setCacheEnabled(true);
-    textLayout.setAdditionalFormats(underlineFormats);
+    textLayout.setFormats(underlineFormats);
 
     if (finalText.isEmpty()) {
         height = fm.height();
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index e3c6eabbc33249dbadcce1417491af8ba806cf18..e2f267d7eee444d09cc7e001d33db4d35729bd5b 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -521,7 +521,7 @@ void QPainterPath::setElementPositionAt(int i, qreal x, qreal y)
 /*!
     Constructs an empty QPainterPath object.
 */
-QPainterPath::QPainterPath()
+QPainterPath::QPainterPath() Q_DECL_NOEXCEPT
     : d_ptr(0)
 {
 }
@@ -3057,20 +3057,19 @@ qreal QPainterPath::slopeAtPercent(qreal t) const
     //tangent line
     qreal slope = 0;
 
-#define SIGN(x) ((x < 0)?-1:1)
     if (m1)
         slope = m2/m1;
     else {
-        //windows doesn't define INFINITY :(
-#ifdef INFINITY
-        slope = INFINITY*SIGN(m2);
-#else
-        if (sizeof(qreal) == sizeof(double)) {
-            return 1.79769313486231570e+308;
+        if (std::numeric_limits<qreal>::has_infinity) {
+            slope = (m2  < 0) ? -std::numeric_limits<qreal>::infinity()
+                              : std::numeric_limits<qreal>::infinity();
         } else {
-            return ((qreal)3.40282346638528860e+38);
+            if (sizeof(qreal) == sizeof(double)) {
+                return 1.79769313486231570e+308;
+            } else {
+                return ((qreal)3.40282346638528860e+38);
+            }
         }
-#endif
     }
 
     return slope;
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index eb32782a96204eb73e2aa4670e3250558b491b1b..4a7bd98234a050082f5056bea70dc24fbdf6ca39 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -81,16 +81,16 @@ public:
         inline bool operator!=(const Element &e) const { return !operator==(e); }
     };
 
-    QPainterPath();
+    QPainterPath() Q_DECL_NOEXCEPT;
     explicit QPainterPath(const QPointF &startPoint);
     QPainterPath(const QPainterPath &other);
     QPainterPath &operator=(const QPainterPath &other);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QPainterPath &operator=(QPainterPath &&other)
+    inline QPainterPath &operator=(QPainterPath &&other) Q_DECL_NOEXCEPT
     { qSwap(d_ptr, other.d_ptr); return *this; }
 #endif
     ~QPainterPath();
-    inline void swap(QPainterPath &other) { d_ptr.swap(other.d_ptr); }
+    inline void swap(QPainterPath &other) Q_DECL_NOEXCEPT { d_ptr.swap(other.d_ptr); }
 
     void closeSubpath();
 
@@ -147,8 +147,8 @@ public:
     void translate(qreal dx, qreal dy);
     inline void translate(const QPointF &offset);
 
-    QPainterPath translated(qreal dx, qreal dy) const;
-    inline QPainterPath translated(const QPointF &offset) const;
+    QPainterPath translated(qreal dx, qreal dy) const Q_REQUIRED_RESULT;
+    inline QPainterPath translated(const QPointF &offset) const Q_REQUIRED_RESULT;
 
     QRectF boundingRect() const;
     QRectF controlPointRect() const;
@@ -158,7 +158,7 @@ public:
 
     bool isEmpty() const;
 
-    QPainterPath toReversed() const;
+    QPainterPath toReversed() const Q_REQUIRED_RESULT;
     QList<QPolygonF> toSubpathPolygons(const QMatrix &matrix = QMatrix()) const;
     QList<QPolygonF> toFillPolygons(const QMatrix &matrix = QMatrix()) const;
     QPolygonF toFillPolygon(const QMatrix &matrix = QMatrix()) const;
@@ -178,12 +178,12 @@ public:
 
     bool intersects(const QPainterPath &p) const;
     bool contains(const QPainterPath &p) const;
-    QPainterPath united(const QPainterPath &r) const;
-    QPainterPath intersected(const QPainterPath &r) const;
-    QPainterPath subtracted(const QPainterPath &r) const;
-    QPainterPath subtractedInverted(const QPainterPath &r) const;
+    QPainterPath united(const QPainterPath &r) const Q_REQUIRED_RESULT;
+    QPainterPath intersected(const QPainterPath &r) const Q_REQUIRED_RESULT;
+    QPainterPath subtracted(const QPainterPath &r) const Q_REQUIRED_RESULT;
+    QPainterPath subtractedInverted(const QPainterPath &r) const Q_REQUIRED_RESULT;
 
-    QPainterPath simplified() const;
+    QPainterPath simplified() const Q_REQUIRED_RESULT;
 
     bool operator==(const QPainterPath &other) const;
     bool operator!=(const QPainterPath &other) const;
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 9b1f5e334a066c70df54a6cfd3e2e48d979ffb76..011094b56b43ca28cede5ad257b9ff41b5c4017b 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -384,7 +384,7 @@ QByteArray QPdf::generateDashes(const QPen &pen)
 
 
 
-static const char* pattern_for_brush[] = {
+static const char* const pattern_for_brush[] = {
     0, // NoBrush
     0, // SolidPattern
     "0 J\n"
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 24ea3f4cdd721442d58d4abca1762e6792348ca6..62492980de3d9f2c4c8e5e96d426ded6ee37b130 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -83,9 +83,10 @@ public:
 
 struct QBackingstoreTextureInfo
 {
-    QWidget *widget; // may be null
+    void *source; // may be null
     GLuint textureId;
     QRect rect;
+    QRect clipRect;
     QPlatformTextureList::Flags flags;
 };
 
@@ -124,10 +125,10 @@ GLuint QPlatformTextureList::textureId(int index) const
     return d->textures.at(index).textureId;
 }
 
-QWidget *QPlatformTextureList::widget(int index)
+void *QPlatformTextureList::source(int index)
 {
     Q_D(const QPlatformTextureList);
-    return d->textures.at(index).widget;
+    return d->textures.at(index).source;
 }
 
 QPlatformTextureList::Flags QPlatformTextureList::flags(int index) const
@@ -142,6 +143,12 @@ QRect QPlatformTextureList::geometry(int index) const
     return d->textures.at(index).rect;
 }
 
+QRect QPlatformTextureList::clipRect(int index) const
+{
+    Q_D(const QPlatformTextureList);
+    return d->textures.at(index).clipRect;
+}
+
 void QPlatformTextureList::lock(bool on)
 {
     Q_D(QPlatformTextureList);
@@ -157,13 +164,15 @@ bool QPlatformTextureList::isLocked() const
     return d->locked;
 }
 
-void QPlatformTextureList::appendTexture(QWidget *widget, GLuint textureId, const QRect &geometry, Flags flags)
+void QPlatformTextureList::appendTexture(void *source, GLuint textureId, const QRect &geometry,
+                                         const QRect &clipRect, Flags flags)
 {
     Q_D(QPlatformTextureList);
     QBackingstoreTextureInfo bi;
-    bi.widget = widget;
+    bi.source = source;
     bi.textureId = textureId;
     bi.rect = geometry;
+    bi.clipRect = clipRect;
     bi.flags = flags;
     d->textures.append(bi);
 }
@@ -198,7 +207,7 @@ void QPlatformTextureList::clear()
 
 #ifndef QT_NO_OPENGL
 
-static QRect deviceRect(const QRect &rect, QWindow *window)
+static inline QRect deviceRect(const QRect &rect, QWindow *window)
 {
     QRect deviceRect(rect.topLeft() * window->devicePixelRatio(),
                      rect.size() * window->devicePixelRatio());
@@ -219,6 +228,32 @@ static QRegion deviceRegion(const QRegion &region, QWindow *window)
     return deviceRegion;
 }
 
+static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
+{
+    return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
+                 topLeftRect.width(), topLeftRect.height());
+}
+
+static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
+                 QOpenGLTextureBlitter *blitter)
+{
+    const QRect rectInWindow = textures->geometry(idx);
+    QRect clipRect = textures->clipRect(idx);
+    if (clipRect.isEmpty())
+        clipRect = QRect(QPoint(0, 0), rectInWindow.size());
+    const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
+    const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
+
+    const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(deviceRect(clippedRectInWindow, window),
+                                                                     deviceWindowRect);
+
+    const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window),
+                                                                     deviceRect(rectInWindow, window).size(),
+                                                                     QOpenGLTextureBlitter::OriginBottomLeft);
+
+    blitter->blit(textures->textureId(idx), target, source);
+}
+
 /*!
     Flushes the given \a region from the specified \a window onto the
     screen, and composes it with the specified \a textures.
@@ -254,15 +289,12 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
 
     d_ptr->blitter->bind();
 
-    QRect windowRect(QPoint(), window->size() * window->devicePixelRatio());
+    const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window);
 
     // Textures for renderToTexture widgets.
     for (int i = 0; i < textures->count(); ++i) {
-        if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
-            QRect targetRect = deviceRect(textures->geometry(i), window);
-            QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, windowRect);
-            d_ptr->blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
-        }
+        if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
+            blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
     }
 
     funcs->glEnable(GL_BLEND);
@@ -272,6 +304,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
     // semi-transparency even when it is not wanted.
     funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 
+    // Backingstore texture with the normal widgets.
     GLuint textureId = 0;
     QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft;
     if (QPlatformGraphicsBuffer *graphicsBuffer = this->graphicsBuffer()) {
@@ -307,12 +340,15 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
             origin = QOpenGLTextureBlitter::OriginBottomLeft;
         textureId = d_ptr->textureId;
     } else {
-        // Backingstore texture with the normal widgets.
-        textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &d_ptr->needsSwizzle);
+        TextureFlags flags = 0;
+        textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &flags);
+        d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0;
+        if (flags & TextureFlip)
+            origin = QOpenGLTextureBlitter::OriginBottomLeft;
     }
 
     if (textureId) {
-        QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), windowRect);
+        QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), deviceWindowRect);
         if (d_ptr->needsSwizzle)
             d_ptr->blitter->setSwizzleRB(true);
         d_ptr->blitter->blit(textureId, target, origin);
@@ -322,11 +358,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
 
     // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
     for (int i = 0; i < textures->count(); ++i) {
-        if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
-            QRect targetRect = deviceRect(textures->geometry(i), window);
-            QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, windowRect);
-            d_ptr->blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
-        }
+        if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
+            blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
     }
 
     funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -354,43 +387,55 @@ QImage QPlatformBackingStore::toImage() const
   backingstore as an OpenGL texture. \a dirtyRegion is the part of the
   backingstore which may have changed since the last call to this function. The
   caller of this function must ensure that there is a current context.
+
   The size of the texture is returned in \a textureSize.
 
   The ownership of the texture is not transferred. The caller must not store
   the return value between calls, but instead call this function before each use.
 
-  The default implementation returns a cached texture if \a dirtyRegion is
-  empty and the window has not been resized, otherwise it retrieves the
-  content using toImage() and performs a texture upload.
+  The default implementation returns a cached texture if \a dirtyRegion is empty and
+  \a textureSize matches the backingstore size, otherwise it retrieves the content using
+  toImage() and performs a texture upload. This works only if the value of \a textureSize
+  is preserved between the calls to this function.
+
+  If the red and blue components have to swapped, \a flags will be set to include \c
+  TextureSwizzle. This allows creating textures from images in formats like
+  QImage::Format_RGB32 without any further image conversion. Instead, the swizzling will
+  be done in the shaders when performing composition. Other formats, that do not need
+  such swizzling due to being already byte ordered RGBA, for example
+  QImage::Format_RGBA8888, must result in having \a needsSwizzle set to false.
 
-  If the red and blue components have to swapped, \a needsSwizzle will be set to \c true.
-  This allows creating textures from images in formats like QImage::Format_RGB32 without
-  any further image conversion. Instead, the swizzling will be done in the shaders when
-  performing composition. Other formats, that do not need such swizzling due to being
-  already byte ordered RGBA, for example QImage::Format_RGBA8888, must result in having \a
-  needsSwizzle set to false.
+  If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
+  flags will be set to include \c TextureFlip.
  */
-GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const
+GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
 {
+    Q_ASSERT(textureSize);
+    Q_ASSERT(flags);
+
     QImage image = toImage();
     QSize imageSize = image.size();
-    if (imageSize.isEmpty())
+
+    *flags = 0;
+    if (image.format() == QImage::Format_RGB32)
+        *flags |= TextureSwizzle;
+
+    if (imageSize.isEmpty()) {
+        *textureSize = imageSize;
         return 0;
+    }
 
-    bool resized = d_ptr->textureSize != imageSize;
+    // Must rely on the input only, not d_ptr.
+    // With the default composeAndFlush() textureSize is &d_ptr->textureSize.
+    bool resized = *textureSize != imageSize;
     if (dirtyRegion.isEmpty() && !resized)
         return d_ptr->textureId;
 
+    *textureSize = imageSize;
+
     // Fast path for RGB32 and RGBA8888, convert everything else to RGBA8888.
-    if (image.format() == QImage::Format_RGB32) {
-        if (needsSwizzle)
-            *needsSwizzle = true;
-    } else {
-        if (needsSwizzle)
-            *needsSwizzle = false;
-        if (image.format() != QImage::Format_RGBA8888)
-            image = image.convertToFormat(QImage::Format_RGBA8888);
-    }
+    if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888)
+        image = image.convertToFormat(QImage::Format_RGBA8888);
 
     QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
 
@@ -412,8 +457,6 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
 
         funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
                             const_cast<uchar*>(image.constBits()));
-        if (textureSize)
-            *textureSize = imageSize;
     } else {
         funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
         QRect imageRect = image.rect();
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index df98ebf51b7a127997c08d4edd6b100453cbfed2..eac97e9cf69c03538836699e43ed1b4be1a82ce2 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -82,12 +82,14 @@ public:
     bool isEmpty() const { return count() == 0; }
     GLuint textureId(int index) const;
     QRect geometry(int index) const;
-    QWidget *widget(int index);
+    QRect clipRect(int index) const;
+    void *source(int index);
     Flags flags(int index) const;
     void lock(bool on);
     bool isLocked() const;
 
-    void appendTexture(QWidget *widget, GLuint textureId, const QRect &geometry, Flags flags = 0);
+    void appendTexture(void *source, GLuint textureId, const QRect &geometry,
+                       const QRect &clipRect = QRect(), Flags flags = 0);
     void clear();
 
  Q_SIGNALS:
@@ -114,7 +116,12 @@ public:
                                  QPlatformTextureList *textures, QOpenGLContext *context,
                                  bool translucentBackground);
     virtual QImage toImage() const;
-    virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const;
+    enum TextureFlag {
+        TextureSwizzle = 0x01,
+        TextureFlip = 0x02
+    };
+    Q_DECLARE_FLAGS(TextureFlags, TextureFlag)
+    virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
 #endif
 
     virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
@@ -130,6 +137,10 @@ private:
     QPlatformBackingStorePrivate *d_ptr;
 };
 
+#ifndef QT_NO_OPENGL
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags)
+#endif
+
 QT_END_NAMESPACE
 
 #endif // QPLATFORMBACKINGSTORE_H
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index ee7d4d31ad7710f0154b30ad0095391f350ffdbf..1549ebe2b5c918c83e56da72872fb4c81dd8748a 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -138,7 +138,7 @@ public:
     void translate(const QPointF &offset);
 
     inline QPolygonF translated(qreal dx, qreal dy) const;
-    QPolygonF translated(const QPointF &offset) const;
+    QPolygonF translated(const QPointF &offset) const Q_REQUIRED_RESULT;
 
     QPolygon toPolygon() const;
 
@@ -148,9 +148,9 @@ public:
 
     bool containsPoint(const QPointF &pt, Qt::FillRule fillRule) const;
 
-    QPolygonF united(const QPolygonF &r) const;
-    QPolygonF intersected(const QPolygonF &r) const;
-    QPolygonF subtracted(const QPolygonF &r) const;
+    QPolygonF united(const QPolygonF &r) const Q_REQUIRED_RESULT;
+    QPolygonF intersected(const QPolygonF &r) const Q_REQUIRED_RESULT;
+    QPolygonF subtracted(const QPolygonF &r) const Q_REQUIRED_RESULT;
 };
 
 inline QPolygonF::QPolygonF(int asize) : QVector<QPointF>(asize) {}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index bab07b5a5dac3d3e972906ccc5c8c1cbf2569681..ab2404e88738db6eeaa680ffce80be7ff5840447 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -66,10 +66,10 @@ public:
     ~QRegion();
     QRegion &operator=(const QRegion &);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QRegion &operator=(QRegion &&other)
+    inline QRegion &operator=(QRegion &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); return *this; }
 #endif
-    inline void swap(QRegion &other) { qSwap(d, other.d); }
+    inline void swap(QRegion &other) Q_DECL_NOEXCEPT { qSwap(d, other.d); }
     bool isEmpty() const;
     bool isNull() const;
 
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index eda65b8e2f290813ad12dcdd7848f20582ccf6e0..f967c091df2db942dc8ca32102ae8f40adfb1ca7 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -201,7 +201,7 @@ public:
     QStroker();
     ~QStroker();
 
-    void setStrokeWidth(qfixed width) { m_strokeWidth = width; }
+    void setStrokeWidth(qfixed width) { m_strokeWidth = width; m_curveThreshold = width >= 1 ? 1.0/width : 0.5;}
     qfixed strokeWidth() const { return m_strokeWidth; }
 
     void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); }
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 4c879cf05d0b29e871f4ab1508b3a0cbc9ca61be..056fd8b70164999c21da32ffdad332ae8ee8a77e 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -42,6 +42,11 @@ QT_BEGIN_NAMESPACE
 
 // #define CACHE_DEBUG
 
+// out-of-line to avoid vtable duplication, breaking e.g. RTTI
+QTextureGlyphCache::~QTextureGlyphCache()
+{
+}
+
 int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
 {
     // Test 12 different subpixel positions since it factors into 3*4 so it gives
@@ -262,6 +267,11 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
  * QImageTextureGlyphCache
  */
 
+// out-of-line to avoid vtable duplication, breaking e.g. RTTI
+QImageTextureGlyphCache::~QImageTextureGlyphCache()
+{
+}
+
 void QImageTextureGlyphCache::resizeTextureData(int width, int height)
 {
     m_image = m_image.copy(0, 0, width, height);
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index c9e7060b0d20e427d51b5d0737f8f75d34586325..7dd8277a45f972dd1911e987dae7c6f31ba9b9c1 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -72,7 +72,7 @@ public:
                                                m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
         { }
 
-    virtual ~QTextureGlyphCache() { }
+    ~QTextureGlyphCache();
 
     struct GlyphAndSubPixelPosition
     {
@@ -158,6 +158,8 @@ class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
 public:
     QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
         : QTextureGlyphCache(format, matrix) { }
+    ~QImageTextureGlyphCache();
+
     virtual void createTextureData(int width, int height) Q_DECL_OVERRIDE;
     virtual void resizeTextureData(int width, int height) Q_DECL_OVERRIDE;
     virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE;
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4b3f0b30dc02f0d66493232707914fad76885e80..fca2b72249c8ee88fbcb74c48b2fb97faa0a0e3d 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1102,7 +1102,7 @@ QDataStream & operator>>(QDataStream &s, QTransform &t)
 #ifndef QT_NO_DEBUG_STREAM
 QDebug operator<<(QDebug dbg, const QTransform &m)
 {
-    static const char *typeStr[] =
+    static const char *const typeStr[] =
     {
         "TxNone",
         "TxTranslate",
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp
index 70be92535d16fb8dcbc843c9f146d8a3597b874d..7735fd6b467b1ee13067d1c76152b045e7037e21 100644
--- a/src/gui/text/qabstracttextdocumentlayout.cpp
+++ b/src/gui/text/qabstracttextdocumentlayout.cpp
@@ -40,6 +40,15 @@
 
 QT_BEGIN_NAMESPACE
 
+QAbstractTextDocumentLayoutPrivate::~QAbstractTextDocumentLayoutPrivate()
+{
+}
+
+QTextObjectInterface::~QTextObjectInterface()
+{
+    // must be empty until ### Qt 6
+}
+
 /*!
     \class QAbstractTextDocumentLayout
     \reentrant
diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h
index 27135b047656c1295554801dfb07b914ed5e7b37..68e7a0e4e9a3f50be2b2a7dc39d33796d762f313 100644
--- a/src/gui/text/qabstracttextdocumentlayout.h
+++ b/src/gui/text/qabstracttextdocumentlayout.h
@@ -126,7 +126,7 @@ private:
 class Q_GUI_EXPORT QTextObjectInterface
 {
 public:
-    virtual ~QTextObjectInterface() {}
+    virtual ~QTextObjectInterface();
     virtual QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
     virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
 };
diff --git a/src/gui/text/qabstracttextdocumentlayout_p.h b/src/gui/text/qabstracttextdocumentlayout_p.h
index 505135fa4babca512a4e4d82dda9e1c50919c133..a7f28ebf960299d55bf36127bb21aa9849b20ceb 100644
--- a/src/gui/text/qabstracttextdocumentlayout_p.h
+++ b/src/gui/text/qabstracttextdocumentlayout_p.h
@@ -58,13 +58,14 @@ struct QTextObjectHandler
 };
 typedef QHash<int, QTextObjectHandler> HandlerHash;
 
-class QAbstractTextDocumentLayoutPrivate : public QObjectPrivate
+class Q_GUI_EXPORT QAbstractTextDocumentLayoutPrivate : public QObjectPrivate
 {
 public:
     Q_DECLARE_PUBLIC(QAbstractTextDocumentLayout)
 
     inline QAbstractTextDocumentLayoutPrivate()
         : paintDevice(0) {}
+    ~QAbstractTextDocumentLayoutPrivate();
 
     inline void setDocument(QTextDocument *doc) {
         document = doc;
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index cc78ea7f454b8237129053899834659a7cd018b7..72e4197fc596d8113c2fa26b2384a941b6478f00 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -237,7 +237,7 @@ public:
     operator QVariant() const;
     bool isCopyOf(const QFont &) const;
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QFont &operator=(QFont &&other)
+    inline QFont &operator=(QFont &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask);  return *this; }
 #endif
 
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 126f0bf3ecd3d30ef0a0ec7df188ae8fc619cb72..dae4d560a8e522de00a66166a4c002a94b25bb01 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -121,6 +121,8 @@ static int getFontWeight(const QString &weightString)
             return QFont::DemiBold;
         return QFont::Bold;
     }
+    if (s.contains(QLatin1String("thin")))
+        return QFont::Thin;
     if (s.contains(QLatin1String("light")))
         return QFont::Light;
     if (s.contains(QLatin1String("black")))
@@ -346,7 +348,6 @@ struct  QtFontFamily
         populated(false),
         fixedPitch(false),
         name(n), count(0), foundries(0)
-        , askedForFallback(false)
     {
         memset(writingSystems, 0, sizeof(writingSystems));
     }
@@ -364,8 +365,6 @@ struct  QtFontFamily
     int count;
     QtFontFoundry **foundries;
 
-    QStringList fallbackFamilies;
-    bool askedForFallback;
     unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
 
     bool matchesFamilyName(const QString &familyName) const;
@@ -630,6 +629,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
     } else {
         fontDef->pixelSize = desc.size->pixelSize;
     }
+    fontDef->pointSize     = request.pointSize;
 
     fontDef->styleHint     = request.styleHint;
     fontDef->styleStrategy = request.styleStrategy;
@@ -758,6 +758,7 @@ QString qt_resolveFontFamilyAlias(const QString &alias)
 
 static QStringList fallbackFamilies(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
 {
+    // make sure that the db has all fallback families
     QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
     QFontDatabasePrivate *db = privateDb();
 
@@ -883,20 +884,13 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
     QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
     Q_ASSERT(!engine || engine->type() != QFontEngine::Multi);
     if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
-        // make sure that the db has all fallback families
-        if (family && !family->askedForFallback) {
-            QFont::Style fontStyle = QFont::Style(style->key.style);
-            QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
-            if (styleHint == QFont::AnyStyle && request.fixedPitch)
-                styleHint = QFont::TypeWriter;
-            family->fallbackFamilies = fallbackFamilies(family->name, fontStyle, styleHint, QChar::Script(script));
+        QStringList fallbacks = request.fallBackFamilies;
 
-            family->askedForFallback = true;
-        }
+        QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
+        if (styleHint == QFont::AnyStyle && request.fixedPitch)
+            styleHint = QFont::TypeWriter;
 
-        QStringList fallbacks = request.fallBackFamilies;
-        if (family)
-            fallbacks += family->fallbackFamilies;
+        fallbacks += fallbackFamilies(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script));
 
         QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
         QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
@@ -2505,9 +2499,7 @@ bool QFontDatabase::supportsThreadedFontRendering()
 /*!
     \internal
 */
-QFontEngine *
-QFontDatabase::findFont(int script, const QFontPrivate *fp,
-                        const QFontDef &request, bool multi)
+QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
 {
     QMutexLocker locker(fontDatabaseMutex());
 
@@ -2515,6 +2507,11 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
         initializeDb();
 
     QFontEngine *engine;
+
+    // Until we specifically asked not to, try looking for Multi font engine
+    // first, the last '1' indicates that we want Multi font engine instead
+    // of single ones
+    bool multi = !(request.styleStrategy & QFont::NoFontMerging);
     QFontCache::Key key(request, script, multi ? 1 : 0);
     engine = QFontCache::instance()->findEngine(key);
     if (engine) {
@@ -2529,6 +2526,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
     if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
         engine =new QTestFontEngine(request.pixelSize);
         engine->fontDef = request;
+        return engine;
     }
 
     QtFontDesc desc;
@@ -2536,24 +2534,14 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
     int index = match(script, request, family_name, foundry_name, &desc, blackListed);
     if (index >= 0) {
         engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
-        if (!engine)
+        if (engine)
+            initFontDef(desc, request, &engine->fontDef, multi);
+        else
             blackListed.append(index);
     } else {
         FM_DEBUG("  NO MATCH FOUND\n");
     }
 
-    if (engine && engine->type() != QFontEngine::TestFontEngine) {
-        initFontDef(desc, request, &engine->fontDef, engine->type() == QFontEngine::Multi);
-
-        if (fp) {
-            QFontDef def = request;
-            if (def.family.isEmpty()) {
-                def.family = fp->request.family;
-                def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
-            }
-        }
-    }
-
     if (!engine) {
         if (!request.family.isEmpty()) {
             QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
@@ -2583,7 +2571,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
                                 loadDef.family = desc.family->name;
                             engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
                             if (engine)
-                                initFontDef(desc, loadDef, &engine->fontDef, engine->type() == QFontEngine::Multi);
+                                initFontDef(desc, loadDef, &engine->fontDef, multi);
                             else
                                 blackListed.append(index);
                         }
@@ -2598,12 +2586,6 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
         FM_DEBUG("returning box engine");
     }
 
-    if (fp && fp->dpi > 0) {
-        engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
-    } else {
-        engine->fontDef.pointSize = request.pointSize;
-    }
-
     return engine;
 }
 
@@ -2671,12 +2653,16 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
     for (; !fe && it != end; ++it) {
         req.family = *it;
 
-        fe = QFontDatabase::findFont(script, d, req, multi);
-        if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty()) {
-            if (fe->ref.load() == 0)
-                delete fe;
-
-            fe = 0;
+        fe = QFontDatabase::findFont(req, script);
+        if (fe) {
+            if (fe->type() == QFontEngine::Box && !req.family.isEmpty()) {
+                if (fe->ref.load() == 0)
+                    delete fe;
+                fe = 0;
+            } else {
+                if (d->dpi > 0)
+                    fe->fontDef.pointSize = qreal(double((fe->fontDef.pixelSize * 72) / d->dpi));
+            }
         }
 
         // No need to check requested fallback families again
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 6d738d96becbb40e839af864af4062074fe9e2c7..02bc8e8a087dcaa1bf59f9729af78a1c2a9aab46 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -153,7 +153,7 @@ private:
     static void createDatabase();
     static void parseFontName(const QString &name, QString &foundry, QString &family);
     static QString resolveFontFamilyAlias(const QString &family);
-    static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false);
+    static QFontEngine *findFont(const QFontDef &request, int script);
     static void load(const QFontPrivate *d, int script);
 
     friend struct QFontDef;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index b028d868b97169c62cfe256800212f6add7dc594..87e6c30afe34ab29bc1e9a2b9cb61ce326c0c1e4 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1641,7 +1641,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
     request.styleStrategy |= QFont::NoFontMerging;
     request.family = fallbackFamilyAt(at - 1);
 
-    if (QFontEngine *engine = QFontDatabase::findFont(m_script, /*fontprivate = */0, request, /*multi = */false)) {
+    if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {
         engine->fontDef = request;
         return engine;
     }
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 931c71dc63945825a18bce4e08d5bcf23dec8b1e..37be0afccfd593ffb6ee8d43233104e5560a16ee 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -115,7 +115,7 @@ public:
 
 QtFreetypeData::~QtFreetypeData()
 {
-    for (QHash<QFontEngine::FaceId, QFreetypeFace *>::ConstIterator iter = faces.begin(); iter != faces.end(); ++iter)
+    for (QHash<QFontEngine::FaceId, QFreetypeFace *>::ConstIterator iter = faces.cbegin(); iter != faces.cend(); ++iter)
         iter.value()->cleanup();
     faces.clear();
     FT_Done_FreeType(library);
diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp
index 7e16983b6c5344f26314bfba383158e15d7ed299..a678b4c8eacae975462d339f8716ce2b97786328 100644
--- a/src/gui/text/qfontengine_qpf2.cpp
+++ b/src/gui/text/qfontengine_qpf2.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
 //#define DEBUG_HEADER
 //#define DEBUG_FONTENGINE
 
-static QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = {
+static const QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = {
     QFontEngineQPF2::StringType, // FontName
     QFontEngineQPF2::StringType, // FileName
     QFontEngineQPF2::UInt32Type, // FileIndex
diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/gui/text/qfontengineglyphcache.cpp
similarity index 85%
rename from src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm
rename to src/gui/text/qfontengineglyphcache.cpp
index 8f30365186785ba17301ff9a317d885545ec1a49..f6fdfa3ce38d780e5c1dd208c0b59399a9927e3f 100644
--- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm
+++ b/src/gui/text/qfontengineglyphcache.cpp
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -31,18 +31,13 @@
 **
 ****************************************************************************/
 
-#include "qcocoaautoreleasepool.h"
+#include <private/qfontengineglyphcache_p.h>
 
 QT_BEGIN_NAMESPACE
 
-QCocoaAutoReleasePool::QCocoaAutoReleasePool()
+// out-of-line to avoid vtable duplication, breaking e.g. RTTI
+QFontEngineGlyphCache::~QFontEngineGlyphCache()
 {
-    pool = [[NSAutoreleasePool alloc] init];
-}
-
-QCocoaAutoReleasePool::~QCocoaAutoReleasePool()
-{
-    [pool release];
 }
 
 QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index 6cf4d2f1ba358b41719669b59d02e6a279027625..def42c22a3ede0c6b52210515f74583c2672e95a 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -56,7 +56,7 @@
 
 QT_BEGIN_NAMESPACE
 
-class QFontEngineGlyphCache: public QSharedData
+class Q_GUI_EXPORT QFontEngineGlyphCache: public QSharedData
 {
 public:
     QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix)
@@ -64,7 +64,7 @@ public:
         Q_ASSERT(m_format != QFontEngine::Format_None);
     }
 
-    virtual ~QFontEngineGlyphCache() { }
+    virtual ~QFontEngineGlyphCache();
 
     QFontEngine::GlyphFormat glyphFormat() const { return m_format; }
     const QTransform &transform() const { return m_transform; }
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index 12aa2dadb4bb6c6833cb80693d022ba27ad59358..65ec219a991c702c15ee47706cd92483d95bc410 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -58,11 +58,12 @@ public:
 
     QFontMetrics &operator=(const QFontMetrics &);
 #ifdef Q_COMPILER_RVALUE_REFS
-    inline QFontMetrics &operator=(QFontMetrics &&other)
+    inline QFontMetrics &operator=(QFontMetrics &&other) Q_DECL_NOEXCEPT
     { qSwap(d, other.d); return *this; }
 #endif
 
-    void swap(QFontMetrics &other) { qSwap(d, other.d); }
+    void swap(QFontMetrics &other) Q_DECL_NOEXCEPT
+    { qSwap(d, other.d); }
 
     int ascent() const;
     int descent() const;
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index e6d6863134c19f9a2576b6980e81d236f5338789..642313d340a411b0a6278eb6d31e42b4a1eabaf7 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
 
     \ingroup text
     \ingroup shared
-    \mainclass
 
     When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points
     into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 2631cf8d17df6199421443a42746afa4eb3008d4..d5567e173db5f7ed02e21ecea5e90fe44937b4e6 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE
 
    \ingroup text
    \ingroup shared
-   \mainclass
 
    \note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
 
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index 38d83c485ce55a5bbb3dadebb5643f58e78b52b4..f03895a16e7a49aa94473fd94c00fe7a0bda5b13 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -39,6 +39,10 @@
 
 QT_BEGIN_NAMESPACE
 
+QStaticTextUserData::~QStaticTextUserData()
+{
+}
+
 /*!
     \class QStaticText
     \brief The QStaticText class enables optimized drawing of text when the text and its layout
@@ -49,7 +53,6 @@ QT_BEGIN_NAMESPACE
     \ingroup multimedia
     \ingroup text
     \ingroup shared
-    \mainclass
 
     QStaticText provides a way to cache layout data for a block of text so that it can be drawn
     more efficiently than by using QPainter::drawText() in which the layout information is
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 088e49e2fccbde372959cbf16b9ed2590a75b4c6..49ca24d51c9c3dfcd0cf8f42423fc38c89dee0a2 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -52,7 +52,8 @@
 
 QT_BEGIN_NAMESPACE
 
-class QStaticTextUserData
+// ### Qt 6: Unexport again, if QOpenGLStaticTextUserData (the one from QtOpenGL) is gone by then
+class Q_GUI_EXPORT QStaticTextUserData
 {
 public:
     enum Type {
@@ -61,7 +62,7 @@ public:
     };
 
     QStaticTextUserData(Type t) : ref(0), type(t) {}
-    virtual ~QStaticTextUserData() {}
+    virtual ~QStaticTextUserData();
 
     QAtomicInt ref;
     Type type;
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 162c646a9834735d31ee835508ebbdae62413c10..f180a839b70945ada6a8c1b2009032cf167b6de2 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -90,13 +90,13 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
 
     QTextLayout *layout = currentBlock.layout();
 
-    QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();
+    QVector<QTextLayout::FormatRange> ranges = layout->formats();
 
     const int preeditAreaStart = layout->preeditAreaPosition();
     const int preeditAreaLength = layout->preeditAreaText().length();
 
     if (preeditAreaLength != 0) {
-        QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
+        QVector<QTextLayout::FormatRange>::Iterator it = ranges.begin();
         while (it != ranges.end()) {
             if (it->start >= preeditAreaStart
                 && it->start + it->length <= preeditAreaStart + preeditAreaLength) {
@@ -142,7 +142,7 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
     }
 
     if (formatsChanged) {
-        layout->setAdditionalFormats(ranges);
+        layout->setFormats(ranges);
         doc->markContentsDirty(currentBlock.position(), currentBlock.length());
     }
 }
@@ -329,7 +329,7 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc)
         QTextCursor cursor(d->doc);
         cursor.beginEditBlock();
         for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next())
-            blk.layout()->clearAdditionalFormats();
+            blk.layout()->clearFormats();
         cursor.endEditBlock();
     }
     d->doc = doc;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index d3b70aaf267bffebad5982a6dde0764453fdc4cd..3d248f4afc66785898cfc6085292f696acc35e36 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1949,7 +1949,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
         for (QTextBlock srcBlock = firstBlock(), dstBlock = clonedDoc->firstBlock();
              srcBlock.isValid() && dstBlock.isValid();
              srcBlock = srcBlock.next(), dstBlock = dstBlock.next()) {
-            dstBlock.layout()->setAdditionalFormats(srcBlock.layout()->additionalFormats());
+            dstBlock.layout()->setFormats(srcBlock.layout()->formats());
         }
 
         QAbstractTextDocumentLayout *layout = doc->documentLayout();
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index db8a792be74e35f27a1f3eecc5d50e478fb20cd9..5864ca0b1a43fd9062da3429e525917b28b90eff 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -504,8 +504,6 @@ public:
     void layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat,
                      QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat);
     void layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, QFixed width = 0);
-    void pageBreakInsideTable(QTextTable *table, QTextLayoutStruct *layoutStruct);
-
 
     void floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const;
     QFixed findY(QFixed yFrom, const QTextLayoutStruct *layoutStruct, QFixed requiredWidth) const;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 67a19804a3da21aa01f0767f642ee1a7f726a1ea..187ffa5be72b24f2c194f6a60a26ecc178ed3767 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2571,7 +2571,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
     clearLineData();
 }
 
-void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats)
+void QTextEngine::setFormats(const QVector<QTextLayout::FormatRange> &formats)
 {
     if (formats.isEmpty()) {
         if (!specialData)
@@ -2946,17 +2946,17 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
 
 namespace {
 class FormatRangeComparatorByStart {
-    const QList<QTextLayout::FormatRange> &list;
+    const QVector<QTextLayout::FormatRange> &list;
 public:
-    FormatRangeComparatorByStart(const QList<QTextLayout::FormatRange> &list) : list(list) { }
+    FormatRangeComparatorByStart(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
     bool operator()(int a, int b) {
         return list.at(a).start < list.at(b).start;
     }
 };
 class FormatRangeComparatorByEnd {
-    const QList<QTextLayout::FormatRange> &list;
+    const QVector<QTextLayout::FormatRange> &list;
 public:
-    FormatRangeComparatorByEnd(const QList<QTextLayout::FormatRange> &list) : list(list) { }
+    FormatRangeComparatorByEnd(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
     bool operator()(int a, int b) {
         return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length;
     }
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 39b9e0cb5ad3028ce32af78c3c140fc1cc9b5a1a..3590c6da078f2f6663888dc1fb6148286bbae792 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -570,9 +570,9 @@ public:
 
     inline bool hasFormats() const
     { return block.docHandle() || (specialData && !specialData->formats.isEmpty()); }
-    inline QList<QTextLayout::FormatRange> formats() const
-    { return specialData ? specialData->formats : QList<QTextLayout::FormatRange>(); }
-    void setFormats(const QList<QTextLayout::FormatRange> &formats);
+    inline QVector<QTextLayout::FormatRange> formats() const
+    { return specialData ? specialData->formats : QVector<QTextLayout::FormatRange>(); }
+    void setFormats(const QVector<QTextLayout::FormatRange> &formats);
 
 private:
     static void init(QTextEngine *e);
@@ -580,7 +580,7 @@ private:
     struct SpecialData {
         int preeditPosition;
         QString preeditText;
-        QList<QTextLayout::FormatRange> formats;
+        QVector<QTextLayout::FormatRange> formats;
         QVector<QTextCharFormat> resolvedFormats;
         // only used when no docHandle is available
         QScopedPointer<QTextFormatCollection> formatCollection;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 7da3e840411cf6e932f5e071033a1a0a91a11b63..c42054c07cf32efe14b53666828eabd487ab659a 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
     for a specified area in the text layout's content.
     \inmodule QtGui
 
-    \sa QTextLayout::setAdditionalFormats(), QTextLayout::draw()
+    \sa QTextLayout::setFormats(), QTextLayout::draw()
 */
 
 /*!
@@ -485,7 +485,6 @@ QString QTextLayout::preeditAreaText() const
     return d->preeditAreaText();
 }
 
-
 /*!
     Sets the additional formats supported by the text layout to \a formatList.
     The formats are applied with preedit area text in place.
@@ -494,7 +493,20 @@ QString QTextLayout::preeditAreaText() const
 */
 void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
 {
-    d->setFormats(formatList);
+    setFormats(formatList.toVector());
+}
+
+/*!
+    \since 5.6
+
+    Sets the additional formats supported by the text layout to \a formats.
+    The formats are applied with preedit area text in place.
+
+    \sa formats(), clearFormats()
+*/
+void QTextLayout::setFormats(const QVector<FormatRange> &formats)
+{
+    d->setFormats(formats);
 
     if (d->block.docHandle())
         d->block.docHandle()->documentChange(d->block.position(), d->block.length());
@@ -506,6 +518,18 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
     \sa setAdditionalFormats(), clearAdditionalFormats()
 */
 QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
+{
+    return formats().toList();
+}
+
+/*!
+    \since 5.6
+
+    Returns the list of additional formats supported by the text layout.
+
+    \sa setFormats(), clearFormats()
+*/
+QVector<QTextLayout::FormatRange> QTextLayout::formats() const
 {
     return d->formats();
 }
@@ -517,7 +541,19 @@ QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
 */
 void QTextLayout::clearAdditionalFormats()
 {
-    setAdditionalFormats(QList<FormatRange>());
+    clearFormats();
+}
+
+/*!
+    \since 5.6
+
+    Clears the list of additional formats supported by the text layout.
+
+    \sa formats(), setFormats()
+*/
+void QTextLayout::clearFormats()
+{
+    setFormats(QVector<FormatRange>());
 }
 
 /*!
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 47dcd388e2af72418cc75572e2691370cbd504a7..9709af4fd122347f01dfead8e5b7b9333d9d3df5 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -125,10 +125,18 @@ public:
         int start;
         int length;
         QTextCharFormat format;
+
+        friend bool operator==(const FormatRange &lhs, const FormatRange &rhs)
+        { return lhs.start == rhs.start && lhs.length == rhs.length && lhs.format == rhs.format; }
+        friend bool operator!=(const FormatRange &lhs, const FormatRange &rhs)
+        { return !operator==(lhs, rhs); }
     };
     void setAdditionalFormats(const QList<FormatRange> &overrides);
     QList<FormatRange> additionalFormats() const;
     void clearAdditionalFormats();
+    void setFormats(const QVector<FormatRange> &overrides);
+    QVector<FormatRange> formats() const;
+    void clearFormats();
 
     void setCacheEnabled(bool enable);
     bool cacheEnabled() const;
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index e5acccb55b034ed961f9af1207b7dc72b1418a94..a75a1aae54ef1996b6c43ca9e4cc89c48200e501 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -1264,12 +1264,6 @@ int QTextTable::columns() const
     return d->nCols;
 }
 
-#if 0
-void QTextTable::mergeCells(const QTextCursor &selection)
-{
-}
-#endif
-
 /*!
     \fn QTextCursor QTextTable::rowStart(const QTextCursor &cursor) const
 
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 9f561dcb02b10313abb2c6fc1f2370b009fde20f..edd344735751e9892dd46df4d04c04cd3b353572 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -670,7 +670,7 @@ void QZipReaderPrivate::scanFiles()
 void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const QByteArray &contents/*, QFile::Permissions permissions, QZip::Method m*/)
 {
 #ifndef NDEBUG
-    static const char *entryTypes[] = {
+    static const char *const entryTypes[] = {
         "directory",
         "file     ",
         "symlink  " };
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index 61e239f67898672f80b87482b59bc2078c0145f7..be60ba72cc409c2a61b3eb96ab817237337ded66 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -21,6 +21,7 @@ HEADERS += \
     text/qtextdocument_p.h \
     text/qtexthtmlparser_p.h \
     text/qabstracttextdocumentlayout.h \
+    text/qabstracttextdocumentlayout_p.h \
     text/qtextdocumentlayout_p.h \
     text/qtextcursor.h \
     text/qtextcursor_p.h \
@@ -47,6 +48,7 @@ HEADERS += \
 SOURCES += \
     text/qfont.cpp \
     text/qfontengine.cpp \
+    text/qfontengineglyphcache.cpp \
     text/qfontsubset.cpp \
     text/qfontmetrics.cpp \
     text/qfontdatabase.cpp \
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index 0114b13209a78283054bc264ac8de937165bb2f2..74c95ecd5e8a4b69d3eff71e209e6ec2e7d10501 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -735,7 +735,10 @@ void QFtpDTP::socketConnectionClosed()
         clearData();
     }
 
-    bytesFromSocket = socket->readAll();
+    if (socket->isOpen())
+        bytesFromSocket = socket->readAll();
+    else
+        bytesFromSocket.clear();
 #if defined(QFTPDTP_DEBUG)
     qDebug("QFtpDTP::connectState(CsClosed)");
 #endif
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 647967839aec4491046bd428e1b663f92b9b4837..98247b7df0265f41b298717918c4c0c970db7533 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -106,15 +106,19 @@ void QHttpNetworkConnectionChannel::init()
     socket->setProxy(QNetworkProxy::NoProxy);
 #endif
 
+    // We want all signals (except the interactive ones) be connected as QueuedConnection
+    // because else we're falling into cases where we recurse back into the socket code
+    // and mess up the state. Always going to the event loop (and expecting that when reading/writing)
+    // is safer.
     QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
                      this, SLOT(_q_bytesWritten(qint64)),
-                     Qt::DirectConnection);
+                     Qt::QueuedConnection);
     QObject::connect(socket, SIGNAL(connected()),
                      this, SLOT(_q_connected()),
-                     Qt::DirectConnection);
+                     Qt::QueuedConnection);
     QObject::connect(socket, SIGNAL(readyRead()),
                      this, SLOT(_q_readyRead()),
-                     Qt::DirectConnection);
+                     Qt::QueuedConnection);
 
     // The disconnected() and error() signals may already come
     // while calling connectToHost().
@@ -143,7 +147,7 @@ void QHttpNetworkConnectionChannel::init()
         // won't be a sslSocket if encrypt is false
         QObject::connect(sslSocket, SIGNAL(encrypted()),
                          this, SLOT(_q_encrypted()),
-                         Qt::DirectConnection);
+                         Qt::QueuedConnection);
         QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
                          this, SLOT(_q_sslErrors(QList<QSslError>)),
                          Qt::DirectConnection);
@@ -152,7 +156,7 @@ void QHttpNetworkConnectionChannel::init()
                          Qt::DirectConnection);
         QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
                          this, SLOT(_q_encryptedBytesWritten(qint64)),
-                         Qt::DirectConnection);
+                         Qt::QueuedConnection);
 
         if (ignoreAllSslErrors)
             sslSocket->ignoreSslErrors();
@@ -189,8 +193,11 @@ void QHttpNetworkConnectionChannel::close()
     // pendingEncrypt must only be true in between connected and encrypted states
     pendingEncrypt = false;
 
-    if (socket)
+    if (socket) {
+        // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
+        // there is no socket yet.
         socket->close();
+    }
 }
 
 
@@ -356,6 +363,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
         }
         return false;
     }
+
+    // This code path for ConnectedState
+    if (pendingEncrypt) {
+        // Let's only be really connected when we have received the encrypted() signal. Else the state machine seems to mess up
+        // and corrupt the things sent to the server.
+        return false;
+    }
+
     return true;
 }
 
@@ -676,6 +691,12 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const
 void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
 {
     Q_UNUSED(bytes);
+    if (ssl) {
+        // In the SSL case we want to send data from encryptedBytesWritten signal since that one
+        // is the one going down to the actual network, not only into some SSL buffer.
+        return;
+    }
+
     // bytes have been written to the socket. write even more of them :)
     if (isSocketWriting())
         sendRequest();
@@ -751,7 +772,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
 
     // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
     //channels[i].reconnectAttempts = 2;
-    if (pendingEncrypt) {
+    if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState
 #ifndef QT_NO_SSL
         if (connection->sslContext().isNull()) {
             // this socket is making the 1st handshake for this connection,
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 6872fcb691d116bfa58408fcea215e118c7461b5..16d6c3b40fef74bb90afdadb436fec81aea0ad1d 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -83,6 +83,8 @@ typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
 class QHttpNetworkConnectionChannel : public QObject {
     Q_OBJECT
 public:
+    // TODO: Refactor this to add an EncryptingState (and remove pendingEncrypt).
+    // Also add an Unconnected state so IdleState does not have double meaning.
     enum ChannelState {
         IdleState = 0,          // ready to send request
         ConnectingState = 1,    // connecting to host
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index eac261bc80e02e33debad98dec69d52d27f90b14..55187755bf9a510c5b8999505a2629f3390aaa97 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -368,6 +368,13 @@ bool QHttpProtocolHandler::sendRequest()
                 // nothing to read currently, break the loop
                 break;
             } else {
+                if (m_channel->written != uploadByteDevice->pos()) {
+                    // Sanity check. This was useful in tracking down an upload corruption.
+                    qWarning() << "QHttpProtocolHandler: Internal error in sendRequest. Expected to write at position" << m_channel->written << "but read device is at" << uploadByteDevice->pos();
+                    Q_ASSERT(m_channel->written == uploadByteDevice->pos());
+                    m_connection->d_func()->emitReplyError(m_socket, m_reply, QNetworkReply::ProtocolFailure);
+                    return false;
+                }
                 qint64 currentWriteSize = m_socket->write(readPointer, currentReadSize);
                 if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
                     // socket broke down
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 4889bcd1f1ba739643f12991ee62fa421635b4c4..784e9c14b880e7c6eb6ed029d445607492581d19 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -191,6 +191,7 @@ protected:
     QByteArray m_dataArray;
     bool m_atEnd;
     qint64 m_size;
+    qint64 m_pos; // to match calls of haveDataSlot with the expected position
 public:
     QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
         : QNonContiguousByteDevice(),
@@ -198,7 +199,8 @@ public:
           m_amount(0),
           m_data(0),
           m_atEnd(aE),
-          m_size(s)
+          m_size(s),
+          m_pos(0)
     {
     }
 
@@ -206,6 +208,11 @@ public:
     {
     }
 
+    qint64 pos() Q_DECL_OVERRIDE
+    {
+        return m_pos;
+    }
+
     const char* readPointer(qint64 maximumLength, qint64 &len) Q_DECL_OVERRIDE
     {
         if (m_amount > 0) {
@@ -233,11 +240,10 @@ public:
 
         m_amount -= a;
         m_data += a;
+        m_pos += a;
 
-        // To main thread to inform about our state
-        emit processedData(a);
-
-        // FIXME possible optimization, already ask user thread for some data
+        // To main thread to inform about our state. The m_pos will be sent as a sanity check.
+        emit processedData(m_pos, a);
 
         return true;
     }
@@ -254,10 +260,21 @@ public:
     {
         m_amount = 0;
         m_data = 0;
+        m_dataArray.clear();
+
+        if (wantDataPending) {
+            // had requested the user thread to send some data (only 1 in-flight at any moment)
+            wantDataPending = false;
+        }
 
         // Communicate as BlockingQueuedConnection
         bool b = false;
         emit resetData(&b);
+        if (b) {
+            // the reset succeeded, we're at pos 0 again
+            m_pos = 0;
+            // the HTTP code will anyway abort the request if !b.
+        }
         return b;
     }
 
@@ -268,8 +285,13 @@ public:
 
 public slots:
     // From user thread:
-    void haveDataSlot(QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
+    void haveDataSlot(qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
     {
+        if (pos != m_pos) {
+            // Sometimes when re-sending a request in the qhttpnetwork* layer there is a pending haveData from the
+            // user thread on the way to us. We need to ignore it since it is the data for the wrong(later) chunk.
+            return;
+        }
         wantDataPending = false;
 
         m_dataArray = dataArray;
@@ -289,7 +311,7 @@ signals:
 
     // to main thread:
     void wantData(qint64);
-    void processedData(qint64);
+    void processedData(qint64 pos, qint64 amount);
     void resetData(bool *b);
 };
 
diff --git a/src/network/access/qnetworkaccessauthenticationmanager_p.h b/src/network/access/qnetworkaccessauthenticationmanager_p.h
index 8f06ecb6b72754e70cba73dea85435468454dc02..462827d7fcf0ca6fac929f933187277ce74842d0 100644
--- a/src/network/access/qnetworkaccessauthenticationmanager_p.h
+++ b/src/network/access/qnetworkaccessauthenticationmanager_p.h
@@ -64,7 +64,7 @@ public:
     QString domain;
     QString user;
     QString password;
-    bool isNull() {
+    bool isNull() const {
         return domain.isNull() && user.isNull() && password.isNull();
     }
 };
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index d4c7e121f046f7b74b963556ef8f58a41815f3ae..e878feb2bf374bbd3ce91693f1147d2601629c64 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -985,6 +985,27 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
     }
 }
 
+/*!
+    \internal
+
+    Returns the network session currently in use.
+    This can be changed at any time, ownership remains with the QNetworkAccessManager
+*/
+const QWeakPointer<const QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q)
+{
+    return q->d_func()->networkSessionWeakRef;
+}
+
+QSharedPointer<QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession() const
+{
+    if (networkSessionStrongRef)
+        return networkSessionStrongRef;
+    return networkSessionWeakRef.toStrongRef();
+}
+
+#endif // QT_NO_BEARERMANAGEMENT
+
+
 #ifndef QT_NO_SSL
 /*!
     \since 5.2
@@ -1045,26 +1066,6 @@ void QNetworkAccessManager::connectToHost(const QString &hostName, quint16 port)
     get(request);
 }
 
-/*!
-    \internal
-
-    Returns the network session currently in use.
-    This can be changed at any time, ownership remains with the QNetworkAccessManager
-*/
-const QWeakPointer<const QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q)
-{
-    return q->d_func()->networkSessionWeakRef;
-}
-
-QSharedPointer<QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession() const
-{
-    if (networkSessionStrongRef)
-        return networkSessionStrongRef;
-    return networkSessionWeakRef.toStrongRef();
-}
-
-#endif // QT_NO_BEARERMANAGEMENT
-
 /*!
     \since 4.7
 
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index 2b11e5f9936a74280e0d98f18414fc57ff4db61d..8a24fc55fdfe4cea9dc35f9a6e742657ef044047 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -499,7 +499,7 @@ static const char zones[] =
     "eet\0" // 2
     "jst\0" // 9
     "\0";
-static int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 };
+static const int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 };
 
 static const char months[] =
     "jan\0"
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 47621f41d80e0b4e979e1efb96075c219ebbb2be..c08648c47b19e7a2d8a00b7b4160fda24474d472 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -425,6 +425,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
     , synchronous(false)
     , state(Idle)
     , statusCode(0)
+    , uploadByteDevicePosition(false)
     , uploadDeviceChoking(false)
     , outgoingData(0)
     , bytesUploaded(-1)
@@ -874,9 +875,9 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
                              q, SLOT(uploadByteDeviceReadyReadSlot()),
                              Qt::QueuedConnection);
 
-            // From main thread to user thread:
-            QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)),
-                             forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection);
+            // From user thread to http thread:
+            QObject::connect(q, SIGNAL(haveUploadData(qint64,QByteArray,bool,qint64)),
+                             forwardUploadDevice, SLOT(haveDataSlot(qint64,QByteArray,bool,qint64)), Qt::QueuedConnection);
             QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
                              forwardUploadDevice, SIGNAL(readyRead()),
                              Qt::QueuedConnection);
@@ -884,8 +885,8 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
             // From http thread to user thread:
             QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
                              q, SLOT(wantUploadDataSlot(qint64)));
-            QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
-                             q, SLOT(sentUploadDataSlot(qint64)));
+            QObject::connect(forwardUploadDevice,SIGNAL(processedData(qint64, qint64)),
+                             q, SLOT(sentUploadDataSlot(qint64,qint64)));
             QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
                     q, SLOT(resetUploadDataSlot(bool*)),
                     Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
@@ -1365,12 +1366,22 @@ void QNetworkReplyHttpImplPrivate::replyPreSharedKeyAuthenticationRequiredSlot(Q
 void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
 {
     *r = uploadByteDevice->reset();
+    if (*r) {
+        // reset our own position which is used for the inter-thread communication
+        uploadByteDevicePosition = 0;
+    }
 }
 
 // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
-void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 amount)
+void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 pos, qint64 amount)
 {
+    if (uploadByteDevicePosition + amount != pos) {
+        // Sanity check, should not happen.
+        error(QNetworkReply::UnknownNetworkError, QString());
+        return;
+    }
     uploadByteDevice->advanceReadPointer(amount);
+    uploadByteDevicePosition += amount;
 }
 
 // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
@@ -1395,7 +1406,7 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
     QByteArray dataArray(data, currentUploadDataLength);
 
     // Communicate back to HTTP thread
-    emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
+    emit q->haveUploadData(uploadByteDevicePosition, dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
 }
 
 void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot()
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 08f3fcf342ad61e2e614d2c7496e3cf0b013673a..fff88f8f2db77320f57a1ee8c2bc1e1a88743c57 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -122,7 +122,7 @@ public:
 
     Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
     Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
-    Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
+    Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
     Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
     Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
     Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
@@ -146,7 +146,7 @@ signals:
 
     void startHttpRequestSynchronously();
 
-    void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
+    void haveUploadData(const qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
 };
 
 class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
@@ -197,6 +197,7 @@ public:
     // upload
     QNonContiguousByteDevice* createUploadByteDevice();
     QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
+    qint64 uploadByteDevicePosition;
     bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
     QIODevice *outgoingData;
     QSharedPointer<QRingBuffer> outgoingDataBuffer;
@@ -288,7 +289,7 @@ public:
     // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
     void resetUploadDataSlot(bool *r);
     void wantUploadDataSlot(qint64);
-    void sentUploadDataSlot(qint64);
+    void sentUploadDataSlot(qint64, qint64);
 
     // From user's QNonContiguousByteDevice
     void uploadByteDeviceReadyReadSlot();
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 33d42370b7a9e7e355023ea95cd64e9e42d0caf1..c1e837de7b59d402371b6e67cb17f6c0ef730450 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -75,6 +75,7 @@ QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate()
     QMutexLocker locker(&mutex);
 
     qDeleteAll(sessionEngines);
+    sessionEngines.clear();
     if (bearerThread)
         bearerThread->quit();
 }
diff --git a/src/network/doc/src/ssl.qdoc b/src/network/doc/src/ssl.qdoc
index 5a994a114c3bfcf712d7931544311c8cba7df053..45dffc95a305a78d5d6d5822ff4a1c173549e106 100644
--- a/src/network/doc/src/ssl.qdoc
+++ b/src/network/doc/src/ssl.qdoc
@@ -36,6 +36,8 @@
     the Secure Sockets Layer (SSL) protocol, using the OpenSSL Toolkit (\l{http://www.openssl.org/})
     to perform encryption and protocol handling.
 
+    \annotatedlist ssl
+
     See the \l {openssl-v1later}{OpenSSL Compatibility} page for information about the
     versions of OpenSSL that are known to work with Qt.
 
diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp
index 0e606c2070ccfd860488761dc2029559530303fe..1a97fe0e404aeda814e6a2b431e609821e7031df 100644
--- a/src/network/kernel/qhostinfo_winrt.cpp
+++ b/src/network/kernel/qhostinfo_winrt.cpp
@@ -35,7 +35,6 @@
 
 #include <qurl.h>
 
-#include <ppltasks.h>
 #include <wrl.h>
 #include <windows.networking.h>
 #include <windows.networking.sockets.h>
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 67dea74436863731385011f63e12591a16e394f7..d6a38224222c96f07b12998bba2c4f19e9ded1a1 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -559,7 +559,6 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
       readBufferMaxSize(0),
       writeBuffer(QABSTRACTSOCKET_BUFFERSIZE),
       isBuffered(false),
-      blockingTimeout(30000),
       connectTimer(0),
       disconnectTimer(0),
       connectTimeElapsed(0),
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index 1c04277f49638c12c592b1325fd3ce5befa16e93..85e82aef47e281c442320643b85c9640cb9c2dc6 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -140,7 +140,6 @@ public:
     QRingBuffer writeBuffer;
 
     bool isBuffered;
-    int blockingTimeout;
 
     QTimer *connectTimer;
     QTimer *disconnectTimer;
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 361fcf7ca2161aca74564ac301fea2d8ff09d8b2..42920c96f26a3a56814b56f173a703de19f1375e 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -46,6 +46,7 @@
 //
 #include <QtCore/QEventLoop>
 #include <QtCore/QBuffer>
+#include <QtCore/QMutex>
 #include "QtNetwork/qhostaddress.h"
 #include "private/qabstractsocketengine_p.h"
 #include <wrl.h>
diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp
index 95c360e7afda08cbebb81cb86c42d7e032750871..82807aec6eef18cadf52c2062fdd08209f385834 100644
--- a/src/network/ssl/qasn1element.cpp
+++ b/src/network/ssl/qasn1element.cpp
@@ -46,32 +46,32 @@ static OidNameMap createOidMap()
 {
     OidNameMap oids;
     // used by unit tests
-    oids.insert(oids.end(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink"));
-    oids.insert(oids.end(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress"));
-    oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.1.1"), QByteArrayLiteral("authorityInfoAccess"));
-    oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.1"), QByteArrayLiteral("OCSP"));
-    oids.insert(oids.end(), QByteArrayLiteral("1.3.6.1.5.5.7.48.2"), QByteArrayLiteral("caIssuers"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.29.14"), QByteArrayLiteral("subjectKeyIdentifier"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.29.15"), QByteArrayLiteral("keyUsage"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.29.17"), QByteArrayLiteral("subjectAltName"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.29.19"), QByteArrayLiteral("basicConstraints"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.29.35"), QByteArrayLiteral("authorityKeyIdentifier"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.13"), QByteArrayLiteral("description"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.17"), QByteArrayLiteral("postalCode"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.3"), QByteArrayLiteral("CN"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.4"), QByteArrayLiteral("SN"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.41"), QByteArrayLiteral("name"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.42"), QByteArrayLiteral("GN"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.43"), QByteArrayLiteral("initials"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.46"), QByteArrayLiteral("dnQualifier"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.5"), QByteArrayLiteral("serialNumber"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.6"), QByteArrayLiteral("C"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.7"), QByteArrayLiteral("L"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.8"), QByteArrayLiteral("ST"));
-    oids.insert(oids.end(), QByteArrayLiteral("2.5.4.9"), QByteArrayLiteral("street"));
+    oids.insert(oids.cend(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink"));
+    oids.insert(oids.cend(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress"));
+    oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.1.1"), QByteArrayLiteral("authorityInfoAccess"));
+    oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.48.1"), QByteArrayLiteral("OCSP"));
+    oids.insert(oids.cend(), QByteArrayLiteral("1.3.6.1.5.5.7.48.2"), QByteArrayLiteral("caIssuers"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.14"), QByteArrayLiteral("subjectKeyIdentifier"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.15"), QByteArrayLiteral("keyUsage"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.17"), QByteArrayLiteral("subjectAltName"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.19"), QByteArrayLiteral("basicConstraints"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.29.35"), QByteArrayLiteral("authorityKeyIdentifier"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.13"), QByteArrayLiteral("description"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.17"), QByteArrayLiteral("postalCode"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.3"), QByteArrayLiteral("CN"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.4"), QByteArrayLiteral("SN"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.41"), QByteArrayLiteral("name"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.42"), QByteArrayLiteral("GN"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.43"), QByteArrayLiteral("initials"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.46"), QByteArrayLiteral("dnQualifier"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.5"), QByteArrayLiteral("serialNumber"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.6"), QByteArrayLiteral("C"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.7"), QByteArrayLiteral("L"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.8"), QByteArrayLiteral("ST"));
+    oids.insert(oids.cend(), QByteArrayLiteral("2.5.4.9"), QByteArrayLiteral("street"));
     return oids;
 }
 Q_GLOBAL_STATIC_WITH_ARGS(OidNameMap, oidNameMap, (createOidMap()))
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 1aac152ca3e0b149cf54d236f372539f8dff549a..6f91ccdb4daecdb49d96bf48af1ce0971f0ba318 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -594,7 +594,7 @@ bool QSslCertificate::importPkcs12(QIODevice *device,
 
 // These certificates are known to be fraudulent and were created during the comodo
 // compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
-static const char *certificate_blacklist[] = {
+static const char *const certificate_blacklist[] = {
     "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", "mail.google.com", // Comodo
     "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", "www.google.com", // Comodo
     "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", "login.yahoo.com", // Comodo
diff --git a/src/network/ssl/qsslellipticcurve_dummy.cpp b/src/network/ssl/qsslellipticcurve_dummy.cpp
index d05c920a49bec4e0e6e5c8dad36e26e94515c290..16b7a3cd00e6c686a033ccfbf296c4d99e152c86 100644
--- a/src/network/ssl/qsslellipticcurve_dummy.cpp
+++ b/src/network/ssl/qsslellipticcurve_dummy.cpp
@@ -57,7 +57,7 @@ QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
     return QSslEllipticCurve();
 }
 
-bool QSslEllipticCurve::isTlsNamedCurve() const
+bool QSslEllipticCurve::isTlsNamedCurve() const Q_DECL_NOTHROW
 {
     return false;
 }
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 00e13e449b9dacf5ff1957b618ba24c723921dd8..436588afc5aed1f454a89571ecebb06a76b37eaa 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -494,30 +494,8 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
 
         // Initialize OpenSSL's random seed.
         if (!q_RAND_status()) {
-            struct {
-                int msec;
-                int sec;
-                void *stack;
-            } randomish;
-
-            int attempts = 500;
-            do {
-                if (attempts < 500) {
-#ifdef Q_OS_UNIX
-                    struct timespec ts = {0, 33333333};
-                    nanosleep(&ts, 0);
-#else
-                    Sleep(3);
-#endif
-                    randomish.msec = attempts;
-                }
-                randomish.stack = (void *)&randomish;
-                randomish.msec = QTime::currentTime().msec();
-                randomish.sec = QTime::currentTime().second();
-                q_RAND_seed((const char *)&randomish, sizeof(randomish));
-            } while (!q_RAND_status() && --attempts);
-            if (!attempts)
-                return false;
+            qWarning("Random number generator not seeded, disabling SSL support");
+            return false;
         }
     }
     return true;
@@ -640,7 +618,10 @@ long QSslSocketPrivate::sslLibraryBuildVersionNumber()
 
 QString QSslSocketPrivate::sslLibraryBuildVersionString()
 {
-    return QLatin1String(OPENSSL_VERSION_TEXT);
+    // Using QStringLiteral to store the version string as unicode and
+    // avoid false positives from Google searching the playstore for old
+    // SSL versions. See QTBUG-46265
+    return QStringLiteral(OPENSSL_VERSION_TEXT);
 }
 
 /*!
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 637bd1c560273b4fec8d6fb640f14f5cd49a8a1c..8e5d93dce24eebb7854ab9a9ec12dbce7c606fc1 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -508,7 +508,7 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
     if (uniformLocations.isEmpty())
         uniformLocations.fill(GLuint(-1), NumUniforms);
 
-    static const char *uniformNames[] = {
+    static const char *const uniformNames[] = {
         "imageTexture",
         "patternColor",
         "globalOpacity",
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 637c3753115bf1926790b445d1867ffb128235d9..9a1ae6e008f011d3888b6c2c5737bbdf98a249e1 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -304,19 +304,23 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
             for (int x = 0; x < maskWidth; ++x)
                 src[x] = -src[x]; // convert 0 and 1 into 0 and 255
         }
-    } else if (mask.format() == QImage::Format_RGB32) {
+    } else if (mask.depth() == 32) {
         // Make the alpha component equal to the average of the RGB values.
         // This is needed when drawing sub-pixel antialiased text on translucent targets.
         for (int y = 0; y < maskHeight; ++y) {
             quint32 *src = (quint32 *) mask.scanLine(y);
             for (int x = 0; x < maskWidth; ++x) {
-                uchar r = src[x] >> 16;
-                uchar g = src[x] >> 8;
-                uchar b = src[x];
-                quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
+                int r = qRed(src[x]);
+                int g = qGreen(src[x]);
+                int b = qBlue(src[x]);
+                int avg;
+                if (mask.format() == QImage::Format_RGB32)
+                    avg = (r + g + b + 1) / 3; // "+1" for rounding.
+                else // Format_ARGB_Premultiplied
+                    avg = qAlpha(src[x]);
                 if (ctx->contextHandle()->isOpenGLES()) {
                     // swizzle the bits to accommodate for the GL_RGBA upload.
-                    src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16);
+                    src[x] = (avg << 24) | (r << 0) | (g << 8) | (b << 16);
                 } else {
                     src[x] = (src[x] & 0x00ffffff) | (avg << 24);
                 }
@@ -325,7 +329,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
     }
 
     funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
-    if (mask.format() == QImage::Format_RGB32) {
+    if (mask.depth() == 32) {
         GLenum format = GL_RGBA;
 #if !defined(QT_OPENGL_ES_2)
         if (!ctx->contextHandle()->isOpenGLES())
diff --git a/src/platformheaders/helper/helper.pri b/src/platformheaders/helper/helper.pri
new file mode 100644
index 0000000000000000000000000000000000000000..2f6e76621453945fd0037e468487d01221f013e3
--- /dev/null
+++ b/src/platformheaders/helper/helper.pri
@@ -0,0 +1,2 @@
+HEADERS += \
+    $$PWD/qplatformheaderhelper.h
diff --git a/src/platformheaders/xcbfunctions/qxcbfunctionshelper.h b/src/platformheaders/helper/qplatformheaderhelper.h
similarity index 94%
rename from src/platformheaders/xcbfunctions/qxcbfunctionshelper.h
rename to src/platformheaders/helper/qplatformheaderhelper.h
index a9d734a387a8c053eaab947fd95c1d7d9e4d76ed..52302dbfba07424b1983732027e4b0bd23e50d66 100644
--- a/src/platformheaders/xcbfunctions/qxcbfunctionshelper.h
+++ b/src/platformheaders/helper/qplatformheaderhelper.h
@@ -31,16 +31,19 @@
 **
 ****************************************************************************/
 
-#ifndef QXCBFUNCTIONHELPER_H
-#define QXCBFUNCTIONHELPER_H
+#ifndef QPLATFORMHEADERHELPER_H
+#define QPLATFORMHEADERHELPER_H
 
 #include <QtCore/QByteArray>
 #include <QtGui/QGuiApplication>
 
+#if 0
+#pragma qt_class(QPlatformHeaderHelper)
+#endif
+
 QT_BEGIN_NAMESPACE
 
-namespace QXcbFunctionsHelper
-{
+namespace QPlatformHeaderHelper {
 
 template<typename ReturnT, typename FunctionT>
 ReturnT callPlatformFunction(const QByteArray &functionName)
@@ -81,4 +84,4 @@ ReturnT callPlatformFunction(const QByteArray &functionName, Arg1 a1, Arg2 a2, A
 
 QT_END_NAMESPACE
 
-#endif  /*QXCBFUNCTIONHELPER_H*/
+#endif  /*QPLATFORMHEADERHELPER_H*/
diff --git a/src/platformheaders/platformheaders.pro b/src/platformheaders/platformheaders.pro
index 5e875f7d2dcde1d67f60111a77b4981fe57082fc..6b6294d34c01b195f054c036ce5bd67d72c6b709 100644
--- a/src/platformheaders/platformheaders.pro
+++ b/src/platformheaders/platformheaders.pro
@@ -7,6 +7,7 @@ include(nativecontexts/nativecontexts.pri)
 include(xcbfunctions/xcbfunctions.pri)
 include(eglfsfunctions/eglfsfunctions.pri)
 include(windowsfunctions/windowsfunctions.pri)
+include(helper/helper.pri)
 
 QMAKE_DOCS = $$PWD/doc/qtplatformheaders.qdocconf
 
diff --git a/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h b/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h
index 87e19e6a456eb66517e8f6bc489995e8a38cc856..66bfb723076f3f9767cfbfe4ea694bd12e187597 100644
--- a/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h
+++ b/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h
@@ -34,7 +34,7 @@
 #ifndef QXCBINTEGRATIONFUNCTIONS_H
 #define QXCBINTEGRATIONFUNCTIONS_H
 
-#include "qxcbfunctionshelper.h"
+#include <QtPlatformHeaders/QPlatformHeaderHelper>
 
 QT_BEGIN_NAMESPACE
 
@@ -45,7 +45,7 @@ public:
     static const QByteArray xEmbedSystemTrayVisualHasAlphaChannelIdentifier() { return QByteArrayLiteral("XcbXEmbedSystemTrayVisualHasAlphaChannel"); }
     static bool xEmbedSystemTrayVisualHasAlphaChannel()
     {
-        return QXcbFunctionsHelper::callPlatformFunction<bool, XEmbedSystemTrayVisualHasAlphaChannel>(xEmbedSystemTrayVisualHasAlphaChannelIdentifier());
+        return QPlatformHeaderHelper::callPlatformFunction<bool, XEmbedSystemTrayVisualHasAlphaChannel>(xEmbedSystemTrayVisualHasAlphaChannelIdentifier());
     }
 };
 
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
index d477a63ec7df24fa3f4d533625abc574fa297e1a..0db2e2a09dfa8d1cc8daea3fd764bfaf95e1fcb1 100644
--- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
@@ -34,7 +34,7 @@
 #ifndef QXCBWINDOWFUNCTIONS_H
 #define QXCBWINDOWFUNCTIONS_H
 
-#include "qxcbfunctionshelper.h"
+#include <QtPlatformHeaders/QPlatformHeaderHelper>
 
 QT_BEGIN_NAMESPACE
 
@@ -66,35 +66,35 @@ public:
     static const QByteArray setWmWindowTypeIdentifier() { return QByteArrayLiteral("XcbSetWmWindowType"); }
     static void setWmWindowType(QWindow *window, WmWindowType type)
     {
-        return QXcbFunctionsHelper::callPlatformFunction<void, SetWmWindowType, QWindow *, WmWindowType>(setWmWindowTypeIdentifier(), window, type);
+        return QPlatformHeaderHelper::callPlatformFunction<void, SetWmWindowType, QWindow *, WmWindowType>(setWmWindowTypeIdentifier(), window, type);
     }
 
     typedef void (*SetWmWindowIconText)(QWindow *window, const QString &text);
     static const QByteArray setWmWindowIconTextIdentifier() { return QByteArrayLiteral("XcbSetWmWindowIconText"); }
     static void setWmWindowIconText(QWindow *window, const QString &text)
     {
-        return QXcbFunctionsHelper::callPlatformFunction<void, SetWmWindowIconText, QWindow *, const QString &>(setWmWindowIconTextIdentifier(), window, text);
+        return QPlatformHeaderHelper::callPlatformFunction<void, SetWmWindowIconText, QWindow *, const QString &>(setWmWindowIconTextIdentifier(), window, text);
     }
 
     typedef void (*SetParentRelativeBackPixmap)(const QWindow *window);
     static const QByteArray setParentRelativeBackPixmapIdentifier() { return QByteArrayLiteral("XcbSetParentRelativeBackPixmap"); }
     static void setParentRelativeBackPixmap(const QWindow *window)
     {
-        return QXcbFunctionsHelper::callPlatformFunction<void, SetParentRelativeBackPixmap, const QWindow *>(setParentRelativeBackPixmapIdentifier(), window);
+        return QPlatformHeaderHelper::callPlatformFunction<void, SetParentRelativeBackPixmap, const QWindow *>(setParentRelativeBackPixmapIdentifier(), window);
     }
 
     typedef bool (*RequestSystemTrayWindowDock)(const QWindow *window);
     static const QByteArray requestSystemTrayWindowDockIdentifier() { return QByteArrayLiteral("XcbRequestSystemTrayWindowDockIdentifier"); }
     static bool requestSystemTrayWindowDock(const QWindow *window)
     {
-        return QXcbFunctionsHelper::callPlatformFunction<bool, RequestSystemTrayWindowDock, const QWindow *>(requestSystemTrayWindowDockIdentifier(), window);
+        return QPlatformHeaderHelper::callPlatformFunction<bool, RequestSystemTrayWindowDock, const QWindow *>(requestSystemTrayWindowDockIdentifier(), window);
     }
 
     typedef QRect (*SystemTrayWindowGlobalGeometry)(const QWindow *window);
     static const QByteArray systemTrayWindowGlobalGeometryIdentifier() { return QByteArrayLiteral("XcbSystemTrayWindowGlobalGeometryIdentifier"); }
     static QRect systemTrayWindowGlobalGeometry(const QWindow *window)
     {
-        return QXcbFunctionsHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window);
+        return QPlatformHeaderHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window);
     }
 
     typedef uint (*VisualId)(QWindow *window);
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
index 771b56e060af2485c5d2a10e16df100b6c70147f..a02f93968d73502d07489ad3972f0cd351b2dfff 100644
--- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
@@ -32,7 +32,7 @@
     \brief The QXcbWindowFunctions class is an inline class containing
     miscellaneous functionality for xcb window specific functionality.
 
-    A commen usage pattern is as follows:
+    A common usage pattern is as follows:
     \snippet qxcbwindowfunctions/main.cpp 0
 
     \note There is no binary compatibility guarantee for this class,
diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
index 93c822cefbe09c3d0d9f6635dffaa12c0913e882..a64e107e71b67de5f0ddc03ca02e24e2e9506309 100644
--- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
+++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
@@ -75,6 +75,9 @@ void QDBusPlatformMenuItem::setIcon(const QIcon &icon)
     m_icon = icon;
 }
 
+/*!
+    Set a submenu under this menu item.
+*/
 void QDBusPlatformMenuItem::setMenu(QPlatformMenu *menu)
 {
     m_subMenu = static_cast<QDBusPlatformMenu *>(menu);
@@ -242,8 +245,12 @@ const QList<QDBusPlatformMenuItem *> QDBusPlatformMenu::items() const
 QPlatformMenuItem *QDBusPlatformMenu::createMenuItem() const
 {
     QDBusPlatformMenuItem *ret = new QDBusPlatformMenuItem();
-    ret->setMenu(const_cast<QDBusPlatformMenu *>(this));
     return ret;
 }
 
+QPlatformMenu *QDBusPlatformMenu::createSubMenu() const
+{
+    return new QDBusPlatformMenu;
+}
+
 QT_END_NAMESPACE
diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
index 2519533e3268f5740c7fa42851c7747f26ac5ad1..16bb4f195c605e7162d69a1006ba46921f5761b4 100644
--- a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
+++ b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
@@ -124,7 +124,7 @@ public:
     quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
     void setTag(quintptr tag) Q_DECL_OVERRIDE;
 
-    const QString text() { return m_text; }
+    const QString text() const { return m_text; }
     void setText(const QString &text) Q_DECL_OVERRIDE;
     void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
     void setEnabled(bool enabled) Q_DECL_OVERRIDE;
@@ -150,6 +150,7 @@ public:
     const QList<QDBusPlatformMenuItem *> items() const;
 
     QPlatformMenuItem *createMenuItem() const Q_DECL_OVERRIDE;
+    QPlatformMenu *createSubMenu() const Q_DECL_OVERRIDE;
 
     bool operator==(const QDBusPlatformMenu& other) { return m_tag == other.m_tag; }
 
@@ -175,6 +176,7 @@ private:
     uint m_revision;
     QHash<quintptr, QDBusPlatformMenuItem *> m_itemsByTag;
     QList<QDBusPlatformMenuItem *> m_items;
+    QDBusPlatformMenuItem *m_containingMenuItem;
     static QList<QDBusPlatformMenu *> m_topLevelMenus;
 };
 
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index be700920106a16ac5b8448df394d9d84eac5c9cf..75c4065d66d0c0decd82677a0b77aca0183c33ae 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -48,18 +48,6 @@
 
 QT_BEGIN_NAMESPACE
 
-namespace {
-class AutoReleasePool
-{
-public:
-    AutoReleasePool(): pool([[NSAutoreleasePool alloc] init]) {}
-    ~AutoReleasePool() { [pool release]; }
-
-private:
-    NSAutoreleasePool *pool;
-};
-}
-
 // this could become a list of all languages used for each writing
 // system, instead of using the single most common language.
 static const char *languageForWritingSystem[] = {
@@ -453,7 +441,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
     Q_UNUSED(style);
     Q_UNUSED(script);
 
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     static QHash<QString, QStringList> fallbackLists;
 
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
index 3fd6c999a2fd78771a18d8984bdbd389b7d15263..2e386532e28ce7768630041d962ff23939bec64e 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
@@ -169,6 +169,29 @@ struct BlendStateBinder
     bool m_blend;
 };
 
+static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
+{
+    return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
+                 topLeftRect.width(), topLeftRect.height());
+}
+
+static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter)
+{
+    const QRect rectInWindow = textures->geometry(idx);
+    QRect clipRect = textures->clipRect(idx);
+    if (clipRect.isEmpty())
+        clipRect = QRect(QPoint(0, 0), rectInWindow.size());
+
+    const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
+    const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
+
+    const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(clippedRectInWindow, targetWindowRect);
+    const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(),
+                                                                     QOpenGLTextureBlitter::OriginBottomLeft);
+
+    blitter->blit(textures->textureId(idx), target, source);
+}
+
 void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
 {
     const QPlatformTextureList *textures = window->textures();
@@ -181,7 +204,6 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
 
     for (int i = 0; i < textures->count(); ++i) {
         uint textureId = textures->textureId(i);
-        QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
         const float opacity = window->sourceWindow()->opacity();
         if (opacity != currentOpacity) {
             currentOpacity = opacity;
@@ -191,24 +213,25 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
         if (textures->count() > 1 && i == textures->count() - 1) {
             // Backingstore for a widget with QOpenGLWidget subwidgets
             blend.set(true);
+            const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
             m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
         } else if (textures->count() == 1) {
             // A regular QWidget window
             const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0;
             blend.set(translucent);
+            const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
             m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
         } else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
             // Texture from an FBO belonging to a QOpenGLWidget
             blend.set(false);
-            m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
+            clippedBlit(textures, i, targetWindowRect, &m_blitter);
         }
     }
 
     for (int i = 0; i < textures->count(); ++i) {
         if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
-            QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
             blend.set(true);
-            m_blitter.blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
+            clippedBlit(textures, i, targetWindowRect, &m_blitter);
         }
     }
 
diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
index 3caec468a6098c515c9d04ea2273c3a84d5cf4d9..8ce1ed2d2b4dda3a1debe3b198a576124da010b1 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
@@ -175,7 +175,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
 
     m_textures->clear();
     for (int i = 0; i < textures->count(); ++i)
-        m_textures->appendTexture(textures->widget(i), textures->textureId(i), textures->geometry(i), textures->flags(i));
+        m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
+                                  textures->clipRect(i), textures->flags(i));
 
     updateTexture();
     m_textures->appendTexture(Q_NULLPTR, m_bsTexture, window->geometry());
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index 9530dd83d059c3742d42e379ceaa8dac7cc45428..6d16b59d35ee27462f8167be49197c792f4ba9f2 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -44,6 +44,7 @@
 #include <QtCore/qdebug.h>
 
 #include <QDir>
+#ifndef QT_NO_BEARERMANAGEMENT
 
 extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
 #import <CoreWLAN/CoreWLAN.h>
@@ -76,17 +77,19 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
 - (id) init
 {
     [locker lock];
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     notificationCenter = [NSNotificationCenter defaultCenter];
     currentInterface = [CWInterface interfaceWithName:nil];
     [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil];
     [locker unlock];
-    [autoreleasepool release];
     return self;
 }
 
+static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
+
 -(void)dealloc
 {
+    listener = nil;
     [super dealloc];
 }
 
@@ -117,7 +120,6 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
 }
 @end
 
-static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
 
 QT_BEGIN_NAMESPACE
 
@@ -151,7 +153,7 @@ void QScanThread::quit()
 
 void QScanThread::run()
 {
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     QStringList found;
     mutex.lock();
     CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)];
@@ -233,7 +235,6 @@ void QScanThread::run()
         }
     }
     emit networksChanged();
-    [autoreleasepool release];
 }
 
 QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
@@ -273,7 +274,7 @@ void QScanThread::getUserConfigurations()
 {
     QMutexLocker locker(&mutex);
 
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     userProfiles.clear();
 
     NSSet *wifiInterfaces = [CWInterface interfaceNames];
@@ -354,7 +355,6 @@ void QScanThread::getUserConfigurations()
             }
         }
     }
-    [autoreleasepool release];
 }
 
 QString QScanThread::getSsidFromNetworkName(const QString &name)
@@ -433,7 +433,7 @@ QCoreWlanEngine::~QCoreWlanEngine()
 void QCoreWlanEngine::initialize()
 {
     QMutexLocker locker(&mutex);
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
 
     if ([[CWInterface interfaceNames] count] > 0 && !listener) {
         listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
@@ -445,7 +445,6 @@ void QCoreWlanEngine::initialize()
     storeSession = NULL;
 
     startNetworkChangeLoop();
-    [autoreleasepool release];
 }
 
 
@@ -466,7 +465,7 @@ bool QCoreWlanEngine::hasIdentifier(const QString &id)
 void QCoreWlanEngine::connectToId(const QString &id)
 {
     QMutexLocker locker(&mutex);
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     QString interfaceString = getInterfaceFromId(id);
 
     CWInterface *wifiInterface =
@@ -538,7 +537,6 @@ void QCoreWlanEngine::connectToId(const QString &id)
 
     locker.unlock();
     emit connectionError(id, InterfaceLookupError);
-    [autoreleasepool release];
 }
 
 void QCoreWlanEngine::disconnectFromId(const QString &id)
@@ -551,7 +549,7 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
         emit connectionError(id, DisconnectionError);
         return;
     }
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
 
     CWInterface *wifiInterface =
         [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)];
@@ -560,14 +558,13 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
     [wifiInterface disassociate];
 
     QTimer::singleShot(1000, this,SLOT(checkDisconnect()));
-    [autoreleasepool release];
 }
 
 void QCoreWlanEngine::checkDisconnect()
 {
     QMutexLocker locker(&mutex);
     if (!disconnectedInterfaceString.isEmpty()) {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
 
         CWInterface *wifiInterface =
                 [CWInterface interfaceWithName: QCFString::toNSString(disconnectedInterfaceString)];
@@ -579,7 +576,6 @@ void QCoreWlanEngine::checkDisconnect()
             emit connectionError(id, DisconnectionError);
             locker.relock();
         }
-        [autoreleasepool release];
         disconnectedInterfaceString.clear();
     }
 }
@@ -594,7 +590,7 @@ void QCoreWlanEngine::doRequestUpdate()
 {
     QMutexLocker locker(&mutex);
 
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
 
     NSSet *wifiInterfaces = [CWInterface interfaceNames];
     for (NSString *ifName in wifiInterfaces) {
@@ -604,7 +600,6 @@ void QCoreWlanEngine::doRequestUpdate()
     locker.unlock();
     if ([wifiInterfaces count] == 0)
         networksChanged();
-    [autoreleasepool release];
 }
 
 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
@@ -612,12 +607,11 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
     QMutexLocker locker(&mutex);
     bool haswifi = false;
     if(hasWifi) {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)];
         if (defaultInterface.powerOn) {
             haswifi = true;
         }
-        [autoreleasepool release];
     }
     return haswifi;
 }
@@ -811,7 +805,7 @@ quint64 QCoreWlanEngine::bytesReceived(const QString &id)
 quint64 QCoreWlanEngine::startTime(const QString &identifier)
 {
     QMutexLocker locker(&mutex);
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     quint64 timestamp = 0;
 
     NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist";
@@ -858,7 +852,6 @@ quint64 QCoreWlanEngine::startTime(const QString &identifier)
             }
         }
     }
-    [autoreleasepool release];
     return timestamp;
 }
 
@@ -888,3 +881,5 @@ quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b)
 }
 
 QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/generic/evdevkeyboard/main.cpp b/src/plugins/generic/evdevkeyboard/main.cpp
index ceb8f4f79281230a5700ec2c86915007878913ed..444c9f1559ab6809a9239dcaf2d5cdd05b8bfb87 100644
--- a/src/plugins/generic/evdevkeyboard/main.cpp
+++ b/src/plugins/generic/evdevkeyboard/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QEvdevKeyboardPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "evdevkeyboard.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "evdevkeyboard.json")
 
 public:
     QEvdevKeyboardPlugin();
diff --git a/src/plugins/generic/evdevmouse/main.cpp b/src/plugins/generic/evdevmouse/main.cpp
index 7e9932ceb9af2e7acc89f317d201ba347934be19..f39f92cfd219f2afc3d5eb6d09f46b9d6770d5ce 100644
--- a/src/plugins/generic/evdevmouse/main.cpp
+++ b/src/plugins/generic/evdevmouse/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QEvdevMousePlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "evdevmouse.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "evdevmouse.json")
 
 public:
     QEvdevMousePlugin();
diff --git a/src/plugins/generic/evdevtablet/main.cpp b/src/plugins/generic/evdevtablet/main.cpp
index 7d62e1a2bc6178c32c1927093592b78fdb41b863..62524e8f33992e496233d29effd6cb3fde3da323 100644
--- a/src/plugins/generic/evdevtablet/main.cpp
+++ b/src/plugins/generic/evdevtablet/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QEvdevTabletPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "evdevtablet.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "evdevtablet.json")
 
 public:
     QEvdevTabletPlugin();
diff --git a/src/plugins/generic/evdevtouch/main.cpp b/src/plugins/generic/evdevtouch/main.cpp
index ef6774b0a03bcd3fdb8d23b35892fc5c2529d77f..bb78dd6e8490a5b9b837906d6d04c64a8a979607 100644
--- a/src/plugins/generic/evdevtouch/main.cpp
+++ b/src/plugins/generic/evdevtouch/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QEvdevTouchScreenPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "evdevtouch.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "evdevtouch.json")
 
 public:
     QEvdevTouchScreenPlugin();
diff --git a/src/plugins/generic/libinput/main.cpp b/src/plugins/generic/libinput/main.cpp
index 2adc0c747b143af3a5cce9ab1e5614ee68524258..9459ca36211ce7691bd569d566494c5e82333dda 100644
--- a/src/plugins/generic/libinput/main.cpp
+++ b/src/plugins/generic/libinput/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QLibInputPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "libinput.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "libinput.json")
 
 public:
     QObject *create(const QString &key, const QString &specification);
diff --git a/src/plugins/generic/tslib/main.cpp b/src/plugins/generic/tslib/main.cpp
index 36f1ac7c3c3c51915943b5c836032500709eb2ce..9459e85544b0419bf4a8c12583c0017e7046596e 100644
--- a/src/plugins/generic/tslib/main.cpp
+++ b/src/plugins/generic/tslib/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QTsLibPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "tslib.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "tslib.json")
 
 public:
     QObject* create(const QString &key, const QString &specification);
diff --git a/src/plugins/generic/tuiotouch/main.cpp b/src/plugins/generic/tuiotouch/main.cpp
index e1d08f0e2624d2e0db40a9b5bb2666bb83ed7b49..35e74e32bd75bc38eb301133f616a7a5fd021c69 100644
--- a/src/plugins/generic/tuiotouch/main.cpp
+++ b/src/plugins/generic/tuiotouch/main.cpp
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
 class QTuioTouchPlugin : public QGenericPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "tuiotouch.json")
+    Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "tuiotouch.json")
 
 public:
     QTuioTouchPlugin();
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
index 5ab0dd8f04632464faed4cced48351701ca43d85..96f6424ba276f3eb23eb0522dd2ac219d4dac391 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
 class QComposePlatformInputContextPlugin : public QPlatformInputContextPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformInputContextFactoryInterface" FILE "compose.json")
+    Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "compose.json")
 
 public:
     QComposeInputContext *create(const QString &, const QStringList &) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforminputcontexts/ibus/main.cpp b/src/plugins/platforminputcontexts/ibus/main.cpp
index b621bec1eedfa0a3907830ae6188baa499d0f2bf..1b1a3be2c4f74d89c8e7ca2292585d7476b8e760 100644
--- a/src/plugins/platforminputcontexts/ibus/main.cpp
+++ b/src/plugins/platforminputcontexts/ibus/main.cpp
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
 class QIbusPlatformInputContextPlugin : public QPlatformInputContextPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformInputContextFactoryInterface" FILE "ibus.json")
+    Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "ibus.json")
 
 public:
     QIBusPlatformInputContext *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 8ee3ff88d12362c2f93e726ea8620783804b2407..be5e969d2bbb13b274a948d5520d3cf0f4deaf0e 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -238,6 +238,52 @@ namespace QtAndroidInput
         QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints);
     }
 
+    static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint deviceId, jlong time, jint action,
+        jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure)
+    {
+        QPointF globalPosF(x, y);
+        QPoint globalPos((int)x, (int)y);
+        QWindow *tlw = topLevelWindowAt(globalPos);
+        QPointF localPos = tlw ? (globalPosF - tlw->position()) : globalPosF;
+
+        // Galaxy Note with plain Android:
+        // 0 1 0    stylus press
+        // 2 1 0    stylus drag
+        // 1 1 0    stylus release
+        // 0 1 2    stylus press with side-button held
+        // 2 1 2    stylus drag with side-button held
+        // 1 1 2    stylus release with side-button held
+        // Galaxy Note 4 with Samsung firmware:
+        // 0 1 0    stylus press
+        // 2 1 0    stylus drag
+        // 1 1 0    stylus release
+        // 211 1 2  stylus press with side-button held
+        // 213 1 2  stylus drag with side-button held
+        // 212 1 2  stylus release with side-button held
+        // when action == ACTION_UP (1) it's a release; otherwise we say which button is pressed
+        Qt::MouseButtons buttons = Qt::NoButton;
+        switch (action) {
+        case 1:     // ACTION_UP
+        case 212:   // stylus release while side-button held on Galaxy Note 4
+            buttons = Qt::NoButton;
+            break;
+        default:    // action is press or drag
+            if (buttonState == 0)
+                buttons = Qt::LeftButton;
+            else // 2 means RightButton
+                buttons = Qt::MouseButtons(buttonState);
+            break;
+        }
+
+#ifdef QT_DEBUG_ANDROID_STYLUS
+        qDebug() << action << pointerType << buttonState << "@" << x << y << "pressure" << pressure << ": buttons" << buttons;
+#endif
+
+        QWindowSystemInterface::handleTabletEvent(tlw, ulong(time),
+            localPos, globalPosF, QTabletEvent::Stylus, pointerType,
+            buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier);
+    }
+
     static int mapAndroidKey(int key)
     {
         // 0--9        0x00000007 -- 0x00000010
@@ -702,6 +748,7 @@ namespace QtAndroidInput
         {"mouseUp", "(III)V", (void *)mouseUp},
         {"mouseMove", "(III)V", (void *)mouseMove},
         {"longPress", "(III)V", (void *)longPress},
+        {"tabletEvent", "(IIJIIIFFF)V", (void *)tabletEvent},
         {"keyDown", "(IIIZ)V", (void *)keyDown},
         {"keyUp", "(IIIZ)V", (void *)keyUp},
         {"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged}
diff --git a/src/plugins/platforms/android/androidplatformplugin.cpp b/src/plugins/platforms/android/androidplatformplugin.cpp
index ea7a3c397a2c477d574e0e90cf2cc15b632af181..245691e79f58fba4b1fb57d91d2ce9a134953720 100644
--- a/src/plugins/platforms/android/androidplatformplugin.cpp
+++ b/src/plugins/platforms/android/androidplatformplugin.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QAndroidPlatformIntegrationPlugin: public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "android.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "android.json")
 public:
     QPlatformIntegration *create(const QString &key, const QStringList &paramList);
 };
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 88bc4a653ac0796dc8bd8642202fa6dba4c2db35..5c8406ca03e39940b15bc80700e80505d74fac41 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -176,6 +176,8 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags)
 #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
     qDebug() << "@@@ GETSEL" << text;
 #endif
+    if (text.isEmpty())
+        return 0;
     return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
 }
 
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index ad6cb3a1fcd22c5ad407e8a02fd273b3e4add9ca..ba0e6b001aaf4f3331f88c6d9b2703b799a1aa13 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -12,7 +12,6 @@ OBJECTIVE_SOURCES += main.mm \
     qcocoawindow.mm \
     qnsview.mm \
     qnsviewaccessibility.mm \
-    qcocoaautoreleasepool.mm \
     qnswindowdelegate.mm \
     qcocoanativeinterface.mm \
     qcocoaeventdispatcher.mm \
@@ -48,7 +47,6 @@ HEADERS += qcocoaintegration.h \
     qcocoabackingstore.h \
     qcocoawindow.h \
     qnsview.h \
-    qcocoaautoreleasepool.h \
     qnswindowdelegate.h \
     qcocoanativeinterface.h \
     qcocoaeventdispatcher.h \
diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm
index eed2ad7dc540e13abc82f28fa919026de4532eda..e6c1ed79b275e578e21c0d21eceb96f7615f64e5 100644
--- a/src/plugins/platforms/cocoa/main.mm
+++ b/src/plugins/platforms/cocoa/main.mm
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
 class QCocoaIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "cocoa.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "cocoa.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&);
 };
@@ -52,7 +52,7 @@ QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, co
 {
     Q_UNUSED(paramList);
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (system.compare(QLatin1String("cocoa"), Qt::CaseInsensitive) == 0)
         return new QCocoaIntegration;
 
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 06e957cd860828bfe309dc743fa6e3b3fce0de81..d1d63302491c3b587064e6710340cdb1334635db 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -34,7 +34,6 @@
 #include "qcocoacursor.h"
 #include "qcocoawindow.h"
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 
 #include <QtGui/QBitmap>
 
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 050fade284dbd7745d033b371875a63b97389b2f..1865624d573aead4a7348f5450f840e634368bf8 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -66,7 +66,6 @@
 ****************************************************************************/
 
 #include "qcocoaeventdispatcher.h"
-#include "qcocoaautoreleasepool.h"
 #include "qcocoawindow.h"
 
 #include "qcocoahelpers.h"
@@ -364,7 +363,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
         if (d->interrupt)
             break;
 
-        QCocoaAutoReleasePool pool;
+        QMacAutoReleasePool pool;
         NSEvent* event = 0;
 
         // First, send all previously excluded input events, if any:
@@ -622,7 +621,7 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
             continue;
 
         if (!info.session) {
-            QCocoaAutoReleasePool pool;
+            QMacAutoReleasePool pool;
             QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(info.window->handle());
             NSWindow *nswindow = cocoaWindow->nativeWindow();
             if (!nswindow)
@@ -670,7 +669,7 @@ void QCocoaEventDispatcherPrivate::updateChildrenWorksWhenModal()
     // Make the dialog children of the window
     // active. And make the dialog children of
     // the previous modal dialog unactive again:
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     int size = cocoaModalSessionStack.size();
     if (size > 0){
         if (QWindow *prevModal = cocoaModalSessionStack[size-1].window)
@@ -691,7 +690,7 @@ void QCocoaEventDispatcherPrivate::cleanupModalSessions()
     // point they were marked as stopped), is that ending a session
     // when no other session runs below it on the stack will make cocoa
     // drop some events on the floor.
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     int stackSize = cocoaModalSessionStack.size();
 
     for (int i=stackSize-1; i>=0; --i) {
@@ -926,7 +925,7 @@ void QCocoaEventDispatcherPrivate::cancelWaitForMoreEvents()
 {
     // In case the event dispatcher is waiting for more
     // events somewhere, we post a dummy event to wake it up:
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
         modifierFlags:0 timestamp:0. windowNumber:0 context:0
         subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
index 48d7efe1747d37cd6c23ebacbfc2740168dbee10..36943a563e15a97d4878df71b7eab889d79d8748 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
@@ -51,6 +51,7 @@ public:
     virtual ~QCocoaFileDialogHelper();
 
     void exec();
+    void execModalForWindow(QWindow *parent);
 
     bool defaultNameFilterDisables() const;
 
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 4ece1b5a22ff5319e2c3db9363d18120d38acce4..fad3f28053d698c193f42e0170ad72ef8b969640 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -53,7 +53,6 @@
 #include <qvarlengtharray.h>
 #include <stdlib.h>
 #include <qabstracteventdispatcher.h>
-#include "qcocoaautoreleasepool.h"
 #include <QDir>
 
 #include <qpa/qplatformnativeinterface.h>
@@ -254,17 +253,22 @@ static QString strippedText(QString s)
         || [self panel:nil shouldShowFilename:filepath];
 
     [self updateProperties];
-    QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
     [mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]];
 
     [mSavePanel setNameFieldStringValue:selectable ? QCFString::toNSString(info.fileName()) : @""];
     NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent));
 
+    qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+    QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
+
     [mSavePanel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){
-        mReturnCode = result;
-        if (mHelper)
-            mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSOKButton);
+        [[NSApplication sharedApplication] stopModalWithCode:result];
     }];
+
+    mReturnCode = [[NSApplication sharedApplication] runModalForWindow:nsparent];
+    QAbstractEventDispatcher::instance()->interrupt();
+    if (mHelper)
+        mHelper->QNSOpenSavePanelDelegate_panelClosed(mReturnCode == NSOKButton);
 }
 
 - (BOOL)isHiddenFile:(NSString *)filename isDir:(BOOL)isDir
@@ -557,7 +561,7 @@ QCocoaFileDialogHelper::~QCocoaFileDialogHelper()
 {
     if (!mDelegate)
         return;
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     [mDelegate release];
     mDelegate = 0;
 }
@@ -687,7 +691,7 @@ bool QCocoaFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
 
 void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     const SharedPointerFileDialogOptions &opts = options();
     const QList<QUrl> selectedFiles = opts->initiallySelectedFiles();
@@ -706,14 +710,15 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
 
 bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent)
 {
+    Q_UNUSED(parent)
+
     createNSOpenSavePanelDelegate();
     if (!mDelegate)
         return false;
     if (windowModality == Qt::NonModal)
         [mDelegate showModelessPanel];
-    else if (windowModality == Qt::WindowModal && parent)
-        [mDelegate showWindowModalSheet:parent];
-    // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel()
+    // no need to show a Qt::ApplicationModal dialog here, since it will be done in exec;
+    // Qt::WindowModal will be done in execModalForWindow.
     return true;
 }
 
@@ -737,7 +742,7 @@ void QCocoaFileDialogHelper::exec()
     // QEventLoop has been interrupted, and the second-most event loop has not
     // yet been reactivated (regardless if [NSApp run] is still on the stack)),
     // showing a native modal dialog will fail.
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if ([mDelegate runApplicationModalPanel])
         emit accept();
     else
@@ -745,6 +750,14 @@ void QCocoaFileDialogHelper::exec()
 
 }
 
+void QCocoaFileDialogHelper::execModalForWindow(QWindow *parent)
+{
+    if (!parent)
+        return exec();
+
+    [mDelegate showWindowModalSheet:parent];
+}
+
 bool QCocoaFileDialogHelper::defaultNameFilterDisables() const
 {
     return true;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index a3c72c58b93cb9091ae60c0fc33635908a96f47c..1d8a1c5e70ea8769ac331d0dfcad062e02206361 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -33,7 +33,6 @@
 
 #include "qcocoaglcontext.h"
 #include "qcocoawindow.h"
-#include "qcocoaautoreleasepool.h"
 #include "qcocoahelpers.h"
 #include <qdebug.h>
 #include <QtCore/private/qcore_mac_p.h>
@@ -145,7 +144,7 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
     if (m_format.renderableType() != QSurfaceFormat::OpenGL)
         return;
 
-    QCocoaAutoReleasePool pool; // For the SG Canvas render thread
+    QMacAutoReleasePool pool; // For the SG Canvas render thread
 
     NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(m_format));
     m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
@@ -218,7 +217,7 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
 {
     Q_ASSERT(surface->surface()->supportsOpenGL());
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
     setActiveWindow(window);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index a84c0c0f2accfceec5f82506c50075abbed2ca74..c2f0c730fe5b97546d02472644f08503469d7595 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -33,7 +33,6 @@
 
 #include "qcocoahelpers.h"
 
-#include "qcocoaautoreleasepool.h"
 
 #include <QtCore>
 #include <QtGui>
@@ -630,7 +629,7 @@ QString qt_mac_applicationName()
 
 int qt_mac_mainScreenHeight()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     // The first screen in the screens array is documented
     // to have the (0,0) origin.
     NSRect screenFrame = [[[NSScreen screens] firstObject] frame];
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
index c22fe8774b7363fb65d589d4046e620c67af9954..f072991bdd2c074e61e8291a35e3a2ecc607f066 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
@@ -34,7 +34,6 @@
 #include "qnsview.h"
 #include "qcocoainputcontext.h"
 #include "qcocoanativeinterface.h"
-#include "qcocoaautoreleasepool.h"
 #include "qcocoawindow.h"
 
 #include <QtCore/QRect>
@@ -98,7 +97,7 @@ void QCocoaInputContext::reset()
     if (!view)
         return;
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (NSTextInputContext *ctxt = [NSTextInputContext currentInputContext]) {
         [ctxt discardMarkedText];
         [view unmarkText];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index ee42a83446b63423dcd159f2086a2e5a803e0839..cc235135f11010590ef7512be14112548320e4a1 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -36,7 +36,6 @@
 
 #include <Cocoa/Cocoa.h>
 
-#include "qcocoaautoreleasepool.h"
 #include "qcocoacursor.h"
 #include "qcocoawindow.h"
 #include "qcocoanativeinterface.h"
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index c8f6dd05db4315e342247c0a21f363bd33652d04..04d576904449b986e02ab9c03c1e14de7c2df113 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -33,7 +33,6 @@
 
 #include "qcocoaintegration.h"
 
-#include "qcocoaautoreleasepool.h"
 #include "qcocoawindow.h"
 #include "qcocoabackingstore.h"
 #include "qcocoanativeinterface.h"
@@ -137,7 +136,7 @@ void QCocoaScreen::updateGeometry()
 
 qreal QCocoaScreen::devicePixelRatio() const
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     NSScreen * screen = osScreen();
     return qreal(screen ? [screen backingScaleFactor] : 1.0);
 }
@@ -263,7 +262,7 @@ QCocoaIntegration::QCocoaIntegration()
     mInstance = this;
 
     initResources();
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false);
 
@@ -314,7 +313,7 @@ QCocoaIntegration::~QCocoaIntegration()
 
     qt_resetNSApplicationSendEvent();
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
         // remove the apple event handlers installed by QCocoaApplicationDelegate
         QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 09a4c9546942df4d7525f3915af9e586ab5f30f2..eb231f064ea032e67874e01ab9071a06cc4538c8 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -34,7 +34,6 @@
 #include "qcocoamenu.h"
 
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 
 #include <QtCore/QtDebug>
 #include <QtCore/qmetaobject.h>
@@ -81,7 +80,7 @@ QT_END_NAMESPACE
 }
 
 - (id) initWithMenu:(QCocoaMenu*) m;
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier;
+- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier;
 
 @end
 
@@ -152,11 +151,20 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
 
     // Change the private unicode keys to the ones used in setting the "Key Equivalents"
     NSString *characters = qt_mac_removePrivateUnicode([event characters]);
-    if ([self hasShortcut:menu
-            forKey:characters
-            // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
-            forModifiers:([event modifierFlags] & (NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask))
-            ]) {
+    // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
+    const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
+    if (NSMenuItem *menuItem = [self findItem:menu forKey:characters forModifiers:([event modifierFlags] & mask)]) {
+        if (!menuItem.target) {
+            // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder
+            // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel.
+            // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal
+            // (modal sheet, window modal, application modal).
+            // Whatever the current first responder is, let's give it a chance
+            // and do not touch the Qt's focusObject (which is different from some native view
+            // having a focus inside NSSave/OpenPanel.
+            return YES;
+        }
+
         QObject *object = qApp->focusObject();
         if (object) {
             QChar ch;
@@ -194,22 +202,23 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
     return NO;
 }
 
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
+- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
 {
     for (NSMenuItem *item in [menu itemArray]) {
         if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
             continue;
-        if ([item hasSubmenu]
-            && [self hasShortcut:[item submenu] forKey:key forModifiers:modifier])
-            return YES;
+        if ([item hasSubmenu]) {
+            if (NSMenuItem *nested = [self findItem:[item submenu] forKey:key forModifiers:modifier])
+                return nested;
+        }
 
         NSString *menuKey = [item keyEquivalent];
         if (menuKey
             && NSOrderedSame == [menuKey compare:key]
             && modifier == [item keyEquivalentModifierMask])
-            return YES;
+            return item;
     }
-    return NO;
+    return nil;
 }
 
 @end
@@ -223,7 +232,7 @@ QCocoaMenu::QCocoaMenu() :
     m_menuBar(0),
     m_containingMenuItem(0)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     m_delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this];
     m_nativeItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
@@ -243,7 +252,7 @@ QCocoaMenu::~QCocoaMenu()
     if (m_containingMenuItem)
         m_containingMenuItem->clearMenu(this);
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     [m_nativeItem setSubmenu:nil];
     [m_nativeMenu release];
     [m_delegate release];
@@ -252,7 +261,7 @@ QCocoaMenu::~QCocoaMenu()
 
 void QCocoaMenu::setText(const QString &text)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QString stripped = qt_mac_removeAmpersandEscapes(text);
     [m_nativeMenu setTitle:QCFString::toNSString(stripped)];
     [m_nativeItem setTitle:QCFString::toNSString(stripped)];
@@ -274,7 +283,7 @@ void QCocoaMenu::setFont(const QFont &font)
 
 void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
     QCocoaMenuItem *beforeItem = static_cast<QCocoaMenuItem *>(before);
 
@@ -328,7 +337,7 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
 
 void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
     if (!m_menuItems.contains(cocoaItem)) {
         qWarning() << Q_FUNC_INFO << "Menu does not contain the item to be removed";
@@ -358,7 +367,7 @@ QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const
 
 void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
     if (!m_menuItems.contains(cocoaItem)) {
         qWarning() << Q_FUNC_INFO << "Item does not belong to this menu";
@@ -387,7 +396,7 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
 
 void QCocoaMenu::syncSeparatorsCollapsible(bool enable)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (enable) {
         bool previousIsSeparator = true; // setting to true kills all the separators placed at the top.
         NSMenuItem *previousItem = nil;
@@ -445,7 +454,7 @@ void QCocoaMenu::setVisible(bool visible)
 
 void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     QPoint pos =  QPoint(targetRect.left(), targetRect.top() + targetRect.height());
     QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0;
@@ -550,7 +559,7 @@ QList<QCocoaMenuItem *> QCocoaMenu::merged() const
 
 void QCocoaMenu::syncModalState(bool modal)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (!m_enabled)
         modal = true;
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 7c902a0e5378fe7971220fd077d91ba3e25189f6..7775cdbde628d165c8f17236625fd9cc7ff5a484 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -37,7 +37,6 @@
 #include "qcocoawindow.h"
 #include "qcocoamenuloader.h"
 #include "qcocoaapplication.h" // for custom application category
-#include "qcocoaautoreleasepool.h"
 #include "qcocoaapplicationdelegate.h"
 
 #include <QtGui/QGuiApplication>
@@ -84,7 +83,7 @@ QCocoaMenuBar::~QCocoaMenuBar()
 
 void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (beforeMenu) {
         NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()];
@@ -127,7 +126,7 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor
 
 void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (menu->menuBar() == this)
         menu->setMenuBar(0);
@@ -148,7 +147,7 @@ void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu)
 
 void QCocoaMenuBar::syncMenu(QPlatformMenu *menu)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     QCocoaMenu *cocoaMenu = static_cast<QCocoaMenu *>(menu);
     Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items())
@@ -261,7 +260,7 @@ void QCocoaMenuBar::resetKnownMenuItemsToQt()
 
 void QCocoaMenuBar::updateMenuBarImmediately()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaMenuBar *mb = findGlobalMenubar();
     QCocoaWindow *cw = findWindowForMenubar();
 
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index f288ab85c0cd89d1e96a678ad2ad3d29e4ae9324..942fc8db21d429bbf624d9324a877b85aa32255d 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -37,7 +37,6 @@
 #include "qcocoamenubar.h"
 #include "messages.h"
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 #include "qt_mac_p.h"
 #include "qcocoaapplication.h" // for custom application category
 #include "qcocoamenuloader.h"
@@ -104,7 +103,7 @@ QCocoaMenuItem::QCocoaMenuItem() :
 
 QCocoaMenuItem::~QCocoaMenuItem()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
         SET_COCOA_MENU_ANCESTOR(m_menu, 0);
@@ -139,7 +138,7 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
             m_menu->setContainingMenuItem(0);
     }
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     m_menu = static_cast<QCocoaMenu *>(menu);
     if (m_menu) {
         SET_COCOA_MENU_ANCESTOR(m_menu, this);
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 205a49d25a4cf9df24f8b3086dd75398d916ea91..c8b54c922472ef73b2a301649eea4ff9f86d03da 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -234,7 +234,7 @@ void QCocoaNativeInterface::registerDraggedTypes(const QStringList &types)
 
 void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaMenu *cocoaPlatformMenu = static_cast<QCocoaMenu *>(platformMenu);
     NSMenu *menu = cocoaPlatformMenu->nsMenu();
     [NSApp QT_MANGLE_NAMESPACE(qt_setDockMenu): menu];
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
index 21339000489f225c1b7e379b20a3197f87cb7ffb..3ac112781fbf9b915acbe189ce04627b8e90bf48 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
@@ -60,13 +60,8 @@ class QCocoaPrintDevice : public QPlatformPrintDevice
 public:
     QCocoaPrintDevice();
     explicit QCocoaPrintDevice(const QString &id);
-    QCocoaPrintDevice(const QCocoaPrintDevice &other);
     virtual ~QCocoaPrintDevice();
 
-    QCocoaPrintDevice *clone();
-
-    bool operator==(const QCocoaPrintDevice &other) const;
-
     bool isValid() const Q_DECL_OVERRIDE;
     bool isDefault() const Q_DECL_OVERRIDE;
 
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index b92ec31a113e57b8973fff8191932e694293d930..4d319e149b9fa77fe29dcb80b06ebaa14d15face 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -96,24 +96,6 @@ QCocoaPrintDevice::QCocoaPrintDevice(const QString &id)
     }
 }
 
-QCocoaPrintDevice::QCocoaPrintDevice(const QCocoaPrintDevice &other)
-    : QPlatformPrintDevice(other),
-      m_printer(0),
-      m_session(0),
-      m_ppd(0)
-{
-    m_printer = other.m_printer;
-    PMRetain(m_printer);
-    m_session = other.m_session;
-    PMRetain(m_session);
-    m_macPapers = other.m_macPapers;
-    foreach (PMPaper paper, m_macPapers.values())
-        PMRetain(paper);
-    openPpdFile();
-    m_customMargins = other.m_customMargins;
-    m_printableMargins = other.m_printableMargins;
-}
-
 QCocoaPrintDevice::~QCocoaPrintDevice()
 {
     if (m_ppd)
@@ -127,16 +109,6 @@ QCocoaPrintDevice::~QCocoaPrintDevice()
         PMRelease(m_printer);
 }
 
-QCocoaPrintDevice *QCocoaPrintDevice::clone()
-{
-    return new QCocoaPrintDevice(*this);
-}
-
-bool QCocoaPrintDevice::operator==(const QCocoaPrintDevice &other) const
-{
-    return (m_id == other.m_id);
-}
-
 bool QCocoaPrintDevice::isValid() const
 {
     return m_printer ? true : false;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 65cc9bc38b9dad60785b7eaf17b5289d70b8ba31..93f8b2ba6fbe844013daeb040b7dda1d54745a8f 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -33,7 +33,6 @@
 
 #include "qcocoasystemsettings.h"
 
-#include "qcocoaautoreleasepool.h"
 #include "qcocoahelpers.h"
 
 #include <QtCore/private/qcore_mac_p.h>
@@ -45,7 +44,7 @@ QT_BEGIN_NAMESPACE
 
 QColor qt_mac_colorForTheme(ThemeBrush brush)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     QCFType<CGColorRef> cgClr = 0;
     HIThemeBrushCreateCGColor(brush, &cgClr);
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
old mode 100755
new mode 100644
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
old mode 100755
new mode 100644
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 11749e14debcad1c35660bf78dffdf52c112f628..4b73d0af08b4003f44598aa4c2eb01f285f5f00f 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -47,7 +47,6 @@
 #include "qcocoamenu.h"
 #include "qcocoamenubar.h"
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 
 #include <QtCore/qfileinfo.h>
 #include <QtGui/private/qguiapplication_p.h>
@@ -253,7 +252,7 @@ QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &siz
                                     QPlatformTheme::IconOptions iconOptions) const
 {
     Q_UNUSED(iconOptions);
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())];
     if (!iconImage)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index fba97c2629b674c1f8edb65a2917e27995c7eb4e..e2ab71a890fb1988994536ce83aad477510a6afd 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -245,6 +245,8 @@ public: // for QNSView
     friend class QCocoaBackingStore;
     friend class QCocoaNativeInterface;
 
+    void removeMonitor();
+
     NSView *m_contentView;
     QNSView *m_qtView;
     QCocoaNSWindow *m_nsWindow;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 0c1da59748001d11de99530655cd623cbd02f1be..c61d6580fa8307552779454bc303b5aae25ecca0 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -33,7 +33,6 @@
 #include "qcocoawindow.h"
 #include "qcocoaintegration.h"
 #include "qnswindowdelegate.h"
-#include "qcocoaautoreleasepool.h"
 #include "qcocoaeventdispatcher.h"
 #ifndef QT_NO_OPENGL
 #include "qcocoaglcontext.h"
@@ -374,7 +373,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
 #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
     qDebug() << "QCocoaWindow::QCocoaWindow" << this;
 #endif
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (tlw->type() == Qt::ForeignWindow) {
         NSView *foreignView = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>());
@@ -410,16 +409,18 @@ QCocoaWindow::~QCocoaWindow()
     qDebug() << "QCocoaWindow::~QCocoaWindow" << this;
 #endif
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     [m_nsWindow setContentView:nil];
     [m_nsWindow.helper detachFromPlatformWindow];
     if (m_isNSWindowChild) {
         if (m_parentCocoaWindow)
             m_parentCocoaWindow->removeChildWindow(this);
-    } else if (parent()) {
+    } else if ([m_contentView superview]) {
         [m_contentView removeFromSuperview];
     }
 
+    removeMonitor();
+
     // Make sure to disconnect observer in all case if view is valid
     // to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute
     if (m_qtView) {
@@ -436,7 +437,9 @@ QCocoaWindow::~QCocoaWindow()
 
     // While it is unlikely that this window will be in the popup stack
     // during deletetion we clear any pointers here to make sure.
-    QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+    if (QCocoaIntegration::instance()) {
+        QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+    }
 
     foreach (QCocoaWindow *child, m_childWindows) {
        [m_nsWindow removeChildWindow:child->m_nsWindow];
@@ -450,7 +453,13 @@ QCocoaWindow::~QCocoaWindow()
 
 QSurfaceFormat QCocoaWindow::format() const
 {
-    return window()->requestedFormat();
+    QSurfaceFormat format = window()->requestedFormat();
+
+    // Upgrade the default surface format to include an alpha channel. The default RGB format
+    // causes Cocoa to spend an unreasonable amount of time converting it to RGBA internally.
+    if (format == QSurfaceFormat())
+        format.setAlphaBufferSize(8);
+    return format;
 }
 
 void QCocoaWindow::setGeometry(const QRect &rectIn)
@@ -492,7 +501,7 @@ QRect QCocoaWindow::geometry() const
 
 void QCocoaWindow::setCocoaGeometry(const QRect &rect)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     if (m_contentViewIsEmbedded) {
         QPlatformWindow::setGeometry(rect);
@@ -616,7 +625,7 @@ void QCocoaWindow::setVisible(bool visible)
 
     m_inSetVisible = true;
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QCocoaWindow *parentCocoaWindow = 0;
     if (window()->transientParent())
         parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle());
@@ -689,8 +698,11 @@ void QCocoaWindow::setVisible(bool visible)
                     && [m_nsWindow isKindOfClass:[NSPanel class]]) {
                     [(NSPanel *)m_nsWindow setWorksWhenModal:YES];
                     if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
-                        monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDown handler:^(NSEvent *) {
-                            QWindowSystemInterface::handleMouseEvent(window(), QPointF(-1, -1), QPointF(window()->framePosition() - QPointF(1, 1)), Qt::LeftButton);
+                        removeMonitor();
+                        monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
+                            QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]);
+                            QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
+                                                                     cocoaButton2QtButton([e buttonNumber]));
                         }];
                     }
                 }
@@ -735,10 +747,7 @@ void QCocoaWindow::setVisible(bool visible)
         } else {
             [m_contentView setHidden:YES];
         }
-        if (monitor && window()->type() == Qt::Popup) {
-            [NSEvent removeMonitor:monitor];
-            monitor = nil;
-        }
+        removeMonitor();
 
         if (window()->type() == Qt::Popup)
             QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
@@ -790,9 +799,22 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
     if (flags & Qt::FramelessWindowHint)
         return styleMask;
     if ((type & Qt::Popup) == Qt::Popup) {
-        if (!windowIsPopupType(type))
-            styleMask = (NSUtilityWindowMask | NSResizableWindowMask | NSClosableWindowMask |
-                         NSMiniaturizableWindowMask | NSTitledWindowMask);
+        if (!windowIsPopupType(type)) {
+            styleMask = NSUtilityWindowMask;
+            if (!(flags & Qt::CustomizeWindowHint)) {
+                styleMask |= NSResizableWindowMask | NSClosableWindowMask |
+                             NSMiniaturizableWindowMask | NSTitledWindowMask;
+            } else {
+                if (flags & Qt::WindowMaximizeButtonHint)
+                    styleMask |= NSResizableWindowMask;
+                if (flags & Qt::WindowTitleHint)
+                    styleMask |= NSTitledWindowMask;
+                if (flags & Qt::WindowCloseButtonHint)
+                    styleMask |= NSClosableWindowMask;
+                if (flags & Qt::WindowMinimizeButtonHint)
+                    styleMask |= NSMiniaturizableWindowMask;
+            }
+        }
     } else {
         if (type == Qt::Window && !(flags & Qt::CustomizeWindowHint)) {
             styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask);
@@ -887,7 +909,7 @@ void QCocoaWindow::setWindowState(Qt::WindowState state)
 
 void QCocoaWindow::setWindowTitle(const QString &title)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (!m_nsWindow)
         return;
 
@@ -898,7 +920,7 @@ void QCocoaWindow::setWindowTitle(const QString &title)
 
 void QCocoaWindow::setWindowFilePath(const QString &filePath)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (!m_nsWindow)
         return;
 
@@ -908,7 +930,7 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
 
 void QCocoaWindow::setWindowIcon(const QIcon &icon)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
     if (iconButton == nil) {
@@ -1026,7 +1048,7 @@ bool QCocoaWindow::isOpaque() const
 
 void QCocoaWindow::propagateSizeHints()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     if (!m_nsWindow)
         return;
 
@@ -1237,7 +1259,9 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
 void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
 {
     bool wasNSWindowChild = m_isNSWindowChild;
-    m_isNSWindowChild = parentWindow && (window()->property("_q_platform_MacUseNSWindow").toBool());
+    BOOL requestNSWindowChild = qt_mac_resolveOption(NO, window(), "_q_platform_MacUseNSWindow",
+                                                                   "QT_MAC_USE_NSWINDOW");
+    m_isNSWindowChild = parentWindow && requestNSWindowChild;
     bool needsNSWindow = m_isNSWindowChild || !parentWindow;
 
     QCocoaWindow *oldParentCocoaWindow = m_parentCocoaWindow;
@@ -1368,7 +1392,7 @@ bool QCocoaWindow::shouldUseNSPanel()
 
 QCocoaNSWindow * QCocoaWindow::createNSWindow()
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight);
     NSRect frame = qt_mac_flipRect(rect);
@@ -1457,6 +1481,14 @@ void QCocoaWindow::removeChildWindow(QCocoaWindow *child)
     [m_nsWindow removeChildWindow:child->m_nsWindow];
 }
 
+void QCocoaWindow::removeMonitor()
+{
+    if (!monitor)
+        return;
+    [NSEvent removeMonitor:monitor];
+    monitor = nil;
+}
+
 // Returns the current global screen geometry for the nswindow associated with this window.
 QRect QCocoaWindow::windowGeometry() const
 {
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index 3d88a8d5df777a496278819fd452e32b6d419900..f4fd32ffd1cffd5515e4c4dfd296f71abb743eb0 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -43,7 +43,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -555,7 +554,7 @@ QMacPasteboard::sync() const
 
 QString qt_mac_get_pasteboardString(PasteboardRef paste)
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     NSPasteboard *pb = nil;
     CFStringRef pbname;
     if (PasteboardCopyName(paste, &pbname) == noErr) {
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 3c12228ef601180573ee5a5c5dc58cbfe4d2b6a8..c71c9f0680afe1adc111f102a5daad40b4db9e2d 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -39,7 +39,6 @@
 #include "qnsview.h"
 #include "qcocoawindow.h"
 #include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
 #include "qmultitouch_mac_p.h"
 #include "qcocoadrag.h"
 #include <qpa/qplatformintegration.h>
@@ -849,7 +848,7 @@ QT_WARNING_POP
 {
     [super updateTrackingAreas];
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     // NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early
     if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea])
@@ -1786,7 +1785,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
 
 -(void)registerDragTypes
 {
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QStringList customTypes = qt_mac_enabledDraggedTypes();
     if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
         if (currentCustomDragTypes == 0)
@@ -1850,41 +1849,9 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
     return NO;
 }
 
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+- (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag
 {
-    return [self handleDrag : sender];
-}
-
-- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
-{
-    return [self handleDrag : sender];
-}
-
-// Sends drag update to Qt, return the action
-- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
-{
-    NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
-    QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
-    Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
-
-    QWindow *target = findEventTargetWindow(m_window);
-    if (!target)
-        return NSDragOperationNone;
-
-    // update these so selecting move/copy/link works
-    QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]];
-
-    QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect());
-    if ([sender draggingSource] != nil) {
-        QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
-        response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed);
-    } else {
-        QCocoaDropData mimeData([sender draggingPasteboard]);
-        response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed);
-    }
-
-    QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
-    const QPixmap pixmapCursor = nativeDrag->currentDrag()->dragCursor(response.acceptedAction());
+    const QPixmap pixmapCursor = drag->currentDrag()->dragCursor(response.acceptedAction());
     NSCursor *nativeCursor = nil;
 
     if (pixmapCursor.isNull()) {
@@ -1924,6 +1891,41 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
     ));
     CGEventPost(kCGHIDEventTap, moveEvent);
     CFRelease(moveEvent);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+    return [self handleDrag : sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+    return [self handleDrag : sender];
+}
+
+// Sends drag update to Qt, return the action
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
+{
+    NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+    QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+    Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+
+    QWindow *target = findEventTargetWindow(m_window);
+    if (!target)
+        return NSDragOperationNone;
+
+    // update these so selecting move/copy/link works
+    QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]];
+
+    QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect());
+    if ([sender draggingSource] != nil) {
+        QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+        response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed);
+        [self updateCursorFromDragResponse:response drag:nativeDrag];
+    } else {
+        QCocoaDropData mimeData([sender draggingPasteboard]);
+        response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed);
+    }
 
     return qt_mac_mapDropAction(response.acceptedAction());
 }
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index 56fc720a83d6e63c856af715f487fea7b602048e..d4552eade4cd5dd1cb368ba275a8afe40dcf66fb 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -38,7 +38,6 @@
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qdebug.h>
 
-#include "qcocoaautoreleasepool.h"
 
 #ifndef QT_NO_PRINTER
 
@@ -50,7 +49,7 @@ QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(ne
 {
     Q_D(QMacPrintEngine);
     d->mode = mode;
-    d->m_printDevice = new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId());
+    d->m_printDevice.reset(new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId()));
     d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize());
     d->initialize();
 }
@@ -233,7 +232,7 @@ void QMacPrintEnginePrivate::initialize()
 
     q->gccaps = paintEngine->gccaps;
 
-    QCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]];
 
     QList<int> resolutions = m_printDevice->supportedResolutions();
@@ -561,7 +560,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
             id = QCocoaPrinterSupport().defaultPrintDeviceId();
         else if (!QCocoaPrinterSupport().availablePrintDeviceIds().contains(id))
             break;
-        d->m_printDevice = new QCocoaPrintDevice(id);
+        d->m_printDevice.reset(new QCocoaPrintDevice(id));
         PMPrinter printer = d->m_printDevice->macPrinter();
         PMRetain(printer);
         PMSessionSetCurrentPMPrinter(d->session(), printer);
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
index 6a795a55d8828c302251318168999b7e9aec4f66..494fb5b9d16f583fb4de9e620f04107e55cfbfc5 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
@@ -116,7 +116,7 @@ class QMacPrintEnginePrivate : public QPaintEnginePrivate
 public:
     QPrinter::PrinterMode mode;
     QPrinter::PrinterState state;
-    QSharedDataPointer<QCocoaPrintDevice> m_printDevice;
+    QSharedPointer<QCocoaPrintDevice> m_printDevice;
     QPageLayout m_pageLayout;
     NSPrintInfo *printInfo;
     PMResolution resolution;
diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h
index e210f0221f9190241e8796401137f3f0c4970017..576e0f972906e2d390c8a35001a650580006e541 100644
--- a/src/plugins/platforms/cocoa/qt_mac_p.h
+++ b/src/plugins/platforms/cocoa/qt_mac_p.h
@@ -103,17 +103,6 @@ public:
     }
 };
 
-class Q_WIDGETS_EXPORT QMacCocoaAutoReleasePool
-{
-private:
-    void *pool;
-public:
-    QMacCocoaAutoReleasePool();
-    ~QMacCocoaAutoReleasePool();
-
-    inline void *handle() const { return pool; }
-};
-
 QString qt_mac_removeMnemonics(const QString &original); //implemented in qmacstyle_mac.cpp
 
 class Q_WIDGETS_EXPORT QMacWindowChangeEvent
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index d439196dc14d9e49f4cc8487b38f5dfd124ba71c..16c05329de4652da094fe394c5385cb6b0ee9533 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -358,10 +358,10 @@ public:
         } else if (path.isRect() && (q->state()->matrix.type() <= QTransform::TxScale)) {
             const qreal * const points = path.points();
             D2D_RECT_F rect = {
-                points[0], // left
-                points[1], // top
-                points[2], // right,
-                points[5]  // bottom
+                FLOAT(points[0]), // left
+                FLOAT(points[1]), // top
+                FLOAT(points[2]), // right,
+                FLOAT(points[5])  // bottom
             };
 
             dc()->PushAxisAlignedClip(rect, antialiasMode());
@@ -918,13 +918,13 @@ public:
 
         DWRITE_GLYPH_RUN glyphRun = {
             fontFace,          //    IDWriteFontFace           *fontFace;
-            fontDef.pixelSize, //    FLOAT                     fontEmSize;
-            numGlyphs,         //    UINT32                    glyphCount;
+            FLOAT(fontDef.pixelSize), // FLOAT                 fontEmSize;
+            UINT32(numGlyphs), //    UINT32                    glyphCount;
             glyphIndices,      //    const UINT16              *glyphIndices;
             glyphAdvances,     //    const FLOAT               *glyphAdvances;
             glyphOffsets,      //    const DWRITE_GLYPH_OFFSET *glyphOffsets;
             FALSE,             //    BOOL                      isSideways;
-            rtl ? 1 : 0        //    UINT32                    bidiLevel;
+            rtl ? 1u : 0u      //    UINT32                    bidiLevel;
         };
 
         const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing)
@@ -1393,8 +1393,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r)
 
         D2D1_ELLIPSE ellipse = {
             to_d2d_point_2f(p),
-            r.width() / 2.0,
-            r.height() / 2.0
+            FLOAT(r.width() / 2.0),
+            FLOAT(r.height() / 2.0)
         };
 
         if (d->brush.brush)
@@ -1421,8 +1421,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &r)
 
         D2D1_ELLIPSE ellipse = {
             to_d2d_point_2f(p),
-            r.width() / 2.0,
-            r.height() / 2.0
+            FLOAT(r.width() / 2.0),
+            FLOAT(r.height() / 2.0)
         };
 
         if (d->brush.brush)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
index ab4be67bbe98b8f286c0ddd8d9f2e293f120f0d2..e4cc163b9ee376a33d7834ea5874a938c0dae65c 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
@@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
 class QWindowsDirect2DIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "direct2d.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "direct2d.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&);
 };
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index e762eab711ad97d850157d95f0a1a4e793d5178d..ba23526447f3335b5b8f809fd84b118eb74eaa6d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -163,7 +163,7 @@ void QWindowsDirect2DWindow::present(const QRegion &region)
     const SIZE size = { bounds.width(), bounds.height() };
     const POINT ptDst = { bounds.x(), bounds.y() };
     const POINT ptSrc = { 0, 0 };
-    const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255.0 * opacity(), AC_SRC_ALPHA };
+    const BLENDFUNCTION blend = { AC_SRC_OVER, 0, BYTE(255.0 * opacity()), AC_SRC_ALPHA };
     const QRect r = region.boundingRect();
     const RECT dirty = { r.left(), r.top(), r.left() + r.width(), r.top() + r.height() };
     UPDATELAYEREDWINDOWINFO info = { sizeof(UPDATELAYEREDWINDOWINFO), NULL,
diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp
index 3faa7c9a8be89656ccf0d73319dde2548c7f5668..4308a164ae5efba415b03ad9399710625ac415c8 100644
--- a/src/plugins/platforms/directfb/main.cpp
+++ b/src/plugins/platforms/directfb/main.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
 class QDirectFbIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "directfb.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "directfb.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&);
 };
diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
index e635d4fd22fad7752573bae997471bd99579b54c..e1d97d96280452a18469d445d34b9509a578e9ca 100644
--- a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
@@ -217,7 +217,7 @@ Qt::KeyboardModifiers QDirectFbConvenience::keyboardModifiers(DFBInputDeviceModi
         modifiers |= Qt::ControlModifier;
     }
     if (mask & DIMM_META) {
-        modifiers | Qt::MetaModifier;
+        modifiers |= Qt::MetaModifier;
     }
     return modifiers;
 }
diff --git a/src/plugins/platforms/eglfs/cursor-atlas.png b/src/plugins/platforms/eglfs/cursor-atlas.png
old mode 100755
new mode 100644
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp
index cd92c49ff1c2c885f79e65d1acc0b823cc74e42a..fe47c947b4ee461068f534f785266151b5c1d9d1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -87,8 +88,11 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
 
 QEglFSKmsCursor::~QEglFSKmsCursor()
 {
-    drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0);
-    drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0);
+    Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
+        QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
+        drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
+        drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0);
+    }
 
     gbm_bo_destroy(m_bo);
     m_bo = Q_NULLPTR;
@@ -143,10 +147,15 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
     gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount());
 
     uint32_t handle = gbm_bo_get_handle(m_bo).u32;
-    int status = drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, handle,
-                                  m_cursorSize.width(), m_cursorSize.height());
-    if (status != 0)
-        qWarning("Could not set cursor: %d", status);
+
+    Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
+        QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
+
+        int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle,
+                                      m_cursorSize.width(), m_cursorSize.height());
+        if (status != 0)
+            qWarning("Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status);
+    }
 }
 #endif // QT_NO_CURSOR
 
@@ -157,12 +166,17 @@ QPoint QEglFSKmsCursor::pos() const
 
 void QEglFSKmsCursor::setPos(const QPoint &pos)
 {
-    QPoint adjustedPos = pos - m_cursorImage.hotspot();
-    int ret = drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, adjustedPos.x(), adjustedPos.y());
-    if (ret == 0) {
-        m_pos = pos;
-    } else {
-        qWarning("Failed to move cursor: %d", ret);
+    Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
+        QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
+        QPoint origin = kmsScreen->geometry().topLeft();
+        QPoint localPos = pos - origin;
+        QPoint adjustedPos = localPos - m_cursorImage.hotspot();
+
+        int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y());
+        if (ret == 0)
+            m_pos = pos;
+        else
+            qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret);
     }
 }
 
@@ -176,8 +190,11 @@ void QEglFSKmsCursor::initCursorAtlas()
 
     QFile file(QString::fromUtf8(json));
     if (!file.open(QFile::ReadOnly)) {
-        drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0);
-        drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0);
+        Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
+            QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
+            drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
+            drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0);
+        }
         m_visible = false;
         return;
     }
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
index bafe1e33240d917156157a0150150625bcce585f..18a66e34f5c8e480074b9972b6c712de39941308 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -308,6 +309,7 @@ QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QStrin
     , m_gbm_device(Q_NULLPTR)
     , m_crtc_allocator(0)
     , m_connector_allocator(0)
+    , m_globalCursor(Q_NULLPTR)
 {
 }
 
@@ -347,6 +349,10 @@ void QEglFSKmsDevice::close()
         qt_safe_close(m_dri_fd);
         m_dri_fd = -1;
     }
+
+    if (m_globalCursor)
+        m_globalCursor->deleteLater();
+    m_globalCursor = Q_NULLPTR;
 }
 
 void QEglFSKmsDevice::createScreens()
@@ -357,6 +363,8 @@ void QEglFSKmsDevice::createScreens()
         return;
     }
 
+    QEglFSKmsScreen *primaryScreen = Q_NULLPTR;
+    QList<QPlatformScreen *> siblings;
     QPoint pos(0, 0);
     QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
 
@@ -369,12 +377,24 @@ void QEglFSKmsDevice::createScreens()
         if (screen) {
             integration->addScreen(screen);
             pos.rx() += screen->geometry().width();
+            siblings << screen;
+
+            if (!primaryScreen)
+                primaryScreen = screen;
         }
 
         drmModeFreeConnector(connector);
     }
 
     drmModeFreeResources(resources);
+
+    if (!m_integration->separateScreens()) {
+        Q_FOREACH (QPlatformScreen *screen, siblings)
+            static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings);
+
+        if (primaryScreen)
+            m_globalCursor = new QEglFSKmsCursor(primaryScreen);
+    }
 }
 
 gbm_device *QEglFSKmsDevice::device() const
@@ -387,6 +407,11 @@ int QEglFSKmsDevice::fd() const
     return m_dri_fd;
 }
 
+QPlatformCursor *QEglFSKmsDevice::globalCursor() const
+{
+    return m_globalCursor;
+}
+
 void QEglFSKmsDevice::handleDrmEvent()
 {
     drmEventContext drmEvent = {
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
index 29a1332c9a5b9b6b1233d142b34985ed0499ecd4..23fca934e5bc3456694b6c94d66d3666b2d1eec7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -34,6 +35,7 @@
 #ifndef QEGLFSKMSDEVICE_H
 #define QEGLFSKMSDEVICE_H
 
+#include "qeglfskmscursor.h"
 #include "qeglfskmsintegration.h"
 
 #include <xf86drm.h>
@@ -57,6 +59,8 @@ public:
     gbm_device *device() const;
     int fd() const;
 
+    QPlatformCursor *globalCursor() const;
+
     void handleDrmEvent();
 
 private:
@@ -70,6 +74,8 @@ private:
     quint32 m_crtc_allocator;
     quint32 m_connector_allocator;
 
+    QEglFSKmsCursor *m_globalCursor;
+
     int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
     QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos);
 
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
index 7bb932cf00d329c29e8f80f5103fa4a2cec8fdad..45224ccb87b688ec661df53d5512f6b47d5395a4 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -60,6 +61,7 @@ QEglFSKmsIntegration::QEglFSKmsIntegration()
     : m_device(Q_NULLPTR)
     , m_hwCursor(true)
     , m_pbuffers(false)
+    , m_separateScreens(false)
 {}
 
 void QEglFSKmsIntegration::platformInit()
@@ -203,6 +205,11 @@ bool QEglFSKmsIntegration::hwCursor() const
     return m_hwCursor;
 }
 
+bool QEglFSKmsIntegration::separateScreens() const
+{
+    return m_separateScreens;
+}
+
 QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const
 {
     return m_outputSettings;
@@ -235,6 +242,7 @@ void QEglFSKmsIntegration::loadConfig()
     m_hwCursor = object.value(QStringLiteral("hwcursor")).toBool(m_hwCursor);
     m_pbuffers = object.value(QStringLiteral("pbuffers")).toBool(m_pbuffers);
     m_devicePath = object.value(QStringLiteral("device")).toString();
+    m_separateScreens = object.value(QStringLiteral("separateScreens")).toBool(m_separateScreens);
 
     const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray();
     for (int i = 0; i < outputs.size(); i++) {
@@ -254,6 +262,7 @@ void QEglFSKmsIntegration::loadConfig()
     qCDebug(qLcEglfsKmsDebug) << "Configuration:\n"
                               << "\thwcursor:" << m_hwCursor << "\n"
                               << "\tpbuffers:" << m_pbuffers << "\n"
+                              << "\tseparateScreens:" << m_separateScreens << "\n"
                               << "\toutputs:" << m_outputSettings;
 }
 
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h
index 9a160d257072c523739711d77d3c4b14bb06a6cf..edb6906a4bd6fcadb1e8f3fda3d50380210a26c9 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -65,6 +66,7 @@ public:
     bool supportsPBuffers() const Q_DECL_OVERRIDE;
 
     bool hwCursor() const;
+    bool separateScreens() const;
     QMap<QString, QVariantMap> outputSettings() const;
 
 private:
@@ -73,6 +75,7 @@ private:
     QEglFSKmsDevice *m_device;
     bool m_hwCursor;
     bool m_pbuffers;
+    bool m_separateScreens;
     QString m_devicePath;
     QMap<QString, QVariantMap> m_outputSettings;
 };
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
index a27819d1dd6d53892a4918d43b579f8614f3afb7..5e49c224a0dfbcf567f0d945e8abdfec56c69b05 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -120,6 +121,7 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
     , m_cursor(Q_NULLPTR)
     , m_interruptHandler(new QEglFSKmsInterruptHandler(this))
 {
+    m_siblings << this;
 }
 
 QEglFSKmsScreen::~QEglFSKmsScreen()
@@ -185,6 +187,9 @@ QString QEglFSKmsScreen::name() const
 QPlatformCursor *QEglFSKmsScreen::cursor() const
 {
     if (m_integration->hwCursor()) {
+        if (!m_integration->separateScreens())
+            return m_device->globalCursor();
+
         if (m_cursor.isNull()) {
             QEglFSKmsScreen *that = const_cast<QEglFSKmsScreen *>(this);
             that->m_cursor.reset(new QEglFSKmsCursor(that));
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
index 16521c7fe0e2fb98278fff8e59f2d99a61c32e05..4c1b0d02ad2fbda40027a8b4af7b54e17c789629 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
@@ -1,5 +1,6 @@
 /****************************************************************************
 **
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
@@ -85,6 +86,10 @@ public:
 
     qreal refreshRate() const Q_DECL_OVERRIDE;
 
+    QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
+    void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
+
+    QEglFSKmsIntegration *integration() const { return m_integration; }
     QEglFSKmsDevice *device() const { return m_device; }
 
     gbm_surface *surface() const { return m_gbm_surface; }
@@ -110,6 +115,8 @@ private:
     QPoint m_pos;
     QScopedPointer<QEglFSKmsCursor> m_cursor;
 
+    QList<QPlatformScreen *> m_siblings;
+
     struct FrameBuffer {
         FrameBuffer() : fb(0) {}
         uint32_t fb;
diff --git a/src/plugins/platforms/eglfs/qeglfsmain.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp
index 4aae7118ac9ee7a27081fb8b40e7b61f7985d05c..89b2f205690eb317a3adefe3379bf9594cd48667 100644
--- a/src/plugins/platforms/eglfs/qeglfsmain.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QEglFSIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "eglfs.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "eglfs.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index 30fdce9fd3e10654a40ee945516a25d9435eaba1..c0d51c94a51e126f9a43ab3f7b2160802d2d8653 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -35,6 +35,7 @@
 #include <qpa/qwindowsysteminterface.h>
 #include <qpa/qplatformintegration.h>
 #include <private/qguiapplication_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
 #include <QtGui/QOpenGLContext>
 #include <QtPlatformSupport/private/qeglplatformcursor_p.h>
 #include <QtPlatformSupport/private/qeglconvenience_p.h>
@@ -106,6 +107,7 @@ void QEglFSWindow::create()
 
     if (isRaster()) {
         QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
+        context->setShareContext(qt_gl_global_share_context());
         context->setFormat(m_format);
         context->setScreen(window()->screen());
         if (!context->create())
diff --git a/src/plugins/platforms/haiku/main.h b/src/plugins/platforms/haiku/main.h
index fbf0bee527a4e9638a256a6a5f7d55f3d7c424b2..9889109c7ebd9dc4355bb62aff0f2681ba17a2fd 100644
--- a/src/plugins/platforms/haiku/main.h
+++ b/src/plugins/platforms/haiku/main.h
@@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE
 class QHaikuIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "haiku.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "haiku.json")
 
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.cpp b/src/plugins/platforms/haiku/qhaikuwindow.cpp
index 140b79af12c4b73396baa001ef6a0f8e5c4e5911..9622d12111471d62282f02fe3a7a3bf131403a14 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.cpp
+++ b/src/plugins/platforms/haiku/qhaikuwindow.cpp
@@ -130,6 +130,7 @@ QHaikuWindow::QHaikuWindow(QWindow *window)
     if (!m_window)
         qFatal("QHaikuWindow: failed to create window");
 
+    setGeometry(rect);
     setWindowFlags(window->flags());
 }
 
@@ -164,13 +165,13 @@ void QHaikuWindow::setVisible(bool visible)
 {
     if (visible) {
         m_window->Show();
+
+        window()->requestActivate();
+
+        QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), window()->geometry().size()));
     } else {
         m_window->Hide();
     }
-
-    window()->requestActivate();
-
-    QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
 }
 
 bool QHaikuWindow::isExposed() const
@@ -307,7 +308,7 @@ void QHaikuWindow::haikuWindowMoved(const QPoint &pos)
 
     QPlatformWindow::setGeometry(newGeometry);
     QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
-    QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
+    QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
 }
 
 void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
@@ -316,7 +317,7 @@ void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
 
     QPlatformWindow::setGeometry(newGeometry);
     QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
-    QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
+    QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
 
     if ((m_windowState == Qt::WindowMaximized) && !zoomInProgress) {
         // the user has resized the window while maximized -> reset maximized flag
diff --git a/src/plugins/platforms/ios/plugin.mm b/src/plugins/platforms/ios/plugin.mm
index 41fe712f608d0c48bc61205b96bd9e47bd02d0c8..e68e1dfd6fdc872b00ae8074905e978d17f71e09 100644
--- a/src/plugins/platforms/ios/plugin.mm
+++ b/src/plugins/platforms/ios/plugin.mm
@@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE
 class QIOSIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-        Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "ios.json")
+        Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "ios.json")
     public:
         QPlatformIntegration *create(const QString&, const QStringList&);
 };
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
index 92799f80c1ed71619dfcc36c9229f4d4ae6bcd98..7a37e213bdb9ed773ed9e6bb11e35255af1f74a8 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -43,7 +43,7 @@
 
 @implementation QIOSApplicationStateListener
 
-- (id) init
+- (id)init
 {
     self = [super init];
     if (self) {
@@ -75,7 +75,7 @@
     return self;
 }
 
-- (void) dealloc
+- (void)dealloc
 {
     [[NSNotificationCenter defaultCenter]
         removeObserver:self
@@ -92,12 +92,12 @@
     [super dealloc];
 }
 
-- (void) applicationDidBecomeActive
+- (void)applicationDidBecomeActive
 {
     [self handleApplicationStateChanged:UIApplicationStateActive];
 }
 
-- (void) applicationWillResignActive
+- (void)applicationWillResignActive
 {
     // Note that UIApplication is still UIApplicationStateActive at this
     // point, but since there is no separate notification for the inactive
@@ -105,12 +105,12 @@
     [self handleApplicationStateChanged:UIApplicationStateInactive];
 }
 
-- (void) applicationDidEnterBackground
+- (void)applicationDidEnterBackground
 {
     [self handleApplicationStateChanged:UIApplicationStateBackground];
 }
 
-- (void) handleApplicationStateChanged:(UIApplicationState) uiApplicationState
+- (void)handleApplicationStateChanged:(UIApplicationState)uiApplicationState
 {
     // We may receive application state changes after QCoreApplication has
     // gone down, as the block we schedule on the main queue keeps the
diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h
index 68c77d99007e45f4906be461a4498433ae282f29..5d2ae429f1d0d753d4dc69e0588ff871d6c16d7e 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.h
+++ b/src/plugins/platforms/ios/qiosbackingstore.h
@@ -39,6 +39,8 @@
 QT_BEGIN_NAMESPACE
 
 class QOpenGLPaintDevice;
+class QOpenGLFramebufferObject;
+class QOffscreenSurface;
 
 class QIOSBackingStore : public QPlatformBackingStore
 {
@@ -49,13 +51,19 @@ public:
     QPaintDevice *paintDevice();
 
     void beginPaint(const QRegion &);
+    void endPaint();
 
     void flush(QWindow *window, const QRegion &region, const QPoint &offset);
     void resize(const QSize &size, const QRegion &staticContents);
+    GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
+
+    void makeCurrent();
 
 private:
     QOpenGLContext *m_context;
     QOpenGLPaintDevice *m_device;
+    QOpenGLFramebufferObject *m_fbo;
+    QOffscreenSurface *m_surface;
 };
 
 QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm
index acec95b0d33ce3aef3f65b16dd72af298356a141..875d06dc8050ee4f5ff40db309b4a798177ca5b5 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.mm
+++ b/src/plugins/platforms/ios/qiosbackingstore.mm
@@ -36,41 +36,117 @@
 
 #include <QtGui/QOpenGLContext>
 #include <QtGui/QOpenGLPaintDevice>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/private/qwindow_p.h>
 
 #include <QtDebug>
 
+class QIOSPaintDevice : public QOpenGLPaintDevice
+{
+public:
+    QIOSPaintDevice(QIOSBackingStore *backingStore) : m_backingStore(backingStore) { }
+    void ensureActiveTarget() Q_DECL_OVERRIDE;
+
+private:
+    QIOSBackingStore *m_backingStore;
+};
+
+void QIOSPaintDevice::ensureActiveTarget()
+{
+    m_backingStore->makeCurrent();
+}
+
 QIOSBackingStore::QIOSBackingStore(QWindow *window)
     : QPlatformBackingStore(window)
     , m_context(new QOpenGLContext)
     , m_device(0)
+    , m_fbo(0)
+    , m_surface(0)
 {
     QSurfaceFormat fmt = window->requestedFormat();
-    fmt.setDepthBufferSize(16);
-    fmt.setStencilBufferSize(8);
+    // Due to sharing QIOSContext redirects our makeCurrent on window() attempts to
+    // the global share context. Hence it is essential to have a compatible format.
+    fmt.setDepthBufferSize(QSurfaceFormat::defaultFormat().depthBufferSize());
+    fmt.setStencilBufferSize(QSurfaceFormat::defaultFormat().stencilBufferSize());
+
+    if (fmt.depthBufferSize() == 0)
+        qWarning("No depth in default format, expect rendering errors");
 
-    // Needed to prevent QOpenGLContext::makeCurrent() from failing
-    window->setSurfaceType(QSurface::OpenGLSurface);
+    if (window->surfaceType() == QSurface::RasterSurface)
+        window->setSurfaceType(QSurface::OpenGLSurface);
 
     m_context->setFormat(fmt);
     m_context->setScreen(window->screen());
+    Q_ASSERT(QOpenGLContext::globalShareContext());
+    m_context->setShareContext(QOpenGLContext::globalShareContext());
     m_context->create();
 }
 
 QIOSBackingStore::~QIOSBackingStore()
 {
+    delete m_fbo;
+    delete m_surface;
     delete m_context;
     delete m_device;
 }
 
+void QIOSBackingStore::makeCurrent()
+{
+    QSurface *surface = m_surface ? m_surface : static_cast<QSurface *>(window());
+    if (!m_context->makeCurrent(surface))
+        qWarning("QIOSBackingStore: makeCurrent() failed");
+    if (m_fbo)
+        m_fbo->bind();
+}
+
 void QIOSBackingStore::beginPaint(const QRegion &)
 {
-    m_context->makeCurrent(window());
+    if (qt_window_private(window())->compositing) {
+        if (!m_fbo) {
+            delete m_device;
+            m_device = 0;
+        }
+        if (!m_surface) {
+            m_surface = new QOffscreenSurface;
+            m_surface->setFormat(m_context->format());
+            m_surface->create();
+        }
+        if (!m_context->makeCurrent(m_surface))
+            qWarning("QIOSBackingStore: Failed to make offscreen surface current");
+        const QSize size = window()->size() * window()->devicePixelRatio();
+        if (m_fbo && m_fbo->size() != size) {
+            delete m_fbo;
+            m_fbo = 0;
+        }
+        if (!m_fbo)
+            m_fbo = new QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::CombinedDepthStencil);
+    } else if (m_fbo) {
+        delete m_fbo;
+        m_fbo = 0;
+        delete m_surface;
+        m_surface = 0;
+        delete m_device;
+        m_device = 0;
+    }
+
+    makeCurrent();
+
+    if (!m_device)
+        m_device = new QIOSPaintDevice(this);
+}
+
+void QIOSBackingStore::endPaint()
+{
+    if (m_fbo) {
+        m_fbo->release();
+        glFlush();
+    }
 }
 
 QPaintDevice *QIOSBackingStore::paintDevice()
 {
-    if (!m_device)
-        m_device = new QOpenGLPaintDevice;
+    Q_ASSERT(m_device);
 
     // Keep paint device size and device pixel ratio in sync with window
     qreal devicePixelRatio = window()->devicePixelRatio();
@@ -82,6 +158,8 @@ QPaintDevice *QIOSBackingStore::paintDevice()
 
 void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
 {
+    Q_ASSERT(!qt_window_private(window)->compositing);
+
     Q_UNUSED(region);
     Q_UNUSED(offset);
 
@@ -111,4 +189,21 @@ void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents)
         qWarning() << "QIOSBackingStore needs to have the same size as its window";
 }
 
+GLuint QIOSBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
+{
+    Q_ASSERT(qt_window_private(window())->compositing);
+    Q_UNUSED(dirtyRegion);
+
+    if (flags)
+        *flags = TextureFlip;
+
+    if (!m_fbo)
+        return 0;
+
+    if (textureSize)
+        *textureSize = m_fbo->size();
+
+    return m_fbo->texture();
+}
+
 QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index 192ee6768924742a0dfbcb091f0973f8cf235092..e0c6ec5d729cd6c0a94f9b6467dee566991029de 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -62,7 +62,7 @@
 
 @implementation QUIClipboard
 
--(id)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
+- (id)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
 {
     self = [super init];
     if (self) {
@@ -87,7 +87,7 @@
     return self;
 }
 
--(void)dealloc
+- (void)dealloc
 {
     [[NSNotificationCenter defaultCenter]
         removeObserver:self
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index c7541fc51bbc3495eda190ae05f8bf0c0baf4c7f..fe0ca33c13ef7b916a46f7874403a1a6dc5e1efc 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -116,7 +116,8 @@ static QString fboStatusString(GLenum status)
 
 bool QIOSContext::makeCurrent(QPlatformSurface *surface)
 {
-    Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+    Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface
+                         || surface->surface()->surfaceType() == QSurface::RasterGLSurface));
 
     [EAGLContext setCurrentContext:m_eaglContext];
 
@@ -141,7 +142,8 @@ void QIOSContext::doneCurrent()
 
 void QIOSContext::swapBuffers(QPlatformSurface *surface)
 {
-    Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+    Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface
+                         || surface->surface()->surfaceType() == QSurface::RasterGLSurface));
 
     if (surface->surface()->surfaceClass() == QSurface::Offscreen)
         return; // Nothing to do
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index fc12e83a8195a337988bdef7940a687e93587cbf..8e4b4c58758bcad273d0d03a891d7c9b20ac62d3 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -293,7 +293,7 @@ static bool rootLevelRunLoopIntegration()
 
 @implementation QIOSApplicationStateTracker
 
-+ (void) load
++ (void)load
 {
     [[NSNotificationCenter defaultCenter]
         addObserver:self
@@ -323,7 +323,7 @@ static bool rootLevelRunLoopIntegration()
 #  error "Unknown processor family"
 #endif
 
-+ (void) applicationDidFinishLaunching
++ (void)applicationDidFinishLaunching
 {
     if (!isQtApplication())
         return;
@@ -377,7 +377,7 @@ static bool rootLevelRunLoopIntegration()
 // four bits of the exit code (exit(3) will only pass on the lower 8 bits).
 static const char kApplicationWillTerminateExitCode = SIGTERM | 0x80;
 
-+ (void) applicationWillTerminate
++ (void)applicationWillTerminate
 {
     if (!isQtApplication())
         return;
diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.h b/src/plugins/platforms/ios/qiosfileengineassetslibrary.h
index 043e101a2144ec6b3840134e9fde97d36d6d18a9..37bbc7bf2322556031f101c772ba8478cfa0a3a0 100644
--- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.h
+++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.h
@@ -55,10 +55,17 @@ public:
     QString fileName(FileName file) const Q_DECL_OVERRIDE;
     void setFileName(const QString &file) Q_DECL_OVERRIDE;
     QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE;
+
+#ifndef QT_NO_FILESYSTEMITERATOR
+    Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE;
+    Iterator *endEntryList() Q_DECL_OVERRIDE;
+#endif
+
     void setError(QFile::FileError error, const QString &str) { QAbstractFileEngine::setError(error, str); }
 
 private:
     QString m_fileName;
+    QString m_assetUrl;
     qint64 m_offset;
     mutable QIOSAssetData *m_data;
 
diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
index 73bfc2a87f7a0c99c6af90699444fe5756d110d8..44a79011601ed78b1a4f51c50ca61eee0158c809 100644
--- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
@@ -38,6 +38,145 @@
 
 #include <QtCore/QTimer>
 #include <QtCore/private/qcoreapplication_p.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qset.h>
+#include <QtCore/qthreadstorage.h>
+
+static QThreadStorage<QString> g_iteratorCurrentUrl;
+static QThreadStorage<QPointer<QIOSAssetData> > g_assetDataCache;
+
+static const int kBufferSize = 10;
+static ALAsset *kNoAsset = 0;
+
+static void ensureAuthorizationDialogNotBlocked()
+{
+    if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusNotDetermined)
+        return;
+    if (static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec)
+        return;
+
+    // Since authorization status has not been determined, the user will be asked
+    // to authorize the app. But since main has not finished, the dialog will be held
+    // back until the launch completes. To avoid a dead-lock below, we start an event
+    // loop to complete the launch.
+    QEventLoop loop;
+    QTimer::singleShot(1, &loop, &QEventLoop::quit);
+    loop.exec();
+}
+
+// -------------------------------------------------------------------------
+
+class QIOSAssetEnumerator
+{
+public:
+    QIOSAssetEnumerator(ALAssetsLibrary *assetsLibrary, ALAssetsGroupType type)
+        : m_semWriteAsset(dispatch_semaphore_create(kBufferSize))
+        , m_semReadAsset(dispatch_semaphore_create(0))
+        , m_stop(false)
+        , m_assetsLibrary([assetsLibrary retain])
+        , m_type(type)
+        , m_buffer(QVector<ALAsset *>(kBufferSize))
+        , m_readIndex(0)
+        , m_writeIndex(0)
+        , m_nextAssetReady(false)
+    {
+        ensureAuthorizationDialogNotBlocked();
+        startEnumerate();
+    }
+
+    ~QIOSAssetEnumerator()
+    {
+        m_stop = true;
+
+        // Flush and autorelease remaining assets in the buffer
+        while (hasNext())
+            next();
+
+        // Documentation states that we need to balance out calls to 'wait'
+        // and 'signal'. Since the enumeration function always will be one 'wait'
+        // ahead, we need to signal m_semProceedToNextAsset one last time.
+        dispatch_semaphore_signal(m_semWriteAsset);
+        dispatch_release(m_semReadAsset);
+        dispatch_release(m_semWriteAsset);
+
+        [m_assetsLibrary autorelease];
+    }
+
+    bool hasNext()
+    {
+        if (!m_nextAssetReady) {
+            dispatch_semaphore_wait(m_semReadAsset, DISPATCH_TIME_FOREVER);
+            m_nextAssetReady = true;
+        }
+        return m_buffer[m_readIndex] != kNoAsset;
+    }
+
+    ALAsset *next()
+    {
+        Q_ASSERT(m_nextAssetReady);
+        Q_ASSERT(m_buffer[m_readIndex]);
+
+        ALAsset *asset = [m_buffer[m_readIndex] autorelease];
+        dispatch_semaphore_signal(m_semWriteAsset);
+
+        m_readIndex = (m_readIndex + 1) % kBufferSize;
+        m_nextAssetReady = false;
+        return asset;
+    }
+
+private:
+    dispatch_semaphore_t m_semWriteAsset;
+    dispatch_semaphore_t m_semReadAsset;
+    std::atomic_bool m_stop;
+
+    ALAssetsLibrary *m_assetsLibrary;
+    ALAssetsGroupType m_type;
+    QVector<ALAsset *> m_buffer;
+    int m_readIndex;
+    int m_writeIndex;
+    bool m_nextAssetReady;
+
+    void writeAsset(ALAsset *asset)
+    {
+        dispatch_semaphore_wait(m_semWriteAsset, DISPATCH_TIME_FOREVER);
+        m_buffer[m_writeIndex] = [asset retain];
+        dispatch_semaphore_signal(m_semReadAsset);
+        m_writeIndex = (m_writeIndex + 1) % kBufferSize;
+    }
+
+    void startEnumerate()
+    {
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            [m_assetsLibrary enumerateGroupsWithTypes:m_type usingBlock:^(ALAssetsGroup *group, BOOL *stopEnumerate) {
+
+                if (!group) {
+                    writeAsset(kNoAsset);
+                    return;
+                }
+
+                if (m_stop) {
+                    *stopEnumerate = true;
+                    return;
+                }
+
+                [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stopEnumerate) {
+                    Q_UNUSED(index);
+                    if (!asset || ![[asset valueForProperty:ALAssetPropertyType] isEqual:ALAssetTypePhoto])
+                       return;
+
+                    writeAsset(asset);
+                    *stopEnumerate = m_stop;
+                }];
+            } failureBlock:^(NSError *error) {
+                NSLog(@"QIOSFileEngine: %@", error);
+                writeAsset(kNoAsset);
+            }];
+        });
+    }
+
+};
+
+// -------------------------------------------------------------------------
 
 class QIOSAssetData : public QObject
 {
@@ -47,35 +186,17 @@ public:
         , m_assetUrl(assetUrl)
         , m_assetLibrary(0)
     {
-        switch ([ALAssetsLibrary authorizationStatus]) {
-        case ALAuthorizationStatusRestricted:
-        case ALAuthorizationStatusDenied:
-            engine->setError(QFile::PermissionsError, QLatin1String("Unauthorized access"));
-            return;
-        case ALAuthorizationStatusNotDetermined:
-            if (!static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec) {
-                // Since authorization status has not been determined, the user will be asked
-                // to authorize the app. But since main has not finished, the dialog will be held
-                // back until the launch completes. To avoid a dead-lock below, we start an event
-                // loop to complete the launch.
-                QEventLoop loop;
-                QTimer::singleShot(1, &loop, &QEventLoop::quit);
-                loop.exec();
-            }
-            break;
-        default:
-            if (g_currentAssetData) {
-                // It's a common pattern that QFiles pointing to the same path are created and destroyed
-                // several times during a single event loop cycle. To avoid loading the same asset
-                // over and over, we check if the last loaded asset has not been destroyed yet, and try to
-                // reuse its data. Since QFile is (mostly) reentrant, we need to protect m_currentAssetData
-                // from being modified by several threads at the same time.
-                QMutexLocker lock(&g_mutex);
-                if (g_currentAssetData && g_currentAssetData->m_assetUrl == assetUrl) {
-                    m_assetLibrary = [g_currentAssetData->m_assetLibrary retain];
-                    m_asset = [g_currentAssetData->m_asset retain];
-                    return;
-                }
+        ensureAuthorizationDialogNotBlocked();
+
+        if (QIOSAssetData *assetData = g_assetDataCache.localData()) {
+            // It's a common pattern that QFiles pointing to the same path are created and destroyed
+            // several times during a single event loop cycle. To avoid loading the same asset
+            // over and over, we check if the last loaded asset has not been destroyed yet, and try to
+            // reuse its data.
+            if (assetData->m_assetUrl == assetUrl) {
+                m_assetLibrary = [assetData->m_assetLibrary retain];
+                m_asset = [assetData->m_asset retain];
+                return;
             }
         }
 
@@ -90,6 +211,26 @@ public:
             NSURL *url = [NSURL URLWithString:assetUrl.toNSString()];
             m_assetLibrary = [[ALAssetsLibrary alloc] init];
             [m_assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
+
+                if (!asset) {
+                    // When an asset couldn't be loaded, chances are that it belongs to ALAssetsGroupPhotoStream.
+                    // Such assets can be stored in the cloud and might need to be downloaded first. Unfortunately,
+                    // forcing that to happen is hidden behind private APIs ([ALAsset requestDefaultRepresentation]).
+                    // As a work-around, we search for it instead, since that will give us a pointer to the asset.
+                    QIOSAssetEnumerator e(m_assetLibrary, ALAssetsGroupPhotoStream);
+                    while (e.hasNext()) {
+                        ALAsset *a = e.next();
+                        QString url = QUrl::fromNSURL([a valueForProperty:ALAssetPropertyAssetURL]).toString();
+                        if (url == assetUrl) {
+                            asset = a;
+                            break;
+                        }
+                    }
+                }
+
+                if (!asset)
+                    engine->setError(QFile::OpenError, QLatin1String("could not open image"));
+
                 m_asset = [asset retain];
                 dispatch_semaphore_signal(semaphore);
             } failureBlock:^(NSError *error) {
@@ -101,17 +242,15 @@ public:
         dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
         dispatch_release(semaphore);
 
-        QMutexLocker lock(&g_mutex);
-        g_currentAssetData = this;
+        g_assetDataCache.setLocalData(this);
     }
 
     ~QIOSAssetData()
     {
-        QMutexLocker lock(&g_mutex);
         [m_assetLibrary release];
         [m_asset release];
-        if (this == g_currentAssetData)
-            g_currentAssetData = 0;
+        if (g_assetDataCache.localData() == this)
+            g_assetDataCache.setLocalData(0);
     }
 
     ALAsset *m_asset;
@@ -119,21 +258,67 @@ public:
 private:
     QString m_assetUrl;
     ALAssetsLibrary *m_assetLibrary;
+};
+
+// -------------------------------------------------------------------------
 
-    static QBasicMutex g_mutex;
-    static QPointer<QIOSAssetData> g_currentAssetData;
+#ifndef QT_NO_FILESYSTEMITERATOR
+
+class QIOSFileEngineIteratorAssetsLibrary : public QAbstractFileEngineIterator
+{
+public:
+    QIOSAssetEnumerator *m_enumerator;
+
+    QIOSFileEngineIteratorAssetsLibrary(
+            QDir::Filters filters, const QStringList &nameFilters)
+        : QAbstractFileEngineIterator(filters, nameFilters)
+        , m_enumerator(new QIOSAssetEnumerator([[[ALAssetsLibrary alloc] init] autorelease], ALAssetsGroupAll))
+    {
+    }
+
+    ~QIOSFileEngineIteratorAssetsLibrary()
+    {
+        delete m_enumerator;
+        g_iteratorCurrentUrl.setLocalData(QString());
+    }
+
+    QString next() Q_DECL_OVERRIDE
+    {
+        // Cache the URL that we are about to return, since QDir will immediately create a
+        // new file engine on the file and ask if it exists. Unless we do this, we end up
+        // creating a new ALAsset just to verify its existence, which will be especially
+        // costly for assets belonging to ALAssetsGroupPhotoStream.
+        ALAsset *asset = m_enumerator->next();
+        QString url = QUrl::fromNSURL([asset valueForProperty:ALAssetPropertyAssetURL]).toString();
+        g_iteratorCurrentUrl.setLocalData(url);
+        return url;
+    }
+
+    bool hasNext() const Q_DECL_OVERRIDE
+    {
+        return m_enumerator->hasNext();
+    }
+
+    QString currentFileName() const Q_DECL_OVERRIDE
+    {
+        return g_iteratorCurrentUrl.localData();
+    }
+
+    QFileInfo currentFileInfo() const
+    {
+        return QFileInfo(currentFileName());
+    }
 };
 
-QBasicMutex QIOSAssetData::g_mutex;
-QPointer<QIOSAssetData> QIOSAssetData::g_currentAssetData = 0;
+#endif
 
 // -------------------------------------------------------------------------
 
 QIOSFileEngineAssetsLibrary::QIOSFileEngineAssetsLibrary(const QString &fileName)
-    : m_fileName(fileName)
-    , m_offset(0)
+    : m_offset(0)
     , m_data(0)
 {
+    setFileName(fileName);
 }
 
 QIOSFileEngineAssetsLibrary::~QIOSFileEngineAssetsLibrary()
@@ -143,18 +328,8 @@ QIOSFileEngineAssetsLibrary::~QIOSFileEngineAssetsLibrary()
 
 ALAsset *QIOSFileEngineAssetsLibrary::loadAsset() const
 {
-    if (!m_data) {
-        // QUrl::fromLocalFile() will remove double slashes. Since the asset url is passed around as a file
-        // name in the app (and converted to/from a file url, e.g in QFileDialog), we need to check if we still
-        // have two leading slashes after the scheme, and restore the second slash if not.
-        QString assetUrl = m_fileName;
-        const int index = 16; // "assets-library://"
-        if (assetUrl[index] != QLatin1Char('/'))
-            assetUrl.insert(index, '/');
-
-        m_data = new QIOSAssetData(assetUrl, const_cast<QIOSFileEngineAssetsLibrary *>(this));
-    }
-
+    if (!m_data)
+        m_data = new QIOSAssetData(m_assetUrl, const_cast<QIOSFileEngineAssetsLibrary *>(this));
     return m_data->m_asset;
 }
 
@@ -179,15 +354,21 @@ bool QIOSFileEngineAssetsLibrary::close()
 QAbstractFileEngine::FileFlags QIOSFileEngineAssetsLibrary::fileFlags(QAbstractFileEngine::FileFlags type) const
 {
     QAbstractFileEngine::FileFlags flags = 0;
-    if (!loadAsset())
+    const bool isDir = (m_assetUrl == QLatin1String("assets-library://"));
+    const bool exists = isDir || m_assetUrl == g_iteratorCurrentUrl.localData() || loadAsset();
+
+    if (!exists)
         return flags;
 
     if (type & FlagsMask)
         flags |= ExistsFlag;
-    if (type & PermsMask)
-        flags |= ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
+    if (type & PermsMask) {
+        ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
+        if (status != ALAuthorizationStatusRestricted && status != ALAuthorizationStatusDenied)
+            flags |= ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
+    }
     if (type & TypesMask)
-        flags |= FileType;
+        flags |= isDir ? DirectoryType : FileType;
 
     return flags;
 }
@@ -245,11 +426,32 @@ void QIOSFileEngineAssetsLibrary::setFileName(const QString &file)
     if (m_data)
         close();
     m_fileName = file;
+    // QUrl::fromLocalFile() will remove double slashes. Since the asset url is
+    // passed around as a file name in the app (and converted to/from a file url, e.g
+    // in QFileDialog), we need to ensure that m_assetUrl ends up being valid.
+    int index = file.indexOf(QLatin1String("asset.JPG?"));
+    if (index == -1)
+        m_assetUrl = QLatin1String("assets-library://");
+    else
+        m_assetUrl = QLatin1String("assets-library://asset/") + file.mid(index);
 }
 
 QStringList QIOSFileEngineAssetsLibrary::entryList(QDir::Filters filters, const QStringList &filterNames) const
 {
-    Q_UNUSED(filters);
-    Q_UNUSED(filterNames);
-    return QStringList();
+    return QAbstractFileEngine::entryList(filters, filterNames);
+}
+
+#ifndef QT_NO_FILESYSTEMITERATOR
+
+QAbstractFileEngine::Iterator *QIOSFileEngineAssetsLibrary::beginEntryList(
+        QDir::Filters filters, const QStringList &filterNames)
+{
+    return new QIOSFileEngineIteratorAssetsLibrary(filters, filterNames);
 }
+
+QAbstractFileEngine::Iterator *QIOSFileEngineAssetsLibrary::endEntryList()
+{
+    return 0;
+}
+
+#endif
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
index 86b784618fb2ac8906579c74940a95c73f201930..544f9e0a42f08a0fed0a2ebf1c8dd26c51144606 100644
--- a/src/plugins/platforms/ios/qiosglobal.h
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -68,7 +68,7 @@ int infoPlistValue(NSString* key, int defaultValue);
 QT_END_NAMESPACE
 
 @interface UIResponder (QtFirstResponder)
-+(id)currentFirstResponder;
++ (id)currentFirstResponder;
 @end
 
 class FirstResponderCandidate : public QScopedValueRollback<UIResponder *>
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index ef24abbfd981725f247ecb8ad8517a33bece80eb..f5b971391db28a78d9868e8e3a7e1ff185eb8d96 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -133,7 +133,7 @@ int infoPlistValue(NSString* key, int defaultValue)
 @end
 
 @implementation QtFirstResponderEvent
-- (void) dealloc
+- (void)dealloc
 {
     self.firstResponder = 0;
     [super dealloc];
@@ -158,7 +158,7 @@ int infoPlistValue(NSString* key, int defaultValue)
 
 @implementation UIResponder (QtFirstResponder)
 
-+(id)currentFirstResponder
++ (id)currentFirstResponder
 {
     QtFirstResponderEvent *event = [[[QtFirstResponderEvent alloc] init] autorelease];
     [[UIApplication sharedApplication] sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event];
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 037b28e91d44c29863cffcecd0e842830cb0d916..d03c589b2a973b4ff47e599f20fe0b999760b92d 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -579,7 +579,7 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
 void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
 {
     // Mask for properties that we are interested in and see if any of them changed
-    updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImReturnKeyType | Qt::ImPlatformData);
+    updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImEnterKeyType | Qt::ImPlatformData);
 
     qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject();
 
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 7cd4280f5e7aa89e526248e36fabebff49349906..b4050b8f6266f7152d3c1e1cb428b2b170c659c9 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -77,6 +77,15 @@ QIOSIntegration::QIOSIntegration()
                "'applicationDidFinishLaunching' inside your UIApplication delegate.\n");
     }
 
+    // The backingstore needs a global share context in order to support composition in
+    // QPlatformBackingStore.
+    qApp->setAttribute(Qt::AA_ShareOpenGLContexts, true);
+    // And that context must match the format used for the backingstore's context.
+    QSurfaceFormat fmt;
+    fmt.setDepthBufferSize(16);
+    fmt.setStencilBufferSize(8);
+    QSurfaceFormat::setDefaultFormat(fmt);
+
     // Set current directory to app bundle folder
     QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
 
@@ -137,6 +146,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const
         return false;
     case ApplicationState:
         return true;
+    case RasterGLSurface:
+        return true;
     default:
         return QPlatformIntegration::hasCapability(cap);
     }
@@ -208,6 +219,10 @@ QPlatformServices *QIOSIntegration::services() const
 QVariant QIOSIntegration::styleHint(StyleHint hint) const
 {
     switch (hint) {
+    case PasswordMaskDelay:
+        // this number is based on timing the native delay
+        // since there is no API to get it
+        return 2000;
     case ShowIsMaximized:
         return true;
     case SetFocusOnTouchRelease:
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 08fc8a5e9c7da76f2edc2f9bd44bc80ef0067abb..045d39e328cfe4b2c47ef48ac212001c1e63920b 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -165,7 +165,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
     [self reloadAllComponents];
 }
 
--(void)listenForKeyboardWillHideNotification:(BOOL)listen
+- (void)listenForKeyboardWillHideNotification:(BOOL)listen
 {
     if (listen) {
         [[NSNotificationCenter defaultCenter]
@@ -179,7 +179,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
     }
 }
 
--(void)dealloc
+- (void)dealloc
 {
     [self listenForKeyboardWillHideNotification:NO];
     self.toolbar = 0;
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 324133074b2e6b22a5761754d6b08184360503eb..3e16efcd22e4857672fc5ccf6b371526257d746b 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -104,12 +104,12 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
     @public
     QIOSScreen *m_screen;
 }
-- (id) initWithQIOSScreen:(QIOSScreen *)screen;
+- (id)initWithQIOSScreen:(QIOSScreen *)screen;
 @end
 
 @implementation QIOSOrientationListener
 
-- (id) initWithQIOSScreen:(QIOSScreen *)screen
+- (id)initWithQIOSScreen:(QIOSScreen *)screen
 {
     self = [super init];
     if (self) {
@@ -123,7 +123,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
     return self;
 }
 
-- (void) dealloc
+- (void)dealloc
 {
     [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
     [[NSNotificationCenter defaultCenter]
@@ -132,7 +132,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
     [super dealloc];
 }
 
-- (void) orientationChanged:(NSNotification *)notification
+- (void)orientationChanged:(NSNotification *)notification
 {
     Q_UNUSED(notification);
     m_screen->updateProperties();
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 3d0bac82c834253d985c51de80bc9af37b7221d7..d86f5451542932b66098bc82569230c435f1e5ab 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -92,12 +92,12 @@
     return [QUITextPosition positionWithIndex:(self.range.location + self.range.length)];
 }
 
-- (NSRange) range
+- (NSRange)range
 {
     return _range;
 }
 
--(BOOL)isEmpty
+- (BOOL)isEmpty
 {
     return (self.range.length == 0);
 }
@@ -111,7 +111,7 @@
 
 @implementation WrapperView
 
--(id)initWithView:(UIView *)view
+- (id)initWithView:(UIView *)view
 {
     if (self = [self init]) {
         [self addSubview:view];
@@ -143,7 +143,7 @@
 // retained, we ensure that all messages sent to the view during
 // its lifetime in a window hierarcy will be able to traverse the
 // responder chain.
--(void)willMoveToWindow:(UIWindow *)window
+- (void)willMoveToWindow:(UIWindow *)window
 {
     if (window)
         [[self nextResponder] retain];
@@ -170,25 +170,25 @@
     QVariantMap platformData = m_configuredImeState->value(Qt::ImPlatformData).toMap();
     Qt::InputMethodHints hints = Qt::InputMethodHints(m_configuredImeState->value(Qt::ImHints).toUInt());
 
-    Qt::ReturnKeyType returnKeyType = Qt::ReturnKeyType(m_configuredImeState->value(Qt::ImReturnKeyType).toUInt());
+    Qt::EnterKeyType enterKeyType = Qt::EnterKeyType(m_configuredImeState->value(Qt::ImEnterKeyType).toUInt());
 
-    switch (returnKeyType) {
-    case Qt::ReturnKeyEnter:
+    switch (enterKeyType) {
+    case Qt::EnterKeyReturn:
         self.returnKeyType = UIReturnKeyDefault;
         break;
-    case Qt::ReturnKeyDone:
+    case Qt::EnterKeyDone:
         self.returnKeyType = UIReturnKeyDone;
         break;
-    case Qt::ReturnKeyGo:
+    case Qt::EnterKeyGo:
         self.returnKeyType = UIReturnKeyGo;
         break;
-    case Qt::ReturnKeySend:
+    case Qt::EnterKeySend:
         self.returnKeyType = UIReturnKeySend;
         break;
-    case Qt::ReturnKeySearch:
+    case Qt::EnterKeySearch:
         self.returnKeyType = UIReturnKeySearch;
         break;
-    case Qt::ReturnKeyNext:
+    case Qt::EnterKeyNext:
         self.returnKeyType = UIReturnKeyNext;
         break;
     default:
@@ -255,7 +255,7 @@
     }
 
     // Based on what we set up in initWithInputContext above
-    updatedProperties &= (Qt::ImHints | Qt::ImReturnKeyType | Qt::ImPlatformData);
+    updatedProperties &= (Qt::ImHints | Qt::ImEnterKeyType | Qt::ImPlatformData);
 
     if (!updatedProperties)
         return NO;
@@ -383,17 +383,17 @@
     return m_inputContext->imeState().currentState.value(query);
 }
 
--(id<UITextInputTokenizer>)tokenizer
+- (id<UITextInputTokenizer>)tokenizer
 {
     return [[[UITextInputStringTokenizer alloc] initWithTextInput:id<UITextInput>(self)] autorelease];
 }
 
--(UITextPosition *)beginningOfDocument
+- (UITextPosition *)beginningOfDocument
 {
     return [QUITextPosition positionWithIndex:0];
 }
 
--(UITextPosition *)endOfDocument
+- (UITextPosition *)endOfDocument
 {
     int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
     return [QUITextPosition positionWithIndex:endPosition];
@@ -659,7 +659,7 @@
     return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey];
 }
 
--(NSDictionary *)markedTextStyle
+- (NSDictionary *)markedTextStyle
 {
     return [NSDictionary dictionary];
 }
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 6667ec3dd85c55fe34c7b6bb5bcedb6aec9db6ee..4ea5fc7de1d7ca7fb71d6695796b64c254106d08 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -288,13 +288,13 @@
 
 // -------------------------------------------------------------------------
 
--(BOOL)shouldAutorotate
+- (BOOL)shouldAutorotate
 {
     return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
 }
 
 #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0)
--(NSUInteger)supportedInterfaceOrientations
+- (NSUInteger)supportedInterfaceOrientations
 {
     // As documented by Apple in the iOS 6.0 release notes, setStatusBarOrientation:animated:
     // only works if the supportedInterfaceOrientations of the view controller is 0, making
@@ -307,7 +307,7 @@
 #endif
 
 #if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
--(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
 {
     Q_UNUSED(interfaceOrientation);
     return [self shouldAutorotate];
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 777a3c12c575f94ba6521e19ae9d53abc9b69085..80fba00ffb5416c81f5eb10ec3c464f47c8da99d 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -119,7 +119,8 @@ void QIOSWindow::setVisible(bool visible)
     }
 
     if (visible && shouldAutoActivateWindow()) {
-        requestActivateWindow();
+        if (!window()->property("_q_showWithoutActivating").toBool())
+            requestActivateWindow();
     } else if (!visible && [m_view isActiveWindow]) {
         // Our window was active/focus window but now hidden, so relinquish
         // focus to the next possible window in the stack.
@@ -145,6 +146,9 @@ void QIOSWindow::setVisible(bool visible)
 
 bool QIOSWindow::shouldAutoActivateWindow() const
 {
+    if (![m_view canBecomeFirstResponder])
+        return false;
+
     // We don't want to do automatic window activation for popup windows
     // that are unlikely to contain editable controls (to avoid hiding
     // the keyboard while the popup is showing)
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
index a690e12c7db1bd727fc9393af094df6c1a912bfb..c76e3a6a1eba87f8057b9b91a086a6b881f4d866 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.h
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -42,8 +42,8 @@
 
 @property (readonly) QAccessible::Id axid;
 
-- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
-+ (QMacAccessibilityElement *) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
+- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
++ (QMacAccessibilityElement *)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
 
 @end
 
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index 2cecfc1126daca7be7b442b55d5d926a4dfa1ea9..3bac1ca88d4618479d56c2616bae05c5240dee33 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -37,7 +37,7 @@
 
 @implementation QMacAccessibilityElement
 
-- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
 {
     Q_ASSERT((int)anId < 0);
     self = [super initWithAccessibilityContainer: view];
@@ -47,7 +47,7 @@
     return self;
 }
 
-+ (id) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
++ (id)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
 {
     Q_ASSERT(anId);
     if (!anId)
@@ -64,17 +64,17 @@
     return element;
 }
 
-- (void) invalidate
+- (void)invalidate
 {
     [self release];
 }
 
-- (BOOL) isAccessibilityElement
+- (BOOL)isAccessibilityElement
 {
     return YES;
 }
 
-- (NSString*) accessibilityLabel
+- (NSString*)accessibilityLabel
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (!iface) {
@@ -85,7 +85,7 @@
     return iface->text(QAccessible::Name).toNSString();
 }
 
-- (NSString*) accessibilityHint
+- (NSString*)accessibilityHint
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (!iface) {
@@ -95,7 +95,7 @@
     return iface->text(QAccessible::Description).toNSString();
 }
 
-- (NSString*) accessibilityValue
+- (NSString*)accessibilityValue
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (!iface) {
@@ -119,7 +119,7 @@
     return [super accessibilityHint];
 }
 
-- (CGRect) accessibilityFrame
+- (CGRect)accessibilityFrame
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (!iface) {
@@ -131,7 +131,7 @@
     return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
 }
 
-- (UIAccessibilityTraits) accessibilityTraits
+- (UIAccessibilityTraits)accessibilityTraits
 {
     UIAccessibilityTraits traits = UIAccessibilityTraitNone;
 
@@ -156,7 +156,7 @@
     return traits;
 }
 
-- (BOOL) accessibilityActivate
+- (BOOL)accessibilityActivate
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (QAccessibleActionInterface *action = iface->actionInterface()) {
@@ -171,21 +171,21 @@
     return NO; // fall back to sending mouse clicks
 }
 
-- (void) accessibilityIncrement
+- (void)accessibilityIncrement
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (QAccessibleActionInterface *action = iface->actionInterface())
         action->doAction(QAccessibleActionInterface::increaseAction());
 }
 
-- (void) accessibilityDecrement
+- (void)accessibilityDecrement
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     if (QAccessibleActionInterface *action = iface->actionInterface())
         action->doAction(QAccessibleActionInterface::decreaseAction());
 }
 
-- (BOOL) accessibilityScroll : (UIAccessibilityScrollDirection) direction
+- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction
 {
     QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
     QAccessibleActionInterface *action = iface->actionInterface();
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 8be3515cb58ad956408cd0908dbf4ade59b3c390..c6ef843b9f4b7aabed2540619d21eeb103336d5f 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -50,7 +50,7 @@
     return [CAEAGLLayer class];
 }
 
--(id)initWithQIOSWindow:(QIOSWindow *)window
+- (id)initWithQIOSWindow:(QIOSWindow *)window
 {
     if (self = [self initWithFrame:toCGRect(window->geometry())])
         m_qioswindow = window;
@@ -77,7 +77,7 @@
         if (QIOSIntegration::instance()->debugWindowManagement()) {
             static CGFloat hue = 0.0;
             CGFloat lastHue = hue;
-            for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabsf(hue - lastHue))
+            for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabs(hue - lastHue))
                 hue = drand48();
 
             #define colorWithBrightness(br) \
@@ -194,7 +194,7 @@
 
 - (BOOL)canBecomeFirstResponder
 {
-    return YES;
+    return !(m_qioswindow->window()->flags() & Qt::WindowDoesNotAcceptFocus);
 }
 
 - (BOOL)becomeFirstResponder
@@ -280,6 +280,12 @@
 
 // -------------------------------------------------------------------------
 
+-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
+{
+    if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput)
+        return NO;
+    return [super pointInside:point withEvent:event];
+}
 
 - (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
 {
@@ -310,7 +316,7 @@
     }
 }
 
-- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
+- (void)sendTouchEventWithTimestamp:(ulong)timeStamp
 {
     // Send touch event synchronously
     QIOSIntegration *iosIntegration = QIOSIntegration::instance();
diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp
index 8683a9c8d13212871d4118218a52abf7b606dc83..565ac7a7d419671698af6800b4d73a0f87a7e7c7 100644
--- a/src/plugins/platforms/kms/main.cpp
+++ b/src/plugins/platforms/kms/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "kms.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "kms.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp
index 046ee913d86071bdaf478984c57e6065442908b8..ba709840731a71f6cca2f21091feb6de380afeae 100644
--- a/src/plugins/platforms/linuxfb/main.cpp
+++ b/src/plugins/platforms/linuxfb/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "linuxfb.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "linuxfb.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp
index 4c746a85f238da631f859b1ea2c85b5daf266848..98babf687606d6f179bf4672d67b989419ae6724 100644
--- a/src/plugins/platforms/minimal/main.cpp
+++ b/src/plugins/platforms/minimal/main.cpp
@@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE
 class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimal.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimal.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/minimalegl/main.cpp b/src/plugins/platforms/minimalegl/main.cpp
index 7ee14ae5ff6b1627da0ae73ccb0a0341b44ad9bc..52ab3ad68996dcd2c9111addecb912cb099c43c9 100644
--- a/src/plugins/platforms/minimalegl/main.cpp
+++ b/src/plugins/platforms/minimalegl/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QMinimalEglIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimalegl.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimalegl.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp
index 64a0586036efdc46e5c300c08f42c1a7010a2198..363f2afcc3a3b30df8e2e4c9c2b63e65614cc2c9 100644
--- a/src/plugins/platforms/offscreen/main.cpp
+++ b/src/plugins/platforms/offscreen/main.cpp
@@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE
 class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "offscreen.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "offscreen.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/openwfd/main.cpp b/src/plugins/platforms/openwfd/main.cpp
index d28ab945fa7b09960cea70886c278d11dfce2306..b0403bc5332cefc8a7359ed7c372e10388249176 100644
--- a/src/plugins/platforms/openwfd/main.cpp
+++ b/src/plugins/platforms/openwfd/main.cpp
@@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE
 
 class QOpenWFDIntegrationPlugin : public QPlatformIntegrationPlugin
 {
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid)
 public:
     QPlatformIntegration *create(const QString&, const QStringList&);
 };
diff --git a/src/plugins/platforms/qnx/main.h b/src/plugins/platforms/qnx/main.h
index 5e69ee3889916192970530a925c3be24ac936035..955bef471c89e7c51dded5ba51bdc688d6b073ab 100644
--- a/src/plugins/platforms/qnx/main.h
+++ b/src/plugins/platforms/qnx/main.h
@@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE
 class QQnxIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "qnx.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "qnx.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&);
 };
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index 99c44c69eff1f7f1fc5f45d65e6d48779d37e651..5ed8d30e67576a52a8a9b1a7613fe856ce82361e 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -102,7 +102,7 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out
 
 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
 {
-    *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR));
+    *version = ::SysAllocString(TEXT(QT_VERSION_STR));
     return S_OK;
 }
 
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index 5bdcbef01eaad54dceadc53a79444eb49fac4ac1..29bb9562e30749fe96a618b5413349bf7e6cdeb7 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -97,7 +97,7 @@ QT_BEGIN_NAMESPACE
 class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "windows.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "windows.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&, int &, char **);
 };
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 0184877fdde6d2adecdfb99ab93f622380027035..06c9985cac29457b54fa2f4e0303ee7a8a9a083d 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -39,7 +39,6 @@
 #include <QtGui/QOpenGLContext>
 
 #if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
-#  define EGL_EGLEXT_PROTOTYPES
 #  include <QtANGLE/EGL/eglext.h>
 #endif
 
@@ -137,7 +136,6 @@ bool QWindowsLibEGL::init()
 
     eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
     eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
-    eglGetPlatformDisplayEXT = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLenum platform, void *native_display, const EGLint *attrib_list)), eglGetPlatformDisplayEXT);
     eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
     eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
     eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
@@ -156,7 +154,15 @@ bool QWindowsLibEGL::init()
     eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
     eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
 
-    return eglGetError && eglGetDisplay && eglInitialize;
+    if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
+        return false;
+
+    eglGetPlatformDisplayEXT = 0;
+#ifdef EGL_ANGLE_platform_angle
+    eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+#endif
+
+    return true;
 }
 
 #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
@@ -360,7 +366,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
     EGLDisplay display = EGL_NO_DISPLAY;
     EGLint major = 0;
     EGLint minor = 0;
-#ifdef EGL_ANGLE_platform_angle_opengl
+#ifdef EGL_ANGLE_platform_angle
     if (libEGL.eglGetPlatformDisplayEXT
         && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
         const EGLint anglePlatformAttributes[][5] = {
@@ -384,7 +390,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
             }
         }
     }
-#else // EGL_ANGLE_platform_angle_opengl
+#else // EGL_ANGLE_platform_angle
     Q_UNUSED(preferredType)
 #endif
     if (display == EGL_NO_DISPLAY)
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 2b249348c3ce4f5cda2c7a355b9ae40af769c30b..d8302c97a7e0b25ddea64a67bd5c335865dd7325 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -46,7 +46,6 @@ struct QWindowsLibEGL
 
     EGLint (EGLAPIENTRY * eglGetError)(void);
     EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
-    EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
     EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
     EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
     EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
@@ -74,6 +73,8 @@ struct QWindowsLibEGL
     EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
     __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname);
 
+    EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
+
 private:
 #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
     void *resolve(const char *name);
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 96911564034e99712e677cc3a9227e313a073f01..6e58c55bbe9439e6809779f975ef47fb7c1d8cf4 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -34,6 +34,7 @@
 #include "qwindowsnativeinterface.h"
 #include "qwindowswindow.h"
 #include "qwindowscontext.h"
+#include "qwindowsfontdatabase.h"
 #include "qwindowsopenglcontext.h"
 #include "qwindowsopengltester.h"
 #include "qwindowsintegration.h"
@@ -222,6 +223,11 @@ int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
     return QWindowsMime::registerMimeType(mimeType);
 }
 
+QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi)
+{
+    return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi);
+}
+
 QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const
 {
     if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index be8418b769638cb7a876a3f89e83ebb4a294020f..97839ae1ae3def66cee2d43828eb7b6cb2122352 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -34,6 +34,7 @@
 #ifndef QWINDOWSNATIVEINTERFACE_H
 #define QWINDOWSNATIVEINTERFACE_H
 
+#include <QtGui/qfont.h>
 #include <QtGui/qpa/qplatformnativeinterface.h>
 
 QT_BEGIN_NAMESPACE
@@ -77,6 +78,7 @@ public:
     Q_INVOKABLE void registerWindowsMime(void *mimeIn);
     Q_INVOKABLE void unregisterWindowsMime(void *mime);
     Q_INVOKABLE int registerMimeType(const QString &mimeType);
+    Q_INVOKABLE QFont logFontToQFont(const void *logFont, int verticalDpi);
 
     bool asyncExpose() const;
     void setAsyncExpose(bool value);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 30b58f78e93db8d62d1c97cac25b611498dd22c7..d6677bb2284b4c6d4f3d268163d9cce0abf0b388 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -438,6 +438,8 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d)
 // Fix top level window flags in case only the type flags are passed.
 static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
 {
+    // Not supported on Windows, also do correction when it is set.
+    flags &= ~Qt::WindowFullscreenButtonHint;
     switch (flags) {
     case Qt::Window:
         flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint
diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp
index 1398c52e968b167c8135260f24cdcce31caa20e3..d1cf08887f41f4df8d26721b66541263bcced928 100644
--- a/src/plugins/platforms/winrt/main.cpp
+++ b/src/plugins/platforms/winrt/main.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -40,7 +43,7 @@ QT_BEGIN_NAMESPACE
 class QWinRTIntegrationPlugin : public QPlatformIntegrationPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "winrt.json")
+    Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "winrt.json")
 
 public:
     QStringList keys() const;
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
index b55551e820b85f88b1805ad1a467c1c6df8dad7d..dcf8239538867758ca7ef035aeb784bf767bf9b1 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h
index 69bd3c397cf74ccd0d5efbb50b1069ca3f7d430e..20b27a38650210aabf5526306d799510ec6f1f52 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.h
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index 1adb2bb89f2b5f5250117933d7f5b0a7883e0e03..94ce23bd2cddfd186c2b0ca3558f185f902c6da7 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -46,7 +49,7 @@ using namespace Microsoft::WRL::Wrappers;
 using namespace ABI::Windows::UI::Core;
 using namespace ABI::Windows::Foundation;
 
-QT_USE_NAMESPACE
+QT_BEGIN_NAMESPACE
 
 class QWinRTCursorPrivate
 {
@@ -155,3 +158,6 @@ QPoint QWinRTCursor::pos() const
     coreWindow->get_PointerPosition(&point);
     return QPoint(point.X, point.Y);
 }
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h
index 4245faab6fe565ff3d5ed2a32fb948973daf7779..9c9b9e93ef8f42a59f3d2b52cb855e5743ad2bac 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.h
+++ b/src/plugins/platforms/winrt/qwinrtcursor.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -36,7 +39,7 @@
 
 #include <qpa/qplatformcursor.h>
 
-QT_USE_NAMESPACE
+QT_BEGIN_NAMESPACE
 
 class QWinRTCursorPrivate;
 class QWinRTCursor : public QPlatformCursor
@@ -54,4 +57,6 @@ private:
     Q_DECLARE_PRIVATE(QWinRTCursor)
 };
 
+QT_END_NAMESPACE
+
 #endif // QWINRTCURSOR_H
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
index fd90582119f6bc6f1ba798273e7ddf0482ff3fe6..42ffe8f716b625315fb5daf6de9ee275ada5403b 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -33,6 +36,9 @@
 
 #include "qwinrteglcontext.h"
 
+#define EGL_EGLEXT_PROTOTYPES
+#include "EGL/eglext.h"
+
 QT_BEGIN_NAMESPACE
 
 QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config)
@@ -40,6 +46,17 @@ QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGL
 {
 }
 
+void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface)
+{
+#ifdef Q_OS_WINPHONE
+    const QSize size = surface->surface()->size();
+    eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface),
+                       0, 0, size.width(), size.height());
+#else
+    eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface));
+#endif
+}
+
 EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
 {
     if (surface->surface()->surfaceClass() == QSurface::Window) {
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h
index bec9c190890adb7745c7332863cb22c3698ef708..958d623c4cff6d98ff9d02b6da39d866cd967b08 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.h
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -43,6 +46,7 @@ class QWinRTEGLContext : public QEGLPlatformContext
 public:
     explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config);
 
+    void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
     QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
 
 protected:
diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp
index 7f77b79660f216171aaa92b738a60cf8f6d0d2cd..716681c905a94622147545cc971d4bd5cca0327b 100644
--- a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp
+++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
index 35e637eba544e1b3aa5211687d937f0c0356b4f1..ecbdde34bd55b2a1eb85fcdd673da5d01e3492c5 100644
--- a/src/plugins/platforms/winrt/qwinrteventdispatcher.h
+++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index 417befeb639027ed9248551868641f1a579a55ba..e1b2a07d5f6947664e9863997325bf0d1d6a75e2 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
index 13abf6e2b8a1a49e5e654dc3adaa53212675cd84..51b79c84efcfbca299cc8b791b1af547beba730f 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index 719bb18dd6db5a7ae132929a31349065cf1d4700..858cb841b94a85e92de5e73b7e11d56a77acff2c 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h
index 983338f2e2d1527e52f0e3745c91096a3dd39db7..86721d85782d63985379c5c2c72a806b4b7e74a2 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.h
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -36,8 +39,6 @@
 
 #include <private/qabstractfileengine_p.h>
 
-QT_BEGIN_NAMESPACE
-
 namespace ABI {
     namespace Windows {
         namespace Storage {
@@ -46,6 +47,8 @@ namespace ABI {
     }
 }
 
+QT_BEGIN_NAMESPACE
+
 class QWinRTFileEngineHandlerPrivate;
 class QWinRTFileEngineHandler : public QAbstractFileEngineHandler
 {
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
index 15767c2805981cb6c33afbbf91f01eb3e04a3670..09edea52e7f3c54c011db19fb92eba246a855704 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -46,6 +49,71 @@ using namespace Microsoft::WRL;
 
 QT_BEGIN_NAMESPACE
 
+// Based on unicode range tables at http://www.microsoft.com/typography/otspec/os2.htm#ur
+static QFontDatabase::WritingSystem writingSystemFromUnicodeRange(const DWRITE_UNICODE_RANGE &range)
+{
+    if (range.first >= 0x0000 && range.last <= 0x007F)
+        return QFontDatabase::Latin;
+    if (range.first >= 0x0370 && range.last <= 0x03FF)
+        return QFontDatabase::Greek;
+    if (range.first >= 0x0400 && range.last <= 0x04FF)
+        return QFontDatabase::Cyrillic;
+    if (range.first >= 0x0530 && range.last <= 0x058F)
+        return QFontDatabase::Armenian;
+    if (range.first >= 0x0590 && range.last <= 0x05FF)
+        return QFontDatabase::Hebrew;
+    if (range.first >= 0x0600 && range.last <= 0x06FF)
+        return QFontDatabase::Arabic;
+    if (range.first >= 0x0700 && range.last <= 0x074F)
+        return QFontDatabase::Syriac;
+    if (range.first >= 0x0780 && range.last <= 0x07BF)
+        return QFontDatabase::Thaana;
+    if (range.first >= 0x0900 && range.last <= 0x097F)
+        return QFontDatabase::Devanagari;
+    if (range.first >= 0x0980 && range.last <= 0x09FF)
+        return QFontDatabase::Bengali;
+    if (range.first >= 0x0A00 && range.last <= 0x0A7F)
+        return QFontDatabase::Gurmukhi;
+    if (range.first >= 0x0A80 && range.last <= 0x0AFF)
+        return QFontDatabase::Gujarati;
+    if (range.first >= 0x0B00 && range.last <= 0x0B7F)
+        return QFontDatabase::Oriya;
+    if (range.first >= 0x0B80 && range.last <= 0x0BFF)
+        return QFontDatabase::Tamil;
+    if (range.first >= 0x0C00 && range.last <= 0x0C7F)
+        return QFontDatabase::Telugu;
+    if (range.first >= 0x0C80 && range.last <= 0x0CFF)
+        return QFontDatabase::Kannada;
+    if (range.first >= 0x0D00 && range.last <= 0x0D7F)
+        return QFontDatabase::Malayalam;
+    if (range.first >= 0x0D80 && range.last <= 0x0DFF)
+        return QFontDatabase::Sinhala;
+    if (range.first >= 0x0E00 && range.last <= 0x0E7F)
+        return QFontDatabase::Thai;
+    if (range.first >= 0x0E80 && range.last <= 0x0EFF)
+        return QFontDatabase::Lao;
+    if (range.first >= 0x0F00 && range.last <= 0x0FFF)
+        return QFontDatabase::Tibetan;
+    if (range.first >= 0x1000 && range.last <= 0x109F)
+        return QFontDatabase::Myanmar;
+    if (range.first >= 0x10A0 && range.last <= 0x10FF)
+        return QFontDatabase::Georgian;
+    if (range.first >= 0x1780 && range.last <= 0x17FF)
+        return QFontDatabase::Khmer;
+    if (range.first >= 0x4E00 && range.last <= 0x9FFF)
+        return QFontDatabase::SimplifiedChinese;
+    if (range.first >= 0xAC00 && range.last <= 0xD7AF)
+        return QFontDatabase::Korean;
+    if (range.first >= 0x1680 && range.last <= 0x169F)
+        return QFontDatabase::Ogham;
+    if (range.first >= 0x16A0 && range.last <= 0x16FF)
+        return QFontDatabase::Runic;
+    if (range.first >= 0x07C0 && range.last <= 0x07FF)
+        return QFontDatabase::Nko;
+
+    return QFontDatabase::Other;
+}
+
 QString QWinRTFontDatabase::fontDir() const
 {
     QString fontDirectory = QBasicFontDatabase::fontDir();
@@ -260,17 +328,27 @@ void QWinRTFontDatabase::populateFamily(const QString &familyName)
 
         const bool fixedPitch = fontFace->IsMonospacedFont();
 
-        quint32 unicodeRange[4];
+        // Get writing systems from unicode ranges
         quint32 actualRangeCount;
-        hr = fontFace->GetUnicodeRanges(
-                    2, reinterpret_cast<DWRITE_UNICODE_RANGE *>(unicodeRange), &actualRangeCount);
-        if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices
+        hr = fontFace->GetUnicodeRanges(0, nullptr, &actualRangeCount);
+        Q_ASSERT(hr == E_NOT_SUFFICIENT_BUFFER);
+        QVector<DWRITE_UNICODE_RANGE> unicodeRanges(actualRangeCount);
+        hr = fontFace->GetUnicodeRanges(actualRangeCount, unicodeRanges.data(), &actualRangeCount);
+        if (FAILED(hr)) {
             qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr)));
             continue;
         }
-        quint32 codePageRange[2] = { 0, 0 };
-        QSupportedWritingSystems writingSystems =
-                QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+        QSupportedWritingSystems writingSystems;
+        for (quint32 i = 0; i < actualRangeCount; ++i) {
+            const QFontDatabase::WritingSystem writingSystem = writingSystemFromUnicodeRange(unicodeRanges.at(i));
+            writingSystems.setSupported(writingSystem);
+        }
+        if (writingSystems.supported(QFontDatabase::SimplifiedChinese)) {
+            writingSystems.setSupported(QFontDatabase::TraditionalChinese);
+            writingSystems.setSupported(QFontDatabase::Japanese);
+        }
+        if (writingSystems.supported(QFontDatabase::Latin))
+            writingSystems.setSupported(QFontDatabase::Vietnamese);
 
         IDWriteFontFile *fontFile;
         hr = fontFace->GetFiles(&fileCount, &fontFile);
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
index cde81baa441b9d185a4d2870419ec6c5a30e2612..7b3f402c13738eede90bdd24abaabd49a17d2567 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -36,12 +39,14 @@
 
 #include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
 
-QT_BEGIN_NAMESPACE
-
 #ifdef QT_WINRT_USE_DWRITE
 struct IDWriteFontFile;
 struct IDWriteFontFamily;
+#endif
 
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_WINRT_USE_DWRITE
 struct FontDescription
 {
     quint32 index;
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
index f0de578db6ea0521fb31fb6804c7cb79576e86ed..c94b53ef1c6cc0af4ed6f30f708a97fc1caa0065 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h
index 761908a9cbad13f8b783cc7d39241242b6b181ee..ce7fbabf499c3faee2bb1319c0b935e8b9d05595 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.h
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 015ebaadb5503547a4f2c1376e9ec30d7ceeee47..70ee6dbe6a2ecef25579c907961bd24cd89f30c7 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
index 1ec44cd46a2384a3e2de9824c7b7f3fb54dd9309..bbd6c1e41b80e051bc6a3bf3c362417b7fceea9d 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.h
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
index c5d36345233cc3701fd3e3e59904e7ef316bc1fe..4fc1fea62698be0ca9758352867a114dc4489fbc 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
index fc510fe34ed85bcab3ce8eb3337e8c76cf08418a..2f473a05f7a2e5ebf9158c1fe755d0e6caed66f9 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index c4512b4d2d4d5e8d0c2d88e18bd8c910410b0906..1d36bb31f6c4c621618f872e41bb2b9bbf3a4929 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index cbef9543a9813f2b654187e2fe823dd4ba4eb611..d34ce75748e5a06e5c61dc8bc314b92932237ed0 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
index 1faa3945a79a78bde4f4492695dd0446f6dbabb2..cb04f670d2f5c8400e9b08342938d4fe1c95983f 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.cpp
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h
index 0262a2ab834b34168cb874e9aa30f56e484f1253..585eb2f010dfeb3fae728c5d56b84cacbb7e22c1 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.h
+++ b/src/plugins/platforms/winrt/qwinrtservices.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
@@ -37,7 +40,7 @@
 #include <qpa/qplatformservices.h>
 #include <QtCore/QScopedPointer>
 
-QT_USE_NAMESPACE
+QT_BEGIN_NAMESPACE
 
 class QWinRTServicesPrivate;
 class QWinRTServices : public QPlatformServices
@@ -54,4 +57,6 @@ private:
     Q_DECLARE_PRIVATE(QWinRTServices)
 };
 
+QT_END_NAMESPACE
+
 #endif // QWINRTSERVICES_H
diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp
index c42368cc8711d93bf4fa5cbb4663fdb1c5d99178..a0fa2798a8d5fb5082f352b9c2b8ab290afe9c2b 100644
--- a/src/plugins/platforms/winrt/qwinrttheme.cpp
+++ b/src/plugins/platforms/winrt/qwinrttheme.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrttheme.h b/src/plugins/platforms/winrt/qwinrttheme.h
index 73dcd6cdf46dbb675af1391f648ac9df3f7480a0..2e159cbd555e7031f65861f068d4e8e65f0cf06d 100644
--- a/src/plugins/platforms/winrt/qwinrttheme.h
+++ b/src/plugins/platforms/winrt/qwinrttheme.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index b96f4255c2a9f643166d146c13b86242f22efd39..adc5dfb776182877c257e4da247a8077d58efaef 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index eee95d6bd38f552141e7180cb61435110a507d68..3cfe346ab2dbe3310a14c3d735e0dcb1b7503dfd 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -5,7 +5,7 @@
 **
 ** This file is part of the plugins of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
 **
 ** 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.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.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.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
 **
 ** $QT_END_LICENSE$
 **
diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro
index 29b6d1d2f734b3136869e1ec0008ed10300cccb7..9de0476810e1412be7df59d042e65dcca423776b 100644
--- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro
+++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro
@@ -1,6 +1,6 @@
 TEMPLATE = subdirs
 
-contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) {
+contains(QT_CONFIG, egl): contains(QT_CONFIG, egl_x11): contains(QT_CONFIG, opengl) {
     SUBDIRS += xcb_egl
 }
 
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
index c71c668f31dda3d8e18af73d50333a6d7c39891d..74c117582a5301578cada7810779df601f9e66ed 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
@@ -57,7 +57,9 @@ public:
     virtual bool handleXcbEvent(xcb_generic_event_t *event, uint responseType);
 
     virtual QXcbWindow *createWindow(QWindow *window) const = 0;
+#ifndef QT_NO_OPENGL
     virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const = 0;
+#endif
     virtual QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const = 0;
 
     virtual QXcbNativeInterfaceHandler *nativeInterfaceHandler() const  { return Q_NULLPTR; }
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 5d32eb7614f188d58d44b4a92f5e5e961a85706d..78282d1415edd47c5a422d4d34a096aee28bdfb7 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -70,7 +70,6 @@
 #endif
 
 #if defined(XCB_USE_XINPUT2)
-#include <X11/extensions/XInput2.h>
 #include <X11/extensions/XI2proto.h>
 #endif
 
@@ -457,6 +456,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
     , m_focusWindow(0)
     , m_systemTrayTracker(0)
     , m_glIntegration(Q_NULLPTR)
+    , m_xiGrab(false)
 {
 #ifdef XCB_USE_XLIB
     Display *dpy = XOpenDisplay(m_displayName.constData());
@@ -909,7 +909,7 @@ static Qt::MouseButtons translateMouseButtons(int s)
     return ret;
 }
 
-static Qt::MouseButton translateMouseButton(xcb_button_t s)
+Qt::MouseButton QXcbConnection::translateMouseButton(xcb_button_t s)
 {
     switch (s) {
     case 1: return Qt::LeftButton;
@@ -944,39 +944,6 @@ static Qt::MouseButton translateMouseButton(xcb_button_t s)
     }
 }
 
-void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev)
-{
-    xcb_button_press_event_t *event = (xcb_button_press_event_t *)ev;
-
-    // the event explicitly contains the state of the three first buttons,
-    // the rest we need to manage ourselves
-    m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
-    m_buttons |= translateMouseButton(event->detail);
-    qCDebug(lcQpaXInput, "xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
-}
-
-void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev)
-{
-    xcb_button_release_event_t *event = (xcb_button_release_event_t *)ev;
-
-    // the event explicitly contains the state of the three first buttons,
-    // the rest we need to manage ourselves
-    m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
-    m_buttons &= ~translateMouseButton(event->detail);
-    qCDebug(lcQpaXInput, "xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
-}
-
-void QXcbConnection::handleMotionNotify(xcb_generic_event_t *ev)
-{
-    xcb_motion_notify_event_t *event = (xcb_motion_notify_event_t *)ev;
-
-    m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
-#ifdef Q_XCB_DEBUG
-    qCDebug(lcQpaXInput, "xcb: moved mouse to %4d, %4d; button state %X",
-           event->event_x, event->event_y, static_cast<unsigned int>(m_buttons));
-#endif
-}
-
 #ifndef QT_NO_XKB
 namespace {
     typedef union {
@@ -1018,18 +985,35 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
         switch (response_type) {
         case XCB_EXPOSE:
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
-        case XCB_BUTTON_PRESS:
-            m_keyboard->updateXKBStateFromCore(((xcb_button_press_event_t *)event)->state);
-            handleButtonPress(event);
+
+        // press/release/motion is only delivered here when XI 2.2+ is _not_ in use
+        case XCB_BUTTON_PRESS: {
+            xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;
+            m_keyboard->updateXKBStateFromCore(ev->state);
+            // the event explicitly contains the state of the three first buttons,
+            // the rest we need to manage ourselves
+            m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+            m_buttons |= translateMouseButton(ev->detail);
+            qCDebug(lcQpaXInput, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
-        case XCB_BUTTON_RELEASE:
-            m_keyboard->updateXKBStateFromCore(((xcb_button_release_event_t *)event)->state);
-            handleButtonRelease(event);
+        }
+        case XCB_BUTTON_RELEASE: {
+            xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
+            m_keyboard->updateXKBStateFromCore(ev->state);
+            m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+            m_buttons &= ~translateMouseButton(ev->detail);
+            qCDebug(lcQpaXInput, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
-        case XCB_MOTION_NOTIFY:
-            m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state);
-            handleMotionNotify(event);
+        }
+        case XCB_MOTION_NOTIFY: {
+            xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event;
+            m_keyboard->updateXKBStateFromCore(ev->state);
+            m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+            qCDebug(lcQpaXInput, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y,
+                    ev->detail, static_cast<unsigned int>(m_buttons));
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
+        }
+
         case XCB_CONFIGURE_NOTIFY:
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
         case XCB_MAP_NOTIFY:
@@ -1090,6 +1074,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
             break;
 #if defined(XCB_USE_XINPUT2)
         case XCB_GE_GENERIC:
+            // Here the windowEventListener is invoked from xi2HandleEvent()
             if (m_xi2Enabled)
                 xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
             break;
@@ -1931,6 +1916,12 @@ void QXcbConnection::initializeXKB()
 #endif
 }
 
+bool QXcbConnection::xi2MouseEvents() const
+{
+    static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
+    return mouseViaXI2;
+}
+
 #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 466492ce42d5cf196d4af9b3241133e005e2540e..0191b0e1efe72b5f0ac2b680f379d2f3769f0e64 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -69,7 +69,8 @@
 #endif
 #endif
 struct XInput2TouchDeviceData;
-#endif
+#endif // XCB_USE_XINPUT2
+
 struct xcb_randr_get_output_info_reply_t;
 
 //#define Q_XCB_DEBUG
@@ -347,6 +348,7 @@ 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 *) {}
+    virtual void handleXIMouseEvent(xcb_ge_event_t *) {}
 
     virtual QXcbWindow *toWindow() { return 0; }
 };
@@ -413,14 +415,14 @@ public:
     void xi2Select(xcb_window_t window);
 #endif
 #ifdef XCB_USE_XINPUT21
-    bool isUsingXInput21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
+    bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
 #else
-    bool isUsingXInput21() const { return false; }
+    bool isAtLeastXI21() const { return false; }
 #endif
 #ifdef XCB_USE_XINPUT22
-    bool isUsingXInput22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
+    bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
 #else
-    bool isUsingXInput22() const { return false; }
+    bool isAtLeastXI22() const { return false; }
 #endif
 
     void sync();
@@ -457,7 +459,9 @@ public:
 
     xcb_timestamp_t getTimestamp();
 
+    void setButton(Qt::MouseButton button, bool down) { if (down) m_buttons |= button; else m_buttons &= ~button; }
     Qt::MouseButtons buttons() const { return m_buttons; }
+    Qt::MouseButton translateMouseButton(xcb_button_t s);
 
     QXcbWindow *focusWindow() const { return m_focusWindow; }
     void setFocusWindow(QXcbWindow *);
@@ -479,12 +483,19 @@ public:
     void handleEnterEvent(const xcb_enter_notify_event_t *);
 #endif
 
+#ifdef XCB_USE_XINPUT22
+    bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
+#endif
+    Qt::MouseButton xiToQtMouseButton(uint32_t b);
+
     QXcbEventReader *eventReader() const { return m_reader; }
 
     bool canGrab() const { return m_canGrabServer; }
 
     QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
 
+    bool xi2MouseEvents() const;
+
 protected:
     bool event(QEvent *e) Q_DECL_OVERRIDE;
 
@@ -512,9 +523,6 @@ private:
     bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
     void initializeScreens();
     void updateScreens(const xcb_randr_notify_event_t *event);
-    void handleButtonPress(xcb_generic_event_t *event);
-    void handleButtonRelease(xcb_generic_event_t *event);
-    void handleMotionNotify(xcb_generic_event_t *event);
 
     bool m_xi2Enabled;
     int m_xi2Minor;
@@ -527,6 +535,9 @@ private:
     void xi2HandleHierachyEvent(void *event);
     void xi2HandleDeviceChangedEvent(void *event);
     int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
+#ifdef XCB_USE_XINPUT22
+    void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
+#endif // XCB_USE_XINPUT22
 #ifndef QT_NO_TABLETEVENT
     struct TabletData {
         TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer),
@@ -546,10 +557,10 @@ private:
         };
         QHash<int, ValuatorClassInfo> valuatorInfo;
     };
-    bool xi2HandleTabletEvent(void *event, TabletData *tabletData);
+    bool xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener);
     void xi2ReportTabletEvent(TabletData &tabletData, void *event);
     QVector<TabletData> m_tabletData;
-#endif
+#endif // !QT_NO_TABLETEVENT
     struct ScrollingDevice {
         ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { }
         int deviceId;
@@ -562,9 +573,7 @@ private:
     void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes);
     void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
     QHash<int, ScrollingDevice> m_scrollingDevices;
-#endif // XCB_USE_XINPUT2
 
-#if defined(XCB_USE_XINPUT2)
     static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value);
     static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode);
 #endif
@@ -636,6 +645,7 @@ private:
     QByteArray m_startupId;
     QXcbSystemTrayTracker *m_systemTrayTracker;
     QXcbGlIntegration *m_glIntegration;
+    bool m_xiGrab;
 
     friend class QXcbEventReader;
 };
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 9e48067a51a865e1867a07d4e41883e39a403b07..e165c753ab2a3bede1a69a555fabfbc602f169ab 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -43,7 +43,6 @@
 
 #include <X11/extensions/XInput2.h>
 #include <X11/extensions/XI2proto.h>
-#define FINGER_MAX_WIDTH_MM 10
 
 struct XInput2TouchDeviceData {
     XInput2TouchDeviceData()
@@ -175,9 +174,11 @@ void QXcbConnection::xi2SetupDevices()
             case XIKeyClass:
                 qCDebug(lcQpaXInputDevices) << "   it's a keyboard";
                 break;
+#ifdef XCB_USE_XINPUT22
             case XITouchClass:
                 // will be handled in deviceForId()
                 break;
+#endif
             default:
                 qCDebug(lcQpaXInputDevices) << "   has class" << devices[i].classes[c]->type;
                 break;
@@ -274,34 +275,37 @@ void QXcbConnection::xi2Select(xcb_window_t window)
     unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask);
 
 #ifdef XCB_USE_XINPUT22
-    if (isUsingXInput22()) {
+    if (isAtLeastXI22()) {
         bitMask |= XI_TouchBeginMask;
         bitMask |= XI_TouchUpdateMask;
         bitMask |= XI_TouchEndMask;
+        bitMask |= XI_PropertyEventMask; // for tablets
+        if (xi2MouseEvents()) {
+            // We want both mouse and touch through XI2 if touch is supported (>= 2.2).
+            // The plain xcb press and motion events will not be delivered after this.
+            bitMask |= XI_ButtonPressMask;
+            bitMask |= XI_ButtonReleaseMask;
+            bitMask |= XI_MotionMask;
+            qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch");
+        }
         XIEventMask mask;
         mask.mask_len = sizeof(bitMask);
         mask.mask = xiBitMask;
-        if (!m_touchDevices.isEmpty()) {
-            // If we select for touch events on the master pointer, XInput2
-            // will not synthesize mouse events. This means Qt must do it,
-            // which is also preferable, since Qt can control better when
-            // to do so.
-            mask.deviceid = XIAllMasterDevices;
-            Status result = XISelectEvents(xDisplay, window, &mask, 1);
-            if (result != Success)
-                qCDebug(lcQpaXInput, "XInput 2.2: failed to select touch events, window %x, result %d", window, result);
-        }
+        // When xi2MouseEvents() is true (the default), pointer emulation for touch and tablet
+        // events will get disabled. This is preferable for touch, as Qt Quick handles touch events
+        // directly while for others QtGui synthesizes mouse events, not so much for tablets. For
+        // the latter we will synthesize the events ourselves.
+        mask.deviceid = XIAllMasterDevices;
+        Status result = XISelectEvents(xDisplay, window, &mask, 1);
+        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();
     QSet<int> tabletDevices;
 #ifndef QT_NO_TABLETEVENT
-    // For each tablet, select some additional event types.
-    // Press, motion, etc. events must never be selected for _all_ devices
-    // as that would render the standard XCB_MOTION_NOTIFY and
-    // similar handlers useless and we have no intention to infect
-    // all the pure xcb code with Xlib-based XI2.
-    if (!m_tabletData.isEmpty()) {
+    if (!m_tabletData.isEmpty() && !pointerSelected) {
         unsigned int tabletBitMask;
         unsigned char *xiTabletBitMask = reinterpret_cast<unsigned char *>(&tabletBitMask);
         QVector<XIEventMask> xiEventMask(m_tabletData.count());
@@ -322,7 +326,8 @@ void QXcbConnection::xi2Select(xcb_window_t window)
 
 #ifdef XCB_USE_XINPUT21
     // Enable each scroll device
-    if (!m_scrollingDevices.isEmpty()) {
+    if (!m_scrollingDevices.isEmpty() && !pointerSelected) {
+        // Only when XI2 mouse events are not enabled, otherwise motion and release are selected already.
         QVector<XIEventMask> xiEventMask(m_scrollingDevices.size());
         unsigned int scrollBitMask;
         unsigned char *xiScrollBitMask = reinterpret_cast<unsigned char *>(&scrollBitMask);
@@ -359,8 +364,8 @@ void QXcbConnection::xi2Select(xcb_window_t window)
 XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
 {
     XInput2TouchDeviceData *dev = Q_NULLPTR;
-    QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.find(id);
-    if ( devIt != m_touchDevices.end() ) {
+    QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constFind(id);
+    if (devIt != m_touchDevices.cend()) {
         dev = devIt.value();
     } else {
         int nrDevices = 0;
@@ -424,7 +429,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
                     dev->size.width() > 10000 || dev->size.height() > 10000)
                 dev->size = QSizeF(130, 110);
         }
-        if (!isUsingXInput22() || type == QTouchDevice::TouchPad)
+        if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
             caps |= QTouchDevice::MouseEmulation;
 
         if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
@@ -446,9 +451,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
 }
 
 #if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT)
-static qreal fixed1616ToReal(FP1616 val)
+static inline qreal fixed1616ToReal(FP1616 val)
 {
-    return (qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF;
+    return qreal(val) / 0x10000;
 }
 #endif // defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT)
 
@@ -467,163 +472,280 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
 {
     if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
         xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+        int sourceDeviceId = xiEvent->deviceid; // may be the master id
+        xXIDeviceEvent *xiDeviceEvent = 0;
+        QXcbWindowEventListener *eventListener = 0;
 
-        if (xiEvent->evtype == XI_HierarchyChanged) {
+        switch (xiEvent->evtype) {
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_Motion:
+        case XI_TouchBegin:
+        case XI_TouchUpdate:
+        case XI_TouchEnd:
+        {
+            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_HierarchyChanged:
             xi2HandleHierachyEvent(xiEvent);
             return;
-        }
-        if (xiEvent->evtype == XI_DeviceChanged) {
+        case XI_DeviceChanged:
             xi2HandleDeviceChangedEvent(xiEvent);
             return;
+        default:
+            break;
         }
 
 #ifndef QT_NO_TABLETEVENT
         for (int i = 0; i < m_tabletData.count(); ++i) {
-            if (m_tabletData.at(i).deviceId == xiEvent->deviceid) {
-                if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i]))
+            if (m_tabletData.at(i).deviceId == sourceDeviceId) {
+                if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
                     return;
             }
         }
 #endif // QT_NO_TABLETEVENT
 
 #ifdef XCB_USE_XINPUT21
-        QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->deviceid);
+        QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
         if (device != m_scrollingDevices.end())
             xi2HandleScrollEvent(xiEvent, device.value());
 #endif // XCB_USE_XINPUT21
 
 #ifdef XCB_USE_XINPUT22
-        if (xiEvent->evtype == XI_TouchBegin || xiEvent->evtype == XI_TouchUpdate || xiEvent->evtype == XI_TouchEnd) {
-            xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
-            if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
-                qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f",
-                        event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail,
-                        fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
-                        fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y) );
-
-            if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
-                XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
-                Q_ASSERT(dev);
-                const bool firstTouch = m_touchPoints.isEmpty();
-                if (xiEvent->evtype == XI_TouchBegin) {
-                    QWindowSystemInterface::TouchPoint tp;
-                    tp.id = xiDeviceEvent->detail % INT_MAX;
-                    tp.state = Qt::TouchPointPressed;
-                    tp.pressure = -1.0;
-                    m_touchPoints[tp.id] = tp;
-                }
-                QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail];
-                qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
-                qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
-                qreal nx = -1.0, ny = -1.0, w = 0.0, h = 0.0;
-                QXcbScreen* screen = m_screens.at(0);
-                for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
-                    XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
-                    if (classinfo->type == XIValuatorClass) {
-                        XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
-                        int n = vci->number;
-                        double value;
-                        if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
-                            continue;
-                        if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
-                            qCDebug(lcQpaXInput, "   valuator %20s value %lf from range %lf -> %lf",
-                                    atomName(vci->label).constData(), value, vci->min, vci->max );
-                        if (vci->label == atom(QXcbAtom::RelX)) {
-                            nx = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::RelY)) {
-                            ny = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::AbsX)) {
-                            nx = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::AbsY)) {
-                            ny = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
-                            nx = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
-                            ny = valuatorNormalized(value, vci);
-                        } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
-                            // Convert the value within its range as a fraction of a finger's max (contact patch)
-                            //  width in mm, and from there to pixels depending on screen resolution
-                            w = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM *
-                                screen->geometry().width() / screen->physicalSize().width();
-                        } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) {
-                            h = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM *
-                                screen->geometry().height() / screen->physicalSize().height();
-                        } else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
-                                   vci->label == atom(QXcbAtom::AbsPressure)) {
-                            touchPoint.pressure = valuatorNormalized(value, vci);
-                        }
-                    }
-                }
-                // If any value was not updated, use the last-known value.
-                if (nx == -1.0) {
-                    x = touchPoint.area.center().x();
-                    nx = x / screen->geometry().width();
-                }
-                if (ny == -1.0) {
-                    y = touchPoint.area.center().y();
-                    ny = y / screen->geometry().height();
-                }
-                if (xiEvent->evtype != XI_TouchEnd) {
-                    if (w == 0.0)
-                        w = touchPoint.area.width();
-                    if (h == 0.0)
-                        h = touchPoint.area.height();
-                }
-
-                switch (xiEvent->evtype) {
-                case XI_TouchBegin:
-                    if (firstTouch) {
-                        dev->firstPressedPosition = QPointF(x, y);
-                        dev->firstPressedNormalPosition = QPointF(nx, ny);
-                    }
-                    dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y));
-                    break;
-                case XI_TouchUpdate:
-                    if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
-                        qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
-                            dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
-                        qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
-                            dev->size.height() * screen->geometry().height() / screen->physicalSize().height();
-                        x = dev->firstPressedPosition.x() + dx;
-                        y = dev->firstPressedPosition.y() + dy;
-                        touchPoint.state = Qt::TouchPointMoved;
-                    } else if (touchPoint.area.center() != QPoint(x, y)) {
-                        touchPoint.state = Qt::TouchPointMoved;
-                        dev->pointPressedPosition[touchPoint.id] = QPointF(x, y);
-                    }
-                    break;
-                case XI_TouchEnd:
-                    touchPoint.state = Qt::TouchPointReleased;
-                    if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
-                        qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
-                            dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
-                        qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
-                            dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
-                        x = dev->firstPressedPosition.x() + dx;
-                        y = dev->firstPressedPosition.y() + dy;
-                    }
-                    dev->pointPressedPosition.remove(touchPoint.id);
-                }
-                touchPoint.area = QRectF(x - w/2, y - h/2, w, h);
-                touchPoint.normalPosition = QPointF(nx, ny);
+        if (xiDeviceEvent) {
+            switch (xiDeviceEvent->evtype) {
+            case XI_ButtonPress:
+            case XI_ButtonRelease:
+            case XI_Motion:
+                if (xi2MouseEvents() && eventListener)
+                    eventListener->handleXIMouseEvent(event);
+                break;
 
+            case XI_TouchBegin:
+            case XI_TouchUpdate:
+            case XI_TouchEnd:
                 if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
-                    qCDebug(lcQpaXInput) << "   touchpoint "  << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
-                            " area " << touchPoint.area << " pressure " << touchPoint.pressure;
-                QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiEvent->time, dev->qtTouchDevice, m_touchPoints.values());
-                if (touchPoint.state == Qt::TouchPointReleased)
-                    // If a touchpoint was released, we can forget it, because the ID won't be reused.
-                    m_touchPoints.remove(touchPoint.id);
-                else
-                    // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent
-                    // with this touch point if the next XI2 event is about a different touch point.
-                    touchPoint.state = Qt::TouchPointStationary;
+                    qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
+                            event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
+                            fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
+                            fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
+                if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
+                    xi2ProcessTouch(xiDeviceEvent, platformWindow);
+                break;
             }
         }
 #endif // XCB_USE_XINPUT22
     }
 }
 
+#ifdef XCB_USE_XINPUT22
+void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
+{
+    xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
+    XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
+    Q_ASSERT(dev);
+    const bool firstTouch = m_touchPoints.isEmpty();
+    if (xiDeviceEvent->evtype == XI_TouchBegin) {
+        QWindowSystemInterface::TouchPoint tp;
+        tp.id = xiDeviceEvent->detail % INT_MAX;
+        tp.state = Qt::TouchPointPressed;
+        tp.pressure = -1.0;
+        m_touchPoints[tp.id] = tp;
+    }
+    QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail];
+    qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
+    qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
+    qreal nx = -1.0, ny = -1.0, d = 0.0;
+    QXcbScreen* screen = m_screens.at(0);
+    for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
+        XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
+        if (classinfo->type == XIValuatorClass) {
+            XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+            int n = vci->number;
+            double value;
+            if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
+                continue;
+            if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+                qCDebug(lcQpaXInput, "   valuator %20s value %lf from range %lf -> %lf",
+                        atomName(vci->label).constData(), value, vci->min, vci->max );
+            if (vci->label == atom(QXcbAtom::RelX)) {
+                nx = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::RelY)) {
+                ny = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::AbsX)) {
+                nx = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::AbsY)) {
+                ny = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
+                nx = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
+                ny = valuatorNormalized(value, vci);
+            } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
+                d = valuatorNormalized(value, vci) * screen->geometry().width();
+            } else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
+                       vci->label == atom(QXcbAtom::AbsPressure)) {
+                touchPoint.pressure = valuatorNormalized(value, vci);
+            }
+        }
+    }
+    // If any value was not updated, use the last-known value.
+    if (nx == -1.0) {
+        x = touchPoint.area.center().x();
+        nx = x / screen->geometry().width();
+    }
+    if (ny == -1.0) {
+        y = touchPoint.area.center().y();
+        ny = y / screen->geometry().height();
+    }
+    if (xiDeviceEvent->evtype != XI_TouchEnd) {
+        if (d == 0.0)
+            d = touchPoint.area.width();
+    }
+
+    switch (xiDeviceEvent->evtype) {
+    case XI_TouchBegin:
+        if (firstTouch) {
+            dev->firstPressedPosition = QPointF(x, y);
+            dev->firstPressedNormalPosition = QPointF(nx, ny);
+        }
+        dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y));
+
+        // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence
+        // will get replayed when the grab ends.
+        if (m_xiGrab) {
+            // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2)
+            // http://lists.x.org/archives/xorg-devel/2014-July/043059.html
+#ifndef LIBXI_MAJOR
+            static bool allowTouchWarningShown = false;
+            if (!allowTouchWarningShown) {
+                allowTouchWarningShown = true;
+                qWarning("Skipping XIAllowTouchEvents() because it was not possible to detect libXi version at build time."
+                         " Minimum libXi version required is 1.7.4."
+                         " Expect issues with touch behavior.");
+            }
+#elif LIBXI_MAJOR == 1 && (LIBXI_MINOR < 7 || (LIBXI_MINOR == 7 && LIBXI_PATCH < 4))
+            static bool allowTouchWarningShown = false;
+            if (!allowTouchWarningShown) {
+                allowTouchWarningShown = true;
+                qWarning("Skipping XIAllowTouchEvents() due to not having libXi >= 1.7.4."
+                         " libXi version at build time was %d.%d.%d."
+                         " Expect issues with touch behavior.", LIBXI_MAJOR, LIBXI_MINOR, LIBXI_PATCH);
+            }
+#else
+            XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
+                               xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch);
+#endif
+        }
+        break;
+    case XI_TouchUpdate:
+        if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+            qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+                dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+            qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+                dev->size.height() * screen->geometry().height() / screen->physicalSize().height();
+            x = dev->firstPressedPosition.x() + dx;
+            y = dev->firstPressedPosition.y() + dy;
+            touchPoint.state = Qt::TouchPointMoved;
+        } else if (touchPoint.area.center() != QPoint(x, y)) {
+            touchPoint.state = Qt::TouchPointMoved;
+            dev->pointPressedPosition[touchPoint.id] = QPointF(x, y);
+        }
+        break;
+    case XI_TouchEnd:
+        touchPoint.state = Qt::TouchPointReleased;
+        if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+            qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+                dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+            qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+                dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+            x = dev->firstPressedPosition.x() + dx;
+            y = dev->firstPressedPosition.y() + dy;
+        }
+        dev->pointPressedPosition.remove(touchPoint.id);
+    }
+    touchPoint.area = QRectF(x - d/2, y - d/2, d, d);
+    touchPoint.normalPosition = QPointF(nx, ny);
+
+    if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+        qCDebug(lcQpaXInput) << "   touchpoint "  << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
+            " area " << touchPoint.area << " pressure " << touchPoint.pressure;
+    QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, m_touchPoints.values());
+    if (touchPoint.state == Qt::TouchPointReleased)
+        // If a touchpoint was released, we can forget it, because the ID won't be reused.
+        m_touchPoints.remove(touchPoint.id);
+    else
+        // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent
+        // with this touch point if the next XI2 event is about a different touch point.
+        touchPoint.state = Qt::TouchPointStationary;
+}
+
+bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
+{
+    if (grab && !canGrab())
+        return false;
+
+    int num_devices = 0;
+    Display *xDisplay = static_cast<Display *>(xlib_display());
+    XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices);
+    if (!info)
+        return false;
+
+    XIEventMask evmask;
+    unsigned char mask[XIMaskLen(XI_LASTEVENT)];
+    evmask.mask = mask;
+    evmask.mask_len = sizeof(mask);
+    memset(mask, 0, sizeof(mask));
+    evmask.deviceid = XIAllMasterDevices;
+
+    XISetMask(mask, XI_ButtonPress);
+    XISetMask(mask, XI_ButtonRelease);
+    XISetMask(mask, XI_Motion);
+    XISetMask(mask, XI_TouchBegin);
+    XISetMask(mask, XI_TouchUpdate);
+    XISetMask(mask, XI_TouchEnd);
+
+    bool grabbed = true;
+    for (int i = 0; i < num_devices; i++) {
+        int id = info[i].deviceid, n = 0;
+        XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n);
+        if (deviceInfo) {
+            const bool grabbable = deviceInfo->use != XIMasterKeyboard;
+            XIFreeDeviceInfo(deviceInfo);
+            if (!grabbable)
+                continue;
+        }
+        if (!grab) {
+            Status result = XIUngrabDevice(xDisplay, id, CurrentTime);
+            if (result != Success) {
+                grabbed = false;
+                qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result);
+            }
+        } else {
+            Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync,
+                                         XIGrabModeAsync, False, &evmask);
+            if (result != Success) {
+                grabbed = false;
+                qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result);
+            }
+        }
+    }
+
+    XIFreeDeviceInfo(info);
+
+    m_xiGrab = grabbed;
+
+    return grabbed;
+}
+#endif // XCB_USE_XINPUT22
+
 void QXcbConnection::xi2HandleHierachyEvent(void *event)
 {
     xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event);
@@ -790,7 +912,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
 #endif // XCB_USE_XINPUT21
 }
 
-static Qt::MouseButton xiToQtMouseButton(uint32_t b) {
+Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
+{
     switch (b) {
     case 1: return Qt::LeftButton;
     case 2: return Qt::MiddleButton;
@@ -837,20 +960,29 @@ static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) {
 }
 
 #ifndef QT_NO_TABLETEVENT
-bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
+bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener)
 {
     bool handled = true;
     Display *xDisplay = static_cast<Display *>(m_xlib_display);
     xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
+    xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xiEvent);
+
+#ifdef XCB_USE_XINPUT22
+    // 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));
+#endif
+
     switch (xiEvent->evtype) {
     case XI_ButtonPress: {
-        Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+        Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
         tabletData->buttons |= b;
         xi2ReportTabletEvent(*tabletData, xiEvent);
         break;
     }
     case XI_ButtonRelease: {
-        Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+        Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
         tabletData->buttons ^= b;
         xi2ReportTabletEvent(*tabletData, xiEvent);
         break;
@@ -913,7 +1045,7 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
                         // TODO maybe have a hash of tabletData->deviceId to device data so we can
                         // look up the tablet name here, and distinguish multiple tablets
                         qCDebug(lcQpaXInput, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d",
-                            ev->deviceid, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
+                            tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
                             ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool);
                     }
                     XFree(data);
@@ -977,7 +1109,7 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
 
     if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
         qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
-            ev->deviceid, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
+            tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
             fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
             fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
             (int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 5a7c2cef83c95bf6fe42eee8649d55167fe56a0c..f3bffd2998331ebe188aa87131d6efe69b034c0f 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -47,6 +47,12 @@
 #include <stdio.h>
 #include <X11/keysym.h>
 
+#ifdef XCB_USE_XINPUT22
+#include <X11/extensions/XI2proto.h>
+#undef KeyPress
+#undef KeyRelease
+#endif
+
 #ifndef XK_ISO_Left_Tab
 #define XK_ISO_Left_Tab         0xFE20
 #endif
@@ -791,6 +797,31 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
     }
 }
 
+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);
+        const xkb_state_component newState = xkb_state_update_mask(xkb_state,
+                                                                   mods->base_mods,
+                                                                   mods->latched_mods,
+                                                                   mods->locked_mods,
+                                                                   group->base_group,
+                                                                   group->latched_group,
+                                                                   group->locked_group);
+
+        if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
+            //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
+        }
+    }
+#else
+    Q_UNUSED(modInfo);
+    Q_UNUSED(groupInfo);
+    Q_ASSERT(false); // this can't be
+#endif
+}
+
 quint32 QXcbKeyboard::xkbModMask(quint16 state)
 {
     quint32 xkb_mask = 0;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 2281674e2f6e4e54ab564b9ee4f355c4c5fd5f6c..d2e37d624cfe5960bf50d8f18f2a82756824fa4d 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -68,6 +68,7 @@ public:
     void updateXKBMods();
     quint32 xkbModMask(quint16 state);
     void updateXKBStateFromCore(quint16 state);
+    void updateXKBStateFromXI(void *modInfo, void *groupInfo);
 #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/qxcbmain.cpp b/src/plugins/platforms/xcb/qxcbmain.cpp
index 0c3e8b5cd3c63b1c178f6a8eae55cdf45189d1d2..4a07b6649131c252e42ba1174e85a35af3fe0606 100644
--- a/src/plugins/platforms/xcb/qxcbmain.cpp
+++ b/src/plugins/platforms/xcb/qxcbmain.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QXcbIntegrationPlugin : public QPlatformIntegrationPlugin
 {
    Q_OBJECT
-   Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "xcb.json")
+   Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "xcb.json")
 public:
     QPlatformIntegration *create(const QString&, const QStringList&, int &, char **) Q_DECL_OVERRIDE;
 };
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index ad7e5a032089a61c452aa1850503722812998742..3bc0df6f5795933470511b371ea22367f2603d71 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -98,6 +98,7 @@
 
 #if defined(XCB_USE_XINPUT2)
 #include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2proto.h>
 #endif
 
 #define XCOORD_MAX 16383
@@ -2069,16 +2070,17 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
     }
 }
 
-void QXcbWindow::handleButtonPressEvent(const xcb_button_press_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)
 {
-    const bool isWheel = event->detail >= 4 && event->detail <= 7;
+    const bool isWheel = detail >= 4 && detail <= 7;
     if (!isWheel && window() != QGuiApplication::focusWindow()) {
         QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver();
         if (!(w->flags() & Qt::WindowDoesNotAcceptFocus))
             w->requestActivate();
     }
 
-    updateNetWmUserTime(event->time);
+    updateNetWmUserTime(timestamp);
 
     if (m_embedded) {
         if (window() != QGuiApplication::focusWindow()) {
@@ -2088,51 +2090,121 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
             sendXEmbedMessage(container->xcb_window(), XEMBED_REQUEST_FOCUS);
         }
     }
-    QPoint local(event->event_x, event->event_y);
-    QPoint global = QPoint(event->root_x, event->root_y);
-
-    Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+    QPoint local(event_x, event_y);
+    QPoint global(root_x, root_y);
 
     if (isWheel) {
-        if (!connection()->isUsingXInput21()) {
+        if (!connection()->isAtLeastXI21()) {
             // Logic borrowed from qapplication_x11.cpp
-            int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
-            bool hor = (((event->detail == 4 || event->detail == 5)
+            int delta = 120 * ((detail == 4 || detail == 6) ? 1 : -1);
+            bool hor = (((detail == 4 || detail == 5)
                          && (modifiers & Qt::AltModifier))
-                        || (event->detail == 6 || event->detail == 7));
+                        || (detail == 6 || detail == 7));
 
-            QWindowSystemInterface::handleWheelEvent(window(), event->time,
+            QWindowSystemInterface::handleWheelEvent(window(), timestamp,
                                                      local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers);
         }
         return;
     }
 
-    handleMouseEvent(event->time, local, global, modifiers);
+    handleMouseEvent(timestamp, local, global, modifiers);
 }
 
-void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
+void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
+                                          int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
 {
-    QPoint local(event->event_x, event->event_y);
-    QPoint global = QPoint(event->root_x, event->root_y);
-    Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+    QPoint local(event_x, event_y);
+    QPoint global(root_x, root_y);
 
-    if (event->detail >= 4 && event->detail <= 7) {
+    if (detail >= 4 && detail <= 7) {
         // mouse wheel, handled in handleButtonPressEvent()
         return;
     }
 
-    handleMouseEvent(event->time, local, global, modifiers);
+    handleMouseEvent(timestamp, local, global, modifiers);
+}
+
+void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
+                                         Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
+{
+    QPoint local(event_x, event_y);
+    QPoint global(root_x, root_y);
+    handleMouseEvent(timestamp, local, global, modifiers);
+}
+
+// Handlers for plain xcb events. Used only when XI 2.2 or newer is not available.
+void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
+{
+    Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+    handleButtonPressEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
+                           modifiers, event->time);
+}
+
+void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
+{
+    Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+    handleButtonReleaseEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
+                             modifiers, event->time);
 }
 
 void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
 {
-    QPoint local(event->event_x, event->event_y);
-    if (!xcbScreen())
-        return;
-    QPoint global = QPoint(event->root_x, event->root_y);
     Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+    handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, event->time);
+}
 
-    handleMouseEvent(event->time, local, global, modifiers);
+#ifdef XCB_USE_XINPUT22
+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);
+    const int event_x = fixed1616ToInt(ev->event_x);
+    const int event_y = fixed1616ToInt(ev->event_y);
+    const int root_x = fixed1616ToInt(ev->root_x);
+    const int root_y = fixed1616ToInt(ev->root_y);
+
+    conn->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
+
+    const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail);
+
+    if (ev->buttons_len > 0) {
+        unsigned char *buttonMask = (unsigned char *) &ev[1];
+        for (int i = 1; i <= 15; ++i)
+            conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
+    }
+
+    switch (ev->evtype) {
+    case XI_ButtonPress:
+        qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button);
+        conn->setButton(button, true);
+        handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
+        break;
+    case XI_ButtonRelease:
+        qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button);
+        conn->setButton(button, false);
+        handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
+        break;
+    case XI_Motion:
+        qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y);
+        handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time);
+        break;
+    default:
+        qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
+        break;
+    }
+#else
+    Q_UNUSED(event);
+    Q_ASSERT(false); // this can't be
+#endif
 }
 
 QXcbWindow *QXcbWindow::toWindow() { return this; }
@@ -2314,6 +2386,10 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
 
 bool QXcbWindow::setMouseGrabEnabled(bool grab)
 {
+#ifdef XCB_USE_XINPUT22
+    if (connection()->xi2MouseEvents())
+        return connection()->xi2SetMouseGrabEnabled(m_window, grab);
+#endif
     if (grab && !connection()->canGrab())
         return false;
 
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 14280f292cc23c6db0171b01b131e8cfa880ab30..1010600e4426b55db642f82dab62181cfac40612 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -132,6 +132,7 @@ 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;
+    void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE;
 
     QXcbWindow *toWindow() Q_DECL_OVERRIDE;
 
@@ -204,6 +205,15 @@ protected:
     void doFocusIn();
     void doFocusOut();
 
+    void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
+                                int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
+    void handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
+                                  int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
+    void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
+                                 Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
     xcb_window_t m_window;
 
     QXcbScreen *m_xcbScreen;
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index fd704dd9041a2829862b9398cebe07b032291b88..12987567ff8d4e064695e9a7ef48d194fcb6bc19 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -59,6 +59,11 @@ contains(QT_CONFIG, xcb-xlib) {
         DEFINES += XCB_USE_XINPUT2
         SOURCES += qxcbconnection_xi2.cpp
         LIBS += -lXi
+        !isEmpty(QMAKE_LIBXI_VERSION_MAJOR) {
+            DEFINES += LIBXI_MAJOR=$$QMAKE_LIBXI_VERSION_MAJOR \
+                       LIBXI_MINOR=$$QMAKE_LIBXI_VERSION_MINOR \
+                       LIBXI_PATCH=$$QMAKE_LIBXI_VERSION_PATCH
+        }
     }
 }
 
diff --git a/src/plugins/platformthemes/gtk2/main.cpp b/src/plugins/platformthemes/gtk2/main.cpp
index 2431443dfa3791a02e719ce25faf7b9baccec731..34ac3ffc0798021e520fd6a6f8bdc8e44e3e4205 100644
--- a/src/plugins/platformthemes/gtk2/main.cpp
+++ b/src/plugins/platformthemes/gtk2/main.cpp
@@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE
 class QGtk2ThemePlugin : public QPlatformThemePlugin
 {
    Q_OBJECT
-   Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformThemeFactoryInterface.5.1" FILE "gtk2.json")
+   Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "gtk2.json")
 
 public:
     QPlatformTheme *create(const QString &key, const QStringList &params) Q_DECL_OVERRIDE;
diff --git a/src/plugins/printsupport/cocoa/main.cpp b/src/plugins/printsupport/cocoa/main.cpp
index d0925bbc34d5696b5e8d53da7419d651a71533d0..2037724719e60a2200f197749cfc9ba9baf2aed6 100644
--- a/src/plugins/printsupport/cocoa/main.cpp
+++ b/src/plugins/printsupport/cocoa/main.cpp
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
 class QCocoaPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.QPlatformPrinterSupportFactoryInterface" FILE "cocoa.json")
+    Q_PLUGIN_METADATA(IID QPlatformPrinterSupportFactoryInterface_iid FILE "cocoa.json")
 
 public:
     QPlatformPrinterSupport *create(const QString &);
diff --git a/src/plugins/printsupport/cups/main.cpp b/src/plugins/printsupport/cups/main.cpp
index 9651a074cc537c1bcb9ae26a416cdf5bd5a6fb6b..82485114ab24e3111c7f55ea12eb67ec237ee8eb 100644
--- a/src/plugins/printsupport/cups/main.cpp
+++ b/src/plugins/printsupport/cups/main.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
 class QCupsPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.QPlatformPrinterSupportFactoryInterface" FILE "cups.json")
+    Q_PLUGIN_METADATA(IID QPlatformPrinterSupportFactoryInterface_iid FILE "cups.json")
 
 public:
     QStringList keys() const;
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index c2bd2872a998ca14063208acc65702b58cdf93e4..808424b1ed19a2e64809bf41c9ffc286c9fa028a 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -89,16 +89,6 @@ QPpdPrintDevice::QPpdPrintDevice(const QString &id)
     }
 }
 
-QPpdPrintDevice::QPpdPrintDevice(const QPpdPrintDevice &other)
-    : QPlatformPrintDevice(other),
-      m_cupsDest(0),
-      m_ppd(0)
-{
-    m_cupsName = other.m_cupsName;
-    m_cupsInstance = other.m_cupsInstance;
-    loadPrinter();
-}
-
 QPpdPrintDevice::~QPpdPrintDevice()
 {
     if (m_ppd)
@@ -109,20 +99,6 @@ QPpdPrintDevice::~QPpdPrintDevice()
     m_ppd = 0;
 }
 
-QPpdPrintDevice &QPpdPrintDevice::operator=(const QPpdPrintDevice &other)
-{
-    m_cupsName = other.m_cupsName;
-    m_cupsInstance = other.m_cupsInstance;
-    if (other.m_cupsDest && other.m_ppd)
-        loadPrinter();
-    return *this;
-}
-
-bool QPpdPrintDevice::operator==(const QPpdPrintDevice &other) const
-{
-    return (m_id == other.m_id);
-}
-
 bool QPpdPrintDevice::isValid() const
 {
     return m_cupsDest && m_ppd;
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h
index 2437234d287751da48605864f74077840340f060..64eb872bd19fa7426fae68f51e3b7c928ec2d22c 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.h
+++ b/src/plugins/printsupport/cups/qppdprintdevice.h
@@ -63,15 +63,8 @@ class QPpdPrintDevice : public QPlatformPrintDevice
 public:
     QPpdPrintDevice();
     explicit QPpdPrintDevice(const QString &id);
-    QPpdPrintDevice(const QPpdPrintDevice &other);
     virtual ~QPpdPrintDevice();
 
-    QPpdPrintDevice &operator=(const QPpdPrintDevice &other);
-
-    QPpdPrintDevice *clone();
-
-    bool operator==(const QPpdPrintDevice &other) const;
-
     bool isValid() const Q_DECL_OVERRIDE;
     bool isDefault() const Q_DECL_OVERRIDE;
 
diff --git a/src/plugins/printsupport/windows/main.cpp b/src/plugins/printsupport/windows/main.cpp
index f1ee620b8b7aeeac87f201fdc64305a128c03381..28e99f19166c185d8a2d326ca24c4da48f47c1bc 100644
--- a/src/plugins/printsupport/windows/main.cpp
+++ b/src/plugins/printsupport/windows/main.cpp
@@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE
 class QWindowsPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
 {
     Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.qt-project.QPlatformPrinterSupportFactoryInterface" FILE "windows.json")
+    Q_PLUGIN_METADATA(IID QPlatformPrinterSupportFactoryInterface_iid FILE "windows.json")
 
 public:
     QPlatformPrinterSupport *create(const QString &);
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index af8e07edd21680dfeb126c10eed5804f16b06987..505f3138cac08d45d72effaa8d87931d5f68c099 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -113,28 +113,11 @@ QWindowsPrintDevice::QWindowsPrintDevice(const QString &id)
     }
 }
 
-QWindowsPrintDevice::QWindowsPrintDevice(const QWindowsPrintDevice &other)
-    : QPlatformPrintDevice(other)
-{
-    OpenPrinter((LPWSTR)other.m_id.utf16(), &m_hPrinter, NULL);
-}
-
 QWindowsPrintDevice::~QWindowsPrintDevice()
 {
     ClosePrinter(m_hPrinter);
 }
 
-QWindowsPrintDevice &QWindowsPrintDevice::operator=(const QWindowsPrintDevice &other)
-{
-    OpenPrinter((LPWSTR)other.m_id.utf16(), &m_hPrinter, NULL);
-    return *this;
-}
-
-bool QWindowsPrintDevice::operator==(const QWindowsPrintDevice &other) const
-{
-    return (m_id == other.m_id);
-}
-
 bool QWindowsPrintDevice::isValid() const
 {
     return m_hPrinter;
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h
index 2e0f6e4658f0c4bba68a0efbd681e67beb5047a3..8ab487a59cc7b7ea2839c77133a4031a26bb364d 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.h
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h
@@ -58,15 +58,8 @@ class QWindowsPrintDevice : public QPlatformPrintDevice
 public:
     QWindowsPrintDevice();
     explicit QWindowsPrintDevice(const QString &id);
-    QWindowsPrintDevice(const QWindowsPrintDevice &other);
     virtual ~QWindowsPrintDevice();
 
-    QWindowsPrintDevice &operator=(const QWindowsPrintDevice &other);
-
-    QWindowsPrintDevice *clone();
-
-    bool operator==(const QWindowsPrintDevice &other) const;
-
     bool isValid() const Q_DECL_OVERRIDE;
     bool isDefault() const Q_DECL_OVERRIDE;
 
diff --git a/src/plugins/styles/bb10style/bright/button/core_button_inactive.png b/src/plugins/styles/bb10style/bright/button/core_button_inactive.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/button/core_button_pressed.png b/src/plugins/styles/bb10style/bright/button/core_button_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png b/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png b/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png b/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png b/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png b/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png b/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/button/core_button_inactive.png b/src/plugins/styles/bb10style/dark/button/core_button_inactive.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/button/core_button_pressed.png b/src/plugins/styles/bb10style/dark/button/core_button_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png b/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png b/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png b/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png b/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png b/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png
old mode 100755
new mode 100644
diff --git a/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png b/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png
old mode 100755
new mode 100644
diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
index 886cbc0152498eba3ff60be2f5ba6356cd356e77..b86de31883b5740bbfaa337293e9736a858feb53 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm
+++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
@@ -201,10 +201,9 @@ int QPageSetupDialog::exec()
 
     QDialog::setVisible(true);
 
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     static_cast <QMacPageSetupDialogPrivate*>(d)->openCocoaPageLayout(Qt::ApplicationModal);
     static_cast <QMacPageSetupDialogPrivate*>(d)->closeCocoaPageLayout();
-    [pool release];
 
     QDialog::setVisible(false);
 
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index 1655131de41cde89befb1ef31152923a3ded310b..030526954dc8b1b714ae52d38a818416565a7ba7 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -301,10 +301,9 @@ int QPrintDialog::exec()
 
     QDialog::setVisible(true);
 
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     d->openCocoaPrintPanel(Qt::ApplicationModal);
     d->closeCocoaPrintPanel();
-    [pool release];
 
     QDialog::setVisible(false);
 
diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp
index bd6d81774c7ad4b1f501d7eb3e918b5dfff5b05a..6385f58aa12a3341b4827bd0929fe0393ed10fbe 100644
--- a/src/printsupport/kernel/qplatformprintdevice.cpp
+++ b/src/printsupport/kernel/qplatformprintdevice.cpp
@@ -75,11 +75,6 @@ QPlatformPrintDevice::~QPlatformPrintDevice()
 {
 }
 
-bool QPlatformPrintDevice::operator==(const QPlatformPrintDevice &other) const
-{
-    return m_id == other.m_id;
-}
-
 QString QPlatformPrintDevice::id() const
 {
     return m_id;
diff --git a/src/printsupport/kernel/qplatformprintdevice.h b/src/printsupport/kernel/qplatformprintdevice.h
index 1e21e608add2d095492d5b06f4567bfbb12603a5..8bb87a70f9fee7fedafd013fbce05bd7d2f148a5 100644
--- a/src/printsupport/kernel/qplatformprintdevice.h
+++ b/src/printsupport/kernel/qplatformprintdevice.h
@@ -55,17 +55,14 @@ QT_BEGIN_NAMESPACE
 
 #ifndef QT_NO_PRINTER
 
-class Q_PRINTSUPPORT_EXPORT QPlatformPrintDevice : public QSharedData
+class Q_PRINTSUPPORT_EXPORT QPlatformPrintDevice
 {
+    Q_DISABLE_COPY(QPlatformPrintDevice)
 public:
     QPlatformPrintDevice();
     explicit QPlatformPrintDevice(const QString &id);
     virtual ~QPlatformPrintDevice();
 
-    QPlatformPrintDevice *clone();
-
-    bool operator==(const QPlatformPrintDevice &other) const;
-
     virtual QString id() const;
     virtual QString name() const;
     virtual QString location() const;
diff --git a/src/printsupport/kernel/qplatformprintplugin.h b/src/printsupport/kernel/qplatformprintplugin.h
index 279de9b952327acdb291735c48dcaf47cd69102a..ad39bf5a0c9bbef82c166303f760c993f92619df 100644
--- a/src/printsupport/kernel/qplatformprintplugin.h
+++ b/src/printsupport/kernel/qplatformprintplugin.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
 
 class QPlatformPrinterSupport;
 
-#define QPlatformPrinterSupportFactoryInterface_iid "org.qt-project.QPlatformPrinterSupportFactoryInterface"
+#define QPlatformPrinterSupportFactoryInterface_iid "org.qt-project.QPlatformPrinterSupportFactoryInterface.5.1"
 
 class Q_PRINTSUPPORT_EXPORT QPlatformPrinterSupportPlugin : public QObject
 {
diff --git a/src/printsupport/kernel/qprintdevice.cpp b/src/printsupport/kernel/qprintdevice.cpp
index 7c18b53e092d98803216973c96fe81bc49ee45aa..a640c14483b68464297fa2bac6b58d535d987610 100644
--- a/src/printsupport/kernel/qprintdevice.cpp
+++ b/src/printsupport/kernel/qprintdevice.cpp
@@ -73,7 +73,7 @@ QPrintDevice &QPrintDevice::operator=(const QPrintDevice &other)
 bool QPrintDevice::operator==(const QPrintDevice &other) const
 {
     if (d && other.d)
-        return *d == *other.d;
+        return d->id() == other.d->id();
     return d == other.d;
 }
 
diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h
index ad55cded0e2d304b20e1241c12465a6a0e4619dc..ddf5595734ee068993320897c2632a1fd93713a4 100644
--- a/src/printsupport/kernel/qprintdevice_p.h
+++ b/src/printsupport/kernel/qprintdevice_p.h
@@ -136,7 +136,7 @@ private:
     friend class QPlatformPrinterSupport;
     friend class QPlatformPrintDevice;
     QPrintDevice(QPlatformPrintDevice *dd);
-    QSharedDataPointer<QPlatformPrintDevice> d;
+    QSharedPointer<QPlatformPrintDevice> d;
 };
 
 Q_DECLARE_SHARED(QPrintDevice)
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 246dae0ddf080864eb2688b14e243c164eb55a98..a106a585026ad849ec357469199cb26894684942 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -1764,7 +1764,7 @@ QRectF QPrinter::paperRect(Unit unit) const
 }
 
 /*!
-    \obsolete Use pageLayout().paintRect() instead.
+    \obsolete Use pageLayout().paintRectPixels(resolution()) instead.
 
     Returns the page's rectangle; this is usually smaller than the
     paperRect() since the page normally has margins between its
@@ -1781,7 +1781,7 @@ QRect QPrinter::pageRect() const
 }
 
 /*!
-    \obsolete Use pageLayout().fullPageRect() instead.
+    \obsolete Use pageLayout().fullRectPixels(resolution()) instead.
 
     Returns the paper's rectangle; this is usually larger than the
     pageRect().
diff --git a/src/printsupport/widgets/qprintpreviewwidget.cpp b/src/printsupport/widgets/qprintpreviewwidget.cpp
index 6033381b5822226bffcfe898e66477ac0a64bf87..686dab07bfa2f96cfee84ee6007c3e69a62f0ef3 100644
--- a/src/printsupport/widgets/qprintpreviewwidget.cpp
+++ b/src/printsupport/widgets/qprintpreviewwidget.cpp
@@ -335,8 +335,8 @@ void QPrintPreviewWidgetPrivate::populateScene()
     pages.clear();
 
     int numPages = pictures.count();
-    QSize paperSize = printer->paperRect().size();
-    QRect pageRect = printer->pageRect();
+    QSize paperSize = printer->pageLayout().fullRectPixels(printer->resolution()).size();
+    QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution());
 
     for (int i = 0; i < numPages; i++) {
         PageItem* item = new PageItem(i+1, pictures.at(i), paperSize, pageRect);
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 6262c25e0d4da3d4aa06b41f43403a046bd90d2b..c35fca7217e45936053b2de0bfd5ef3ab838389f 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -837,6 +837,9 @@ QString QSqlResult::executedQuery() const
     return d->executedQuery;
 }
 
+/*!
+    Resets the number of bind parameters.
+*/
 void QSqlResult::resetBindCount()
 {
     Q_D(QSqlResult);
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index b687ae568d3c229f629adcc71b8a6d350171c9ac..b0d3e6df9d412ab8c2b50c1444b89ff92347b698 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -1302,6 +1302,14 @@ Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
         return QSqlQueryModel::flags(index) | Qt::ItemIsEditable;
 }
 
+/*!
+    This is an overloaded function.
+
+    It returns an empty record, having only the field names. This function can be used to
+    retrieve the field names of a record.
+
+    \sa QSqlRecord::isEmpty()
+*/
 QSqlRecord QSqlTableModel::record() const
 {
     return QSqlQueryModel::record();
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 35b4fbcb7b77d110f6f32fb8e0dc79fa0f123b25..0fafc733b18cdce3acb7a9cbacab2c9928f7b716 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -40,5 +40,8 @@ excludedirs += ../../../examples/widgets/doc
 
 imagedirs   += images
 
+# Add a thumbnail for examples that do not have images
+manifestmeta.thumbnail.names = "QtTestLib/Chapter *"
+
 navigation.landingpage = "Qt Test"
 navigation.cppclassespage = "Qt Test C++ Classes"
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 81cc07c410cc2f06467013203117c378f19bc209..994179958b2e7bd968d60ea879d73e6804197e04 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -274,14 +274,33 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
 }
 QT_END_NAMESPACE
 
+#ifdef QT_TESTCASE_BUILDDIR
+#  define QTEST_SET_MAIN_SOURCE_PATH  QTest::setMainSourcePath(__FILE__, QT_TESTCASE_BUILDDIR);
+#else
+#  define QTEST_SET_MAIN_SOURCE_PATH  QTest::setMainSourcePath(__FILE__);
+#endif
+
 #define QTEST_APPLESS_MAIN(TestObject) \
 int main(int argc, char *argv[]) \
 { \
     TestObject tc; \
+    QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
 }
 
 #include <QtTest/qtestsystem.h>
+#include <set>
+
+#ifndef QT_NO_OPENGL
+#  define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+    extern Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &); \
+    extern Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &);
+#  define QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+    qgpu_features_ptr = qgpu_features;
+#else
+#  define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+#  define QTEST_ADD_GPU_BLACKLIST_SUPPORT
+#endif
 
 #if defined(QT_WIDGETS_LIB)
 
@@ -294,12 +313,17 @@ int main(int argc, char *argv[]) \
 #endif
 
 #define QTEST_MAIN(TestObject) \
+QT_BEGIN_NAMESPACE \
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+QT_END_NAMESPACE \
 int main(int argc, char *argv[]) \
 { \
     QApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
     QTEST_DISABLE_KEYPAD_NAVIGATION \
+    QTEST_ADD_GPU_BLACKLIST_SUPPORT \
     TestObject tc; \
+    QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
 }
 
@@ -308,11 +332,16 @@ int main(int argc, char *argv[]) \
 #include <QtTest/qtest_gui.h>
 
 #define QTEST_MAIN(TestObject) \
+QT_BEGIN_NAMESPACE \
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+QT_END_NAMESPACE \
 int main(int argc, char *argv[]) \
 { \
     QGuiApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
+    QTEST_ADD_GPU_BLACKLIST_SUPPORT \
     TestObject tc; \
+    QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
 }
 
@@ -324,6 +353,7 @@ int main(int argc, char *argv[]) \
     QCoreApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
     TestObject tc; \
+    QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
 }
 
@@ -335,6 +365,7 @@ int main(int argc, char *argv[]) \
     QCoreApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
     TestObject tc; \
+    QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
 }
 
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index bfeca0861778f65c462e7336410b6458ab13b288..f9ce908a008b7f23c4fac647f164083be82c3c80 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -34,6 +34,7 @@
 #include "qtestresult_p.h"
 
 #include <QtTest/qtestcase.h>
+#include <QtTest/qtest.h>
 #include <QtCore/qbytearray.h>
 #include <QtCore/qfile.h>
 #include <QtCore/qset.h>
@@ -161,6 +162,9 @@ static bool checkCondition(const QByteArray &condition)
 
 static bool ignoreAll = false;
 static std::set<QByteArray> *ignoredTests = 0;
+static std::set<QByteArray> *gpuFeatures = 0;
+
+Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &) = 0;
 
 namespace QTestPrivate {
 
@@ -196,7 +200,18 @@ void parseBlackList()
     }
 }
 
-void checkBlackList(const char *slot, const char *data)
+void parseGpuBlackList()
+{
+    if (!qgpu_features_ptr)
+        return;
+    QString filename = QTest::qFindTestData(QStringLiteral("GPU_BLACKLIST"));
+    if (filename.isEmpty())
+        return;
+    if (!gpuFeatures)
+        gpuFeatures = qgpu_features_ptr(filename);
+}
+
+void checkBlackLists(const char *slot, const char *data)
 {
     bool ignore = ignoreAll;
 
@@ -211,6 +226,16 @@ void checkBlackList(const char *slot, const char *data)
     }
 
     QTestResult::setBlacklistCurrentTest(ignore);
+
+    // Tests blacklisted in GPU_BLACKLIST are to be skipped. Just ignoring the result is
+    // not sufficient since these are expected to crash or behave in undefined ways.
+    if (!ignore && gpuFeatures) {
+        const QByteArray disableKey = QByteArrayLiteral("disable_") + QByteArray(slot);
+        if (gpuFeatures->find(disableKey) != gpuFeatures->end()) {
+            const QByteArray msg = QByteArrayLiteral("Skipped due to GPU blacklist: ") + disableKey;
+            QTest::qSkip(msg.constData(), __FILE__, __LINE__);
+        }
+    }
 }
 
 }
diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h
index 158d99593e86dddfd7fd37c322a4ec3f0bbc96fe..87f4dfdb5e8893ddebd910c3a26669da12bdc9c5 100644
--- a/src/testlib/qtestblacklist_p.h
+++ b/src/testlib/qtestblacklist_p.h
@@ -50,8 +50,10 @@
 QT_BEGIN_NAMESPACE
 
 namespace QTestPrivate {
-    void parseBlackList();
-    void checkBlackList(const char *slot, const char *data);
+    // Export functions so they can also be used by QQuickTest
+    Q_TESTLIB_EXPORT void parseBlackList();
+    Q_TESTLIB_EXPORT void parseGpuBlackList();
+    Q_TESTLIB_EXPORT void checkBlackLists(const char *slot, const char *data);
 }
 
 QT_END_NAMESPACE
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index e1e6805a0f52e815621a8252b0c244f160acc40c..858475f3963cf0d11d59cb317a65475f9e0f88de 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1374,6 +1374,7 @@ static bool installCoverageTool(const char * appname, const char * testname)
 namespace QTest
 {
     static QObject *currentTestObject = 0;
+    static QString mainSourcePath;
 
     class TestFunction {
     public:
@@ -2167,7 +2168,7 @@ static bool qInvokeTestMethod(const char *slotName, const char *data, WatchDog *
                 if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
                     foundFunction = true;
 
-                    QTestPrivate::checkBlackList(slot, dataCount ? table.testData(curDataIndex)->dataTag() : 0);
+                    QTestPrivate::checkBlackLists(slot, dataCount ? table.testData(curDataIndex)->dataTag() : 0);
 
                     QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
                                                       : table.testData(curDataIndex));
@@ -2682,6 +2683,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
 #endif
 
     QTestPrivate::parseBlackList();
+    QTestPrivate::parseGpuBlackList();
 
     QTestResult::reset();
 
@@ -3032,6 +3034,13 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co
             found = candidate;
     }
 
+    // 6. Try main source directory
+    if (found.isEmpty()) {
+        QString candidate = QTest::mainSourcePath % QLatin1Char('/') % base;
+        if (QFileInfo(candidate).exists())
+            found = candidate;
+    }
+
     if (found.isEmpty()) {
         QTest::qWarn(qPrintable(
             QString::fromLatin1("testdata %1 could not be located!").arg(base)),
@@ -3218,6 +3227,19 @@ QObject *QTest::testObject()
     return currentTestObject;
 }
 
+/*! \internal
+ */
+void QTest::setMainSourcePath(const char *file, const char *builddir)
+{
+    QString mainSourceFile = QFile::decodeName(file);
+    QFileInfo fi;
+    if (builddir)
+        fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
+    else
+        fi.setFile(mainSourceFile);
+    QTest::mainSourcePath = fi.absolutePath();
+}
+
 /*! \internal
     This function is called by various specializations of QTest::qCompare
     to decide whether to report a failure and to produce verbose test output.
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index 45290de6de47856ac433d386a531094895a116ce..2c6a94faa1c9f2024eedad289317b7f003693077 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -236,6 +236,8 @@ namespace QTest
     Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = 0);
     Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
 
+    Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = 0);
+
     Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description,
                                  const char *file, int line);
     Q_TESTLIB_EXPORT void qFail(const char *statementStr, const char *file, int line);
diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/testlib/qtestmouse.cpp
similarity index 81%
rename from src/plugins/platforms/cocoa/qcocoaautoreleasepool.h
rename to src/testlib/qtestmouse.cpp
index 8b2a9f3788d5ea4ec36bb88a30325a30f053a154..99a75744fab67a97dc686188d9d484939c545747 100644
--- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h
+++ b/src/testlib/qtestmouse.cpp
@@ -3,7 +3,7 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtTest module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL21$
 ** Commercial License Usage
@@ -31,23 +31,17 @@
 **
 ****************************************************************************/
 
-#ifndef QCOCOAAUTORELEASEPOOL_H
-#define QCOCOAAUTORELEASEPOOL_H
-
-#undef slots
-#include <qglobal.h>
-#include <Cocoa/Cocoa.h>
+#include <QtCore/QtGlobal>
+#include <QtCore/qnamespace.h>
+#include <QtTest/qtest_global.h>
 
 QT_BEGIN_NAMESPACE
-class QCocoaAutoReleasePool
-{
-public:
-    QCocoaAutoReleasePool();
-    ~QCocoaAutoReleasePool();
 
-private:
-    NSAutoreleasePool *pool;
-};
-QT_END_NAMESPACE
+namespace QTest {
+
+Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton = Qt::NoButton;
+Q_TESTLIB_EXPORT int lastMouseTimestamp = 0;
 
-#endif // QCOCOAAUTORELEASEPOOL_H
+} // namespace QTest
+
+QT_END_NAMESPACE
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index 2cf84a7ea0720d5ea9c994c4f016cf94168ee164..cd3901ae6fed7e50d69ec4a3924ac6425f450cdc 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -45,6 +45,7 @@
 #include <QtTest/qtestspontaneevent.h>
 #include <QtCore/qpoint.h>
 #include <QtCore/qstring.h>
+#include <QtCore/qpointer.h>
 #include <QtGui/qevent.h>
 #include <QtGui/qwindow.h>
 
@@ -57,12 +58,15 @@
 
 QT_BEGIN_NAMESPACE
 
-Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
+Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp);
 
 namespace QTest
 {
     enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove };
 
+    extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton;
+    extern Q_TESTLIB_EXPORT int lastMouseTimestamp;
+
     static void waitForEvents()
     {
 #ifdef Q_OS_MAC
@@ -83,52 +87,48 @@ namespace QTest
             QTest::qWarn("Mouse event occurs outside of target window.");
         }
 
-         static Qt::MouseButton lastButton = Qt::NoButton;
-
         if (delay == -1 || delay < defaultMouseDelay())
             delay = defaultMouseDelay();
-        if (delay > 0)
+        if (delay > 0) {
             QTest::qWait(delay);
+            lastMouseTimestamp += delay;
+        }
 
         if (pos.isNull())
             pos = window->geometry().center();
 
-        if (action == MouseClick) {
-            mouseEvent(MousePress, window, button, stateKey, pos);
-            mouseEvent(MouseRelease, window, button, stateKey, pos);
-            return;
-        }
         QTEST_ASSERT(uint(stateKey) == 0 || stateKey & Qt::KeyboardModifierMask);
 
         stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask);
 
+        QPointF global = window->mapToGlobal(pos);
+        QPointer<QWindow> w(window);
 
         switch (action)
         {
-            case MousePress:
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey);
-                lastButton = button;
-                break;
-            case MouseRelease:
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey);
-                lastButton = Qt::NoButton;
-                break;
-            case MouseDClick:
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey);
-                qWait(10);
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey);
-                qWait(20);
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey);
-                qWait(10);
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey);
-                break;
-            case MouseMove:
-                qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),lastButton,stateKey);
-                // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system
-                // which is highly undesired here. Tests must avoid relying on QCursor.
+        case MouseDClick:
+            qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp);
+            qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp);
+            // fall through
+        case MousePress:
+        case MouseClick:
+            qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp);
+            lastMouseButton = button;
+            if (action == MousePress)
                 break;
-            default:
-                QTEST_ASSERT(false);
+            // fall through
+        case MouseRelease:
+            qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp);
+            lastMouseTimestamp += 500; // avoid double clicks being generated
+            lastMouseButton = Qt::NoButton;
+            break;
+        case MouseMove:
+            qt_handleMouseEvent(w, pos, global, lastMouseButton, stateKey, ++lastMouseTimestamp);
+            // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system
+            // which is highly undesired here. Tests must avoid relying on QCursor.
+            break;
+        default:
+            QTEST_ASSERT(false);
         }
         waitForEvents();
     }
@@ -153,6 +153,15 @@ namespace QTest
                            Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1)
     {
         QTEST_ASSERT(widget);
+
+        if (pos.isNull())
+            pos = widget->rect().center();
+
+#ifdef QTEST_QPA_MOUSE_HANDLING
+        QWindow *w = widget->window()->windowHandle();
+        QTEST_ASSERT(w);
+        mouseEvent(action, w, button, stateKey, w->mapFromGlobal(widget->mapToGlobal(pos)), delay);
+#else
         extern int Q_TESTLIB_EXPORT defaultMouseDelay();
 
         if (delay == -1 || delay < defaultMouseDelay())
@@ -160,9 +169,6 @@ namespace QTest
         if (delay > 0)
             QTest::qWait(delay);
 
-        if (pos.isNull())
-            pos = widget->rect().center();
-
         if (action == MouseClick) {
             mouseEvent(MousePress, widget, button, stateKey, pos);
             mouseEvent(MouseRelease, widget, button, stateKey, pos);
@@ -198,12 +204,12 @@ namespace QTest
         }
         QSpontaneKeyEvent::setSpontaneous(&me);
         if (!qApp->notify(widget, &me)) {
-            static const char *mouseActionNames[] =
+            static const char *const mouseActionNames[] =
                 { "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" };
             QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget");
             QTest::qWarn(warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])).toLatin1().data());
         }
-
+#endif
     }
 
     inline void mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0,
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 52bcdd097bc440702f7d19428cfc37aed067c1b1..2d9bae5f31c6a73e4d74a64ce9a85bd3f14f0cc8 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -56,6 +56,7 @@ SOURCES = qtestcase.cpp \
     qcsvbenchmarklogger.cpp \
     qtestelement.cpp \
     qtestelementattribute.cpp \
+    qtestmouse.cpp \
     qtestxunitstreamer.cpp \
     qxunittestlogger.cpp \
     qtestblacklist.cpp
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index a92e5b8f3d7f193e1cf729c9b765d57b09308111..be6bcadacba015469bd6a6cf7d80bdbfc9d763ce 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -97,6 +97,7 @@ SOURCES += \
            ../../corelib/tools/qlocale_tools.cpp \
            ../../corelib/tools/qmap.cpp \
            ../../corelib/tools/qregexp.cpp \
+           ../../corelib/tools/qringbuffer.cpp \
            ../../corelib/tools/qpoint.cpp \
            ../../corelib/tools/qrect.cpp \
            ../../corelib/tools/qsize.cpp \
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 8b6a0519c560e857d5203416209cbd6e37157b2d..5be58d3c4bd50aa6b5913d602ec0dcce299dfa98 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -448,7 +448,8 @@ void Generator::generateCode()
 // Generate internal qt_static_metacall() function
 //
     const bool hasStaticMetaCall = !isQt &&
-            (cdef->hasQObject || !cdef->methodList.isEmpty() || !cdef->propertyList.isEmpty());
+            (cdef->hasQObject || !cdef->methodList.isEmpty()
+             || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
     if (hasStaticMetaCall)
         generateStaticMetacall();
 
@@ -1125,7 +1126,8 @@ void Generator::generateStaticMetacall()
                 fprintf(out, "%s", QByteArray("QPrivateSignal()").constData());
             }
             fprintf(out, ");\n");
-            fprintf(out, "            if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n");
+            fprintf(out, "            if (_a[0]) *reinterpret_cast<%s**>(_a[0]) = _r; } break;\n",
+                    cdef->hasQGadget ? "void" : "QObject");
         }
         fprintf(out, "        default: break;\n");
         fprintf(out, "        }\n");
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 51873033c7257b74b5fd071eec10cef1183bc0c1..f253c49995cbffd9746fbef28e444eeeee8b94d7 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -661,8 +661,10 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion += s;
                 }
             } else if (mode == Hash) {
-                if (index < 0)
+                if (index < 0 || index >= arguments.size()) {
                     that->error("'#' is not followed by a macro parameter");
+                    continue;
+                }
 
                 const Symbols &arg = arguments.at(index);
                 QByteArray stringified;
@@ -681,7 +683,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion.pop_back();
 
                 Symbol next = s;
-                if (index >= 0) {
+                if (index >= 0 && index < arguments.size()) {
                     const Symbols &arg = arguments.at(index);
                     if (arg.size() == 0) {
                         mode = Normal;
@@ -703,7 +705,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion += next;
                 }
 
-                if (index >= 0) {
+                if (index >= 0 && index < arguments.size()) {
                     const Symbols &arg = arguments.at(index);
                     for (int i = 1; i < arg.size(); ++i)
                         expansion += arg.at(i);
diff --git a/src/tools/qdoc/atom.cpp b/src/tools/qdoc/atom.cpp
index ebbe685985c68faceb3348fcd5283390b25b403c..f50f401c5b68055e1af01c1ed936da289fb92667 100644
--- a/src/tools/qdoc/atom.cpp
+++ b/src/tools/qdoc/atom.cpp
@@ -66,8 +66,6 @@ QT_BEGIN_NAMESPACE
 
 /*! \enum Atom::AtomType
 
-  \value AbstractLeft
-  \value AbstractRight
   \value AnnotatedList
   \value AutoLink
   \value BaseName
@@ -149,8 +147,6 @@ static const struct {
     const char *english;
     int no;
 } atms[] = {
-    { "AbstractLeft", Atom::AbstractLeft },
-    { "AbstractRight", Atom::AbstractRight },
     { "AnnotatedList", Atom::AnnotatedList },
     { "AutoLink", Atom::AutoLink },
     { "BaseName", Atom::BaseName },
diff --git a/src/tools/qdoc/atom.h b/src/tools/qdoc/atom.h
index dae106a74258f497877a5ee22f63fc5fc135cf14..86b8ba7b3c6573258a185108d72e506f6ced6f57 100644
--- a/src/tools/qdoc/atom.h
+++ b/src/tools/qdoc/atom.h
@@ -47,8 +47,6 @@ class Atom
 {
 public:
     enum AtomType {
-        AbstractLeft,
-        AbstractRight,
         AnnotatedList,
         AutoLink,
         BaseName,
diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp
index 90823080ce99af0d011b089c7f7e82d207e4bf44..4f80ec80d99666bb762dab403723dadeeb3926b1 100644
--- a/src/tools/qdoc/codeparser.cpp
+++ b/src/tools/qdoc/codeparser.cpp
@@ -423,33 +423,6 @@ void CodeParser::checkModuleInclusion(Node* n)
                                             .arg(n->name()).arg(Generator::defaultModuleName()));
             }
             break;
-#if 0
-        case Node::Document:
-            if (n->access() != Node::Private && !n->doc().isEmpty()) {
-                if (n->docSubtype() == Node::HeaderFile) {
-#if 0
-                    n->doc().location().warning(tr("Header file with title \"%1\" has no \\inmodule command; "
-                                                   "using project name by default: %2")
-                                                .arg(n->title()).arg(Generator::defaultModuleName()));
-#endif
-                }
-                else if (n->docSubtype() == Node::Page) {
-#if 0
-                    n->doc().location().warning(tr("Page with title \"%1\" has no \\inmodule command; "
-                                                   "using project name by default: %2")
-                                                .arg(n->title()).arg(Generator::defaultModuleName()));
-#endif
-                }
-                else if (n->docSubtype() == Node::Example) {
-#if 0
-                    n->doc().location().warning(tr("Example with title \"%1\" has no \\inmodule command; "
-                                                   "using project name by default: %2")
-                                                .arg(n->title()).arg(Generator::defaultModuleName()));
-#endif
-                }
-            }
-            break;
-#endif
         default:
             break;
         }
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index 552fb6a4ba27f5c4cb3d0728c4ac136ac96c93e2..0468f3691edee5ef02ad00d3a9a8867fa7310325 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -520,16 +520,6 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
             else if (t == "ditamap")
                 ptype = Node::DitaMapPage;
         }
-
-#if 0
-        const Node* n = qdb_->checkForCollision(args[0]);
-        if (n) {
-            QString other = n->doc().location().fileName();
-            doc.location().warning(tr("Name/title collision detected: '%1' in '\\%2'")
-                                   .arg(args[0]).arg(command),
-                                   tr("Also used here: %1").arg(other));
-        }
-#endif
         DocumentNode* dn = 0;
         if (ptype == Node::DitaMapPage)
             dn = new DitaMapNode(qdb_->primaryTreeRoot(), args[0]);
@@ -870,7 +860,8 @@ const QSet<QString>& CppCodeParser::otherMetaCommands()
                            << COMMAND_QMLINSTANTIATES
                            << COMMAND_QMLDEFAULT
                            << COMMAND_QMLREADONLY
-                           << COMMAND_QMLABSTRACT;
+                           << COMMAND_QMLABSTRACT
+                           << COMMAND_ABSTRACT;
     }
     return otherMetaCommands_;
 }
@@ -891,8 +882,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
             ((Aggregate *) node)->addInclude(arg);
         }
         else {
-            doc.location().warning(tr("Ignored '\\%1'")
-                                   .arg(COMMAND_INHEADERFILE));
+            doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_INHEADERFILE));
         }
     }
     else if (command == COMMAND_OVERLOAD) {
@@ -931,9 +921,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
                 func->setReimplemented(true);
             }
             else {
-                doc.location().warning(tr("Ignored '\\%1' in %2")
-                                       .arg(COMMAND_REIMP)
-                                       .arg(node->name()));
+                doc.location().warning(tr("Ignored '\\%1' in %2").arg(COMMAND_REIMP).arg(node->name()));
             }
         }
     }
@@ -1014,7 +1002,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
             }
         }
     }
-    else if (command == COMMAND_QMLABSTRACT) {
+    else if ((command == COMMAND_QMLABSTRACT) || (command == COMMAND_ABSTRACT)) {
         if (node->isQmlType() || node->isJsType())
             node->setAbstract(true);
     }
@@ -2077,29 +2065,25 @@ bool CppCodeParser::matchDeclList(Aggregate *parent)
         case Tok_Q_DECLARE_SEQUENTIAL_ITERATOR:
             readToken();
             if (match(Tok_LeftParen) && match(Tok_Ident))
-                sequentialIteratorClasses.insert(previousLexeme(),
-                                                 location().fileName());
+                sequentialIteratorClasses.insert(previousLexeme(), location().fileName());
             match(Tok_RightParen);
             break;
         case Tok_Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR:
             readToken();
             if (match(Tok_LeftParen) && match(Tok_Ident))
-                mutableSequentialIteratorClasses.insert(previousLexeme(),
-                                                        location().fileName());
+                mutableSequentialIteratorClasses.insert(previousLexeme(), location().fileName());
             match(Tok_RightParen);
             break;
         case Tok_Q_DECLARE_ASSOCIATIVE_ITERATOR:
             readToken();
             if (match(Tok_LeftParen) && match(Tok_Ident))
-                associativeIteratorClasses.insert(previousLexeme(),
-                                                  location().fileName());
+                associativeIteratorClasses.insert(previousLexeme(), location().fileName());
             match(Tok_RightParen);
             break;
         case Tok_Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR:
             readToken();
             if (match(Tok_LeftParen) && match(Tok_Ident))
-                mutableAssociativeIteratorClasses.insert(previousLexeme(),
-                                                         location().fileName());
+                mutableAssociativeIteratorClasses.insert(previousLexeme(), location().fileName());
             match(Tok_RightParen);
             break;
         case Tok_Q_DECLARE_FLAGS:
diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h
index 4acd370541d5c90516afb05fe838c2601bc824c3..31964699a2075533fbb4492d7e3556c9a88bd505 100644
--- a/src/tools/qdoc/cppcodeparser.h
+++ b/src/tools/qdoc/cppcodeparser.h
@@ -177,6 +177,7 @@ protected:
     QString exampleImageFilter;
 };
 
+#define COMMAND_ABSTRACT                Doc::alias("abstract")
 #define COMMAND_CLASS                   Doc::alias("class")
 #define COMMAND_CONTENTSPAGE            Doc::alias("contentspage")
 #define COMMAND_DITAMAP                 Doc::alias("ditamap")
diff --git a/src/tools/qdoc/doc.cpp b/src/tools/qdoc/doc.cpp
index bfe9cbe935776f035162f68c891ecad1e1534eca..f322bd936009b7a1bd387632d83639f552242d27 100644
--- a/src/tools/qdoc/doc.cpp
+++ b/src/tools/qdoc/doc.cpp
@@ -69,7 +69,6 @@ struct Macro
 
 enum {
     CMD_A,
-    CMD_ABSTRACT,
     CMD_ANNOTATEDLIST,
     CMD_B,
     CMD_BADCODE,
@@ -85,7 +84,6 @@ enum {
     CMD_DOTS,
     CMD_E,
     CMD_ELSE,
-    CMD_ENDABSTRACT,
     CMD_ENDCHAPTER,
     CMD_ENDCODE,
     CMD_ENDDIV,
@@ -187,7 +185,6 @@ static struct {
     QString *alias;
 } cmds[] = {
     { "a", CMD_A, 0 },
-    { "abstract", CMD_ABSTRACT, 0 },
     { "annotatedlist", CMD_ANNOTATEDLIST, 0 },
     { "b", CMD_B, 0 },
     { "badcode", CMD_BADCODE, 0 },
@@ -203,7 +200,6 @@ static struct {
     { "dots", CMD_DOTS, 0 },
     { "e", CMD_E, 0 },
     { "else", CMD_ELSE, 0 },
-    { "endabstract", CMD_ENDABSTRACT, 0 },
     { "endchapter", CMD_ENDCHAPTER, 0 },
     { "endcode", CMD_ENDCODE, 0 },
     { "enddiv", CMD_ENDDIV, 0 },
@@ -631,12 +627,6 @@ void DocParser::parse(const QString& source,
                     append(Atom::FormattingRight,ATOM_FORMATTING_PARAMETER);
                     priv->params.insert(p1);
                     break;
-                case CMD_ABSTRACT:
-                    if (openCommand(cmd)) {
-                        leavePara();
-                        append(Atom::AbstractLeft);
-                    }
-                    break;
                 case CMD_BADCODE:
                     leavePara();
                     append(Atom::CodeBad,getCode(CMD_BADCODE, marker));
@@ -748,12 +738,6 @@ void DocParser::parse(const QString& source,
                         location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ELSE)));
                     }
                     break;
-                case CMD_ENDABSTRACT:
-                    if (closeCommand(cmd)) {
-                        leavePara();
-                        append(Atom::AbstractRight);
-                    }
-                    break;
                 case CMD_ENDCHAPTER:
                     endSection(Doc::Chapter, cmd);
                     break;
@@ -1830,11 +1814,6 @@ bool DocParser::openCommand(int cmd)
         if (outer == CMD_LIST) {
             ok = (cmd == CMD_FOOTNOTE || cmd == CMD_LIST);
         }
-        else if (outer == CMD_ABSTRACT) {
-            ok = (cmd == CMD_LIST ||
-                  cmd == CMD_QUOTATION ||
-                  cmd == CMD_TABLE);
-        }
         else if (outer == CMD_SIDEBAR) {
             ok = (cmd == CMD_LIST ||
                   cmd == CMD_QUOTATION ||
@@ -2674,8 +2653,6 @@ void DocParser::skipToNextPreprocessorCommand()
 int DocParser::endCmdFor(int cmd)
 {
     switch (cmd) {
-    case CMD_ABSTRACT:
-        return CMD_ENDABSTRACT;
     case CMD_BADCODE:
         return CMD_ENDCODE;
     case CMD_CHAPTER:
diff --git a/src/tools/qdoc/doc/qdoc-manual-cmdindex.qdoc b/src/tools/qdoc/doc/qdoc-manual-cmdindex.qdoc
index 87416fcd14fb95ee998aa2fa3ba6a2867ad1b79c..63fcee6469a2e4b0af733663d24dee0d11a6b7e8 100644
--- a/src/tools/qdoc/doc/qdoc-manual-cmdindex.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-cmdindex.qdoc
@@ -106,6 +106,7 @@
     \li \l {printto-command} {\\printto}
     \li \l {printuntil-command} {\\printuntil}
     \li \l {property-command} {\\property}
+    \li \l {qmlabstract-command} {\\qmlabstract}
     \li \l {qmlattachedproperty-command} {\\qmlattachedproperty}
     \li \l {qmlattachedsignal-command} {\\qmlattachedsignal}
     \li \l {qmlbasictype-command} {\\qmlbasictype}
diff --git a/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc
index 700b1a09c7e0a703101eaf8991d02f5385e7f827..3bf63214ad404a32dccedf30fe15d66e95ee4b29 100644
--- a/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-contextcmds.qdoc
@@ -46,6 +46,7 @@
     below the \l {Topic Commands} {topic} command.
 
     \list
+      \li \l {abstract-command} {\\abstract}
       \li \l {compat-command}{\\compat},
       \li \l {contentspage-command}{\\contentspage},
       \li \l {indexpage-command}{\\indexpage},
@@ -59,6 +60,7 @@
       \li \l {overload-command}{\\overload},
       \li \l {preliminary-command}{\\preliminary},
       \li \l {previouspage-command}{\\previouspage},
+      \li \l {qmlabstract-command} {\\qmlabstract}
       \li \l {reentrant-command}{\\reentrant},
       \li \l {reimp-command}{\\reimp},
       \li \l {relates-command}{\\relates},
@@ -199,21 +201,41 @@
     index page of the collection.
 */
 
-
 /*!
     \page 16-qdoc-commands-status.html
     \previouspage Document Navigation
     \contentspage QDoc Manual
     \nextpage Thread Support
 
-    \title Reporting Status
-
-    These commands are for indicating that a documented element is
-    still under development, is becoming obsolete, is provided for
-    compatibility reasons, or is simply not to be included in the
-    public interface. The \l {since-command}{\\since} command is for
-    including information about the version when a function or class
-    first appeared.
+    \title Status
+
+    These commands are for indicating that a documented element has
+    some special status. The element could be marked as about to be
+    made obsolete, or that it is provided for compatibility with an
+    earlier version, or is simply not to be included in the public
+    interface. The \l {since-command}{\\since} command is for
+    specifying the version number in which a function or class first
+    appeared. The \l {qmlabstract-command} {\\qmlabstract} command is
+    for marking a QML type as an abstract base class.
+
+    \target abstract-command
+    \target qmlabstract-command
+    \section1 \\abstract and \\qmlabstract
+
+    \\abstract is a synonym for the \\qmlabstract command. Add this
+    command to the \l {qmltype-command} {\\qmltype} comment for a QML
+    type when that type is meant to be used \e {only} as an abstract
+    base type. When a QML type is abstract, it means that the QML type
+    that can't be instantiated. Instead, the properties in its public
+    API are included in the public properties list on the reference
+    page for each QML type that inherits the abstract QML type. The
+    properties are documented as if they are properties of the
+    inheriting QML type.
+
+    Normally, when a QML type is marked with \e{\\qmlabstract}, it is
+    also marked with \e{\\internal} so that its reference page is not
+    generated. It the abstract QML type is not marked internal, it
+    will have a reference page in the documentation.
 
     \target compat-command
     \section1 \\compat
diff --git a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
index d9b5a6f659bf2647be18518c459e86e1b303944c..9458d96045bce78d526d8c8fabba0d126e9e6c47 100644
--- a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc
@@ -38,7 +38,6 @@
 
     \list
     \li \l {a-command} {\\a}
-    \li \l {abstract-command} {\\abstract}
     \li \l {annotatedlist-command} {\\annotatedlist}
     \li \l {b-command} {\\b} \span {class="newStuff"}
     \li \l {b-command} {\\bold} {(deprecated, use \\b)}
@@ -2886,19 +2885,6 @@
     parts with a special rendering, conceptual meaning or
     function.
 
-    \target abstract-command
-    \section1 \\abstract
-
-    The \\abstract and \\endabstract commands delimit a
-    document's abstract section.
-
-    The abstract section is rendered as an indented italicized
-    paragraph.
-
-    \warning The \b{\\abstract} and \b{\\endabstract} commands
-    have not been implemented. The abstract section is rendered as a
-    regular HTML paragraph.
-
     \target quotation-command
     \section1 \\quotation
 
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 3fb6acf72bc4de6d7d089fb9c9230e3daf5f3599..d7a17fce26557f564a723584b77978a48607b31d 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -474,14 +474,6 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
     static bool in_para = false;
 
     switch (atom->type()) {
-    case Atom::AbstractLeft:
-        if (relative)
-            relative->doc().location().warning(tr("\abstract is not implemented."));
-        else
-            Location::information(tr("\abstract is not implemented."));
-        break;
-    case Atom::AbstractRight:
-        break;
     case Atom::AutoLink:
     case Atom::NavAutoLink:
         if (!inLink_ && !inContents_ && !inSectionHeading_) {
@@ -2199,7 +2191,7 @@ void HtmlGenerator::generateRequisites(Aggregate *inner, CodeMarker *marker)
         out() << "<div class=\"table\"><table class=\"alignedsummary\">\n";
 
         QStringList::ConstIterator i;
-        for (i = requisiteorder.begin(); i != requisiteorder.constEnd(); ++i) {
+        for (i = requisiteorder.constBegin(); i != requisiteorder.constEnd(); ++i) {
 
             if (requisites.contains(*i)) {
                 out() << "<tr>"
@@ -2319,7 +2311,7 @@ void HtmlGenerator::generateQmlRequisites(QmlTypeNode *qcn, CodeMarker *marker)
         out() << "<div class=\"table\"><table class=\"alignedsummary\">\n";
 
         QStringList::ConstIterator i;
-        for (i = requisiteorder.begin(); i != requisiteorder.constEnd(); ++i) {
+        for (i = requisiteorder.constBegin(); i != requisiteorder.constEnd(); ++i) {
 
             if (requisites.contains(*i)) {
                 out() << "<tr>"
@@ -3559,7 +3551,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
             bool handled = false;
             for (int k = 0; k != 18; ++k) {
                 const QString & tag = spanTags[2 * k];
-                if (tag == QStringRef(&src, i, tag.length())) {
+                if (i + tag.length() <= src.length() &&
+                    tag == QStringRef(&src, i, tag.length())) {
                     html += spanTags[2 * k + 1];
                     i += tag.length();
                     handled = true;
@@ -4544,33 +4537,49 @@ void HtmlGenerator::generateManifestFile(const QString &manifest, const QString
             writer.writeCDATA(QString("No description available"));
         writer.writeEndElement(); // description
 
-        // Add words from module name as tags (QtQuickControls -> qt,quick,controls)
-        QRegExp re("([A-Z]+[a-z0-9]*)");
+        // Add words from module name as tags
+        // QtQuickControls -> qt,quick,controls
+        // QtOpenGL -> qt,opengl
+        QRegExp re("([A-Z]+[a-z0-9]*(3D|GL)?)");
         int pos = 0;
         while ((pos = re.indexIn(project, pos)) != -1) {
             tags << re.cap(1).toLower();
             pos += re.matchedLength();
         }
         tags += QSet<QString>::fromList(en->title().toLower().split(QLatin1Char(' ')));
+
+        // Clean up tags, exclude invalid and common words
+        QSet<QString>::iterator tag_it = tags.begin();
+        QSet<QString> modified;
+        while (tag_it != tags.end()) {
+            QString s = *tag_it;
+            if (s.at(0) == '(')
+                s.remove(0, 1).chop(1);
+            if (s.endsWith(QLatin1Char(':')))
+                s.chop(1);
+
+            if (s.length() < 2
+                || s.at(0).isDigit()
+                || s.at(0) == '-'
+                || s == QStringLiteral("qt")
+                || s == QStringLiteral("the")
+                || s == QStringLiteral("and")
+                || s.startsWith(QStringLiteral("example"))
+                || s.startsWith(QStringLiteral("chapter")))
+                tag_it = tags.erase(tag_it);
+            else if (s != *tag_it) {
+                modified << s;
+                tag_it = tags.erase(tag_it);
+            }
+            else
+                ++tag_it;
+        }
+        tags += modified;
+
         if (!tags.isEmpty()) {
             writer.writeStartElement("tags");
             bool wrote_one = false;
-            // Exclude invalid and common words
             foreach (QString tag, tags) {
-                if (tag.length() < 2)
-                    continue;
-                if (tag.at(0).isDigit())
-                    continue;
-                if (tag.at(0) == '-')
-                    continue;
-                if (tag == QLatin1String("qt"))
-                    continue;
-                if (tag.startsWith("example"))
-                    continue;
-                if (tag.startsWith("chapter"))
-                    continue;
-                if (tag.endsWith(QLatin1Char(':')))
-                    tag.chop(1);
                 if (wrote_one)
                     writer.writeCharacters(",");
                 writer.writeCharacters(tag);
diff --git a/src/tools/qdoc/location.cpp b/src/tools/qdoc/location.cpp
index 12dc9e1b4ca499234ee053866a388aad08a54dd7..5eba2a69ef737cb2676ab044475dcf910d677ba0 100644
--- a/src/tools/qdoc/location.cpp
+++ b/src/tools/qdoc/location.cpp
@@ -256,7 +256,7 @@ QString Location::canonicalRelativePath(const QString &path)
  */
 void Location::warning(const QString& message, const QString& details) const
 {
-    if (!Generator::preparing())
+    if (!Generator::preparing() || Generator::singleExec())
         emitMessage(Warning, message, details);
 }
 
@@ -267,7 +267,7 @@ void Location::warning(const QString& message, const QString& details) const
  */
 void Location::error(const QString& message, const QString& details) const
 {
-    if (!Generator::preparing())
+    if (!Generator::preparing() || Generator::singleExec())
         emitMessage(Error, message, details);
 }
 
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index ec721aee644b1f488bc1f63e74195775876c4583..dbe397357ced39e1933a3fe5d8e4b8802164c763 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -2760,8 +2760,8 @@ bool CollectionNode::hasNamespaces() const
 bool CollectionNode::hasClasses() const
 {
     if (!members_.isEmpty()) {
-        NodeList::const_iterator i = members_.begin();
-        while (i != members_.end()) {
+        NodeList::const_iterator i = members_.cbegin();
+        while (i != members_.cend()) {
             if ((*i)->isClass())
                 return true;
             ++i;
@@ -2777,8 +2777,8 @@ bool CollectionNode::hasClasses() const
 void CollectionNode::getMemberNamespaces(NodeMap& out)
 {
     out.clear();
-    NodeList::const_iterator i = members_.begin();
-    while (i != members_.end()) {
+    NodeList::const_iterator i = members_.cbegin();
+    while (i != members_.cend()) {
         if ((*i)->isNamespace())
             out.insert((*i)->name(),(*i));
         ++i;
@@ -2792,8 +2792,8 @@ void CollectionNode::getMemberNamespaces(NodeMap& out)
 void CollectionNode::getMemberClasses(NodeMap& out)
 {
     out.clear();
-    NodeList::const_iterator i = members_.begin();
-    while (i != members_.end()) {
+    NodeList::const_iterator i = members_.cbegin();
+    while (i != members_.cend()) {
         if ((*i)->isClass())
             out.insert((*i)->name(),(*i));
         ++i;
diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp
index 6b644cac317e79ae1ba7d88b461220e40bd006a7..bfd39253534af1e6db1fd9351fba80e25edeb78a 100644
--- a/src/tools/qdoc/puredocparser.cpp
+++ b/src/tools/qdoc/puredocparser.cpp
@@ -188,8 +188,8 @@ bool PureDocParser::processQdocComments()
                     topics.insert(i+1,"and");
                     doc.location().warning(tr("Multiple topic commands found in comment: %1").arg(topics));
                 }
-                ArgList::ConstIterator a = args.begin();
-                while (a != args.end()) {
+                ArgList::ConstIterator a = args.cbegin();
+                while (a != args.cend()) {
                     Doc nodeDoc = doc;
                     Node* node = processTopicCommand(nodeDoc,topic,*a);
                     if (node != 0) {
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index fca34b0a6a4c2ba3d83c10508056ba809307f7e5..f10072a94307a9a83f7b984daae175ea3590b1cd 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -1549,8 +1549,8 @@ void QDocDatabase::mergeCollections(Node::Genus genus, CNMap& cnm, const Node* r
     foreach (Tree* t, searchOrder()) {
         CNMap* m = t->getCollectionMap(genus);
         if (m && !m->isEmpty()) {
-            CNMap::const_iterator i = m->begin();
-            while (i != m->end()) {
+            CNMap::const_iterator i = m->cbegin();
+            while (i != m->cend()) {
                 if (!i.value()->isInternal())
                     cnmm.insert(i.key(), i.value());
                 ++i;
diff --git a/src/tools/qdoc/qmlcodeparser.cpp b/src/tools/qdoc/qmlcodeparser.cpp
index 4f5720a94d2567bf640c8be3197dae780e03684e..f485255b8eae8c747a14f6e4842c94239e8c9129 100644
--- a/src/tools/qdoc/qmlcodeparser.cpp
+++ b/src/tools/qdoc/qmlcodeparser.cpp
@@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE
 #define COMMAND_SINCE                   Doc::alias("since")
 #define COMMAND_WRAPPER                 Doc::alias("wrapper")
 
+#define COMMAND_ABSTRACT                Doc::alias("abstract")
 #define COMMAND_QMLABSTRACT             Doc::alias("qmlabstract")
 #define COMMAND_QMLCLASS                Doc::alias("qmlclass")
 #define COMMAND_QMLTYPE                 Doc::alias("qmltype")
@@ -251,6 +252,7 @@ const QSet<QString>& QmlCodeParser::otherMetaCommands()
                            << COMMAND_OBSOLETE
                            << COMMAND_PRELIMINARY
                            << COMMAND_SINCE
+                           << COMMAND_ABSTRACT
                            << COMMAND_QMLABSTRACT
                            << COMMAND_INQMLMODULE
                            << COMMAND_INJSMODULE
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index 4803a1d63a95e889edbf168eec19daf7232dd9fc..360af5adf6b5928169e960eda68b4f7d59db28e4 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE
 #define COMMAND_SINCE                   Doc::alias(QLatin1String("since"))
 #define COMMAND_WRAPPER                 Doc::alias(QLatin1String("wrapper"))
 
+#define COMMAND_ABSTRACT                Doc::alias(QLatin1String("abstract"))
 #define COMMAND_QMLABSTRACT             Doc::alias(QLatin1String("qmlabstract"))
 #define COMMAND_QMLCLASS                Doc::alias(QLatin1String("qmlclass"))
 #define COMMAND_QMLTYPE                 Doc::alias(QLatin1String("qmltype"))
@@ -497,7 +498,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
         while (i != metacommands.end()) {
             QString command = *i;
             ArgList args = doc.metaCommandArgs(command);
-            if (command == COMMAND_QMLABSTRACT) {
+            if ((command == COMMAND_QMLABSTRACT) || (command == COMMAND_ABSTRACT)) {
                 if (node->isQmlType() || node->isJsType()) {
                     node->setAbstract(true);
                 }
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 0da963fe0b4cd0e8e49cac5dc0bdf0688bae60bd..629514e7d1e3dae511a38121780a7fc7afcee52f 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -1222,8 +1222,8 @@ CollectionNode* Tree::getCollection(const QString& name, Node::Genus genus)
 {
     CNMap* m = getCollectionMap(genus);
     if (m) {
-        CNMap::const_iterator i = m->find(name);
-        if (i != m->end())
+        CNMap::const_iterator i = m->constFind(name);
+        if (i != m->cend())
             return i.value();
     }
     return 0;
@@ -1249,8 +1249,8 @@ CollectionNode* Tree::findCollection(const QString& name, Node::Genus genus)
     CNMap* m = getCollectionMap(genus);
     if (!m) // error
         return 0;
-    CNMap::const_iterator i = m->find(name);
-    if (i != m->end())
+    CNMap::const_iterator i = m->constFind(name);
+    if (i != m->cend())
         return i.value();
     Node::NodeType t = Node::NoType;
     switch (genus) {
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index 4f6cb56060a19f2261203e47c482a11a79b2968f..c7625c282765da3ac3c306cd79c32a492ccd7002 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -1010,6 +1010,9 @@ QAccessible::Role QAccessibleTableCell::role() const
 QAccessible::State QAccessibleTableCell::state() const
 {
     QAccessible::State st;
+    if (!view)
+        return st;
+
     QRect globalRect = view->rect();
     globalRect.translate(view->mapToGlobal(QPoint(0,0)));
     if (!globalRect.intersects(rect()))
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 65def6d4b83657532219d3d4360759904d5b9782..6676a3ccba683a65524ca437400b8f5e3ab4ea3d 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -534,7 +534,10 @@ int QDialog::exec()
 
     QPointer<QDialog> guard = this;
     if (d->nativeDialogInUse) {
-        d->platformHelper()->exec();
+        if (windowModality() == Qt::WindowModal)
+            d->platformHelper()->execModalForWindow(d->parentWindow());
+        else
+            d->platformHelper()->exec();
     } else {
         QEventLoop eventLoop;
         d->eventLoop = &eventLoop;
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 1be2f93478a3637b386a1bc2232fae62163dec4b..41522bfa19057f55f1bfe973471a310d20f7ab04 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -893,6 +893,12 @@ void QFileDialogPrivate::_q_goToUrl(const QUrl &url)
 
 /*!
     Sets the file dialog's current \a directory.
+
+    \note On iOS, if you set \a directory to \l{QStandardPaths::standardLocations()}
+        {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()},
+        a native image picker dialog will be used for accessing the user's photo album.
+        The filename returned can be loaded using QFile and related APIs.
+        This feature was added in Qt 5.5.
 */
 void QFileDialog::setDirectory(const QString &directory)
 {
diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
index df07de79754b8acc3f4fa94e18a88c395268fc56..7329019a87d8f23420a7a6d5cf832312edf1c488 100644
--- a/src/widgets/dialogs/qfileinfogatherer.cpp
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -185,6 +185,8 @@ void QFileInfoGatherer::removePath(const QString &path)
 #ifndef QT_NO_FILESYSTEMWATCHER
     QMutexLocker locker(&mutex);
     watcher->removePath(path);
+#else
+    Q_UNUSED(path);
 #endif
 }
 
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index 04238f242a8f161bb297dc592a8006d1d9126094..4859231d956fd802016cdf8ab4de796b6e976a0f 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -544,7 +544,7 @@ QModelIndex QFileSystemModel::parent(const QModelIndex &index) const
 
     QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index);
     Q_ASSERT(indexNode != 0);
-    QFileSystemModelPrivate::QFileSystemNode *parentNode = (indexNode ? indexNode->parent : 0);
+    QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;
     if (parentNode == 0 || parentNode == &d->root)
         return QModelIndex();
 
@@ -653,10 +653,12 @@ int QFileSystemModel::columnCount(const QModelIndex &parent) const
  */
 QVariant QFileSystemModel::myComputer(int role) const
 {
+#ifndef QT_NO_FILESYSTEMWATCHER
     Q_D(const QFileSystemModel);
+#endif
     switch (role) {
     case Qt::DisplayRole:
-        return d->myComputer();
+        return QFileSystemModelPrivate::myComputer();
 #ifndef QT_NO_FILESYSTEMWATCHER
     case Qt::DecorationRole:
         return d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Computer);
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index 701fea1c03b2c8fc90afe31f133b726741aec440..a4b37f360b9ac12d613db6ed9bc8fbf8f95d4074 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -361,6 +361,36 @@ bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type)
 
 Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
 
+static LOGFONT getCaptionLogFont(HANDLE hTheme)
+{
+    LOGFONT result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
+
+    if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &result))) {
+        NONCLIENTMETRICS ncm;
+        ncm.cbSize = sizeof(NONCLIENTMETRICS);
+        SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
+        result = ncm.lfMessageFont;
+    }
+    return result;
+}
+
+static bool getCaptionQFont(int dpi, QFont *result)
+{
+    if (!pOpenThemeData)
+        return false;
+    const HANDLE hTheme =
+        pOpenThemeData(QApplicationPrivate::getHWNDForWidget(QApplication::desktop()), L"WINDOW");
+    if (!hTheme)
+        return false;
+    // Call into QWindowsNativeInterface to convert the LOGFONT into a QFont.
+    const LOGFONT logFont = getCaptionLogFont(hTheme);
+    QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
+    return ni && QMetaObject::invokeMethod(ni, "logFontToQFont", Qt::DirectConnection,
+                                           Q_RETURN_ARG(QFont, *result),
+                                           Q_ARG(const void *, &logFont),
+                                           Q_ARG(int, dpi));
+}
+
 void QVistaHelper::drawTitleBar(QPainter *painter)
 {
     Q_ASSERT(backButton_);
@@ -378,7 +408,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter)
     const int verticalCenter = (btnTop + btnHeight / 2) - 1;
 
     const QString text = wizard->window()->windowTitle();
-    const QFont font = QApplication::font("QMdiSubWindowTitleBar");
+    QFont font;
+    if (!isWindow || !getCaptionQFont(wizard->logicalDpiY() * wizard->devicePixelRatio(), &font))
+        font = QApplication::font("QMdiSubWindowTitleBar");
     const QFontMetrics fontMetrics(font);
     const QRect brect = fontMetrics.boundingRect(text);
     int textHeight = brect.height();
@@ -649,19 +681,6 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
      return false;
 }
 
-HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
-{
-    LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
-
-    if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf))) {
-        NONCLIENTMETRICS ncm;
-        ncm.cbSize = sizeof(NONCLIENTMETRICS);
-        SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
-        lf = ncm.lfMessageFont;
-    }
-    return CreateFontIndirect(&lf);
-}
-
 // Return a HDC for the wizard along with the transformation if the
 // wizard is a child window.
 HDC QVistaHelper::backingStoreDC(const QWidget *wizard, QPoint *offset)
@@ -713,7 +732,8 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
         bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
 
         // Set up the DC
-        HFONT hCaptionFont = getCaptionFont(hTheme);
+        const LOGFONT captionLogFont = getCaptionLogFont(hTheme);
+        const HFONT hCaptionFont = CreateFontIndirect(&captionLogFont);
         HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
         HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);
 
diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h
index 8c36472bee6024391bde879791e9f7361ece1eb2..84b795d5066748ac23266a3d7a88862830e3f1d4 100644
--- a/src/widgets/dialogs/qwizard_win_p.h
+++ b/src/widgets/dialogs/qwizard_win_p.h
@@ -105,7 +105,6 @@ public:
     static HDC backingStoreDC(const QWidget *wizard, QPoint *offset);
 
 private:
-    static HFONT getCaptionFont(HANDLE hTheme);
     HWND wizardHWND() const;
     bool drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc);
     static bool drawBlackRect(const QRect &rect, HDC hdc);
diff --git a/src/widgets/doc/images/listview.png b/src/widgets/doc/images/listview.png
old mode 100755
new mode 100644
diff --git a/src/widgets/doc/images/modelview-combobox.png b/src/widgets/doc/images/modelview-combobox.png
old mode 100755
new mode 100644
diff --git a/src/widgets/doc/images/tableview.png b/src/widgets/doc/images/tableview.png
old mode 100755
new mode 100644
diff --git a/src/widgets/doc/snippets/macmainwindow.mm b/src/widgets/doc/snippets/macmainwindow.mm
old mode 100755
new mode 100644
diff --git a/src/widgets/effects/qgraphicseffect.cpp b/src/widgets/effects/qgraphicseffect.cpp
index f53804e4947a05f942f11f7f9996ae5d988ecdef..5a97be3d9645108e9d9052b53837fc7889f25b2e 100644
--- a/src/widgets/effects/qgraphicseffect.cpp
+++ b/src/widgets/effects/qgraphicseffect.cpp
@@ -111,6 +111,10 @@
 #ifndef QT_NO_GRAPHICSEFFECT
 QT_BEGIN_NAMESPACE
 
+QGraphicsEffectPrivate::~QGraphicsEffectPrivate()
+{
+}
+
 /*!
     \internal
     \class QGraphicsEffectSource
diff --git a/src/widgets/effects/qgraphicseffect_p.h b/src/widgets/effects/qgraphicseffect_p.h
index 6e990cc52e0f745b372db6abd2d25e1bcac0b212..35264c0d3051fd2deefeb61b0a241d4d025fb250 100644
--- a/src/widgets/effects/qgraphicseffect_p.h
+++ b/src/widgets/effects/qgraphicseffect_p.h
@@ -142,6 +142,7 @@ class Q_WIDGETS_EXPORT QGraphicsEffectPrivate : public QObjectPrivate
     Q_DECLARE_PUBLIC(QGraphicsEffect)
 public:
     QGraphicsEffectPrivate() : source(0), isEnabled(1) {}
+    ~QGraphicsEffectPrivate();
 
     inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
     {
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index cd304100972c8d32d2028fb454e45e412b009931..1fdbe0fc1817941625c3f7bd16deb47a6f52a14b 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -10829,9 +10829,7 @@ void QGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphic
         range.start = 0;
         range.length = layout.text().length();
         range.format.setTextOutline(d->pen);
-        QList<QTextLayout::FormatRange> formats;
-        formats.append(range);
-        layout.setAdditionalFormats(formats);
+        layout.setFormats(QVector<QTextLayout::FormatRange>(1, range));
     }
 
     setupTextLayout(&layout);
diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
index db4d18299bf1d143abeb7b9c3664a23ecb11d772..08ea1ea0e35ae9ea6816f566f968f08227c8adf6 100644
--- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
@@ -269,8 +269,7 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent
     // Send mouse event.
     QMouseEvent mouseEvent(type, pos, receiver->mapTo(receiver->topLevelWidget(), pos.toPoint()),
                            receiver->mapToGlobal(pos.toPoint()),
-                           event->button(), event->buttons(), event->modifiers());
-    QGuiApplicationPrivate::setMouseEventSource(&mouseEvent, event->source());
+                           event->button(), event->buttons(), event->modifiers(), event->source());
 
     QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
     QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget,
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index b025730bb1527c5e8b94b41bd507768e57e415b2..68382bf498394eff16f7f505decb71da60c9e772 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -282,6 +282,10 @@ protected:
                            QWidget *widget = 0);
 
 protected Q_SLOTS:
+    // ### Qt 6: make unconditional
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+    virtual
+#endif
     bool focusNextPrevChild(bool next);
 
 Q_SIGNALS:
diff --git a/src/widgets/graphicsview/qgraphicstransform.cpp b/src/widgets/graphicsview/qgraphicstransform.cpp
index 67564b5a8b784fa21d6cd7c7aef6eb96261d1161..fe963fbf3cb8361215ee08d876a66cdc7582b38c 100644
--- a/src/widgets/graphicsview/qgraphicstransform.cpp
+++ b/src/widgets/graphicsview/qgraphicstransform.cpp
@@ -89,6 +89,11 @@
 
 #ifndef QT_NO_GRAPHICSVIEW
 QT_BEGIN_NAMESPACE
+
+QGraphicsTransformPrivate::~QGraphicsTransformPrivate()
+{
+}
+
 void QGraphicsTransformPrivate::setItem(QGraphicsItem *i)
 {
     if (item == i)
diff --git a/src/widgets/graphicsview/qgraphicstransform_p.h b/src/widgets/graphicsview/qgraphicstransform_p.h
index dde085935fd585f45e0316b5f8d210838a313363..c81a95fd3d6eb00a2ad599ef46421a457cc49877 100644
--- a/src/widgets/graphicsview/qgraphicstransform_p.h
+++ b/src/widgets/graphicsview/qgraphicstransform_p.h
@@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE
 
 class QGraphicsItem;
 
-class QGraphicsTransformPrivate : public QObjectPrivate {
+// ### Qt 6: unexport again, if QtQuick1's QDeclarativeTranslatePrivate is gone by then
+class Q_WIDGETS_EXPORT QGraphicsTransformPrivate : public QObjectPrivate {
 public:
     Q_DECLARE_PUBLIC(QGraphicsTransform)
 
     QGraphicsTransformPrivate()
         : QObjectPrivate(), item(0) {}
+    ~QGraphicsTransformPrivate();
 
     QGraphicsItem *item;
 
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index c270c4be8891553b689aaf4cff19b41ac76b3d38..decb4559885ab04a64bdaf8898b858d7f22f9459 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -362,6 +362,10 @@ QGraphicsViewPrivate::QGraphicsViewPrivate()
     styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
 }
 
+QGraphicsViewPrivate::~QGraphicsViewPrivate()
+{
+}
+
 /*!
     \internal
 */
diff --git a/src/widgets/graphicsview/qgraphicsview_p.h b/src/widgets/graphicsview/qgraphicsview_p.h
index fec83366955178979d574dd9092ed3e101a98486..dcbffb1c39424a78489cbbb5c2c9c9e83ce2d850 100644
--- a/src/widgets/graphicsview/qgraphicsview_p.h
+++ b/src/widgets/graphicsview/qgraphicsview_p.h
@@ -63,6 +63,7 @@ class Q_WIDGETS_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
     Q_DECLARE_PUBLIC(QGraphicsView)
 public:
     QGraphicsViewPrivate();
+    ~QGraphicsViewPrivate();
 
     void recalculateContentSize();
     void centerView(QGraphicsView::ViewportAnchor anchor);
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp
index 402d54d2d8c8c5e05ba6385c4505465cdb96f0cd..e9ab6dffec5bb321fa98b57a4e43291846abf369 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp
@@ -64,9 +64,7 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl
     adjustWindowFlags(&wFlags);
     windowFlags = wFlags;
 
-    if (parentItem)
-        setParentItemHelper(parentItem, 0, 0);
-
+    q->setParentItem(parentItem);
     q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
     q->setGraphicsItem(q);
 
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 2caf5d1eb3f10550e643ab819c2533c7b1e2134b..5b955a6e144923fbba7683ea0d5f65f418a25974 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1882,8 +1882,7 @@ void QAbstractItemView::mouseDoubleClickEvent(QMouseEvent *event)
         || (d->pressedIndex != index)) {
         QMouseEvent me(QEvent::MouseButtonPress,
                        event->localPos(), event->windowPos(), event->screenPos(),
-                       event->button(), event->buttons(), event->modifiers());
-        QGuiApplicationPrivate::setMouseEventSource(&me, event->source());
+                       event->button(), event->buttons(), event->modifiers(), event->source());
         mousePressEvent(&me);
         return;
     }
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index b79222831287d05ed80233942b5e692991dcc85d..016c50436b3e3fbf805545018524fc05dcff3b41 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -168,8 +168,20 @@ public:
         QModelIndex index;
         int col = -1;
         int row = -1;
+        const QMimeData *mime = event->mimeData();
+
+        // Drag enter event shall always be accepted, if mime type and action match.
+        // Whether the data can actually be dropped will be checked in drag move.
+        if (event->type() == QEvent::DragEnter) {
+            const QStringList modelTypes = model->mimeTypes();
+            for (int i = 0; i < modelTypes.count(); ++i)
+                if (mime->hasFormat(modelTypes.at(i))
+                    && (event->dropAction() & model->supportedDropActions()))
+                    return true;
+        }
+
         if (dropOn(event, &row, &col, &index)) {
-            return model->canDropMimeData(event->mimeData(),
+            return model->canDropMimeData(mime,
                                           dragDropMode == QAbstractItemView::InternalMove ? Qt::MoveAction : event->dropAction(),
                                           row, col, index);
         }
diff --git a/src/widgets/itemviews/qcolumnview.cpp b/src/widgets/itemviews/qcolumnview.cpp
index 5c317bbb0c7acf2466fcd7568370b8617c9a033c..0ee03035a416df6aa028f03ea6e498f7c8c03fb4 100644
--- a/src/widgets/itemviews/qcolumnview.cpp
+++ b/src/widgets/itemviews/qcolumnview.cpp
@@ -878,7 +878,9 @@ QList<int> QColumnView::columnWidths() const
 {
     Q_D(const QColumnView);
     QList<int> list;
-    for (int i = 0; i < d->columns.count(); ++i)
+    const int columnCount = d->columns.count();
+    list.reserve(columnCount);
+    for (int i = 0; i < columnCount; ++i)
         list.append(d->columnSizes.at(i));
     return list;
 }
diff --git a/src/widgets/itemviews/qcolumnview_p.h b/src/widgets/itemviews/qcolumnview_p.h
index ed30b5f0852adcbd92906014e542225c5f43da7a..0c0bdb5d1f3e0cdcae04ebf412e2c14859cd1830 100644
--- a/src/widgets/itemviews/qcolumnview_p.h
+++ b/src/widgets/itemviews/qcolumnview_p.h
@@ -89,6 +89,16 @@ public:
         QAbstractScrollArea::resizeEvent(event);
     }
 
+    void scrollContentsBy(int dx, int dy) Q_DECL_OVERRIDE
+    {
+        if (!previewWidget)
+            return;
+        scrollDirtyRegion(dx, dy);
+        viewport()->scroll(dx, dy);
+
+        QAbstractItemView::scrollContentsBy(dx, dy);
+    }
+
     QRect visualRect(const QModelIndex &) const Q_DECL_OVERRIDE
     {
         return QRect();
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index 1cc3a2a9055009468ee8084127d2f79061d509a5..cab32619c530ae35b7fd38d140d9a884d425b237 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -117,6 +117,7 @@ public:
             if (themeSizes.isEmpty())
                 return sizes;
 
+            sizes.reserve(themeSizes.count());
             foreach (int size, themeSizes)
                 sizes << QSize(size, size);
         }
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 66ff4727248714b88c6337020e5177f4f2f2bc88..bca315f80b36be319192de807a242dfb2ff5cca0 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -1879,13 +1879,13 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent,
 
     // insert sections into hiddenSectionSize
     QHash<int, int> newHiddenSectionSize; // from logical index to section size
-    for (int i = 0; i < logicalFirst; ++i)
-        if (isSectionHidden(i))
-            newHiddenSectionSize[i] = d->hiddenSectionSize[i];
-    for (int j = logicalLast + 1; j < d->sectionCount(); ++j)
-        if (isSectionHidden(j))
-            newHiddenSectionSize[j] = d->hiddenSectionSize[j - insertCount];
-    d->hiddenSectionSize = newHiddenSectionSize;
+    for (QHash<int, int>::const_iterator it = d->hiddenSectionSize.cbegin(),
+         end = d->hiddenSectionSize.cend(); it != end; ++it) {
+        const int oldIndex = it.key();
+        const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
+        newHiddenSectionSize[newIndex] = it.value();
+    }
+    d->hiddenSectionSize.swap(newHiddenSectionSize);
 
     d->doDelayedResizeSections();
     emit sectionCountChanged(oldCount, count());
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index b7a4ec39254e17279a7814c2c6824d13d4076cb1..9b07564db9612cd663a0cef7a8da041358f01153 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -53,6 +53,8 @@
 
 QT_BEGIN_NAMESPACE
 
+extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
 /*!
     \class QListView
 
@@ -796,6 +798,35 @@ void QListView::mouseReleaseEvent(QMouseEvent *e)
     }
 }
 
+#ifndef QT_NO_WHEELEVENT
+/*!
+  \reimp
+*/
+void QListView::wheelEvent(QWheelEvent *e)
+{
+    Q_D(QListView);
+    if (e->orientation() == Qt::Vertical) {
+        if (e->angleDelta().x() == 0
+            && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap))
+            && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) {
+            QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x());
+            QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x());
+            QWheelEvent hwe(e->pos(), e->globalPos(), pixelDelta, angleDelta, e->delta(),
+                            Qt::Horizontal, e->buttons(), e->modifiers(), e->phase());
+            if (e->spontaneous())
+                qt_sendSpontaneousEvent(d->hbar, &hwe);
+            else
+                QApplication::sendEvent(d->hbar, &hwe);
+            e->setAccepted(hwe.isAccepted());
+        } else {
+            QApplication::sendEvent(d->vbar, e);
+        }
+    } else {
+        QApplication::sendEvent(d->hbar, e);
+    }
+}
+#endif // QT_NO_WHEELEVENT
+
 /*!
   \reimp
 */
@@ -1846,8 +1877,17 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
     const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
                                     qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
 
-    if (bothScrollBarsAuto && contentsSize.width() - qq->verticalScrollBar()->width() <= viewport()->width()
-                           && contentsSize.height() - qq->horizontalScrollBar()->height() <= viewport()->height()) {
+    const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0),
+                             viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0));
+
+    bool verticalWantsToShow = contentsSize.height() > viewportSize.height();
+    bool horizontalWantsToShow;
+    if (verticalWantsToShow)
+        horizontalWantsToShow = contentsSize.width() > viewportSize.width() - qq->verticalScrollBar()->width();
+    else
+        horizontalWantsToShow = contentsSize.width() > viewportSize.width();
+
+    if (bothScrollBarsAuto && !horizontalWantsToShow) {
         // break the infinite loop described above by setting the range to 0, 0.
         // QAbstractScrollArea will then hide the scroll bar for us
         horizontalScrollBar()->setRange(0, 0);
@@ -1868,8 +1908,17 @@ void QCommonListViewBase::updateVerticalScrollBar(const QSize &step)
     const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
                                     qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
 
-    if (bothScrollBarsAuto && contentsSize.width() - qq->verticalScrollBar()->width() <= viewport()->width()
-                           && contentsSize.height() - qq->horizontalScrollBar()->height() <= viewport()->height()) {
+    const QSize viewportSize(viewport()->width() + (qq->verticalScrollBar()->maximum() > 0 ? qq->verticalScrollBar()->width() : 0),
+                             viewport()->height() + (qq->horizontalScrollBar()->maximum() > 0 ? qq->horizontalScrollBar()->height() : 0));
+
+    bool horizontalWantsToShow = contentsSize.width() > viewportSize.width();
+    bool verticalWantsToShow;
+    if (horizontalWantsToShow)
+        verticalWantsToShow = contentsSize.height() > viewportSize.height() - qq->horizontalScrollBar()->height();
+    else
+        verticalWantsToShow = contentsSize.height() > viewportSize.height();
+
+    if (bothScrollBarsAuto && !verticalWantsToShow) {
         // break the infinite loop described above by setting the range to 0, 0.
         // QAbstractScrollArea will then hide the scroll bar for us
         verticalScrollBar()->setRange(0, 0);
diff --git a/src/widgets/itemviews/qlistview.h b/src/widgets/itemviews/qlistview.h
index f62c96067f71887f2d3b95d909f91edf4c7dd020..ac65a47d9f51f0976a3550244cccb705e815e105 100644
--- a/src/widgets/itemviews/qlistview.h
+++ b/src/widgets/itemviews/qlistview.h
@@ -146,6 +146,9 @@ protected:
 
     void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
     void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
+#ifndef QT_NO_WHEELEVENT
+    void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE;
+#endif
 
     void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
     void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 66f965aa54ea3f460d6d9dc78fbe7cf566ff7e75..668bfda59d6cd970298db79ccf8981de1b8c3c53 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -299,7 +299,10 @@ void QListModel::sort(int column, Qt::SortOrder order)
     std::sort(sorting.begin(), sorting.end(), compare);
     QModelIndexList fromIndexes;
     QModelIndexList toIndexes;
-    for (int r = 0; r < sorting.count(); ++r) {
+    const int sortingCount = sorting.count();
+    fromIndexes.reserve(sortingCount);
+    toIndexes.reserve(sortingCount);
+    for (int r = 0; r < sortingCount; ++r) {
         QListWidgetItem *item = sorting.at(r).first;
         toIndexes.append(createIndex(r, 0, item));
         fromIndexes.append(createIndex(sorting.at(r).second, 0, sorting.at(r).first));
@@ -423,7 +426,9 @@ QMimeData *QListModel::internalMimeData()  const
 QMimeData *QListModel::mimeData(const QModelIndexList &indexes) const
 {
     QList<QListWidgetItem*> itemlist;
-    for (int i = 0; i < indexes.count(); ++i)
+    const int indexesCount = indexes.count();
+    itemlist.reserve(indexesCount);
+    for (int i = 0; i < indexesCount; ++i)
         itemlist << at(indexes.at(i).row());
     const QListWidget *view = qobject_cast<const QListWidget*>(QObject::parent());
 
@@ -1710,7 +1715,9 @@ QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFla
     QModelIndexList indexes = d->listModel()->match(model()->index(0, 0, QModelIndex()),
                                                 Qt::DisplayRole, text, -1, flags);
     QList<QListWidgetItem*> items;
-    for (int i = 0; i < indexes.size(); ++i)
+    const int indexesSize = indexes.size();
+    items.reserve(indexesSize);
+    for (int i = 0; i < indexesSize; ++i)
         items.append(d->listModel()->at(indexes.at(i).row()));
     return items;
 }
@@ -1795,6 +1802,7 @@ QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*> items) const
 
     // if non empty, it's called from the model's own mimeData
     if (cachedIndexes.isEmpty()) {
+        cachedIndexes.reserve(items.count());
         foreach (QListWidgetItem *item, items)
             cachedIndexes << indexFromItem(item);
 
@@ -1845,7 +1853,9 @@ void QListWidget::dropEvent(QDropEvent *event) {
         if (d->dropOn(event, &row, &col, &topIndex)) {
             QList<QModelIndex> selIndexes = selectedIndexes();
             QList<QPersistentModelIndex> persIndexes;
-            for (int i = 0; i < selIndexes.count(); i++)
+            const int selIndexesCount = selIndexes.count();
+            persIndexes.reserve(selIndexesCount);
+            for (int i = 0; i < selIndexesCount; i++)
                 persIndexes.append(selIndexes.at(i));
 
             if (persIndexes.contains(topIndex))
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index 9ebcbc35a767f628988d5dc4aa59c4acea0d3b78..b2d4abe5ac6bbd0054dbbb215deecf2cd6d560bc 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -812,7 +812,9 @@ QMimeData *QTableModel::internalMimeData()  const
 QMimeData *QTableModel::mimeData(const QModelIndexList &indexes) const
 {
     QList<QTableWidgetItem*> items;
-    for (int i = 0; i < indexes.count(); ++i)
+    const int indexesCount = indexes.count();
+    items.reserve(indexesCount);
+    for (int i = 0; i < indexesCount; ++i)
         items << item(indexes.at(i));
     const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
 
@@ -2326,7 +2328,9 @@ QList<QTableWidgetSelectionRange> QTableWidget::selectedRanges() const
 {
     const QList<QItemSelectionRange> ranges = selectionModel()->selection();
     QList<QTableWidgetSelectionRange> result;
-    for (int i = 0; i < ranges.count(); ++i)
+    const int rangesCount = ranges.count();
+    result.reserve(rangesCount);
+    for (int i = 0; i < rangesCount; ++i)
         result.append(QTableWidgetSelectionRange(ranges.at(i).top(),
                                                  ranges.at(i).left(),
                                                  ranges.at(i).bottom(),
@@ -2372,7 +2376,9 @@ QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchF
         indexes += d->model->match(model()->index(0, column, QModelIndex()),
                                      Qt::DisplayRole, text, -1, flags);
     QList<QTableWidgetItem*> items;
-    for (int i = 0; i < indexes.size(); ++i)
+    const int indexCount = indexes.size();
+    items.reserve(indexCount);
+    for (int i = 0; i < indexCount; ++i)
         items.append(d->tableModel()->item(indexes.at(i)));
     return items;
 }
@@ -2565,6 +2571,7 @@ QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
 
     // if non empty, it's called from the model's own mimeData
     if (cachedIndexes.isEmpty()) {
+        cachedIndexes.reserve(items.count());
         foreach (QTableWidgetItem *item, items)
             cachedIndexes << indexFromItem(item);
 
@@ -2676,7 +2683,9 @@ void QTableWidget::dropEvent(QDropEvent *event) {
             }
 
             QList<QTableWidgetItem *> taken;
-            for (int i = 0; i < indexes.count(); ++i)
+            const int indexesCount = indexes.count();
+            taken.reserve(indexesCount);
+            for (int i = 0; i < indexesCount; ++i)
                 taken.append(takeItem(indexes.at(i).row(), indexes.at(i).column()));
 
             for (int i = 0; i < indexes.count(); ++i) {
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 43db43fcd4ee424b6fdc376ddac285fbbf60ea03..9b3e270fdde98f6a1eba8b45bc2d67733e469cd5 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3658,6 +3658,7 @@ void QTreeViewPrivate::updateScrollBars()
     if (!viewportSize.isValid())
         viewportSize = QSize(0, 0);
 
+    executePostedLayout();
     if (viewItems.isEmpty()) {
         q->doItemsLayout();
     }
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index 1366a00318415deb91d0f3d4acbb509ddb6f9fcc..5970e9429273022dcf0ed17831bcf8cc112ac1ac 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -3042,7 +3042,9 @@ QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFla
     QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
                                                 Qt::DisplayRole, text, -1, flags);
     QList<QTreeWidgetItem*> items;
-    for (int i = 0; i < indexes.size(); ++i)
+    const int indexesSize = indexes.size();
+    items.reserve(indexesSize);
+    for (int i = 0; i < indexesSize; ++i)
         items.append(d->item(indexes.at(i)));
     return items;
 }
@@ -3371,7 +3373,9 @@ void QTreeWidget::dropEvent(QDropEvent *event) {
         if (d->dropOn(event, &row, &col, &topIndex)) {
             QList<QModelIndex> idxs = selectedIndexes();
             QList<QPersistentModelIndex> indexes;
-            for (int i = 0; i < idxs.count(); i++)
+            const int indexesCount = idxs.count();
+            indexes.reserve(indexesCount);
+            for (int i = 0; i < indexesCount; i++)
                 indexes.append(idxs.at(i));
 
             if (indexes.contains(topIndex))
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 88c1e2595b295e097f54eec156d19ffea91b3153..21a982f34989bc39f94d1a40e06a8c648faee8d7 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -49,6 +49,7 @@ SOURCES += \
 	kernel/qlayoutengine.cpp \
 	kernel/qlayoutitem.cpp \
         kernel/qshortcut.cpp \
+        kernel/qsizepolicy.cpp \
         kernel/qstackedlayout.cpp \
 	kernel/qtooltip.cpp \
 	kernel/qwhatsthis.cpp \
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index dd7474b930af54f923bc013cb1ca8c423687ace2..f457993168c620986b1328b06ab335a75262b78c 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -3250,12 +3250,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
 
             QPointer<QWidget> pw = w;
             while (w) {
-                QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(), mouse->button(), mouse->buttons(),
-                               mouse->modifiers());
+                QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(),
+                               mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());
                 me.spont = mouse->spontaneous();
                 me.setTimestamp(mouse->timestamp());
                 QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags());
-                QGuiApplicationPrivate::setMouseEventSource(&me, mouse->source());
                 // throw away any mouse-tracking-only mouse events
                 if (!w->hasMouseTracking()
                     && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
@@ -4273,15 +4272,16 @@ void QApplicationPrivate::cleanupMultitouch_sys()
 {
 }
 
-QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos)
+QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint)
 {
+    const QPointF screenPos = touchPoint.screenPos();
     int closestTouchPointId = -1;
     QObject *closestTarget = 0;
     qreal closestDistance = qreal(0.);
     QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it = activeTouchPoints.constBegin(),
             ite = activeTouchPoints.constEnd();
     while (it != ite) {
-        if (it.key().device == device) {
+        if (it.key().device == device && it.key().touchPointId != touchPoint.id()) {
             const QTouchEvent::TouchPoint &touchPoint = it->touchPoint;
             qreal dx = screenPos.x() - touchPoint.screenPos().x();
             qreal dy = screenPos.y() - touchPoint.screenPos().y();
@@ -4337,7 +4337,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
             }
 
             if (device->type() == QTouchDevice::TouchScreen) {
-                QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint.screenPos());
+                QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
                 QWidget *widget = static_cast<QWidget *>(target.data());
                 if (closestWidget
                         && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
@@ -4357,8 +4357,10 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
 
 #ifdef Q_OS_OSX
         // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set.
-        // In Qt 4 this check was in OS X-only coode. That behavior is preserved here by the #ifdef.
-        if (touchPoints.count() == 1 && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents))
+        // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef.
+        if (touchPoints.count() == 1
+            && device->type() == QTouchDevice::TouchPad
+            && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents))
             continue;
 #endif
 
@@ -4374,7 +4376,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
     QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
     const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
     for (; it != end; ++it) {
-        QWidget *widget = it.key();
+        const QPointer<QWidget> widget = it.key();
         if (!QApplicationPrivate::tryModalHelper(widget, 0))
             continue;
 
@@ -4414,7 +4416,8 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
             // has been implicitly accepted and continue to send touch events
             if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted()) {
                 accepted = true;
-                widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
+                if (!widget.isNull())
+                    widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
             }
             break;
         }
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 46359d79403910f1b97935ead71c9fa39e74633e..ba8d7ff63cf1e5b734c31f1562ac2cf4f1953a61 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -280,7 +280,7 @@ public:
     void initializeMultitouch_sys();
     void cleanupMultitouch();
     void cleanupMultitouch_sys();
-    QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QPointF &screenPos);
+    QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint);
     void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
     void removeTouchPoint(int touchPointId);
     static bool translateRawTouchEvent(QWidget *widget,
diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp
index 713a019cc35974a007b25824d36b01c56213b2a7..7b7d465070b19fa9b59515facedba239795f5f2f 100644
--- a/src/widgets/kernel/qgesture.cpp
+++ b/src/widgets/kernel/qgesture.cpp
@@ -36,7 +36,7 @@
 #include "private/qstandardgestures_p.h"
 #include "qgraphicsview.h"
 
-#include <QtCore/QDebug>
+#include <private/qdebug_p.h>
 #ifndef QT_NO_GESTURES
 
 QT_BEGIN_NAMESPACE
@@ -1091,9 +1091,12 @@ QPointF QGestureEvent::mapToGraphicsScene(const QPointF &gesturePoint) const
 
 static void formatGestureHeader(QDebug d, const char *className, const QGesture *gesture)
 {
-     d << className << "(state=" << gesture->state();
-     if (gesture->hasHotSpot())
-         d << ",hotSpot=" << gesture->hotSpot();
+     d << className << "(state=";
+     QtDebugUtils::formatQEnum(d, gesture->state());
+     if (gesture->hasHotSpot()) {
+         d << ",hotSpot=";
+         QtDebugUtils::formatQPoint(d, gesture->hotSpot());
+     }
 }
 
 Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QGesture *gesture)
@@ -1103,31 +1106,42 @@ Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QGesture *gesture)
     switch (gesture->gestureType()) {
     case Qt::TapGesture:
         formatGestureHeader(d, "QTapGesture", gesture);
-        d << ",position=" << static_cast<const QTapGesture*>(gesture)->position() << ')';
+        d << ",position=";
+        QtDebugUtils::formatQPoint(d, static_cast<const QTapGesture*>(gesture)->position());
+        d << ')';
         break;
     case Qt::TapAndHoldGesture: {
         const QTapAndHoldGesture *tap = static_cast<const QTapAndHoldGesture*>(gesture);
         formatGestureHeader(d, "QTapAndHoldGesture", tap);
-        d << ",position=" << tap->position() << ",timeout=" << tap->timeout() << ')';
+        d << ",position=";
+        QtDebugUtils::formatQPoint(d, tap->position());
+        d << ",timeout=" << tap->timeout() << ')';
     }
         break;
     case Qt::PanGesture: {
         const QPanGesture *pan = static_cast<const QPanGesture*>(gesture);
         formatGestureHeader(d, "QPanGesture", pan);
-        d << ",lastOffset=" << pan->lastOffset() << ",offset=" << pan->offset()
-            << ",acceleration=" << pan->acceleration()
-            << ",delta=" << pan->delta() << ')';
+        d << ",lastOffset=";
+        QtDebugUtils::formatQPoint(d, pan->lastOffset());
+        d << pan->lastOffset();
+        d << ",offset=";
+        QtDebugUtils::formatQPoint(d, pan->offset());
+        d  << ",acceleration=" << pan->acceleration() << ",delta=";
+        QtDebugUtils::formatQPoint(d, pan->delta());
+        d << ')';
     }
         break;
     case Qt::PinchGesture: {
         const QPinchGesture *pinch = static_cast<const QPinchGesture*>(gesture);
         formatGestureHeader(d, "QPinchGesture", pinch);
         d << ",totalChangeFlags=" << pinch->totalChangeFlags()
-            << ",changeFlags=" << pinch->changeFlags()
-            << ",startCenterPoint=" << pinch->startCenterPoint()
-            << ",lastCenterPoint=" << pinch->lastCenterPoint()
-            << ",centerPoint=" << pinch->centerPoint()
-            << ",totalScaleFactor=" << pinch->totalScaleFactor()
+          << ",changeFlags=" << pinch->changeFlags() << ",startCenterPoint=";
+        QtDebugUtils::formatQPoint(d, pinch->startCenterPoint());
+        d << ",lastCenterPoint=";
+        QtDebugUtils::formatQPoint(d, pinch->lastCenterPoint());
+        d << ",centerPoint=";
+        QtDebugUtils::formatQPoint(d, pinch->centerPoint());
+        d << ",totalScaleFactor=" << pinch->totalScaleFactor()
             << ",lastScaleFactor=" << pinch->lastScaleFactor()
             << ",scaleFactor=" << pinch->scaleFactor()
             << ",totalRotationAngle=" << pinch->totalRotationAngle()
@@ -1138,9 +1152,11 @@ Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QGesture *gesture)
     case Qt::SwipeGesture: {
         const QSwipeGesture *swipe = static_cast<const QSwipeGesture*>(gesture);
         formatGestureHeader(d, "QSwipeGesture", swipe);
-        d << ",horizontalDirection=" << swipe->horizontalDirection()
-            << ",verticalDirection=" << swipe->verticalDirection()
-            << ",swipeAngle=" << swipe->swipeAngle() << ')';
+        d << ",horizontalDirection=";
+        QtDebugUtils::formatQEnum(d, swipe->horizontalDirection());
+        d << ",verticalDirection=";
+        QtDebugUtils::formatQEnum(d, swipe->verticalDirection());
+        d << ",swipeAngle=" << swipe->swipeAngle() << ')';
     }
         break;
     default:
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index dcacea47774d2365ddc680115c44e2063fce3eca..e74f17b6f7a36b575af49c7cc999618b8bd72ede 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -1470,85 +1470,4 @@ QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
     return result;
 }
 
-void QSizePolicy::setControlType(ControlType type)
-{
-    /*
-        The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
-        etc. In memory, we pack it onto the available bits (CTSize) in
-        setControlType(), and unpack it here.
-
-        Example:
-
-            0x00000001 maps to 0
-            0x00000002 maps to 1
-            0x00000004 maps to 2
-            0x00000008 maps to 3
-            etc.
-    */
-
-    int i = 0;
-    while (true) {
-        if (type & (0x1 << i)) {
-            bits.ctype = i;
-            return;
-        }
-        ++i;
-    }
-}
-
-QSizePolicy::ControlType QSizePolicy::controlType() const
-{
-    return QSizePolicy::ControlType(1 << bits.ctype);
-}
-
-#ifndef QT_NO_DATASTREAM
-
-/*!
-    \relates QSizePolicy
-    \since 4.2
-
-    Writes the size \a policy to the data stream \a stream.
-
-    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
-{
-    // The order here is for historical reasons. (compatibility with Qt4)
-    quint32 data = (policy.bits.horPolicy |         // [0, 3]
-                    policy.bits.verPolicy << 4 |    // [4, 7]
-                    policy.bits.hfw << 8 |          // [8]
-                    policy.bits.ctype << 9 |        // [9, 13]
-                    policy.bits.wfh << 14 |         // [14]
-                    policy.bits.retainSizeWhenHidden << 15 |     // [15]
-                    policy.bits.verStretch << 16 |  // [16, 23]
-                    policy.bits.horStretch << 24);  // [24, 31]
-    return stream << data;
-}
-
-#define VALUE_OF_BITS(data, bitstart, bitcount) ((data >> bitstart) & ((1 << bitcount) -1))
-
-/*!
-    \relates QSizePolicy
-    \since 4.2
-
-    Reads the size \a policy from the data stream \a stream.
-
-    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
-*/
-QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
-{
-    quint32 data;
-    stream >> data;
-    policy.bits.horPolicy =  VALUE_OF_BITS(data, 0, 4);
-    policy.bits.verPolicy =  VALUE_OF_BITS(data, 4, 4);
-    policy.bits.hfw =        VALUE_OF_BITS(data, 8, 1);
-    policy.bits.ctype =      VALUE_OF_BITS(data, 9, 5);
-    policy.bits.wfh =        VALUE_OF_BITS(data, 14, 1);
-    policy.bits.retainSizeWhenHidden =    VALUE_OF_BITS(data, 15, 1);
-    policy.bits.verStretch = VALUE_OF_BITS(data, 16, 8);
-    policy.bits.horStretch = VALUE_OF_BITS(data, 24, 8);
-    return stream;
-}
-#endif // QT_NO_DATASTREAM
-
 QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index b21925e1d45cff1a849559f6614299456f64d336..21f4c9a221f4cea1136b0b2c66f01585bc08a000 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -34,7 +34,6 @@
 #include "qlayout.h"
 
 #include "qapplication.h"
-#include "qdebug.h"
 #include "qlayoutengine_p.h"
 #include "qmenubar.h"
 #include "qtoolbar.h"
@@ -67,14 +66,6 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
     return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
 }
 
-/*!
-   Returns a QVariant storing this QSizePolicy.
-*/
-QSizePolicy::operator QVariant() const
-{
-    return QVariant(QVariant::SizePolicy, this);
-}
-
 /*!
     \class QLayoutItem
     \brief The QLayoutItem class provides an abstract item that a
@@ -847,14 +838,4 @@ int QWidgetItemV2::heightForWidth(int width) const
     return height;
 }
 
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QSizePolicy &p)
-{
-    QDebugStateSaver saver(dbg);
-    dbg.nospace() << "QSizePolicy(horizontalPolicy = " << p.horizontalPolicy()
-                  << ", verticalPolicy = " << p.verticalPolicy() << ')';
-    return dbg;
-}
-#endif
-
 QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 7e4efc0e77b3a1b8bf86d8561f030bedaeb171de..14e0abf7c726b4938388e7ea95ec72300604c3c5 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -104,6 +104,12 @@ QT_BEGIN_NAMESPACE
   non-sharable. To overcome this issue, prefer using
   QSurfaceFormat::setDefaultFormat() instead of setFormat().
 
+  \note Calling QSurfaceFormat::setDefaultFormat() before constructing
+  the QApplication instance is mandatory on some platforms (for example,
+  OS X) when an OpenGL core profile context is requested. This is to
+  ensure that resource sharing between contexts stays functional as all
+  internal contexts are created using the correct version and profile.
+
   \section1 Painting Techniques
 
   As described above, subclass QOpenGLWidget to render pure 3D content in the
@@ -739,6 +745,7 @@ void QOpenGLWidgetPrivate::initialize()
     QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
     ctx->setShareContext(shareContext);
     ctx->setFormat(requestedFormat);
+    ctx->setScreen(shareContext->screen());
     if (!ctx->create()) {
         qWarning("QOpenGLWidget: Failed to create context");
         return;
@@ -762,6 +769,7 @@ void QOpenGLWidgetPrivate::initialize()
     // in QQuickWidget, use a dedicated QOffscreenSurface.
     surface = new QOffscreenSurface;
     surface->setFormat(ctx->format());
+    surface->setScreen(ctx->screen());
     surface->create();
 
     if (!ctx->makeCurrent(surface)) {
diff --git a/src/widgets/kernel/qsizepolicy.qdoc b/src/widgets/kernel/qsizepolicy.cpp
similarity index 75%
rename from src/widgets/kernel/qsizepolicy.qdoc
rename to src/widgets/kernel/qsizepolicy.cpp
index e84412bc46f3f29eeccc7d9586e40583684f3bee..1476b4c5d78e7a6ce83a178fedb71ac5cdd3c986 100644
--- a/src/widgets/kernel/qsizepolicy.qdoc
+++ b/src/widgets/kernel/qsizepolicy.cpp
@@ -3,9 +3,9 @@
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
-** This file is part of the documentation of the Qt Toolkit.
+** This file is part of the QtWidgets module of the Qt Toolkit.
 **
-** $QT_BEGIN_LICENSE:FDL$
+** $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
@@ -14,17 +14,31 @@
 ** and conditions see http://www.qt.io/terms-conditions. For further
 ** information use the contact form at http://www.qt.io/contact-us.
 **
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** 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$
 **
 ****************************************************************************/
 
+#include "qsizepolicy.h"
+
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
 /*!
     \class QSizePolicy
     \brief The QSizePolicy class is a layout attribute describing horizontal
@@ -207,15 +221,18 @@
 */
 
 /*!
-    \fn ControlType QSizePolicy::controlType() const
     \since 4.3
 
     Returns the control type associated with the widget for which
     this size policy applies.
 */
+QSizePolicy::ControlType QSizePolicy::controlType() const
+{
+    return QSizePolicy::ControlType(1 << bits.ctype);
+}
+
 
 /*!
-    \fn void QSizePolicy::setControlType(ControlType type)
     \since 4.3
 
     Sets the control type associated with the widget for which this
@@ -230,6 +247,31 @@
 
     \sa QStyle::layoutSpacing()
 */
+void QSizePolicy::setControlType(ControlType type)
+{
+    /*
+        The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
+        etc. In memory, we pack it onto the available bits (CTSize) in
+        setControlType(), and unpack it here.
+
+        Example:
+
+            0x00000001 maps to 0
+            0x00000002 maps to 1
+            0x00000004 maps to 2
+            0x00000008 maps to 3
+            etc.
+    */
+
+    int i = 0;
+    while (true) {
+        if (type & (0x1 << i)) {
+            bits.ctype = i;
+            return;
+        }
+        ++i;
+    }
+}
 
 /*!
     \fn void QSizePolicy::setHeightForWidth(bool dependent)
@@ -344,7 +386,8 @@
     \fn void QSizePolicy::retainSizeWhenHidden() const
     \since 5.2
 
-    Returns if the layout should retain the widgets size when it is hidden. This is by default false.
+    Returns whether the layout should retain the widget's size when it is hidden.
+    This is \c false by default.
 
     \sa setRetainSizeWhenHidden()
 */
@@ -353,8 +396,8 @@
    \fn void QSizePolicy::setRetainSizeWhenHidden(bool retainSize)
    \since 5.2
 
-    Set if a layout should retain the widgets size when it is hidden.
-    If \a retainSize is true the layout will not be changed by hiding the widget.
+    Sets whether a layout should retain the widget's size when it is hidden.
+    If \a retainSize is \c true, the layout will not be changed by hiding the widget.
 
     \sa retainSizeWhenHidden()
 */
@@ -385,3 +428,72 @@
     \sa setControlType(), controlType()
 */
 
+/*!
+   Returns a QVariant storing this QSizePolicy.
+*/
+QSizePolicy::operator QVariant() const
+{
+    return QVariant(QVariant::SizePolicy, this);
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+    \relates QSizePolicy
+    \since 4.2
+
+    Writes the size \a policy to the data stream \a stream.
+
+    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
+{
+    // The order here is for historical reasons. (compatibility with Qt4)
+    quint32 data = (policy.bits.horPolicy |         // [0, 3]
+                    policy.bits.verPolicy << 4 |    // [4, 7]
+                    policy.bits.hfw << 8 |          // [8]
+                    policy.bits.ctype << 9 |        // [9, 13]
+                    policy.bits.wfh << 14 |         // [14]
+                    policy.bits.retainSizeWhenHidden << 15 |     // [15]
+                    policy.bits.verStretch << 16 |  // [16, 23]
+                    policy.bits.horStretch << 24);  // [24, 31]
+    return stream << data;
+}
+
+#define VALUE_OF_BITS(data, bitstart, bitcount) ((data >> bitstart) & ((1 << bitcount) -1))
+
+/*!
+    \relates QSizePolicy
+    \since 4.2
+
+    Reads the size \a policy from the data stream \a stream.
+
+    \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
+*/
+QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
+{
+    quint32 data;
+    stream >> data;
+    policy.bits.horPolicy =  VALUE_OF_BITS(data, 0, 4);
+    policy.bits.verPolicy =  VALUE_OF_BITS(data, 4, 4);
+    policy.bits.hfw =        VALUE_OF_BITS(data, 8, 1);
+    policy.bits.ctype =      VALUE_OF_BITS(data, 9, 5);
+    policy.bits.wfh =        VALUE_OF_BITS(data, 14, 1);
+    policy.bits.retainSizeWhenHidden =    VALUE_OF_BITS(data, 15, 1);
+    policy.bits.verStretch = VALUE_OF_BITS(data, 16, 8);
+    policy.bits.horStretch = VALUE_OF_BITS(data, 24, 8);
+    return stream;
+}
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QSizePolicy &p)
+{
+    QDebugStateSaver saver(dbg);
+    dbg.nospace() << "QSizePolicy(horizontalPolicy = " << p.horizontalPolicy()
+                  << ", verticalPolicy = " << p.verticalPolicy() << ')';
+    return dbg;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
index 2376a2c64496d1b513547f3b121fa033660140f2..6cd511f5132fc0e3c5e5a3d71adfa3814240ba12 100644
--- a/src/widgets/kernel/qsizepolicy.h
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -112,7 +112,7 @@ public:
 
     bool operator==(const QSizePolicy& s) const { return data == s.data; }
     bool operator!=(const QSizePolicy& s) const { return data != s.data; }
-    operator QVariant() const; // implemented in qlayoutitem.cpp
+    operator QVariant() const;
 
     int horizontalStretch() const { return static_cast<int>(bits.horStretch); }
     int verticalStretch() const { return static_cast<int>(bits.verStretch); }
@@ -155,7 +155,6 @@ Q_DECLARE_TYPEINFO(QSizePolicy, Q_PRIMITIVE_TYPE);
 Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
 
 #ifndef QT_NO_DATASTREAM
-// implemented in qlayout.cpp
 Q_WIDGETS_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
 Q_WIDGETS_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
 #endif
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index f05094dd01559480d1c8e533416fe6581b7384d3..6e7479d29af3c7f03d98e5c97a898f55e02dd5d6 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -4860,7 +4860,7 @@ void QWidget::unsetLayoutDirection()
     \fn QFontMetrics QWidget::fontMetrics() const
 
     Returns the font metrics for the widget's current font.
-    Equivalent to QFontMetrics(widget->font()).
+    Equivalent to \c QFontMetrics(widget->font()).
 
     \sa font(), fontInfo(), setFont()
 */
@@ -4869,7 +4869,7 @@ void QWidget::unsetLayoutDirection()
     \fn QFontInfo QWidget::fontInfo() const
 
     Returns the font info for the widget's current font.
-    Equivalent to QFontInto(widget->font()).
+    Equivalent to \c QFontInfo(widget->font()).
 
     \sa font(), fontMetrics(), setFont()
 */
@@ -7335,6 +7335,8 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
         stream >> restoredScreenWidth;
 
     const QDesktopWidget * const desktop = QApplication::desktop();
+    if (restoredScreenNumber >= desktop->numScreens())
+        restoredScreenNumber = desktop->primaryScreen();
     const qreal screenWidthF = qreal(desktop->screenGeometry(restoredScreenNumber).width());
     // Sanity check bailing out when large variations of screen sizes occur due to
     // high DPI scaling or different levels of DPI awareness.
@@ -7362,9 +7364,6 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
                                        .expandedTo(d_func()->adjustedSize()));
     }
 
-    if (restoredScreenNumber >= desktop->numScreens())
-        restoredScreenNumber = desktop->primaryScreen();
-
     const QRect availableGeometry = desktop->availableGeometry(restoredScreenNumber);
 
     // Modify the restored geometry if we are about to restore to coordinates
@@ -12092,6 +12091,7 @@ QOpenGLContext *QWidgetPrivate::shareContext() const
         QOpenGLContext *ctx = new QOpenGLContext;
         ctx->setShareContext(qt_gl_global_share_context());
         ctx->setFormat(extra->topextra->window->format());
+        ctx->setScreen(extra->topextra->window->screen());
         ctx->create();
         that->extra->topextra->shareContext = ctx;
     }
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 485cf8207875e60889de6f1cbcbfc821e2f8f8d9..d1070839fa036f02452ae349bb04fbc5ade98e12 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -962,7 +962,8 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
         QPlatformTextureList::Flags flags = 0;
         if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
             flags |= QPlatformTextureList::StacksOnTop;
-        widgetTextures->appendTexture(widget, wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()), flags);
+        const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
+        widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
     }
 
     for (int i = 0; i < wd->children.size(); ++i) {
@@ -1156,7 +1157,7 @@ void QWidgetBackingStore::doSync()
 #ifndef QT_NO_OPENGL
     if (widgetTextures && widgetTextures->count()) {
         for (int i = 0; i < widgetTextures->count(); ++i) {
-            QWidget *w = widgetTextures->widget(i);
+            QWidget *w = static_cast<QWidget *>(widgetTextures->source(i));
             if (dirtyRenderToTextureWidgets.contains(w)) {
                 const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already
                 dirty += rect;
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index d8f89d279b46ab160a7c967292f2864e6939002d..633e7108530ff690eca7a234e9f8417a711f5554 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE
 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
 
 QWidget *qt_button_down = 0; // widget got last button-down
-static QPointer<QWidget> qt_tablet_target = 0;
 
 // popup control
 QWidget *qt_popup_down = 0; // popup that contains the pressed widget
@@ -447,8 +446,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
             if (receiver != popup)
                 widgetPos = receiver->mapFromGlobal(event->globalPos());
             QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos()));
-            QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers());
-            QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event));
+            QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
+                          event->button(), event->buttons(), event->modifiers(), event->source());
             e.setTimestamp(event->timestamp());
             QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver);
             qt_last_mouse_receiver = receiver;
@@ -490,9 +489,9 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
                         if (globalGeometry.contains(event->globalPos())) {
                             // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
                             const QPoint localPos = win->mapFromGlobal(event->globalPos());
-                            QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
+                            QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(),
+                                                             event->button(), event->buttons(), event->modifiers(), event->source());
                             QCoreApplicationPrivate::setEventSpontaneous(e, true);
-                            QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event));
                             e->setTimestamp(event->timestamp());
                             QCoreApplication::postEvent(win, e);
                         }
@@ -549,8 +548,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
         // The preceding statement excludes MouseButtonPress events which caused
         // creation of a MouseButtonDblClick event. QTBUG-25831
         QMouseEvent translated(event->type(), mapped, event->windowPos(), event->screenPos(),
-                               event->button(), event->buttons(), event->modifiers());
-        QGuiApplicationPrivate::setMouseEventSource(&translated, QGuiApplicationPrivate::mouseEventSource(event));
+                               event->button(), event->buttons(), event->modifiers(), event->source());
         translated.setTimestamp(event->timestamp());
         QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
                                             &qt_button_down, qt_last_mouse_receiver);
@@ -875,6 +873,7 @@ bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, long
 #ifndef QT_NO_TABLETEVENT
 void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
 {
+    static QPointer<QWidget> qt_tablet_target = 0;
     if (event->type() == QEvent::TabletPress) {
         QWidget *widget = m_widget->childAt(event->pos());
         if (!widget)
diff --git a/src/widgets/styles/qcommonstylepixmaps_p.h b/src/widgets/styles/qcommonstylepixmaps_p.h
index 471903e927df96016266e1fc8bc7a4bfba0432be..8075256158719607977cb571b77329a32c88d27e 100644
--- a/src/widgets/styles/qcommonstylepixmaps_p.h
+++ b/src/widgets/styles/qcommonstylepixmaps_p.h
@@ -348,7 +348,7 @@ static const char * const qt_unshade_xpm[] = {
 "..........",
 ".........."};
 
-static const char * dock_widget_close_xpm[] = {
+static const char * const dock_widget_close_xpm[] = {
 "8 8 2 1",
 "# c #000000",
 ". c None",
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 95a41b483039220a851d356c40a48d8db425dbab..518f985b1341834e4d8e8e4b62a3a00e9b084ee5 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -93,18 +93,6 @@
 
 QT_USE_NAMESPACE
 
-namespace {
-class AutoReleasePool
-{
-public:
-    AutoReleasePool(): pool([[NSAutoreleasePool alloc] init]) {}
-    ~AutoReleasePool() { [pool release]; }
-
-private:
-    NSAutoreleasePool *pool;
-};
-}
-
 @interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject {
 QMacStylePrivate *mPrivate;
 }
@@ -1753,7 +1741,7 @@ QMacStylePrivate::QMacStylePrivate()
 
 QMacStylePrivate::~QMacStylePrivate()
 {
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
     Q_FOREACH (NSView *b, cocoaControls)
         [b release];
 }
@@ -2135,7 +2123,7 @@ QMacStyle::QMacStyle()
     : QCommonStyle(*new QMacStylePrivate)
 {
     Q_D(QMacStyle);
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     d->receiver = [[NotificationReceiver alloc] initWithPrivate:d];
     NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver);
@@ -2152,7 +2140,7 @@ QMacStyle::QMacStyle()
 QMacStyle::~QMacStyle()
 {
     Q_D(QMacStyle);
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     [reinterpret_cast<NSScroller*>(d->nsscroller) release];
 
@@ -2169,7 +2157,7 @@ QMacStyle::~QMacStyle()
 */
 QPixmap QMacStylePrivate::generateBackgroundPattern() const
 {
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
     QPixmap px(4, 4);
     QMacCGContext cg(&px);
     HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal);
@@ -2767,7 +2755,7 @@ QPalette QMacStyle::standardPalette() const
 int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w,
                          QStyleHintReturn *hret) const
 {
-    AutoReleasePool pool;
+    QMacAutoReleasePool pool;
 
     SInt32 ret = 0;
     switch (sh) {
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 862a4302f30ba834e8df5dc5183495859687279c..1849331b7913305f9c864357b9ab1a8190775bc5 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -2368,8 +2368,8 @@ QDebug operator<<(QDebug debug, QStyle::State state)
     return operator<< <QStyle::StateFlag>(debug, state);
 #    else
     Q_UNUSED(state);
-#    endif
     return debug;
+#    endif
 }
 #  endif // !QT_NO_DEBUG_STREAM
 #endif // QT_VERSION < QT_VERSION_CHECK(6,0,0)
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 86b5632d2e396f52f455a89b4ab93a96f0af16b8..40b8aaae9a8ac5a7c0a3049aeff2e60b5e10abd2 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -586,7 +586,7 @@ public:
 };
 
 ///////////////////////////////////////////////////////////////////////////////////////////
-static const char *knownStyleHints[] = {
+static const char *const knownStyleHints[] = {
     "activate-on-singleclick",
     "alignment",
     "arrow-keys-navigate-into-children",
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 40597a41f3985a6501bda5a644a887635db6da74..db8a649931b0e0fdab91bf3060dbdde32093160c 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -299,8 +299,8 @@ void QWindowsStyle::polish(QPalette &pal)
 
 int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget)
 {
-    switch (pm) {
 #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+    switch (pm) {
     case QStyle::PM_DockWidgetFrameWidth:
 #  ifndef Q_OS_WINCE
         return GetSystemMetrics(SM_CXFRAME);
@@ -337,13 +337,14 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const
 #  else
         return GetSystemMetrics(SM_CYDLGFRAME);
 #  endif
-#else
-    Q_UNUSED(widget)
-#endif // Q_OS_WIN
 
     default:
         break;
     }
+#else // Q_OS_WIN && !Q_OS_WINRT
+    Q_UNUSED(pm);
+    Q_UNUSED(widget);
+#endif
     return QWindowsStylePrivate::InvalidMetric;
 }
 
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index f715d9329817cb3603fa11c41b30a1014926ac04..daa8ab12a9198ff052cf95413911a97629266e97 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -250,8 +250,6 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
 
     int state = option->state;
     if (!QWindowsVistaStylePrivate::useVista()) {
-        foreach (const QObject *target, d->animationTargets())
-            d->stopAnimation(target);
         QWindowsStyle::drawPrimitive(element, option, painter, widget);
         return;
     }
@@ -810,8 +808,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
 
     if (!QWindowsVistaStylePrivate::useVista()) {
-        foreach (const QObject *target, d->animationTargets())
-            d->stopAnimation(target);
         QWindowsStyle::drawControl(element, option, painter, widget);
         return;
     }
@@ -1494,8 +1490,6 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
 {
     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
     if (!QWindowsVistaStylePrivate::useVista()) {
-        foreach (const QObject *target, d->animationTargets())
-            d->stopAnimation(target);
         QWindowsStyle::drawComplexControl(control, option, painter, widget);
         return;
     }
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index 0e598717c89688bbd87721708d7f7c824a0fa2c9..8eadc426251dd508720d97b841aa871b1ed8afb6 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -66,8 +66,8 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
     case QEvent::MouseButtonRelease:
     case QEvent::MouseMove: {
         QMouseEvent *me = static_cast<QMouseEvent *>(e);
-        QMouseEvent *cme = new QMouseEvent(me->type(), QPoint(0, 0), me->windowPos(), me->screenPos(), me->button(), me->buttons(), me->modifiers());
-        QGuiApplicationPrivate::setMouseEventSource(cme, me->source());
+        QMouseEvent *cme = new QMouseEvent(me->type(), QPoint(0, 0), me->windowPos(), me->screenPos(),
+                                           me->button(), me->buttons(), me->modifiers(), me->source());
         return cme;
     }
 #ifndef QT_NO_GRAPHICSVIEW
@@ -78,8 +78,8 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
 #if 1
         QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress :
                            (me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove);
-        QMouseEvent *cme = new QMouseEvent(met, QPoint(0, 0), QPoint(0, 0), me->screenPos(), me->button(), me->buttons(), me->modifiers());
-        QGuiApplicationPrivate::setMouseEventSource(cme, me->source());
+        QMouseEvent *cme = new QMouseEvent(met, QPoint(0, 0), QPoint(0, 0), me->screenPos(),
+                                           me->button(), me->buttons(), me->modifiers(), me->source());
         return cme;
 #else
         QGraphicsSceneMouseEvent *copy = new QGraphicsSceneMouseEvent(me->type());
@@ -240,8 +240,7 @@ public:
             qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
             QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
                            mouseButton, QApplication::mouseButtons() & ~mouseButton,
-                           QApplication::keyboardModifiers());
-            QGuiApplicationPrivate::setMouseEventSource(&re, mouseEventSource);
+                           QApplication::keyboardModifiers(), mouseEventSource);
             sendMouseEvent(&re, RegrabMouseAfterwards);
             // don't clear the mouseTarget just yet, since we need to explicitly ungrab the mouse on release!
         }
@@ -291,8 +290,7 @@ protected:
             if (me) {
                 QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()),
                                  mouseTarget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
-                                 me->button(), me->buttons(), me->modifiers());
-                QGuiApplicationPrivate::setMouseEventSource(&copy, me->source());
+                                 me->button(), me->buttons(), me->modifiers(), me->source());
                 qt_sendSpontaneousEvent(mouseTarget, &copy);
             }
 
diff --git a/src/widgets/util/qscroller_mac.mm b/src/widgets/util/qscroller_mac.mm
index 9120c43075454425e33c72f308dec9cbc266c6a2..07de07de525c5dec3dbd9fb7d5809849802bbbca 100644
--- a/src/widgets/util/qscroller_mac.mm
+++ b/src/widgets/util/qscroller_mac.mm
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
 
 QPointF QScrollerPrivate::realDpi(int screen)
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    QMacAutoReleasePool pool;
     NSArray *nsscreens = [NSScreen screens];
 
     if (screen < 0 || screen >= int([nsscreens count]))
@@ -59,7 +59,6 @@ QPointF QScrollerPrivate::realDpi(int screen)
     } else {
         return QPointF();
     }
-    [pool release];
 }
 
 QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 2e1caedde78425d01bcf12455f7ee9be50d805f9..5e45c66f3b145842272f6479fc939a6cc8a0ccd7 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -168,6 +168,10 @@ QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
 {
 }
 
+QAbstractScrollAreaPrivate::~QAbstractScrollAreaPrivate()
+{
+}
+
 QAbstractScrollAreaScrollBarContainer::QAbstractScrollAreaScrollBarContainer(Qt::Orientation orientation, QWidget *parent)
     :QWidget(parent), scrollBar(new QScrollBar(orientation, this)),
      layout(new QBoxLayout(orientation == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom)),
diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h
index f770bb69f86d51dd3b6c131a3a7f03d2449812d0..33222573f4fb80a2de67b763efe49b1768ec69a3 100644
--- a/src/widgets/widgets/qabstractscrollarea_p.h
+++ b/src/widgets/widgets/qabstractscrollarea_p.h
@@ -54,12 +54,15 @@ QT_BEGIN_NAMESPACE
 
 class QScrollBar;
 class QAbstractScrollAreaScrollBarContainer;
+
+// ### Qt 6: is the export still needed? If not, unexport QFramePrivate, too.
 class Q_WIDGETS_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
 {
     Q_DECLARE_PUBLIC(QAbstractScrollArea)
 
 public:
     QAbstractScrollAreaPrivate();
+    ~QAbstractScrollAreaPrivate();
 
     void replaceScrollBar(QScrollBar *scrollBar, Qt::Orientation orientation);
 
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 76f923904ddbffba5831787cc64da7703c4e0035..ef80e359df2780f0409b67e7287b8c8361c5c2de 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -3034,7 +3034,7 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
     QStyle::SubControl sc = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), q);
 
     if (e->button() == Qt::LeftButton
-            && sc != QStyle::SC_None
+            && !(sc == QStyle::SC_None && e->type() == QEvent::MouseButtonRelease)
             && (sc == QStyle::SC_ComboBoxArrow || !q->isEditable())
             && !viewContainer()->isVisible()) {
         if (sc == QStyle::SC_ComboBoxArrow)
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index b1749fa5d34dc72f19878ee3e102b65cf3281a9f..a8da78a025a74bb35ab55b54f46c628e2448087f 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -2316,9 +2316,9 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
 QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
 {
     if (ap == AmText) {
-        return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
+        return (cs == UpperCase ? QDateTimeParser::tr("AM") : QDateTimeParser::tr("am"));
     } else {
-        return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
+        return (cs == UpperCase ? QDateTimeParser::tr("PM") : QDateTimeParser::tr("pm"));
     }
 }
 
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index 237eb775b911dbd63fce0c095456fa6136b0b47a..3e8c08f923c170886055ef2a5972993575f4cc2a 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -852,9 +852,19 @@ void QDialogButtonBoxPrivate::_q_handleButtonClicked()
 {
     Q_Q(QDialogButtonBox);
     if (QAbstractButton *button = qobject_cast<QAbstractButton *>(q->sender())) {
+        // Can't fetch this *after* emitting clicked, as clicked may destroy the button
+        // or change its role. Now changing the role is not possible yet, but arguably
+        // both clicked and accepted/rejected/etc. should be emitted "atomically"
+        // depending on whatever role the button had at the time of the click.
+        const QDialogButtonBox::ButtonRole buttonRole = q->buttonRole(button);
+        QPointer<QDialogButtonBox> guard(q);
+
         emit q->clicked(button);
 
-        switch (q->buttonRole(button)) {
+        if (!guard)
+            return;
+
+        switch (buttonRole) {
         case QPlatformDialogHelper::AcceptRole:
         case QPlatformDialogHelper::YesRole:
             emit q->accepted();
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index af0f2515fecc24cdf1ced05e4442093e3000d047..bc2259ce909cf982bd575ea2669f68b271308763 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1854,20 +1855,6 @@ static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
     return Qt::NoDockWidgetArea;
 }
 
-static QRect constrainedRect(QRect rect, const QRect &desktop)
-{
-    if (desktop.isValid()) {
-        rect.setWidth(qMin(rect.width(), desktop.width()));
-        rect.setHeight(qMin(rect.height(), desktop.height()));
-        rect.moveLeft(qMax(rect.left(), desktop.left()));
-        rect.moveTop(qMax(rect.top(), desktop.top()));
-        rect.moveRight(qMin(rect.right(), desktop.right()));
-        rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
-    }
-
-    return rect;
-}
-
 bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, bool testing)
 {
     uchar marker;
@@ -1958,11 +1945,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
 #endif
                     if (!testing) {
                         QRect r(x, y, w, h);
-                        QDesktopWidget *desktop = QApplication::desktop();
-                        if (desktop->isVirtualDesktop())
-                            r = constrainedRect(r, desktop->screenGeometry(desktop->screenNumber(r.topLeft())));
-                        else
-                            r = constrainedRect(r, desktop->screenGeometry(widget));
+                        r = QDockAreaLayout::constrainedRect(r, widget);
                         widget->move(r.topLeft());
                         widget->resize(r.size());
                     }
@@ -2075,6 +2058,36 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
 #endif //QT_NO_TABBAR
 
 #ifndef QT_NO_TABBAR
+/*! \internal
+    reparent all the widgets contained in this layout portion to the
+    specified parent. This is used to reparent dock widgets and tabbars
+    to the floating window or the main window
+ */
+void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
+{
+    if (tabBar)
+        tabBar->setParent(parent);
+
+    for (int i = 0; i < item_list.count(); ++i) {
+        const QDockAreaLayoutItem &item = item_list.at(i);
+        if (item.flags & QDockAreaLayoutItem::GapItem)
+            continue;
+        if (item.skip())
+            continue;
+        if (item.subinfo)
+            item.subinfo->reparentWidgets(parent);
+        if (item.widgetItem) {
+            QWidget *w = item.widgetItem->widget();
+            if (w->parent() != parent) {
+                bool hidden = w->isHidden();
+                w->setParent(parent);
+                if (!hidden)
+                    w->show();
+            }
+        }
+    }
+}
+
 //returns whether the tabbar is visible or not
 bool QDockAreaLayoutInfo::updateTabBar() const
 {
@@ -2981,6 +2994,33 @@ QSize QDockAreaLayout::minimumSize() const
     return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
 }
 
+/*! \internal
+    Try to fit the given rectangle \a rect on the screen which contains
+    the window \a widget.
+    Used to compute the geometry of a dragged a dock widget that should
+    be shown with \a rect, but needs to be visible on the screen
+ */
+QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
+{
+    QRect desktop;
+    QDesktopWidget *desktopW = QApplication::desktop();
+    if (desktopW->isVirtualDesktop())
+        desktop = desktopW->screenGeometry(rect.topLeft());
+    else
+        desktop = desktopW->screenGeometry(widget);
+
+    if (desktop.isValid()) {
+        rect.setWidth(qMin(rect.width(), desktop.width()));
+        rect.setHeight(qMin(rect.height(), desktop.height()));
+        rect.moveLeft(qMax(rect.left(), desktop.left()));
+        rect.moveTop(qMax(rect.top(), desktop.top()));
+        rect.moveRight(qMin(rect.right(), desktop.right()));
+        rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
+    }
+
+    return rect;
+}
+
 bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
 {
     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
@@ -2994,9 +3034,7 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
     item.widgetItem = new QDockWidgetItem(dockWidget);
 
     if (placeHolder->window) {
-        const QRect screenGeometry =
-            QApplication::desktop()->screenGeometry(placeHolder->topLevelRect.center());
-        const QRect r = constrainedRect(placeHolder->topLevelRect, screenGeometry);
+        const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
         dockWidget->d_func()->setWindowState(true, true, r);
     }
     dockWidget->setVisible(!placeHolder->hidden);
diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h
index 64fae7ebf62efdf8af8e2b2d0e689468b5a8bf9c..93b005f64f359fcf4cb1cae97a6064bf920b94c3 100644
--- a/src/widgets/widgets/qdockarealayout_p.h
+++ b/src/widgets/widgets/qdockarealayout_p.h
@@ -202,6 +202,7 @@ public:
     QTabBar *tabBar;
     int tabBarShape;
 
+    void reparentWidgets(QWidget *p);
     bool updateTabBar() const;
     void setTabBarShape(int shape);
     QSize tabBarMinimumSize() const;
@@ -232,7 +233,8 @@ public:
 
     bool isValid() const;
 
-    enum { DockWidgetStateMarker = 0xfd };
+    enum { DockWidgetStateMarker = 0xfd, FloatingDockWidgetTabMarker = 0xf9 };
+    static QRect constrainedRect(QRect rect, QWidget *widget);
     void saveState(QDataStream &stream) const;
     bool restoreState(QDataStream &stream, const QList<QDockWidget*> &widgets, bool testing = false);
 
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 21b0904cc0e24179e5c670614084635a51684344..1b7473fbd72f0087c7544fe9752ffbc612a36206 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -65,6 +65,18 @@ extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); /
 // qmainwindow.cpp
 extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
 
+static inline QMainWindowLayout *qt_mainwindow_layout_from_dock(const QDockWidget *dock)
+{
+    const QWidget *p = dock->parentWidget();
+    while (p) {
+        const QMainWindow *window = qobject_cast<const QMainWindow*>(p);
+        if (window)
+            return qt_mainwindow_layout(window);
+        p = p->parentWidget();
+    }
+    return Q_NULLPTR;
+}
+
 static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature)
 { return (priv->features & feature) == feature; }
 
@@ -194,25 +206,40 @@ QDockWidgetLayout::~QDockWidgetLayout()
     qDeleteAll(item_list);
 }
 
+/*! \internal
+    Returns true if the dock widget managed by this layout should have a native
+    window decoration or if Qt needs to draw it.
+ */
 bool QDockWidgetLayout::nativeWindowDeco() const
 {
-    return nativeWindowDeco(parentWidget()->isWindow());
+    bool floating = parentWidget()->isWindow();
+    if (!floating && qobject_cast<QDockWidgetGroupWindow*>(parentWidget()->parentWidget()))
+        return wmSupportsNativeWindowDeco();
+    return nativeWindowDeco(floating);
 }
 
-static bool isXcb()
+/*! \internal
+    Returns true if the window manager can draw natively the windows decoration
+    of a dock widget
+ */
+bool QDockWidgetLayout::wmSupportsNativeWindowDeco()
 {
+#if defined(Q_OS_WINCE) || defined(Q_OS_ANDROID)
+    return false;
+#else
     static const bool xcb = !QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive);
-    return xcb;
+    return !xcb;
+#endif
 }
 
+/*! \internal
+   Returns true if the dock widget managed by this layout should have a native
+   window decoration or if Qt needs to draw it. The \a floating parameter
+   overrides the floating current state of the dock widget.
+ */
 bool QDockWidgetLayout::nativeWindowDeco(bool floating) const
 {
-#if defined(Q_OS_WINCE) || defined(Q_OS_ANDROID)
-    Q_UNUSED(floating)
-    return false;
-#else
-    return !isXcb() && (floating && item_list[QDockWidgetLayout::TitleBar] == 0);
-#endif
+    return wmSupportsNativeWindowDeco() && floating && item_list.at(QDockWidgetLayout::TitleBar) == 0;
 }
 
 
@@ -611,7 +638,10 @@ void QDockWidget::initStyleOption(QStyleOptionDockWidget *option) const
         return;
     QDockWidgetLayout *dwlayout = qobject_cast<QDockWidgetLayout*>(layout());
 
-    option->initFrom(this);
+    QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent());
+    // If we are in a floating tab, init from the parent because the attributes and the geometry
+    // of the title bar should be taken from the floating window.
+    option->initFrom(floatingTab && !isFloating() ? parentWidget() : this);
     option->rect = dwlayout->titleArea();
     option->title = d->fixedWindowTitle;
     option->closable = hasFeature(this, QDockWidget::DockWidgetClosable);
@@ -681,14 +711,20 @@ void QDockWidgetPrivate::_q_toggleTopLevel()
     q->setFloating(!q->isFloating());
 }
 
+/*! \internal
+    Initialize the drag state structure and remember the position of the click.
+    This is called when the mouse is pressed, but the dock is not yet dragged out.
+
+    \a nca specify that the event comes from NonClientAreaMouseButtonPress
+ */
 void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
 {
+    Q_Q(QDockWidget);
+
     if (state != 0)
         return;
 
-    QMainWindow *win = qobject_cast<QMainWindow*>(parent);
-    Q_ASSERT(win != 0);
-    QMainWindowLayout *layout = qt_mainwindow_layout(win);
+    QMainWindowLayout *layout = qt_mainwindow_layout_from_dock(q);
     Q_ASSERT(layout != 0);
     if (layout->pluggingWidget != 0) // the main window is animating a docking operation
         return;
@@ -702,17 +738,23 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
     state->ctrlDrag = false;
 }
 
-void QDockWidgetPrivate::startDrag()
+/*! \internal
+    Actually start the drag and detach the dockwidget.
+    The \a group parameter is true when we should potentially drag a group of
+    tabbed widgets, and false if the dock widget should always be dragged
+    alone.
+ */
+void QDockWidgetPrivate::startDrag(bool group)
 {
     Q_Q(QDockWidget);
 
     if (state == 0 || state->dragging)
         return;
 
-    QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
+    QMainWindowLayout *layout = qt_mainwindow_layout_from_dock(q);
     Q_ASSERT(layout != 0);
 
-    state->widgetItem = layout->unplug(q);
+    state->widgetItem = layout->unplug(q, group);
     if (state->widgetItem == 0) {
         /* I have a QMainWindow parent, but I was never inserted with
             QMainWindow::addDockWidget, so the QMainWindowLayout has no
@@ -728,6 +770,11 @@ void QDockWidgetPrivate::startDrag()
     state->dragging = true;
 }
 
+/*! \internal
+    Ends the drag end drop operation of the QDockWidget.
+    The \a abort parameter specifies that it ends because of programmatic state
+    reset rather than mouse release event.
+ */
 void QDockWidgetPrivate::endDrag(bool abort)
 {
     Q_Q(QDockWidget);
@@ -736,29 +783,31 @@ void QDockWidgetPrivate::endDrag(bool abort)
     q->releaseMouse();
 
     if (state->dragging) {
-        QMainWindowLayout *mwLayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
+        QMainWindowLayout *mwLayout = qt_mainwindow_layout_from_dock(q);
         Q_ASSERT(mwLayout != 0);
 
         if (abort || !mwLayout->plug(state->widgetItem)) {
             if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
+                // This QDockWidget will now stay in the floating state.
                 if (state->ownWidgetItem)
                     delete state->widgetItem;
                 mwLayout->restore();
-                if (isXcb()) {
+                QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
+                if (!dwLayout->nativeWindowDeco()) {
                     // get rid of the X11BypassWindowManager window flag and activate the resizer
                     Qt::WindowFlags flags = q->windowFlags();
                     flags &= ~Qt::X11BypassWindowManagerHint;
                     q->setWindowFlags(flags);
-                    setResizerActive(true);
+                    setResizerActive(q->isFloating());
                     q->show();
                 } else {
-                    QDockWidgetLayout *myLayout
-                            = qobject_cast<QDockWidgetLayout*>(layout);
-                    setResizerActive(myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
+                    setResizerActive(false);
                 }
                 undockedGeometry = q->geometry();
                 q->activateWindow();
             } else {
+                // The tab was not plugged back in the QMainWindow but the QDockWidget cannot
+                // stay floating, revert to the previous state.
                 mwLayout->revert(state->widgetItem);
             }
         }
@@ -782,11 +831,7 @@ bool QDockWidgetPrivate::isAnimating() const
 {
     Q_Q(const QDockWidget);
 
-    QMainWindow *mainWin = qobject_cast<QMainWindow*>(parent);
-    if (mainWin == 0)
-        return false;
-
-    QMainWindowLayout *mainWinLayout = qt_mainwindow_layout(mainWin);
+    QMainWindowLayout *mainWinLayout = qt_mainwindow_layout_from_dock(q);
     if (mainWinLayout == 0)
         return false;
 
@@ -804,12 +849,14 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
     if (!dwLayout->nativeWindowDeco()) {
         QRect titleArea = dwLayout->titleArea();
 
+        QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
+
         if (event->button() != Qt::LeftButton ||
             !titleArea.contains(event->pos()) ||
             // check if the tool window is movable... do nothing if it
             // is not (but allow moving if the window is floating)
             (!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
-            qobject_cast<QMainWindow*>(parent) == 0 ||
+            (qobject_cast<QMainWindow*>(parent) == 0 && !floatingTab) ||
             isAnimating() || state != 0) {
             return false;
         }
@@ -853,7 +900,7 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
 
     QDockWidgetLayout *dwlayout
         = qobject_cast<QDockWidgetLayout *>(layout);
-    QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
+    QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q);
     if (!dwlayout->nativeWindowDeco()) {
         if (!state->dragging
             && mwlayout->pluggingWidget == 0
@@ -871,7 +918,12 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
 
     if (state->dragging && !state->nca) {
         QPoint pos = event->globalPos() - state->pressPos;
-        q->move(pos);
+
+        QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
+        if (floatingTab && !q->isFloating())
+            floatingTab->move(pos);
+        else
+            q->move(pos);
 
         if (state && !state->ctrlDrag)
             mwlayout->hover(state->widgetItem, event->globalPos());
@@ -902,8 +954,9 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
 
     int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q);
 
-    QRect geo = q->geometry();
-    QRect titleRect = q->frameGeometry();
+    QWidget *tl = q->topLevelWidget();
+    QRect geo = tl->geometry();
+    QRect titleRect = tl->frameGeometry();
 #ifdef Q_DEAD_CODE_FROM_QT4_MAC
     if ((features & QDockWidget::DockWidgetVerticalTitleBar)) {
         titleRect.setTop(geo.top());
@@ -924,7 +977,7 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
                 break;
             if (state != 0)
                 break;
-            if (qobject_cast<QMainWindow*>(parent) == 0)
+            if (qobject_cast<QMainWindow*>(parent) == 0 && qobject_cast<QDockWidgetGroupWindow*>(parent) == 0)
                 break;
             if (isAnimating())
                 break;
@@ -958,11 +1011,17 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
     }
 }
 
+/*! \internal
+    Called when the QDockWidget or the QDockWidgetGroupWindow is moved
+ */
 void QDockWidgetPrivate::moveEvent(QMoveEvent *event)
 {
     Q_Q(QDockWidget);
 
-    if (state == 0 || !state->dragging || !state->nca || !q->isWindow())
+    if (state == 0 || !state->dragging || !state->nca)
+        return;
+
+    if (!q->isWindow() && qobject_cast<QDockWidgetGroupWindow*>(parent) == 0)
         return;
 
     // When the native window frame is being dragged, all we get is these mouse
@@ -971,7 +1030,7 @@ void QDockWidgetPrivate::moveEvent(QMoveEvent *event)
     if (state->ctrlDrag)
         return;
 
-    QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
+    QMainWindowLayout *layout = qt_mainwindow_layout_from_dock(q);
     Q_ASSERT(layout != 0);
 
     QPoint globalMousePos = event->pos() + state->pressPos;
@@ -999,8 +1058,9 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
     Q_Q(QDockWidget);
 
     if (!floating && parent) {
-        QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
-        if (mwlayout && mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea)
+        QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q);
+        if (mwlayout && mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea
+                && !qobject_cast<QDockWidgetGroupWindow *>(parent))
             return; // this dockwidget can't be redocked
     }
 
@@ -1048,7 +1108,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
     if (floating != wasFloating) {
         emit q->topLevelChanged(floating);
         if (!floating && parent) {
-            QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget()));
+            QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q);
             if (mwlayout)
                 emit q->dockLocationChanged(mwlayout->dockWidgetArea(q));
         }
@@ -1230,8 +1290,11 @@ void QDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features)
     emit featuresChanged(d->features);
     update();
     if (closableChanged && layout->nativeWindowDeco()) {
-        //this ensures the native decoration is drawn
-        d->setWindowState(true /*floating*/, true /*unplug*/);
+        QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow *>(parent());
+        if (floatingTab && !isFloating())
+            floatingTab->adjustFlags();
+        else
+            d->setWindowState(true /*floating*/, true /*unplug*/);  //this ensures the native decoration is drawn
     }
 }
 
@@ -1323,11 +1386,12 @@ void QDockWidget::changeEvent(QEvent *event)
 #endif
 #ifndef QT_NO_TABBAR
         {
-            QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget());
-            if (QMainWindowLayout *winLayout = qt_mainwindow_layout(win)) {
+            if (QMainWindowLayout *winLayout = qt_mainwindow_layout_from_dock(this)) {
                 if (QDockAreaLayoutInfo *info = winLayout->layoutState.dockAreaLayout.info(this))
                     info->updateTabBar();
             }
+            if (QDockWidgetGroupWindow *p = qobject_cast<QDockWidgetGroupWindow *>(parent()))
+                p->adjustFlags();
         }
 #endif // QT_NO_TABBAR
         break;
@@ -1380,7 +1444,7 @@ bool QDockWidget::event(QEvent *event)
     Q_D(QDockWidget);
 
     QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget());
-    QMainWindowLayout *layout = qt_mainwindow_layout(win);
+    QMainWindowLayout *layout = qt_mainwindow_layout_from_dock(this);
 
     switch (event->type()) {
 #ifndef QT_NO_ACTION
@@ -1417,6 +1481,9 @@ bool QDockWidget::event(QEvent *event)
         }
         if (!isFloating() && layout != 0 && onTop)
             layout->raise(this);
+        if (QDockWidgetGroupWindow *p = qobject_cast<QDockWidgetGroupWindow *>(parent()))
+            p->adjustFlags();
+
         break;
     }
     case QEvent::WindowActivate:
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index 752d6519e5fbf5bf72d1b2af7bbf540906443556..9c68bc5fb1633bb114ad1c83157d6ab4020f98fb 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -108,7 +108,7 @@ public:
     void setWindowState(bool floating, bool unplug = false, const QRect &rect = QRect());
     void nonClientAreaMouseEvent(QMouseEvent *event);
     void initDrag(const QPoint &pos, bool nca);
-    void startDrag();
+    void startDrag(bool group = true);
     void endDrag(bool abort = false);
     void moveEvent(QMoveEvent *event);
 
@@ -151,6 +151,7 @@ public:
     int minimumTitleWidth() const;
     int titleHeight() const;
     void updateMaxSize();
+    static bool wmSupportsNativeWindowDeco();
     bool nativeWindowDeco() const;
     bool nativeWindowDeco(bool floating) const;
 
diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp
index 0861ea70b5ffc35fec1ee9af1dac2ef3250a7f59..755b03a4ca84f3710643a4e4326e95ae19f1ee68 100644
--- a/src/widgets/widgets/qframe.cpp
+++ b/src/widgets/widgets/qframe.cpp
@@ -45,7 +45,7 @@
 QT_BEGIN_NAMESPACE
 
 QFramePrivate::QFramePrivate()
-    : frect(QRect(0, 0, 0, 0)),
+    : frect(0, 0, 0, 0),
       frameStyle(QFrame::NoFrame | QFrame::Plain),
       lineWidth(1),
       midLineWidth(0),
@@ -55,6 +55,10 @@ QFramePrivate::QFramePrivate()
 {
 }
 
+QFramePrivate::~QFramePrivate()
+{
+}
+
 inline void QFramePrivate::init()
 {
     setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
diff --git a/src/widgets/widgets/qframe_p.h b/src/widgets/widgets/qframe_p.h
index 2b80e9abbe13133fe8782c240298efb193726497..eb04bbed4ad255c8410a9a1c7cff8dd4dd002334 100644
--- a/src/widgets/widgets/qframe_p.h
+++ b/src/widgets/widgets/qframe_p.h
@@ -50,11 +50,13 @@
 
 QT_BEGIN_NAMESPACE
 
-class QFramePrivate : public QWidgetPrivate
+// ### unexport this class when and if QAbstractScrollAreaPrivate is unexported
+class Q_WIDGETS_EXPORT QFramePrivate : public QWidgetPrivate
 {
     Q_DECLARE_PUBLIC(QFrame)
 public:
     QFramePrivate();
+    ~QFramePrivate();
 
     void        updateFrameWidth();
     void        updateStyledFrameWidths();
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index fa1a5acb5f23f390071a5ddfd6e8019f30689a68..c70bc4baef1bf25d20bd84e8c8fbf281f0e88eb8 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -53,6 +53,10 @@
 
 QT_BEGIN_NAMESPACE
 
+QLabelPrivate::~QLabelPrivate()
+{
+}
+
 /*!
     \class QLabel
     \brief The QLabel widget provides a text or image display.
diff --git a/src/widgets/widgets/qlabel_p.h b/src/widgets/widgets/qlabel_p.h
index 3778cb9d4762e59a6bb1d0ac0d034ae222c48812..2eb4ff9fc6ac0d7b343d1dea7efa9fdfaf8ca4b8 100644
--- a/src/widgets/widgets/qlabel_p.h
+++ b/src/widgets/widgets/qlabel_p.h
@@ -65,6 +65,7 @@ class QLabelPrivate : public QFramePrivate
     Q_DECLARE_PUBLIC(QLabel)
 public:
     QLabelPrivate() {}
+    ~QLabelPrivate();
 
     void init();
     void clearContents();
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 6a41c3791f8633da114963852af423602a4e1ee6..ad3a92d35acfa0c5a86b8050ce252b451eda8fec 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -440,6 +440,10 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
     Q_Q(QLineEdit);
     if (!newAction)
         return 0;
+    if (!hasSideWidgets()) { // initial setup.
+        QObject::connect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
+        lastTextSize = q->text().size();
+    }
     QWidget *w = 0;
     // Store flags about QWidgetAction here since removeAction() may be called from ~QAction,
     // in which a qobject_cast<> no longer works.
@@ -456,10 +460,6 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
         toolButton->setDefaultAction(newAction);
         w = toolButton;
     }
-    if (!hasSideWidgets()) { // initial setup.
-        QObject::connect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
-        lastTextSize = q->text().size();
-    }
     // If there is a 'before' action, it takes preference
     PositionIndexPair positionIndex = before ? findSideWidget(before) : PositionIndexPair(position, -1);
     SideWidgetEntryList &list = positionIndex.first == QLineEdit::TrailingPosition ? trailingSideWidgets : leadingSideWidgets;
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index 1ede07e4cbb45f4d0cbbd48fe75255e9a5fb3000..4654262ea736ed3887d6bddb8ab916aa37d2e97e 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
 
 // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text
 
-class QLineEditIconButton : public QToolButton
+class Q_AUTOTEST_EXPORT QLineEditIconButton : public QToolButton
 {
     Q_OBJECT
     Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
diff --git a/src/widgets/widgets/qmacnativewidget_mac.h b/src/widgets/widgets/qmacnativewidget_mac.h
index b27d877e8f3e9928d1fb3926694dd75eb1c09ef9..761e55656b4cd8d159e1acf00b9e3f8ed625c26f 100644
--- a/src/widgets/widgets/qmacnativewidget_mac.h
+++ b/src/widgets/widgets/qmacnativewidget_mac.h
@@ -52,7 +52,6 @@ public:
     NSView *nativeView() const;
 
 protected:
-    void init(NSView *parentView);
     bool event(QEvent *ev);
 
 private:
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 2a1e8428abdcc980028a9b4081c2953478efbb05..f365ff7d1706a4a6679a7f72a113cfa1bd5714bf 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -420,6 +420,13 @@ QMainWindow::~QMainWindow()
                             at the bottom. Implies AllowTabbedDocks. See also
                             \l setTabPosition().
 
+    \value GroupedDragging  When dragging the titlebar of a dock, all the tabs
+                            that are tabbed with it are going to be dragged.
+                            Implies AllowTabbedDocks. Does not work well if
+                            some QDockWidgets have restrictions in which area
+                            they are allowed. (This enum value was added in Qt
+                            5.6.)
+
     These options only control how dock widgets may be dropped in a QMainWindow.
     They do not re-arrange the dock widgets to conform with the specified
     options. For this reason they should be set before any dock widgets
@@ -1080,7 +1087,7 @@ void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget
     addDockWidget(area, dockwidget, orientation);
 
 #ifdef Q_DEAD_CODE_FROM_QT4_MAC     //drawer support
-    QMacCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
     if (qt_mac_is_macdrawer(dockwidget)) {
         extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h
index cbbea74b9b3194bbba3655c29d2bfab8d592bdff..0bd70c87a6cd68c72fdc8c93f09d2cd63e9646df 100644
--- a/src/widgets/widgets/qmainwindow.h
+++ b/src/widgets/widgets/qmainwindow.h
@@ -77,7 +77,8 @@ public:
         AllowNestedDocks = 0x02,
         AllowTabbedDocks = 0x04,
         ForceTabbedDocks = 0x08,  // implies AllowTabbedDocks, !AllowNestedDocks
-        VerticalTabs = 0x10       // implies AllowTabbedDocks
+        VerticalTabs = 0x10,      // implies AllowTabbedDocks
+        GroupedDragging = 0x20    // implies AllowTabbedDocks
     };
     Q_ENUM(DockOption)
     Q_DECLARE_FLAGS(DockOptions, DockOption)
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 3620aa04fc69026c857d6fcf03a841f53a6bd5d9..ee76720a2768fb2a4b288142caf84d30974ab1d8 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -49,6 +50,7 @@
 #include <qstatusbar.h>
 #include <qstring.h>
 #include <qstyle.h>
+#include <qstylepainter.h>
 #include <qvarlengtharray.h>
 #include <qstack.h>
 #include <qmap.h>
@@ -61,6 +63,7 @@
 
 #include <private/qapplication_p.h>
 #include <private/qlayoutengine_p.h>
+#include <private/qwidgetresizehandler_p.h>
 #ifdef Q_DEAD_CODE_FROM_QT4_MAC
 #   include <private/qcore_mac_p.h>
 #   include <private/qt_cocoa_helpers_mac_p.h>
@@ -68,9 +71,7 @@
 
 QT_BEGIN_NAMESPACE
 
-#ifdef QT_NO_DOCKWIDGET
 extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
-#endif
 
 /******************************************************************************
 ** debug
@@ -164,6 +165,242 @@ QDebug operator<<(QDebug debug, const QMainWindowLayout *layout)
 
 #endif // !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_DEBUG)
 
+/******************************************************************************
+ ** QDockWidgetGroupWindow
+ */
+// QDockWidgetGroupWindow is the floating window containing the tabbed dockwidgets in case several
+// dockwidgets are dragged together (QMainWindow::GroupedDragging feature).
+// QDockWidgetGroupLayout is the layout of that window and use a QDockAreaLayoutInfo to layout
+// the tabs inside it.
+#ifndef QT_NO_DOCKWIDGET
+class QDockWidgetGroupLayout : public QLayout {
+    QDockAreaLayoutInfo info;
+    QWidgetResizeHandler *resizer;
+public:
+    QDockWidgetGroupLayout(QWidget* parent) : QLayout(parent) {
+        setSizeConstraint(QLayout::SetMinAndMaxSize);
+        resizer = new QWidgetResizeHandler(parent);
+        resizer->setMovingEnabled(false);
+    }
+    ~QDockWidgetGroupLayout() {
+        info.deleteAllLayoutItems();
+    }
+
+    void addItem(QLayoutItem*) Q_DECL_OVERRIDE { Q_UNREACHABLE(); }
+    int count() const Q_DECL_OVERRIDE { return 0; }
+    QLayoutItem* itemAt(int index) const Q_DECL_OVERRIDE
+    {
+        int x = 0;
+        return info.itemAt(&x, index);
+    }
+    QLayoutItem* takeAt(int index) Q_DECL_OVERRIDE
+    {
+        int x = 0;
+        return info.takeAt(&x, index);
+    }
+    QSize sizeHint() const Q_DECL_OVERRIDE
+    {
+        int fw = frameWidth();
+        return info.sizeHint() + QSize(fw, fw);
+    }
+    QSize minimumSize() const Q_DECL_OVERRIDE
+    {
+        int fw = frameWidth();
+        return info.minimumSize() + QSize(fw, fw);
+    }
+    QSize maximumSize() const Q_DECL_OVERRIDE
+    {
+        int fw = frameWidth();
+        return info.maximumSize() + QSize(fw, fw);
+    }
+    void setGeometry(const QRect&r) Q_DECL_OVERRIDE
+    {
+        QDockAreaLayoutInfo *li = layoutInfo();
+        if (li->isEmpty()) {
+            static_cast<QDockWidgetGroupWindow *>(parent())->destroyIfEmpty();
+            return;
+        }
+        int fw = frameWidth();
+        li->reparentWidgets(parentWidget());
+        li->rect = r.adjusted(fw, fw, -fw, -fw);
+        li->fitItems();
+        li->apply(false);
+        resizer->setActive(QWidgetResizeHandler::Resize, !nativeWindowDeco());
+    }
+
+    QDockAreaLayoutInfo *layoutInfo() {
+        return &info;
+    }
+
+    bool nativeWindowDeco() const
+    {
+        return QDockWidgetLayout::wmSupportsNativeWindowDeco();
+    }
+
+    int frameWidth() const
+    {
+        return nativeWindowDeco() ? 0 :
+            parentWidget()->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, parentWidget());
+    }
+};
+
+// This item will be used in the layout for the gap item. We cannot use QWidgetItem directly
+// because QWidgetItem functions return an empty size for widgets are are floating.
+class QDockWidgetGroupWindowItem : public QWidgetItem
+{
+public:
+    QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {}
+    QSize minimumSize() const Q_DECL_OVERRIDE { return lay()->minimumSize(); }
+    QSize maximumSize() const Q_DECL_OVERRIDE { return lay()->maximumSize(); }
+    QSize sizeHint() const Q_DECL_OVERRIDE { return lay()->sizeHint(); }
+
+private:
+    QLayout *lay() const { return const_cast<QDockWidgetGroupWindowItem *>(this)->widget()->layout(); }
+};
+
+bool QDockWidgetGroupWindow::event(QEvent *e)
+{
+    switch (e->type()) {
+    case QEvent::Close:
+        // Forward the close to the QDockWidget just as if its close button was pressed
+        if (QDockWidget *dw = topDockWidget()) {
+            e->ignore();
+            dw->close();
+            adjustFlags();
+        }
+        return true;
+    case QEvent::Move:
+        // Let QDockWidgetPrivate::moseEvent handle the dragging
+        if (QDockWidget *dw = topDockWidget())
+            static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->moveEvent(static_cast<QMoveEvent*>(e));
+        return true;
+    case QEvent::NonClientAreaMouseMove:
+    case QEvent::NonClientAreaMouseButtonPress:
+    case QEvent::NonClientAreaMouseButtonRelease:
+    case QEvent::NonClientAreaMouseButtonDblClick:
+        // Let the QDockWidgetPrivate of the currently visible dock widget handle the drag and drop
+        if (QDockWidget *dw = topDockWidget())
+            static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->nonClientAreaMouseEvent(static_cast<QMouseEvent*>(e));
+        return true;
+    case QEvent::ChildAdded:
+        if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
+            adjustFlags();
+        break;
+    default:
+        break;
+    }
+    return QWidget::event(e);
+}
+
+void QDockWidgetGroupWindow::paintEvent(QPaintEvent *)
+{
+    QDockWidgetGroupLayout *lay = static_cast<QDockWidgetGroupLayout *>(layout());
+    bool nativeDeco = lay->nativeWindowDeco();
+
+    if (!nativeDeco) {
+        QStyleOptionFrame framOpt;
+        framOpt.init(this);
+        QStylePainter p(this);
+        p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt);
+    }
+}
+
+QDockAreaLayoutInfo *QDockWidgetGroupWindow::layoutInfo() const
+{
+    return static_cast<QDockWidgetGroupLayout*>(layout())->layoutInfo();
+}
+
+/*! \internal
+    Returns the currently active QDockWidget.
+ */
+QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
+{
+    QDockAreaLayoutInfo *info = layoutInfo();
+    QDockWidget *dw = 0;
+    if (info->tabBar && info->tabBar->currentIndex() >= 0) {
+        int i = info->tabIndexToListIndex(info->tabBar->currentIndex());
+        if (i >= 0) {
+            const QDockAreaLayoutItem &item = info->item_list.at(i);
+            if (item.widgetItem)
+                dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
+        }
+    }
+    if (!dw) {
+        for (int i = 0; !dw && i < info->item_list.count(); ++i) {
+            const QDockAreaLayoutItem &item = info->item_list.at(i);
+            if (item.skip())
+                continue;
+            if (!item.widgetItem)
+                continue;
+            dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
+        }
+    }
+    return dw;
+}
+
+/*! \internal
+    Destroy this window if there is no more QDockWidget in it.
+ */
+void QDockWidgetGroupWindow::destroyIfEmpty()
+{
+    if (layoutInfo()->isEmpty()) {
+        // Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
+        foreach (QDockWidget *dw,
+                 findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
+            bool wasFloating = dw->isFloating();
+            bool wasHidden = dw->isHidden();
+            dw->setParent(parentWidget());
+            if (wasFloating) {
+                dw->setFloating(true);
+            } else {
+                // maybe it was hidden, we still have to put it back in the main layout.
+                QMainWindowLayout *ml = qt_mainwindow_layout(static_cast<QMainWindow*>(parentWidget()));
+                Qt::DockWidgetArea area = ml->dockWidgetArea(this);
+                if (area == Qt::NoDockWidgetArea)
+                    area = Qt::LeftDockWidgetArea;
+                static_cast<QMainWindow*>(parentWidget())->addDockWidget(area, dw);
+            }
+            if (!wasHidden)
+                dw->show();
+        }
+        foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
+            tb->setParent(parentWidget());
+        deleteLater();
+    }
+}
+
+/*! \internal
+    Sets the flags of this window in accordence to the capabilities of the dock widgets
+ */
+void QDockWidgetGroupWindow::adjustFlags()
+{
+    QDockWidget *top = topDockWidget();
+    if (!top)
+        return;
+    const bool nativeDeco = static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco();
+
+    Qt::WindowFlags oldFlags = windowFlags();
+    Qt::WindowFlags flags = oldFlags;
+    if (nativeDeco) {
+        flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint;
+        if (top->features() & QDockWidget::DockWidgetClosable)
+            flags |= Qt::WindowCloseButtonHint;
+        else
+            flags &= ~Qt::WindowCloseButtonHint;
+        flags &= ~Qt::FramelessWindowHint;
+    } else {
+        flags |= Qt::FramelessWindowHint;
+    }
+    if (oldFlags != flags) {
+        setWindowFlags(flags);
+        show(); // setWindowFlags hides the window
+    }
+
+    setWindowTitle(top->windowTitle());
+    setWindowIcon(top->windowIcon());
+}
+#endif
+
 /******************************************************************************
 ** QMainWindowLayoutState
 */
@@ -335,8 +572,8 @@ QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const
 
 #ifndef QT_NO_DOCKWIDGET
     // is it a dock widget?
-    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) {
-        result = dockAreaLayout.indexOf(dockWidget);
+    if (qobject_cast<QDockWidget *>(widget) || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+        result = dockAreaLayout.indexOf(widget);
         if (!result.isEmpty())
             result.prepend(1);
         return result;
@@ -413,7 +650,8 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
 
 #ifndef QT_NO_DOCKWIDGET
     // is it a dock widget?
-    if (qobject_cast<QDockWidget *>(widget) != 0) {
+    if (qobject_cast<QDockWidget *>(widget) != 0
+            || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
         result = dockAreaLayout.gapIndex(pos);
         if (!result.isEmpty())
             result.prepend(1);
@@ -440,7 +678,7 @@ bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item
 
 #ifndef QT_NO_DOCKWIDGET
     if (i == 1) {
-        Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
+        Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) || qobject_cast<QDockWidgetGroupWindow*>(item->widget()));
         return dockAreaLayout.insertGap(path.mid(1), item);
     }
 #endif //QT_NO_DOCKWIDGET
@@ -593,6 +831,17 @@ void QMainWindowLayoutState::saveState(QDataStream &stream) const
 {
 #ifndef QT_NO_DOCKWIDGET
     dockAreaLayout.saveState(stream);
+#ifndef QT_NO_TABBAR
+    QList<QDockWidgetGroupWindow *> floatingTabs =
+        mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+
+    foreach (QDockWidgetGroupWindow *floating, floatingTabs) {
+        if (floating->layoutInfo()->isEmpty())
+            continue;
+        stream << uchar(QDockAreaLayout::FloatingDockWidgetTabMarker) << floating->geometry();
+        floating->layoutInfo()->saveState(stream);
+    }
+#endif
 #endif
 #ifndef QT_NO_TOOLBAR
     toolBarAreaLayout.saveState(stream);
@@ -638,12 +887,28 @@ bool QMainWindowLayoutState::checkFormat(QDataStream &stream)
             case QDockAreaLayout::DockWidgetStateMarker:
                 {
                     QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                    foreach (QDockWidgetGroupWindow *floating, findChildrenHelper<QDockWidgetGroupWindow*>(mainWindow))
+                        dockWidgets += findChildrenHelper<QDockWidget*>(floating);
                     if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
                         return false;
                     }
                 }
                 break;
-#endif
+#ifndef QT_NO_TABBAR
+            case QDockAreaLayout::FloatingDockWidgetTabMarker:
+                {
+                    QRect geom;
+                    stream >> geom;
+                    QDockAreaLayoutInfo info;
+                    QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                    foreach (QDockWidgetGroupWindow *floating, findChildrenHelper<QDockWidgetGroupWindow*>(mainWindow))
+                        dockWidgets += findChildrenHelper<QDockWidget*>(floating);
+                    if (!info.restoreState(stream, dockWidgets, true /* testing*/))
+                        return false;
+                }
+                break;
+#endif // QT_NO_TABBAR
+#endif // QT_NO_DOCKWIDGET
             default:
                 //there was an error during the parsing
                 return false;
@@ -682,6 +947,8 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
             case QDockAreaLayout::DockWidgetStateMarker:
                 {
                     QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                    foreach (QDockWidgetGroupWindow *floating, findChildrenHelper<QDockWidgetGroupWindow*>(mainWindow))
+                        dockWidgets += findChildrenHelper<QDockWidget*>(floating);
                     if (!dockAreaLayout.restoreState(stream, dockWidgets))
                         return false;
 
@@ -702,6 +969,26 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
                     }
                 }
                 break;
+#ifndef QT_NO_TABBAR
+            case QDockAreaLayout::FloatingDockWidgetTabMarker:
+            {
+                QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                foreach (QDockWidgetGroupWindow *floating, findChildrenHelper<QDockWidgetGroupWindow*>(mainWindow))
+                    dockWidgets += findChildrenHelper<QDockWidget*>(floating);
+                QDockWidgetGroupWindow* floatingTab = qt_mainwindow_layout(mainWindow)->createTabbedDockWindow();
+                *floatingTab->layoutInfo() = QDockAreaLayoutInfo(&dockAreaLayout.sep, QInternal::LeftDock,
+                                                                 Qt::Horizontal, QTabBar::RoundedSouth, mainWindow);
+                QRect geometry;
+                stream >> geometry;
+                if (!floatingTab->layoutInfo()->restoreState(stream, dockWidgets, false))
+                    return false;
+                geometry = QDockAreaLayout::constrainedRect(geometry, floatingTab);
+                floatingTab->move(geometry.topLeft());
+                floatingTab->resize(geometry.size());
+                floatingTab->show();
+            }
+            break;
+#endif // QT_NO_TABBAR
 #endif // QT_NO_DOCKWIDGET
 
 #ifndef QT_NO_TOOLBAR
@@ -1223,7 +1510,7 @@ void QMainWindowLayout::splitDockWidget(QDockWidget *after,
     invalidate();
 }
 
-Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const
+Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QWidget *widget) const
 {
     QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
     if (pathToWidget.isEmpty())
@@ -1238,20 +1525,88 @@ void QMainWindowLayout::keepSize(QDockWidget *w)
 
 #ifndef QT_NO_TABBAR
 
+// Handle custom tooltip, and allow to drag tabs away.
 class QMainWindowTabBar : public QTabBar
 {
+    QMainWindow *mainWindow;
+    QDockWidget *draggingDock; // Currently dragging (detached) dock widget
 public:
-    QMainWindowTabBar(QWidget *parent);
+    QMainWindowTabBar(QMainWindow *parent);
 protected:
     bool event(QEvent *e) Q_DECL_OVERRIDE;
+    void mouseReleaseEvent(QMouseEvent*) Q_DECL_OVERRIDE;
+    void mouseMoveEvent(QMouseEvent*) Q_DECL_OVERRIDE;
+
 };
 
-QMainWindowTabBar::QMainWindowTabBar(QWidget *parent)
-    : QTabBar(parent)
+QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent)
+    : QTabBar(parent), mainWindow(parent), draggingDock(0)
 {
     setExpanding(false);
 }
 
+void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
+{
+    // The QTabBar handles the moving (reordering) of tabs.
+    // When QTabBarPrivate::dragInProgress is true, and that the mouse is outside of a region
+    // around the QTabBar, we will consider the user wants to drag that QDockWidget away from this
+    // tab area.
+
+    QTabBarPrivate *d = static_cast<QTabBarPrivate*>(d_ptr.data());
+    if (!draggingDock && (mainWindow->dockOptions() & QMainWindow::GroupedDragging)) {
+        int offset = QApplication::startDragDistance() + 1;
+        offset *= 3;
+        QRect r = rect().adjusted(-offset, -offset, offset, offset);
+        if (d->dragInProgress && !r.contains(e->pos()) && d->validIndex(d->pressedIndex)) {
+            QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow);
+            QDockAreaLayoutInfo *info = mlayout->dockInfo(this);
+            Q_ASSERT(info);
+            int idx = info->tabIndexToListIndex(d->pressedIndex);
+            const QDockAreaLayoutItem &item = info->item_list.at(idx);
+            if (item.widgetItem
+                    && (draggingDock = qobject_cast<QDockWidget *>(item.widgetItem->widget()))) {
+                // We should drag this QDockWidget away by unpluging it.
+                // First cancel the QTabBar's internal move
+                d->moveTabFinished(d->pressedIndex);
+                d->pressedIndex = -1;
+                if (d->movingTab)
+                    d->movingTab->setVisible(false);
+                d->dragStartPosition = QPoint();
+
+                // Then starts the drag using QDockWidgetPrivate's API
+                QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
+                QDockWidgetLayout *dwlayout = static_cast<QDockWidgetLayout *>(draggingDock->layout());
+                dockPriv->initDrag(dwlayout->titleArea().center(), true);
+                dockPriv->startDrag(false);
+                if (dockPriv->state)
+                    dockPriv->state->ctrlDrag = e->modifiers() & Qt::ControlModifier;
+            }
+        }
+    }
+
+    if (draggingDock) {
+        QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
+        if (dockPriv->state && dockPriv->state->dragging) {
+            QPoint pos = e->globalPos() - dockPriv->state->pressPos;
+            draggingDock->move(pos);
+            // move will call QMainWindowLayout::hover
+        }
+    }
+    QTabBar::mouseMoveEvent(e);
+}
+
+void QMainWindowTabBar::mouseReleaseEvent(QMouseEvent *e)
+{
+    if (draggingDock && e->button() == Qt::LeftButton) {
+        QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
+        if (dockPriv->state && dockPriv->state->dragging) {
+            dockPriv->endDrag();
+        }
+        draggingDock = 0;
+    }
+    QTabBar::mouseReleaseEvent(e);
+}
+
 bool QMainWindowTabBar::event(QEvent *e)
 {
     // show the tooltip if tab is too small to fit label
@@ -1276,7 +1631,7 @@ QTabBar *QMainWindowLayout::getTabBar()
     if (!unusedTabBars.isEmpty()) {
         result = unusedTabBars.takeLast();
     } else {
-        result = new QMainWindowTabBar(parentWidget());
+        result = new QMainWindowTabBar(static_cast<QMainWindow *>(parentWidget()));
         result->setDrawBase(true);
         result->setElideMode(Qt::ElideRight);
         result->setDocumentMode(_documentMode);
@@ -1305,12 +1660,30 @@ QWidget *QMainWindowLayout::getSeparatorWidget()
     return result;
 }
 
+/*! \internal
+    Returns a pointer QDockAreaLayoutInfo which contains this \a widget directly
+    (in its internal list)
+ */
+QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget)
+{
+    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
+    if (info)
+        return info;
+    foreach (QDockWidgetGroupWindow *dwgw,
+             parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+        info = dwgw->layoutInfo()->info(widget);
+        if (info)
+            return info;
+    }
+    return 0;
+}
+
 void QMainWindowLayout::tabChanged()
 {
     QTabBar *tb = qobject_cast<QTabBar*>(sender());
     if (tb == 0)
         return;
-    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
+    QDockAreaLayoutInfo *info = dockInfo(tb);
     if (info == 0)
         return;
     info->apply(false);
@@ -1323,7 +1696,7 @@ void QMainWindowLayout::tabMoved(int from, int to)
 {
     QTabBar *tb = qobject_cast<QTabBar*>(sender());
     Q_ASSERT(tb);
-    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
+    QDockAreaLayoutInfo *info = dockInfo(tb);
     Q_ASSERT(info);
 
     info->moveTab(from, to);
@@ -1365,7 +1738,7 @@ bool QMainWindowLayout::endSeparatorMove(const QPoint&)
 
 void QMainWindowLayout::raise(QDockWidget *widget)
 {
-    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
+    QDockAreaLayoutInfo *info = dockInfo(widget);
     if (info == 0)
         return;
 #ifndef QT_NO_TABBAR
@@ -1549,6 +1922,8 @@ void QMainWindowLayout::revert(QLayoutItem *widgetItem)
     QWidget *widget = widgetItem->widget();
     layoutState = savedState;
     currentGapPos = layoutState.indexOf(widget);
+    if (currentGapPos.isEmpty())
+        return;
     fixToolBarOrientation(widgetItem, currentGapPos.at(1));
     layoutState.unplug(currentGapPos);
     layoutState.fitLayout();
@@ -1613,6 +1988,42 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
     if (widget == pluggingWidget) {
 
 #ifndef QT_NO_DOCKWIDGET
+        if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+            // When the animated widget was a QDockWidgetGroupWindow, it means each of the
+            // embedded QDockWidget needs to be plugged back into the QMainWindow layout.
+            savedState.clear();
+            QDockAreaLayoutInfo* info = dwgw->layoutInfo();
+            QList<int> path = layoutState.dockAreaLayout.indexOf(widget);
+            Q_ASSERT(path.size() >= 2);
+
+            QDockAreaLayoutInfo* parentInfo = layoutState.dockAreaLayout.info(path);
+            Q_ASSERT(parentInfo);
+            if (parentInfo->tabbed) {
+                // merge the two tab widgets
+                int idx = path.last();
+                Q_ASSERT(parentInfo->item_list[idx].widgetItem->widget() == dwgw);
+                delete parentInfo->item_list[idx].widgetItem;
+                parentInfo->item_list.removeAt(idx);
+                std::copy(info->item_list.cbegin(), info->item_list.cend(),
+                          std::inserter(parentInfo->item_list, parentInfo->item_list.begin() + idx));
+                quintptr currentId = info->currentTabId();
+                *info = QDockAreaLayoutInfo();
+                parentInfo->reparentWidgets(parentWidget());
+                parentInfo->updateTabBar();
+                parentInfo->setCurrentTabId(currentId);
+            } else {
+                QDockAreaLayoutItem &item = layoutState.dockAreaLayout.item(path);
+                Q_ASSERT(item.widgetItem->widget() == dwgw);
+                delete item.widgetItem;
+                item.widgetItem = 0;
+                item.subinfo = new QDockAreaLayoutInfo(qMove(*info));
+                *info = QDockAreaLayoutInfo();
+                item.subinfo->reparentWidgets(parentWidget());
+                item.subinfo->setTabBarShape(parentInfo->tabBarShape);
+            }
+            dwgw->destroyIfEmpty();
+        }
+
         if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
             dw->d_func()->plug(currentGapRect);
 #endif
@@ -1633,7 +2044,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
         if (qobject_cast<QDockWidget*>(widget) != 0) {
             // info() might return null if the widget is destroyed while
             // animating but before the animationFinished signal is received.
-            if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
+            if (QDockAreaLayoutInfo *info = dockInfo(widget))
                 info->setCurrentTab(widget);
         }
 #endif
@@ -1777,8 +2188,33 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget)
     invalidate();
 }
 
-QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
-{
+/*! \internal
+    Unplug \a widget (QDockWidget or QToolBar) from it's parent container.
+
+    If \a group is true we might actually unplug the group of tabs this
+    widget is part if QMainWindow::GroupedDragging is set. When \a group
+    is false, the widget itself is always unplugged alone
+
+    Returns the QLayoutItem of the dragged element.
+    The layout item is kept in the layout but set as a gap item.
+ */
+QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
+{
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_TABBAR)
+    QDockWidgetGroupWindow *floatingParent = qobject_cast<QDockWidgetGroupWindow *>(widget->parentWidget());
+    if (group && floatingParent && !widget->isWindow()) {
+        // We are just dragging a floating window as it, not need to do anything, we just have to
+        // look up the corresponding QWidgetItem* if it exists
+        QList<int> tabbedWindowPath = layoutState.indexOf(widget->parentWidget());
+        return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath);
+    } else if (floatingParent) {
+        // We are unplugging a dock widget from a floating window.
+        if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
+            dw->d_func()->unplug(widget->geometry());
+            return 0;
+        }
+    }
+#endif
     QList<int> path = layoutState.indexOf(widget);
     if (path.isEmpty())
         return 0;
@@ -1792,9 +2228,35 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
 
 #ifndef QT_NO_DOCKWIDGET
     if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
-        dw->d_func()->unplug(r);
+        Q_ASSERT(path.first() == 1);
+        bool actualGroup = false;
+#ifndef QT_NO_TABBAR
+        if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3) {
+            QDockAreaLayoutItem &parentItem = layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2));
+            if (parentItem.subinfo && parentItem.subinfo->tabbed) {
+                // The QDockWidget is part of a group of tab and we need to unplug them all.
+                actualGroup = true;
+                path.removeLast();
+
+                QDockWidgetGroupWindow* floatingTabs = createTabbedDockWindow();
+                QDockAreaLayoutInfo* info = floatingTabs->layoutInfo();
+                *info = qMove(*parentItem.subinfo);
+                delete parentItem.subinfo;
+                parentItem.subinfo = 0;
+                floatingTabs->setGeometry(info->rect.translated(parentWidget()->pos()));
+                floatingTabs->show();
+                floatingTabs->raise();
+                item = new QDockWidgetGroupWindowItem(floatingTabs);
+                parentItem.widgetItem = item;
+                savedState = layoutState;
+            }
+        }
+#endif // QT_NO_TABBAR
+        if (!actualGroup) {
+            dw->d_func()->unplug(r);
+        }
     }
-#endif
+#endif // QT_NO_DOCKWIDGET
 #ifndef QT_NO_TOOLBAR
     if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
         tb->d_func()->unplug(r);
@@ -1841,6 +2303,9 @@ QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mouse
 #ifndef QT_NO_DOCKWIDGET
         if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
             allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
+
+        if (qobject_cast<QDockWidgetGroupWindow *>(widget))
+            allowed = true;
 #endif
 #ifndef QT_NO_TOOLBAR
         if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
@@ -1893,11 +2358,23 @@ QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mouse
     return path;
 }
 
+QDockWidgetGroupWindow *QMainWindowLayout::createTabbedDockWindow()
+{
+    QDockWidgetGroupWindow* f = new QDockWidgetGroupWindow(parentWidget(), Qt::Tool);
+    new QDockWidgetGroupLayout(f);
+    return f;
+}
+
 void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
 {
 #ifndef QT_NO_DOCKWIDGET
 #ifndef QT_NO_TABBAR
     QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
+    foreach (QDockWidgetGroupWindow *dwgw,
+             parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+        used += dwgw->layoutInfo()->usedTabBars();
+    }
+
     QSet<QTabBar*> retired = usedTabBars - used;
     usedTabBars = used;
     foreach (QTabBar *tab_bar, retired) {
@@ -1916,6 +2393,8 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat
         }
     }
 
+    for (int i = 0; i < QInternal::DockCount; ++i)
+        newState.dockAreaLayout.docks[i].reparentWidgets(parentWidget());
 
 #endif // QT_NO_TABBAR
 #endif // QT_NO_DOCKWIDGET
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index 8ccb4d303fabfcd67305d7f48e893bddd761a045..9155c5fb23b0e302425f90541ee3a522adcf735f 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -77,6 +77,23 @@ QT_BEGIN_NAMESPACE
 class QToolBar;
 class QRubberBand;
 
+#ifndef QT_NO_DOCKWIDGET
+class QDockWidgetGroupWindow : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit QDockWidgetGroupWindow(QWidget* parent = 0, Qt::WindowFlags f = 0)
+        : QWidget(parent, f) {}
+    QDockAreaLayoutInfo *layoutInfo() const;
+    QDockWidget *topDockWidget() const;
+    void destroyIfEmpty();
+    void adjustFlags();
+protected:
+    bool event(QEvent *) Q_DECL_OVERRIDE;
+    void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
+};
+#endif
+
 /* This data structure represents the state of all the tool-bars and dock-widgets. It's value based
    so it can be easilly copied into a temporary variable. All operations are performed without moving
    any widgets. Only when we are sure we have the desired state, we call apply(), which moves the
@@ -196,10 +213,11 @@ public:
                          QDockWidget *dockwidget,
                          Qt::Orientation orientation);
     void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
-    Qt::DockWidgetArea dockWidgetArea(QDockWidget *dockwidget) const;
+    Qt::DockWidgetArea dockWidgetArea(QWidget* widget) const;
     void raise(QDockWidget *widget);
     void setVerticalTabsEnabled(bool enabled);
     bool restoreDockWidget(QDockWidget *dockwidget);
+    QDockAreaLayoutInfo *dockInfo(QWidget *w);
 
 #ifndef QT_NO_TABBAR
     bool _documentMode;
@@ -224,6 +242,8 @@ public:
     void setTabShape(QTabWidget::TabShape tabShape);
     QTabWidget::TabPosition tabPosition(Qt::DockWidgetArea area) const;
     void setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition);
+
+    QDockWidgetGroupWindow *createTabbedDockWindow();
 #endif // QT_NO_TABWIDGET
 #endif // QT_NO_TABBAR
 
@@ -273,7 +293,7 @@ public:
 
     QList<int> hover(QLayoutItem *widgetItem, const QPoint &mousePos);
     bool plug(QLayoutItem *widgetItem);
-    QLayoutItem *unplug(QWidget *widget);
+    QLayoutItem *unplug(QWidget *widget, bool group = false);
     void revert(QLayoutItem *widgetItem);
     void updateGapIndicator();
     void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip);
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 1749f9d8c711786189aa4e18b5e55bdbfaab26f7..4403deda8e671c1f5ac322d52819c26f74110ed0 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -183,7 +183,7 @@ void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu)
 }
 
 // forward declare function
-static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item);
+static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu);
 
 void QMenuPrivate::syncPlatformMenu()
 {
@@ -200,7 +200,7 @@ void QMenuPrivate::syncPlatformMenu()
         menuItem->setTag(reinterpret_cast<quintptr>(action));
         QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
         QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection);
-        copyActionToPlatformItem(action, menuItem);
+        copyActionToPlatformItem(action, menuItem, platformMenu.data());
         platformMenu->insertMenuItem(menuItem, beforeItem);
         beforeItem = menuItem;
     }
@@ -1110,8 +1110,7 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
             handleEnterLeaveEvents(&previousMouseMenu,qobject_cast<QMenu *>(caused));
             if(e->type() != QEvent::MouseButtonRelease || mouseDown == caused) {
             QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(),
-                              e->button(), e->buttons(), e->modifiers());
-            QGuiApplicationPrivate::setMouseEventSource(&new_e, e->source());
+                              e->button(), e->buttons(), e->modifiers(), e->source());
             QApplication::sendEvent(caused, &new_e);
             return true;
             }
@@ -3105,7 +3104,7 @@ QMenu::timerEvent(QTimerEvent *e)
     }
 }
 
-static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item)
+static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu)
 {
     item->setText(action->text());
     item->setIsSeparator(action->isSeparator());
@@ -3131,6 +3130,8 @@ static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* i
     item->setEnabled(action->isEnabled());
 
     if (action->menu()) {
+        if (!action->menu()->platformMenu())
+            action->menu()->setPlatformMenu(itemsMenu->createSubMenu());
         item->setMenu(action->menu()->platformMenu());
     } else {
         item->setMenu(0);
@@ -3185,7 +3186,7 @@ void QMenu::actionEvent(QActionEvent *e)
             menuItem->setTag(reinterpret_cast<quintptr>(e->action()));
             QObject::connect(menuItem, SIGNAL(activated()), e->action(), SLOT(trigger()));
             QObject::connect(menuItem, SIGNAL(hovered()), e->action(), SIGNAL(hovered()));
-            copyActionToPlatformItem(e->action(), menuItem);
+            copyActionToPlatformItem(e->action(), menuItem, d->platformMenu);
             QPlatformMenuItem* beforeItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before()));
             d->platformMenu->insertMenuItem(menuItem, beforeItem);
         } else if (e->type() == QEvent::ActionRemoved) {
@@ -3195,7 +3196,7 @@ void QMenu::actionEvent(QActionEvent *e)
         } else if (e->type() == QEvent::ActionChanged) {
             QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
             if (menuItem) {
-                copyActionToPlatformItem(e->action(), menuItem);
+                copyActionToPlatformItem(e->action(), menuItem, d->platformMenu);
                 d->platformMenu->syncMenuItem(menuItem);
             }
         }
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 4659d9cf6c7d739f3d0ba77f101ee15262470b4d..1ad99bed9c0200084e104a84b958b30de2f2c680 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1632,7 +1632,7 @@ QSize QMenuBar::sizeHint() const
     if(d->leftWidget) {
         QSize sz = d->leftWidget->sizeHint();
         sz.rheight() += margin;
-        ret.expandedTo(sz);
+        ret = ret.expandedTo(sz);
     }
     if(d->rightWidget) {
         QSize sz = d->rightWidget->sizeHint();
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index de6e45234c3565acf6d550fd44b977d09dacbcbc..38773a4fbf2491558db14761d5ed1b5f6c16acb2 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -58,6 +58,10 @@ QT_BEGIN_NAMESPACE
 
 //#define QSPLITTER_DEBUG
 
+QSplitterPrivate::~QSplitterPrivate()
+{
+}
+
 /*!
     \class QSplitterHandle
     \brief The QSplitterHandle class provides handle functionality for the splitter.
diff --git a/src/widgets/widgets/qsplitter_p.h b/src/widgets/widgets/qsplitter_p.h
index a45f776da1207f181de42a015db2216fcb573182..890bd535ecf500835c3632fc44b72b2fc3f5eb98 100644
--- a/src/widgets/widgets/qsplitter_p.h
+++ b/src/widgets/widgets/qsplitter_p.h
@@ -76,6 +76,7 @@ class QSplitterPrivate : public QFramePrivate
 public:
     QSplitterPrivate() : rubberBand(0), opaque(true), firstShow(true),
                          childrenCollapsible(true), compatMode(false), handleWidth(-1), blockChildAdd(false), opaqueResizeSet(false) {}
+    ~QSplitterPrivate();
 
     QPointer<QRubberBand> rubberBand;
     mutable QList<QSplitterLayoutStruct *> list;
diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp
index 2cec8a0b9cf5dded37b1fabdc8e0ed4f3bb5f0ba..19a2edf0f2773ddfd7d64ec7bd5f88066866acc4 100644
--- a/src/widgets/widgets/qstackedwidget.cpp
+++ b/src/widgets/widgets/qstackedwidget.cpp
@@ -182,7 +182,9 @@ int QStackedWidget::insertWidget(int index, QWidget *widget)
     not deleted but simply removed from the stacked layout, causing it
     to be hidden.
 
-    \b{Note:} Ownership of \a widget reverts to the application.
+    \note Parent object and parent widget of \a widget will remain the
+    QStackedWidget. If the application wants to reuse the removed
+    \a widget, then it is recommended to re-parent it.
 
     \sa addWidget(), insertWidget(), currentWidget()
 */
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 5a56c592a68a561de5d76bff2520ba491a94f242..8473b261fccb20e878ea294cc65f875005152ca0 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -897,7 +897,7 @@ void QToolButton::setDefaultAction(QAction *action)
         return;
     if (!actions().contains(action))
         addAction(action);
-    setText(action->iconText());
+    setText(action->text());
     setIcon(action->icon());
 #ifndef QT_NO_TOOLTIP
     setToolTip(action->toolTip());
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 759e41a5fadb2c59816663022e81e7831d3964b2..436937be72fc87ee6eee75cce16de4b8bae645d1 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -189,7 +189,7 @@ void QWidgetLineControl::commitPreedit()
 
     m_preeditCursor = 0;
     setPreeditArea(-1, QString());
-    m_textLayout.clearAdditionalFormats();
+    m_textLayout.clearFormats();
     updateDisplayText(/*force*/ true);
 #endif
 }
@@ -557,7 +557,8 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
     const int oldPreeditCursor = m_preeditCursor;
     m_preeditCursor = event->preeditString().length();
     m_hideCursor = false;
-    QList<QTextLayout::FormatRange> formats;
+    QVector<QTextLayout::FormatRange> formats;
+    formats.reserve(event->attributes().size());
     for (int i = 0; i < event->attributes().size(); ++i) {
         const QInputMethodEvent::Attribute &a = event->attributes().at(i);
         if (a.type == QInputMethodEvent::Cursor) {
@@ -574,7 +575,7 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
             }
         }
     }
-    m_textLayout.setAdditionalFormats(formats);
+    m_textLayout.setFormats(formats);
     updateDisplayText(/*force*/ true);
     if (cursorPositionChanged)
         emitCursorPositionChanged();
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index faa63cb4006991232da3737d807f70692d8c822c..22d199fc7471396ae549011f908cf1d23ad4fff4 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -883,7 +883,8 @@ void QWidgetTextControl::setTextCursor(const QTextCursor &cursor)
     const bool posChanged = cursor.position() != d->cursor.position();
     const QTextCursor oldSelection = d->cursor;
     d->cursor = cursor;
-    d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable);
+    d->cursorOn = d->hasFocus
+            && (d->interactionFlags & (Qt::TextSelectableByKeyboard | Qt::TextEditable));
     d->_q_updateCurrentCharFormatAndSelection();
     ensureCursorVisible();
     d->repaintOldAndNewSelection(oldSelection);
@@ -2028,7 +2029,8 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
     QTextLayout *layout = block.layout();
     if (isGettingInput)
         layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
-    QList<QTextLayout::FormatRange> overrides;
+    QVector<QTextLayout::FormatRange> overrides;
+    overrides.reserve(e->attributes().size());
     const int oldPreeditCursor = preeditCursor;
     preeditCursor = e->preeditString().length();
     hideCursor = false;
@@ -2048,7 +2050,7 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
             }
         }
     }
-    layout->setAdditionalFormats(overrides);
+    layout->setFormats(overrides);
 
     cursor.endEditBlock();
 
@@ -2138,7 +2140,7 @@ void QWidgetTextControlPrivate::focusEvent(QFocusEvent *e)
 #ifdef QT_KEYPAD_NAVIGATION
         if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason))) {
 #endif
-        cursorOn = (interactionFlags & Qt::TextSelectableByKeyboard);
+        cursorOn = (interactionFlags & (Qt::TextSelectableByKeyboard | Qt::TextEditable));
         if (interactionFlags & Qt::TextEditable) {
             setBlinkingCursorEnabled(true);
         }
@@ -2877,7 +2879,7 @@ void QWidgetTextControlPrivate::commitPreedit()
     QTextBlock block = cursor.block();
     QTextLayout *layout = block.layout();
     layout->setPreeditArea(-1, QString());
-    layout->clearAdditionalFormats();
+    layout->clearFormats();
     cursor.endEditBlock();
 }
 
diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp
index e88cecf0b3d84efb471e8ffaf96826014996a1c1..2944e07e00b53e2ba18b5a6ef3c6207a30df9de2 100644
--- a/src/winmain/qtmain_win.cpp
+++ b/src/winmain/qtmain_win.cpp
@@ -111,7 +111,7 @@ extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int
     argv[argc] = Q_NULLPTR;
     LocalFree(argvW);
     const int exitCode = main(argc, argv);
-    for (int i = 0; i < argc; ++i)
+    for (int i = 0; i < argc && argv[i]; ++i)
         delete [] argv[i];
     delete [] argv;
     return exitCode;
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index 5a44df622a40b729b2a00d0713958661a1f4d8e6..e68da520e7780ecc9a5d4c9673ee73cb9df14b54 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -222,11 +222,49 @@ private:
 // Main entry point for Appx containers
 int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
 {
+#if _MSC_VER < 1900
     int argc = 0;
     char **argv, **env;
     _startupinfo info = { _query_new_mode() };
     if (int init = __getmainargs(&argc, &argv, &env, false, &info))
         return init;
+#else
+    QByteArray commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8();
+    QVarLengthArray<char *> args;
+    args.append(commandLine.data());
+    bool quote = false;
+    bool escape = false;
+    for (int i = 0; i < commandLine.size(); ++i) {
+        switch (commandLine.at(i)) {
+        case '\\':
+            escape = true;
+            break;
+        case '"':
+            if (escape) {
+                escape = false;
+                break;
+            }
+            quote = !quote;
+            commandLine[i] = '\0';
+            break;
+        case ' ':
+            if (quote)
+                break;
+            commandLine[i] = '\0';
+            if (args.last()[0] != '\0')
+                args.append(commandLine.data() + i + 1);
+            // fall through
+        default:
+            if (args.last()[0] == '\0')
+                args.last() = commandLine.data() + i;
+            escape = false; // only quotes are escaped
+            break;
+        }
+    }
+    int argc = args.size();
+    char **argv = args.data();
+    char **env = Q_NULLPTR;
+#endif // _MSC_VER >= 1900
 
     for (int i = 0; env && env[i]; ++i) {
         QByteArray var(env[i]);
diff --git a/src/xml/doc/qtxml.qdocconf b/src/xml/doc/qtxml.qdocconf
index 8ca421ff4ed81e10dcae28cb5a504bc807a0871d..419859ac8b0f589d8e20a0debe13bfd58686defb 100644
--- a/src/xml/doc/qtxml.qdocconf
+++ b/src/xml/doc/qtxml.qdocconf
@@ -40,3 +40,6 @@ imagedirs   += images \
 
 navigation.landingpage = "Qt XML"
 navigation.cppclassespage = "Qt XML C++ Classes"
+
+# Add a thumbnail for examples that do not have images
+manifestmeta.thumbnail.names = "QtXml/XML Stream Lint Example"
diff --git a/sync.profile b/sync.profile
index bf29ca6e26b8166dc58762c4acf78da9a98795cf..1700d94fff9e5beab7d0ecd08e2cb689dc44e38e 100644
--- a/sync.profile
+++ b/sync.profile
@@ -50,7 +50,7 @@
     }
 );
 
-@qpa_headers = ( qr/^qplatform/, qr/^qwindowsystem/ );
+@qpa_headers = ( qr/^(?!qplatformheaderhelper)qplatform/, qr/^qwindowsystem/ );
 my @angle_headers = ('egl.h', 'eglext.h', 'eglplatform.h', 'gl2.h', 'gl2ext.h', 'gl2platform.h', 'ShaderLang.h', 'khrplatform.h');
 my @internal_zlib_headers = ( "crc32.h", "deflate.h", "gzguts.h", "inffast.h", "inffixed.h", "inflate.h", "inftrees.h", "trees.h", "zutil.h" );
 my @zlib_headers = ( "zconf.h", "zlib.h" );
diff --git a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
index 21cab8f67d53be5396c5f86ae3287a5f404df544..7b374505ce80ed62f248ab3dcec953a7e56e487d 100644
--- a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
+++ b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
@@ -1,3 +1,4 @@
+CONFIG   += testcase
 QT       += testlib core-private
 
 QT       -= gui
diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
index e6b2f8a11670f9bca76bb4c120ed002def13d190..68129f9081f4c6677252b36101df1f069874e013 100644
--- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
+++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
@@ -41,10 +41,17 @@
 #include <QtCore/QThread>
 #include <QtTest/QtTest>
 
+#if defined(Q_OS_UNIX)
+#include <sys/resource.h>
+#endif
+
 class tst_QGlobalStatic : public QObject
 {
     Q_OBJECT
 
+public Q_SLOTS:
+    void initTestCase();
+
 private Q_SLOTS:
     void beforeInitialization();
     void api();
@@ -55,6 +62,20 @@ private Q_SLOTS:
     void afterDestruction();
 };
 
+void tst_QGlobalStatic::initTestCase()
+{
+#if defined(Q_OS_UNIX)
+    // The tests create a lot of threads, which require file descriptors. On systems like
+    // OS X low defaults such as 256 as the limit for the number of simultaneously
+    // open files is not sufficient.
+    struct rlimit numFiles;
+    if (getrlimit(RLIMIT_NOFILE, &numFiles) == 0 && numFiles.rlim_cur < 1024) {
+        numFiles.rlim_cur = qMin(rlim_t(1024), numFiles.rlim_max);
+        setrlimit(RLIMIT_NOFILE, &numFiles);
+    }
+#endif
+}
+
 Q_GLOBAL_STATIC_WITH_ARGS(const int, constInt, (42))
 Q_GLOBAL_STATIC_WITH_ARGS(volatile int, volatileInt, (-47))
 
diff --git a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
index f792b34d48aa4cff6d784afff7c2a4e4b326a29b..3b730d97f9fadbd520467233acb3b430485296a7 100644
--- a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
+++ b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
@@ -151,7 +151,7 @@ void tst_QBuffer::readBlock()
     QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
     b.open(QIODevice::WriteOnly);
     QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QBuffer): WriteOnly device");
     QCOMPARE(b.read(a, arraySize), (qint64) -1); // no read access
     b.close();
 
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 98963108be187c04f04751f24a4b01f42ea97b3d..5025dd38db28f03b53f6690c8d21ff892e2ce21a 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2334,7 +2334,7 @@ void tst_QFile::readFromWriteOnlyFile()
     QFile file("writeonlyfile");
     QVERIFY(file.open(QFile::WriteOnly));
     char c;
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QFile, \"writeonlyfile\"): WriteOnly device");
     QCOMPARE(file.read(&c, 1), qint64(-1));
 }
 
@@ -2343,7 +2343,7 @@ void tst_QFile::writeToReadOnlyFile()
     QFile file("readonlyfile");
     QVERIFY(file.open(QFile::ReadOnly));
     char c = 0;
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::write (QFile, \"readonlyfile\"): ReadOnly device");
     QCOMPARE(file.write(&c, 1), qint64(-1));
 }
 
diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index f756588e80eb8c14cd9b8a6c19a61f265376b60e..565ca18899edf233a56e98965fec1bf95d726cec 100644
--- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -224,7 +224,7 @@ void tst_QIODevice::unget()
         buf[0] = '@';
         buf[1] = '@';
         QTest::ignoreMessage(QtWarningMsg,
-                              "QIODevice::readLine: Called with maxSize < 2");
+                              "QIODevice::readLine (QBuffer): Called with maxSize < 2");
         QCOMPARE(buffer.readLine(buf, 1), qint64(-1));
         QCOMPARE(buffer.readLine(buf, 2), qint64(i < 4 ? 1 : -1));
         switch (i) {
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
index bef3d3a012875f5360800f154a3d9464888bf30d..27614e0eb8cf863e89c0c0b358890074943fe7ad 100644
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
@@ -57,11 +57,16 @@ private slots:
     void waitForLock();
     void staleLockFromCrashedProcess_data();
     void staleLockFromCrashedProcess();
+    void staleLockFromCrashedProcessReusedPid();
     void staleShortLockFromBusyProcess();
     void staleLongLockFromBusyProcess();
     void staleLockRace();
     void noPermissions();
     void noPermissionsWindows();
+    void corruptedLockFile();
+
+private:
+    static bool overwritePidInLockFile(const QString &filePath, qint64 pid);
 
 public:
     QString m_helperApp;
@@ -276,6 +281,30 @@ void tst_QLockFile::staleLockFromCrashedProcess()
 #endif // !QT_NO_PROCESS
 }
 
+void tst_QLockFile::staleLockFromCrashedProcessReusedPid()
+{
+#if defined(QT_NO_PROCESS)
+    QSKIP("This test requires QProcess support");
+#elif defined(Q_OS_WINRT) || defined(Q_OS_WINCE) || defined(Q_OS_IOS)
+    QSKIP("We cannot retrieve information about other processes on this platform.");
+#else
+    const QString fileName = dir.path() + "/staleLockFromCrashedProcessReusedPid";
+
+    int ret = QProcess::execute(m_helperApp, QStringList() << fileName << "-crash");
+    QCOMPARE(ret, int(QLockFile::NoError));
+    QVERIFY(QFile::exists(fileName));
+    QVERIFY(overwritePidInLockFile(fileName, QCoreApplication::applicationPid()));
+
+    QLockFile secondLock(fileName);
+    qint64 pid = 0;
+    secondLock.getLockInfo(&pid, 0, 0);
+    QCOMPARE(pid, QCoreApplication::applicationPid());
+    secondLock.setStaleLockTime(0);
+    QVERIFY(secondLock.tryLock());
+    QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
+#endif // !QT_NO_PROCESS
+}
+
 void tst_QLockFile::staleShortLockFromBusyProcess()
 {
 #ifdef QT_NO_PROCESS
@@ -480,5 +509,41 @@ void tst_QLockFile::noPermissionsWindows()
     QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
 }
 
+void tst_QLockFile::corruptedLockFile()
+{
+    const QString fileName = dir.path() + "/corruptedLockFile";
+
+    {
+        // Create a empty file. Typically the result of a computer crash or hard disk full.
+        QFile file(fileName);
+        QVERIFY(file.open(QFile::WriteOnly));
+    }
+
+    QLockFile secondLock(fileName);
+    secondLock.setStaleLockTime(100);
+    QVERIFY(secondLock.tryLock(10000));
+    QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
+}
+
+bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid)
+{
+    QFile f(filePath);
+    if (!f.open(QFile::ReadWrite)) {
+        qWarning("Cannot open %s.", qPrintable(filePath));
+        return false;
+    }
+    QByteArray buf = f.readAll();
+    int i = buf.indexOf('\n');
+    if (i < 0) {
+        qWarning("Unexpected lockfile content.");
+        return false;
+    }
+    buf.remove(0, i);
+    buf.prepend(QByteArray::number(pid));
+    f.seek(0);
+    f.resize(buf.size());
+    return f.write(buf) == buf.size();
+}
+
 QTEST_MAIN(tst_QLockFile)
 #include "tst_qlockfile.moc"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index ff4963a960e9fd5c5685ca91493e79824e5b4268..924db17c04552daf32b6989861f47eb8392f884c 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -112,6 +112,22 @@ void tst_QCoreApplication::qAppName()
     // The application name should still be available after destruction;
     // global statics often rely on this.
     QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName));
+
+    // Setting the appname before creating the application should work (QTBUG-45283)
+    const QString wantedAppName("my app name");
+    {
+        int argc = 1;
+        char *argv[] = { const_cast<char*>(appName) };
+        QCoreApplication::setApplicationName(wantedAppName);
+        TestApplication app(argc, argv);
+        QCOMPARE(::qAppName(), QString::fromLatin1(appName));
+        QCOMPARE(QCoreApplication::applicationName(), wantedAppName);
+    }
+    QCOMPARE(QCoreApplication::applicationName(), wantedAppName);
+
+    // Restore to initial value
+    QCoreApplication::setApplicationName(QString());
+    QCOMPARE(QCoreApplication::applicationName(), QString());
 }
 
 void tst_QCoreApplication::argc()
diff --git a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
index 17b00ebf639d6f187667ea50352505cda4af7eda..5a10cf51e6c5fe34c5b404054adc8e582e4f384a 100644
--- a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
+++ b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
@@ -91,5 +91,13 @@ void tst_QMetaEnum::valuesToKeys()
     QCOMPARE(me.valueToKeys(windowFlags), expected);
 }
 
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<tst_QMetaEnum::SuperEnum>::Value);
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::WindowFlags>::Value);
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::Orientation>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<int>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<QObject>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<QObject*>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<void>::Value);
+
 QTEST_MAIN(tst_QMetaEnum)
 #include "tst_qmetaenum.moc"
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index b3333c6d68a8b9c70431491d475b28de41d8b798..9cdb1f47f89b0f65914dc52dffa1216f020bb7fe 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -142,8 +142,14 @@ public:
 class CustomGadget {
     Q_GADGET
 };
+class CustomGadget_NonDefaultConstructible {
+    Q_GADGET
+public:
+    CustomGadget_NonDefaultConstructible(int) {};
+};
 
 class CustomNonQObject {};
+class GadgetDerived : public CustomGadget {};
 
 void tst_QMetaType::defined()
 {
@@ -153,11 +159,12 @@ void tst_QMetaType::defined()
     QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0);
     QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1);
     QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1);
+    QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined);
     QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined));
     QVERIFY(!QMetaTypeId2<CustomQObject>::Defined);
     QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
     QVERIFY(!QMetaTypeId2<CustomNonQObject*>::Defined);
-    QVERIFY(!QMetaTypeId2<CustomGadget*>::Defined);
+    QVERIFY(!QMetaTypeId2<CustomGadget_NonDefaultConstructible>::Defined);
 }
 
 struct Bar
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 263cc5a07a0320d67581907e0053fb73ae902727..3ec84b5198c4bc352b4bd5b5a2a301ca2e868f9d 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -128,6 +128,7 @@ private slots:
     void connectWithReference();
     void connectManyArguments();
     void connectForwardDeclare();
+    void connectNoDefaultConstructorArg();
     void returnValue_data();
     void returnValue();
     void returnValue2_data();
@@ -5227,6 +5228,29 @@ void tst_QObject::connectForwardDeclare()
     QVERIFY(connect(&ob, &ForwardDeclareArguments::mySignal, &ob, &ForwardDeclareArguments::mySlot, Qt::QueuedConnection));
 }
 
+class NoDefaultConstructor
+{
+    Q_GADGET
+public:
+    NoDefaultConstructor(int) {}
+};
+
+class NoDefaultContructorArguments : public QObject
+{
+    Q_OBJECT
+signals:
+    void mySignal(const NoDefaultConstructor&);
+public slots:
+    void mySlot(const NoDefaultConstructor&) {}
+};
+
+void tst_QObject::connectNoDefaultConstructorArg()
+{
+    NoDefaultContructorArguments ob;
+    // it should compile
+    QVERIFY(connect(&ob, &NoDefaultContructorArguments::mySignal, &ob, &NoDefaultContructorArguments::mySlot, Qt::QueuedConnection));
+}
+
 class ReturnValue : public QObject {
 friend class tst_QObject;
 Q_OBJECT
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index cd77b188ccfd04980060c00bdb4b83137eba8460..72bd38d1167a0702472a700e7a80075186678b75 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -312,7 +312,7 @@ void tst_QPluginLoader::loadCorruptElf()
 
 void tst_QPluginLoader::loadMachO_data()
 {
-#ifdef Q_OF_MACH_O
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)
     QTest::addColumn<int>("parseResult");
 
     QTest::newRow("/dev/null") << int(QMachOParser::NotSuitable);
@@ -348,7 +348,7 @@ void tst_QPluginLoader::loadMachO_data()
 
 void tst_QPluginLoader::loadMachO()
 {
-#ifdef Q_OF_MACH_O
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)
     QFile f(QFINDTESTDATA(QTest::currentDataTag()));
     QVERIFY(f.open(QIODevice::ReadOnly));
     QByteArray data = f.readAll();
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 96d0a62f6bbf10c1645b9b50e9d4d88c56543522..1292c3b98f145a06ed0143def0247a962831bca8 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -247,6 +247,9 @@ private slots:
 
     void qtbug_44963();
     void qtbug_44783();
+    void internalTransition();
+    void conflictingTransition();
+    void qtbug_46059();
 };
 
 class TestState : public QState
@@ -256,10 +259,12 @@ public:
         Entry,
         Exit
     };
-    TestState(QState *parent)
-        : QState(parent) {}
-    TestState(ChildMode mode)
-        : QState(mode) {}
+    TestState(QState *parent, const QString &objectName = QString())
+        : QState(parent)
+    { setObjectName(objectName); }
+    TestState(ChildMode mode, const QString &objectName = QString())
+        : QState(mode)
+    { setObjectName(objectName); }
     QList<QPair<int, Event> > events;
 protected:
     virtual void onEntry(QEvent *) {
@@ -273,9 +278,9 @@ protected:
 class TestTransition : public QAbstractTransition
 {
 public:
-    TestTransition(QAbstractState *target)
+    TestTransition(QAbstractState *target, const QString &objectName = QString())
         : QAbstractTransition()
-    { setTargetState(target); }
+    { setTargetState(target); setObjectName(objectName); }
     QList<int> triggers;
 protected:
     virtual bool eventTest(QEvent *) {
@@ -1352,15 +1357,16 @@ void tst_QStateMachine::stateEntryAndExit()
     {
         QStateMachine machine;
 
-        TestState *s1 = new TestState(&machine);
-        TestState *s11 = new TestState(s1);
-        TestState *s12 = new TestState(s1);
-        TestState *s2 = new TestState(&machine);
+        TestState *s1 = new TestState(&machine, "s1");
+        TestState *s11 = new TestState(s1, "s11");
+        TestState *s12 = new TestState(s1, "s12");
+        TestState *s2 = new TestState(&machine, "s2");
         QFinalState *s3 = new QFinalState(&machine);
+        s3->setObjectName("s3");
         s1->setInitialState(s11);
-        TestTransition *t1 = new TestTransition(s12);
+        TestTransition *t1 = new TestTransition(s12, "t1");
         s11->addTransition(t1);
-        TestTransition *t2 = new TestTransition(s2);
+        TestTransition *t2 = new TestTransition(s2, "t2");
         s12->addTransition(t2);
         s2->addTransition(s3);
 
@@ -6335,5 +6341,149 @@ void tst_QStateMachine::qtbug_44783()
     QVERIFY(machine.isRunning());
 }
 
+void tst_QStateMachine::internalTransition()
+{
+    SignalEmitter emitter;
+
+    QStateMachine machine;
+    QState *s = new QState(&machine);
+        QState *s1 = new QState(s);
+            QState *s11 = new QState(s1);
+
+    DEFINE_ACTIVE_SPY(s);
+    DEFINE_ACTIVE_SPY(s1);
+    DEFINE_ACTIVE_SPY(s11);
+
+    machine.setInitialState(s);
+    s->setInitialState(s1);
+    s1->setInitialState(s11);
+    QSignalTransition *t = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s11);
+    t->setObjectName("s1->s11");
+    t->setTransitionType(QAbstractTransition::InternalTransition);
+
+    s->setObjectName("s");
+    s1->setObjectName("s1");
+    s11->setObjectName("s11");
+
+    machine.start();
+
+    QTRY_COMPARE(machine.configuration().contains(s), true);
+    QTRY_COMPARE(machine.configuration().contains(s1), true);
+    QTRY_COMPARE(machine.configuration().contains(s11), true);
+    TEST_ACTIVE_CHANGED(s, 1);
+    TEST_ACTIVE_CHANGED(s1, 1);
+    TEST_ACTIVE_CHANGED(s11, 1);
+
+    emitter.emitSignalWithNoArg();
+
+    QTRY_COMPARE(machine.configuration().contains(s), true);
+    QTRY_COMPARE(machine.configuration().contains(s1), true);
+    QTRY_COMPARE(machine.configuration().contains(s11), true);
+    TEST_ACTIVE_CHANGED(s11, 3);
+    TEST_ACTIVE_CHANGED(s1, 1); // external transitions will return 3, internal transitions should return 1.
+    TEST_ACTIVE_CHANGED(s, 1);
+}
+
+void tst_QStateMachine::conflictingTransition()
+{
+    SignalEmitter emitter;
+
+    QStateMachine machine;
+    QState b(QState::ParallelStates, &machine);
+        QState c(&b);
+        QState d(QState::ParallelStates, &b);
+            QState e(&d);
+                QState e1(&e);
+                QState e2(&e);
+            QState f(&d);
+                QState f1(&f);
+                QState f2(&f);
+    QState a1(&machine);
+
+    machine.setInitialState(&b);
+    e.setInitialState(&e1);
+    f.setInitialState(&f1);
+    c.addTransition(&emitter, SIGNAL(signalWithNoArg()), &a1)->setObjectName("c->a1");
+    e1.addTransition(&emitter, SIGNAL(signalWithNoArg()), &e2)->setObjectName("e1->e2");
+    f1.addTransition(&emitter, SIGNAL(signalWithNoArg()), &f2)->setObjectName("f1->f2");
+
+    b.setObjectName("b");
+    c.setObjectName("c");
+    d.setObjectName("d");
+    e.setObjectName("e");
+    e1.setObjectName("e1");
+    e2.setObjectName("e2");
+    f.setObjectName("f");
+    f1.setObjectName("f1");
+    f2.setObjectName("f2");
+    a1.setObjectName("a1");
+
+    machine.start();
+
+    QTRY_COMPARE(machine.configuration().contains(&b), true);
+    QTRY_COMPARE(machine.configuration().contains(&c), true);
+    QTRY_COMPARE(machine.configuration().contains(&d), true);
+    QTRY_COMPARE(machine.configuration().contains(&e), true);
+    QTRY_COMPARE(machine.configuration().contains(&e1), true);
+    QTRY_COMPARE(machine.configuration().contains(&e2), false);
+    QTRY_COMPARE(machine.configuration().contains(&f), true);
+    QTRY_COMPARE(machine.configuration().contains(&f1), true);
+    QTRY_COMPARE(machine.configuration().contains(&f2), false);
+    QTRY_COMPARE(machine.configuration().contains(&a1), false);
+
+    emitter.emitSignalWithNoArg();
+
+    QTRY_COMPARE(machine.configuration().contains(&b), true);
+    QTRY_COMPARE(machine.configuration().contains(&c), true);
+    QTRY_COMPARE(machine.configuration().contains(&d), true);
+    QTRY_COMPARE(machine.configuration().contains(&e), true);
+    QTRY_COMPARE(machine.configuration().contains(&e1), false);
+    QTRY_COMPARE(machine.configuration().contains(&e2), true);
+    QTRY_COMPARE(machine.configuration().contains(&f), true);
+    QTRY_COMPARE(machine.configuration().contains(&f1), false);
+    QTRY_COMPARE(machine.configuration().contains(&f2), true);
+    QTRY_COMPARE(machine.configuration().contains(&a1), false);
+
+    QVERIFY(machine.isRunning());
+}
+
+void tst_QStateMachine::qtbug_46059()
+{
+    QStateMachine machine;
+    QState a(&machine);
+        QState b(&a);
+        QState c(&a);
+        QState success(&a);
+    QState failure(&machine);
+
+    machine.setInitialState(&a);
+    a.setInitialState(&b);
+    b.addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), &c));
+    c.addTransition(new EventTransition(QEvent::Type(QEvent::User + 2), &success));
+    b.addTransition(new EventTransition(QEvent::Type(QEvent::User + 2), &failure));
+
+    machine.start();
+    QCoreApplication::processEvents();
+
+    QTRY_COMPARE(machine.configuration().contains(&a), true);
+    QTRY_COMPARE(machine.configuration().contains(&b), true);
+    QTRY_COMPARE(machine.configuration().contains(&c), false);
+    QTRY_COMPARE(machine.configuration().contains(&failure), false);
+    QTRY_COMPARE(machine.configuration().contains(&success), false);
+
+    machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 0)), QStateMachine::HighPriority);
+    machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)), QStateMachine::HighPriority);
+    machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 2)), QStateMachine::NormalPriority);
+    QCoreApplication::processEvents();
+
+    QTRY_COMPARE(machine.configuration().contains(&a), true);
+    QTRY_COMPARE(machine.configuration().contains(&b), false);
+    QTRY_COMPARE(machine.configuration().contains(&c), false);
+    QTRY_COMPARE(machine.configuration().contains(&failure), false);
+    QTRY_COMPARE(machine.configuration().contains(&success), true);
+
+    QVERIFY(machine.isRunning());
+}
+
 QTEST_MAIN(tst_QStateMachine)
 #include "tst_qstatemachine.moc"
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm b/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm
index c2b76cc41a16e38a5f989af4b86a9a32769a419f..95d05904a2b9b8dfc8073bde1e083c4335bb2cda 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray_mac.mm
@@ -72,35 +72,31 @@ void tst_QByteArray_macTypes()
     }
     // QByteArray <-> NSData
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         QByteArray qtByteArray("test bytearray");
         const NSData *nsData = qtByteArray.toNSData();
         QCOMPARE(QByteArray::fromNSData(nsData), qtByteArray);
-        [autoreleasepool release];
     }
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         QByteArray qtByteArray("test bytearray");
         const NSData *nsData = qtByteArray.toNSData();
         QByteArray qtByteArrayCopy(qtByteArray);
         qtByteArray = qtByteArray.toUpper(); // modify
         QCOMPARE(QByteArray::fromNSData(nsData), qtByteArrayCopy);
-        [autoreleasepool release];
     }
     // QByteArray <-> NSData Raw
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         QByteArray qtByteArray("test bytearray");
         const NSData *nsData = qtByteArray.toRawNSData();
         QCOMPARE([nsData bytes], qtByteArray.constData());
-        [autoreleasepool release];
     }
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         const char data[] = "nsdata test";
         const NSData *nsData = [NSData dataWithBytes:data length:sizeof(data)];
         QByteArray qtByteArray = QByteArray::fromRawNSData(nsData);
         QCOMPARE(qtByteArray.constData(), [nsData bytes]);
-        [autoreleasepool release];
     }
 }
diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
index 01855a730e10fee7c8a2bf1b642f62e411cc8327..76687bd478f76c86692269aee60ed1e355056f05 100644
--- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
+++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -43,6 +43,8 @@ class tst_QContiguousCache : public QObject
 {
     Q_OBJECT
 private slots:
+    void assignment();
+
     void empty();
     void swap();
 
@@ -64,6 +66,16 @@ private slots:
 
 QTEST_MAIN(tst_QContiguousCache)
 
+void tst_QContiguousCache::assignment()
+{
+    // compile-only test: QTBUG-45783
+   QContiguousCache<int> cc1, cc2;
+   // copy:
+   cc1 = cc2;
+   // move:
+   cc1 = qMove(cc2);
+}
+
 void tst_QContiguousCache::empty()
 {
     QContiguousCache<int> c(10);
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm b/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm
index 6bdaa94e49e633a2d80b4db3f57de99ae0050003..0ad9a8253b03359eba25edb83530bab08a96b232 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm
@@ -56,19 +56,17 @@ void tst_QDateTime_macTypes()
     }
     // QDateTime <-> NSDate
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         QDateTime qtDateTime = QDateTime::fromMSecsSinceEpoch(0);
         const NSDate *nsDate = qtDateTime.toNSDate();
         QCOMPARE(QDateTime::fromNSDate(nsDate), qtDateTime);
-        [autoreleasepool release];
     }
     {
-        NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
         QDateTime qtDateTime = QDateTime::fromMSecsSinceEpoch(0);
         const NSDate *nsDate = qtDateTime.toNSDate();
         QDateTime qtDateTimeCopy(qtDateTime);
         qtDateTime.setTime_t(10000); // modify
         QCOMPARE(QDateTime::fromNSDate(nsDate), qtDateTimeCopy);
-        [autoreleasepool release];
     }
 }
diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
index 044fdbdee525fdf50a9faedcdb5c1baf335fdce4..f9bca77ed3b2a4f8d1ad237f36e0f6cfcd36f62d 100644
--- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
+++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
@@ -48,6 +48,7 @@ private slots:
     void sizeWhenReserved();
     void free();
     void reserveAndRead();
+    void reserveFrontAndRead();
     void chop();
     void ungetChar();
     void indexOf();
@@ -219,6 +220,28 @@ void tst_QRingBuffer::reserveAndRead()
     QVERIFY(ringBuffer.size() == 0);
 }
 
+void tst_QRingBuffer::reserveFrontAndRead()
+{
+    QRingBuffer ringBuffer;
+    // fill buffer with an arithmetic progression
+    for (int i = 1; i < 256; ++i) {
+        QByteArray ba(i, char(i));
+        char *ringPos = ringBuffer.reserveFront(i);
+        QVERIFY(ringPos);
+        memcpy(ringPos, ba.constData(), i);
+    }
+
+    // readback and check stored data
+    for (int i = 255; i > 0; --i) {
+        QByteArray ba;
+        ba.resize(i);
+        qint64 thisRead = ringBuffer.read(ba.data(), i);
+        QCOMPARE(thisRead, qint64(i));
+        QVERIFY(ba.count(char(i)) == i);
+    }
+    QVERIFY(ringBuffer.size() == 0);
+}
+
 void tst_QRingBuffer::chop()
 {
     QRingBuffer ringBuffer;
diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp
index f13d69514af2b050a1fa7f36eed429ea854663cb..ef0ebabd6648d28e98636f790db1a534b6585e10 100644
--- a/tests/auto/corelib/tools/qset/tst_qset.cpp
+++ b/tests/auto/corelib/tools/qset/tst_qset.cpp
@@ -73,6 +73,7 @@ private slots:
     void makeSureTheComfortFunctionsCompile();
     void initializerList();
     void qhash();
+    void intersects();
 };
 
 struct IdentityTracker {
@@ -1030,6 +1031,32 @@ void tst_QSet::qhash()
     }
 }
 
+void tst_QSet::intersects()
+{
+    QSet<int> s1;
+    QSet<int> s2;
+
+    QVERIFY(!s1.intersects(s1));
+    QVERIFY(!s1.intersects(s2));
+
+    s1 << 100;
+    QVERIFY(s1.intersects(s1));
+    QVERIFY(!s1.intersects(s2));
+
+    s2 << 200;
+    QVERIFY(!s1.intersects(s2));
+
+    s1 << 200;
+    QVERIFY(s1.intersects(s2));
+
+    const QtQHashSeedSaver seedSaver(0x10101010);
+    QSet<int> s3;
+    s3 << 500;
+    QVERIFY(!s1.intersects(s3));
+    s3 << 200;
+    QVERIFY(s1.intersects(s3));
+}
+
 QTEST_APPLESS_MAIN(tst_QSet)
 
 #include "tst_qset.moc"
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm b/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm
index f4b748e62ad21078c3ff1c0c448619626a75e233..550f835bea43ac1173272f3fb04c7d3d76c5abb4 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm
+++ b/tests/auto/corelib/tools/qstring/tst_qstring_mac.mm
@@ -55,23 +55,19 @@ void tst_QString_macTypes()
     }
     // QString <-> NSString
     {
-        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
 
         QString qtString("test string");
         const NSString *nsString = qtString.toNSString();
         QCOMPARE(QString::fromNSString(nsString), qtString);
-
-        [pool release];
     }
     {
-        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+        QMacAutoReleasePool pool;
 
         QString qtString("test string");
         const NSString *nsString = qtString.toNSString();
         QString qtStringCopy(qtString);
         qtString = qtString.toUpper(); // modify
         QCOMPARE(QString::fromNSString(nsString), qtStringCopy);
-
-        [pool release];
     }
 }
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index 3f95fa18f65adcd73d4509cbdae582b31a17d0d1..f9f9ac472ae486fdb691c166919002e213ad1f08 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -198,6 +198,8 @@ private slots:
     void clearMovable() const;
     void clearCustom() const;
     void constData() const;
+    void constFirst() const;
+    void constLast() const;
     void contains() const;
     void countInt() const;
     void countMovable() const;
@@ -1222,16 +1224,86 @@ void tst_QVector::first() const
 
     // test it starts ok
     QCOMPARE(myvec.first(), 69);
+    QCOMPARE(myvec.constFirst(), 69);
 
     // test removal changes
     myvec.remove(0);
     QCOMPARE(myvec.first(), 42);
+    QCOMPARE(myvec.constFirst(), 42);
 
     // test prepend changes
     myvec.prepend(23);
     QCOMPARE(myvec.first(), 23);
+    QCOMPARE(myvec.constFirst(), 23);
 }
 
+void tst_QVector::constFirst() const
+{
+    QVector<int> myvec;
+    myvec << 69 << 42 << 3;
+
+    // test it starts ok
+    QCOMPARE(myvec.constFirst(), 69);
+    QVERIFY(myvec.isDetached());
+
+    QVector<int> myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constFirst(), 69);
+    QCOMPARE(myvecCopy.constFirst(), 69);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    // test removal changes
+    myvec.remove(0);
+    QVERIFY(myvec.isDetached());
+    QVERIFY(!myvec.isSharedWith(myvecCopy));
+    QCOMPARE(myvec.constFirst(), 42);
+    QCOMPARE(myvecCopy.constFirst(), 69);
+
+    myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constFirst(), 42);
+    QCOMPARE(myvecCopy.constFirst(), 42);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    // test prepend changes
+    myvec.prepend(23);
+    QVERIFY(myvec.isDetached());
+    QVERIFY(!myvec.isSharedWith(myvecCopy));
+    QCOMPARE(myvec.constFirst(), 23);
+    QCOMPARE(myvecCopy.constFirst(), 42);
+
+    myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constFirst(), 23);
+    QCOMPARE(myvecCopy.constFirst(), 23);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+}
+
+
 template<typename T>
 void tst_QVector::fromList() const
 {
@@ -1409,14 +1481,83 @@ void tst_QVector::last() const
 
     // test starts ok
     QCOMPARE(myvec.last(), QLatin1String("C"));
+    QCOMPARE(myvec.constLast(), QLatin1String("C"));
 
     // test it changes ok
     myvec.append(QLatin1String("X"));
     QCOMPARE(myvec.last(), QLatin1String("X"));
+    QCOMPARE(myvec.constLast(), QLatin1String("X"));
 
     // and remove again
     myvec.remove(3);
     QCOMPARE(myvec.last(), QLatin1String("C"));
+    QCOMPARE(myvec.constLast(), QLatin1String("C"));
+}
+
+void tst_QVector::constLast() const
+{
+    QVector<int> myvec;
+    myvec << 69 << 42 << 3;
+
+    // test it starts ok
+    QCOMPARE(myvec.constLast(), 3);
+    QVERIFY(myvec.isDetached());
+
+    QVector<int> myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constLast(), 3);
+    QCOMPARE(myvecCopy.constLast(), 3);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    // test removal changes
+    myvec.removeLast();
+    QVERIFY(myvec.isDetached());
+    QVERIFY(!myvec.isSharedWith(myvecCopy));
+    QCOMPARE(myvec.constLast(), 42);
+    QCOMPARE(myvecCopy.constLast(), 3);
+
+    myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constLast(), 42);
+    QCOMPARE(myvecCopy.constLast(), 42);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    // test prepend changes
+    myvec.append(23);
+    QVERIFY(myvec.isDetached());
+    QVERIFY(!myvec.isSharedWith(myvecCopy));
+    QCOMPARE(myvec.constLast(), 23);
+    QCOMPARE(myvecCopy.constLast(), 42);
+
+    myvecCopy = myvec;
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
+
+    QCOMPARE(myvec.constLast(), 23);
+    QCOMPARE(myvecCopy.constLast(), 23);
+
+    QVERIFY(!myvec.isDetached());
+    QVERIFY(!myvecCopy.isDetached());
+    QVERIFY(myvec.isSharedWith(myvecCopy));
+    QVERIFY(myvecCopy.isSharedWith(myvec));
 }
 
 void tst_QVector::lastIndexOf() const
diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
index 11c292db9169103708db873810d42743c7c029d6..a07247316e2bf46f6812413f19d9b3d0c5e574f4 100644
--- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
+++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
@@ -39,10 +39,7 @@
 
 #include <QtDBus/private/qdbusutil_p.h>
 #include <QtDBus/private/qdbusconnection_p.h>
-
-#define QT_LINKED_LIBDBUS
-#include <QtDBus/private/qdbusutil_p.h>
-#include <QtDBus/private/qdbusconnection_p.h>
+#include <QtDBus/private/qdbus_symbols_p.h>
 
 static const char serviceName[] = "org.qtproject.autotests.qpong";
 static const char objectPath[] = "/org/qtproject/qpong";
@@ -85,10 +82,8 @@ private slots:
     void sendCallErrors_data();
     void sendCallErrors();
 
-#ifdef DBUS_TYPE_UNIX_FD
     void receiveUnknownType_data();
     void receiveUnknownType();
-#endif
 
     void demarshallPrimitives_data();
     void demarshallPrimitives();
@@ -1017,7 +1012,6 @@ void tst_QDBusMarshall::sendCallErrors()
     QCOMPARE(reply.errorMessage(), errorMsg);
 }
 
-#ifdef DBUS_TYPE_UNIX_FD
 // If DBUS_TYPE_UNIX_FD is not defined, it means the current system's D-Bus library is too old for this test
 void tst_QDBusMarshall::receiveUnknownType_data()
 {
@@ -1075,6 +1069,27 @@ public:
     }
 };
 
+// mostly the same as qdbusintegrator.cpp:connectionCapabilies
+static bool canSendUnixFd(DBusConnection *connection)
+{
+    typedef dbus_bool_t (*can_send_type_t)(DBusConnection *, int);
+    static can_send_type_t can_send_type = 0;
+
+#if defined(QT_LINKED_LIBDBUS)
+# if DBUS_VERSION-0 >= 0x010400
+    can_send_type = dbus_connection_can_send_type;
+# endif
+#else
+    // run-time check if the next functions are available
+    can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type");
+#endif
+
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+#endif
+    return can_send_type && can_send_type(connection, DBUS_TYPE_UNIX_FD);
+}
+
 void tst_QDBusMarshall::receiveUnknownType()
 {
     QDBusConnection con = QDBusConnection::sessionBus();
@@ -1088,7 +1103,8 @@ void tst_QDBusMarshall::receiveUnknownType()
     QVERIFY2(rawcon.data(), error.name);
 
     // check if this bus supports passing file descriptors
-    if (!q_dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD))
+
+    if (!canSendUnixFd(rawcon.data()))
         QSKIP("Your session bus does not allow sending Unix file descriptors");
 
     // make sure this QDBusConnection won't handle Unix file descriptors
@@ -1184,7 +1200,6 @@ void tst_QDBusMarshall::receiveUnknownType()
         QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId);
     }
 }
-#endif
 
 void tst_QDBusMarshall::demarshallPrimitives_data()
 {
diff --git a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
index ced73dbf3b1fc553c86f629fee759cb772b82d52..63444b61ad9b33d3082b53338d03d69369045433 100644
--- a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
+++ b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
@@ -87,8 +87,19 @@ static void addFixedTypes()
     QTest::newRow("int64") << DBUS_TYPE_INT64_AS_STRING << true << true;
     QTest::newRow("uint64") << DBUS_TYPE_UINT64_AS_STRING << true << true;
     QTest::newRow("double") << DBUS_TYPE_DOUBLE_AS_STRING << true << true;
+
 #ifdef DBUS_TYPE_UNIX_FD_AS_STRING
-    QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
+#  ifndef QT_LINKED_LIBDBUS
+    // We have got the macro from dbus_minimal_p.h, so we need to check if
+    // the library recognizes this as valid type first.
+    // The following function was added for Unix FD support, so if it is
+    // present, so is support for Unix FDs.
+    bool supportsUnixFds = qdbus_resolve_conditionally("dbus_connection_can_send_type");
+#  else
+    bool supportsUnixFds = true;
+#  endif
+    if (supportsUnixFds)
+        QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
 #endif
 }
 
diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..97deae3e253e9c3463d0cec502a835a00400215b
Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg differ
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 2931185c8b536c2c09aa3206aca71bea84dfd384..da29a57f98c2602129fb8655cf4b7a584802abd8 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -184,6 +184,8 @@ private slots:
     void exifOrientation_data();
     void exifOrientation();
 
+    void exif_QTBUG45865();
+
     void cleanupFunctions();
 
     void devicePixelRatio();
@@ -2816,31 +2818,56 @@ void tst_QImage::invertPixelsRGB()
 void tst_QImage::exifOrientation_data()
 {
     QTest::addColumn<QString>("fileName");
-    QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg";
-    QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg";
-    QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg";
-    QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg";
-    QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg";
-    QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg";
-    QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg";
-    QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg";
-    QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg";
-}
+    QTest::addColumn<int>("orientation");
+    QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg" << (int)QImageIOHandler::TransformationNone;
+    QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg" << (int)QImageIOHandler::TransformationMirror;
+    QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg" << (int)QImageIOHandler::TransformationRotate180;
+    QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg" << (int)QImageIOHandler::TransformationFlip;
+    QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg" << (int)QImageIOHandler::TransformationFlipAndRotate90;
+    QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg" << (int)QImageIOHandler::TransformationRotate90;
+    QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg" << (int)QImageIOHandler::TransformationRotate90;
+    QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg" << (int)QImageIOHandler::TransformationMirrorAndRotate90;
+    QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg" << (int)QImageIOHandler::TransformationRotate270;
+}
+
+QT_BEGIN_NAMESPACE
+extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
+QT_END_NAMESPACE
+QT_USE_NAMESPACE
 
 void tst_QImage::exifOrientation()
 {
     QFETCH(QString, fileName);
+    QFETCH(int, orientation);
 
-    QImage img;
+    QImageReader imageReader(fileName);
+    imageReader.setAutoTransform(true);
+    QCOMPARE(imageReader.transformation(), orientation);
+    QImage img = imageReader.read();
     QRgb px;
-
-    QVERIFY(img.load(fileName));
+    QVERIFY(!img.isNull());
 
     px = img.pixel(0, 0);
     QVERIFY(qRed(px) > 250 && qGreen(px) < 5 && qBlue(px) < 5);
 
     px = img.pixel(img.width() - 1, 0);
     QVERIFY(qRed(px) < 5 && qGreen(px) < 5 && qBlue(px) > 250);
+
+    QImageReader imageReader2(fileName);
+    QCOMPARE(imageReader2.autoTransform(), false);
+    QCOMPARE(imageReader2.transformation(), orientation);
+    QImage img2 = imageReader2.read();
+    qt_imageTransform(img2, imageReader2.transformation());
+    QCOMPARE(img, img2);
+}
+
+void tst_QImage::exif_QTBUG45865()
+{
+    QFile file(m_prefix + "jpeg_exif_QTBUG-45865.jpg");
+    QVERIFY(file.open(QIODevice::ReadOnly));
+    QByteArray byteArray = file.readAll();
+    QImage image = QImage::fromData(byteArray);
+    QCOMPARE(image.size(), QSize(5, 8));
 }
 
 static void cleanupFunction(void* info)
diff --git a/tests/auto/gui/kernel/qtouchevent/BLACKLIST b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
new file mode 100644
index 0000000000000000000000000000000000000000..8e78d7e41f5fa41749888b184470d27cc2dd0522
--- /dev/null
+++ b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
@@ -0,0 +1,6 @@
+[basicRawEventTranslation]
+linux
+[multiPointRawEventTranslationOnTouchScreen]
+linux
+[multiPointRawEventTranslationOnTouchPad]
+linux
diff --git a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
index 713661116594125f2124633f963bc4aa0c480eeb..b1e3c107242a3244d5f13081ae40eb33231ee4c0 100644
--- a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
+++ b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
@@ -1,3 +1,5 @@
+CONFIG += testcase
+osx: CONFIG += insignificant_test # QTBUG-46266, crashes
 SOURCES=tst_qtouchevent.cpp
 TARGET=tst_qtouchevent
 QT += testlib widgets gui-private
diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
index fe11f39242d7239aba254d79eee16cf67e67c8d1..aa1f573aa94043840b381f9521b5b34944e039ff 100644
--- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
@@ -31,11 +31,16 @@
 **
 ****************************************************************************/
 
-#include <QtGui>
-#include <QtWidgets>
+#include <QtWidgets/QDesktopWidget>
+#include <QtWidgets/QGraphicsItem>
+#include <QtWidgets/QGraphicsScene>
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QGraphicsWidget>
+#include <QtWidgets/QWidget>
 #include <QtTest>
 #include <qpa/qwindowsysteminterface.h>
 
+// FIXME: Use static functions of QWindowSystemInterface introduced with HighDPI scaling in 5.6 instead.
 static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt)
 {
     QWindowSystemInterface::TouchPoint p;
@@ -72,8 +77,7 @@ public:
     ulong timestamp;
     QTouchDevice *deviceFromEvent;
 
-    tst_QTouchEventWidget()
-        : QWidget()
+    explicit tst_QTouchEventWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
     {
         reset();
     }
@@ -88,7 +92,7 @@ public:
         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
     }
 
-    bool event(QEvent *event)
+    bool event(QEvent *event) Q_DECL_OVERRIDE
     {
         switch (event->type()) {
         case QEvent::TouchBegin:
@@ -142,8 +146,8 @@ public:
     bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
     tst_QTouchEventGraphicsItem **weakpointer;
 
-    tst_QTouchEventGraphicsItem()
-        : QGraphicsItem(), weakpointer(0)
+    explicit tst_QTouchEventGraphicsItem(QGraphicsItem *parent = Q_NULLPTR)
+        : QGraphicsItem(parent), weakpointer(0)
     {
         reset();
     }
@@ -165,10 +169,10 @@ public:
         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
     }
 
-    QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
-    void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) { }
+    QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(0, 0, 10, 10); }
+    void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE { }
 
-    bool sceneEvent(QEvent *event)
+    bool sceneEvent(QEvent *event) Q_DECL_OVERRIDE
     {
         switch (event->type()) {
         case QEvent::TouchBegin:
@@ -214,9 +218,9 @@ class tst_QTouchEvent : public QObject
     Q_OBJECT
 public:
     tst_QTouchEvent();
-    ~tst_QTouchEvent() { }
 
 private slots:
+    void cleanup();
     void touchDisabledByDefault();
     void touchEventAcceptedByDefault();
     void touchBeginPropagatesWhenIgnored();
@@ -236,15 +240,18 @@ private:
     QTouchDevice *touchPadDevice;
 };
 
-tst_QTouchEvent::tst_QTouchEvent()
+tst_QTouchEvent::tst_QTouchEvent() : touchScreenDevice(new QTouchDevice), touchPadDevice(new QTouchDevice)
 {
-    touchScreenDevice = new QTouchDevice;
-    touchPadDevice = new QTouchDevice;
     touchPadDevice->setType(QTouchDevice::TouchPad);
     QWindowSystemInterface::registerTouchDevice(touchScreenDevice);
     QWindowSystemInterface::registerTouchDevice(touchPadDevice);
 }
 
+void tst_QTouchEvent::cleanup()
+{
+    QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
+}
+
 void tst_QTouchEvent::touchDisabledByDefault()
 {
     // QWidget
@@ -261,8 +268,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                touchPoints);
-        bool res = QApplication::sendEvent(&widget, &touchEvent);
-        QVERIFY(!res);
+        QVERIFY(!QApplication::sendEvent(&widget, &touchEvent));
         QVERIFY(!touchEvent.isAccepted());
     }
 
@@ -290,8 +296,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
-        QVERIFY(!res);
+        QVERIFY(!QApplication::sendEvent(view.viewport(), &touchEvent));
         QVERIFY(!touchEvent.isAccepted());
         QVERIFY(!item.seenTouchBegin);
     }
@@ -299,7 +304,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
 
 void tst_QTouchEvent::touchEventAcceptedByDefault()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     // QWidget
@@ -317,16 +322,14 @@ void tst_QTouchEvent::touchEventAcceptedByDefault()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                touchPoints);
-        bool res = QApplication::sendEvent(&widget, &touchEvent);
-        QVERIFY(res);
-        QVERIFY(touchEvent.isAccepted());
+        QVERIFY(QApplication::sendEvent(&widget, &touchEvent));
+        QVERIFY(!touchEvent.isAccepted()); // Qt 5.X ignores touch events.
 
         // tst_QTouchEventWidget does handle, sending succeeds
         tst_QTouchEventWidget touchWidget;
         touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
         touchEvent.ignore();
-        res = QApplication::sendEvent(&touchWidget, &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&touchWidget, &touchEvent));
         QVERIFY(touchEvent.isAccepted());
     }
 
@@ -355,8 +358,7 @@ void tst_QTouchEvent::touchEventAcceptedByDefault()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
         QVERIFY(touchEvent.isAccepted());
         QVERIFY(item.seenTouchBegin);
     }
@@ -383,8 +385,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                touchPoints);
-        bool res = QApplication::sendEvent(&grandchild, &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent));
         QVERIFY(touchEvent.isAccepted());
         QVERIFY(grandchild.seenTouchBegin);
         QVERIFY(child.seenTouchBegin);
@@ -398,8 +399,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
         grandchild.setAttribute(Qt::WA_AcceptTouchEvents, false);
 
         touchEvent.ignore();
-        res = QApplication::sendEvent(&grandchild, &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent));
         QVERIFY(touchEvent.isAccepted());
         QVERIFY(!grandchild.seenTouchBegin);
         QVERIFY(child.seenTouchBegin);
@@ -435,8 +435,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
         QVERIFY(touchEvent.isAccepted());
         QVERIFY(grandchild.seenTouchBegin);
         QVERIFY(child.seenTouchBegin);
@@ -471,8 +470,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
                                Qt::NoModifier,
                                Qt::TouchPointPressed,
                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
         QVERIFY(touchEvent.isAccepted());
         QVERIFY(!grandchild.seenTouchBegin);
         QVERIFY(child.seenTouchBegin);
@@ -499,8 +497,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                     Qt::NoModifier,
                                     Qt::TouchPointPressed,
                                     touchPoints);
-        bool res = QApplication::sendEvent(&child, &touchBeginEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&child, &touchBeginEvent));
         QVERIFY(touchBeginEvent.isAccepted());
         QVERIFY(child.seenTouchBegin);
         QVERIFY(!window.seenTouchBegin);
@@ -511,8 +508,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                      Qt::NoModifier,
                                      Qt::TouchPointMoved,
                                      touchPoints);
-        res = QApplication::sendEvent(&child, &touchUpdateEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&child, &touchUpdateEvent));
         QVERIFY(!touchUpdateEvent.isAccepted());
         QVERIFY(child.seenTouchUpdate);
         QVERIFY(!window.seenTouchUpdate);
@@ -523,8 +519,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                   Qt::NoModifier,
                                   Qt::TouchPointReleased,
                                   touchPoints);
-        res = QApplication::sendEvent(&child, &touchEndEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(&child, &touchEndEvent));
         QVERIFY(!touchEndEvent.isAccepted());
         QVERIFY(child.seenTouchEnd);
         QVERIFY(!window.seenTouchEnd);
@@ -558,8 +553,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                     Qt::NoModifier,
                                     Qt::TouchPointPressed,
                                     (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        bool res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
         QVERIFY(touchBeginEvent.isAccepted());
         QVERIFY(child.seenTouchBegin);
         QVERIFY(!root.seenTouchBegin);
@@ -571,8 +565,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                      Qt::NoModifier,
                                      Qt::TouchPointMoved,
                                      (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
         // the scene accepts the event, since it found an item to send the event to
         QVERIFY(!touchUpdateEvent.isAccepted());
         QVERIFY(child.seenTouchUpdate);
@@ -585,8 +578,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
                                   Qt::NoModifier,
                                   Qt::TouchPointReleased,
                                   (QList<QTouchEvent::TouchPoint>() << touchPoint));
-        res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
-        QVERIFY(res);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
         // the scene accepts the event, since it found an item to send the event to
         QVERIFY(!touchEndEvent.isAccepted());
         QVERIFY(child.seenTouchEnd);
@@ -601,17 +593,20 @@ QPointF normalized(const QPointF &pos, const QRectF &rect)
 
 void tst_QTouchEvent::basicRawEventTranslation()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     tst_QTouchEventWidget touchWidget;
+    touchWidget.setWindowTitle(QTest::currentTestFunction());
     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     touchWidget.setGeometry(100, 100, 400, 300);
+    touchWidget.show();
+    QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
 
     QPointF pos = touchWidget.rect().center();
     QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
     QPointF delta(10, 10);
-    QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+    QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
 
     QTouchEvent::TouchPoint rawTouchPoint;
     rawTouchPoint.setId(0);
@@ -726,24 +721,24 @@ void tst_QTouchEvent::basicRawEventTranslation()
 
 void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     tst_QTouchEventWidget touchWidget;
+    touchWidget.setWindowTitle(QTest::currentTestFunction());
     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     touchWidget.setGeometry(100, 100, 400, 300);
 
-    tst_QTouchEventWidget leftWidget;
-    leftWidget.setParent(&touchWidget);
+    tst_QTouchEventWidget leftWidget(&touchWidget);
     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     leftWidget.setGeometry(0, 100, 100, 100);
-    leftWidget.show();
 
-    tst_QTouchEventWidget rightWidget;
-    rightWidget.setParent(&touchWidget);
+    tst_QTouchEventWidget rightWidget(&touchWidget);
     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     rightWidget.setGeometry(300, 100, 100, 100);
-    rightWidget.show();
+
+    touchWidget.show();
+    QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
 
     QPointF leftPos = leftWidget.rect().center();
     QPointF rightPos = rightWidget.rect().center();
@@ -751,8 +746,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
-    QPointF delta(10, 10);
-    QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+    QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
 
     QList<QTouchEvent::TouchPoint> rawTouchPoints;
     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -956,24 +950,25 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
 
 void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     tst_QTouchEventWidget touchWidget;
+    touchWidget.setWindowTitle(QTest::currentTestFunction());
     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     touchWidget.setGeometry(100, 100, 400, 300);
 
-    tst_QTouchEventWidget leftWidget;
-    leftWidget.setParent(&touchWidget);
+    tst_QTouchEventWidget leftWidget(&touchWidget);
     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     leftWidget.setGeometry(0, 100, 100, 100);
-    leftWidget.show();
+    leftWidget.acceptTouchBegin =true;
 
-    tst_QTouchEventWidget rightWidget;
-    rightWidget.setParent(&touchWidget);
+    tst_QTouchEventWidget rightWidget(&touchWidget);
     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     rightWidget.setGeometry(300, 100, 100, 100);
-    rightWidget.show();
+
+    touchWidget.show();
+    QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
 
     QPointF leftPos = leftWidget.rect().center();
     QPointF rightPos = rightWidget.rect().center();
@@ -981,8 +976,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
-    QPointF delta(10, 10);
-    QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+    QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
 
     QList<QTouchEvent::TouchPoint> rawTouchPoints;
     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -1003,7 +997,8 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
     QVERIFY(!touchWidget.seenTouchBegin);
     QVERIFY(!touchWidget.seenTouchUpdate);
     QVERIFY(!touchWidget.seenTouchEnd);
-    QVERIFY(leftWidget.seenTouchBegin);
+    QEXPECT_FAIL("", "QTBUG-46266, fails in Qt 5", Abort);
+    QVERIFY(!leftWidget.seenTouchBegin);
     QVERIFY(!leftWidget.seenTouchUpdate);
     QVERIFY(!leftWidget.seenTouchEnd);
     QVERIFY(!rightWidget.seenTouchBegin);
@@ -1186,19 +1181,15 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
 
 void tst_QTouchEvent::deleteInEventHandler()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     // QWidget
     {
         QWidget window;
-        tst_QTouchEventWidget *child1, *child2, *child3;
-        child1 = new tst_QTouchEventWidget;
-        child2 = new tst_QTouchEventWidget;
-        child3 = new tst_QTouchEventWidget;
-        child1->setParent(&window);
-        child2->setParent(&window);
-        child3->setParent(&window);
+        QPointer<tst_QTouchEventWidget> child1 = new tst_QTouchEventWidget(&window);
+        QPointer<tst_QTouchEventWidget> child2 = new tst_QTouchEventWidget(&window);
+        QPointer<tst_QTouchEventWidget> child3 = new tst_QTouchEventWidget(&window);
         child1->setAttribute(Qt::WA_AcceptTouchEvents);
         child2->setAttribute(Qt::WA_AcceptTouchEvents);
         child3->setAttribute(Qt::WA_AcceptTouchEvents);
@@ -1223,47 +1214,43 @@ void tst_QTouchEvent::deleteInEventHandler()
                                Qt::NoModifier,
                                Qt::TouchPointReleased,
                                touchPoints);
-        QPointer<QWidget> p;
-        bool res;
-
         touchBeginEvent.ignore();
-        p = child1;
-        res = QApplication::sendEvent(child1, &touchBeginEvent);
+        QVERIFY(QApplication::sendEvent(child1, &touchBeginEvent));
         // event is handled, but widget should be deleted
-        QVERIFY(res && touchBeginEvent.isAccepted() && p.isNull());
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(child1.isNull());
 
         touchBeginEvent.ignore();
-        p = child2;
-        res = QApplication::sendEvent(child2, &touchBeginEvent);
-        QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+        QVERIFY(QApplication::sendEvent(child2, &touchBeginEvent));
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(!child2.isNull());
         touchUpdateEvent.ignore();
-        res = QApplication::sendEvent(child2, &touchUpdateEvent);
-        QVERIFY(res && touchUpdateEvent.isAccepted() && p.isNull());
+        QVERIFY(QApplication::sendEvent(child2, &touchUpdateEvent));
+        QVERIFY(touchUpdateEvent.isAccepted());
+        QVERIFY(child2.isNull());
 
         touchBeginEvent.ignore();
-        p = child3;
-        res = QApplication::sendEvent(child3, &touchBeginEvent);
-        QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+        QVERIFY(QApplication::sendEvent(child3, &touchBeginEvent));
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(!child3.isNull());
         touchUpdateEvent.ignore();
-        res = QApplication::sendEvent(child3, &touchUpdateEvent);
-        QVERIFY(res && touchUpdateEvent.isAccepted() && !p.isNull());
+        QVERIFY(QApplication::sendEvent(child3, &touchUpdateEvent));
+        QVERIFY(touchUpdateEvent.isAccepted());
+        QVERIFY(!child3.isNull());
         touchEndEvent.ignore();
-        res = QApplication::sendEvent(child3, &touchEndEvent);
-        QVERIFY(res && touchEndEvent.isAccepted() && p.isNull());
+        QVERIFY(QApplication::sendEvent(child3, &touchEndEvent));
+        QVERIFY(touchEndEvent.isAccepted());
+        QVERIFY(child3.isNull());
     }
 
     // QGraphicsView
     {
         QGraphicsScene scene;
         QGraphicsView view(&scene);
-        tst_QTouchEventGraphicsItem *root, *child1, *child2, *child3;
-        root = new tst_QTouchEventGraphicsItem;
-        child1 = new tst_QTouchEventGraphicsItem;
-        child2 = new tst_QTouchEventGraphicsItem;
-        child3 = new tst_QTouchEventGraphicsItem;
-        child1->setParentItem(root);
-        child2->setParentItem(root);
-        child3->setParentItem(root);
+        QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem);
+        tst_QTouchEventGraphicsItem *child1 = new tst_QTouchEventGraphicsItem(root.data());
+        tst_QTouchEventGraphicsItem *child2 = new tst_QTouchEventGraphicsItem(root.data());
+        tst_QTouchEventGraphicsItem *child3 = new tst_QTouchEventGraphicsItem(root.data());
         child1->setZValue(1.);
         child2->setZValue(0.);
         child3->setZValue(-1.);
@@ -1274,7 +1261,7 @@ void tst_QTouchEvent::deleteInEventHandler()
         child2->deleteInTouchUpdate = true;
         child3->deleteInTouchEnd = true;
 
-        scene.addItem(root);
+        scene.addItem(root.data());
         view.resize(200, 200);
         view.fitInView(scene.sceneRect());
 
@@ -1302,71 +1289,75 @@ void tst_QTouchEvent::deleteInEventHandler()
                                Qt::NoModifier,
                                Qt::TouchPointReleased,
                                touchPoints);
-        bool res;
 
         child1->weakpointer = &child1;
         touchBeginEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
-        QVERIFY(res && touchBeginEvent.isAccepted() && !child1);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(!child1);
         touchUpdateEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
-        QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+        QVERIFY(!touchUpdateEvent.isAccepted()); // Qt 5.X ignores touch events.
+        QVERIFY(!child1);
         touchEndEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
-        QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+        QVERIFY(!touchUpdateEvent.isAccepted());
+        QVERIFY(!child1);
 
         child2->weakpointer = &child2;
         touchBeginEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
-        QVERIFY(res && touchBeginEvent.isAccepted() && child2);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(child2);
         touchUpdateEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
-        QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+        QVERIFY(!touchUpdateEvent.isAccepted());
+        QVERIFY(!child2);
         touchEndEvent.ignore();
-        res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
-        QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+        QVERIFY(!touchUpdateEvent.isAccepted());
+        QVERIFY(!child2);
 
         child3->weakpointer = &child3;
-        res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
-        QVERIFY(res && touchBeginEvent.isAccepted() && child3);
-        res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
-        QVERIFY(res && !touchUpdateEvent.isAccepted() && child3);
-        res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
-        QVERIFY(res && !touchEndEvent.isAccepted() && !child3);
-
-        delete root;
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+        QVERIFY(touchBeginEvent.isAccepted());
+        QVERIFY(child3);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+        QVERIFY(!touchUpdateEvent.isAccepted());
+        QVERIFY(child3);
+        QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+        QVERIFY(!touchEndEvent.isAccepted());
+        QVERIFY(!child3);
     }
 }
 
 void tst_QTouchEvent::deleteInRawEventTranslation()
 {
-    if (qApp->platformName().toLower() == QLatin1String("wayland"))
+    if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
         QSKIP("Wayland: This fails. Figure out why.");
 
     tst_QTouchEventWidget touchWidget;
+    touchWidget.setWindowTitle(QTest::currentTestFunction());
     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
     touchWidget.setGeometry(100, 100, 300, 300);
 
-    tst_QTouchEventWidget *leftWidget = new tst_QTouchEventWidget;
-    leftWidget->setParent(&touchWidget);
+    QPointer<tst_QTouchEventWidget> leftWidget = new tst_QTouchEventWidget(&touchWidget);
     leftWidget->setAttribute(Qt::WA_AcceptTouchEvents);
     leftWidget->setGeometry(0, 100, 100, 100);
     leftWidget->deleteInTouchBegin = true;
-    leftWidget->show();
 
-    tst_QTouchEventWidget *centerWidget = new tst_QTouchEventWidget;
-    centerWidget->setParent(&touchWidget);
+    QPointer<tst_QTouchEventWidget> centerWidget = new tst_QTouchEventWidget(&touchWidget);
     centerWidget->setAttribute(Qt::WA_AcceptTouchEvents);
     centerWidget->setGeometry(100, 100, 100, 100);
     centerWidget->deleteInTouchUpdate = true;
-    centerWidget->show();
 
-    tst_QTouchEventWidget *rightWidget = new tst_QTouchEventWidget;
-    rightWidget->setParent(&touchWidget);
+    QPointer<tst_QTouchEventWidget> rightWidget = new tst_QTouchEventWidget(&touchWidget);
     rightWidget->setAttribute(Qt::WA_AcceptTouchEvents);
     rightWidget->setGeometry(200, 100, 100, 100);
     rightWidget->deleteInTouchEnd = true;
-    rightWidget->show();
+
+    touchWidget.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
 
     QPointF leftPos = leftWidget->rect().center();
     QPointF centerPos = centerWidget->rect().center();
@@ -1374,9 +1365,7 @@ void tst_QTouchEvent::deleteInRawEventTranslation()
     QPointF leftScreenPos = leftWidget->mapToGlobal(leftPos.toPoint());
     QPointF centerScreenPos = centerWidget->mapToGlobal(centerPos.toPoint());
     QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint());
-    QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
-
-    QPointer<QWidget> pl = leftWidget, pc = centerWidget, pr = rightWidget;
+    QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
 
     QList<QTouchEvent::TouchPoint> rawTouchPoints;
     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -1398,7 +1387,9 @@ void tst_QTouchEvent::deleteInRawEventTranslation()
                                              touchScreenDevice,
                                              touchPointList(rawTouchPoints));
     QCoreApplication::processEvents();
-    QVERIFY(pl.isNull() && !pc.isNull() && !pr.isNull());
+    QVERIFY(leftWidget.isNull());
+    QVERIFY(!centerWidget.isNull());
+    QVERIFY(!rightWidget.isNull());
 
     // generate update events on all widget, the center widget should die
     rawTouchPoints[0].setState(Qt::TouchPointMoved);
@@ -1455,14 +1446,13 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
 {
     QGraphicsScene scene;
     QGraphicsView view(&scene);
-    tst_QTouchEventGraphicsItem *root;
-    root = new tst_QTouchEventGraphicsItem;
+    QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem);
     root->setAcceptTouchEvents(true);
-    scene.addItem(root);
+    scene.addItem(root.data());
 
-    QGraphicsWidget *glassWidget = new QGraphicsWidget;
+    QScopedPointer<QGraphicsWidget> glassWidget(new QGraphicsWidget);
     glassWidget->setMinimumSize(100, 100);
-    scene.addItem(glassWidget);
+    scene.addItem(glassWidget.data());
 
     view.resize(200, 200);
     view.show();
@@ -1478,7 +1468,7 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
             .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
             .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
 
-    QCOMPARE(root->touchBeginCounter, 1);
+    QTRY_COMPARE(root->touchBeginCounter, 1);
     QCOMPARE(root->touchUpdateCounter, 1);
     QCOMPARE(root->touchEndCounter, 1);
     QCOMPARE(root->touchUpdatePoints.size(), 2);
@@ -1498,17 +1488,13 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
     QCOMPARE(root->touchBeginCounter, 0);
     QCOMPARE(root->touchUpdateCounter, 0);
     QCOMPARE(root->touchEndCounter, 0);
-
-
-    delete root;
-    delete glassWidget;
 }
 
 class WindowTouchEventFilter : public QObject
 {
     Q_OBJECT
 public:
-    bool eventFilter(QObject *obj, QEvent *event);
+    bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
     struct TouchInfo {
         QList<QTouchEvent::TouchPoint> points;
         QEvent::Type lastSeenType;
@@ -1537,18 +1523,18 @@ void tst_QTouchEvent::testQGuiAppDelivery()
     device->setType(QTouchDevice::TouchScreen);
     QWindowSystemInterface::registerTouchDevice(device);
 
-    QWindow *w = new QWindow;
-    w->setGeometry(100, 100, 100, 100);
-    w->show();
-    QVERIFY(QTest::qWaitForWindowExposed(w));
+    QWindow w;
+    w.setGeometry(100, 100, 100, 100);
+    w.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&w));
 
     WindowTouchEventFilter filter;
-    w->installEventFilter(&filter);
+    w.installEventFilter(&filter);
 
     QList<QWindowSystemInterface::TouchPoint> points;
 
     // Pass empty list, should be ignored.
-    QWindowSystemInterface::handleTouchEvent(w, 0, points);
+    QWindowSystemInterface::handleTouchEvent(&w, 0, points);
     QCoreApplication::processEvents();
     QCOMPARE(filter.d.isEmpty(), true);
 
@@ -1559,12 +1545,12 @@ void tst_QTouchEvent::testQGuiAppDelivery()
     points.append(tp);
 
     // Pass 0 as device, should be ignored.
-    QWindowSystemInterface::handleTouchEvent(w, 0, points);
+    QWindowSystemInterface::handleTouchEvent(&w, 0, points);
     QCoreApplication::processEvents();
     QCOMPARE(filter.d.isEmpty(), true);
 
     // Now the real thing.
-    QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchBegin
+    QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchBegin
     QCoreApplication::processEvents();
     QCOMPARE(filter.d.count(), 1);
     QCOMPARE(filter.d.contains(device), true);
@@ -1572,7 +1558,7 @@ void tst_QTouchEvent::testQGuiAppDelivery()
     QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchBegin);
 
     points[0].state = Qt::TouchPointMoved;
-    QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchUpdate
+    QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchUpdate
     QCoreApplication::processEvents();
     QCOMPARE(filter.d.count(), 1);
     QCOMPARE(filter.d.contains(device), true);
@@ -1580,7 +1566,7 @@ void tst_QTouchEvent::testQGuiAppDelivery()
     QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchUpdate);
 
     points[0].state = Qt::TouchPointReleased;
-    QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchEnd
+    QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchEnd
     QCoreApplication::processEvents();
     QCOMPARE(filter.d.count(), 1);
     QCOMPARE(filter.d.contains(device), true);
@@ -1597,13 +1583,13 @@ void tst_QTouchEvent::testMultiDevice()
     deviceTwo->setType(QTouchDevice::TouchScreen);
     QWindowSystemInterface::registerTouchDevice(deviceTwo);
 
-    QWindow *w = new QWindow;
-    w->setGeometry(100, 100, 100, 100);
-    w->show();
-    QVERIFY(QTest::qWaitForWindowExposed(w));
+    QWindow w;
+    w.setGeometry(100, 100, 100, 100);
+    w.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&w));
 
     WindowTouchEventFilter filter;
-    w->installEventFilter(&filter);
+    w.installEventFilter(&filter);
 
     QList<QWindowSystemInterface::TouchPoint> pointsOne, pointsTwo;
 
@@ -1620,8 +1606,8 @@ void tst_QTouchEvent::testMultiDevice()
     tp.area = QRectF(140, 140, 20, 20);
     pointsTwo.append(tp);
 
-    QWindowSystemInterface::handleTouchEvent(w, deviceOne, pointsOne);
-    QWindowSystemInterface::handleTouchEvent(w, deviceTwo, pointsTwo);
+    QWindowSystemInterface::handleTouchEvent(&w, deviceOne, pointsOne);
+    QWindowSystemInterface::handleTouchEvent(&w, deviceTwo, pointsTwo);
     QCoreApplication::processEvents();
 
     QCOMPARE(filter.d.contains(deviceOne), true);
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
new file mode 100644
index 0000000000000000000000000000000000000000..ee9709e68ba75bfc29903111087abe31040a059d
--- /dev/null
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -0,0 +1,6 @@
+[positioning:default]
+ubuntu-14.04
+[modalWindowPosition]
+ubuntu-14.04
+[modalWithChildWindow]
+ubuntu-14.04
diff --git a/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp b/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
index 014ed4c7c8c5c4c47b8db1341f914b22c622e24e..c0b0738e2ad178ca68dd3581b334638a89dfe974 100644
--- a/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
+++ b/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
@@ -120,7 +120,7 @@ void tst_QSyntaxHighlighter::cleanup()
 class TestHighlighter : public QSyntaxHighlighter
 {
 public:
-    inline TestHighlighter(const QList<QTextLayout::FormatRange> &fmts, QTextDocument *parent)
+    inline TestHighlighter(const QVector<QTextLayout::FormatRange> &fmts, QTextDocument *parent)
         : QSyntaxHighlighter(parent), formats(fmts), highlighted(false), callCount(0) {}
     inline TestHighlighter(QObject *parent)
         : QSyntaxHighlighter(parent) {}
@@ -138,24 +138,15 @@ public:
                 ++callCount;
             }
 
-            QList<QTextLayout::FormatRange> formats;
+            QVector<QTextLayout::FormatRange> formats;
             bool highlighted;
             int callCount;
             QString highlightedText;
 };
 
-QT_BEGIN_NAMESPACE
-bool operator==(const QTextLayout::FormatRange &lhs, const QTextLayout::FormatRange &rhs)
-{
-    return lhs.start == rhs.start
-        && lhs.length == rhs.length
-        && lhs.format == rhs.format;
-}
-QT_END_NAMESPACE
-
 void tst_QSyntaxHighlighter::basic()
 {
-    QList<QTextLayout::FormatRange> formats;
+    QVector<QTextLayout::FormatRange> formats;
     QTextLayout::FormatRange range;
     range.start = 0;
     range.length = 2;
@@ -179,7 +170,7 @@ void tst_QSyntaxHighlighter::basic()
     QVERIFY(hl->highlighted);
     QVERIFY(lout->documentChangedCalled);
 
-    QVERIFY(doc->begin().layout()->additionalFormats() == formats);
+    QVERIFY(doc->begin().layout()->formats() == formats);
 }
 
 class CommentTestHighlighter : public QSyntaxHighlighter
@@ -222,7 +213,7 @@ void tst_QSyntaxHighlighter::basicTwo()
 
 void tst_QSyntaxHighlighter::removeFormatsOnDelete()
 {
-    QList<QTextLayout::FormatRange> formats;
+    QVector<QTextLayout::FormatRange> formats;
     QTextLayout::FormatRange range;
     range.start = 0;
     range.length = 9;
@@ -237,9 +228,9 @@ void tst_QSyntaxHighlighter::removeFormatsOnDelete()
     QVERIFY(lout->documentChangedCalled);
 
     lout->documentChangedCalled = false;
-    QVERIFY(!doc->begin().layout()->additionalFormats().isEmpty());
+    QVERIFY(!doc->begin().layout()->formats().isEmpty());
     delete hl;
-    QVERIFY(doc->begin().layout()->additionalFormats().isEmpty());
+    QVERIFY(doc->begin().layout()->formats().isEmpty());
     QVERIFY(lout->documentChangedCalled);
 }
 
@@ -405,7 +396,7 @@ void tst_QSyntaxHighlighter::highlightToEndOfDocument2()
 
 void tst_QSyntaxHighlighter::preservePreeditArea()
 {
-    QList<QTextLayout::FormatRange> formats;
+    QVector<QTextLayout::FormatRange> formats;
     QTextLayout::FormatRange range;
     range.start = 0;
     range.length = 8;
@@ -432,12 +423,12 @@ void tst_QSyntaxHighlighter::preservePreeditArea()
     hl->callCount = 0;
 
     cursor.beginEditBlock();
-    layout->setAdditionalFormats(formats);
+    layout->setFormats(formats);
     cursor.endEditBlock();
 
     QCOMPARE(hl->callCount, 1);
 
-    formats = layout->additionalFormats();
+    formats = layout->formats();
     QCOMPARE(formats.count(), 3);
 
     range = formats.at(0);
@@ -483,7 +474,7 @@ void tst_QSyntaxHighlighter::avoidUnnecessaryRehighlight()
 
 void tst_QSyntaxHighlighter::noContentsChangedDuringHighlight()
 {
-    QList<QTextLayout::FormatRange> formats;
+    QVector<QTextLayout::FormatRange> formats;
     QTextLayout::FormatRange range;
     range.start = 0;
     range.length = 10;
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 517f7fe3bde0a3bad36b84aec86a50c2ecae66cd..666bedc8c21a4b07a75545b29ca3607411125b90 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -470,6 +470,9 @@ private Q_SLOTS:
     void ioHttpChangeMaxRedirects();
     void ioHttpRedirectErrors_data();
     void ioHttpRedirectErrors();
+#ifndef QT_NO_SSL
+    void putWithServerClosingConnectionImmediately();
+#endif
 
     // NOTE: This test must be last!
     void parentingRepliesToTheApp();
@@ -4744,18 +4747,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
 class SslServer : public QTcpServer {
     Q_OBJECT
 public:
-    SslServer() : socket(0) {};
+    SslServer() : socket(0), m_ssl(true) {}
     void incomingConnection(qintptr socketDescriptor) {
         QSslSocket *serverSocket = new QSslSocket;
         serverSocket->setParent(this);
 
         if (serverSocket->setSocketDescriptor(socketDescriptor)) {
+            connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+            if (!m_ssl) {
+                emit newPlainConnection(serverSocket);
+                return;
+            }
             QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath();
             if (testDataDir.isEmpty())
                 testDataDir = QCoreApplication::applicationDirPath();
 
             connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
-            connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
             serverSocket->setProtocol(QSsl::AnyProtocol);
             connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
             serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
@@ -4766,11 +4773,12 @@ public:
         }
     }
 signals:
-    void newEncryptedConnection();
+    void newEncryptedConnection(QSslSocket *s);
+    void newPlainConnection(QSslSocket *s);
 public slots:
     void encryptedSlot() {
         socket = (QSslSocket*) sender();
-        emit newEncryptedConnection();
+        emit newEncryptedConnection(socket);
     }
     void readyReadSlot() {
         // for the incoming sockets, not the server socket
@@ -4779,6 +4787,7 @@ public slots:
 
 public:
     QSslSocket *socket;
+    bool m_ssl;
 };
 
 // very similar to ioPostToHttpUploadProgress but for SSL
@@ -4806,7 +4815,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
     QNetworkReplyPtr reply(manager.post(request, sourceFile));
 
     QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
-    connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+    connect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
     connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply.data(), SLOT(ignoreSslErrors()));
 
     // get the request started and the incoming socket connected
@@ -4814,7 +4823,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
     QVERIFY(!QTestEventLoop::instance().timeout());
     QTcpSocket *incomingSocket = server.socket;
     QVERIFY(incomingSocket);
-    disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+    disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
 
     incomingSocket->setReadBufferSize(1*1024);
@@ -8147,6 +8156,159 @@ void tst_QNetworkReply::ioHttpRedirectErrors()
     QCOMPARE(spy.count(), 1);
     QVERIFY(reply->error() == error);
 }
+#ifndef QT_NO_SSL
+
+class PutWithServerClosingConnectionImmediatelyHandler: public QObject
+{
+    Q_OBJECT
+public:
+    bool m_parsedHeaders;
+    QByteArray m_receivedData;
+    QByteArray m_expectedData;
+    QSslSocket *m_socket;
+    PutWithServerClosingConnectionImmediatelyHandler(QSslSocket *s, QByteArray expected) :m_parsedHeaders(false),  m_expectedData(expected), m_socket(s)
+    {
+        m_socket->setParent(this);
+        connect(m_socket, SIGNAL(readyRead()), SLOT(readyReadSlot()));
+        connect(m_socket, SIGNAL(disconnected()), SLOT(disconnectedSlot()));
+    }
+signals:
+    void correctFileUploadReceived();
+    void corruptFileUploadReceived();
+
+public slots:
+    void closeDelayed() {
+        m_socket->close();
+    }
+
+    void readyReadSlot()
+    {
+        QByteArray data = m_socket->readAll();
+        m_receivedData += data;
+        if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) {
+            m_parsedHeaders = true;
+            QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency
+            // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout
+            // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload
+            // This test catches that.
+        }
+
+    }
+    void disconnectedSlot()
+    {
+        if (m_parsedHeaders) {
+            //qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n"));
+            m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data
+        }
+        if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) {
+            // We had received some data but it is corrupt!
+            qDebug() << "CORRUPT" << m_receivedData.count();
+
+            // Use this to track down the pattern of the corruption and conclude the source
+//            QFile a("/tmp/corrupt");
+//            a.open(QIODevice::WriteOnly);
+//            a.write(m_receivedData);
+//            a.close();
+
+//            QFile b("/tmp/correct");
+//            b.open(QIODevice::WriteOnly);
+//            b.write(m_expectedData);
+//            b.close();
+            //exit(1);
+            emit corruptFileUploadReceived();
+        } else {
+            emit correctFileUploadReceived();
+        }
+    }
+};
+
+class PutWithServerClosingConnectionImmediatelyServer: public SslServer
+{
+    Q_OBJECT
+public:
+    int m_correctUploads;
+    int m_corruptUploads;
+    int m_repliesFinished;
+    int m_expectedReplies;
+    QByteArray m_expectedData;
+    PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0)
+    {
+        QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+        QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+    }
+
+public slots:
+    void createHandlerForConnection(QSslSocket* s) {
+        PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData);
+        handler->setParent(this);
+        QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect()));
+        QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt()));
+    }
+    void increaseCorrect() {
+        m_correctUploads++;
+    }
+    void increaseCorrupt() {
+        m_corruptUploads++;
+    }
+    void replyFinished() {
+        m_repliesFinished++;
+        if (m_repliesFinished == m_expectedReplies) {
+            QTestEventLoop::instance().exitLoop();
+        }
+     }
+};
+
+
+
+void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
+{
+    const int numUploads = 40;
+    qint64 wantedSize = 512*1024; // 512 kB
+    QByteArray sourceFile;
+    for (int i = 0; i < wantedSize; ++i) {
+        sourceFile += (char)'a' +(i%26);
+    }
+    bool withSsl = false;
+
+    for (int s = 0; s <= 1; s++) {
+        withSsl = (s == 1);
+        // Test also needs to run several times because of 9c2ecf89
+        for (int j = 0; j < 20; j++) {
+            // emulate a minimal https server
+            PutWithServerClosingConnectionImmediatelyServer server;
+            server.m_ssl = withSsl;
+            server.m_expectedData = sourceFile;
+            server.m_expectedReplies = numUploads;
+            server.listen(QHostAddress(QHostAddress::LocalHost), 0);
+
+            for (int i = 0; i < numUploads; i++) {
+                // create the request
+                QUrl url = QUrl(QString("http%1://127.0.0.1:%2/file=%3").arg(withSsl ? "s" : "").arg(server.serverPort()).arg(i));
+                QNetworkRequest request(url);
+                QNetworkReply *reply = manager.put(request, sourceFile);
+                connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+                connect(reply, SIGNAL(finished()), &server, SLOT(replyFinished()));
+                reply->setParent(&server);
+            }
+
+            // get the request started and the incoming socket connected
+            QTestEventLoop::instance().enterLoop(10);
+
+            //qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" <<numUploads;
+
+            // Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
+            QVERIFY(server.m_correctUploads > 5);
+            // Because actually important is that we don't get any corruption:
+            QCOMPARE(server.m_corruptUploads, 0);
+
+            server.close();
+        }
+    }
+
+
+}
+
+#endif
 
 // NOTE: This test must be last testcase in tst_qnetworkreply!
 void tst_QNetworkReply::parentingRepliesToTheApp()
diff --git a/tests/auto/network/kernel/qhostinfo/BLACKLIST b/tests/auto/network/kernel/qhostinfo/BLACKLIST
deleted file mode 100644
index ea4b64d7c236aa7f06a07f651c5ec00f24dc6b74..0000000000000000000000000000000000000000
--- a/tests/auto/network/kernel/qhostinfo/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-# QTBUG-23837
-[abortHostLookupInDifferentThread]
-opensuse-13.1 64bit
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index 9762e8244c47e603f50cafb03667d01135aa9092..599e475bebdf3011cb55cf9784a64813dfd8d0fd 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -126,7 +126,6 @@ private slots:
     void cache();
 
     void abortHostLookup();
-    void abortHostLookupInDifferentThread();
 protected slots:
     void resultsReady(const QHostInfo &);
 
@@ -621,25 +620,5 @@ public:
     int id;
 };
 
-void tst_QHostInfo::abortHostLookupInDifferentThread()
-{
-    //reset counter
-    lookupsDoneCounter = 0;
-    bool valid = false;
-    int id = -1;
-    QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
-    QVERIFY(!valid);
-    QThread thread;
-    LookupAborter aborter;
-    aborter.id = id;
-    aborter.moveToThread(&thread);
-    connect(&thread, SIGNAL(started()), &aborter, SLOT(abort()));
-    //it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort
-    thread.start();
-    QVERIFY(thread.wait(5000));
-    QTestEventLoop::instance().enterLoop(5);
-    QCOMPARE(lookupsDoneCounter, 0);
-}
-
 QTEST_MAIN(tst_QHostInfo)
 #include "tst_qhostinfo.moc"
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index d95f2fa5469a743913b95f981b83597f00f4bf65..b823b8712561b8e4473c3c08a77d69b078942b18 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -404,8 +404,8 @@ void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthent
 
 void tst_QSslSocket::constructing()
 {
-    const char readNotOpenMessage[] = "QIODevice::read: device not open";
-    const char writeNotOpenMessage[] = "QIODevice::write: device not open";
+    const char readNotOpenMessage[] = "QIODevice::read (QSslSocket): device not open";
+    const char writeNotOpenMessage[] = "QIODevice::write (QSslSocket): device not open";
 
     if (!QSslSocket::supportsSsl())
         return;
@@ -443,13 +443,13 @@ void tst_QSslSocket::constructing()
     QCOMPARE(socket.read(0, 0), qint64(-1));
     QTest::ignoreMessage(QtWarningMsg, readNotOpenMessage);
     QVERIFY(socket.readAll().isEmpty());
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine (QSslSocket): Called with maxSize < 2");
     QCOMPARE(socket.readLine(0, 0), qint64(-1));
     char buf[10];
     QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1));
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek (QSslSocket): Cannot call seek on a sequential device");
     QVERIFY(!socket.reset());
-    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
+    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek (QSslSocket): Cannot call seek on a sequential device");
     QVERIFY(!socket.seek(2));
     QCOMPARE(socket.size(), qint64(0));
     QVERIFY(!socket.waitForBytesWritten(10));
diff --git a/tests/auto/other/baselineexample/baselineexample.pro b/tests/auto/other/baselineexample/baselineexample.pro
deleted file mode 100644
index c1c4b31bfe3c8afcb94eeafebddb535ad39f1794..0000000000000000000000000000000000000000
--- a/tests/auto/other/baselineexample/baselineexample.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2010-12-09T14:55:13
-#
-#-------------------------------------------------
-
-QT       += testlib widgets
-
-TARGET = tst_baselineexample
-CONFIG   += console
-CONFIG   -= app_bundle
-
-TEMPLATE = app
-
-SOURCES += tst_baselineexample.cpp
-DEFINES += SRCDIR=\\\"$$PWD/\\\"
-
-include($$PWD/../../../baselineserver/shared/qbaselinetest.pri)
-DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/other/baselineexample/tst_baselineexample.cpp b/tests/auto/other/baselineexample/tst_baselineexample.cpp
deleted file mode 100644
index 9059989015782000c54e38f611af101733af7c32..0000000000000000000000000000000000000000
--- a/tests/auto/other/baselineexample/tst_baselineexample.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
-
-#include <qbaselinetest.h>
-#include <QPushButton>
-
-class tst_BaselineExample : public QObject
-{
-    Q_OBJECT
-
-public:
-    tst_BaselineExample();
-
-private Q_SLOTS:
-    void testBasicUsage();
-    void testMultipleImages();
-    void testDataDriven_data();
-    void testDataDriven();
-    void testDataDrivenChecksum_data();
-    void testDataDrivenChecksum();
-};
-
-
-tst_BaselineExample::tst_BaselineExample()
-{
-}
-
-
-void tst_BaselineExample::testBasicUsage()
-{
-    // Generate an image:
-    QPushButton b("Press me!");
-    b.resize(100, 50);
-    b.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&b));
-    QImage img1 = b.grab().toImage();
-    QVERIFY(!img1.isNull());
-
-    // Compare it to baseline on server:
-    QBASELINE_CHECK(img1, "button");
-}
-
-
-void tst_BaselineExample::testMultipleImages()
-{
-    QPushButton b("Press me!");
-    b.resize(100, 50);
-    b.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&b));
-    QBASELINE_CHECK(b.grab().toImage(), "text1");
-
-    b.setText("Kick me!");
-    QTest::qWait(50);
-    QBASELINE_CHECK(b.grab().toImage(), "text2");
-}
-
-
-void tst_BaselineExample::testDataDriven_data()
-{
-    QTest::addColumn<QString>("label");
-    QBaselineTest::newRow("short") << "Ok!";
-    QBaselineTest::newRow("long") << "A really long button text that just does not seem to end";
-    QBaselineTest::newRow("empty") << "";
-    QBaselineTest::newRow("signs") << "!@#$%^&*()_";
-    QBaselineTest::newRow("html") << "<b>BOLD</b>";
-}
-
-
-void tst_BaselineExample::testDataDriven()
-{
-    QFETCH(QString, label);
-    QPushButton b(label);
-    b.resize(100, 50);
-    b.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&b));
-    QBASELINE_TEST(b.grab().toImage());
-}
-
-
-void tst_BaselineExample::testDataDrivenChecksum_data()
-{
-    QTest::addColumn<QString>("label");
-
-    const int numItems = 5;
-    const char *tags[numItems] = {"short", "long", "empty", "signs", "html"};
-    const char *labels[numItems] = {"Ok!", "A really long button text that just does not seem to end", "", "!@#$%^&*()_", "<b>BOLD</b>"};
-
-    for (int i = 0; i<numItems; i++) {
-        quint16 checksum = qChecksum(labels[i], qstrlen(labels[i]));
-        QBaselineTest::newRow(tags[i], checksum) << labels[i];
-    }
-}
-
-
-void tst_BaselineExample::testDataDrivenChecksum()
-{
-    QFETCH(QString, label);
-    QPushButton b(label);
-    b.resize(100, 50);
-    b.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&b));
-    QBASELINE_TEST(b.grab().toImage());
-}
-
-
-QTEST_MAIN(tst_BaselineExample);
-
-#include "tst_baselineexample.moc"
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index a5ed4c5f313a0d078130040c31d73abeac128e35..8c911da2e09b0982dbfec1dda5b410cc2c344b26 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -1,7 +1,6 @@
 TEMPLATE=subdirs
 SUBDIRS=\
    # atwrapper \ # QTBUG-19452
-   baselineexample \
    compiler \
    gestures \
    lancelot \
@@ -26,7 +25,6 @@ SUBDIRS=\
    toolsupport \
 
 !qtHaveModule(widgets): SUBDIRS -= \
-   baselineexample \
    gestures \
    lancelot \
    languagechange \
@@ -41,7 +39,6 @@ SUBDIRS=\
    qaccessibilitymac \
 
 !qtHaveModule(network): SUBDIRS -= \
-   baselineexample \
    lancelot \
    networkselftest \
    qnetworkaccessmanager_and_qprogressdialog \
diff --git a/tests/auto/sql/kernel/qsqldatabase/testdata/qtest.mdb b/tests/auto/sql/kernel/qsqldatabase/testdata/qtest.mdb
old mode 100755
new mode 100644
diff --git a/tests/auto/testlib/selftests/blacklisted/BLACKLIST b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
new file mode 100644
index 0000000000000000000000000000000000000000..36b7699cbdc51b428e1b808d6486d07ed3947db4
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
@@ -0,0 +1,12 @@
+[pass]
+*
+[skip]
+*
+[fail]
+*
+[xpass]
+*
+[xfail]
+*
+[messages]
+*
diff --git a/tests/auto/testlib/selftests/blacklisted/blacklisted.pro b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
new file mode 100644
index 0000000000000000000000000000000000000000..5bd22910b14963e76398729cc9c1df0c1ac2eeaa
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
@@ -0,0 +1,7 @@
+SOURCES += tst_blacklisted.cpp
+QT = core testlib-private
+
+mac: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = blacklisted
diff --git a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1df285a51be6d51d9f1b82246bb184c4e41c757
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+#include <private/qtestlog_p.h>
+
+class tst_Blacklisted : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void pass();
+    void skip();
+    void fail();
+    void xfail();
+    void xpass();
+
+    // This test function must be last, as it calls qFatal().
+    void messages();
+};
+
+// All the tests below have been blacklisted in blacklisted/BLACKLIST
+
+void tst_Blacklisted::pass()
+{
+    QVERIFY(true);
+}
+
+void tst_Blacklisted::skip()
+{
+    QSKIP("This test should SKIP");
+}
+
+void tst_Blacklisted::fail()
+{
+    QVERIFY2(false, "This test should BFAIL");
+}
+
+void tst_Blacklisted::xfail()
+{
+    QEXPECT_FAIL("", "This test should XFAIL then BFAIL", Abort);
+    QVERIFY(false);
+}
+
+void tst_Blacklisted::xpass()
+{
+    QEXPECT_FAIL("", "This test should XPASS", Abort);
+    QVERIFY2(true, "This test should XPASS, blacklist ignored for XPASS");
+}
+
+void tst_Blacklisted::messages()
+{
+    qWarning("This is a warning that should not appear in silent test output");
+    QWARN("This is an internal testlib warning that should not appear in silent test output");
+    qDebug("This is a debug message that should not appear in silent test output");
+    qCritical("This is a critical message that should not appear in silent test output");
+    qInfo("This is an info message that should not appear in silent test output");
+    QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
+    qFatal("This is a fatal error message that should still appear in silent test output");
+}
+
+QTEST_MAIN(tst_Blacklisted)
+#include "tst_blacklisted.moc"
diff --git a/tests/auto/testlib/selftests/expected_blacklisted.txt b/tests/auto/testlib/selftests/expected_blacklisted.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3afd93b0ccfcd5c68be2c688fbe13b2df14c06dc
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_blacklisted.txt
@@ -0,0 +1,26 @@
+********* Start testing of tst_Blacklisted *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS   : tst_Blacklisted::initTestCase()
+BPASS  : tst_Blacklisted::pass()
+SKIP   : tst_Blacklisted::skip() This test should SKIP
+   Loc: [tst_blacklisted.cpp(62)]
+BFAIL  : tst_Blacklisted::fail() 'false' returned FALSE. (This test should BFAIL)
+   Loc: [tst_blacklisted.cpp(67)]
+XFAIL  : tst_Blacklisted::xfail() This test should XFAIL then BFAIL
+   Loc: [tst_blacklisted.cpp(73)]
+BPASS  : tst_Blacklisted::xfail()
+XPASS  : tst_Blacklisted::xpass() 'true' returned TRUE unexpectedly. (This test should XPASS, blacklist ignored for XPASS)
+   Loc: [tst_blacklisted.cpp(79)]
+QWARN  : tst_Blacklisted::messages() This is a warning that should not appear in silent test output
+WARNING: tst_Blacklisted::messages() This is an internal testlib warning that should not appear in silent test output
+   Loc: [tst_blacklisted.cpp(85)]
+QDEBUG : tst_Blacklisted::messages() This is a debug message that should not appear in silent test output
+QSYSTEM: tst_Blacklisted::messages() This is a critical message that should not appear in silent test output
+QINFO  : tst_Blacklisted::messages() This is an info message that should not appear in silent test output
+INFO   : tst_Blacklisted::messages() This is an internal testlib info message that should not appear in silent test output
+   Loc: [tst_blacklisted.cpp(89)]
+QFATAL : tst_Blacklisted::messages() This is a fatal error message that should still appear in silent test output
+BFAIL  : tst_Blacklisted::messages() Received a fatal error.
+   Loc: [Unknown file(0)]
+Totals: 1 passed, 1 failed, 1 skipped, 4 blacklisted
+********* Finished testing of tst_Blacklisted *********
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 7b706735a9a1d89c0736e47f735098759cd60e50..7404a1c49bee441afb6f37efa624f4fd37df2845 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -8,6 +8,7 @@ SUBPROGRAMS = \
      benchliboptions \
      benchlibtickcounter \
      benchlibwalltime \
+     blacklisted \
      cmptest \
      commandlinedata \
      counting \
diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc
index ba567f1fb490977d69d3bcde488c3e6e402adb52..715e255e762d257d65aa519278c7597be5faae95 100644
--- a/tests/auto/testlib/selftests/selftests.qrc
+++ b/tests/auto/testlib/selftests/selftests.qrc
@@ -151,5 +151,6 @@
         <file>expected_xunit.txt</file>
         <file>expected_xunit.xml</file>
         <file>expected_xunit.xunitxml</file>
+        <file>expected_blacklisted.txt</file>
     </qresource>
 </RCC>
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index a5840d16d226a99de0ddec6d8e394e2ac2543ac8..5e97a9cfe4e118b9d3c9c64c8f8a6a29aee392a9 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -352,6 +352,7 @@ void tst_Selftests::runSubTest_data()
         << "benchlibcounting"
         << "benchlibeventcounter"
         << "benchliboptions"
+        << "blacklisted"
         << "cmptest"
         << "commandlinedata"
         << "counting"
@@ -470,6 +471,9 @@ void tst_Selftests::runSubTest_data()
                 if (subtest == "benchliboptions") {
                     continue;
                 }
+                if (subtest == "blacklisted") {
+                    continue;
+                }
                 if (subtest == "printdatatags") {
                     continue;
                 }
@@ -503,7 +507,8 @@ void tst_Selftests::runSubTest_data()
 
             const bool crashes = subtest == QLatin1String("assert") || subtest == QLatin1String("exceptionthrow")
                 || subtest == QLatin1String("fetchbogus") || subtest == QLatin1String("crashedterminate")
-                || subtest == QLatin1String("crashes") || subtest == QLatin1String("silent");
+                || subtest == QLatin1String("crashes") || subtest == QLatin1String("silent")
+                || subtest == QLatin1String("blacklisted");
             QTest::newRow(qPrintable(QString("%1 %2").arg(subtest).arg(loggerSet.name)))
                 << subtest
                 << loggers
@@ -612,6 +617,7 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
         && subdir != QLatin1String("fetchbogus")
         && subdir != QLatin1String("xunit")
 #ifdef Q_CC_MINGW
+        && subdir != QLatin1String("blacklisted") // calls qFatal()
         && subdir != QLatin1String("silent") // calls qFatal()
 #endif
         && subdir != QLatin1String("benchlibcallgrind"))
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 00e5c60b29c0ec56b15c7cecfac64c7198936c63..350c6142d204c9d4702d446cdb60844f9ab51efb 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -87,6 +87,18 @@ struct QTBUG_31218_Derived : QTBUG_31218<-1<0> {};
  class QTBUG_45790 : Bug() { };
 #endif
 
+class CreatableGadget
+{
+    Q_GADGET
+public:
+    Q_INVOKABLE CreatableGadget()
+    {
+        CreatableGadget::qt_static_metacall((QObject*)this, QMetaObject::ReadProperty, -1, Q_NULLPTR);
+    }
+};
+
+CreatableGadget creatableGadget; // Force the compiler to use the constructor
+
 struct MyStruct {};
 struct MyStruct2 {};
 
@@ -680,7 +692,7 @@ void tst_Moc::oldStyleCasts()
 
     QStringList args;
     args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
-         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
     proc.start("gcc", args);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -750,7 +762,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension()
 
     QStringList args;
     args << "-c" << "-x" << "c++" << "-I" << ".."
-         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" <<  "-";
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" <<  "-";
     proc.start("gcc", args);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -1029,7 +1041,7 @@ void tst_Moc::ignoreOptionClashes()
     // If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
     QStringList gccArgs;
     gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
-         << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIE" <<  "-";
+         << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIC" <<  "-";
     proc.start("gcc", gccArgs);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -1870,6 +1882,13 @@ void tst_Moc::warnings_data()
         << 1
         << QString()
         << QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro.");
+
+    QTest::newRow("QTBUG-46210: crash on invalid macro")
+        << QByteArray("#define Foo(a, b, c) a b c #a #b #c a##b##c #d\n Foo(45);")
+        << QStringList()
+        << 1
+        << QString("IGNORE_ALL_STDOUT")
+        << QString(":2: Error: '#' is not followed by a macro parameter");
 }
 
 void tst_Moc::warnings()
diff --git a/tests/auto/tools/qmake/qmake.pro b/tests/auto/tools/qmake/qmake.pro
index 5ed3073e2018e2761ea835e1927e829f3faf3345..d0817247db9fd1797a0294a60afcaea55140a4e7 100644
--- a/tests/auto/tools/qmake/qmake.pro
+++ b/tests/auto/tools/qmake/qmake.pro
@@ -8,5 +8,11 @@ SOURCES += tst_qmake.cpp testcompiler.cpp
 QT = core testlib
 
 cross_compile: DEFINES += QMAKE_CROSS_COMPILED
+debug_and_release {
+    CONFIG(debug, debug|release): \
+        DEFINES += DEBUG_BUILD
+    else: \
+        DEFINES += RELEASE_BUILD
+}
 
 TESTDATA += testdata/*
diff --git a/tests/auto/tools/qmake/testdata/comments/comments.pro b/tests/auto/tools/qmake/testdata/comments/comments.pro
deleted file mode 100644
index 510ab95ab39b2df0f8d28b1dd0274c56ac0138a7..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/comments/comments.pro
+++ /dev/null
@@ -1,31 +0,0 @@
-LIST = 1 2 3 4 #a comment
-!equals( LIST, 1 2 3 4 ) {
-   message( "FAILED: inline comment" )
-}
-
-LIST = 1 \
-       2 \
-#      3 \
-       4
-!equals( LIST, 1 2 4 ) {
-   message( "FAILED: commented out continuation" )
-}
-
-LIST = 1 \
-       2 \#comment
-       3 \
-       4
-!equals( LIST, 1 2 3 4 ) {
-    message( "FAILED: comment at end of continuation")
-}
-
-
-LIST = 1 2 3 4#comment
-!equals( LIST, 1 2 3 4 ) {
-    message( "FAILED: no space before comment" )
-}
-
-LIST = 1 2 3 4$${LITERAL_HASH}five
-!equals( LIST, 1 2 3 4$${LITERAL_HASH}five ) {
-    message( "FAILED: using LITERAL_HASH" )
-}
diff --git a/tests/auto/tools/qmake/testdata/func_export/func_export.pro b/tests/auto/tools/qmake/testdata/func_export/func_export.pro
deleted file mode 100644
index fc3818985b42272cbb312af949de4ec14bb0a4b3..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/func_export/func_export.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-defineTest(doExport) {
-        EXPORTED += $$1
-        export(EXPORTED)
-}
-
-defineTest(callDoExport) {
-        doExport(bar)
-        doExport(baz)
-        EXPORTED = oink
-        !isEqual(EXPORTED, "oink") {
-           message( "FAILED: function-scope exports [$$EXPORTED] != oink" )
-        }
-}
-
-doExport(foo)
-callDoExport()
-!isEqual(EXPORTED, "foo bar baz") {
-   message( "FAILED: global-scope exports [$$EXPORTED] != foo bar baz" )   
-}
diff --git a/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro b/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro
deleted file mode 100644
index cc13437f4a164610a0c4bb7570823ce4103eac25..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro
+++ /dev/null
@@ -1,49 +0,0 @@
-defineTest(testVariable) {
-    varname=$$1
-    value=$$eval($$varname)
-    RESULT=$$value
-    export(RESULT)
-}
-
-defineTest(callTest) {
-    myvar=$$1
-    testVariable(myvar)
-}
-
-defineTest(callTestExport) {
-    myvar=$$1
-    export(myvar)
-    testVariable(myvar)
-}
-
-defineTest(callTestExportChange) {
-    myvar=foo
-    export(myvar)
-    myvar=$$1
-    testVariable(myvar)
-}
-
-value=direct
-myvar=$$value
-testVariable(myvar)
-!isEqual(RESULT,$$value) {
-   message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=export
-callTestExport($$value)
-!isEqual(RESULT,$$value) {
-   message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=export_and_change
-callTestExportChange($$value)
-!isEqual(RESULT,$$value) {
-   message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=local
-callTest($$value)
-!isEqual(RESULT,$$value) {
-   message( "FAILED: result [$$RESULT] != $$value" )
-}
diff --git a/tests/auto/tools/qmake/testdata/functions/functions.pro b/tests/auto/tools/qmake/testdata/functions/functions.pro
deleted file mode 100644
index 5db80361885b0c4a5deb5d887c41cee35be594cd..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/functions.pro
+++ /dev/null
@@ -1,184 +0,0 @@
-VAR = qt thread
-
-defineTest(testReplace) {
-    !isEqual(1, $$2):message("FAILED: $$3: got $$1, expected $${2}.")
-}
-
-#count
-!count( VAR, 2 ) {
-   message( "FAILED: count function: $$VAR" )
-}
-
-#contains
-!contains( VAR, thread ) {
-   message( "FAILED: contains function: $$VAR" )
-}
-
-#exists
-!exists( functions.pro ) {
-   message( "FAILED: exists function" )
-}
-
-#isEmpty
-isEmpty( VAR ) {
-   message( "FAILED: isEmpty function: $VAR" )
-}
-
-#files
-!equals($$list($$files(one/*.cpp)), "one/1.cpp one/2.cpp") {
-   message( "FAILED: files function: one/*.cpp" )
-}
-!equals($$list($$files(one/1*.cpp)), "one/1.cpp") {
-   message( "FAILED: files function: one/1*.cpp" )
-}
-!equals($$list($$files(two/*.cpp)), "two/1.cpp two/2.cpp") {
-   message( "FAILED: files function: two/*.cpp" )
-}
-!equals($$list($$files(three/wildcard*.cpp)), "three/wildcard21.cpp three/wildcard22.cpp") {
-   message( "FAILED: files function: three/wildcard*.cpp" )
-}
-!equals($$list($$files(*.cpp)), "1.cpp 2.cpp wildcard21.cpp wildcard22.cpp") {
-   message( "FAILED: files function: *.cpp" )
-}
-!equals($$list($$files(wildcard*.cpp)), "wildcard21.cpp wildcard22.cpp") {
-   message( "FAILED: files function: wildcard*.cpp" )
-}
-
-#infile
-!infile( infiletest.pro, DEFINES, QT_DLL ){
-   message( "FAILED: infile function" )
-}
-
-#include
-include( infiletest.pro, "", true ) 
-!contains( DEFINES, QT_DLL ) {
-   message( "FAILED: include function: $$DEFINES" )
-}
-
-#replace
-VERSION=1.0.0
-VERSION_replaced=$$replace(VERSION,\\.,_)
-!isEqual(VERSION_replaced, 1_0_0) {
-   message( "FAILED: replace function: $$VERSION_replaced" )
-}
-
-#test functions
-defineTest(myTestFunction) {
-   RESULT =
-   list=$$1
-   for(l, list) {
-       RESULT += $$l
-   }
-   export(RESULT)
-}
-myTestFunction(oink baa moo)
-!equals($$list($$member(RESULT, 0)), "oink") {
-     message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction("oink baa" moo)
-!equals($$list($$member(RESULT, 0)), "oink baa") {
-     message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction(oink "baa moo")
-!equals($$list($$member(RESULT, 0)), "oink") {
-     message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction("oink baa moo")
-!equals($$list($$member(RESULT, 0)), "oink baa moo") {
-     message("FAILED: myTestFunction: $$RESULT")
-}
-
-#recursive
-defineReplace(myRecursiveReplaceFunction) {
-    RESULT =
-    list = $$1
-    RESULT += $$member(list, 0)
-    list -= $$RESULT
-    !isEmpty(list):RESULT += $$myRecursiveReplaceFunction($$list)
-    return($$RESULT)
-}
-RESULT = $$myRecursiveReplaceFunction(oink baa moo)
-!isEqual(RESULT, "oink baa moo") {
-    message( "FAILED: myRecursiveReplaceFunction [$$RESULT] != oink baa moo" )
-}
-
-moo = "this is a test" "for real"
-fn = $$OUT_PWD/testdir/afile
-write_file($$fn, moo)|message("FAILED: write_file() failed")
-exists($$fn)|message("FAILED: write_file() didn't write anything")
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong")
-moo += "another line"
-write_file($$fn, moo)|message("FAILED: write_file() failed (take 2)")
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong (take 2)")
-mooadd = "yet another line"
-write_file($$fn, mooadd, append)|message("FAILED: write_file() failed (append)")
-moo += $$mooadd
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong when appending")
-
-pn = $$OUT_PWD/testpath/subdir
-mkpath($$pn)|message("FAILED: mkpath() failed")
-exists($$pn)|message("FAILED: mkpath() didn't create anything")
-
-in = easy "less easy" sca$${LITERAL_HASH}ry crazy$$escape_expand(\\t\\r\\n) $$escape_expand(\\t)shit \'no\"way\\here
-out = "easy \"less easy\" sca\$\${LITERAL_HASH}ry crazy\$\$escape_expand(\\\\t\\\\r\\\\n) \$\$escape_expand(\\\\t)shit \\\'no\\\"way\\\\here"
-testReplace($$val_escape(in), $$out, "val_escape")
-
-testReplace($$shadowed($$PWD/something), $$OUT_PWD/something, "shadowed")
-testReplace($$shadowed($$PWD), $$OUT_PWD, "shadowed (take 2)")
-
-#format_number
-spc = " "
-testReplace($$format_number(13), 13, "simple number format")
-testReplace($$format_number(-13), -13, "negative number format")
-testReplace($$format_number(13, ibase=16), 19, "hex input number format")
-testReplace($$format_number(13, obase=16), d, "hex output number format")
-testReplace($$format_number(13, width=5), " $$spc 13", "right aligned number format")
-testReplace($$format_number(13, width=5 leftalign), "13 $$spc ", "left aligned number format")
-testReplace($$format_number(13, width=5 zeropad), "00013", "zero-padded number format")
-testReplace($$format_number(13, width=5 alwayssign), "$$spc +13", "always signed number format")
-testReplace($$format_number(13, width=5 alwayssign zeropad), "+0013", "zero-padded always signed number format")
-testReplace($$format_number(13, width=5 padsign), " $$spc 13", "sign-padded number format")
-testReplace($$format_number(13, width=5 padsign zeropad), " 0013", "zero-padded sign-padded number format")
-
-testReplace($$clean_path("c:$${DIR_SEPARATOR}crazy//path/../trolls"), "c:/crazy/trolls", "clean_path")
-
-testReplace($$shell_path("/crazy/trolls"), "$${QMAKE_DIR_SEP}crazy$${QMAKE_DIR_SEP}trolls", "shell_path")
-testReplace($$system_path("/crazy/trolls"), "$${DIR_SEPARATOR}crazy$${DIR_SEPARATOR}trolls", "system_path")
-
-testReplace($$absolute_path("crazy/trolls"), "$$PWD/crazy/trolls", "absolute_path")
-testReplace($$absolute_path("crazy/trolls", "/fake/path"), "/fake/path/crazy/trolls", "absolute_path with base")
-testReplace($$absolute_path(""), "$$PWD", "absolute_path of empty")
-testReplace($$relative_path($$_PRO_FILE_PWD_), $$basename($$_PRO_FILE_), "relative_path")
-testReplace($$relative_path("/fake/trolls", "/fake/path"), "../trolls", "relative_path with base")
-testReplace($$relative_path(""), "", "relative_path of empty")
-
-#this test is very rudimentary. the backend function is thoroughly tested in qt creator
-in = "some nasty & ugly\" path & thing\\"
-out_cmd = "\"some nasty & ugly\\\" path ^& thing\\\\^\""
-out_sh = "'some nasty & ugly\" path & thing\\'"
-equals(QMAKE_HOST.os, Windows): \
-    out = $$out_cmd
-else: \
-    out = $$out_sh
-testReplace($$system_quote($$in), $$out, "system_quote")
-!equals(QMAKE_DIR_SEP, /): \
-    out = $$out_cmd
-else: \
-    out = $$out_sh
-testReplace($$shell_quote($$in), $$out, "shell_quote")
-
-testReplace($$reverse($$list(one two three)), three two one, "reverse")
-
-testReplace($$cat(textfile), hi '"holla he"' 'hu!')
-
-MOD.a.depends =
-MOD.b.depends =
-MOD.b.priority = 1
-MOD.c.depends = a b
-testReplace($$resolve_depends($$list(c), "MOD."), c b a)
-MOD.a.priority = 1
-MOD.b.priority = 0
-testReplace($$resolve_depends($$list(c), "MOD."), c a b)
diff --git a/tests/auto/tools/qmake/testdata/functions/textfile b/tests/auto/tools/qmake/testdata/functions/textfile
deleted file mode 100644
index a8248ed6f8f47e8695d650c48c1be87fc9e8f440..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/textfile
+++ /dev/null
@@ -1 +0,0 @@
-hi "holla he" hu!
diff --git a/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp b/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp b/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/two/1.cpp b/tests/auto/tools/qmake/testdata/functions/two/1.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/two/1.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/two/2.cpp b/tests/auto/tools/qmake/testdata/functions/two/2.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/two/2.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp b/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp b/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp
deleted file mode 100644
index 8bdc2e59e82770eb9e091abeedb542778bc126a4..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/include_function/existing_file.pri b/tests/auto/tools/qmake/testdata/include_function/existing_file.pri
deleted file mode 100644
index 8b9aaca340cf476e22196effdebd3afa21342cd5..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/include_function/existing_file.pri
+++ /dev/null
@@ -1,3 +0,0 @@
-QT =
-CONFIG = console
-SOURCES = main.cpp
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro b/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro
deleted file mode 100644
index 424062a9ac94703dbd83d923e0ec71bbd494f1e6..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-# Test to see if include(), by default, succeeds when the specific file 
-#   to include exists
-include(existing_file.pri)
-
-# Test to see if by specifying full set of parameters to include()
-#  succeeds when the specified filed to include exists 
-include(existing_file.pri, "", false)
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro b/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro
deleted file mode 100644
index 0b59981240c2eddbcd2327aed6d2c51f594f9e39..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-# Test to see if include(), by default, fails when the specific file 
-#   to include does not exist
-include(missing_file.pri)
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro b/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro
deleted file mode 100644
index 542b9ff5161b77cc84e95aa1f3134c7ee4b71795..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-# Specifying full set of parameters to include() to test that a warning 
-#   is shown for this non-existing file.
-include(missing_file.pri, "", false)
diff --git a/tests/auto/tools/qmake/testdata/json/json.pro b/tests/auto/tools/qmake/testdata/json/json.pro
deleted file mode 100644
index 33440b3209e950b047d0b69c7228037413674bb8..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/json/json.pro
+++ /dev/null
@@ -1,26 +0,0 @@
-jsontext = $$cat($$PWD/test.json)
-parseJson(jsontext, json)
-
-# print all keys
-message(json._KEYS_ $${json._KEYS_})
-
-# print array
-message(json.array._KEYS_ $${json.array._KEYS_})
-for(key, json.array._KEYS_): \
-    message(json.array.$${key} $$eval(json.array.$${key}))
-
-# print object
-message(json.object._KEYS_ $${json.object._KEYS_})
-for(key, json.object._KEYS_): \
-    message(json.object.$${key} $$eval(json.object.$${key}))
-
-# print value tyes
-message(json.string: $${json.string})
-message(json.number: $${json.number})
-message(json.true: $${json.true})
-message(json.false: $${json.false})
-message(json.null: $${json.null})
-
-# check that booleans work
-$${json.true}: message(json.true is true)
-!$${json.false}: message(json.false is false)
diff --git a/tests/auto/tools/qmake/testdata/json/test.json b/tests/auto/tools/qmake/testdata/json/test.json
deleted file mode 100644
index cc82908eba49e2f3241e0c904bb7ca7fc400e905..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/json/test.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "array" : ["arrayItem1", "arrayItem2", "arrayItem3"],
-    "object" : { "key1" : "objectValue1", "key2" : "objectValue2" },
-    "string" : "test string",
-    "number" : 999,
-    "true" : true,
-    "false" :false,
-    "null" : null
-}
diff --git a/tests/auto/tools/qmake/testdata/operators/operators.pro b/tests/auto/tools/qmake/testdata/operators/operators.pro
deleted file mode 100644
index 463fa73d8160c37334586bd9a7ec4c1bc0a1d404..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/operators/operators.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-VAR = qt thread
-
-VAR += debug
-!contains( VAR, debug ) {
-   message( "FAILED: +=" )
-}
-
-VAR -= thread
-contains( VAR, thread ) {
-   message( "FAILED: -=" )
-}
-
-VAR = thread
-VAR *= thread
-!count( VAR, 1 ) {
-   message( "FAILED: *=" )
-}
-
-VAR = thread QT_DLL debug
-VAR ~= s/QT_+/Q_
-!contains( VAR, Q_DLL ) {
-   message( "FAILED: ~=" )
-}
diff --git a/tests/auto/tools/qmake/testdata/include_function/main.cpp b/tests/auto/tools/qmake/testdata/resources/main.cpp
similarity index 92%
rename from tests/auto/tools/qmake/testdata/include_function/main.cpp
rename to tests/auto/tools/qmake/testdata/resources/main.cpp
index 68e9c98e778686448578da56b1f5e45f1029f4d0..78f981439671541150e21798213b50ecf1b46b14 100644
--- a/tests/auto/tools/qmake/testdata/include_function/main.cpp
+++ b/tests/auto/tools/qmake/testdata/resources/main.cpp
@@ -31,7 +31,12 @@
 **
 ****************************************************************************/
 
-int main(int /*argc*/, char ** /*argv*/)
+
+
+#include <qguiapplication.h>
+
+int main( int argc, char **argv )
 {
-    return 0;
+    QGuiApplication a( argc, argv );
+    return a.exec();
 }
diff --git a/tests/auto/tools/qmake/testdata/resources/resources.pro b/tests/auto/tools/qmake/testdata/resources/resources.pro
new file mode 100644
index 0000000000000000000000000000000000000000..f024fe561708ebb54910a90a780cf83e8b0c7a3d
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/resources/resources.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+SOURCES = main.cpp
+
+pro_file.files = resources.pro
+pro_file.prefix = /prefix
+
+subdir.files = subdir/file.txt
+subdir.base = subdir
+
+RESOURCES = test.qrc main.cpp pro_file subdir
diff --git a/tests/auto/tools/qmake/testdata/resources/subdir/file.txt b/tests/auto/tools/qmake/testdata/resources/subdir/file.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmake/testdata/resources/test.qrc b/tests/auto/tools/qmake/testdata/resources/test.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..decde3dd24bf991147d41c9ee327574b33c4c3df
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/resources/test.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>test.qrc</file>
+    </qresource>
+</RCC>
diff --git a/tests/auto/tools/qmake/testdata/variables/variables.pro b/tests/auto/tools/qmake/testdata/variables/variables.pro
deleted file mode 100644
index e4b9eaa884d5db861edf7151ebf3c5e58988bfe5..0000000000000000000000000000000000000000
--- a/tests/auto/tools/qmake/testdata/variables/variables.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-VAR = 1 2 3 4 5
-JOINEDVAR = $$join( VAR, "-GLUE-", "-BEFORE-", "-AFTER-" )
-!contains( JOINEDVAR, -BEFORE-1-GLUE-2-GLUE-3-GLUE-4-GLUE-5-AFTER- ) {
-   message( "FAILED: join [$$JOINEDVAR != -BEFORE-1-GLUE-2-GLUE-3-GLUE-4-GLUE-5-AFTER-]" )
-}
-
-# To test member we need to use join
-NEWVAR = $$member( VAR, 4 ) $$member( VAR, 3 ) $$member( VAR, 2 )
-JOINEDNEWVAR = $$join( NEWVAR, "-" )
-!contains( JOINEDNEWVAR, 5-4-3 ) {
-  message( "FAILED: member [$$JOINEDNEWVAR != 5-4-3]" )
-}
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index 8d7f7bbc68c88bfca231f3eed1f3372f978632da..ac94d1a2b9b6d86df0111e4630a174cb866c8484 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -39,6 +39,14 @@
 #include <QStandardPaths>
 #include <QDir>
 
+#if defined(DEBUG_BUILD)
+#  define DIR_INFIX "debug/"
+#elif defined(RELEASE_BUILD)
+#  define DIR_INFIX "release/"
+#else
+#  define DIR_INFIX ""
+#endif
+
 class tst_qmake : public QObject
 {
     Q_OBJECT
@@ -60,12 +68,6 @@ private slots:
     void simple_dll();
     void subdirs();
     void subdir_via_pro_file_extra_target();
-    void functions();
-    void operators();
-    void variables();
-    void func_export();
-    void func_variables();
-    void comments();
     void duplicateLibraryEntries();
     void export_across_file_boundaries();
     void include_dir();
@@ -80,11 +82,10 @@ private slots:
 #if defined(Q_OS_MAC)
     void bundle_spaces();
 #endif
-    void includefunction();
     void substitutes();
     void project();
     void proFileCache();
-    void json();
+    void resources();
 
 private:
     TestCompiler test_compiler;
@@ -253,43 +254,6 @@ void tst_qmake::subdir_via_pro_file_extra_target()
     QVERIFY( test_compiler.make( workDir, "extratarget" ));
 }
 
-void tst_qmake::functions()
-{
-    QString workDir = base_path + "/testdata/functions";
-    QString buildDir = base_path + "/testdata/functions_build";
-    QVERIFY( test_compiler.qmake( workDir, "functions", buildDir ));
-}
-
-void tst_qmake::operators()
-{
-    QString workDir = base_path + "/testdata/operators";
-    QVERIFY( test_compiler.qmake( workDir, "operators" ));
-}
-
-void tst_qmake::variables()
-{
-    QString workDir = base_path + "/testdata/variables";
-    QVERIFY(test_compiler.qmake( workDir, "variables" ));
-}
-
-void tst_qmake::func_export()
-{
-    QString workDir = base_path + "/testdata/func_export";
-    QVERIFY(test_compiler.qmake( workDir, "func_export" ));
-}
-
-void tst_qmake::func_variables()
-{
-    QString workDir = base_path + "/testdata/func_variables";
-    QVERIFY(test_compiler.qmake( workDir, "func_variables" ));
-}
-
-void tst_qmake::comments()
-{
-    QString workDir = base_path + "/testdata/comments";
-    QVERIFY(test_compiler.qmake( workDir, "comments" ));
-}
-
 void tst_qmake::duplicateLibraryEntries()
 {
     QVERIFY(true);
@@ -490,26 +454,6 @@ void tst_qmake::bundle_spaces()
 }
 #endif // defined(Q_OS_MAC)
 
-void tst_qmake::includefunction()
-{
-    QString workDir = base_path + "/testdata/include_function";
-    QRegExp warningMsg("Cannot read .*: No such file or directory");
-    QVERIFY(test_compiler.qmake( workDir, "include_existing_file"));
-    QVERIFY(!test_compiler.commandOutput().contains(warningMsg));
-
-    // test include()  usage on a missing file
-    test_compiler.clearCommandOutput();
-    workDir = base_path + "/testdata/include_function";
-    QVERIFY(test_compiler.qmake( workDir, "include_missing_file" ));
-    QVERIFY(test_compiler.commandOutput().contains(warningMsg));
-
-    // test include() usage on a missing file when all function parameters are used
-    test_compiler.clearCommandOutput();
-    workDir = base_path + "/testdata/include_function";
-    QVERIFY(test_compiler.qmake( workDir, "include_missing_file2" ));
-    QVERIFY(test_compiler.commandOutput().contains(warningMsg));
-}
-
 void tst_qmake::substitutes()
 {
     QString workDir = base_path + "/testdata/substitutes";
@@ -555,32 +499,37 @@ void tst_qmake::proFileCache()
     QVERIFY( test_compiler.qmake( workDir, "pro_file_cache" ));
 }
 
-void tst_qmake::json()
+void tst_qmake::resources()
 {
-    QString workDir = base_path + "/testdata/json";
-    QVERIFY( test_compiler.qmake( workDir, "json.pro" ));
-    QString output = test_compiler.commandOutput();
-
-    // all keys
-    QVERIFY(output.contains("json._KEYS_ array false null number object string true"));
-    // array
-    QVERIFY(output.contains("json.array._KEYS_ 0 1 2"));
-    QVERIFY(output.contains("json.array.0 arrayItem1"));
-    QVERIFY(output.contains("json.array.1 arrayItem2"));
-    QVERIFY(output.contains("json.array.2 arrayItem3"));
-    // object
-    QVERIFY(output.contains("json.object._KEYS_ key1 key2"));
-    QVERIFY(output.contains("json.object.key1 objectValue1"));
-    QVERIFY(output.contains("json.object.key1 objectValue1"));
-     // value types
-    QVERIFY(output.contains("json.string: test string"));
-    QVERIFY(output.contains("json.number: 999"));
-    QVERIFY(output.contains("json.true: true"));
-    QVERIFY(output.contains("json.false: false"));
-    QVERIFY(output.contains("json.null:"));
-    // functional booleans
-    QVERIFY(output.contains("json.true is true"));
-    QVERIFY(output.contains("json.false is false"));
+    QString workDir = base_path + "/testdata/resources";
+    QVERIFY(test_compiler.qmake(workDir, "resources"));
+
+    {
+        QFile qrcFile(workDir + "/.rcc/" DIR_INFIX "qmake_pro_file.qrc");
+        QVERIFY(qrcFile.exists());
+        QVERIFY(qrcFile.open(QFile::ReadOnly));
+        QByteArray qrcXml = qrcFile.readAll();
+        QVERIFY(qrcXml.contains("alias=\"resources.pro\""));
+        QVERIFY(qrcXml.contains("prefix=\"/prefix\""));
+    }
+
+    {
+        QFile qrcFile(workDir + "/.rcc/" DIR_INFIX "qmake_subdir.qrc");
+        QVERIFY(qrcFile.exists());
+        QVERIFY(qrcFile.open(QFile::ReadOnly));
+        QByteArray qrcXml = qrcFile.readAll();
+        QVERIFY(qrcXml.contains("alias=\"file.txt\""));
+    }
+
+    {
+        QFile qrcFile(workDir + "/.rcc/" DIR_INFIX "qmake_qmake_immediate.qrc");
+        QVERIFY(qrcFile.exists());
+        QVERIFY(qrcFile.open(QFile::ReadOnly));
+        QByteArray qrcXml = qrcFile.readAll();
+        QVERIFY(qrcXml.contains("alias=\"main.cpp\""));
+    }
+
+    QVERIFY(test_compiler.make(workDir));
 }
 
 QTEST_MAIN(tst_qmake)
diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fab2cdce17f8cd4d89fc4c5d2f07ae05992e8740
--- /dev/null
+++ b/tests/auto/tools/qmakelib/evaltest.cpp
@@ -0,0 +1,2513 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include "tst_qmakelib.h"
+
+#include <proitems.h>
+#include <qmakevfs.h>
+#include <qmakeparser.h>
+#include <qmakeglobals.h>
+#include <qmakeevaluator.h>
+
+void tst_qmakelib::addAssignments()
+{
+    QTest::newRow("assignment")
+            << "VAR = foo bar baz"
+            << "VAR = foo bar baz"
+            << ""
+            << true;
+
+    QTest::newRow("appending")
+            << "VAR = foo bar baz\nVAR += foo gaz gaz"
+            << "VAR = foo bar baz foo gaz gaz"
+            << ""
+            << true;
+
+    QTest::newRow("unique appending")
+            << "VAR = foo bar baz\nVAR *= foo gaz gaz"
+            << "VAR = foo bar baz gaz"
+            << ""
+            << true;
+
+    QTest::newRow("removing")
+            << "VAR = foo bar foo baz\nVAR -= foo gaz gaz"
+            << "VAR = bar baz"
+            << ""
+            << true;
+
+    // Somewhat unexpectedly, the g modifier is implicit within each element.
+    QTest::newRow("replacing")
+            << "VAR = foo bar foo baz\nVAR ~= s,o,0,"
+            << "VAR = f00 bar foo baz"
+            << ""
+            << true;
+
+    // Consistently with the "there are no empty elements", what becomes empty gets zapped.
+    QTest::newRow("replacing with nothing")
+            << "VAR = foo bar foo baz\nVAR ~= s,foo,,"
+            << "VAR = bar foo baz"
+            << ""
+            << true;
+
+    QTest::newRow("replacing case-insensitively")
+            << "VAR = foO bar foo baz\nVAR ~= s,o,0,i"
+            << "VAR = f00 bar foo baz"
+            << ""
+            << true;
+
+    // In all elements, not all within each/one/??? element.
+    QTest::newRow("replacing globally")
+            << "VAR = foo bar foo baz\nVAR ~= s,o,0,g"
+            << "VAR = f00 bar f00 baz"
+            << ""
+            << true;
+
+    // Replacing with the same string counts as no match.
+    // This is rather questionable ...
+    QTest::newRow("replacing with same")
+            << "VAR = foo bar foo baz\nVAR ~= s,ba[rz],bar,"
+            << "VAR = foo bar foo bar"
+            << ""
+            << true;
+
+    QTest::newRow("replacing with auto-quote")
+            << "VAR = foo [bar] foo baz\nVAR ~= s,[bar],bar,q"
+            << "VAR = foo bar foo baz"
+            << ""
+            << true;
+
+    QTest::newRow("replacing with expansions")
+            << "VAR = foo bar foo baz\nPAT = foo\nREPL = 'yee haw'\nVAR ~= s,$$PAT,$$REPL,"
+            << "VAR = 'yee haw' bar foo baz"
+            << ""
+            << true;
+
+    QTest::newRow("~= with bad function")
+            << "VAR ~= m/foo/"
+            << ""
+            << "##:1: The ~= operator can handle only the s/// function."
+            << true; // rather questionable
+
+    QTest::newRow("~= s with bad number of arguments")
+            << "VAR ~= s/bla\nVAR ~= s/bla/foo//"
+            << ""
+            << "##:1: The s/// function expects 3 or 4 arguments.\n"
+               "##:2: The s/// function expects 3 or 4 arguments."
+            << true; // rather questionable
+}
+
+void tst_qmakelib::addExpansions()
+{
+    QTest::newRow("expand variable")
+            << "V1 = foo\nVAR = $$V1"
+            << "VAR = foo"
+            << ""
+            << true;
+
+    QTest::newRow("expand property")
+            << "VAR = $$[P1]"
+            << "VAR = 'prop val'"
+            << ""
+            << true;
+
+    QTest::newRow("expand environment variable")
+            << "VAR = $$(E1)"
+            << "VAR = 'env var'"
+            << ""
+            << true;
+
+    // These test addStr/addStr.
+
+    QTest::newRow("expand: str $$(env)")
+            << "VAR = foo $$(E1)"
+            << "VAR = foo 'env var'"
+            << ""
+            << true;
+
+    QTest::newRow("expand: str$$(env)")
+            << "VAR = foo$$(E1)"
+            << "VAR = 'fooenv var'"
+            << ""
+            << true;
+
+    QTest::newRow("expand: 'str $$(env)'")
+            << "VAR = 'foo $$(E1)'"
+            << "VAR = 'foo env var'"
+            << ""
+            << true;
+
+    // These test addStr/addStrList
+
+    QTest::newRow("expand: str $$var")
+            << "V1 = foo barbaz\nVAR = str $$V1"
+            << "VAR = str foo barbaz"
+            << ""
+            << true;
+
+    QTest::newRow("expand: $$var str")
+            << "V1 = foo barbaz\nVAR = $$V1 str"
+            << "VAR = foo barbaz str"
+            << ""
+            << true;
+
+    QTest::newRow("expand: str$$var")
+            << "V1 = foo barbaz\nVAR = str$$V1"
+            << "VAR = strfoo barbaz"
+            << ""
+            << true;
+
+    QTest::newRow("expand: $${var}str")
+            << "V1 = foo barbaz\nVAR = $${V1}str"
+            << "VAR = foo barbazstr"
+            << ""
+            << true;
+
+    QTest::newRow("expand: 'str $$var'")
+            << "V1 = foo barbaz\nVAR = 'str $$V1'"
+            << "VAR = 'str foo barbaz'"
+            << ""
+            << true;
+
+    QTest::newRow("expand: '$$var str'")
+            << "V1 = foo barbaz\nVAR = '$$V1 str'"
+            << "VAR = 'foo barbaz str'"
+            << ""
+            << true;
+
+    // Same again in joined context
+
+    QTest::newRow("expand joined: str $$(env)")
+            << "VAR = $$quote(foo $$(E1))"
+            << "VAR = 'foo env var'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: str$$(env)")
+            << "VAR = $$quote(foo$$(E1))"
+            << "VAR = 'fooenv var'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: 'str $$(env)'")
+            << "VAR = $$quote('foo $$(E1)')"
+            << "VAR = 'foo env var'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: str $$var")
+            << "V1 = foo barbaz\nVAR = $$quote(str $$V1)"
+            << "VAR = 'str foo barbaz'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: $$var str")
+            << "V1 = foo barbaz\nVAR = $$quote($$V1 str)"
+            << "VAR = 'foo barbaz str'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: str$$var")
+            << "V1 = foo barbaz\nVAR = $$quote(str$$V1)"
+            << "VAR = 'strfoo barbaz'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: $${var}str")
+            << "V1 = foo barbaz\nVAR = $$quote($${V1}str)"
+            << "VAR = 'foo barbazstr'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: 'str $$var'")
+            << "V1 = foo barbaz\nVAR = $$quote('str $$V1')"
+            << "VAR = 'str foo barbaz'"
+            << ""
+            << true;
+
+    QTest::newRow("expand joined: '$$var str'")
+            << "V1 = foo barbaz\nVAR = $$quote('$$V1 str')"
+            << "VAR = 'foo barbaz str'"
+            << ""
+            << true;
+
+    // Variable expansions on LHS
+
+    QTest::newRow("indirect assign: $$var")
+            << "V = VAR\n$$V = foo"
+            << "VAR = foo"
+            << ""
+            << true;
+
+    QTest::newRow("indirect assign: fix$$var")
+            << "V = AR\nV$$V = foo"
+            << "VAR = foo"
+            << ""
+            << true;
+
+    QTest::newRow("indirect assign: $${var}fix")
+            << "V = VA\n$${V}R = foo"
+            << "VAR = foo"
+            << ""
+            << true;
+
+    QTest::newRow("indirect assign: eval")
+            << "V = VAR\n$$eval(V) = foo"
+            << "VAR = foo"
+            << ""
+            << true;
+
+    QTest::newRow("indirect assign: multiple")
+            << "V = FOO BAR\n$$V = foo"
+            << ""
+            << "##:2: Left hand side of assignment must expand to exactly one word."
+            << true;
+}
+
+void tst_qmakelib::addControlStructs()
+{
+    QTest::newRow("true")
+            << "true: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false")
+            << "false: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-config")
+            << "CONFIG += test\ntest: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false-config")
+            << "test: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-wildcard")
+            << "CONFIG += testing\ntest*: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false-wildcard")
+            << "test*: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-else")
+            << "true: VAR1 = 1\nelse: VAR2 = 1"
+            << "VAR1 = 1\nVAR2 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-else")
+            << "false: VAR1 = 1\nelse: VAR2 = 1"
+            << "VAR1 = UNDEF\nVAR2 = 1"
+            << ""
+            << true;
+
+    QTest::newRow("true-else-true-else")
+            << "true: VAR1 = 1\nelse: true: VAR2 = 1\nelse: VAR3 = 1"
+            << "VAR1 = 1\nVAR2 = UNDEF\nVAR3 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-else-false-else")
+            << "true: VAR1 = 1\nelse: false: VAR2 = 1\nelse: VAR3 = 1"
+            << "VAR1 = 1\nVAR2 = UNDEF\nVAR3 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-else-true-else")
+            << "false: VAR1 = 1\nelse: true: VAR2 = 1\nelse: VAR3 = 1"
+            << "VAR1 = UNDEF\nVAR2 = 1\nVAR3 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-else-false-else")
+            << "false: VAR1 = 1\nelse: false: VAR2 = 1\nelse: VAR3 = 1"
+            << "VAR1 = UNDEF\nVAR2 = UNDEF\nVAR3 = 1"
+            << ""
+            << true;
+
+    QTest::newRow("true-{false-else}-else")
+            << "true {\nfalse: VAR1 = 1\nelse: VAR2 = 1\n}\nelse: VAR3 = 1"
+            << "VAR1 = UNDEF\nVAR2 = 1\nVAR3 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("NOT-true")
+            << "!true: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("NOT-false")
+            << "!false: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("true-AND-true")
+            << "true:true: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("true-AND-false")
+            << "true:false: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-AND-true")
+            << "false:true: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-OR-false")
+            << "false|false: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-OR-false")
+            << "true|false: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false-OR-true")
+            << "false|true: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("NOT-false-AND-true")
+            << "!false:true: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("true-AND-message")
+            << "true:message(hi): VAR = 1"
+            << "VAR = 1"
+            << "Project MESSAGE: hi"
+            << true;
+
+    QTest::newRow("false-AND-message")
+            << "false:message(hi): VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-OR-message")
+            << "true|message(hi): VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false-OR-message")
+            << "false|message(hi): VAR = 1"
+            << "VAR = 1"
+            << "Project MESSAGE: hi"
+            << true;
+
+    QTest::newRow("true-OR-message-AND-false")
+            << "true|message(hi):false: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-OR-message-AND-false")
+            << "false|message(hi):false: VAR = 1"
+            << "VAR = UNDEF"
+            << "Project MESSAGE: hi"
+            << true;
+
+    QTest::newRow("true (indirect)")
+            << "TEST = true\n$$TEST: VAR = 1"
+            << "VAR = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false (indirect)")
+            << "TEST = false\n$$TEST: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    // Yes, this is not supposed to work
+    QTest::newRow("true|false (indirect)")
+            << "TEST = true|false\n$$TEST: VAR = 1"
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("for (var, var)")
+            << "IN = one two three\nfor (IT, IN) { OUT += $$IT }"
+            << "OUT = one two three"
+            << ""
+            << true;
+
+    QTest::newRow("for (var, range)")
+            << "for (IT, 1..3) { OUT += $$IT }"
+            << "OUT = 1 2 3"
+            << ""
+            << true;
+
+    QTest::newRow("for (var, reverse-range)")
+            << "for (IT, 3..1) { OUT += $$IT }"
+            << "OUT = 3 2 1"
+            << ""
+            << true;
+
+    // This syntax is rather ridiculous.
+    QTest::newRow("for (ever)")
+            << "for (ever) {}"
+            << ""
+            << "##:1: Ran into infinite loop (> 1000 iterations)."
+            << true;
+
+    // This is even worse.
+    QTest::newRow("for (VAR, forever)")
+            << "for (VAR, forever) { OUT = $$VAR }"
+            << "OUT = 999"
+            << "##:1: Ran into infinite loop (> 1000 iterations)."
+            << true;
+
+    QTest::newRow("for (garbage)")
+            << "for (garbage) { OUT = FAIL }"
+            << "OUT = UNDEF"
+            << "##:1: Invalid loop expression."
+            << true;
+
+    QTest::newRow("next()")
+            << "IN = one two three\nfor (IT, IN) {\nequals(IT, two):next()\nOUT += $$IT\n}"
+            << "OUT = one three"
+            << ""
+            << true;
+
+    QTest::newRow("nested next()")
+            << "IN = one two three\nfor (IT, IN) {\nfor (NIT, IN):next()\nOUT += $$IT\n}"
+            << "OUT = one two three"
+            << ""
+            << true;
+
+    QTest::newRow("break()")
+            << "IN = one two three\nfor (IT, IN) {\nequals(IT, three):break()\nOUT += $$IT\n}"
+            << "OUT = one two"
+            << ""
+            << true;
+
+    QTest::newRow("nested break()")
+            << "IN = one two three\nfor (IT, IN) {\nfor (NIT, IN):break()\nOUT += $$IT\n}"
+            << "OUT = one two three"
+            << ""
+            << true;
+
+    QTest::newRow("defineReplace()")
+            << "defineReplace(func) { return($$1 + $$2) }\n"
+               "VAR = $$func(test me, \"foo bar\")"
+            << "VAR = test me + 'foo bar'"
+            << ""
+            << true;
+
+    QTest::newRow("defineTest()")
+            << "defineTest(func) { return($$1) }\n"
+               "func(true): VAR += true\n"
+               "func(false): VAR += false"
+            << "VAR = true"
+            << ""
+            << true;
+
+    QTest::newRow("true-AND-defineTest()")
+            << "true: defineTest(func)\n"
+               "defined(func): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("false-AND-defineTest()")
+            << "false: defineTest(func)\n"
+               "defined(func): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("true-OR-defineTest()")
+            << "true| defineTest(func)\n"
+               "defined(func): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("false-OR-defineTest()")
+            << "false| defineTest(func)\n"
+               "defined(func): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("variable scoping")
+            << "defineTest(func) {\n"
+                   "VAR1 = modified\n!equals(VAR1, modified): return(false)\n"
+                   "VAR2 += modified\n!equals(VAR2, original modified): return(false)\n"
+                   "VAR3 = new var\n!equals(VAR3, new var): return(false)\n"
+                   "return(true)\n"
+               "}\n"
+               "VAR1 = pristine\nVAR2 = original\nfunc(): OK = 1"
+            << "OK = 1\nVAR1 = pristine\nVAR2 = original\nVAR3 = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("ARGC and ARGS")
+            << "defineTest(func) {\n"
+                   "export(ARGC)\n"
+                   "export(ARGS)\n"
+               "}\n"
+               "func(test me, \"foo bar\")"
+            << "ARGC = 2\nARGS = test me 'foo bar'"
+            << ""
+            << true;
+
+    QTest::newRow("recursion")
+            << "defineReplace(func) {\n"
+                   "RET = *$$member(1, 0)*\n"
+                   "REST = $$member(1, 1, -1)\n"
+                   "!isEmpty(REST): RET += $$func($$REST)\n"
+                   "return($$RET)\n"
+               "}\n"
+               "VAR = $$func(you are ...)"
+            << "VAR = *you* *are* *...*"
+            << ""
+            << true;
+
+    QTest::newRow("top-level return()")
+            << "VAR = good\nreturn()\nVAR = bad"
+            << "VAR = good"
+            << ""
+            << true;
+
+    QTest::newRow("return() from function")
+            << "defineTest(func) {\nVAR = good\nexport(VAR)\nreturn()\nVAR = bad\nexport(VAR)\n}\n"
+               "func()"
+            << "VAR = good"
+            << ""
+            << true;
+
+    QTest::newRow("return() from nested function")
+            << "defineTest(inner) {\nVAR = initial\nexport(VAR)\nreturn()\nVAR = bad\nexport(VAR)\n}\n"
+               "defineTest(outer) {\ninner()\nVAR = final\nexport(VAR)\n}\n"
+               "outer()"
+            << "VAR = final"
+            << ""
+            << true;
+}
+
+void tst_qmakelib::addReplaceFunctions(const QString &qindir)
+{
+    QTest::newRow("$$member(): empty")
+            << "IN = \nVAR = $$member(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): too short")
+            << "IN = one two three\nVAR = $$member(IN, 1, 5)"
+            << "VAR ="  // this is actually kinda stupid
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): ok")
+            << "IN = one two three four five six seven\nVAR = $$member(IN, 1, 4)"
+            << "VAR = two three four five"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): ok (default start)")
+            << "IN = one two three\nVAR = $$member(IN)"
+            << "VAR = one"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): ok (default end)")
+            << "IN = one two three\nVAR = $$member(IN, 2)"
+            << "VAR = three"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): negative")
+            << "IN = one two three four five six seven\nVAR = $$member(IN, -4, -3)"
+            << "VAR = four five"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): inverse")
+            << "IN = one two three four five six seven\nVAR = $$member(IN, 4, 1)"
+            << "VAR = five four three two"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): dots")
+            << "IN = one two three four five six seven\nVAR = $$member(IN, 1..4)"
+            << "VAR = two three four five"
+            << ""
+            << true;
+
+    QTest::newRow("$$member(): bad number of arguments")
+            << "VAR = $$member(1, 2, 3, 4)"
+            << "VAR ="
+            << "##:1: member(var, start, end) requires one to three arguments."
+            << true;
+
+    QTest::newRow("$$member(): bad args (1)")
+            << "IN = one two three\nVAR = $$member(IN, foo, 4)"
+            << "VAR ="
+            << "##:2: member() argument 2 (start) 'foo' invalid."
+            << true;
+
+    QTest::newRow("$$member(): bad args (2)")
+            << "IN = one two three\nVAR = $$member(IN, foo..4)"
+            << "VAR ="
+            << "##:2: member() argument 2 (start) 'foo..4' invalid."
+            << true;
+
+    QTest::newRow("$$member(): bad args (3)")
+            << "IN = one two three\nVAR = $$member(IN, 4, foo)"
+            << "VAR ="
+            << "##:2: member() argument 3 (end) 'foo' invalid."
+            << true;
+
+    QTest::newRow("$$member(): bad args (4)")
+            << "IN = one two three\nVAR = $$member(IN, 4..foo)"
+            << "VAR ="
+            << "##:2: member() argument 2 (start) '4..foo' invalid."
+            << true;
+
+    QTest::newRow("$$first(): empty")
+            << "IN = \nVAR = $$first(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$first(): one")
+            << "IN = one\nVAR = $$first(IN)"
+            << "VAR = one"
+            << ""
+            << true;
+
+    QTest::newRow("$$first(): multiple")
+            << "IN = one two three\nVAR = $$first(IN)"
+            << "VAR = one"
+            << ""
+            << true;
+
+    QTest::newRow("$$first(): bad number of arguments")
+            << "VAR = $$first(1, 2)"
+            << "VAR ="
+            << "##:1: first(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$last(): empty")
+            << "IN = \nVAR = $$last(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$last(): one")
+            << "IN = one\nVAR = $$last(IN)"
+            << "VAR = one"
+            << ""
+            << true;
+
+    QTest::newRow("$$last(): multiple")
+            << "IN = one two three\nVAR = $$last(IN)"
+            << "VAR = three"
+            << ""
+            << true;
+
+    QTest::newRow("$$last(): bad number of arguments")
+            << "VAR = $$last(1, 2)"
+            << "VAR ="
+            << "##:1: last(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$size()")
+            << "IN = one two three\nVAR = $$size(IN)"
+            << "VAR = 3"
+            << ""
+            << true;
+
+    QTest::newRow("$$size(): bad number of arguments")
+            << "VAR = $$size(1, 2)"
+            << "VAR ="
+            << "##:1: size(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$fromfile(): right var")
+            << "VAR = $$fromfile(" + qindir + "/fromfile/infile.prx, DEFINES)"
+            << "VAR = QT_DLL"
+            << ""
+            << true;
+
+    QTest::newRow("$$fromfile(): wrong var")
+            << "VAR = $$fromfile(" + qindir + "/fromfile/infile.prx, INCLUDES)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$fromfile(): bad file")
+            << "VAR = $$fromfile(" + qindir + "/fromfile/badfile.prx, DEFINES)"
+            << "VAR ="
+            << "Project ERROR: fail!"
+            << true;
+
+    QTest::newRow("$$fromfile(): bad number of arguments")
+            << "VAR = $$fromfile(1) \\\n$$fromfile(1, 2, 3)"
+            << "VAR ="
+            << "##:1: fromfile(file, variable) requires two arguments.\n"
+               "##:2: fromfile(file, variable) requires two arguments."
+            << true;
+
+    QTest::newRow("$$eval()")
+            << "IN = one two three\nVAR = $$eval(IN)"
+            << "VAR = one two three"
+            << ""
+            << true;
+
+    QTest::newRow("$$eval(): bad number of arguments")
+            << "VAR = $$eval(1, 2)"
+            << "VAR ="
+            << "##:1: eval(variable) requires one argument."
+            << true;
+
+    QTest::newRow("$$list()")
+            << "VARNAME = $$list(one, two three, 'four five')\nVAR = $$eval($$VARNAME)"
+            << "VAR = one two three four five"  // total nonsense ...
+            << ""
+            << true;
+
+    QTest::newRow("$$sprintf()")
+            << "VAR = $$sprintf(hello %1 %2, you, there)"
+            << "VAR = 'hello you there'"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): simple number format")
+            << "VAR = $$format_number(13)"
+            << "VAR = 13"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): negative number format")
+            << "VAR = $$format_number(-13)"
+            << "VAR = -13"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): hex input number format")
+            << "VAR = $$format_number(13, ibase=16)"
+            << "VAR = 19"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): hex output number format")
+            << "VAR = $$format_number(13, obase=16)"
+            << "VAR = d"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): right aligned number format")
+            << "VAR = $$format_number(13, width=5)"
+            << "VAR = '   13'"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): left aligned number format")
+            << "VAR = $$format_number(13, width=5 leftalign)"
+            << "VAR = '13   '"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): zero-padded number format")
+            << "VAR = $$format_number(13, width=5 zeropad)"
+            << "VAR = 00013"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): always signed number format")
+            << "VAR = $$format_number(13, width=5 alwayssign)"
+            << "VAR = '  +13'"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): zero-padded always signed number format")
+            << "VAR = $$format_number(13, width=5 alwayssign zeropad)"
+            << "VAR = +0013"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): sign-padded number format")
+            << "VAR = $$format_number(13, width=5 padsign)"
+            << "VAR = '   13'"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): zero-padded sign-padded number format")
+
+            << "VAR = $$format_number(13, width=5 padsign zeropad)"
+            << "VAR = ' 0013'"
+            << ""
+            << true;
+
+    QTest::newRow("$$format_number(): bad number of arguments")
+            << "VAR = $$format_number(13, 1, 2)"
+            << "VAR ="
+            << "##:1: format_number(number[, options...]) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$format_number(): invalid option")
+            << "VAR = $$format_number(13, foo=bar)"
+            << "VAR ="
+            << "##:1: format_number(): invalid format option foo=bar."
+            << true;
+
+    QTest::newRow("$$join(): empty")
+            << "IN = \nVAR = $$join(IN, //)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$join(): multiple")
+            << "IN = one two three\nVAR = $$join(IN, //)"
+            << "VAR = one//two//three"
+            << ""
+            << true;
+
+    QTest::newRow("$$join(): multiple surrounded")
+            << "IN = one two three\nVAR = $$join(IN, //, <<, >>)"
+            << "VAR = <<one//two//three>>"
+            << ""
+            << true;
+
+    QTest::newRow("$$join(): bad number of arguments")
+            << "VAR = $$join(1, 2, 3, 4, 5)"
+            << "VAR ="
+            << "##:1: join(var, glue, before, after) requires one to four arguments."
+            << true;
+
+    QTest::newRow("$$split(): default sep")
+            << "IN = 'one/two three' 'four / five'\nVAR = $$split(IN)"
+            << "VAR = one/two three four / five"
+            << ""
+            << true;
+
+    QTest::newRow("$$split(): specified sep")
+            << "IN = 'one/two three' 'four / five'\nVAR = $$split(IN, /)"
+            << "VAR = one 'two three' 'four ' ' five'"
+            << ""
+            << true;
+
+    QTest::newRow("$$split(): bad number of arguments")
+            << "VAR = $$split(1, 2, 3)"
+            << "VAR ="
+            << "##:1: split(var, sep) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$basename(): empty")
+            << "IN = \nVAR = $$basename(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$basename(): bare")
+            << "IN = file\nVAR = $$basename(IN)"
+            << "VAR = file"
+            << ""
+            << true;
+
+    QTest::newRow("$$basename(): relative")
+            << "IN = path/file\nVAR = $$basename(IN)"
+            << "VAR = file"
+            << ""
+            << true;
+
+    QTest::newRow("$$basename(): absolute")
+            << "IN = \\\\path\\\\file\nVAR = $$basename(IN)"
+            << "VAR = file"
+            << ""
+            << true;
+
+    QTest::newRow("$$basename(): bad number of arguments")
+            << "VAR = $$basename(1, 2)"
+            << "VAR ="
+            << "##:1: basename(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$dirname(): empty")
+            << "IN = \nVAR = $$dirname(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$dirname(): bare")
+            << "IN = file\nVAR = $$dirname(IN)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$dirname(): relative")
+            << "IN = path/file\nVAR = $$dirname(IN)"
+            << "VAR = path"
+            << ""
+            << true;
+
+    QTest::newRow("$$dirname(): absolute")
+            << "IN = \\\\path\\\\file\nVAR = $$dirname(IN)"
+            << "VAR = \\\\path"
+            << ""
+            << true;
+
+    QTest::newRow("$$dirname(): bad number of arguments")
+            << "VAR = $$dirname(1, 2)"
+            << "VAR ="
+            << "##:1: dirname(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$section(): explicit end")
+            << "IN = one~two~three~four~five~six\nVAR = $$section(IN, ~, 2, 4)"
+            << "VAR = three~four~five"
+            << ""
+            << true;
+
+    QTest::newRow("$$section(): implicit end")
+            << "IN = one~two~three~four~five~six\nVAR = $$section(IN, ~, 3)"
+            << "VAR = four~five~six"
+            << ""
+            << true;
+
+    QTest::newRow("$$section(): bad number of arguments")
+            << "VAR = $$section(1, 2) \\\n$$section(1, 2, 3, 4, 5)"
+            << "VAR ="
+            << "##:1: section(var) section(var, sep, begin, end) requires three or four arguments.\n"
+               "##:2: section(var) section(var, sep, begin, end) requires three or four arguments."
+            << true;
+
+    QTest::newRow("$$find()")
+            << "IN = foo bar baz blubb\nVAR = $$find(IN, ^ba)"
+            << "VAR = bar baz"
+            << ""
+            << true;
+
+    QTest::newRow("$$find(): bad number of arguments")
+            << "VAR = $$find(1) \\\n$$find(1, 2, 3)"
+            << "VAR ="
+            << "##:1: find(var, str) requires two arguments.\n"
+               "##:2: find(var, str) requires two arguments."
+            << true;
+
+    // FIXME: $$cat() & $$system(): There is no way to generate the newlines
+    // necessary for testing "multi-line" and "blob" mode adequately.
+    // Note: these functions have *different* splitting behavior.
+
+    // This gives split_value_list() an exercise
+    QTest::newRow("$$cat(): default mode")
+            << "VAR = $$cat(" + qindir + "/cat/file2.txt)"
+            << "VAR = foo bar baz \"\\\"Hello, \\' world.\\\"\" post \"\\'Hello, \\\" world.\\'\" post \\\\\\\" \\\\\\' \\\\\\\\ \\\\a \\\\ nix \"\\\" \\\"\""
+            << ""
+            << true;
+
+    QTest::newRow("$$cat(): lines mode")
+            << "VAR = $$cat(" + qindir + "/cat/file1.txt, lines)"
+            << "VAR = '\"Hello, world.\"' 'foo bar baz'"
+            << ""
+            << true;
+
+    QTest::newRow("$$cat(): bad number of arguments")
+            << "VAR = $$cat(1, 2, 3)"
+            << "VAR ="
+            << "##:1: cat(file, singleline=true) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$system(): default mode")
+#ifdef Q_OS_WIN
+            << "VAR = $$system('echo Hello, ^\"world.&& echo foo^\" bar baz')"
+#else
+            << "VAR = $$system('echo Hello, \\\\\\\"world. && echo foo\\\\\\\" bar baz')"
+#endif
+            << "VAR = Hello, '\"world. foo\"' bar baz"
+            << ""
+            << true;
+
+    QTest::newRow("$$system(): lines mode")
+#ifdef Q_OS_WIN
+            << "VAR = $$system('echo Hello, ^\"world.&& echo foo^\" bar baz', lines)"
+#else
+            << "VAR = $$system('echo Hello, \\\\\\\"world. && echo foo\\\\\\\" bar baz', lines)"
+#endif
+            << "VAR = 'Hello, \"world.' 'foo\" bar baz'"
+            << ""
+            << true;
+
+    QTest::newRow("$$system(): bad number of arguments")
+            << "VAR = $$system(1, 2, 3)"
+            << "VAR ="
+            << "##:1: system(execute) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$unique()")
+            << "IN = foo bar foo baz\nVAR = $$unique(IN)"
+            << "VAR = foo bar baz"
+            << ""
+            << true;
+
+    QTest::newRow("$$unique(): bad number of arguments")
+            << "VAR = $$unique(1, 2)"
+            << "VAR ="
+            << "##:1: unique(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$reverse()")
+            << "IN = one two three\nVAR = $$reverse(IN)"
+            << "VAR = three two one"
+            << ""
+            << true;
+
+    QTest::newRow("$$reverse(): bad number of arguments")
+            << "VAR = $$reverse(1, 2)"
+            << "VAR ="
+            << "##:1: reverse(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$quote()")
+            << "VAR = $$quote(foo bar, 'foo bar')"
+            << "VAR = 'foo bar' 'foo bar'"
+            << ""
+            << true;
+
+    // FIXME: \n and \r go untested, because there is no way to get them into the
+    // expected result. And if there was one, this function would be unnecessary.
+    // In other news, the behavior of backslash escaping makes no sense.
+    QTest::newRow("$$escape_expand()")
+            << "VAR = $$escape_expand(foo\\\\ttab\\\\\\\\slash\\\\invalid, verbatim)"
+            << "VAR = 'foo\ttab\\\\\\\\slash\\\\invalid' verbatim"
+            << ""
+            << true;
+
+    QTest::newRow("$$upper()")
+            << "VAR = $$upper(kEwL, STuff)"
+            << "VAR = KEWL STUFF"
+            << ""
+            << true;
+
+    QTest::newRow("$$lower()")
+            << "VAR = $$lower(kEwL, STuff)"
+            << "VAR = kewl stuff"
+            << ""
+            << true;
+
+    QTest::newRow("$$title()")
+            << "VAR = $$title(kEwL, STuff)"
+            << "VAR = Kewl Stuff"
+            << ""
+            << true;
+
+    QTest::newRow("$$re_escape()")
+            << "VAR = $$re_escape(one, hey.*you[funny]+people)"
+            << "VAR = one hey\\\\.\\\\*you\\\\[funny\\\\]\\\\+people"
+            << ""
+            << true;
+
+    QTest::newRow("$$val_escape()")
+            << "IN = easy \"less easy\" sca$${LITERAL_HASH}ry"
+                    " crazy$$escape_expand(\\\\t\\\\r\\\\n)"
+                    " $$escape_expand(\\\\t)stuff \\'no\\\"way\\\\here\n"
+               "VAR = $$val_escape(IN)"
+            << "VAR = easy '\\\"less easy\\\"' sca\\$\\${LITERAL_HASH}ry"
+                    " crazy\\$\\$escape_expand(\\\\\\\\t\\\\\\\\r\\\\\\\\n)"
+                    " \\$\\$escape_expand(\\\\\\\\t)stuff \\\\\\'no\\\\\\\"way\\\\\\\\here"
+            << ""
+            << true;
+
+    QTest::newRow("$$val_escape(): bad number of arguments")
+            << "VAR = $$val_escape(1, 2)"
+            << "VAR ="
+            << "##:1: val_escape(var) requires one argument."
+            << true;
+
+    QTest::newRow("$$files(): non-recursive")
+            << "VAR = $$files(" + qindir + "/files/file*.txt)"
+            << "VAR = " + qindir + "/files/file1.txt "
+                        + qindir + "/files/file2.txt"
+            << ""
+            << true;
+
+    QTest::newRow("$$files(): recursive")
+            << "VAR = $$files(" + qindir + "/files/file*.txt, true)"
+            << "VAR = " + qindir + "/files/file1.txt "
+                        + qindir + "/files/file2.txt "
+                        + qindir + "/files/dir/file1.txt "
+                        + qindir + "/files/dir/file2.txt"
+            << ""
+            << true;
+
+    QTest::newRow("$$files(): bad number of arguments")
+            << "VAR = $$files(1, 2, 3)"
+            << "VAR ="
+            << "##:1: files(pattern, recursive=false) requires one or two arguments."
+            << true;
+
+#if 0
+    // FIXME: no emulated input layer
+    QTest::newRow("$$prompt()")
+            << "VAR = $$prompt(que)"
+            << "VAR = whatever"
+            << "Project PROMPT: que? "
+            << true;
+#endif
+
+    QTest::newRow("$$replace()")
+            << "IN = foo 'bar baz'\nVAR = $$replace(IN, \\\\bba, hello)"
+            << "VAR = foo 'hellor helloz'"
+            << ""
+            << true;
+
+    QTest::newRow("$$replace(): bad number of arguments")
+            << "VAR = $$replace(1, 2) \\\n$$replace(1, 2, 3, 4)"
+            << "VAR ="
+            << "##:1: replace(var, before, after) requires three arguments.\n"
+               "##:2: replace(var, before, after) requires three arguments."
+            << true;
+
+    QTest::newRow("$$sort_depends()")
+            << "foo.depends = bar baz\n"
+               "bar.depends = baz bak duck\n"
+               "baz.depends = bak\n"
+               "bak.depends = duck\n"
+               "VAR = $$sort_depends($$list(baz foo duck bar))"
+            << "VAR = foo bar baz duck"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): basic")
+            << "foo.depends = bar baz\n"
+               "bar.depends = baz bak duck\n"
+               "baz.depends = bak\n"
+               "bak.depends = duck\n"
+               "VAR = $$resolve_depends($$list(baz foo duck bar))"
+            << "VAR = foo bar baz bak duck"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): prefix and multiple suffixes")
+            << "MOD.foo.dep = bar baz\n"
+               "MOD.bar.dep = baz bak\n"
+               "MOD.bar.priv_dep = duck\n"
+               "MOD.baz.dep = bak\n"
+               "MOD.bak.dep = duck\n"
+               "VAR = $$resolve_depends($$list(baz foo duck bar), MOD., .dep .priv_dep)"
+            << "VAR = foo bar baz bak duck"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): priorities: b first")
+            << "MOD.a.depends =\n"
+               "MOD.b.depends =\n"
+               "MOD.b.priority = 1\n"
+               "MOD.c.depends = a b\n"
+               "VAR = $$resolve_depends($$list(c), MOD.)"
+            << "VAR = c b a"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): priorities: a first")
+            << "MOD.a.depends =\n"
+               "MOD.a.priority = 1\n"
+               "MOD.b.depends =\n"
+               "MOD.b.priority = 0\n"
+               "MOD.c.depends = a b\n"
+               "VAR = $$resolve_depends($$list(c), MOD.)"
+            << "VAR = c a b"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): priorities: custom suffix")
+            << "MOD.a.depends =\n"
+               "MOD.a.prrt = 1\n"
+               "MOD.b.depends =\n"
+               "MOD.b.prrt = 0\n"
+               "MOD.c.depends = a b\n"
+               "VAR = $$resolve_depends($$list(c), MOD., .depends, .prrt)"
+            << "VAR = c a b"
+            << ""
+            << true;
+
+    QTest::newRow("$$resolve_depends(): bad number of arguments")
+            << "VAR = $$resolve_depends(1, 2, 3, 4, 5)"
+            << "VAR ="
+            << "##:1: resolve_depends(var, [prefix, [suffixes, [prio-suffix]]]) requires one to four arguments."
+            << true;
+
+    QTest::newRow("$$enumerate_vars()")
+            << "V1 = foo\nV2 = bar\nVAR = $$enumerate_vars()\n"
+               "count(VAR, 2, >=):contains(VAR, V1):contains(VAR, V2): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("$$shadowed(): bare")
+            << "VAR = $$shadowed(test.txt)"
+            << "VAR = " + QMakeEvaluator::quoteValue(ProString(m_outdir + "/test.txt"))
+            << ""
+            << true;
+
+    QTest::newRow("$$shadowed(): subdir")
+            << "VAR = $$shadowed(" + qindir + "/sub/test.txt)"
+            << "VAR = " + QMakeEvaluator::quoteValue(ProString(m_outdir + "/sub/test.txt"))
+            << ""
+            << true;
+
+    QTest::newRow("$$shadowed(): outside source dir")
+            << "VAR = $$shadowed(/some/random/path)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$shadowed(): bad number of arguments")
+            << "VAR = $$shadowed(1, 2)"
+            << "VAR ="
+            << "##:1: shadowed(path) requires one argument."
+            << true;
+
+    QTest::newRow("$$absolute_path(): relative file")
+            << "VAR = $$absolute_path(dir/file.ext)"
+            << "VAR = " + qindir + "/dir/file.ext"
+            << ""
+            << true;
+
+    QTest::newRow("$$absolute_path(): file & path")
+            << "VAR = $$absolute_path(dir/file.ext, /root/sub)"
+            << "VAR = /root/sub/dir/file.ext"
+            << ""
+            << true;
+
+    QTest::newRow("$$absolute_path(): absolute file & path")
+            << "VAR = $$absolute_path(/root/sub/dir/file.ext, /other)"
+            << "VAR = /root/sub/dir/file.ext"
+            << ""
+            << true;
+
+    QTest::newRow("$$absolute_path(): empty file & path")
+            << "VAR = $$absolute_path('', /root/sub)"
+            << "VAR = /root/sub"
+            << ""
+            << true;
+
+    QTest::newRow("$$absolute_path(): bad number of arguments")
+            << "VAR = $$absolute_path(1, 2, 3)"
+            << "VAR ="
+            << "##:1: absolute_path(path[, base]) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$relative_path(): relative file")
+            << "VAR = $$relative_path(dir/file.ext)"
+            << "VAR = dir/file.ext"
+            << ""
+            << true;
+
+    QTest::newRow("$$relative_path(): relative file to empty")
+            << "VAR = $$relative_path(dir/..)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$relative_path(): absolute file & path")
+            << "VAR = $$relative_path(/root/sub/dir/file.ext, /root/sub)"
+            << "VAR = dir/file.ext"
+            << ""
+            << true;
+
+    QTest::newRow("$$relative_path(): empty file & path")
+            << "VAR = $$relative_path('', /root/sub)"
+            << "VAR ="
+            << ""
+            << true;
+
+    QTest::newRow("$$relative_path(): bad number of arguments")
+            << "VAR = $$relative_path(1, 2, 3)"
+            << "VAR ="
+            << "##:1: relative_path(path[, base]) requires one or two arguments."
+            << true;
+
+    QTest::newRow("$$clean_path()")
+#ifdef Q_OS_WIN  // This is actually kinda stupid.
+            << "VAR = $$clean_path(foo//bar\\\\../baz/)"
+#else
+            << "VAR = $$clean_path(foo//bar/../baz/)"
+#endif
+            << "VAR = foo/baz"
+            << ""
+            << true;
+
+    QTest::newRow("$$clean_path(): bad number of arguments")
+            << "VAR = $$clean_path(1, 2)"
+            << "VAR ="
+            << "##:1: clean_path(path) requires one argument."
+            << true;
+
+    QTest::newRow("$$system_path()")
+            << "VAR = $$system_path(foo/bar\\\\baz)"
+#ifdef Q_OS_WIN
+            << "VAR = foo\\\\bar\\\\baz"
+#else
+            << "VAR = foo/bar/baz"
+#endif
+            << ""
+            << true;
+
+    QTest::newRow("$$system_path(): bad number of arguments")
+            << "VAR = $$system_path(1, 2)"
+            << "VAR ="
+            << "##:1: system_path(path) requires one argument."
+            << true;
+
+    // This is is effectively $$system_path() in this test, as we load no specs
+    QTest::newRow("$$shell_path()")
+            << "VAR = $$shell_path(foo/bar\\\\baz)"
+#ifdef Q_OS_WIN
+            << "VAR = foo\\\\bar\\\\baz"
+#else
+            << "VAR = foo/bar/baz"
+#endif
+            << ""
+            << true;
+
+    QTest::newRow("$$shell_path(): bad number of arguments")
+            << "VAR = $$shell_path(1, 2)"
+            << "VAR ="
+            << "##:1: shell_path(path) requires one argument."
+            << true;
+
+    // The quoteArgs() test exercises this more thoroughly
+    QTest::newRow("$$system_quote()")
+            << "IN = \nVAR = $$system_quote(\"some nasty & ugly\\\" path & thing\\\\\")"
+#ifdef Q_OS_WIN
+            << "VAR = \"\\\"some nasty & ugly\\\\\\\" path ^& thing\\\\\\\\^\\\"\""
+#else
+            << "VAR = \"'some nasty & ugly\\\" path & thing\\\\'\""
+#endif
+            << ""
+            << true;
+
+    QTest::newRow("$$system_quote(): bad number of arguments")
+            << "VAR = $$system_quote(1, 2)"
+            << "VAR ="
+            << "##:1: system_quote(arg) requires one argument."
+            << true;
+
+    // This is is effectively $$system_path() in this test, as we load no specs
+    QTest::newRow("$$shell_quote()")
+            << "IN = \nVAR = $$shell_quote(\"some nasty & ugly\\\" path & thing\\\\\")"
+#ifdef Q_OS_WIN
+            << "VAR = \"\\\"some nasty & ugly\\\\\\\" path ^& thing\\\\\\\\^\\\"\""
+#else
+            << "VAR = \"'some nasty & ugly\\\" path & thing\\\\'\""
+#endif
+            << ""
+            << true;
+
+    QTest::newRow("$$shell_quote(): bad number of arguments")
+            << "VAR = $$shell_quote(1, 2)"
+            << "VAR ="
+            << "##:1: shell_quote(arg) requires one argument."
+            << true;
+
+    QTest::newRow("$$getenv()")
+            << "VAR = $$getenv(E1)"
+            << "VAR = 'env var'"
+            << ""
+            << true;
+
+    QTest::newRow("$$getenv(): bad number of arguments")
+            << "VAR = $$getenv(1, 2)"
+            << "VAR ="
+            << "##:1: getenv(arg) requires one argument."
+            << true;
+}
+
+void tst_qmakelib::addTestFunctions(const QString &qindir)
+{
+    QTest::newRow("defined(): found replace")
+            << "defineReplace(func) {}\ndefined(func): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("defined(): found test")
+            << "defineTest(func) {}\ndefined(func): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("defined(): not found")
+            << "defined(func): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("defined(replace): found")
+            << "defineReplace(func) {}\ndefined(func, replace): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("defined(replace): not found")
+            << "defineTest(func) {}\ndefined(func, replace): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("defined(test): found")
+            << "defineTest(func) {}\ndefined(func, test): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("defined(test): not found")
+            << "defineReplace(func) {}\ndefined(func, test): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("defined(var): found")
+            << "VAR = 1\ndefined(VAR, var): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("defined(var): not found")
+            << "defined(VAR, var): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("defined(): invalid type")
+            << "defined(VAR, nope): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: defined(function, type): unexpected type [nope]."
+            << true;
+
+    QTest::newRow("defined(): bad number of arguments")
+            << "defined(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: defined(function, [\"test\"|\"replace\"|\"var\"]) requires one or two arguments."
+            << true;
+
+    QTest::newRow("export()")
+            << "defineTest(func) {\n"
+                   "VAR1 += different\nexport(VAR1)\n"
+                   "unset(VAR2)\nexport(VAR2): OK = 1\nexport(OK)\n"
+                   "VAR3 = new var\nexport(VAR3)\n"
+               "}\n"
+               "VAR1 = entirely\nVAR2 = set\nfunc()"
+            << "OK = 1\nVAR1 = entirely different\nVAR2 =\nVAR3 = new var"
+            << ""
+            << true;
+
+    QTest::newRow("export(): bad number of arguments")
+            << "export(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: export(variable) requires one argument."
+            << true;
+
+    QTest::newRow("infile(): found")
+            << "infile(" + qindir + "/fromfile/infile.prx, DEFINES): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("infile(): not found")
+            << "infile(" + qindir + "/fromfile/infile.prx, INCLUDES): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("infile(plain): found")
+            << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, QT_DLL): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("infile(plain): not found")
+            << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, NOPE): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("infile(regex): found")
+            << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, QT_.*): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("infile(regex): not found")
+            << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, NO.*): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    // The early return is debatable, esp. as it's inconsistent with $$fromfile()
+    QTest::newRow("infile(): bad file")
+            << "infile(" + qindir + "/fromfile/badfile.prx, DEFINES): OK = 1\nOKE = 1"
+            << "OK = UNDEF\nOKE = UNDEF"
+            << "Project ERROR: fail!"
+            << false;
+
+    QTest::newRow("infile(): bad number of arguments")
+            << "infile(1): OK = 1\ninfile(1, 2, 3, 4): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: infile(file, var, [values]) requires two or three arguments.\n"
+               "##:2: infile(file, var, [values]) requires two or three arguments."
+            << true;
+
+    QTest::newRow("requires()")
+            << "requires(true, false, isEmpty(FOO), !isEmpty(BAR), true|false, true:false)"
+            << "QMAKE_FAILED_REQUIREMENTS = false !isEmpty(BAR) true:false"
+            << ""
+            << true;
+
+    // The sparator semantics are *very* questionable.
+    // The return value semantics are rather questionable.
+    QTest::newRow("eval()")
+            << "eval(FOO = one, two$$escape_expand(\\\\n)BAR = blah$$escape_expand(\\\\n)error(fail)$$escape_expand(\\\\n)BAZ = nope)"
+            << "FOO = one two\nBAR = blah\nBAZ = UNDEF"
+            << "Project ERROR: fail"
+            << true;
+
+    QTest::newRow("if(): true")
+            << "if(false|true): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("if(): true (space)")
+            << "if(false| true): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("if(): true (spaces)")
+            << "if( false | true ): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("if(): false")
+            << "if(false:true): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("if(): false (space)")
+            << "if(false: true): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("if(): false (spaces)")
+            << "if( false : true ): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("if(): bad number of arguments")
+            << "if(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: if(condition) requires one argument."
+            << true;
+
+    QTest::newRow("CONFIG(simple): true")
+            << "CONFIG = debug release\nCONFIG(debug): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("CONFIG(simple): false")
+            << "CONFIG = debug release\nCONFIG(nope): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("CONFIG(alt): true")
+            << "CONFIG = debug release\nCONFIG(release, debug|release): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("CONFIG(alt): false (presence)")
+            << "CONFIG = not here\nCONFIG(debug, debug|release): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("CONFIG(alt): false (order)")
+            << "CONFIG = debug release\nCONFIG(debug, debug|release): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("CONFIG(): bad number of arguments")
+            << "CONFIG(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: CONFIG(config) requires one or two arguments."
+            << true;
+
+    QTest::newRow("contains(simple plain): true")
+            << "VAR = one two three\ncontains(VAR, two): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("contains(simple plain): false")
+            << "VAR = one two three\ncontains(VAR, four): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(simple regex): true")
+            << "VAR = one two three\ncontains(VAR, tw.*): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("contains(simple regex): false")
+            << "VAR = one two three\ncontains(VAR, fo.*): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt plain): true")
+            << "VAR = one two three\ncontains(VAR, three, two|three): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt plain): false (presence)")
+            << "VAR = one four five\ncontains(VAR, three, two|three): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt plain): false (order)")
+            << "VAR = one two three\ncontains(VAR, two, two|three): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt regex): true")
+            << "VAR = one two three\ncontains(VAR, th.*, two|three): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt regex): false (presence)")
+            << "VAR = one four five\ncontains(VAR, th.*, two|three): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(alt regex): false (order)")
+            << "VAR = one two three\ncontains(VAR, tw.*, two|three): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("contains(): bad number of arguments")
+            << "contains(1): OK = 1\ncontains(1, 2, 3, 4): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: contains(var, val) requires two or three arguments.\n"
+               "##:2: contains(var, val) requires two or three arguments."
+            << true;
+
+    QTest::newRow("count(): true")
+            << "VAR = one two three\ncount(VAR, 3): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("count(): false")
+            << "VAR = one two three\ncount(VAR, 4): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("count(operators): true")
+            << "VAR = one two three\n"
+               "count(VAR, 3, equals): OKE1 = 1\n"
+               "count(VAR, 3, isEqual): OKE2 = 1\n"
+               "count(VAR, 3, =): OKE3 = 1\n"
+               "count(VAR, 3, ==): OKE4 = 1\n"
+               "count(VAR, 2, greaterThan): OKG1 = 1\n"
+               "count(VAR, 2, >): OKG2 = 1\n"
+               "count(VAR, 2, >=): OKGE = 1\n"
+               "count(VAR, 4, lessThan): OKL1 = 1\n"
+               "count(VAR, 4, <): OKL2 = 1\n"
+               "count(VAR, 4, <=): OKLE = 1\n"
+            << "OKE1 = 1\nOKE2 = 1\nOKE3 = 1\nOKE4 = 1\n"
+               "OKG1 = 1\nOKG2 = 1\nOKGE = 1\n"
+               "OKL1 = 1\nOKL2 = 1\nOKLE = 1"
+            << ""
+            << true;
+
+    QTest::newRow("count(operators): false")
+            << "VAR = one two three\n"
+               "count(VAR, 4, equals): OKE1 = 1\n"
+               "count(VAR, 4, isEqual): OKE2 = 1\n"
+               "count(VAR, 4, =): OKE3 = 1\n"
+               "count(VAR, 4, ==): OKE4 = 1\n"
+               "count(VAR, 3, greaterThan): OKG1 = 1\n"
+               "count(VAR, 3, >): OKG2 = 1\n"
+               "count(VAR, 4, >=): OKGE = 1\n"
+               "count(VAR, 3, lessThan): OKL1 = 1\n"
+               "count(VAR, 3, <): OKL2 = 1\n"
+               "count(VAR, 2, <=): OKLE = 1\n"
+            << "OKE1 = UNDEF\nOKE2 = UNDEF\nOKE3 = UNDEF\nOKE4 = UNDEF\n"
+               "OKG1 = UNDEF\nOKG2 = UNDEF\nOKGE = UNDEF\n"
+               "OKL1 = UNDEF\nOKL2 = UNDEF\nOKLE = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("count(): bad operator")
+            << "VAR = one two three\ncount(VAR, 2, !!!): OK = 1"
+            << "OK = UNDEF"
+            << "##:2: Unexpected modifier to count(!!!)."
+            << true;
+
+    QTest::newRow("count(): bad number of arguments")
+            << "count(1): OK = 1\ncount(1, 2, 3, 4): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: count(var, count, op=\"equals\") requires two or three arguments.\n"
+               "##:2: count(var, count, op=\"equals\") requires two or three arguments."
+            << true;
+
+    QTest::newRow("greaterThan(int): true")
+            << "VAR = 20\ngreaterThan(VAR, 3): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("greaterThan(int): false")
+            << "VAR = 3\ngreaterThan(VAR, 20): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("greaterThan(string): true")
+            << "VAR = foo 3\ngreaterThan(VAR, foo 20): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("greaterThan(string): false")
+            << "VAR = foo 20\ngreaterThan(VAR, foo 3): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("greaterThan(): bad number of arguments")
+            << "greaterThan(1): OK = 1\ngreaterThan(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: greaterThan(variable, value) requires two arguments.\n"
+               "##:2: greaterThan(variable, value) requires two arguments."
+            << true;
+
+    QTest::newRow("lessThan(int): true")
+            << "VAR = 3\nlessThan(VAR, 20): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("lessThan(int): false")
+            << "VAR = 20\nlessThan(VAR, 3): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("lessThan(string): true")
+            << "VAR = foo 20\nlessThan(VAR, foo 3): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("lessThan(string): false")
+            << "VAR = foo 3\nlessThan(VAR, foo 20): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("lessThan(): bad number of arguments")
+            << "lessThan(1): OK = 1\nlessThan(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: lessThan(variable, value) requires two arguments.\n"
+               "##:2: lessThan(variable, value) requires two arguments."
+            << true;
+
+    QTest::newRow("equals(): true")
+            << "VAR = foo\nequals(VAR, foo): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("equals(): false")
+            << "VAR = foo\nequals(VAR, bar): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("equals(): bad number of arguments")
+            << "equals(1): OK = 1\nequals(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: equals(variable, value) requires two arguments.\n"
+               "##:2: equals(variable, value) requires two arguments."
+            << true;
+
+    // That's just an alias, so don't test much.
+    QTest::newRow("isEqual(): true")
+            << "VAR = foo\nisEqual(VAR, foo): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("clear(): top-level")
+            << "VAR = there\nclear(VAR): OK = 1"
+            << "OK = 1\nVAR ="
+            << ""
+            << true;
+
+    QTest::newRow("clear(): scoped")
+            << "defineTest(func) {\n"
+                   "clear(VAR): OK = 1\nexport(OK)\n"
+                   "equals(VAR, \"\"): OKE = 1\nexport(OKE)\n"
+               "}\n"
+               "VAR = there\nfunc()"
+            << "OK = 1\nOKE = 1"
+            << ""
+            << true;
+
+    QTest::newRow("clear(): absent")
+            << "clear(VAR): OK = 1"
+            << "OK = UNDEF\nVAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("clear(): bad number of arguments")
+            << "clear(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: clear(variable) requires one argument."
+            << true;
+
+    QTest::newRow("unset(): top-level")
+            << "VAR = there\nunset(VAR): OK = 1"
+            << "OK = 1\nVAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("unset(): scoped")
+            << "defineTest(func) {\n"
+                   "unset(VAR): OK = 1\nexport(OK)\n"
+                   "!defined(VAR, var): OKE = 1\nexport(OKE)\n"
+               "}\n"
+               "VAR = there\nfunc()"
+            << "OK = 1\nOKE = 1"
+            << ""
+            << true;
+
+    QTest::newRow("unset(): absent")
+            << "unset(VAR): OK = 1"
+            << "OK = UNDEF\nVAR = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("unset(): bad number of arguments")
+            << "unset(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: unset(variable) requires one argument."
+            << true;
+
+    // This function does not follow the established naming pattern.
+    QTest::newRow("parseJson()")
+            << "jsontext = \\\n"
+               "    \"{\"\\\n"
+               "    \"    \\\"array\\\" : [\\\"arrayItem1\\\", \\\"arrayItem2\\\", \\\"arrayItem3\\\"],\"\\\n"
+               "    \"    \\\"object\\\" : { \\\"key1\\\" : \\\"objectValue1\\\", \\\"key2\\\" : \\\"objectValue2\\\" },\"\\\n"
+               "    \"    \\\"string\\\" : \\\"test string\\\",\"\\\n"
+               "    \"    \\\"number\\\" : 999,\"\\\n"
+               "    \"    \\\"true\\\" : true,\"\\\n"
+               "    \"    \\\"false\\\" :false,\"\"\\\n"
+               "    \"    \\\"null\\\" : null\"\"\\\n"
+               "    \"}\"\n"
+               "parseJson(jsontext, json): OK = 1"
+            << "OK = 1\n"
+               "json._KEYS_ = array false null number object string true\n"
+               // array
+               "json.array._KEYS_ = 0 1 2\n"
+               "json.array.0 = arrayItem1\n"
+               "json.array.1 = arrayItem2\n"
+               "json.array.2 = arrayItem3\n"
+               // object
+               "json.object._KEYS_ = key1 key2\n"
+               "json.object.key1 = objectValue1\n"
+               "json.object.key1 = objectValue1\n"
+                // value types
+               "json.string = 'test string'\n"
+               "json.number = 999\n"
+               "json.true = true\n"
+               "json.false = false\n"
+               "json.null = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("parseJson(): bad input")
+            << "jsontext = not good\n"
+               "parseJson(jsontext, json): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("parseJson(): bad number of arguments")
+            << "parseJson(1): OK = 1\nparseJson(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: parseJson(variable, into) requires two arguments.\n"
+               "##:2: parseJson(variable, into) requires two arguments."
+            << true;
+
+    QTest::newRow("include()")
+            << "include(include/inc.pri): OK = 1\nfunc()"
+            << "OK = 1\nVAR = val\n.VAR = nope"
+            << "Project MESSAGE: say hi!"
+            << true;
+
+    QTest::newRow("include(): fail")
+            << "include(include/nope.pri): OK = 1"
+            << "OK = UNDEF"
+            << "Cannot read " + m_indir + "/include/nope.pri: No such file or directory"
+            << true;
+
+    QTest::newRow("include(): silent fail")
+            << "include(include/nope.pri, , true): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("include(into)")
+            << "SUB.MISS = 1\ninclude(include/inc.pri, SUB): OK = 1"
+            << "OK = 1\nSUB.VAR = val\nSUB..VAR = UNDEF\nSUB.MISS = UNDEF\n"
+               // As a side effect, we test some things that need full project setup
+               "SUB.MATCH = 1\nSUB.QMAKESPEC = " + qindir + "/mkspecs/fake-g++"
+            << ""
+            << true;
+
+    QTest::newRow("include(): bad number of arguments")
+            << "include(1, 2, 3, 4): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: include(file, [into, [silent]]) requires one, two or three arguments."
+            << true;
+
+    QTest::newRow("load()")
+            << "load(testfeat): OK = 1"
+            << "OK = 1\nVAR = foo bar"
+            << ""
+            << true;
+
+    QTest::newRow("load(): fail")
+            << "load(no_such_feature): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: Cannot find feature no_such_feature"
+            << true;
+
+    QTest::newRow("load(): silent fail")
+            << "load(no_such_feature, true): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("load(): bad number of arguments")
+            << "load(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: load(feature) requires one or two arguments."
+            << true;
+
+    // We don't test debug() and log(), because they print directly to stderr.
+
+    QTest::newRow("message()")
+            << "message('Hello, World!'): OK = 1\nOKE = 1"
+            << "OK = 1\nOKE = 1"
+            << "Project MESSAGE: Hello, World!"
+            << true;
+
+    // Don't test that for warning() and error(), as it's the same code path.
+    QTest::newRow("message(): bad number of arguments")
+            << "message(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: message(message) requires one argument."
+            << true;
+
+    QTest::newRow("warning()")
+            << "warning('World, be warned!'): OK = 1\nOKE = 1"
+            << "OK = 1\nOKE = 1"
+            << "Project WARNING: World, be warned!"
+            << true;
+
+    QTest::newRow("error()")
+            << "error('World, you FAIL!'): OK = 1\nOKE = 1"
+            << "OK = UNDEF\nOKE = UNDEF"
+            << "Project ERROR: World, you FAIL!"
+            << false;
+
+    QTest::newRow("system()")
+            << "system('"
+#ifdef Q_OS_WIN
+               "cd"
+#else
+               "pwd"
+#endif
+               "> '" + QMakeEvaluator::quoteValue(ProString(QDir::toNativeSeparators(
+                            m_outdir + "/system_out.txt"))) + "): OK = 1\n"
+               "DIR = $$cat(" + QMakeEvaluator::quoteValue(ProString(
+                            m_outdir + "/system_out.txt")) + ")"
+            << "OK = 1\nDIR = " + QMakeEvaluator::quoteValue(ProString(QDir::toNativeSeparators(m_indir)))
+            << ""
+            << true;
+
+    QTest::newRow("system(): fail")
+#ifdef Q_OS_WIN
+            << "system(no_such_cmd 2> NUL): OK = 1"
+#else
+            << "system(no_such_cmd 2> /dev/null): OK = 1"
+#endif
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("system(): bad number of arguments")
+            << "system(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: system(exec) requires one argument."
+            << true;
+
+    QTest::newRow("isEmpty(): true (empty)")
+            << "VAR =\nisEmpty(VAR): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("isEmpty(): true (undef)")
+            << "isEmpty(VAR): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("isEmpty(): false")
+            << "VAR = val\nisEmpty(VAR): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("isEmpty(): bad number of arguments")
+            << "isEmpty(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: isEmpty(var) requires one argument."
+            << true;
+
+    QTest::newRow("exists(plain): true")
+            << "exists(files/file1.txt): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("exists(plain): false")
+            << "exists(files/not_there.txt): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("exists(wildcard): true")
+            << "exists(files/fil*.txt): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("exists(wildcard): false")
+            << "exists(files/not_th*.txt): OK = 1"
+            << "OK = UNDEF"
+            << ""
+            << true;
+
+    QTest::newRow("exists(): bad number of arguments")
+            << "exists(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: exists(file) requires one argument."
+            << true;
+
+    QString wpath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/outdir/written.txt"));
+    QTest::newRow("write_file(): create")
+            << "VAR = 'this is text' 'yet again'\n"
+               "write_file(" + wpath + ", VAR): OK = 1\n"
+               "OUT = $$cat(" + wpath + ", lines)"
+            << "OK = 1\nOUT = 'this is text' 'yet again'"
+            << ""
+            << true;
+
+    QTest::newRow("write_file(): truncate")
+            << "VAR = 'other content'\n"
+               "write_file(" + wpath + ", VAR): OK = 1\n"
+               "OUT = $$cat(" + wpath + ", lines)"
+            << "OK = 1\nOUT = 'other content'"
+            << ""
+            << true;
+
+    QTest::newRow("write_file(): append")
+            << "VAR = 'one more line'\n"
+               "write_file(" + wpath + ", VAR, append): OK = 1\n"
+               "OUT = $$cat(" + wpath + ", lines)"
+            << "OK = 1\nOUT = 'other content' 'one more line'"
+            << ""
+            << true;
+
+    QString vpath = QMakeEvaluator::quoteValue(ProString(m_outdir));
+    QTest::newRow("write_file(): fail")
+            << "write_file(" + vpath + "): OK = 1"
+            << "OK = UNDEF"
+#ifdef Q_OS_WIN
+            << "##:1: Cannot write file " + QDir::toNativeSeparators(m_outdir) + ": Access is denied."
+#else
+            << "##:1: Cannot write file " + m_outdir + ": Is a directory"
+#endif
+            << true;
+
+    QTest::newRow("write_file(): bad number of arguments")
+            << "write_file(1, 2, 3, 4): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: write_file(name, [content var, [append]]) requires one to three arguments."
+            << true;
+
+    // FIXME: This doesn't test whether it actually works.
+    QTest::newRow("touch()")
+            << "touch(" + wpath + ", files/other.txt): OK = 1"
+            << "OK = 1"
+            << ""
+            << true;
+
+    QTest::newRow("touch(): missing target")
+            << "touch(/does/not/exist, files/other.txt): OK = 1"
+            << "OK = UNDEF"
+#ifdef Q_OS_WIN
+            << "##:1: Cannot open /does/not/exist: The system cannot find the path specified."
+#else
+            << "##:1: Cannot touch /does/not/exist: No such file or directory."
+#endif
+            << true;
+
+    QTest::newRow("touch(): missing reference")
+            << "touch(" + wpath + ", /does/not/exist): OK = 1"
+            << "OK = UNDEF"
+#ifdef Q_OS_WIN
+            << "##:1: Cannot open reference file /does/not/exist: The system cannot find the path specified."
+#else
+            << "##:1: Cannot stat() reference file /does/not/exist: No such file or directory."
+#endif
+            << true;
+
+    QTest::newRow("touch(): bad number of arguments")
+            << "touch(1): OK = 1\ntouch(1, 2, 3): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: touch(file, reffile) requires two arguments.\n"
+               "##:2: touch(file, reffile) requires two arguments."
+            << true;
+
+    QString apath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/a/path"));
+    QTest::newRow("mkpath()")
+            << "mkpath(" + apath + "): OK = 1\n"
+               "exists(" + apath + "): OKE = 1"
+            << "OK = 1\nOKE = 1"
+            << ""
+            << true;
+
+    QString bpath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/fail_me"));
+    QTest::newRow("mkpath(): fail")
+            << "write_file(" + bpath + ")|error(FAIL)\n"
+               "mkpath(" + bpath + "): OK = 1"
+            << "OK = UNDEF"
+            << "##:2: Cannot create directory " + QDir::toNativeSeparators(m_outdir + "/fail_me") + '.'
+            << true;
+
+    QTest::newRow("mkpath(): bad number of arguments")
+            << "mkpath(1, 2): OK = 1"
+            << "OK = UNDEF"
+            << "##:1: mkpath(file) requires one argument."
+            << true;
+
+#if 0
+    // FIXME ... insanity lies ahead
+    QTest::newRow("cache()")
+            << ""
+            << ""
+            << ""
+            << true;
+#endif
+}
+
+void tst_qmakelib::proEval_data()
+{
+    QTest::addColumn<QString>("in");
+    QTest::addColumn<QString>("out");
+    QTest::addColumn<QString>("msgs");
+    QTest::addColumn<bool>("ok");
+
+    QTest::newRow("empty")
+            << ""
+            << "VAR = UNDEF"
+            << ""
+            << true;
+
+    addAssignments();
+    addExpansions(); // Variable, etc. expansions on RHS
+    addControlStructs(); // Conditions, loops, custom functions
+
+    QString qindir = QMakeEvaluator::quoteValue(ProString(m_indir));
+    addReplaceFunctions(qindir); // Built-in replace functions
+    addTestFunctions(qindir); // Built-in test functions
+
+    // Some compound tests that verify compatibility with odd Qt 4 edge cases
+
+    QTest::newRow("empty (leading)")
+            << "defineTest(myMsg) { message(\"$$1\") }\n"
+               "XMPL = /this/is/a/test\n"
+               "message(split: $$split(XMPL, /))\n"
+               "message(split joined:$$split(XMPL, /))\n"
+               "message(\"split quoted: $$split(XMPL, /)\")\n"
+               "myMsg(my split: $$split(XMPL, /) :post)\n"
+               "myMsg(my split joined:$$split(XMPL, /):post)\n"
+               "myMsg(\"my split quoted: $$split(XMPL, /) post\")\n"
+               "OUT = word $$split(XMPL, /) done\n"
+               "message(\"assign split separate: $$OUT\")\n"
+               "OUT = word:$$split(XMPL, /):done\n"
+               "message(\"assign split joined: $$OUT\")\n"
+               "OUT = \"word $$split(XMPL, /) done\"\n"
+               "message(\"assign split quoted: $$OUT\")\n"
+            << ""
+            << "Project MESSAGE: split: this is a test\n"
+               "Project MESSAGE: split joined: this is a test\n"
+               "Project MESSAGE: split quoted:  this is a test\n"
+               "Project MESSAGE: my split: this is a test :post\n"
+               "Project MESSAGE: my split joined: this is a test:post\n"
+               "Project MESSAGE: my split quoted:  this is a test post\n"
+               "Project MESSAGE: assign split separate: word this is a test done\n"
+               "Project MESSAGE: assign split joined: word: this is a test:done\n"
+               "Project MESSAGE: assign split quoted: word  this is a test done"
+            << true;
+
+    QTest::newRow("empty (multiple)")
+            << "defineTest(myMsg) { message(\"$$1\") }\n"
+               "XMPL = //this///is/a/////test\n"
+               "message(split: $$split(XMPL, /) :post)\n"
+               "message(split joined:$$split(XMPL, /):post)\n"
+               "message(\"split quoted: $$split(XMPL, /) post\")\n"
+               "myMsg(my split: $$split(XMPL, /) :post)\n"
+               "myMsg(my split joined:$$split(XMPL, /):post)\n"
+               "myMsg(\"my split quoted: $$split(XMPL, /) post\")\n"
+               "OUT = word $$split(XMPL, /) done\n"
+               "message(\"assign split separate: $$OUT\")\n"
+               "OUT = word:$$split(XMPL, /):done\n"
+               "message(\"assign split joined: $$OUT\")\n"
+               "OUT = \"word $$split(XMPL, /) done\"\n"
+               "message(\"assign split quoted: $$OUT\")\n"
+            << ""
+            << "Project MESSAGE: split:  this   is a     test :post\n"
+               "Project MESSAGE: split joined:  this   is a     test:post\n"
+               "Project MESSAGE: split quoted:   this   is a     test post\n"
+               "Project MESSAGE: my split:  this   is a     test :post\n"
+               "Project MESSAGE: my split joined:  this   is a     test:post\n"
+               "Project MESSAGE: my split quoted:   this   is a     test post\n"
+               "Project MESSAGE: assign split separate: word this is a test done\n"
+               "Project MESSAGE: assign split joined: word: this is a test:done\n"
+               "Project MESSAGE: assign split quoted: word   this   is a     test done"
+            << true;
+}
+
+static QString formatValue(const ProStringList &vals)
+{
+    QString ret;
+
+    foreach (const ProString &str, vals) {
+        ret += QLatin1Char(' ');
+        ret += QMakeEvaluator::quoteValue(str);
+    }
+    return ret;
+}
+
+static void skipNoise(const ushort *&tokPtr)
+{
+    forever {
+        ushort tok = *tokPtr;
+        if (tok != TokLine)
+            break;
+        tokPtr += 2;
+    }
+}
+
+static bool compareState(QMakeEvaluator *eval, ProFile *out)
+{
+    bool ret = true;
+    const ushort *tokPtr = out->tokPtr();
+    forever {
+        skipNoise(tokPtr);
+        ushort tok = *tokPtr++;
+        if (!tok)
+            break;
+        if (tok != TokHashLiteral) {
+            qWarning("Expected output is malformed: not variable%s",
+                     qPrintable(QMakeParser::formatProBlock(out->items())));
+            return false;
+        }
+        const ProKey &var = out->getHashStr(tokPtr);
+        tok = *tokPtr++;
+        if (tok != TokAssign) {
+            qWarning("Expected output is malformed: not assignment%s",
+                     qPrintable(QMakeParser::formatProBlock(out->items())));
+            return false;
+        }
+        ProStringList value;
+        value.reserve(*tokPtr++);
+        forever {
+            skipNoise(tokPtr);
+            tok = *tokPtr++;
+            if (tok == TokValueTerminator)
+                break;
+            if (tok != (TokLiteral | TokNewStr)) {
+                qWarning("Expected output is malformed: not literal%s",
+                         qPrintable(QMakeParser::formatProBlock(out->items())));
+                return false;
+            }
+            value << out->getStr(tokPtr);
+        }
+        ProValueMap::Iterator it;
+        ProValueMap *vmap = eval->findValues(var, &it);
+        if (value.length() == 1 && value.at(0) == "UNDEF") {
+            if (vmap) {
+                qWarning("Value of %s is incorrect.\n  Actual:%s\nExpected: <UNDEFINED>",
+                         qPrintable(var.toQString()),
+                         qPrintable(formatValue(*it)));
+                ret = false;
+            }
+        } else {
+            if (!vmap) {
+                qWarning("Value of %s is incorrect.\n  Actual: <UNDEFINED>\nExpected:%s",
+                         qPrintable(var.toQString()),
+                         qPrintable(formatValue(value)));
+                ret = false;
+            } else if (*it != value) {
+                qWarning("Value of %s is incorrect.\n  Actual:%s\nExpected:%s",
+                         qPrintable(var.toQString()),
+                         qPrintable(formatValue(*it)), qPrintable(formatValue(value)));
+                ret = false;
+            }
+        }
+    }
+    return ret;
+}
+
+void tst_qmakelib::proEval()
+{
+    QFETCH(QString, in);
+    QFETCH(QString, out);
+    QFETCH(QString, msgs);
+    QFETCH(bool, ok);
+
+    QString infile = m_indir + "/test.pro";
+    bool verified = true;
+    QMakeTestHandler handler;
+    handler.setExpectedMessages(msgs.replace("##:", infile + ':').split('\n', QString::SkipEmptyParts));
+    QMakeVfs vfs;
+    QMakeParser parser(0, &vfs, &handler);
+    QMakeGlobals globals;
+    globals.do_cache = false;
+    globals.xqmakespec = "fake-g++";
+    globals.environment = m_env;
+    globals.setProperties(m_prop);
+    globals.setDirectories(m_indir, m_outdir);
+    ProFile *outPro = parser.parsedProBlock(out, "out", 1, QMakeParser::FullGrammar);
+    if (!outPro->isOk()) {
+        qWarning("Expected output is malformed");
+        verified = false;
+    }
+    ProFile *pro = parser.parsedProBlock(in, infile, 1, QMakeParser::FullGrammar);
+    QMakeEvaluator visitor(&globals, &parser, &vfs, &handler);
+    visitor.setOutputDir(m_outdir);
+#ifdef Q_OS_WIN
+    visitor.m_dirSep = ProString("\\");
+#else
+    visitor.m_dirSep = ProString("/");
+#endif
+    QMakeEvaluator::VisitReturn ret
+            = visitor.visitProFile(pro, QMakeHandler::EvalAuxFile, QMakeEvaluator::LoadProOnly);
+    if (handler.printedMessages()) {
+        qWarning("Got unexpected message(s)");
+        verified = false;
+    }
+    QStringList missingMsgs = handler.expectedMessages();
+    if (!missingMsgs.isEmpty()) {
+        foreach (const QString &msg, missingMsgs)
+            qWarning("Missing message: %s", qPrintable(msg));
+        verified = false;
+    }
+    if ((ret == QMakeEvaluator::ReturnTrue) != ok) {
+        static const char * const lbl[] = { "failure", "success" };
+        qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
+        verified = false;
+    }
+    if (!compareState(&visitor, outPro))
+        verified = false;
+    pro->deref();
+    outPro->deref();
+    QVERIFY(verified);
+}
diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a7b7431a98a041343f08853c78be70ac8c73cf57
--- /dev/null
+++ b/tests/auto/tools/qmakelib/parsertest.cpp
@@ -0,0 +1,1987 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include "tst_qmakelib.h"
+
+#include <proitems.h>
+#include <qmakevfs.h>
+#include <qmakeparser.h>
+
+class TokenStream
+{
+public:
+    TokenStream() {}
+    QString toString() const { return ts; }
+
+    TokenStream &operator<<(ushort n) { ts += QChar(n); return *this; }
+    TokenStream &operator<<(uint n) { ts += QChar(n & 0xffff); ts += QChar(n >> 16); return *this; }
+    TokenStream &operator<<(const QStringRef &s) { ts += s; return *this; }
+    TokenStream &operator<<(const ProString &s) { return *this << ushort(s.length()) << s.toQStringRef(); }
+    TokenStream &operator<<(const ProKey &s) { return *this << s.hash() << s.toString(); }
+
+private:
+    QString ts;
+};
+
+#define TS(s) (TokenStream() s).toString()
+#define H(n) ushort(n)
+#define I(n) uint(n)
+#define S(s) ProString(QString::fromWCharArray(s))
+#define HS(s) ProKey(QString::fromWCharArray(s))
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4003)  // "not enough actual parameters for macro TS()"
+
+void tst_qmakelib::addParseOperators()
+{
+    QTest::newRow("assign none")
+            << "VAR ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("append none")
+            << "VAR +="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAppend) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("unique append none")
+            << "VAR *="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAppendUnique) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("remove none")
+            << "VAR -="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokRemove) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("replace empty")
+            << "VAR ~="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokReplace) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("assignment without variable")
+            << "="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokAssign) << H(0)
+    /*     4 */ << H(TokValueTerminator))
+            << "in:1: Assignment needs exactly one word on the left hand side."
+            << false;
+
+    QTest::newRow("assignment with multiple variables")
+            << "VAR VAR ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokAssign) << H(0)
+    /*     4 */ << H(TokValueTerminator))
+            << "in:1: Assignment needs exactly one word on the left hand side."
+            << false;
+}
+
+void tst_qmakelib::addParseValues()
+{
+#define ASSIGN_VAR(h) \
+        H(TokLine) << H(1) \
+        << H(TokHashLiteral) << HS(L"VAR") \
+        << H(TokAssign) << H(h)
+
+    QTest::newRow("one literal")
+            << "VAR = val"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val")
+    /*    16 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("one literal (squeezed)")
+            << "VAR=val"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val")
+    /*    16 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("many literals")
+            << "VAR = foo barbaz bak hello"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(4)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
+    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
+    /*    36 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("many literals (tab-separated")
+            << "VAR\t=\tfoo\tbarbaz\tbak\thello"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(4)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
+    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
+    /*    36 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("one quoted literal")
+            << "VAR = \"val ue\""
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val ue")
+    /*    19 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("quoted literal with missing quote")
+            << "VAR = val \"ue"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(0)
+    /*    11 */ << H(TokValueTerminator))
+            << "in:1: Missing closing \" quote"
+            << false;
+
+    QTest::newRow("many quoted literals")
+            << "VAR = \"foo\" barbaz    'bak hello' \"\""
+            << TS(
+    /*     0 */ << ASSIGN_VAR(3)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak hello")
+    /*    35 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("many quoted literals (with tabs)")
+            << "VAR\t=\t\"foo\"\tbarbaz\t'bak\thello'"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(3)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak\thello")
+    /*    35 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("quoted and unquoted spaces")
+            << "  VAR = \"val ue   \"   "
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val ue   ")
+    /*    22 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("funny literals")
+            << "VAR = foo:bar|!baz(blam!, ${foo})"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(2)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo:bar|!baz(blam!,")
+    /*    32 */ << H(TokLiteral | TokNewStr) << S(L"${foo})")
+    /*    41 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("literals with escapes")
+            << "VAR = \\{hi\\} \\[ho\\] \\)uh\\( \"\\\\oh\\$\"\\' \\$\\${FOO}"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(5)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{hi}")
+    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"[ho]")
+    /*    23 */ << H(TokLiteral | TokNewStr) << S(L")uh(")
+    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"\\oh$'")
+    /*    36 */ << H(TokLiteral | TokNewStr) << S(L"$${FOO}")
+    /*    45 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("magic variables")
+            << "VAR = $$LITERAL_HASH $$LITERAL_DOLLAR $$LITERAL_WHITESPACE $$_FILE_ $$_LINE_"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(5)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"#")
+    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"$")
+    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"\t")
+    /*    20 */ << H(TokLiteral | TokNewStr) << S(L"in")
+    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"1")
+    /*    27 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("continuations and comments")
+            << "VAR = foo \\\n  bar\n  \n"
+               "GAR = foo \\ # comment\n  bar \\\n   # comment\n baz \\\n"
+                    "\"quoted \\ #comment\n    escape\" \\\n    right\\\n      after \\\n    gorilla!\n \n\n"
+               "MOO = \\\n  kuh # comment\nLOO =\n\n"
+               "FOO = bar \\\n# comment\n   baz \\\n    \n# comment\n"
+               "GAZ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(2)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+    /*    21 */ << H(TokValueTerminator)
+    /*    22 */ << H(TokLine) << H(4)
+    /*    24 */ << H(TokHashLiteral) << HS(L"GAR")
+    /*    31 */ << H(TokAssign) << H(7)
+    /*    33 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    38 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+    /*    43 */ << H(TokLiteral | TokNewStr) << S(L"baz")
+    /*    48 */ << H(TokLiteral | TokNewStr) << S(L"quoted  escape")
+    /*    64 */ << H(TokLiteral | TokNewStr) << S(L"right")
+    /*    71 */ << H(TokLiteral | TokNewStr) << S(L"after")
+    /*    78 */ << H(TokLiteral | TokNewStr) << S(L"gorilla!")
+    /*    88 */ << H(TokValueTerminator)
+    /*    89 */ << H(TokLine) << H(15)
+    /*    91 */ << H(TokHashLiteral) << HS(L"MOO")
+    /*    98 */ << H(TokAssign) << H(0)
+    /*   100 */ << H(TokLiteral | TokNewStr) << S(L"kuh")
+    /*   105 */ << H(TokValueTerminator)
+    /*   106 */ << H(TokLine) << H(17)
+    /*   108 */ << H(TokHashLiteral) << HS(L"LOO")
+    /*   115 */ << H(TokAssign) << H(0)
+    /*   117 */ << H(TokValueTerminator)
+    /*   118 */ << H(TokLine) << H(19)
+    /*   120 */ << H(TokHashLiteral) << HS(L"FOO")
+    /*   127 */ << H(TokAssign) << H(2)
+    /*   129 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+    /*   134 */ << H(TokLiteral | TokNewStr) << S(L"baz")
+    /*   139 */ << H(TokValueTerminator)
+    /*   140 */ << H(TokLine) << H(24)
+    /*   142 */ << H(TokHashLiteral) << HS(L"GAZ")
+    /*   149 */ << H(TokAssign) << H(0)
+    /*   151 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("accidental continuation")
+            << "VAR0 = \\\n    this \\\n    is \\\n    ok\n"
+               "VAR1 = \\\n    this \\\n    is=still \\\n    ok\n"
+               "VAR2 = \\\n    this \\\n    is \\\n"
+               "VAR3 = \\\n    not ok\n"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR0")
+    /*    10 */ << H(TokAssign) << H(3)
+    /*    12 */ << H(TokLiteral | TokNewStr) << S(L"this")
+    /*    18 */ << H(TokLiteral | TokNewStr) << S(L"is")
+    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+    /*    26 */ << H(TokValueTerminator)
+    /*    27 */ << H(TokLine) << H(5)
+    /*    29 */ << H(TokHashLiteral) << HS(L"VAR1")
+    /*    37 */ << H(TokAssign) << H(3)
+    /*    39 */ << H(TokLiteral | TokNewStr) << S(L"this")
+    /*    45 */ << H(TokLiteral | TokNewStr) << S(L"is=still")
+    /*    55 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+    /*    59 */ << H(TokValueTerminator)
+    /*    60 */ << H(TokLine) << H(9)
+    /*    62 */ << H(TokHashLiteral) << HS(L"VAR2")
+    /*    70 */ << H(TokAssign) << H(6)
+    /*    72 */ << H(TokLiteral | TokNewStr) << S(L"this")
+    /*    78 */ << H(TokLiteral | TokNewStr) << S(L"is")
+    /*    82 */ << H(TokLiteral | TokNewStr) << S(L"VAR3")
+    /*    88 */ << H(TokLiteral | TokNewStr) << S(L"=")
+    /*    91 */ << H(TokLiteral | TokNewStr) << S(L"not")
+    /*    96 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+    /*   100 */ << H(TokValueTerminator))
+            << "WARNING: in:12: Possible accidental line continuation"
+            << true;
+
+    QTest::newRow("plain variable expansion")
+            << "VAR = $$bar"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+    /*    18 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("braced variable expansion")
+            << "VAR = $${foo/bar}"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"foo/bar")
+    /*    22 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("bogus variable expansion")
+            << "VAR = $$  "
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"")
+    /*    15 */ << H(TokValueTerminator))
+            << "WARNING: in:1: Missing name in expansion"
+            << true;
+
+    QTest::newRow("bogus braced variable expansion")
+            << "VAR = $${}"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"")
+    /*    15 */ << H(TokValueTerminator))
+            << "WARNING: in:1: Missing name in expansion"
+            << true;
+
+    QTest::newRow("unterminated braced variable expansion")
+            << "VAR = $${FOO"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"FOO")
+    /*    18 */ << H(TokValueTerminator))
+            << "in:1: Missing } terminator [found end-of-line]"
+            << false;
+
+    QTest::newRow("invalid identifier in braced variable expansion")
+            << "VAR = $${FOO/BAR+BAZ}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"FOO/BAR")
+    /*    22 */ << H(TokLiteral) << S(L"+BAZ")
+    /*    28 */ << H(TokValueTerminator))
+            << "in:1: Missing } terminator [found +]"
+            << false;
+
+    QTest::newRow("property expansion")
+            << "VAR = $$[bar]"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokProperty | TokNewStr) << HS(L"bar")
+    /*    18 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("environment expansion")
+            << "VAR = $$(bar)"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokEnvVar | TokNewStr) << S(L"bar")
+    /*    16 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("plain function call")
+            << "VAR = $$bar()"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    18 */     << H(TokFuncTerminator)
+    /*    19 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("braced function call")
+            << "VAR = $${bar()}"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    18 */     << H(TokFuncTerminator)
+    /*    19 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function call with one argument")
+            << "VAR = $$bar(blubb)"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
+    /*    25 */     << H(TokFuncTerminator)
+    /*    26 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function call with multiple arguments")
+            << "VAR = $$bar(  blubb blubb, hey  ,$$you)"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
+    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
+    /*    32 */     << H(TokArgSeparator)
+    /*    33 */     << H(TokLiteral | TokNewStr) << S(L"hey")
+    /*    38 */     << H(TokArgSeparator)
+    /*    39 */     << H(TokVariable | TokNewStr) << HS(L"you")
+    /*    46 */     << H(TokFuncTerminator)
+    /*    47 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("nested function call")
+            << "VAR = $$foo(yo, $$bar(blubb))"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"foo")
+    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"yo")
+    /*    22 */     << H(TokArgSeparator)
+    /*    23 */     << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    30 */         << H(TokLiteral | TokNewStr) << S(L"blubb")
+    /*    37 */         << H(TokFuncTerminator)
+    /*    38 */     << H(TokFuncTerminator)
+    /*    39 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("function call with parenthesized argument")
+            << "VAR = $$bar(blubb (yo, man) blabb, nope)"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
+    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"(yo,")
+    /*    31 */     << H(TokLiteral | TokNewStr) << S(L"man)")
+    /*    37 */     << H(TokLiteral | TokNewStr) << S(L"blabb")
+    /*    44 */     << H(TokArgSeparator)
+    /*    45 */     << H(TokLiteral | TokNewStr) << S(L"nope")
+    /*    51 */     << H(TokFuncTerminator)
+    /*    52 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("separate literal and expansion")
+            << "VAR = foo $$bar"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(2)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+    /*    23 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("separate expansion and literal")
+            << "VAR = $$bar foo"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+    /*    18 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    23 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("joined literal and expansion")
+            << "VAR = foo$$bar"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokVariable) << HS(L"bar")
+    /*    23 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("joined expansion and literal")
+            << "VAR = $${bar}foo"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+    /*    18 */ << H(TokLiteral) << S(L"foo")
+    /*    23 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("plain variable expansion with funny name and literal")
+            << "VAR = $$az_AZ_09.dot/nix"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot")
+    /*    27 */ << H(TokLiteral) << S(L"/nix")
+    /*    33 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("braced variable expansion with funny name")
+            << "VAR = $${az_AZ_09.dot/nix}"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot/nix")
+    /*    31 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("quoted joined literal and expansion")
+            << "VAR = 'foo$$bar'"
+            << TS(
+    /*     0 */ << ASSIGN_VAR(0)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    16 */ << H(TokVariable | TokQuoted) << HS(L"bar")
+    /*    23 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("assignment with expansion in variable name")
+            << "VAR$$EXTRA ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokVariable) << HS(L"EXTRA")
+    /*    18 */ << H(TokAssign) << H(0)
+    /*    20 */ << H(TokValueTerminator))
+            << ""
+            << true;
+}
+
+void tst_qmakelib::addParseConditions()
+{
+    QTest::newRow("one test")
+            << "foo"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("wildcard-test")
+            << "foo-*"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo-*")
+    /*    11 */ << H(TokCondition))
+            << ""
+            << true;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("one quoted test")
+            << "\"foo\""
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("two tests")
+            << "foo\nbar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokLine) << H(2)
+    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    19 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("bogus two tests")
+            << "foo bar\nbaz"
+            << TS()
+            << "in:1: Extra characters after test expression."
+            << false;
+
+    QTest::newRow("test-AND-test")
+            << "foo:bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("test-OR-test")
+            << "  foo  | bar "
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokOr)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("NOT-test")
+            << "!foo"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokNot)
+    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
+    /*    10 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("NOT-NOT-test")
+            << "!!foo"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition))
+            << ""
+            << true;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("quoted-NOT-test")
+            << "\"!foo\""
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokNot)
+    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
+    /*    10 */ << H(TokCondition))
+            << ""
+            << true;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("NOT-quoted-test")
+            << "!\"foo\""
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokNot)
+    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
+    /*    10 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-NOT-test")
+            << "foo:!bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokNot)
+    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    19 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("test-assignment")
+            << "foo\nVAR="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokLine) << H(2)
+    /*    12 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*    19 */ << H(TokAssign) << H(0)
+    /*    21 */ << H(TokValueTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-assignment")
+            << "foo: VAR ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokBranch)
+    /*    11 */ /* then branch */ << I(11)
+    /*    13 */     << H(TokHashLiteral) << HS(L"VAR")
+    /*    20 */     << H(TokAssign) << H(0)
+    /*    22 */     << H(TokValueTerminator)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-else-test")
+            << "foo\nelse: bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokBranch)
+    /*    11 */ /* then branch */ << I(0)
+    /*    13 */ /* else branch */ << I(11)
+    /*    15 */     << H(TokLine) << H(2)
+    /*    17 */     << H(TokHashLiteral) << HS(L"bar")
+    /*    24 */     << H(TokCondition)
+    /*    25 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function-else-test")
+            << "foo()\nelse: bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncTerminator)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(0)
+    /*    14 */ /* else branch */ << I(11)
+    /*    16 */     << H(TokLine) << H(2)
+    /*    18 */     << H(TokHashLiteral) << HS(L"bar")
+    /*    25 */     << H(TokCondition)
+    /*    26 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-test-else-test")
+            << "foo:bar\nelse: baz"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokCondition)
+    /*    19 */ << H(TokBranch)
+    /*    20 */ /* then branch */ << I(0)
+    /*    22 */ /* else branch */ << I(11)
+    /*    24 */     << H(TokLine) << H(2)
+    /*    26 */     << H(TokHashLiteral) << HS(L"baz")
+    /*    33 */     << H(TokCondition)
+    /*    34 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-test-else-test-else-test-function")
+            << "foo:bar\nelse: baz\nelse: bak\nbuzz()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokCondition)
+    /*    19 */ << H(TokBranch)
+    /*    20 */ /* then branch */ << I(0)
+    /*    22 */ /* else branch */ << I(27)
+    /*    24 */     << H(TokLine) << H(2)
+    /*    26 */     << H(TokHashLiteral) << HS(L"baz")
+    /*    33 */     << H(TokCondition)
+    /*    34 */     << H(TokBranch)
+    /*    35 */     /* then branch */ << I(0)
+    /*    37 */     /* else branch */ << I(11)
+    /*    39 */         << H(TokLine) << H(3)
+    /*    41 */         << H(TokHashLiteral) << HS(L"bak")
+    /*    48 */         << H(TokCondition)
+    /*    49 */         << H(TokTerminator)
+    /*    50 */     << H(TokTerminator)
+    /*    51 */ << H(TokLine) << H(4)
+    /*    53 */ << H(TokHashLiteral) << HS(L"buzz")
+    /*    61 */ << H(TokTestCall)
+    /*    62 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-assignment-else-assignment")
+            << "foo: VAR =\nelse: VAR="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokBranch)
+    /*    11 */ /* then branch */ << I(11)
+    /*    13 */     << H(TokHashLiteral) << HS(L"VAR")
+    /*    20 */     << H(TokAssign) << H(0)
+    /*    22 */     << H(TokValueTerminator)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(13)
+    /*    26 */     << H(TokLine) << H(2)
+    /*    28 */     << H(TokHashLiteral) << HS(L"VAR")
+    /*    35 */     << H(TokAssign) << H(0)
+    /*    37 */     << H(TokValueTerminator)
+    /*    38 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-else-test-assignment")
+            << "foo\nelse: bar: VAR ="
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokBranch)
+    /*    11 */ /* then branch */ << I(0)
+    /*    13 */ /* else branch */ << I(27)
+    /*    15 */     << H(TokLine) << H(2)
+    /*    17 */     << H(TokHashLiteral) << HS(L"bar")
+    /*    24 */     << H(TokCondition)
+    /*    25 */     << H(TokBranch)
+    /*    26 */     /* then branch */ << I(11)
+    /*    28 */         << H(TokHashLiteral) << HS(L"VAR")
+    /*    35 */         << H(TokAssign) << H(0)
+    /*    37 */         << H(TokValueTerminator)
+    /*    38 */         << H(TokTerminator)
+    /*    39 */     /* else branch */ << I(0)
+    /*    41 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("one function")
+            << "foo()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("one function (with spaces)")
+            << " foo(  ) "
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("unterminated function call")
+            << "foo(\nfoo"
+            << TS()
+            << "in:1: Missing closing parenthesis in function call"
+            << false;
+
+    QTest::newRow("function with arguments")
+            << "foo(blah, hi ho)"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokLiteral | TokNewStr) << S(L"blah")
+    /*    16 */     << H(TokArgSeparator)
+    /*    17 */     << H(TokLiteral | TokNewStr) << S(L"hi")
+    /*    21 */     << H(TokLiteral | TokNewStr) << S(L"ho")
+    /*    25 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function with empty arguments")
+            << "foo(,)"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokArgSeparator)
+    /*    11 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function with funny arguments")
+            << "foo(blah\\, \"hi ,  \\ho\" ,uh\\  ,\\oh  ,,   )"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokLiteral | TokNewStr) << S(L"blah\\")
+    /*    17 */     << H(TokArgSeparator)
+    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"hi ,  \\ho")
+    /*    29 */     << H(TokArgSeparator)
+    /*    30 */     << H(TokLiteral | TokNewStr) << S(L"uh\\")
+    /*    35 */     << H(TokArgSeparator)
+    /*    36 */     << H(TokLiteral | TokNewStr) << S(L"\\oh")
+    /*    41 */     << H(TokArgSeparator)
+    /*    42 */     << H(TokArgSeparator)
+    /*    43 */     << H(TokFuncTerminator))
+            << "WARNING: in:1: Unescaped backslashes are deprecated\n"
+               "WARNING: in:1: Unescaped backslashes are deprecated\n"
+               "WARNING: in:1: Unescaped backslashes are deprecated\n"
+               "WARNING: in:1: Unescaped backslashes are deprecated"
+            << true;
+
+    QTest::newRow("function with nested call")
+            << "foo($$blah(hi ho))"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncName | TokNewStr) << HS(L"blah")
+    /*    18 */         << H(TokLiteral | TokNewStr) << S(L"hi")
+    /*    22 */         << H(TokLiteral | TokNewStr) << S(L"ho")
+    /*    26 */         << H(TokFuncTerminator)
+    /*    27 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("stand-alone parentheses")
+            << "()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestCall)
+    /*     3 */     << H(TokFuncTerminator))
+            << "in:1: Opening parenthesis without prior test name."
+            << false;
+
+    QTest::newRow("bogus test and function")
+            << "foo bar()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestCall)
+    /*     3 */     << H(TokFuncTerminator))
+            << "in:1: Extra characters after test expression."
+            << false;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("two functions")
+            << "foo() bar()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncTerminator)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokTestCall)
+    /*    19 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("function-AND-test")
+            << "foo():bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokTestCall)
+    /*    10 */     << H(TokFuncTerminator)
+    /*    11 */ << H(TokAnd)
+    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    19 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-function")
+            << "foo:bar()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    18 */ << H(TokTestCall)
+    /*    19 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("NOT-function-AND-test")
+            << "!foo():bar"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokNot)
+    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
+    /*    10 */ << H(TokTestCall)
+    /*    11 */     << H(TokFuncTerminator)
+    /*    12 */ << H(TokAnd)
+    /*    13 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    20 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-NOT-function")
+            << "foo:!bar()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
+    /*     9 */ << H(TokCondition)
+    /*    10 */ << H(TokAnd)
+    /*    11 */ << H(TokNot)
+    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
+    /*    19 */ << H(TokTestCall)
+    /*    20 */     << H(TokFuncTerminator))
+            << ""
+            << true;
+}
+
+void tst_qmakelib::addParseControlStatements()
+{
+    QTest::newRow("for(VAR, LIST) loop")
+            << "for(VAR, LIST)"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"VAR")
+    /*     9 */ /* iterator */ << I(7)
+    /*    11 */     << H(TokLiteral | TokNewStr) << S(L"LIST")
+    /*    17 */     << H(TokValueTerminator)
+    /*    18 */ /* body */ << I(1)
+    /*    20 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("for(ever) loop")
+            << "for(ever)"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(1)
+    /*    19 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    // This is a rather questionable "feature"
+    QTest::newRow("for($$blub) loop")
+            << "for($$blub)"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokVariable | TokNewStr) << HS(L"blub")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(1)
+    /*    19 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-for-test-else-test")
+            << "true:for(VAR, LIST): true\nelse: true"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(31)
+    /*    14 */     << H(TokForLoop) << HS(L"VAR")
+    /*    21 */     /* iterator */ << I(7)
+    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
+    /*    29 */         << H(TokValueTerminator)
+    /*    30 */     /* body */ << I(12)
+    /*    32 */         << H(TokLine) << H(1)
+    /*    34 */         << H(TokHashLiteral) << HS(L"true")
+    /*    42 */         << H(TokCondition)
+    /*    43 */         << H(TokTerminator)
+    /*    44 */     << H(TokTerminator)
+    /*    45 */ /* else branch */ << I(12)
+    /*    47 */     << H(TokLine) << H(2)
+    /*    49 */     << H(TokHashLiteral) << HS(L"true")
+    /*    57 */     << H(TokCondition)
+    /*    58 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("next()")
+            << "for(ever): next()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(4)
+    /*    19 */     << H(TokLine) << H(1)
+    /*    21 */     << H(TokNext)
+    /*    22 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("break()")
+            << "for(ever): break()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(4)
+    /*    19 */     << H(TokLine) << H(1)
+    /*    21 */     << H(TokBreak)
+    /*    22 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("top-level return()")
+            << "return()"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokReturn))
+            << ""
+            << true;
+
+    QTest::newRow("else")
+            << "else"
+            << TS()
+            << "in:1: Unexpected 'else'."
+            << false;
+
+    QTest::newRow("test-{else}")
+            << "test { else }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(0))
+            << "in:1: Unexpected 'else'."
+            << false;
+
+    QTest::newRow("defineTest-{else}")
+            << "defineTest(fn) { else }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestDef) << HS(L"fn")
+    /*     8 */ /* body */ << I(1)
+    /*    10 */     << H(TokTerminator))
+            << "in:1: Unexpected 'else'."
+            << false;
+
+    QTest::newRow("for-else")
+            << "for(ever) { else }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(1)
+    /*    19 */     << H(TokTerminator))
+            << "in:1: Unexpected 'else'."
+            << false;
+
+    QTest::newRow("double-test-else")
+            << "foo bar\nelse"
+            << TS(
+    /*     0 */ << H(TokBranch)
+    /*     1 */ /* then branch */ << I(0)
+    /*     3 */ /* else branch */ << I(1)  // This seems weird
+    /*     5 */     << H(TokTerminator))
+            << "in:1: Extra characters after test expression."
+            << false;
+
+    QTest::newRow("test-function-else")
+            << "foo bar()\nelse"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestCall)  // This seems pointless
+    /*     3 */     << H(TokFuncTerminator)
+    /*     4 */ << H(TokBranch)
+    /*     5 */ /* then branch */ << I(0)
+    /*     7 */ /* else branch */ << I(1)  // This seems weird
+    /*     9 */     << H(TokTerminator))
+            << "in:1: Extra characters after test expression."
+            << false;
+}
+
+void tst_qmakelib::addParseBraces()
+{
+    QTest::newRow("{}")
+            << "{ }"
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("{}-newlines")
+            << "\n\n{ }\n\n"
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("{")
+            << "{"
+            << TS()
+            << "in:2: Missing closing brace(s)."
+            << false;
+
+    QTest::newRow("test {")
+            << "test {"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(0))
+            << "in:2: Missing closing brace(s)."
+            << false;
+
+    QTest::newRow("}")
+            << "}"
+            << TS()
+            << "in:1: Excess closing brace."
+            << false;
+
+    QTest::newRow("{test}")
+            << "{ true }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("{test-newlines}")
+            << "{\ntrue\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(2)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("{assignment-test}-test")
+            << "{ VAR = { foo } bar } true"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(4)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{")
+    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    19 */ << H(TokLiteral | TokNewStr) << S(L"}")
+    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+    /*    27 */ << H(TokValueTerminator)
+    /*    28 */ << H(TokHashLiteral) << HS(L"true")
+    /*    36 */ << H(TokCondition))
+            << ""
+            << true;
+
+    QTest::newRow("assignment with excess opening brace")
+            << "VAR = { { foo }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
+    /*     9 */ << H(TokAssign) << H(4)
+    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{")
+    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"{")
+    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"}")
+    /*    25 */ << H(TokValueTerminator))
+            << "WARNING: in:1: Possible braces mismatch"
+            << true;
+
+    QTest::newRow("test-{}")
+            << "true {}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-{newlines}")
+            << "true {\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-{test}")
+            << "true { true }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(10)
+    /*    14 */     << H(TokHashLiteral) << HS(L"true")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test:-{test}")
+            << "true: { true }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(10)
+    /*    14 */     << H(TokHashLiteral) << HS(L"true")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(0))
+            << "WARNING: in:1: Excess colon in front of opening brace."
+            << true;
+
+    QTest::newRow("test-{test-newlines}")
+            << "true {\ntrue\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(12)
+    /*    14 */     << H(TokLine) << H(2)
+    /*    16 */     << H(TokHashLiteral) << HS(L"true")
+    /*    24 */     << H(TokCondition)
+    /*    25 */     << H(TokTerminator)
+    /*    26 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test:-{test-newlines}")
+            << "true: {\ntrue\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(12)
+    /*    14 */     << H(TokLine) << H(2)
+    /*    16 */     << H(TokHashLiteral) << HS(L"true")
+    /*    24 */     << H(TokCondition)
+    /*    25 */     << H(TokTerminator)
+    /*    26 */ /* else branch */ << I(0))
+            << "WARNING: in:1: Excess colon in front of opening brace."
+            << true;
+
+    QTest::newRow("test-{assignment}")
+            << "true { VAR = {foo} }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(18)
+    /*    14 */     << H(TokHashLiteral) << HS(L"VAR")
+    /*    21 */     << H(TokAssign) << H(0)
+    /*    23 */     << H(TokLiteral | TokNewStr) << S(L"{foo}")
+    /*    30 */     << H(TokValueTerminator)
+    /*    31 */     << H(TokTerminator)
+    /*    32 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-{test-assignment}")
+            << "true { true: VAR = {foo} }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(33)
+    /*    14 */     << H(TokHashLiteral) << HS(L"true")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokBranch)
+    /*    24 */     /* then branch */ << I(18)
+    /*    26 */         << H(TokHashLiteral) << HS(L"VAR")
+    /*    33 */         << H(TokAssign) << H(0)
+    /*    35 */         << H(TokLiteral | TokNewStr) << S(L"{foo}")
+    /*    42 */         << H(TokValueTerminator)
+    /*    43 */         << H(TokTerminator)
+    /*    44 */     /* else branch */ << I(0)
+    /*    46 */     << H(TokTerminator)
+    /*    47 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-{assignment-newlines}")
+            << "true {\nVAR = {foo}\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(20)
+    /*    14 */     << H(TokLine) << H(2)
+    /*    16 */     << H(TokHashLiteral) << HS(L"VAR")
+    /*    23 */     << H(TokAssign) << H(0)
+    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"{foo}")
+    /*    32 */     << H(TokValueTerminator)
+    /*    33 */     << H(TokTerminator)
+    /*    34 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-{}-else-test-{}")
+            << "true {} else: true {}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(18)
+    /*    17 */     << H(TokLine) << H(1)
+    /*    19 */     << H(TokHashLiteral) << HS(L"true")
+    /*    27 */     << H(TokCondition)
+    /*    28 */     << H(TokBranch)
+    /*    29 */     /* then branch */ << I(1)
+    /*    31 */         << H(TokTerminator)
+    /*    32 */     /* else branch */ << I(0)
+    /*    34 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-{}-else-test-{}-newlines")
+            << "true {\n}\nelse: true {\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(1)
+    /*    14 */     << H(TokTerminator)
+    /*    15 */ /* else branch */ << I(18)
+    /*    17 */     << H(TokLine) << H(3)
+    /*    19 */     << H(TokHashLiteral) << HS(L"true")
+    /*    27 */     << H(TokCondition)
+    /*    28 */     << H(TokBranch)
+    /*    29 */     /* then branch */ << I(1)
+    /*    31 */         << H(TokTerminator)
+    /*    32 */     /* else branch */ << I(0)
+    /*    34 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-{test}-else-test-{}-newlines")
+            << "true {\ntrue\n}\nelse: true {\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(12)
+    /*    14 */     << H(TokLine) << H(2)
+    /*    16 */     << H(TokHashLiteral) << HS(L"true")
+    /*    24 */     << H(TokCondition)
+    /*    25 */     << H(TokTerminator)
+    /*    26 */ /* else branch */ << I(18)
+    /*    28 */     << H(TokLine) << H(4)
+    /*    30 */     << H(TokHashLiteral) << HS(L"true")
+    /*    38 */     << H(TokCondition)
+    /*    39 */     << H(TokBranch)
+    /*    40 */     /* then branch */ << I(1)
+    /*    42 */         << H(TokTerminator)
+    /*    43 */     /* else branch */ << I(0)
+    /*    45 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("for-{next}")
+            << "for(ever) { next() }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(4)
+    /*    19 */     << H(TokLine) << H(1)
+    /*    21 */     << H(TokNext)
+    /*    22 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("for:-{next}")
+            << "for(ever): { next() }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokForLoop) << HS(L"")
+    /*     6 */ /* iterator */ << I(9)
+    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
+    /*    16 */     << H(TokValueTerminator)
+    /*    17 */ /* body */ << I(4)
+    /*    19 */     << H(TokLine) << H(1)
+    /*    21 */     << H(TokNext)
+    /*    22 */     << H(TokTerminator))
+            << "WARNING: in:1: Excess colon in front of opening brace."
+            << true;
+
+    QTest::newRow("test-for-{test-else-test-newlines}")
+            << "true:for(VAR, LIST) {\ntrue\nelse: true\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(48)
+    /*    14 */     << H(TokForLoop) << HS(L"VAR")
+    /*    21 */     /* iterator */ << I(7)
+    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
+    /*    29 */         << H(TokValueTerminator)
+    /*    30 */     /* body */ << I(29)
+    /*    32 */         << H(TokLine) << H(2)
+    /*    34 */         << H(TokHashLiteral) << HS(L"true")
+    /*    42 */         << H(TokCondition)
+    /*    43 */         << H(TokBranch)
+    /*    44 */         /* then branch */ << I(0)
+    /*    46 */         /* else branch */ << I(12)
+    /*    48 */             << H(TokLine) << H(3)
+    /*    50 */             << H(TokHashLiteral) << HS(L"true")
+    /*    58 */             << H(TokCondition)
+    /*    59 */             << H(TokTerminator)
+    /*    60 */         << H(TokTerminator)
+    /*    61 */     << H(TokTerminator)
+    /*    62 */ /* else branch */ << I(0))
+            << ""
+            << true;
+
+    QTest::newRow("test-for-{test-else-test}")
+            << "true:for(VAR, LIST) { true\nelse: true }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"true")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(48)
+    /*    14 */     << H(TokForLoop) << HS(L"VAR")
+    /*    21 */     /* iterator */ << I(7)
+    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
+    /*    29 */         << H(TokValueTerminator)
+    /*    30 */     /* body */ << I(29)
+    /*    32 */         << H(TokLine) << H(1)
+    /*    34 */         << H(TokHashLiteral) << HS(L"true")
+    /*    42 */         << H(TokCondition)
+    /*    43 */         << H(TokBranch)
+    /*    44 */         /* then branch */ << I(0)
+    /*    46 */         /* else branch */ << I(12)
+    /*    48 */             << H(TokLine) << H(2)
+    /*    50 */             << H(TokHashLiteral) << HS(L"true")
+    /*    58 */             << H(TokCondition)
+    /*    59 */             << H(TokTerminator)
+    /*    60 */         << H(TokTerminator)
+    /*    61 */     << H(TokTerminator)
+    /*    62 */ /* else branch */ << I(0))
+            << ""
+            << true;
+}
+
+void tst_qmakelib::addParseCustomFunctions()
+{
+    QTest::newRow("defineTest-{newlines}")
+            << "defineTest(test) {\n}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestDef) << HS(L"test")
+    /*    10 */ /* body */ << I(1)
+    /*    12 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("defineTest:-test")
+            << "defineTest(test): test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestDef) << HS(L"test")
+    /*    10 */ /* body */ << I(12)
+    /*    12 */     << H(TokLine) << H(1)
+    /*    14 */     << H(TokHashLiteral) << HS(L"test")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("defineTest-{test}")
+            << "defineTest(test) { test }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestDef) << HS(L"test")
+    /*    10 */ /* body */ << I(12)
+    /*    12 */     << H(TokLine) << H(1)
+    /*    14 */     << H(TokHashLiteral) << HS(L"test")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("defineTest-{return}")
+            << "defineTest(test) { return() }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokTestDef) << HS(L"test")
+    /*    10 */ /* body */ << I(4)
+    /*    12 */     << H(TokLine) << H(1)
+    /*    14 */     << H(TokReturn)
+    /*    15 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("defineReplace-{return-stuff}")
+            << "defineReplace(stuff) { return(foo bar) }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokReplaceDef) << HS(L"stuff")
+    /*    11 */ /* body */ << I(14)
+    /*    13 */     << H(TokLine) << H(1)
+    /*    15 */     << H(TokLiteral | TokNewStr) << S(L"foo")
+    /*    20 */     << H(TokLiteral | TokNewStr) << S(L"bar")
+    /*    25 */     << H(TokReturn)
+    /*    26 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-AND-defineTest-{}")
+            << "test: defineTest(test) {}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokAnd)
+    /*    12 */ << H(TokTestDef) << HS(L"test")
+    /*    20 */ /* body */ << I(1)
+    /*    22 */     << H(TokTerminator))
+            << ""
+            << true;
+
+    QTest::newRow("test-OR-defineTest-{}")
+            << "test| defineTest(test) {}"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokOr)
+    /*    12 */ << H(TokTestDef) << HS(L"test")
+    /*    20 */ /* body */ << I(1)
+    /*    22 */     << H(TokTerminator))
+            << ""
+            << true;
+}
+
+void tst_qmakelib::addParseAbuse()
+{
+    QTest::newRow("!")
+            << ""
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("|")
+            << ""
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow(":")
+            << ""
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("NOT-assignment")
+            << "!VAR ="
+            << TS()
+            << "in:1: Unexpected NOT operator in front of assignment."
+            << false;
+
+    QTest::newRow("NOT-{}")
+            << "!{}"
+            << TS()
+            << "in:1: Unexpected NOT operator in front of opening brace."
+            << false;
+
+    QTest::newRow("NOT-else")
+            << "test\n!else {}"
+            << TS()
+            << "in:2: Unexpected NOT operator in front of else."
+            << false;
+
+    QTest::newRow("NOT-for-{}")
+            << "!for(ever) {}"
+            << TS()
+            << "in:1: Unexpected NOT operator in front of for()."
+            << false;
+
+    QTest::newRow("NOT-defineTest-{}")
+            << "!defineTest(test) {}"
+            << TS()
+            << "in:1: Unexpected NOT operator in front of function definition."
+            << false;
+
+    QTest::newRow("AND-test")
+            << ":test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition))
+            << "in:1: AND operator without prior condition."
+            << false;
+
+    QTest::newRow("test-AND-else")
+            << "test:else"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition))
+            << "in:1: Unexpected AND operator in front of else."
+            << false;
+
+    QTest::newRow("test-AND-AND-test")
+            << "test::test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokAnd)
+    /*    12 */ << H(TokHashLiteral) << HS(L"test")
+    /*    20 */ << H(TokCondition))
+            << "WARNING: in:1: Stray AND operator in front of AND operator."
+            << true;
+
+    QTest::newRow("test-AND-OR-test")
+            << "test:|test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokOr)
+    /*    12 */ << H(TokHashLiteral) << HS(L"test")
+    /*    20 */ << H(TokCondition))
+            << "WARNING: in:1: Stray AND operator in front of OR operator."
+            << true;
+
+    QTest::newRow("test-{AND-test}")
+            << "test { :test }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(10)
+    /*    14 */     << H(TokHashLiteral) << HS(L"test")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(0))
+            << "in:1: AND operator without prior condition."
+            << false;
+
+    QTest::newRow("test-OR-assignment")
+            << "foo| VAR ="
+            << TS()
+            << "in:1: Unexpected OR operator in front of assignment."
+            << false;
+
+    QTest::newRow("test-OR-{}")
+            << "foo|{}"
+            << TS()
+            << "in:1: Unexpected OR operator in front of opening brace."
+            << false;
+
+    QTest::newRow("test-OR-for")
+            << "foo|for(ever) {}"
+            << TS()
+            << "in:1: Unexpected OR operator in front of for()."
+            << false;
+
+    QTest::newRow("OR-test")
+            << "|test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition))
+            << "in:1: OR operator without prior condition."
+            << false;
+
+    QTest::newRow("test-OR-else")
+            << "test|else"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition))
+            << "in:1: Unexpected OR operator in front of else."
+            << false;
+
+    QTest::newRow("test-OR-OR-test")
+            << "test||test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokOr)
+    /*    12 */ << H(TokHashLiteral) << HS(L"test")
+    /*    20 */ << H(TokCondition))
+            << "WARNING: in:1: Stray OR operator in front of OR operator."
+            << true;
+
+    QTest::newRow("test-OR-AND-test")
+            << "test|:test"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokAnd)
+    /*    12 */ << H(TokHashLiteral) << HS(L"test")
+    /*    20 */ << H(TokCondition))
+            << "WARNING: in:1: Stray OR operator in front of AND operator."
+            << true;
+
+    QTest::newRow("test-{OR-test}")
+            << "test { |test }"
+            << TS(
+    /*     0 */ << H(TokLine) << H(1)
+    /*     2 */ << H(TokHashLiteral) << HS(L"test")
+    /*    10 */ << H(TokCondition)
+    /*    11 */ << H(TokBranch)
+    /*    12 */ /* then branch */ << I(10)
+    /*    14 */     << H(TokHashLiteral) << HS(L"test")
+    /*    22 */     << H(TokCondition)
+    /*    23 */     << H(TokTerminator)
+    /*    24 */ /* else branch */ << I(0))
+            << "in:1: OR operator without prior condition."
+            << false;
+}
+
+void tst_qmakelib::proParser_data()
+{
+    QTest::addColumn<QString>("in");
+    QTest::addColumn<QString>("out");
+    QTest::addColumn<QString>("msgs");
+    QTest::addColumn<bool>("ok");
+
+    QTest::newRow("empty")
+            << ""
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("empty (whitespace)")
+            << "  \t   \t"
+            << TS()
+            << ""
+            << true;
+
+    addParseOperators();  // Variable operators
+
+    addParseValues();
+
+    addParseConditions();  // "Tests"
+
+    addParseControlStatements();
+
+    addParseBraces();
+
+    addParseCustomFunctions();
+
+    addParseAbuse();  // Mostly operator abuse
+
+    // option() (these produce no tokens)
+
+    QTest::newRow("option(host_build)")
+            << "option(host_build)"
+            << TS()
+            << ""
+            << true;
+
+    QTest::newRow("option()")
+            << "option()"
+            << TS()
+            << "in:1: option() requires one literal argument."
+            << false;
+
+    QTest::newRow("option(host_build magic)")
+            << "option(host_build magic)"
+            << TS()
+            << "in:1: option() requires one literal argument."
+            << false;
+
+    QTest::newRow("option(host_build, magic)")
+            << "option(host_build, magic)"
+            << TS()
+            << "in:1: option() requires one literal argument."
+            << false;
+
+    QTest::newRow("option($$OPTION)")
+            << "option($$OPTION)"
+            << TS()
+            << "in:1: option() requires one literal argument."
+            << false;
+
+    QTest::newRow("{option(host_build)}")
+            << "{option(host_build)}"
+            << TS()
+            << "in:1: option() must appear outside any control structures."
+            << false;
+}
+
+QT_WARNING_POP
+
+void tst_qmakelib::proParser()
+{
+    QFETCH(QString, in);
+    QFETCH(QString, out);
+    QFETCH(QString, msgs);
+    QFETCH(bool, ok);
+
+    bool verified = true;
+    QMakeTestHandler handler;
+    handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts));
+    QMakeVfs vfs;
+    QMakeParser parser(0, &vfs, &handler);
+    ProFile *pro = parser.parsedProBlock(in, "in", 1, QMakeParser::FullGrammar);
+    if (handler.printedMessages()) {
+        qWarning("Got unexpected message(s)");
+        verified = false;
+    }
+    QStringList missingMsgs = handler.expectedMessages();
+    if (!missingMsgs.isEmpty()) {
+        foreach (const QString &msg, missingMsgs)
+            qWarning("Missing message: %s", qPrintable(msg));
+        verified = false;
+    }
+    if (pro->isOk() != ok) {
+        static const char * const lbl[] = { "failure", "success" };
+        qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
+        verified = false;
+    }
+    if (pro->items() != out && (ok || !out.isEmpty())) {
+        qWarning("Bytecode mismatch.\nActual:%s\nExpected:%s",
+                 qPrintable(QMakeParser::formatProBlock(pro->items())),
+                 qPrintable(QMakeParser::formatProBlock(out)));
+        verified = false;
+    }
+    pro->deref();
+    QVERIFY(verified);
+}
diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro
index e7807838aa7c4b3bfa1c59c42fd09edf3e38e1fa..f1b8dfef3d7d2aa4e37fd889b4abd95b9a5c1d72 100644
--- a/tests/auto/tools/qmakelib/qmakelib.pro
+++ b/tests/auto/tools/qmakelib/qmakelib.pro
@@ -6,11 +6,19 @@ QT = core testlib
 INCLUDEPATH += ../../../../qmake/library
 VPATH += ../../../../qmake/library
 
+HEADERS += \
+    tst_qmakelib.h
+
 SOURCES += \
     tst_qmakelib.cpp \
+    parsertest.cpp \
+    evaltest.cpp \
     ioutils.cpp \
     proitems.cpp \
     qmakevfs.cpp \
-    qmakeparser.cpp
+    qmakeparser.cpp \
+    qmakeglobals.cpp \
+    qmakebuiltins.cpp \
+    qmakeevaluator.cpp
 
-DEFINES += PROPARSER_DEBUG
+DEFINES += PROPARSER_DEBUG PROEVALUATOR_FULL PROEVALUATOR_SETENV
diff --git a/tests/auto/tools/qmakelib/testdata/cat/file1.txt b/tests/auto/tools/qmakelib/testdata/cat/file1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e3e4cd41b676926262f3e692ffdf8f11b4ec7b6f
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/cat/file1.txt
@@ -0,0 +1,2 @@
+"Hello, world."
+foo bar baz
diff --git a/tests/auto/tools/qmakelib/testdata/cat/file2.txt b/tests/auto/tools/qmakelib/testdata/cat/file2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..18483311e6cbb431360bb1c04050aa8bcb7fc1e7
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/cat/file2.txt
@@ -0,0 +1,5 @@
+foo bar	baz
+"Hello, ' world." post
+'Hello, " world.' post
+\" \' \\ \a \  nix
+" "
diff --git a/tests/auto/tools/qmakelib/testdata/files/dir/file1.txt b/tests/auto/tools/qmakelib/testdata/files/dir/file1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmakelib/testdata/files/dir/file2.txt b/tests/auto/tools/qmakelib/testdata/files/dir/file2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmakelib/testdata/files/file1.txt b/tests/auto/tools/qmakelib/testdata/files/file1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmakelib/testdata/files/file2.txt b/tests/auto/tools/qmakelib/testdata/files/file2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmakelib/testdata/files/other.txt b/tests/auto/tools/qmakelib/testdata/files/other.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx b/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx
new file mode 100644
index 0000000000000000000000000000000000000000..a916f21587a7f576b5d07001326c0fe3ef679870
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx
@@ -0,0 +1 @@
+error("fail!")
diff --git a/tests/auto/tools/qmake/testdata/functions/infiletest.pro b/tests/auto/tools/qmakelib/testdata/fromfile/infile.prx
similarity index 100%
rename from tests/auto/tools/qmake/testdata/functions/infiletest.pro
rename to tests/auto/tools/qmakelib/testdata/fromfile/infile.prx
diff --git a/tests/auto/tools/qmakelib/testdata/include/inc.pri b/tests/auto/tools/qmakelib/testdata/include/inc.pri
new file mode 100644
index 0000000000000000000000000000000000000000..1f1b3a287faf146638dd2b41c054e566be25323c
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/include/inc.pri
@@ -0,0 +1,8 @@
+VAR = val
+.VAR = nope
+
+fake-*: MATCH = 1
+
+defineTest(func) {
+    message("say hi!")
+}
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf b/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d7a17d2429a43c3ddfce2f56dc8012da7c2894cf
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf
new file mode 100644
index 0000000000000000000000000000000000000000..d7a17d2429a43c3ddfce2f56dc8012da7c2894cf
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf
new file mode 100644
index 0000000000000000000000000000000000000000..d7a17d2429a43c3ddfce2f56dc8012da7c2894cf
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf
new file mode 100644
index 0000000000000000000000000000000000000000..d7a17d2429a43c3ddfce2f56dc8012da7c2894cf
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf
new file mode 100644
index 0000000000000000000000000000000000000000..d7a17d2429a43c3ddfce2f56dc8012da7c2894cf
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf
new file mode 100644
index 0000000000000000000000000000000000000000..57c9a0d783f11e4b1214d1801d1cd333467c9a85
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf
@@ -0,0 +1 @@
+VAR = foo bar
diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
index 1c6d43338d0e7aa67ae49eb275779b0d5e7b0bb1..3da48815fbe4910c8e6a68565f7b1f7b917c65b9 100644
--- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp
+++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
@@ -31,37 +31,112 @@
 **
 ****************************************************************************/
 
-#include <QtTest/QtTest>
+#include "tst_qmakelib.h"
 
 #include <ioutils.h>
-#include <proitems.h>
-#include <qmakevfs.h>
-#include <qmakeparser.h>
-
-#include <QObject>
 
 using namespace QMakeInternal;
 
-class tst_qmakelib : public QObject
+void tst_qmakelib::initTestCase()
+{
+    m_indir = QFINDTESTDATA("testdata");
+    m_outdir = m_indir + QLatin1String("_build");
+    m_env.insert(QStringLiteral("E1"), QStringLiteral("env var"));
+#ifdef Q_OS_WIN
+    m_env.insert(QStringLiteral("COMSPEC"), qgetenv("COMSPEC"));
+#endif
+    m_prop.insert(ProKey("P1"), ProString("prop val"));
+    m_prop.insert(ProKey("QT_HOST_DATA/get"), ProString(m_indir));
+
+    QVERIFY(!m_indir.isEmpty());
+    QVERIFY(QDir(m_outdir).removeRecursively());
+    QVERIFY(QDir().mkpath(m_outdir));
+}
+
+void tst_qmakelib::cleanupTestCase()
 {
-    Q_OBJECT
+    QVERIFY(QDir(m_outdir).removeRecursively());
+}
+
+void tst_qmakelib::proString()
+{
+    QString qs1(QStringLiteral("this is a string"));
+
+    ProString s1(qs1);
+    QCOMPARE(s1.toQString(), QStringLiteral("this is a string"));
+
+    ProString s2(qs1, 5, 8);
+    QCOMPARE(s2.toQString(), QStringLiteral("is a str"));
+
+    QCOMPARE(s2.hash(), 0x80000000);
+    qHash(s2);
+    QCOMPARE(s2.hash(), 90404018U);
 
-public:
-    tst_qmakelib() {}
-    virtual ~tst_qmakelib() {}
+    QCOMPARE(s2.mid(0, 10).toQString(), QStringLiteral("is a str"));
+    QCOMPARE(s2.mid(1, 5).toQString(), QStringLiteral("s a s"));
+    QCOMPARE(s2.mid(10, 3).toQString(), QStringLiteral(""));
 
-private slots:
-    void quoteArgUnix_data();
-    void quoteArgUnix();
-    void quoteArgWin_data();
-    void quoteArgWin();
-    void pathUtils();
+    QString qs2(QStringLiteral("   spacy  string   "));
+    QCOMPARE(ProString(qs2, 3, 13).trimmed().toQString(), QStringLiteral("spacy  string"));
+    QCOMPARE(ProString(qs2, 1, 17).trimmed().toQString(), QStringLiteral("spacy  string"));
 
-    void proStringList();
+    QVERIFY(s2.toQStringRef().string()->isSharedWith(qs1));
+    s2.prepend(ProString("there "));
+    QCOMPARE(s2.toQString(), QStringLiteral("there is a str"));
+    QVERIFY(!s2.toQStringRef().string()->isSharedWith(qs1));
 
-    void proParser_data();
-    void proParser();
-};
+    ProString s3("this is a longish string with bells and whistles");
+    s3 = s3.mid(18, 17);
+    // Prepend to detached string with lots of spare space in it.
+    s3.prepend(ProString("another "));
+    QCOMPARE(s3.toQString(), QStringLiteral("another string with bells"));
+
+    // Note: The string still has plenty of spare space.
+    s3.append(QLatin1Char('.'));
+    QCOMPARE(s3.toQString(), QStringLiteral("another string with bells."));
+    s3.append(QLatin1String(" eh?"));
+    QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh?"));
+
+    s3.append(ProString(" yeah!"));
+    QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah!"));
+
+    bool pending = false; // Not in string, but joining => add space
+    s3.append(ProString("..."), &pending);
+    QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah! ..."));
+    QVERIFY(pending);
+
+    ProStringList sl1;
+    sl1 << ProString("") << ProString("foo") << ProString("barbaz");
+    ProString s4a("hallo");
+    s4a.append(sl1);
+    QCOMPARE(s4a.toQString(), QStringLiteral("hallo foo barbaz"));
+    ProString s4b("hallo");
+    pending = false;
+    s4b.append(sl1, &pending);
+    QCOMPARE(s4b.toQString(), QStringLiteral("hallo  foo barbaz"));
+    ProString s4c;
+    pending = false;
+    s4c.append(sl1, &pending);
+    QCOMPARE(s4c.toQString(), QStringLiteral(" foo barbaz"));
+    // bizarreness
+    ProString s4d("hallo");
+    pending = false;
+    s4d.append(sl1, &pending, true);
+    QCOMPARE(s4d.toQString(), QStringLiteral("hallo foo barbaz"));
+    ProString s4e;
+    pending = false;
+    s4e.append(sl1, &pending, true);
+    QCOMPARE(s4e.toQString(), QStringLiteral("foo barbaz"));
+
+    ProStringList sl2;
+    sl2 << ProString("foo");
+    ProString s5;
+    s5.append(sl2);
+    QCOMPARE(s5.toQString(), QStringLiteral("foo"));
+    QVERIFY(s5.toQStringRef().string()->isSharedWith(*sl2.first().toQStringRef().string()));
+
+    QCOMPARE(ProString("one") + ProString(" more"), QStringLiteral("one more"));
+}
 
 void tst_qmakelib::proStringList()
 {
@@ -171,1940 +246,24 @@ void tst_qmakelib::pathUtils()
     QCOMPARE(IoUtils::resolvePath(fnbase, fn1), QStringLiteral("/a/unix/file/path"));
 }
 
-class QMakeHandler : public QMakeParserHandler {
-public:
-    QMakeHandler() : QMakeParserHandler(), printed(false) {}
-    virtual void message(int type, const QString &msg, const QString &fileName, int lineNo)
-        { print(fileName, lineNo, type, msg); }
-
-    void setExpectedMessages(const QStringList &msgs) { expected = msgs; }
-    QStringList expectedMessages() const { return expected; }
-
-    bool printedMessages() const { return printed; }
-
-private:
-    void print(const QString &fileName, int lineNo, int type, const QString &msg)
-    {
-        QString pfx = ((type & QMakeParserHandler::CategoryMask) == QMakeParserHandler::WarningMessage)
-                      ? QString::fromLatin1("WARNING: ") : QString();
-        QString out;
-        if (lineNo)
-            out = QStringLiteral("%1%2:%3: %4").arg(pfx, fileName, QString::number(lineNo), msg);
-        else
-            out = QStringLiteral("%1%2").arg(pfx, msg);
-        if (!expected.isEmpty() && expected.first() == out) {
-            expected.removeAt(0);
-            return;
-        }
-        qWarning("%s", qPrintable(out));
-        printed = true;
-    }
-
-    QStringList expected;
-    bool printed;
-};
-
-static QMakeHandler qmakeHandler;
-
-class TokenStream
+void QMakeTestHandler::print(const QString &fileName, int lineNo, int type, const QString &msg)
 {
-public:
-    TokenStream() {}
-    QString toString() const { return ts; }
-
-    TokenStream &operator<<(ushort n) { ts += QChar(n); return *this; }
-    TokenStream &operator<<(uint n) { ts += QChar(n & 0xffff); ts += QChar(n >> 16); return *this; }
-    TokenStream &operator<<(const QStringRef &s) { ts += s; return *this; }
-    TokenStream &operator<<(const ProString &s) { return *this << ushort(s.length()) << s.toQStringRef(); }
-    TokenStream &operator<<(const ProKey &s) { return *this << s.hash() << s.toString(); }
-
-private:
-    QString ts;
-};
-
-#define TS(s) (TokenStream() s).toString()
-#define H(n) ushort(n)
-#define I(n) uint(n)
-#define S(s) ProString(QString::fromWCharArray(s))
-#define HS(s) ProKey(QString::fromWCharArray(s))
-
-void tst_qmakelib::proParser_data()
-{
-    QTest::addColumn<QString>("in");
-    QTest::addColumn<QString>("out");
-    QTest::addColumn<QString>("msgs");
-    QTest::addColumn<bool>("ok");
-
-    QTest::newRow("empty")
-            << ""
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("empty (whitespace)")
-            << "  \t   \t"
-            << TS()
-            << ""
-            << true;
-
-    // Variable operators
-
-    QTest::newRow("assign none")
-            << "VAR ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("append none")
-            << "VAR +="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAppend) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("unique append none")
-            << "VAR *="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAppendUnique) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("remove none")
-            << "VAR -="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokRemove) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("replace empty")
-            << "VAR ~="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokReplace) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("assignment without variable")
-            << "="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokAssign) << H(0)
-    /*     4 */ << H(TokValueTerminator))
-            << "in:1: Assignment needs exactly one word on the left hand side."
-            << false;
-
-    QTest::newRow("assignment with multiple variables")
-            << "VAR VAR ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokAssign) << H(0)
-    /*     4 */ << H(TokValueTerminator))
-            << "in:1: Assignment needs exactly one word on the left hand side."
-            << false;
-
-    // Values
-
-#define ASSIGN_VAR(h) \
-        H(TokLine) << H(1) \
-        << H(TokHashLiteral) << HS(L"VAR") \
-        << H(TokAssign) << H(h)
-
-    QTest::newRow("one literal")
-            << "VAR = val"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val")
-    /*    16 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("one literal (squeezed)")
-            << "VAR=val"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val")
-    /*    16 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("many literals")
-            << "VAR = foo barbaz bak hello"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(4)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
-    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
-    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
-    /*    36 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("many literals (tab-separated")
-            << "VAR\t=\tfoo\tbarbaz\tbak\thello"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(4)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
-    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
-    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
-    /*    36 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("one quoted literal")
-            << "VAR = \"val ue\""
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val ue")
-    /*    19 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("quoted literal with missing quote")
-            << "VAR = val \"ue"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(0)
-    /*    11 */ << H(TokValueTerminator))
-            << "in:1: Missing closing \" quote"
-            << false;
-
-    QTest::newRow("many quoted literals")
-            << "VAR = \"foo\" barbaz    'bak hello' \"\""
-            << TS(
-    /*     0 */ << ASSIGN_VAR(3)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
-    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak hello")
-    /*    35 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("many quoted literals (with tabs)")
-            << "VAR\t=\t\"foo\"\tbarbaz\t'bak\thello'"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(3)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
-    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"bak\thello")
-    /*    35 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("quoted and unquoted spaces")
-            << "  VAR = \"val ue   \"   "
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"val ue   ")
-    /*    22 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("funny literals")
-            << "VAR = foo:bar|!baz(blam!, ${foo})"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(2)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo:bar|!baz(blam!,")
-    /*    32 */ << H(TokLiteral | TokNewStr) << S(L"${foo})")
-    /*    41 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("literals with escapes")
-            << "VAR = \\{hi\\} \\[ho\\] \\)uh\\( \"\\\\oh\\$\"\\' \\$\\${FOO}"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(5)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{hi}")
-    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"[ho]")
-    /*    23 */ << H(TokLiteral | TokNewStr) << S(L")uh(")
-    /*    29 */ << H(TokLiteral | TokNewStr) << S(L"\\oh$'")
-    /*    36 */ << H(TokLiteral | TokNewStr) << S(L"$${FOO}")
-    /*    45 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("magic variables")
-            << "VAR = $$LITERAL_HASH $$LITERAL_DOLLAR $$LITERAL_WHITESPACE $$_FILE_ $$_LINE_"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(5)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"#")
-    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"$")
-    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"\t")
-    /*    20 */ << H(TokLiteral | TokNewStr) << S(L"in")
-    /*    24 */ << H(TokLiteral | TokNewStr) << S(L"1")
-    /*    27 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("continuations and comments")
-            << "VAR = foo \\\n  bar\n  \n"
-               "GAR = foo \\ # comment\n  bar \\\n   # comment\n baz \\\n"
-                    "\"quoted \\ #comment\n    escape\" \\\n    right\\\n      after \\\n    gorilla!\n \n\n"
-               "MOO = \\\n  kuh # comment\nLOO =\n\n"
-               "FOO = bar \\\n# comment\n   baz \\\n    \n# comment\n"
-               "GAZ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(2)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokLiteral | TokNewStr) << S(L"bar")
-    /*    21 */ << H(TokValueTerminator)
-    /*    22 */ << H(TokLine) << H(4)
-    /*    24 */ << H(TokHashLiteral) << HS(L"GAR")
-    /*    31 */ << H(TokAssign) << H(7)
-    /*    33 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    38 */ << H(TokLiteral | TokNewStr) << S(L"bar")
-    /*    43 */ << H(TokLiteral | TokNewStr) << S(L"baz")
-    /*    48 */ << H(TokLiteral | TokNewStr) << S(L"quoted  escape")
-    /*    64 */ << H(TokLiteral | TokNewStr) << S(L"right")
-    /*    71 */ << H(TokLiteral | TokNewStr) << S(L"after")
-    /*    78 */ << H(TokLiteral | TokNewStr) << S(L"gorilla!")
-    /*    88 */ << H(TokValueTerminator)
-    /*    89 */ << H(TokLine) << H(15)
-    /*    91 */ << H(TokHashLiteral) << HS(L"MOO")
-    /*    98 */ << H(TokAssign) << H(0)
-    /*   100 */ << H(TokLiteral | TokNewStr) << S(L"kuh")
-    /*   105 */ << H(TokValueTerminator)
-    /*   106 */ << H(TokLine) << H(17)
-    /*   108 */ << H(TokHashLiteral) << HS(L"LOO")
-    /*   115 */ << H(TokAssign) << H(0)
-    /*   117 */ << H(TokValueTerminator)
-    /*   118 */ << H(TokLine) << H(19)
-    /*   120 */ << H(TokHashLiteral) << HS(L"FOO")
-    /*   127 */ << H(TokAssign) << H(2)
-    /*   129 */ << H(TokLiteral | TokNewStr) << S(L"bar")
-    /*   134 */ << H(TokLiteral | TokNewStr) << S(L"baz")
-    /*   139 */ << H(TokValueTerminator)
-    /*   140 */ << H(TokLine) << H(24)
-    /*   142 */ << H(TokHashLiteral) << HS(L"GAZ")
-    /*   149 */ << H(TokAssign) << H(0)
-    /*   151 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("accidental continuation")
-            << "VAR0 = \\\n    this \\\n    is \\\n    ok\n"
-               "VAR1 = \\\n    this \\\n    is=still \\\n    ok\n"
-               "VAR2 = \\\n    this \\\n    is \\\n"
-               "VAR3 = \\\n    not ok\n"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR0")
-    /*    10 */ << H(TokAssign) << H(3)
-    /*    12 */ << H(TokLiteral | TokNewStr) << S(L"this")
-    /*    18 */ << H(TokLiteral | TokNewStr) << S(L"is")
-    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"ok")
-    /*    26 */ << H(TokValueTerminator)
-    /*    27 */ << H(TokLine) << H(5)
-    /*    29 */ << H(TokHashLiteral) << HS(L"VAR1")
-    /*    37 */ << H(TokAssign) << H(3)
-    /*    39 */ << H(TokLiteral | TokNewStr) << S(L"this")
-    /*    45 */ << H(TokLiteral | TokNewStr) << S(L"is=still")
-    /*    55 */ << H(TokLiteral | TokNewStr) << S(L"ok")
-    /*    59 */ << H(TokValueTerminator)
-    /*    60 */ << H(TokLine) << H(9)
-    /*    62 */ << H(TokHashLiteral) << HS(L"VAR2")
-    /*    70 */ << H(TokAssign) << H(6)
-    /*    72 */ << H(TokLiteral | TokNewStr) << S(L"this")
-    /*    78 */ << H(TokLiteral | TokNewStr) << S(L"is")
-    /*    82 */ << H(TokLiteral | TokNewStr) << S(L"VAR3")
-    /*    88 */ << H(TokLiteral | TokNewStr) << S(L"=")
-    /*    91 */ << H(TokLiteral | TokNewStr) << S(L"not")
-    /*    96 */ << H(TokLiteral | TokNewStr) << S(L"ok")
-    /*   100 */ << H(TokValueTerminator))
-            << "WARNING: in:12: Possible accidental line continuation"
-            << true;
-
-    QTest::newRow("plain variable expansion")
-            << "VAR = $$bar"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
-    /*    18 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("braced variable expansion")
-            << "VAR = $${foo/bar}"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"foo/bar")
-    /*    22 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("bogus variable expansion")
-            << "VAR = $$  "
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"")
-    /*    15 */ << H(TokValueTerminator))
-            << "WARNING: in:1: Missing name in expansion"
-            << true;
-
-    QTest::newRow("bogus braced variable expansion")
-            << "VAR = $${}"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"")
-    /*    15 */ << H(TokValueTerminator))
-            << "WARNING: in:1: Missing name in expansion"
-            << true;
-
-    QTest::newRow("unterminated braced variable expansion")
-            << "VAR = $${FOO"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"FOO")
-    /*    18 */ << H(TokValueTerminator))
-            << "in:1: Missing } terminator [found end-of-line]"
-            << false;
-
-    QTest::newRow("invalid identifier in braced variable expansion")
-            << "VAR = $${FOO/BAR+BAZ}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"FOO/BAR")
-    /*    22 */ << H(TokLiteral) << S(L"+BAZ")
-    /*    28 */ << H(TokValueTerminator))
-            << "in:1: Missing } terminator [found +]"
-            << false;
-
-    QTest::newRow("property expansion")
-            << "VAR = $$[bar]"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokProperty | TokNewStr) << HS(L"bar")
-    /*    18 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("environment expansion")
-            << "VAR = $$(bar)"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokEnvVar | TokNewStr) << S(L"bar")
-    /*    16 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("plain function call")
-            << "VAR = $$bar()"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    18 */     << H(TokFuncTerminator)
-    /*    19 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("braced function call")
-            << "VAR = $${bar()}"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    18 */     << H(TokFuncTerminator)
-    /*    19 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function call with one argument")
-            << "VAR = $$bar(blubb)"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
-    /*    25 */     << H(TokFuncTerminator)
-    /*    26 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function call with multiple arguments")
-            << "VAR = $$bar(  blubb blubb, hey  ,$$you)"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
-    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
-    /*    32 */     << H(TokArgSeparator)
-    /*    33 */     << H(TokLiteral | TokNewStr) << S(L"hey")
-    /*    38 */     << H(TokArgSeparator)
-    /*    39 */     << H(TokVariable | TokNewStr) << HS(L"you")
-    /*    46 */     << H(TokFuncTerminator)
-    /*    47 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("nested function call")
-            << "VAR = $$foo(yo, $$bar(blubb))"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"foo")
-    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"yo")
-    /*    22 */     << H(TokArgSeparator)
-    /*    23 */     << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    30 */         << H(TokLiteral | TokNewStr) << S(L"blubb")
-    /*    37 */         << H(TokFuncTerminator)
-    /*    38 */     << H(TokFuncTerminator)
-    /*    39 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("function call with parenthesized argument")
-            << "VAR = $$bar(blubb (yo, man) blabb, nope)"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
-    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"blubb")
-    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"(yo,")
-    /*    31 */     << H(TokLiteral | TokNewStr) << S(L"man)")
-    /*    37 */     << H(TokLiteral | TokNewStr) << S(L"blabb")
-    /*    44 */     << H(TokArgSeparator)
-    /*    45 */     << H(TokLiteral | TokNewStr) << S(L"nope")
-    /*    51 */     << H(TokFuncTerminator)
-    /*    52 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("separate literal and expansion")
-            << "VAR = foo $$bar"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(2)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokVariable | TokNewStr) << HS(L"bar")
-    /*    23 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("separate expansion and literal")
-            << "VAR = $$bar foo"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
-    /*    18 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    23 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("joined literal and expansion")
-            << "VAR = foo$$bar"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokVariable) << HS(L"bar")
-    /*    23 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("joined expansion and literal")
-            << "VAR = $${bar}foo"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
-    /*    18 */ << H(TokLiteral) << S(L"foo")
-    /*    23 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("plain variable expansion with funny name and literal")
-            << "VAR = $$az_AZ_09.dot/nix"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot")
-    /*    27 */ << H(TokLiteral) << S(L"/nix")
-    /*    33 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("braced variable expansion with funny name")
-            << "VAR = $${az_AZ_09.dot/nix}"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot/nix")
-    /*    31 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("quoted joined literal and expansion")
-            << "VAR = 'foo$$bar'"
-            << TS(
-    /*     0 */ << ASSIGN_VAR(0)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    16 */ << H(TokVariable | TokQuoted) << HS(L"bar")
-    /*    23 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("assignment with expansion in variable name")
-            << "VAR$$EXTRA ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokVariable) << HS(L"EXTRA")
-    /*    18 */ << H(TokAssign) << H(0)
-    /*    20 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    // Conditionals ("Tests")
-
-    QTest::newRow("one test")
-            << "foo"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("wildcard-test")
-            << "foo-*"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo-*")
-    /*    11 */ << H(TokCondition))
-            << ""
-            << true;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("one quoted test")
-            << "\"foo\""
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("two tests")
-            << "foo\nbar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokLine) << H(2)
-    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    19 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("bogus two tests")
-            << "foo bar\nbaz"
-            << TS()
-            << "in:1: Extra characters after test expression."
-            << false;
-
-    QTest::newRow("test-AND-test")
-            << "foo:bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("test-OR-test")
-            << "  foo  | bar "
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokOr)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("NOT-test")
-            << "!foo"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokNot)
-    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
-    /*    10 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("NOT-NOT-test")
-            << "!!foo"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition))
-            << ""
-            << true;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("quoted-NOT-test")
-            << "\"!foo\""
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokNot)
-    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
-    /*    10 */ << H(TokCondition))
-            << ""
-            << true;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("NOT-quoted-test")
-            << "!\"foo\""
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokNot)
-    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
-    /*    10 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-NOT-test")
-            << "foo:!bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokNot)
-    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    19 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("test-assignment")
-            << "foo\nVAR="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokLine) << H(2)
-    /*    12 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*    19 */ << H(TokAssign) << H(0)
-    /*    21 */ << H(TokValueTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-assignment")
-            << "foo: VAR ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokBranch)
-    /*    11 */ /* then branch */ << I(11)
-    /*    13 */     << H(TokHashLiteral) << HS(L"VAR")
-    /*    20 */     << H(TokAssign) << H(0)
-    /*    22 */     << H(TokValueTerminator)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-else-test")
-            << "foo\nelse: bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokBranch)
-    /*    11 */ /* then branch */ << I(0)
-    /*    13 */ /* else branch */ << I(11)
-    /*    15 */     << H(TokLine) << H(2)
-    /*    17 */     << H(TokHashLiteral) << HS(L"bar")
-    /*    24 */     << H(TokCondition)
-    /*    25 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function-else-test")
-            << "foo()\nelse: bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncTerminator)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(0)
-    /*    14 */ /* else branch */ << I(11)
-    /*    16 */     << H(TokLine) << H(2)
-    /*    18 */     << H(TokHashLiteral) << HS(L"bar")
-    /*    25 */     << H(TokCondition)
-    /*    26 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-test-else-test")
-            << "foo:bar\nelse: baz"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokCondition)
-    /*    19 */ << H(TokBranch)
-    /*    20 */ /* then branch */ << I(0)
-    /*    22 */ /* else branch */ << I(11)
-    /*    24 */     << H(TokLine) << H(2)
-    /*    26 */     << H(TokHashLiteral) << HS(L"baz")
-    /*    33 */     << H(TokCondition)
-    /*    34 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-test-else-test-else-test-function")
-            << "foo:bar\nelse: baz\nelse: bak\nbuzz()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokCondition)
-    /*    19 */ << H(TokBranch)
-    /*    20 */ /* then branch */ << I(0)
-    /*    22 */ /* else branch */ << I(27)
-    /*    24 */     << H(TokLine) << H(2)
-    /*    26 */     << H(TokHashLiteral) << HS(L"baz")
-    /*    33 */     << H(TokCondition)
-    /*    34 */     << H(TokBranch)
-    /*    35 */     /* then branch */ << I(0)
-    /*    37 */     /* else branch */ << I(11)
-    /*    39 */         << H(TokLine) << H(3)
-    /*    41 */         << H(TokHashLiteral) << HS(L"bak")
-    /*    48 */         << H(TokCondition)
-    /*    49 */         << H(TokTerminator)
-    /*    50 */     << H(TokTerminator)
-    /*    51 */ << H(TokLine) << H(4)
-    /*    53 */ << H(TokHashLiteral) << HS(L"buzz")
-    /*    61 */ << H(TokTestCall)
-    /*    62 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-assignment-else-assignment")
-            << "foo: VAR =\nelse: VAR="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokBranch)
-    /*    11 */ /* then branch */ << I(11)
-    /*    13 */     << H(TokHashLiteral) << HS(L"VAR")
-    /*    20 */     << H(TokAssign) << H(0)
-    /*    22 */     << H(TokValueTerminator)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(13)
-    /*    26 */     << H(TokLine) << H(2)
-    /*    28 */     << H(TokHashLiteral) << HS(L"VAR")
-    /*    35 */     << H(TokAssign) << H(0)
-    /*    37 */     << H(TokValueTerminator)
-    /*    38 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-else-test-assignment")
-            << "foo\nelse: bar: VAR ="
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokBranch)
-    /*    11 */ /* then branch */ << I(0)
-    /*    13 */ /* else branch */ << I(27)
-    /*    15 */     << H(TokLine) << H(2)
-    /*    17 */     << H(TokHashLiteral) << HS(L"bar")
-    /*    24 */     << H(TokCondition)
-    /*    25 */     << H(TokBranch)
-    /*    26 */     /* then branch */ << I(11)
-    /*    28 */         << H(TokHashLiteral) << HS(L"VAR")
-    /*    35 */         << H(TokAssign) << H(0)
-    /*    37 */         << H(TokValueTerminator)
-    /*    38 */         << H(TokTerminator)
-    /*    39 */     /* else branch */ << I(0)
-    /*    41 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("one function")
-            << "foo()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("one function (with spaces)")
-            << " foo(  ) "
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("unterminated function call")
-            << "foo(\nfoo"
-            << TS()
-            << "in:1: Missing closing parenthesis in function call"
-            << false;
-
-    QTest::newRow("function with arguments")
-            << "foo(blah, hi ho)"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokLiteral | TokNewStr) << S(L"blah")
-    /*    16 */     << H(TokArgSeparator)
-    /*    17 */     << H(TokLiteral | TokNewStr) << S(L"hi")
-    /*    21 */     << H(TokLiteral | TokNewStr) << S(L"ho")
-    /*    25 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function with empty arguments")
-            << "foo(,)"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokArgSeparator)
-    /*    11 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function with funny arguments")
-            << "foo(blah\\, \"hi ,  \\ho\" ,uh\\  ,\\oh  ,,   )"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokLiteral | TokNewStr) << S(L"blah\\")
-    /*    17 */     << H(TokArgSeparator)
-    /*    18 */     << H(TokLiteral | TokNewStr) << S(L"hi ,  \\ho")
-    /*    29 */     << H(TokArgSeparator)
-    /*    30 */     << H(TokLiteral | TokNewStr) << S(L"uh\\")
-    /*    35 */     << H(TokArgSeparator)
-    /*    36 */     << H(TokLiteral | TokNewStr) << S(L"\\oh")
-    /*    41 */     << H(TokArgSeparator)
-    /*    42 */     << H(TokArgSeparator)
-    /*    43 */     << H(TokFuncTerminator))
-            << "WARNING: in:1: Unescaped backslashes are deprecated\n"
-               "WARNING: in:1: Unescaped backslashes are deprecated\n"
-               "WARNING: in:1: Unescaped backslashes are deprecated\n"
-               "WARNING: in:1: Unescaped backslashes are deprecated"
-            << true;
-
-    QTest::newRow("function with nested call")
-            << "foo($$blah(hi ho))"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncName | TokNewStr) << HS(L"blah")
-    /*    18 */         << H(TokLiteral | TokNewStr) << S(L"hi")
-    /*    22 */         << H(TokLiteral | TokNewStr) << S(L"ho")
-    /*    26 */         << H(TokFuncTerminator)
-    /*    27 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("stand-alone parentheses")
-            << "()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestCall)
-    /*     3 */     << H(TokFuncTerminator))
-            << "in:1: Opening parenthesis without prior test name."
-            << false;
-
-    QTest::newRow("bogus test and function")
-            << "foo bar()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestCall)
-    /*     3 */     << H(TokFuncTerminator))
-            << "in:1: Extra characters after test expression."
-            << false;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("two functions")
-            << "foo() bar()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncTerminator)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokTestCall)
-    /*    19 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("function-AND-test")
-            << "foo():bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokTestCall)
-    /*    10 */     << H(TokFuncTerminator)
-    /*    11 */ << H(TokAnd)
-    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    19 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-function")
-            << "foo:bar()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    18 */ << H(TokTestCall)
-    /*    19 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("NOT-function-AND-test")
-            << "!foo():bar"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokNot)
-    /*     3 */ << H(TokHashLiteral) << HS(L"foo")
-    /*    10 */ << H(TokTestCall)
-    /*    11 */     << H(TokFuncTerminator)
-    /*    12 */ << H(TokAnd)
-    /*    13 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    20 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-NOT-function")
-            << "foo:!bar()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"foo")
-    /*     9 */ << H(TokCondition)
-    /*    10 */ << H(TokAnd)
-    /*    11 */ << H(TokNot)
-    /*    12 */ << H(TokHashLiteral) << HS(L"bar")
-    /*    19 */ << H(TokTestCall)
-    /*    20 */     << H(TokFuncTerminator))
-            << ""
-            << true;
-
-    // Control statements
-
-    QTest::newRow("for(VAR, LIST) loop")
-            << "for(VAR, LIST)"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"VAR")
-    /*     9 */ /* iterator */ << I(7)
-    /*    11 */     << H(TokLiteral | TokNewStr) << S(L"LIST")
-    /*    17 */     << H(TokValueTerminator)
-    /*    18 */ /* body */ << I(1)
-    /*    20 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("for(ever) loop")
-            << "for(ever)"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(1)
-    /*    19 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    // This is a rather questionable "feature"
-    QTest::newRow("for($$blub) loop")
-            << "for($$blub)"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokVariable | TokNewStr) << HS(L"blub")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(1)
-    /*    19 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-for-test-else-test")
-            << "true:for(VAR, LIST): true\nelse: true"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(31)
-    /*    14 */     << H(TokForLoop) << HS(L"VAR")
-    /*    21 */     /* iterator */ << I(7)
-    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
-    /*    29 */         << H(TokValueTerminator)
-    /*    30 */     /* body */ << I(12)
-    /*    32 */         << H(TokLine) << H(1)
-    /*    34 */         << H(TokHashLiteral) << HS(L"true")
-    /*    42 */         << H(TokCondition)
-    /*    43 */         << H(TokTerminator)
-    /*    44 */     << H(TokTerminator)
-    /*    45 */ /* else branch */ << I(12)
-    /*    47 */     << H(TokLine) << H(2)
-    /*    49 */     << H(TokHashLiteral) << HS(L"true")
-    /*    57 */     << H(TokCondition)
-    /*    58 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("next()")
-            << "for(ever): next()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(4)
-    /*    19 */     << H(TokLine) << H(1)
-    /*    21 */     << H(TokNext)
-    /*    22 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("break()")
-            << "for(ever): break()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(4)
-    /*    19 */     << H(TokLine) << H(1)
-    /*    21 */     << H(TokBreak)
-    /*    22 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("top-level return()")
-            << "return()"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokReturn))
-            << ""
-            << true;
-
-    QTest::newRow("else")
-            << "else"
-            << TS()
-            << "in:1: Unexpected 'else'."
-            << false;
-
-    QTest::newRow("test-{else}")
-            << "test { else }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(0))
-            << "in:1: Unexpected 'else'."
-            << false;
-
-    QTest::newRow("defineTest-{else}")
-            << "defineTest(fn) { else }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestDef) << HS(L"fn")
-    /*     8 */ /* body */ << I(1)
-    /*    10 */     << H(TokTerminator))
-            << "in:1: Unexpected 'else'."
-            << false;
-
-    QTest::newRow("for-else")
-            << "for(ever) { else }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(1)
-    /*    19 */     << H(TokTerminator))
-            << "in:1: Unexpected 'else'."
-            << false;
-
-    // Braces
-
-    QTest::newRow("{}")
-            << "{ }"
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("{}-newlines")
-            << "\n\n{ }\n\n"
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("{")
-            << "{"
-            << TS()
-            << "in:2: Missing closing brace(s)."
-            << false;
-
-    QTest::newRow("test {")
-            << "test {"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(0))
-            << "in:2: Missing closing brace(s)."
-            << false;
-
-    QTest::newRow("}")
-            << "}"
-            << TS()
-            << "in:1: Excess closing brace."
-            << false;
-
-    QTest::newRow("{test}")
-            << "{ true }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("{test-newlines}")
-            << "{\ntrue\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(2)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("{assignment-test}-test")
-            << "{ VAR = { foo } bar } true"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(4)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{")
-    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    19 */ << H(TokLiteral | TokNewStr) << S(L"}")
-    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"bar")
-    /*    27 */ << H(TokValueTerminator)
-    /*    28 */ << H(TokHashLiteral) << HS(L"true")
-    /*    36 */ << H(TokCondition))
-            << ""
-            << true;
-
-    QTest::newRow("assignment with excess opening brace")
-            << "VAR = { { foo }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"VAR")
-    /*     9 */ << H(TokAssign) << H(4)
-    /*    11 */ << H(TokLiteral | TokNewStr) << S(L"{")
-    /*    14 */ << H(TokLiteral | TokNewStr) << S(L"{")
-    /*    17 */ << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    22 */ << H(TokLiteral | TokNewStr) << S(L"}")
-    /*    25 */ << H(TokValueTerminator))
-            << "WARNING: in:1: Possible braces mismatch"
-            << true;
-
-    QTest::newRow("test-{}")
-            << "true {}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-{newlines}")
-            << "true {\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-{test}")
-            << "true { true }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(10)
-    /*    14 */     << H(TokHashLiteral) << HS(L"true")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test:-{test}")
-            << "true: { true }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(10)
-    /*    14 */     << H(TokHashLiteral) << HS(L"true")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(0))
-            << "WARNING: in:1: Excess colon in front of opening brace."
-            << true;
-
-    QTest::newRow("test-{test-newlines}")
-            << "true {\ntrue\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(12)
-    /*    14 */     << H(TokLine) << H(2)
-    /*    16 */     << H(TokHashLiteral) << HS(L"true")
-    /*    24 */     << H(TokCondition)
-    /*    25 */     << H(TokTerminator)
-    /*    26 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test:-{test-newlines}")
-            << "true: {\ntrue\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(12)
-    /*    14 */     << H(TokLine) << H(2)
-    /*    16 */     << H(TokHashLiteral) << HS(L"true")
-    /*    24 */     << H(TokCondition)
-    /*    25 */     << H(TokTerminator)
-    /*    26 */ /* else branch */ << I(0))
-            << "WARNING: in:1: Excess colon in front of opening brace."
-            << true;
-
-    QTest::newRow("test-{assignment}")
-            << "true { VAR = {foo} }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(18)
-    /*    14 */     << H(TokHashLiteral) << HS(L"VAR")
-    /*    21 */     << H(TokAssign) << H(0)
-    /*    23 */     << H(TokLiteral | TokNewStr) << S(L"{foo}")
-    /*    30 */     << H(TokValueTerminator)
-    /*    31 */     << H(TokTerminator)
-    /*    32 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-{test-assignment}")
-            << "true { true: VAR = {foo} }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(33)
-    /*    14 */     << H(TokHashLiteral) << HS(L"true")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokBranch)
-    /*    24 */     /* then branch */ << I(18)
-    /*    26 */         << H(TokHashLiteral) << HS(L"VAR")
-    /*    33 */         << H(TokAssign) << H(0)
-    /*    35 */         << H(TokLiteral | TokNewStr) << S(L"{foo}")
-    /*    42 */         << H(TokValueTerminator)
-    /*    43 */         << H(TokTerminator)
-    /*    44 */     /* else branch */ << I(0)
-    /*    46 */     << H(TokTerminator)
-    /*    47 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-{assignment-newlines}")
-            << "true {\nVAR = {foo}\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(20)
-    /*    14 */     << H(TokLine) << H(2)
-    /*    16 */     << H(TokHashLiteral) << HS(L"VAR")
-    /*    23 */     << H(TokAssign) << H(0)
-    /*    25 */     << H(TokLiteral | TokNewStr) << S(L"{foo}")
-    /*    32 */     << H(TokValueTerminator)
-    /*    33 */     << H(TokTerminator)
-    /*    34 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-{}-else-test-{}")
-            << "true {} else: true {}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(18)
-    /*    17 */     << H(TokLine) << H(1)
-    /*    19 */     << H(TokHashLiteral) << HS(L"true")
-    /*    27 */     << H(TokCondition)
-    /*    28 */     << H(TokBranch)
-    /*    29 */     /* then branch */ << I(1)
-    /*    31 */         << H(TokTerminator)
-    /*    32 */     /* else branch */ << I(0)
-    /*    34 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-{}-else-test-{}-newlines")
-            << "true {\n}\nelse: true {\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(1)
-    /*    14 */     << H(TokTerminator)
-    /*    15 */ /* else branch */ << I(18)
-    /*    17 */     << H(TokLine) << H(3)
-    /*    19 */     << H(TokHashLiteral) << HS(L"true")
-    /*    27 */     << H(TokCondition)
-    /*    28 */     << H(TokBranch)
-    /*    29 */     /* then branch */ << I(1)
-    /*    31 */         << H(TokTerminator)
-    /*    32 */     /* else branch */ << I(0)
-    /*    34 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-{test}-else-test-{}-newlines")
-            << "true {\ntrue\n}\nelse: true {\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(12)
-    /*    14 */     << H(TokLine) << H(2)
-    /*    16 */     << H(TokHashLiteral) << HS(L"true")
-    /*    24 */     << H(TokCondition)
-    /*    25 */     << H(TokTerminator)
-    /*    26 */ /* else branch */ << I(18)
-    /*    28 */     << H(TokLine) << H(4)
-    /*    30 */     << H(TokHashLiteral) << HS(L"true")
-    /*    38 */     << H(TokCondition)
-    /*    39 */     << H(TokBranch)
-    /*    40 */     /* then branch */ << I(1)
-    /*    42 */         << H(TokTerminator)
-    /*    43 */     /* else branch */ << I(0)
-    /*    45 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("for-{next}")
-            << "for(ever) { next() }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(4)
-    /*    19 */     << H(TokLine) << H(1)
-    /*    21 */     << H(TokNext)
-    /*    22 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("for:-{next}")
-            << "for(ever): { next() }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokForLoop) << HS(L"")
-    /*     6 */ /* iterator */ << I(9)
-    /*     8 */     << H(TokHashLiteral) << HS(L"ever")
-    /*    16 */     << H(TokValueTerminator)
-    /*    17 */ /* body */ << I(4)
-    /*    19 */     << H(TokLine) << H(1)
-    /*    21 */     << H(TokNext)
-    /*    22 */     << H(TokTerminator))
-            << "WARNING: in:1: Excess colon in front of opening brace."
-            << true;
-
-    QTest::newRow("test-for-{test-else-test-newlines}")
-            << "true:for(VAR, LIST) {\ntrue\nelse: true\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(48)
-    /*    14 */     << H(TokForLoop) << HS(L"VAR")
-    /*    21 */     /* iterator */ << I(7)
-    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
-    /*    29 */         << H(TokValueTerminator)
-    /*    30 */     /* body */ << I(29)
-    /*    32 */         << H(TokLine) << H(2)
-    /*    34 */         << H(TokHashLiteral) << HS(L"true")
-    /*    42 */         << H(TokCondition)
-    /*    43 */         << H(TokBranch)
-    /*    44 */         /* then branch */ << I(0)
-    /*    46 */         /* else branch */ << I(12)
-    /*    48 */             << H(TokLine) << H(3)
-    /*    50 */             << H(TokHashLiteral) << HS(L"true")
-    /*    58 */             << H(TokCondition)
-    /*    59 */             << H(TokTerminator)
-    /*    60 */         << H(TokTerminator)
-    /*    61 */     << H(TokTerminator)
-    /*    62 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    QTest::newRow("test-for-{test-else-test}")
-            << "true:for(VAR, LIST) { true\nelse: true }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"true")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(48)
-    /*    14 */     << H(TokForLoop) << HS(L"VAR")
-    /*    21 */     /* iterator */ << I(7)
-    /*    23 */         << H(TokLiteral | TokNewStr) << S(L"LIST")
-    /*    29 */         << H(TokValueTerminator)
-    /*    30 */     /* body */ << I(29)
-    /*    32 */         << H(TokLine) << H(1)
-    /*    34 */         << H(TokHashLiteral) << HS(L"true")
-    /*    42 */         << H(TokCondition)
-    /*    43 */         << H(TokBranch)
-    /*    44 */         /* then branch */ << I(0)
-    /*    46 */         /* else branch */ << I(12)
-    /*    48 */             << H(TokLine) << H(2)
-    /*    50 */             << H(TokHashLiteral) << HS(L"true")
-    /*    58 */             << H(TokCondition)
-    /*    59 */             << H(TokTerminator)
-    /*    60 */         << H(TokTerminator)
-    /*    61 */     << H(TokTerminator)
-    /*    62 */ /* else branch */ << I(0))
-            << ""
-            << true;
-
-    // Custom functions
-
-    QTest::newRow("defineTest-{newlines}")
-            << "defineTest(test) {\n}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestDef) << HS(L"test")
-    /*    10 */ /* body */ << I(1)
-    /*    12 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("defineTest:-test")
-            << "defineTest(test): test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestDef) << HS(L"test")
-    /*    10 */ /* body */ << I(12)
-    /*    12 */     << H(TokLine) << H(1)
-    /*    14 */     << H(TokHashLiteral) << HS(L"test")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("defineTest-{test}")
-            << "defineTest(test) { test }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestDef) << HS(L"test")
-    /*    10 */ /* body */ << I(12)
-    /*    12 */     << H(TokLine) << H(1)
-    /*    14 */     << H(TokHashLiteral) << HS(L"test")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("defineTest-{return}")
-            << "defineTest(test) { return() }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokTestDef) << HS(L"test")
-    /*    10 */ /* body */ << I(4)
-    /*    12 */     << H(TokLine) << H(1)
-    /*    14 */     << H(TokReturn)
-    /*    15 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("defineReplace-{return-stuff}")
-            << "defineReplace(stuff) { return(foo bar) }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokReplaceDef) << HS(L"stuff")
-    /*    11 */ /* body */ << I(14)
-    /*    13 */     << H(TokLine) << H(1)
-    /*    15 */     << H(TokLiteral | TokNewStr) << S(L"foo")
-    /*    20 */     << H(TokLiteral | TokNewStr) << S(L"bar")
-    /*    25 */     << H(TokReturn)
-    /*    26 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-AND-defineTest-{}")
-            << "test: defineTest(test) {}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokAnd)
-    /*    12 */ << H(TokTestDef) << HS(L"test")
-    /*    20 */ /* body */ << I(1)
-    /*    22 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    QTest::newRow("test-OR-defineTest-{}")
-            << "test| defineTest(test) {}"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokOr)
-    /*    12 */ << H(TokTestDef) << HS(L"test")
-    /*    20 */ /* body */ << I(1)
-    /*    22 */     << H(TokTerminator))
-            << ""
-            << true;
-
-    // Operator abuse
-
-    QTest::newRow("!")
-            << ""
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("|")
-            << ""
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow(":")
-            << ""
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("NOT-assignment")
-            << "!VAR ="
-            << TS()
-            << "in:1: Unexpected NOT operator in front of assignment."
-            << false;
-
-    QTest::newRow("NOT-{}")
-            << "!{}"
-            << TS()
-            << "in:1: Unexpected NOT operator in front of opening brace."
-            << false;
-
-    QTest::newRow("NOT-else")
-            << "test\n!else {}"
-            << TS()
-            << "in:2: Unexpected NOT operator in front of else."
-            << false;
-
-    QTest::newRow("NOT-for-{}")
-            << "!for(ever) {}"
-            << TS()
-            << "in:1: Unexpected NOT operator in front of for()."
-            << false;
-
-    QTest::newRow("NOT-defineTest-{}")
-            << "!defineTest(test) {}"
-            << TS()
-            << "in:1: Unexpected NOT operator in front of function definition."
-            << false;
-
-    QTest::newRow("AND-test")
-            << ":test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition))
-            << "in:1: AND operator without prior condition."
-            << false;
-
-    QTest::newRow("test-AND-else")
-            << "test:else"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition))
-            << "in:1: Unexpected AND operator in front of else."
-            << false;
-
-    QTest::newRow("test-AND-AND-test")
-            << "test::test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokAnd)
-    /*    12 */ << H(TokHashLiteral) << HS(L"test")
-    /*    20 */ << H(TokCondition))
-            << "WARNING: in:1: Stray AND operator in front of AND operator."
-            << true;
-
-    QTest::newRow("test-AND-OR-test")
-            << "test:|test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokOr)
-    /*    12 */ << H(TokHashLiteral) << HS(L"test")
-    /*    20 */ << H(TokCondition))
-            << "WARNING: in:1: Stray AND operator in front of OR operator."
-            << true;
-
-    QTest::newRow("test-{AND-test}")
-            << "test { :test }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(10)
-    /*    14 */     << H(TokHashLiteral) << HS(L"test")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(0))
-            << "in:1: AND operator without prior condition."
-            << false;
-
-    QTest::newRow("test-OR-assignment")
-            << "foo| VAR ="
-            << TS()
-            << "in:1: Unexpected OR operator in front of assignment."
-            << false;
-
-    QTest::newRow("test-OR-{}")
-            << "foo|{}"
-            << TS()
-            << "in:1: Unexpected OR operator in front of opening brace."
-            << false;
-
-    QTest::newRow("test-OR-for")
-            << "foo|for(ever) {}"
-            << TS()
-            << "in:1: Unexpected OR operator in front of for()."
-            << false;
-
-    QTest::newRow("OR-test")
-            << "|test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition))
-            << "in:1: OR operator without prior condition."
-            << false;
-
-    QTest::newRow("test-OR-else")
-            << "test|else"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition))
-            << "in:1: Unexpected OR operator in front of else."
-            << false;
-
-    QTest::newRow("test-OR-OR-test")
-            << "test||test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokOr)
-    /*    12 */ << H(TokHashLiteral) << HS(L"test")
-    /*    20 */ << H(TokCondition))
-            << "WARNING: in:1: Stray OR operator in front of OR operator."
-            << true;
-
-    QTest::newRow("test-OR-AND-test")
-            << "test|:test"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokAnd)
-    /*    12 */ << H(TokHashLiteral) << HS(L"test")
-    /*    20 */ << H(TokCondition))
-            << "WARNING: in:1: Stray OR operator in front of AND operator."
-            << true;
-
-    QTest::newRow("test-{OR-test}")
-            << "test { |test }"
-            << TS(
-    /*     0 */ << H(TokLine) << H(1)
-    /*     2 */ << H(TokHashLiteral) << HS(L"test")
-    /*    10 */ << H(TokCondition)
-    /*    11 */ << H(TokBranch)
-    /*    12 */ /* then branch */ << I(10)
-    /*    14 */     << H(TokHashLiteral) << HS(L"test")
-    /*    22 */     << H(TokCondition)
-    /*    23 */     << H(TokTerminator)
-    /*    24 */ /* else branch */ << I(0))
-            << "in:1: OR operator without prior condition."
-            << false;
-
-    // option() (these produce no tokens)
-
-    QTest::newRow("option(host_build)")
-            << "option(host_build)"
-            << TS()
-            << ""
-            << true;
-
-    QTest::newRow("option()")
-            << "option()"
-            << TS()
-            << "in:1: option() requires one literal argument."
-            << false;
-
-    QTest::newRow("option(host_build magic)")
-            << "option(host_build magic)"
-            << TS()
-            << "in:1: option() requires one literal argument."
-            << false;
-
-    QTest::newRow("option(host_build, magic)")
-            << "option(host_build, magic)"
-            << TS()
-            << "in:1: option() requires one literal argument."
-            << false;
-
-    QTest::newRow("option($$OPTION)")
-            << "option($$OPTION)"
-            << TS()
-            << "in:1: option() requires one literal argument."
-            << false;
-
-    QTest::newRow("{option(host_build)}")
-            << "{option(host_build)}"
-            << TS()
-            << "in:1: option() must appear outside any control structures."
-            << false;
+    QString pfx = ((type & QMakeParserHandler::CategoryMask) == QMakeParserHandler::WarningMessage)
+                  ? QString::fromLatin1("WARNING: ") : QString();
+    if (lineNo)
+        doPrint(QStringLiteral("%1%2:%3: %4").arg(pfx, fileName, QString::number(lineNo), msg));
+    else
+        doPrint(QStringLiteral("%1%2").arg(pfx, msg));
 }
 
-void tst_qmakelib::proParser()
+void QMakeTestHandler::doPrint(const QString &msg)
 {
-    QFETCH(QString, in);
-    QFETCH(QString, out);
-    QFETCH(QString, msgs);
-    QFETCH(bool, ok);
-
-    bool verified = true;
-    QMakeHandler handler;
-    handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts));
-    QMakeVfs vfs;
-    QMakeParser parser(0, &vfs, &handler);
-    ProFile *pro = parser.parsedProBlock(in, "in", 1, QMakeParser::FullGrammar);
-    if (handler.printedMessages()) {
-        qWarning("Got unexpected message(s)");
-        verified = false;
-    }
-    QStringList missingMsgs = handler.expectedMessages();
-    if (!missingMsgs.isEmpty()) {
-        foreach (const QString &msg, missingMsgs)
-            qWarning("Missing message: %s", qPrintable(msg));
-        verified = false;
-    }
-    if (pro->isOk() != ok) {
-        static const char * const lbl[] = { "failure", "success" };
-        qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
-        verified = false;
-    }
-    if (pro->items() != out && (ok || !out.isEmpty())) {
-        qWarning("Bytecode mismatch.\nActual:%s\nExpected:%s",
-                 qPrintable(QMakeParser::formatProBlock(pro->items())),
-                 qPrintable(QMakeParser::formatProBlock(out)));
-        verified = false;
+    if (!expected.isEmpty() && expected.first() == msg) {
+        expected.removeAt(0);
+    } else {
+        qWarning("%s", qPrintable(msg));
+        printed = true;
     }
-    pro->deref();
-    QVERIFY(verified);
 }
 
 QTEST_MAIN(tst_qmakelib)
-#include "tst_qmakelib.moc"
diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.h b/tests/auto/tools/qmakelib/tst_qmakelib.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4716ca65ef5853f6c827ec52732654384eb8d57
--- /dev/null
+++ b/tests/auto/tools/qmakelib/tst_qmakelib.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include <qmakeevaluator.h>
+
+#include <QObject>
+#include <QProcessEnvironment>
+#include <QtTest/QtTest>
+
+class tst_qmakelib : public QObject
+{
+    Q_OBJECT
+
+public:
+    tst_qmakelib() {}
+    virtual ~tst_qmakelib() {}
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void quoteArgUnix_data();
+    void quoteArgUnix();
+    void quoteArgWin_data();
+    void quoteArgWin();
+    void pathUtils();
+
+    void proString();
+    void proStringList();
+
+    void proParser_data();
+    void proParser();
+
+    void proEval_data();
+    void proEval();
+
+private:
+    void addParseOperators();
+    void addParseValues();
+    void addParseConditions();
+    void addParseControlStatements();
+    void addParseBraces();
+    void addParseCustomFunctions();
+    void addParseAbuse();
+
+    void addAssignments();
+    void addExpansions();
+    void addControlStructs();
+    void addReplaceFunctions(const QString &qindir);
+    void addTestFunctions(const QString &qindir);
+
+    QProcessEnvironment m_env;
+    QHash<ProKey, ProString> m_prop;
+    QString m_indir, m_outdir;
+};
+
+class QMakeTestHandler : public QMakeHandler {
+public:
+    QMakeTestHandler() : QMakeHandler(), printed(false) {}
+    virtual void message(int type, const QString &msg, const QString &fileName, int lineNo)
+        { print(fileName, lineNo, type, msg); }
+
+    virtual void fileMessage(const QString &msg)
+        { doPrint(msg); }
+
+    virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {}
+    virtual void doneWithEval(ProFile *) {}
+
+    void setExpectedMessages(const QStringList &msgs) { expected = msgs; }
+    QStringList expectedMessages() const { return expected; }
+
+    bool printedMessages() const { return printed; }
+
+private:
+    void print(const QString &fileName, int lineNo, int type, const QString &msg);
+    void doPrint(const QString &msg);
+
+    QStringList expected;
+    bool printed;
+};
+
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index fecc14f541e4aa57140fc28f99f24b7c6436450d..e62ce3ceb5c120efff65bf0ad45cd466e3db1cb2 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -564,6 +564,11 @@ void tst_QDialog::snapToDefaultButton()
     topLeftPos = QPoint(topLeftPos.x() + 100, topLeftPos.y() + 100);
     QPoint startingPos(topLeftPos.x() + 250, topLeftPos.y() + 250);
     QCursor::setPos(startingPos);
+#ifdef Q_OS_OSX
+    // On OS X we use CGEventPost to move the cursor, it needs at least
+    // some time before the event handled and the position really set.
+    QTest::qWait(100);
+#endif
     QCOMPARE(QCursor::pos(), startingPos);
     QDialog dialog;
     QPushButton *button = new QPushButton(&dialog);
diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm
index 6e4ad29190237e805b98a275b7d2fdb1cdfc54aa..0d29f5b7a2ef3e6880935a2f2d313f1ed72c08f3 100644
--- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm
+++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm
@@ -36,7 +36,7 @@
 
 void click_cocoa_button()
 {
-    QMacCocoaAutoReleasePool pool;
+    QMacAutoReleasePool pool;
     NSArray *windows = [NSApp windows];
     for (NSWindow *window in windows) {
         // This is NOT how one should do RTTI, but since I don't want to leak the class too much...
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
index d9d9818d6c125be590f4b8a9c9fc93a9362dfda7..38fef5139451ea53e916211f672581058cc5d355 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
@@ -6,5 +6,4 @@ QT += core-private gui-private
 
 SOURCES  += tst_qgraphicsproxywidget.cpp
 
-contains(QT_CONFIG,xcb):CONFIG+=insignificant_test  # QTBUG-25294
 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index f8d852888c925b1f5b3ee63d1e669672b29c6bbe..05a97dc2f3285ef03b5ecdad3725869c12828b55 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -1223,6 +1223,7 @@ void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
 
     QGraphicsScene scene;
     QGraphicsView view(&scene);
+    view.resize(500, 500);
     view.show();
     QVERIFY(QTest::qWaitForWindowExposed(&view));
 
@@ -1231,7 +1232,6 @@ void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
     QPushButton *widget = new QPushButton;
     QSignalSpy spy(widget, SIGNAL(clicked()));
     widget->resize(50, 50);
-    view.resize(100, 100);
     if (hasWidget) {
         proxy->setWidget(widget);
         proxy->show();
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index 7bd039376049a55750e8061959d01cb19faf71c2..ff29f998754e4be69568e54af2bdc2c7038ed212 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -1282,33 +1282,16 @@ void tst_QGraphicsScene::removeItem()
     view.show();
     QApplication::setActiveWindow(&view);
     QVERIFY(QTest::qWaitForWindowActive(&view));
-    QTest::mouseMove(view.viewport(), QPoint(-1, -1));
-    {
-        QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
-        QApplication::sendEvent(view.viewport(), &moveEvent);
-    }
-    qApp->processEvents(); // update
-    qApp->processEvents(); // draw
-    QVERIFY(!hoverItem->isHovered);
+    QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton);
+    QTRY_VERIFY(!hoverItem->isHovered);
 
-    {
-        QTest::qWait(250);
-        QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
-        QTest::qWait(10);
-        QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos()), Qt::NoButton, 0, 0);
-        QApplication::sendEvent(view.viewport(), &moveEvent);
-    }
-    qApp->processEvents(); // update
-    qApp->processEvents(); // draw
-    QVERIFY(hoverItem->isHovered);
+    QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
+    QTRY_VERIFY(hoverItem->isHovered);
 
     scene.removeItem(hoverItem);
     hoverItem->setAcceptsHoverEvents(false);
     scene.addItem(hoverItem);
-    qApp->processEvents(); // <- delayed update is called
-    qApp->processEvents(); // <- scene schedules pending update
-    qApp->processEvents(); // <- pending update is sent to view
-    QVERIFY(!hoverItem->isHovered);
+    QTRY_VERIFY(!hoverItem->isHovered);
 }
 
 void tst_QGraphicsScene::focusItem()
@@ -3509,6 +3492,8 @@ void tst_QGraphicsScene::task160653_selectionChanged()
 
     QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
     QGraphicsView view(&scene);
+    view.show();
+    QVERIFY(QTest::qWaitForWindowActive(&view));
     QTest::mouseClick(
         view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
     QCOMPARE(spy.count(), 1);
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index da0c5532a56a9db0abb0870661587ed3948fc2ac..ec2203e615c4146962fb9b954c30302c87049f77 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -179,16 +179,9 @@ private slots:
     void task250119_shortcutContext();
     void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
     void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
+    void QTBUG_45867_send_itemChildAddedChange_to_parent();
 };
 
-
-static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
-{
-    QTest::mouseMove(widget, point);
-    QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
-    QApplication::sendEvent(widget, &event);
-}
-
 // Subclass that exposes the protected functions.
 class SubQGraphicsWidget : public QGraphicsWidget {
 public:
@@ -196,7 +189,7 @@ public:
         : QGraphicsWidget(parent, windowFlags), eventCount(0)
         { }
 
-    void initStyleOption(QStyleOption *option)
+    void initStyleOption(QStyleOption *option) const
         { QGraphicsWidget::initStyleOption(option); }
 
     void call_changeEvent(QEvent* event)
@@ -1109,8 +1102,8 @@ void tst_QGraphicsWidget::initStyleOption()
 {
     QGraphicsScene scene;
     QGraphicsView view(&scene);
+    view.resize(300, 300);
     view.show();
-    QApplication::setActiveWindow(&view);
     QVERIFY(QTest::qWaitForWindowActive(&view));
 
     view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
@@ -1132,10 +1125,8 @@ void tst_QGraphicsWidget::initStyleOption()
     }
     QFETCH(bool, underMouse);
     if (underMouse) {
-        view.resize(300, 300);
-        view.show();
-        QVERIFY(QTest::qWaitForWindowActive(&view));
-        sendMouseMove(view.viewport(), view.mapFromScene(widget->mapToScene(widget->boundingRect().center())));
+        QCursor::setPos(view.viewport()->mapToGlobal(view.mapFromScene(widget->mapToScene(widget->boundingRect().center()))));
+        QTest::qWait(100);
     }
 
     QFETCH(QPalette, palette);
@@ -3490,5 +3481,36 @@ void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
     //This should not crash
 }
 
+void tst_QGraphicsWidget::QTBUG_45867_send_itemChildAddedChange_to_parent()
+{
+    class GraphicsItem : public QGraphicsItem
+    {
+    public:
+        int m_itemChildAddedChangeNotificationsCount;
+
+        GraphicsItem()
+            : QGraphicsItem(),
+              m_itemChildAddedChangeNotificationsCount(0)
+        {
+        }
+
+        QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(); }
+
+        void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE {}
+
+    protected:
+        QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) Q_DECL_OVERRIDE
+        {
+            if (change == QGraphicsItem::ItemChildAddedChange)
+                ++m_itemChildAddedChangeNotificationsCount;
+            return QGraphicsItem::itemChange(change, value);
+        }
+    };
+
+    GraphicsItem item;
+    QGraphicsWidget widget(&item);
+    QCOMPARE(item.m_itemChildAddedChangeNotificationsCount, 1);
+}
+
 QTEST_MAIN(tst_QGraphicsWidget)
 #include "tst_qgraphicswidget.moc"
diff --git a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
index 3a6f1f933dc9ab4684500889390838794e083389..f92eb7c8f961b01a11feb164586ca188f7b72067 100644
--- a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
+++ b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
@@ -483,6 +483,7 @@ void tst_QItemView::spider()
     view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
     view->setModel(treeModel);
     view->show();
+    QVERIFY(QTest::qWaitForWindowActive(view));
 #if defined(Q_OS_WINCE)
     srandom(0);
 #else
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index cea08435c980d241aabdb140d1e3bdcb4abf7615..b06a63365c8830a128b9c9493083c6b426da943c 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -38,6 +38,7 @@
 #include <qapplication.h>
 #include <qlistview.h>
 #include <private/qlistview_p.h>
+#include <private/qcoreapplication_p.h>
 #include <qlistwidget.h>
 #include <qitemdelegate.h>
 #include <qstandarditemmodel.h>
@@ -47,6 +48,7 @@
 #include <QtWidgets/QScrollBar>
 #include <QtWidgets/QDialog>
 #include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QStyleFactory>
 
 #if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
 #  include <windows.h>
@@ -148,6 +150,7 @@ private slots:
     void testScrollToWithHidden();
     void testViewOptions();
     void taskQTBUG_39902_mutualScrollBars();
+    void horizontalScrollingByVerticalWheelEvents();
 };
 
 // Testing get/set functions
@@ -1218,7 +1221,7 @@ void tst_QListView::scrollTo()
     list << "Short item";
     model.setStringList(list);
     lv.setModel(&model);
-    lv.setFixedSize(100, 200);
+    lv.setFixedSize(110, 200);
     topLevel.show();
     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
 
@@ -2348,11 +2351,34 @@ void tst_QListView::testViewOptions()
     QCOMPARE(options.decorationPosition, QStyleOptionViewItem::Top);
 }
 
+// make sure we have no transient scroll bars
+class TempStyleSetter
+{
+public:
+    TempStyleSetter()
+        : m_oldStyle(qApp->style())
+    {
+        m_oldStyle->setParent(0);
+        QListView tempView;
+        if (QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, tempView.horizontalScrollBar()))
+            QApplication::setStyle(QStyleFactory::create("Fusion"));
+    }
+
+    ~TempStyleSetter()
+    {
+        QApplication::setStyle(m_oldStyle);
+    }
+private:
+    QStyle* m_oldStyle;
+};
+
 void tst_QListView::taskQTBUG_39902_mutualScrollBars()
 {
     QWidget window;
     window.resize(400, 300);
     QListView *view = new QListView(&window);
+    // make sure we have no transient scroll bars
+    TempStyleSetter styleSetter;
     QStandardItemModel model(200, 1);
     const QSize itemSize(100, 20);
     for (int i = 0; i < model.rowCount(); ++i)
@@ -2370,6 +2396,91 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars()
     view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
     // this will end up in a stack overflow, if QTBUG-39902 is not fixed
     QTest::qWait(100);
+
+    // these tests do not apply with transient scroll bars enabled
+    QVERIFY (!view->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, view->horizontalScrollBar()));
+
+    // make it double as large, no scroll bars should be visible
+    view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2);
+    QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+    // make it half the size, both scroll bars should be visible
+    view->resize((itemSize.width() + view->frameWidth() * 2) / 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) / 2);
+    QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+    // make it double as large, no scroll bars should be visible
+    view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2);
+    QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+    // now, coming from the double size, resize it to the exactly matching size, still no scroll bars should be visible again
+    view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+    QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+    // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other
+    view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1);
+    QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+    // now remove just one single pixel in with -> both scroll bars will show up since they depend on each other
+    view->resize(itemSize.width() + view->frameWidth() * 2 - 1, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+    QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+    // finally, coming from a size being to small, resize back to the exactly matching size -> both scroll bars should disappear again
+    view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+    QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+    QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+}
+
+void tst_QListView::horizontalScrollingByVerticalWheelEvents()
+{
+    QListView lv;
+    lv.setWrapping(true);
+
+    TestDelegate *delegate = new TestDelegate(&lv);
+    delegate->m_sizeHint = QSize(100, 100);
+    lv.setItemDelegate(delegate);
+
+    QtTestModel model;
+    model.colCount = 1;
+    model.rCount = 100;
+
+    lv.setModel(&model);
+
+    lv.resize(300, 300);
+    lv.show();
+    QTest::qWaitForWindowExposed(&lv);
+
+    QPoint globalPos = lv.geometry().center();
+    QPoint pos = lv.viewport()->geometry().center();
+
+    QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), -120, Qt::Vertical, 0, 0);
+    QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), 120, Qt::Vertical, 0, 0);
+    QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), -120, Qt::Vertical, 0, 0);
+
+    int hValue = lv.horizontalScrollBar()->value();
+    QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
+    QVERIFY(lv.horizontalScrollBar()->value() > hValue);
+
+    QApplication::sendEvent(lv.viewport(), &wheelUpEvent);
+    QVERIFY(lv.horizontalScrollBar()->value() == hValue);
+
+    QApplication::sendEvent(lv.viewport(), &wheelLeftDownEvent);
+    QVERIFY(lv.horizontalScrollBar()->value() == hValue);
+
+    // ensure that vertical wheel events are not converted when vertical
+    // scroll bar is not visible but vertical scrolling is possible
+    lv.setWrapping(false);
+    lv.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    QApplication::processEvents();
+
+    int vValue = lv.verticalScrollBar()->value();
+    QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
+    QVERIFY(lv.verticalScrollBar()->value() > vValue);
 }
 
 QTEST_MAIN(tst_QListView)
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 6786ae9aa2b0f728412c98963780be67ad8c9cd4..dcbdbe824ad39809941ec1da00663d62e42a93ca 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -605,21 +605,21 @@ void tst_QListWidget::insertItems()
 void tst_QListWidget::itemAssignment()
 {
     QListWidgetItem itemInWidget("inWidget", testWidget);
-    itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+    itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsUserTristate);
     QListWidgetItem itemOutsideWidget("outsideWidget");
 
     QVERIFY(itemInWidget.listWidget());
     QCOMPARE(itemInWidget.text(), QString("inWidget"));
-    QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+    QVERIFY(itemInWidget.flags() & Qt::ItemIsUserTristate);
 
     QVERIFY(!itemOutsideWidget.listWidget());
     QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
-    QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+    QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsUserTristate));
 
     itemOutsideWidget = itemInWidget;
     QVERIFY(!itemOutsideWidget.listWidget());
     QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
-    QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+    QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsUserTristate);
 }
 
 void tst_QListWidget::item_data()
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 75f77f8107c30bc2c3101cf56129f9c07c1ae274..e5abd6bc463fdb7068d956ed2981bcce4c4c9de8 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -2249,11 +2249,11 @@ void tst_QTableView::resizeColumnsToContents_data()
     QTest::addColumn<int>("rowHeight");
     QTest::addColumn<int>("columnWidth");
 
-    QTest::newRow("10x10 grid shown 40x40")
-        << 10 << 10 << false << 40 << 40 << 40 << 40;
+    QTest::newRow("10x10 grid not shown 60x60")
+        << 10 << 10 << false << 60 << 60 << 60 << 60;
 
-    QTest::newRow("10x10 grid not shown 40x40")
-        << 10 << 10 << true << 40 << 40 << 41 << 41;
+    QTest::newRow("10x10 grid shown 60x60")
+        << 10 << 10 << true << 60 << 60 << 61 << 61;
 }
 
 void tst_QTableView::resizeColumnsToContents()
@@ -4051,9 +4051,9 @@ void tst_QTableView::mouseWheel()
     QWheelEvent verticalEvent(pos, delta, 0, 0, Qt::Vertical);
     QWheelEvent horizontalEvent(pos, delta, 0, 0, Qt::Horizontal);
     QApplication::sendEvent(view.viewport(), &horizontalEvent);
-    QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 10);
+    QVERIFY(qAbs(view.horizontalScrollBar()->value() - horizontalPositon) < 15);
     QApplication::sendEvent(view.viewport(), &verticalEvent);
-    QVERIFY(qAbs(view.verticalScrollBar()->value() - verticalPosition) < 10);
+    QVERIFY(qAbs(view.verticalScrollBar()->value() - verticalPosition) < 15);
 }
 #endif // !QT_NO_WHEELEVENT
 
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index a4c6e13979a1de8b140043f983895d73459064b3..36bc23910c3deb5a47d843c4f12b8af126cf31ec 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -281,21 +281,21 @@ void tst_QTableWidget::itemAssignment()
 {
     QTableWidgetItem itemInWidget("inWidget");
     testWidget->setItem(0, 0, &itemInWidget);
-    itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+    itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsUserTristate);
     QTableWidgetItem itemOutsideWidget("outsideWidget");
 
     QVERIFY(itemInWidget.tableWidget());
     QCOMPARE(itemInWidget.text(), QString("inWidget"));
-    QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+    QVERIFY(itemInWidget.flags() & Qt::ItemIsUserTristate);
 
     QVERIFY(!itemOutsideWidget.tableWidget());
     QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
-    QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+    QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsUserTristate));
 
     itemOutsideWidget = itemInWidget;
     QVERIFY(!itemOutsideWidget.tableWidget());
     QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
-    QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+    QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsUserTristate);
 }
 
 void tst_QTableWidget::item_data()
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 3ead172d82df830d19601eb67771032e5876f3ed..1324027af64daa037f43fd84798c197061804bfe 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -255,6 +255,7 @@ private slots:
     void taskQTBUG_8176_emitOnExpandAll();
     void taskQTBUG_34717_collapseAtBottom();
     void taskQTBUG_37813_crash();
+    void taskQTBUG_45697_crash();
     void testInitialFocus();
 };
 
@@ -4385,5 +4386,82 @@ void tst_QTreeView::taskQTBUG_37813_crash()
 #endif // QT_BUILD_INTERNAL
 }
 
+// QTBUG-45697: Using a QTreeView with a multi-column model filtered by QSortFilterProxyModel,
+// when sorting the source model while the widget is not yet visible and showing the widget
+// later on, corruption occurs in QTreeView.
+class Qtbug45697TestWidget : public QWidget
+{
+   Q_OBJECT
+public:
+    static const int columnCount = 3;
+
+    explicit Qtbug45697TestWidget();
+    int timerTick() const { return m_timerTick; }
+
+public slots:
+    void slotTimer();
+
+private:
+   QTreeView *m_treeView;
+   QStandardItemModel *m_model;
+   QSortFilterProxyModel *m_sortFilterProxyModel;
+   int m_timerTick;
+};
+
+Qtbug45697TestWidget::Qtbug45697TestWidget()
+    : m_treeView(new QTreeView(this))
+    , m_model(new QStandardItemModel(0, Qtbug45697TestWidget::columnCount, this))
+    , m_sortFilterProxyModel(new QSortFilterProxyModel(this))
+    , m_timerTick(0)
+ {
+   QVBoxLayout *vBoxLayout = new QVBoxLayout(this);
+   vBoxLayout->addWidget(m_treeView);
+
+   for (char sortChar = 'z'; sortChar >= 'a' ; --sortChar) {
+       QList<QStandardItem *>  items;
+       for (int column = 0; column < Qtbug45697TestWidget::columnCount; ++column) {
+           const QString text = QLatin1Char(sortChar) + QLatin1String(" ") + QString::number(column);
+           items.append(new QStandardItem(text));
+       }
+       m_model->appendRow(items);
+   }
+
+   m_sortFilterProxyModel->setSourceModel(m_model);
+   m_treeView->setModel(m_sortFilterProxyModel);
+
+   QHeaderView *headerView = m_treeView->header();
+   for (int s = 1, lastSection = headerView->count() - 1; s < lastSection; ++s )
+       headerView->setSectionResizeMode(s, QHeaderView::ResizeToContents);
+
+   QTimer *timer = new QTimer(this);
+   timer->setInterval(50);
+   connect(timer, &QTimer::timeout, this, &Qtbug45697TestWidget::slotTimer);
+   timer->start();
+}
+
+void Qtbug45697TestWidget::slotTimer()
+{
+    switch (m_timerTick++) {
+    case 0:
+        m_model->sort(0);
+        break;
+    case 1:
+        show();
+        break;
+    default:
+        close();
+        break;
+    }
+}
+
+void tst_QTreeView::taskQTBUG_45697_crash()
+{
+    Qtbug45697TestWidget testWidget;
+    testWidget.setWindowTitle(QTest::currentTestFunction());
+    testWidget.resize(400, 400);
+    testWidget.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(100, 100));
+    QTRY_VERIFY(testWidget.timerTick() >= 2);
+}
+
 QTEST_MAIN(tst_QTreeView)
 #include "tst_qtreeview.moc"
diff --git a/tests/auto/widgets/kernel/qaction/BLACKLIST b/tests/auto/widgets/kernel/qaction/BLACKLIST
index f67a3c471e6aa087e65cf2c2a734bba4a76a6ae9..a2afc905ba5096439eea049692b9184e21f73c67 100644
--- a/tests/auto/widgets/kernel/qaction/BLACKLIST
+++ b/tests/auto/widgets/kernel/qaction/BLACKLIST
@@ -1,2 +1,2 @@
 [setStandardKeys]
-ubuntu-14.04
+ubuntu
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index bee18392b4c49e6a71464607391a6828ccfa104f..5d833eea2820ebc9522377c389d37a7f276520d5 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -179,6 +179,12 @@ private slots:
 
     void settableStyleHints_data();
     void settableStyleHints();  // Needs to run last as it changes style hints.
+
+protected slots:
+    void quitApplication();
+
+private:
+    bool quitApplicationTriggered;
 };
 
 class EventSpy : public QObject
@@ -236,6 +242,7 @@ public:
 static  char *argv0;
 
 tst_QApplication::tst_QApplication()
+    : quitApplicationTriggered(false)
 {
 #ifdef Q_OS_WINCE
     // Clean up environment previously to launching test
@@ -720,11 +727,8 @@ void tst_QApplication::quitOnLastWindowClosed()
     {
         int argc = 0;
         QApplication app(argc, 0);
-        QTimer timer;
-        timer.setInterval(100);
 
         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
-        QSignalSpy spy2(&timer, SIGNAL(timeout()));
 
         CloseEventTestWindow mainWindow;
 
@@ -734,14 +738,14 @@ void tst_QApplication::quitOnLastWindowClosed()
         mainWindow.show();
         QVERIFY(QTest::qWaitForWindowExposed(&mainWindow));
 
-        timer.start();
-        QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should quit the application
-        QTimer::singleShot(2000, &app, SLOT(quit()));        // This makes sure we quit even if it didn't
+        QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should NOT quit the application (see CloseEventTestWindow)
+        quitApplicationTriggered = false;
+        QTimer::singleShot(2000, this, SLOT(quitApplication())); // This actually quits the application.
 
         app.exec();
 
         QCOMPARE(spy.count(), 1);
-        QVERIFY(spy2.count() > 15);      // Should be around 20 if closing did not caused the quit
+        QVERIFY(quitApplicationTriggered);
     }
     {
         int argc = 0;
@@ -769,24 +773,20 @@ void tst_QApplication::quitOnLastWindowClosed()
         QApplication app(argc, 0);
         QVERIFY(app.quitOnLastWindowClosed());
 
-        QTimer timer;
-        timer.setInterval(100);
-        QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
-
         QWindow w;
         w.show();
 
         QWidget wid;
         wid.show();
 
-        timer.start();
         QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
                                                        // QWindow is still there.
-        QTimer::singleShot(2000, &app, SLOT(quit()));  // This causes the quit.
+        quitApplicationTriggered = false;
+        QTimer::singleShot(2000, this, SLOT(quitApplication()));  // This causes the quit.
 
         app.exec();
 
-        QVERIFY(timerSpy.count() > 15);      // Should be around 20 if closing did not caused the quit
+        QVERIFY(quitApplicationTriggered);      // Should be around 20 if closing did not caused the quit
     }
     {   // QTBUG-31569: If the last widget with Qt::WA_QuitOnClose set is closed, other
         // widgets that don't have the attribute set should be closed automatically.
@@ -2411,6 +2411,12 @@ void tst_QApplication::globalStaticObjectDestruction()
 #endif
 }
 
+void tst_QApplication::quitApplication()
+{
+    quitApplicationTriggered = true;
+    qApp->quit();
+}
+
 //QTEST_APPLESS_MAIN(tst_QApplication)
 int main(int argc, char *argv[])
 {
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
index ebd99be786127ae81b68d7a525b4f71c0f8b2698..0de9e188a042ef46838bd5a932dad37c5499baf6 100644
--- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -34,30 +34,32 @@
 
 #include <QtTest/QtTest>
 #include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qscreen.h>
 
 class tst_QToolTip : public QObject
 {
     Q_OBJECT
 
-public:
-    tst_QToolTip() {}
-    virtual ~tst_QToolTip() {}
-
-public slots:
-    void initTestCase() {}
-    void cleanupTestCase() {}
-    void init() {}
-    void cleanup() {}
-
 private slots:
-
-    // task-specific tests below me
+    void init();
+    void cleanup();
     void task183679_data();
     void task183679();
     void whatsThis();
     void setPalette();
 };
 
+void tst_QToolTip::init()
+{
+    QVERIFY(!QToolTip::isVisible());
+}
+
+void tst_QToolTip::cleanup()
+{
+    QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
+}
+
 class Widget_task183679 : public QWidget
 {
     Q_OBJECT
@@ -100,12 +102,14 @@ void tst_QToolTip::task183679()
 #endif
 
     Widget_task183679 widget;
+    widget.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(50, 50));
+    widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())
+                          + QLatin1Char(' ') + QLatin1String(QTest::currentDataTag()));
     widget.show();
     QApplication::setActiveWindow(&widget);
     QVERIFY(QTest::qWaitForWindowActive(&widget));
 
     widget.showDelayedToolTip(100);
-    QTest::qWait(300);
     QTRY_VERIFY(QToolTip::isVisible());
 
     QTest::keyPress(&widget, key);
@@ -116,26 +120,31 @@ void tst_QToolTip::task183679()
     QTest::qWait(1500);
 
     QCOMPARE(QToolTip::isVisible(), visible);
+    if (visible)
+        QToolTip::hideText();
 }
 
-#include <QWhatsThis>
+static QWidget *findWhatsThat()
+{
+    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+        if (widget->inherits("QWhatsThat"))
+            return widget;
+    }
+    return Q_NULLPTR;
+}
 
 void tst_QToolTip::whatsThis()
 {
     qApp->setStyleSheet( "QWidget { font-size: 72px; }" );
-    QWhatsThis::showText(QPoint(0,0), "THis is text");
-    QTest::qWait(400);
-    QWidget *whatsthis = 0;
-    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
-        if (widget->inherits("QWhatsThat")) {
-            whatsthis = widget;
-            break;
-        }
-    }
-    QVERIFY(whatsthis);
+    QWhatsThis::showText(QPoint(0, 0), "This is text");
+
+    QWidget *whatsthis = Q_NULLPTR;
+    QTRY_VERIFY( (whatsthis = findWhatsThat()) );
     QVERIFY(whatsthis->isVisible());
-    QVERIFY(whatsthis->height() > 100); // Test QTBUG-2416
-    qApp->setStyleSheet("");
+    const int whatsThisHeight = whatsthis->height();
+    qApp->setStyleSheet(QString());
+    QWhatsThis::hideText();
+    QVERIFY2(whatsThisHeight > 100, QByteArray::number(whatsThisHeight)); // Test QTBUG-2416
 }
 
 
@@ -167,6 +176,7 @@ void tst_QToolTip::setPalette()
     newPalette.setColor(QPalette::ToolTipText, Qt::blue);
     QToolTip::setPalette(newPalette);
     QCOMPARE(toolTip->palette(), newPalette);
+    QToolTip::hideText();
 }
 
 QTEST_MAIN(tst_QToolTip)
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index ed40f98051b9036c8f5cea42274d449ad30bf7f4..591aa9e40f5539bef3283256eacba5d7c6eab370 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -1,11 +1,16 @@
+# OSX QTBUG-25300 QTBUG-45502
 [normalGeometry]
 ubuntu-14.04
+osx
 [saveRestoreGeometry]
 ubuntu-14.04
+osx
 [restoreVersion1Geometry]
 ubuntu-14.04
+osx
 [updateWhileMinimized]
 ubuntu-14.04
+osx
 [focusProxyAndInputMethods]
 ubuntu-14.04
 [touchEventSynthesizedMouseEvent]
@@ -14,3 +19,119 @@ ubuntu-14.04
 ubuntu-14.04
 [largerThanScreen_QTBUG30142]
 ubuntu-14.04
+[windowState]
+osx
+[showMaximized]
+osx
+[setGeometry]
+osx
+[stackUnder]
+osx
+[raise]
+osx-10.9
+[widgetAt]
+osx
+[sheetOpacity]
+osx
+[resizeEvent]
+osx
+[setWindowGeometry:100,123 200x200, flags 0]
+osx-10.10
+[windowMoveResize:100,123 200x200, flags 0]
+osx-10.10
+[setWindowGeometry:100,122 200x200, flags 0]
+osx-10.9
+[windowMoveResize:100,122 200x200, flags 0]
+osx-10.9
+[setWindowGeometry:100,100 824x564, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x564, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x516, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x516, flags 0]
+osx-10.10
+[setWindowGeometry:100,73 200x0, flags 0]
+osx-10.10
+[windowMoveResize:100,73 200x0, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x519, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x519, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x518, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x518, flags 0]
+osx-10.10
+[setWindowGeometry:100,72 200x0, flags 0]
+osx-10.9
+[windowMoveResize:100,72 200x0, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x574, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x574, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x578, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x578, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x576, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x576, flags 0]
+osx-10.9
+[setWindowGeometry:100,100 824x521, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x521, flags 0]
+osx-10.10
+[setWindowGeometry:100,122 952x577, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x577, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x580, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x580, flags 0]
+osx-10.9
+[windowMoveResize:130,72 0x0, flags 0]
+osx-10.9
+[windowMoveResize:130,122 0x200, flags 0]
+osx-10.9
+[childEvents]
+osx
+[renderInvisible]
+osx
+[optimizedResizeMove]
+osx
+[optimizedResize_topLevel]
+osx
+[render_systemClip]
+osx
+[update]
+osx
+[doubleRepaint]
+osx
+[childAt_unifiedToolBar]
+osx
+[showMinimizedKeepsFocus]
+osx-10.10
+[moveWindowInShowEvent:1]
+osx-10.9
+[moveWindowInShowEvent:2]
+osx-10.9
+[taskQTBUG_4055_sendSyntheticEnterLeave]
+osx
+[syntheticEnterLeave]
+osx
+[maskedUpdate]
+osx
+[hideWhenFocusWidgetIsChild]
+osx-10.10
+[hideOpaqueChildWhileHidden]
+osx
+[resizeStaticContentsChildWidget_QTBUG35282]
+osx-10.9
+[lower]
+osx
+[setClearAndResizeMask]
+osx
+[setToolTip]
+osx-10.9
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index 30e1048247c5a495c22d38e51d28255346495c53..aae083d45e0e2c90b133d61404be02a5c3c1e293 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -21,5 +21,3 @@ x11 {
 }
 
 !wince*:win32:!winrt: LIBS += -luser32 -lgdi32
-
-mac:CONFIG+=insignificant_test # QTBUG-25300, QTBUG-23695
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index e9b8372b434f07e888fc187114ff3f9ba2aae76c..38a45117a1a059536b9895a928d69423472ade78 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -443,6 +443,7 @@ private slots:
     void grabKeyboard();
 
     void touchEventSynthesizedMouseEvent();
+    void touchUpdateOnNewTouch();
 
     void styleSheetPropagation();
 
@@ -3342,8 +3343,6 @@ void tst_QWidget::widgetAt()
 #if defined(Q_OS_WINCE)
     QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
 #endif
-    if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
-        QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
 
     QTRY_VERIFY((wr = QApplication::widgetAt(testPos)));
     QTRY_COMPARE(wr->objectName(), w1->objectName());
@@ -3362,8 +3361,6 @@ void tst_QWidget::widgetAt()
 #if defined(Q_OS_WINCE)
     QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
 #endif
-    if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
-        QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
     QTRY_VERIFY(QApplication::widgetAt(testPos) == w1.data());
     QTRY_VERIFY(QApplication::widgetAt(testPos + QPoint(1, 1)) == w2.data());
 }
@@ -3451,7 +3448,8 @@ void tst_QWidget::testDeletionInEventHandlers()
     w = new Widget;
     w->show();
     w->deleteThis = true;
-    QTest::mouseRelease(w, Qt::LeftButton);
+    QMouseEvent me(QEvent::MouseButtonRelease, QPoint(1, 1), Qt::LeftButton, Qt::LeftButton, 0);
+    qApp->notify(w, &me);
     QVERIFY(w == 0);
     delete w;
 
@@ -3489,7 +3487,7 @@ void tst_QWidget::testDeletionInEventHandlers()
     w->setMouseTracking(true);
     w->show();
     w->deleteThis = true;
-    QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
+    me = QMouseEvent(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
     QApplication::sendEvent(w, &me);
     QVERIFY(w == 0);
     delete w;
@@ -8966,7 +8964,7 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
          int numEnterEvents, numMouseMoveEvents;
      };
 
-    QCursor::setPos(QPoint(0,0));
+     QCursor::setPos(QPoint(0,0));
 
      SELParent parent;
      parent.move(200, 200);
@@ -8974,8 +8972,7 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
      SELChild child(&parent);
      child.resize(200, 200);
      parent.show();
-     QVERIFY(QTest::qWaitForWindowExposed(&parent));
-     QTest::qWait(150);
+     QVERIFY(QTest::qWaitForWindowActive(&parent));
 
      QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
      // Make sure the cursor has entered the child.
@@ -9723,8 +9720,9 @@ void tst_QWidget::grabMouse()
     QVERIFY(QTest::qWaitForWindowActive(&w));
 
     QStringList expectedLog;
-    grabber->grabMouse();
     QPoint mousePos = QPoint(w.width() / 2, 10);
+    QTest::mouseMove(w.windowHandle(), mousePos);
+    grabber->grabMouse();
     const int step = w.height() / 5;
     for ( ; mousePos.y() < w.height() ; mousePos.ry() += step) {
         QTest::mouseClick(w.windowHandle(), Qt::LeftButton, 0, mousePos);
@@ -9765,6 +9763,9 @@ class TouchMouseWidget : public QWidget {
 public:
     explicit TouchMouseWidget(QWidget *parent = 0)
         : QWidget(parent),
+          m_touchBeginCount(0),
+          m_touchUpdateCount(0),
+          m_touchEndCount(0),
           m_touchEventCount(0),
           m_acceptTouch(false),
           m_mouseEventCount(0),
@@ -9791,6 +9792,12 @@ protected:
         case QEvent::TouchBegin:
         case QEvent::TouchUpdate:
         case QEvent::TouchEnd:
+            if (e->type() == QEvent::TouchBegin)
+                ++m_touchBeginCount;
+            else if (e->type() == QEvent::TouchUpdate)
+                ++m_touchUpdateCount;
+            else if (e->type() == QEvent::TouchEnd)
+                ++m_touchEndCount;
             ++m_touchEventCount;
             if (m_acceptTouch)
                 e->accept();
@@ -9815,6 +9822,9 @@ protected:
     }
 
 public:
+    int m_touchBeginCount;
+    int m_touchUpdateCount;
+    int m_touchEndCount;
     int m_touchEventCount;
     bool m_acceptTouch;
     int m_mouseEventCount;
@@ -9931,6 +9941,46 @@ void tst_QWidget::touchEventSynthesizedMouseEvent()
     }
 }
 
+void tst_QWidget::touchUpdateOnNewTouch()
+{
+    QTouchDevice *device = new QTouchDevice;
+    device->setType(QTouchDevice::TouchScreen);
+    QWindowSystemInterface::registerTouchDevice(device);
+
+    TouchMouseWidget widget;
+    widget.setAcceptTouch(true);
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->addWidget(new QWidget);
+    widget.setLayout(layout);
+    widget.show();
+
+    QWindow* window = widget.windowHandle();
+    QVERIFY(QTest::qWaitForWindowExposed(window));
+    QCOMPARE(widget.m_touchBeginCount, 0);
+    QCOMPARE(widget.m_touchUpdateCount, 0);
+    QCOMPARE(widget.m_touchEndCount, 0);
+    QTest::touchEvent(window, device).press(0, QPoint(20, 20), window);
+    QCOMPARE(widget.m_touchBeginCount, 1);
+    QCOMPARE(widget.m_touchUpdateCount, 0);
+    QCOMPARE(widget.m_touchEndCount, 0);
+    QTest::touchEvent(window, device).move(0, QPoint(25, 25), window);
+    QCOMPARE(widget.m_touchBeginCount, 1);
+    QCOMPARE(widget.m_touchUpdateCount, 1);
+    QCOMPARE(widget.m_touchEndCount, 0);
+    QTest::touchEvent(window, device).stationary(0).press(1, QPoint(40, 40), window);
+    QCOMPARE(widget.m_touchBeginCount, 1);
+    QCOMPARE(widget.m_touchUpdateCount, 2);
+    QCOMPARE(widget.m_touchEndCount, 0);
+    QTest::touchEvent(window, device).stationary(1).release(0, QPoint(25, 25), window);
+    QCOMPARE(widget.m_touchBeginCount, 1);
+    QCOMPARE(widget.m_touchUpdateCount, 3);
+    QCOMPARE(widget.m_touchEndCount, 0);
+    QTest::touchEvent(window, device).release(1, QPoint(40, 40), window);
+    QCOMPARE(widget.m_touchBeginCount, 1);
+    QCOMPARE(widget.m_touchUpdateCount, 3);
+    QCOMPARE(widget.m_touchEndCount, 1);
+}
+
 void tst_QWidget::styleSheetPropagation()
 {
     QTableView tw;
@@ -10342,6 +10392,9 @@ public:
 void tst_QWidget::keyboardModifiers()
 {
     KeyboardWidget w;
+    w.resize(300, 300);
+    w.show();
+    QVERIFY(QTest::qWaitForWindowActive(&w));
     QTest::mouseClick(&w, Qt::LeftButton, Qt::ControlModifier);
     QCOMPARE(w.m_eventCounter, 1);
     QCOMPARE(int(w.m_modifiers), int(Qt::ControlModifier));
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
index 9c549365ff0ce6c4b4f047cf1162eda7c15525d0..38b473e5aed514c8788d4d36612ebc659a601b7f 100644
--- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
@@ -90,6 +90,7 @@ private slots:
 //    void buttons();
 
     void testDelete();
+    void testSignalEmissionAfterDelete_QTBUG_45835();
     void testRemove();
     void testMultipleAdd();
     void testStandardButtonMapping_data();
@@ -111,6 +112,7 @@ private:
 
 tst_QDialogButtonBox::tst_QDialogButtonBox()
 {
+    qRegisterMetaType<QAbstractButton *>();
 }
 
 tst_QDialogButtonBox::~tst_QDialogButtonBox()
@@ -414,6 +416,70 @@ void tst_QDialogButtonBox::testDelete()
     QCOMPARE(buttonBox.buttons().count(), 0);
 }
 
+class ObjectDeleter : public QObject
+{
+    Q_OBJECT
+public slots:
+    void deleteButton(QAbstractButton *button)
+    {
+        delete button;
+    }
+
+    void deleteSender()
+    {
+        delete sender();
+    }
+};
+
+void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835()
+{
+    {
+        QDialogButtonBox buttonBox;
+        QCOMPARE(buttonBox.buttons().count(), 0);
+
+        QSignalSpy buttonClickedSpy(&buttonBox, &QDialogButtonBox::clicked);
+        QVERIFY(buttonClickedSpy.isValid());
+
+        QSignalSpy buttonBoxAcceptedSpy(&buttonBox, &QDialogButtonBox::accepted);
+        QVERIFY(buttonBoxAcceptedSpy.isValid());
+
+        QPushButton *button = buttonBox.addButton("Test", QDialogButtonBox::AcceptRole);
+        QCOMPARE(buttonBox.buttons().count(), 1);
+
+        ObjectDeleter objectDeleter;
+        connect(&buttonBox, &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteButton);
+
+        button->click();
+
+        QCOMPARE(buttonBox.buttons().count(), 0);
+        QCOMPARE(buttonClickedSpy.count(), 1);
+        QCOMPARE(buttonBoxAcceptedSpy.count(), 1);
+    }
+
+    {
+        QPointer<QDialogButtonBox> buttonBox(new QDialogButtonBox);
+        QCOMPARE(buttonBox->buttons().count(), 0);
+
+        QSignalSpy buttonClickedSpy(buttonBox.data(), &QDialogButtonBox::clicked);
+        QVERIFY(buttonClickedSpy.isValid());
+
+        QSignalSpy buttonBoxAcceptedSpy(buttonBox.data(), &QDialogButtonBox::accepted);
+        QVERIFY(buttonBoxAcceptedSpy.isValid());
+
+        QPushButton *button = buttonBox->addButton("Test", QDialogButtonBox::AcceptRole);
+        QCOMPARE(buttonBox->buttons().count(), 1);
+
+        ObjectDeleter objectDeleter;
+        connect(buttonBox.data(), &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteSender);
+
+        button->click();
+
+        QVERIFY(buttonBox.isNull());
+        QCOMPARE(buttonClickedSpy.count(), 1);
+        QCOMPARE(buttonBoxAcceptedSpy.count(), 0);
+    }
+}
+
 void tst_QDialogButtonBox::testMultipleAdd()
 {
     // Add a button into the thing multiple times.
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index ade9f725437e234f3ffd3d52477c26daba53f306..2bbc2e05b733dbf28718ac56080fcb55cdfbd50a 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -764,6 +764,8 @@ void tst_QDockWidget::restoreDockWidget()
         restoreWindow.show();
         QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow));
         QTRY_VERIFY(dock->isFloating());
+        if (!QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive))
+            QSKIP("Skip due to Window manager positioning issues", Abort);
         QTRY_COMPARE(dock->pos(), dockPos);
     }
 }
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 94175410400076f5fa7f103fff2e5f6e782f90d0..adedc601a96588dbee9048b2d33a05b7cfb847c2 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -304,6 +304,7 @@ private slots:
     void undoRedoAndEchoModes();
 
     void clearButton();
+    void clearButtonVisibleAfterSettingText_QTBUG_45518();
     void sideWidgets();
 
     void shouldShowPlaceholderText_data();
@@ -4273,6 +4274,50 @@ void tst_QLineEdit::clearButton()
     QVERIFY(!clearButton->isEnabled());
 }
 
+void tst_QLineEdit::clearButtonVisibleAfterSettingText_QTBUG_45518()
+{
+#ifndef QT_BUILD_INTERNAL
+    QSKIP("This test requires a developer build");
+#else
+    QLineEdit edit;
+    edit.setMinimumWidth(200);
+    centerOnScreen(&edit);
+    QLineEditIconButton *clearButton;
+    clearButton = edit.findChild<QLineEditIconButton *>();
+    QVERIFY(!clearButton);
+
+    edit.setText(QStringLiteral("some text"));
+    edit.show();
+    QVERIFY(QTest::qWaitForWindowActive(&edit));
+
+    QVERIFY(!edit.isClearButtonEnabled());
+
+    clearButton = edit.findChild<QLineEditIconButton *>();
+    QVERIFY(!clearButton);
+
+    edit.setClearButtonEnabled(true);
+    QVERIFY(edit.isClearButtonEnabled());
+
+    clearButton = edit.findChild<QLineEditIconButton *>();
+    QVERIFY(clearButton);
+    QVERIFY(clearButton->isVisible());
+
+    QTRY_VERIFY(clearButton->opacity() > 0);
+    QTRY_COMPARE(clearButton->cursor().shape(), Qt::ArrowCursor);
+
+    QTest::mouseClick(clearButton, Qt::LeftButton, 0, clearButton->rect().center());
+    QTRY_COMPARE(edit.text(), QString());
+
+    QTRY_COMPARE(clearButton->opacity(), qreal(0));
+    QTRY_COMPARE(clearButton->cursor().shape(), clearButton->parentWidget()->cursor().shape());
+
+    edit.setClearButtonEnabled(false);
+    QVERIFY(!edit.isClearButtonEnabled());
+    clearButton = edit.findChild<QLineEditIconButton *>();
+    QVERIFY(!clearButton);
+#endif // QT_BUILD_INTERNAL
+}
+
 void tst_QLineEdit::sideWidgets()
 {
     QWidget testWidget;
diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST
new file mode 100644
index 0000000000000000000000000000000000000000..de49d5ff45926eb1cbdb9d38de87cc120a57bca3
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST
@@ -0,0 +1,2 @@
+[task258920_mouseBorder]
+osx
diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
index 53ea4a91488c5f1d96678ab0661a11b574cf1dbc..424ab2ceedd219cea4d79a377cfd75e31a508ac7 100644
--- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
@@ -2,3 +2,5 @@
 ubuntu-14.04
 [taskQTBUG4965_escapeEaten]
 ubuntu-14.04
+[task256322_highlight]
+osx
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/001.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/001.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/002.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/002.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/004.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/004.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/005.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/005.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/006.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/006.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/007.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/007.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/008.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/008.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/009.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/009.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/011.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/011.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/012.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/012.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/013.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/013.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/014.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/ext-sa/014.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/002.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/002.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/003-1.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/003-1.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/004-1.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/004-1.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/004-2.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/004-2.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/005-1.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/005-1.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/005-2.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/005-2.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/006.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/006.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/007.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/007.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/008.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/008.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/009.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/009.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/010.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/010.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/011.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/011.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/012.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/012.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/013.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/013.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/014.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/014.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/015.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/015.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/016.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/016.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/017.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/017.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/018.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/018.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/019.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/019.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/020.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/020.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/021.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/021.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/022.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/022.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/023.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/023.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/024.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/024.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/025.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/025.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/026.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/026.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/027.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/027.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/028.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/028.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/029.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/029.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/030.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/030.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/031-1.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/031-1.ent
old mode 100755
new mode 100644
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/031-2.ent b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/not-sa/031-2.ent
old mode 100755
new mode 100644
diff --git a/tests/benchmarks/gui/text/qtext/main.cpp b/tests/benchmarks/gui/text/qtext/main.cpp
index 224d9619ec0bb43cb850a448d4e2c67dbbc56619..f20b3f6cce3d0be58f16ee3142df711a71ffb257 100644
--- a/tests/benchmarks/gui/text/qtext/main.cpp
+++ b/tests/benchmarks/gui/text/qtext/main.cpp
@@ -42,7 +42,7 @@
 #include <QBuffer>
 #include <qtest.h>
 
-Q_DECLARE_METATYPE(QList<QTextLayout::FormatRange>)
+Q_DECLARE_METATYPE(QVector<QTextLayout::FormatRange>)
 
 class tst_QText: public QObject
 {
@@ -324,13 +324,13 @@ void tst_QText::layout()
 void tst_QText::formattedLayout_data()
 {
     QTest::addColumn<QString>("text");
-    QTest::addColumn<QList<QTextLayout::FormatRange> >("ranges");
+    QTest::addColumn<QVector<QTextLayout::FormatRange> >("ranges");
 
     QTextCharFormat format;
     format.setForeground(QColor("steelblue"));
 
     {
-        QList<QTextLayout::FormatRange> ranges;
+        QVector<QTextLayout::FormatRange> ranges;
 
         QTextLayout::FormatRange formatRange;
         formatRange.format = format;
@@ -341,7 +341,7 @@ void tst_QText::formattedLayout_data()
         QTest::newRow("short-single") << m_shortLorem << ranges;
     }
     {
-        QList<QTextLayout::FormatRange> ranges;
+        QVector<QTextLayout::FormatRange> ranges;
 
         QString text = m_lorem.repeated(100);
         const int width = 1;
@@ -360,15 +360,15 @@ void tst_QText::formattedLayout_data()
 void tst_QText::formattedLayout()
 {
     QFETCH(QString, text);
-    QFETCH(QList<QTextLayout::FormatRange>, ranges);
+    QFETCH(QVector<QTextLayout::FormatRange>, ranges);
 
     QTextLayout layout(text);
-    layout.setAdditionalFormats(ranges);
+    layout.setFormats(ranges);
     setupTextLayout(&layout);
 
     QBENCHMARK {
         QTextLayout layout(text);
-        layout.setAdditionalFormats(ranges);
+        layout.setFormats(ranges);
         setupTextLayout(&layout);
     }
 }
diff --git a/tests/manual/qscreen/README b/tests/manual/qscreen/README
index 5f5da17293df062e2916dd2cebbc9d5ae14b1935..cd1324276d13531657dced8eb7dee3df32e08eb5 100644
--- a/tests/manual/qscreen/README
+++ b/tests/manual/qscreen/README
@@ -20,14 +20,10 @@ create two windows, and will center one each screen, by setting the geometry.
 
 Alternatively you can configure xorg.conf to create separate screens for each
 graphics card; then the mouse cursor can move between the screens, but
-application windows cannot: each app needs to be started up on the screen that
-you want to run it on. In either case, ideally this test app ought to create
-two windows, one on each screen; but in fact, it can do that only if the
-screens are virtual siblings. If they are on different Displays, the second
-Display is not accessible to the QXcbConnection instance which was createad on
-the first Display. It can be considered a known bug that the API appears to
-make this possible (you would think QWindow::setScreen might work) but it
-isn't possible.
+application windows cannot: each app needs to be started on the screen that
+you want to run it on (by specifying e.g. DISPLAY=:0.1 for the second screen),
+or the application has to set the desired screen via QWindow::setScreen() before
+showing the window.
 
 The physical size of the screen is considered to be a constant. This can create
 discrepancies in DPI when orientation is changed, or when the screen is
diff --git a/tests/manual/qscreen/main.cpp b/tests/manual/qscreen/main.cpp
index ef9c2efe191eb9e96ff0e6afbac113d1d6604cda..8ed9cebfb46908da4e90378035257e778998c87b 100644
--- a/tests/manual/qscreen/main.cpp
+++ b/tests/manual/qscreen/main.cpp
@@ -44,6 +44,7 @@
 #include <QAction>
 #include <QStatusBar>
 #include <QLineEdit>
+#include <QDesktopWidget>
 
 class ScreenPropertyWatcher : public PropertyWatcher
 {
@@ -156,19 +157,17 @@ void screenAdded(QScreen* screen)
         (screen->virtualSiblings().isEmpty() ? "none" : qPrintable(screen->virtualSiblings().first()->name())));
     ScreenWatcherMainWindow *w = new ScreenWatcherMainWindow(screen);
 
-    // This doesn't work.  If the multiple screens are part of
-    // a virtual desktop (i.e. they are virtual siblings), then
-    // setScreen has no effect, and we need the code below to
-    // change the window geometry.  If on the other hand the
-    // screens are really separate, so that windows are not
-    // portable between them, XCreateWindow needs to have not just
-    // a different root Window but also a different Display, in order to
-    // put the window on the other screen.  That would require a
-    // different QXcbConnection.  So this setScreen call doesn't seem useful.
-    //w->windowHandle()->setScreen(screen);
-
-    // But this works as long as the screens are all virtual siblings
+    // Set the screen via QDesktopWidget. This corresponds to setScreen() for the underlying
+    // QWindow. This is essential when having separate X screens since the the positioning below is
+    // not sufficient to get the windows show up on the desired screen.
+    QList<QScreen *> screens = QGuiApplication::screens();
+    int screenNumber = screens.indexOf(screen);
+    Q_ASSERT(screenNumber >= 0);
+    w->setParent(qApp->desktop()->screen(screenNumber));
+
     w->show();
+
+    // Position the windows so that they end up at the center of the corresponding screen.
     QRect geom = w->geometry();
     geom.setSize(w->sizeHint());
     if (geom.height() > screen->geometry().height())
diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp
index 5a83decfa2162152967fcf771158fff1838c4295..c8353a40c0a1b4edf1fd86a489dc4610437a1da6 100644
--- a/tests/manual/qtabletevent/regular_widgets/main.cpp
+++ b/tests/manual/qtabletevent/regular_widgets/main.cpp
@@ -100,17 +100,19 @@ EventReportWidget::EventReportWidget()
 void EventReportWidget::paintEvent(QPaintEvent *)
 {
     QPainter p(this);
+    int lineSpacing = fontMetrics().lineSpacing();
+    int halfLineSpacing = lineSpacing / 2;
     const QRectF geom = QRectF(QPoint(0, 0), size());
     p.fillRect(geom, Qt::white);
     p.drawRect(QRectF(geom.topLeft(), geom.bottomRight() - QPointF(1,1)));
     p.setPen(Qt::white);
     QPainterPath ellipse;
-    ellipse.addEllipse(0, 0, 50, 10);
+    ellipse.addEllipse(0, 0, halfLineSpacing * 5, halfLineSpacing);
     foreach (const TabletPoint &t, m_points) {
         if (geom.contains(t.pos)) {
               QPainterPath pp;
-              pp.addEllipse(t.pos, 8, 8);
-              QRectF pointBounds(t.pos.x() - 10, t.pos.y() - 10, 20, 20);
+              pp.addEllipse(t.pos, halfLineSpacing, halfLineSpacing);
+              QRectF pointBounds(t.pos.x() - halfLineSpacing, t.pos.y() - halfLineSpacing, lineSpacing, lineSpacing);
               switch (t.type) {
               case TabletButtonPress:
                   p.fillPath(pp, Qt::darkGreen);
@@ -133,7 +135,7 @@ void EventReportWidget::paintEvent(QPaintEvent *)
                           p.drawPath(ellipse);
                           p.restore();
                       } else {
-                          p.drawEllipse(t.pos, t.pressure * 10.0, t.pressure * 10.0);
+                          p.drawEllipse(t.pos, t.pressure * halfLineSpacing, t.pressure * halfLineSpacing);
                       }
                       p.setPen(Qt::white);
                   } else {
diff --git a/tests/manual/touch/main.cpp b/tests/manual/touch/main.cpp
index f4c9f6bf8bf18a277e34251d234c993de71e5b55..b7029767c9f07b153891e60caa1feb49d80ab5ca 100644
--- a/tests/manual/touch/main.cpp
+++ b/tests/manual/touch/main.cpp
@@ -32,21 +32,65 @@
 ****************************************************************************/
 
 #include <QApplication>
+#include <QGesture>
 #include <QLabel>
 #include <QMenu>
 #include <QMenuBar>
 #include <QAction>
 #include <QMainWindow>
 #include <QSplitter>
+#include <QToolBar>
 #include <QVector>
 #include <QCommandLineOption>
 #include <QCommandLineParser>
 #include <QPlainTextEdit>
+#include <QPainter>
+#include <QPainterPath>
 #include <QPaintEvent>
 #include <QScreen>
+#include <QSharedPointer>
 #include <QDebug>
 #include <QTextStream>
 
+bool optIgnoreTouch = false;
+QVector<Qt::GestureType> optGestures;
+
+static inline void drawCircle(const QPointF &center, qreal radius, const QColor &color, QPainter &painter)
+{
+    const QPen oldPen = painter.pen();
+    QPen pen = oldPen;
+    pen.setColor(color);
+    painter.setPen(pen);
+    painter.drawEllipse(center, radius, radius);
+    painter.setPen(oldPen);
+}
+
+static inline void fillCircle(const QPointF &center, qreal radius, const QColor &color, QPainter &painter)
+{
+    QPainterPath painterPath;
+    painterPath.addEllipse(center, radius, radius);
+    painter.fillPath(painterPath, color);
+}
+
+// Draws an arrow assuming a mathematical coordinate system, Y axis pointing
+// upwards, angle counterclockwise (that is, 45' is pointing up/right).
+static void drawArrow(const QPointF &center, qreal length, qreal angleDegrees,
+                      const QColor &color, int arrowSize, QPainter &painter)
+{
+    painter.save();
+    painter.translate(center); // Transform center to (0,0) rotate and draw arrow pointing right.
+    painter.rotate(-angleDegrees);
+    QPen pen = painter.pen();
+    pen.setColor(color);
+    pen.setWidth(2);
+    painter.setPen(pen);
+    const QPointF endPoint(length, 0);
+    painter.drawLine(QPointF(0, 0), endPoint);
+    painter.drawLine(endPoint, endPoint + QPoint(-arrowSize, -arrowSize));
+    painter.drawLine(endPoint, endPoint + QPoint(-arrowSize, arrowSize));
+    painter.restore();
+}
+
 QDebug operator<<(QDebug debug, const QTouchDevice *d)
 {
     QDebugStateSaver saver(debug);
@@ -65,6 +109,110 @@ QDebug operator<<(QDebug debug, const QTouchDevice *d)
     return debug;
 }
 
+// Hierarchy of classes containing gesture parameters and drawing functionality.
+class Gesture {
+    Q_DISABLE_COPY(Gesture)
+public:
+    static Gesture *fromQGesture(const QWidget *w, const  QGesture *source);
+    virtual ~Gesture() {}
+
+    virtual void draw(const QRectF &rect, QPainter &painter) const = 0;
+
+protected:
+    explicit Gesture(const QWidget *w, const QGesture *source) : m_type(source->gestureType())
+        , m_hotSpot(w->mapFromGlobal(source->hotSpot().toPoint()))
+        , m_hasHotSpot(source->hasHotSpot()) {}
+
+    QPointF drawHotSpot(const QRectF &rect, QPainter &painter) const
+    {
+        const QPointF h = m_hasHotSpot ? m_hotSpot : rect.center();
+        painter.drawEllipse(h, 15, 15);
+        return h;
+    }
+
+private:
+    Qt::GestureType m_type;
+    QPointF m_hotSpot;
+    bool m_hasHotSpot;
+};
+
+class PanGesture : public Gesture {
+public:
+    explicit PanGesture(const QWidget *w, const QPanGesture *source) : Gesture(w, source)
+        , m_offset(source->offset()) {}
+
+    void draw(const QRectF &rect, QPainter &painter) const Q_DECL_OVERRIDE
+    {
+        const QPointF hotSpot = drawHotSpot(rect, painter);
+        painter.drawLine(hotSpot, hotSpot + m_offset);
+    }
+
+private:
+    QPointF m_offset;
+};
+
+class SwipeGesture : public Gesture {
+public:
+    explicit SwipeGesture(const QWidget *w, const QSwipeGesture *source) : Gesture(w, source)
+        , m_horizontal(source->horizontalDirection()), m_vertical(source->verticalDirection())
+        , m_angle(source->swipeAngle()) {}
+
+    void draw(const QRectF &rect, QPainter &painter) const Q_DECL_OVERRIDE;
+
+private:
+    QSwipeGesture::SwipeDirection m_horizontal;
+    QSwipeGesture::SwipeDirection m_vertical;
+    qreal m_angle;
+};
+
+static qreal swipeDirectionAngle(QSwipeGesture::SwipeDirection d)
+{
+    switch (d) {
+    case QSwipeGesture::NoDirection:
+    case QSwipeGesture::Right:
+        break;
+    case QSwipeGesture::Left:
+        return 180;
+    case QSwipeGesture::Up:
+        return 90;
+    case QSwipeGesture::Down:
+        return 270;
+    }
+    return 0;
+}
+
+void SwipeGesture::draw(const QRectF &rect, QPainter &painter) const
+{
+    enum { arrowLength = 50, arrowHeadSize = 10 };
+    const QPointF hotSpot = drawHotSpot(rect, painter);
+    drawArrow(hotSpot, arrowLength, swipeDirectionAngle(m_horizontal), Qt::red, arrowHeadSize, painter);
+    drawArrow(hotSpot, arrowLength, swipeDirectionAngle(m_vertical), Qt::green, arrowHeadSize, painter);
+    drawArrow(hotSpot, arrowLength, m_angle, Qt::blue, arrowHeadSize, painter);
+}
+
+Gesture *Gesture::fromQGesture(const QWidget *w, const QGesture *source)
+{
+    Gesture *result = Q_NULLPTR;
+    switch (source->gestureType()) {
+    case Qt::TapGesture:
+    case Qt::TapAndHoldGesture:
+    case Qt::PanGesture:
+        result = new PanGesture(w, static_cast<const QPanGesture *>(source));
+        break;
+    case Qt::PinchGesture:
+    case Qt::CustomGesture:
+    case Qt::LastGestureType:
+        break;
+    case Qt::SwipeGesture:
+        result = new SwipeGesture(w, static_cast<const QSwipeGesture *>(source));
+        break;
+    }
+    return result;
+}
+
+typedef QSharedPointer<Gesture> GesturePtr;
+typedef QVector<GesturePtr> GesturePtrs;
+
 typedef QVector<QEvent::Type> EventTypeVector;
 
 class EventFilter : public QObject {
@@ -86,33 +234,189 @@ bool EventFilter::eventFilter(QObject *o, QEvent *e)
     static int n = 0;
     if (m_types.contains(e->type())) {
         QString message;
-        QDebug(&message) << '#' << n++ << ' ' << o->objectName() << ' ' << e;
+        QDebug debug(&message);
+        debug << '#' << n++ << ' ' << o->objectName() << ' ';
+        switch (e->type()) {
+        case QEvent::Gesture:
+        case QEvent::GestureOverride:
+            debug << static_cast<const QGestureEvent *>(e); // Special operator
+            break;
+        default:
+            debug << e;
+            break;
+        }
         emit eventReceived(message);
     }
     return false;
 }
 
+enum PointType {
+    TouchPoint,
+    MousePress,
+    MouseRelease
+};
+
+struct Point
+{
+    Point(const QPointF &p = QPoint(), PointType t = TouchPoint,
+          Qt::MouseEventSource s = Qt::MouseEventNotSynthesized) : pos(p), type(t), source(s) {}
+
+    QColor color() const;
+
+    QPointF pos;
+    PointType type;
+    Qt::MouseEventSource source;
+};
+
+QColor Point::color() const
+{
+    Qt::GlobalColor globalColor = Qt::black;
+    if (type != TouchPoint) {
+        switch (source) {
+        case Qt::MouseEventSynthesizedBySystem:
+            globalColor = Qt::red;
+            break;
+        case Qt::MouseEventSynthesizedByQt:
+            globalColor = Qt::blue;
+            break;
+        case Qt::MouseEventNotSynthesized:
+            break;
+        }
+    }
+    const QColor result(globalColor);
+    return type == MousePress ? result.lighter() : result;
+}
+
 class TouchTestWidget : public QWidget {
+    Q_OBJECT
+    Q_PROPERTY(bool drawPoints READ drawPoints WRITE setDrawPoints)
 public:
-    explicit TouchTestWidget(QWidget *parent = 0) : QWidget(parent)
+    explicit TouchTestWidget(QWidget *parent = 0) : QWidget(parent), m_drawPoints(true)
     {
         setAttribute(Qt::WA_AcceptTouchEvents);
+        foreach (Qt::GestureType t, optGestures)
+            grabGesture(t);
     }
 
-    bool event(QEvent *event) Q_DECL_OVERRIDE
-    {
-        switch (event->type()) {
-        case QEvent::TouchBegin:
-        case QEvent::TouchUpdate:
-        case QEvent::TouchEnd:
+    bool drawPoints() const { return m_drawPoints; }
+
+public slots:
+    void clearPoints();
+    void setDrawPoints(bool drawPoints);
+
+signals:
+    void logMessage(const QString &);
+
+protected:
+    bool event(QEvent *event) Q_DECL_OVERRIDE;
+    void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
+
+private:
+    void handleGestureEvent(QGestureEvent *gestureEvent);
+
+    QVector<Point> m_points;
+    GesturePtrs m_gestures;
+    bool m_drawPoints;
+};
+
+void TouchTestWidget::clearPoints()
+{
+    if (!m_points.isEmpty() || !m_gestures.isEmpty()) {
+        m_points.clear();
+        m_gestures.clear();
+        update();
+    }
+}
+
+void TouchTestWidget::setDrawPoints(bool drawPoints)
+{
+    if (m_drawPoints != drawPoints) {
+        clearPoints();
+        m_drawPoints = drawPoints;
+    }
+}
+
+bool TouchTestWidget::event(QEvent *event)
+{
+    const QEvent::Type type = event->type();
+    switch (type) {
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+        if (m_drawPoints) {
+            const QMouseEvent *me = static_cast<const QMouseEvent *>(event);
+            m_points.append(Point(me->localPos(),
+                                  type == QEvent::MouseButtonPress ? MousePress : MouseRelease,
+                                  me->source()));
+            update();
+        }
+        break;
+    case QEvent::TouchBegin:
+    case QEvent::TouchUpdate:
+        if (m_drawPoints) {
+            foreach (const QTouchEvent::TouchPoint &p, static_cast<const QTouchEvent *>(event)->touchPoints())
+                m_points.append(Point(p.pos(), TouchPoint));
+            update();
+        }
+    case QEvent::TouchEnd:
+        if (optIgnoreTouch)
+            event->ignore();
+        else
             event->accept();
-            return true;
-        default:
-            break;
+        return true;
+    case QEvent::Gesture:
+        handleGestureEvent(static_cast<QGestureEvent *>(event));
+        break;
+    default:
+        break;
+    }
+    return QWidget::event(event);
+}
+
+void TouchTestWidget::handleGestureEvent(QGestureEvent *gestureEvent)
+{
+    foreach (QGesture *gesture, gestureEvent->gestures()) {
+        if (optGestures.contains(gesture->gestureType())) {
+            switch (gesture->state()) {
+            case Qt::NoGesture:
+                break;
+            case Qt::GestureStarted:
+            case Qt::GestureUpdated:
+                gestureEvent->accept(gesture);
+                break;
+            case Qt::GestureFinished:
+                gestureEvent->accept(gesture);
+                if (Gesture *g = Gesture::fromQGesture(this, gesture)) {
+                    m_gestures.append(GesturePtr(g));
+                    update();
+                }
+                break;
+            case Qt::GestureCanceled:
+                emit logMessage(QLatin1String("=== Qt::GestureCanceled ==="));
+                break;
+            }
         }
-        return QWidget::event(event);
     }
-};
+}
+
+void TouchTestWidget::paintEvent(QPaintEvent *)
+{
+    // Draw touch points as dots, mouse press as light filled circles, mouse release as circles.
+    QPainter painter(this);
+    const QRectF geom = QRectF(QPointF(0, 0), QSizeF(size()));
+    painter.fillRect(geom, Qt::white);
+    painter.drawRect(QRectF(geom.topLeft(), geom.bottomRight() - QPointF(1, 1)));
+    foreach (const Point &point, m_points) {
+        if (geom.contains(point.pos)) {
+            const qreal radius = point.type == TouchPoint ? 1 : 4;
+            if (point.type == MouseRelease) {
+                drawCircle(point.pos, radius, point.color(), painter);
+            } else
+                fillCircle(point.pos, radius, point.color(), painter);
+        }
+    }
+    foreach (const GesturePtr &gp, m_gestures)
+        gp->draw(geom, painter);
+}
 
 class MainWindow : public QMainWindow
 {
@@ -126,7 +430,7 @@ public slots:
     void dumpTouchDevices();
 
 private:
-    QWidget *m_touchWidget;
+    TouchTestWidget *m_touchWidget;
     QPlainTextEdit *m_logTextEdit;
 };
 
@@ -137,23 +441,38 @@ MainWindow::MainWindow()
     setWindowTitle(QStringLiteral("Touch Event Tester ") + QT_VERSION_STR);
 
     setObjectName("MainWin");
+    QToolBar *toolBar = new QToolBar(this);
+    addToolBar(Qt::TopToolBarArea, toolBar);
     QMenu *fileMenu = menuBar()->addMenu("File");
-    QAction *da = fileMenu->addAction(QStringLiteral("Dump devices"));
-    da->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D));
-    connect(da, SIGNAL(triggered()), this, SLOT(dumpTouchDevices()));
-    QAction *qa = fileMenu->addAction(QStringLiteral("Quit"));
-    qa->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
-    connect(qa, SIGNAL(triggered()), this, SLOT(close()));
+    QAction *dumpDeviceAction = fileMenu->addAction(QStringLiteral("Dump devices"));
+    dumpDeviceAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D));
+    connect(dumpDeviceAction, SIGNAL(triggered()), this, SLOT(dumpTouchDevices()));
+    toolBar->addAction(dumpDeviceAction);
+    QAction *clearLogAction = fileMenu->addAction(QStringLiteral("Clear Log"));
+    clearLogAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
+    connect(clearLogAction, SIGNAL(triggered()), m_logTextEdit, SLOT(clear()));
+    toolBar->addAction(clearLogAction);
+    QAction *toggleDrawPointAction = fileMenu->addAction(QStringLiteral("Draw Points"));
+    toggleDrawPointAction->setCheckable(true);
+    toggleDrawPointAction->setChecked(m_touchWidget->drawPoints());
+    connect(toggleDrawPointAction, SIGNAL(toggled(bool)), m_touchWidget, SLOT(setDrawPoints(bool)));
+    toolBar->addAction(toggleDrawPointAction);
+    QAction *clearPointAction = fileMenu->addAction(QStringLiteral("Clear Points"));
+    clearPointAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P));
+    connect(clearPointAction, SIGNAL(triggered()), m_touchWidget, SLOT(clearPoints()));
+    toolBar->addAction(clearPointAction);
+    QAction *quitAction = fileMenu->addAction(QStringLiteral("Quit"));
+    quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
+    connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
+    toolBar->addAction(quitAction);
 
-    QSplitter *mainSplitter = new QSplitter(Qt::Vertical);
+    QSplitter *mainSplitter = new QSplitter(Qt::Vertical, this);
 
     m_touchWidget->setObjectName(QStringLiteral("TouchWidget"));
-    const QSize screenSize = QGuiApplication::primaryScreen()->availableGeometry().size();
-    m_touchWidget->setMinimumSize(screenSize / 2);
     mainSplitter->addWidget(m_touchWidget);
+    connect(m_touchWidget, &TouchTestWidget::logMessage, this, &MainWindow::appendToLog);
 
     m_logTextEdit->setObjectName(QStringLiteral("LogTextEdit"));
-    m_logTextEdit->setMinimumHeight(screenSize.height() / 4);
     mainSplitter->addWidget(m_logTextEdit);
     setCentralWidget(mainSplitter);
 
@@ -183,19 +502,57 @@ int main(int argc, char *argv[])
     const QCommandLineOption globalFilterOption(QStringLiteral("global"),
                                              QStringLiteral("Global event filter"));
     parser.addOption(globalFilterOption);
+
+    const QCommandLineOption ignoreTouchOption(QStringLiteral("ignore"),
+                                               QStringLiteral("Ignore touch events (for testing mouse emulation)."));
+    parser.addOption(ignoreTouchOption);
+    const QCommandLineOption noTouchLogOption(QStringLiteral("notouchlog"),
+                                              QStringLiteral("Do not log touch events (for testing gestures)."));
+    parser.addOption(noTouchLogOption);
+    const QCommandLineOption noMouseLogOption(QStringLiteral("nomouselog"),
+                                              QStringLiteral("Do not log mouse events (for testing gestures)."));
+    parser.addOption(noMouseLogOption);
+
+    const QCommandLineOption tapGestureOption(QStringLiteral("tap"), QStringLiteral("Grab tap gesture."));
+    parser.addOption(tapGestureOption);
+    const QCommandLineOption tapAndHoldGestureOption(QStringLiteral("tap-and-hold"),
+                                                     QStringLiteral("Grab tap-and-hold gesture."));
+    parser.addOption(tapAndHoldGestureOption);
+    const QCommandLineOption panGestureOption(QStringLiteral("pan"), QStringLiteral("Grab pan gesture."));
+    parser.addOption(panGestureOption);
+    const QCommandLineOption pinchGestureOption(QStringLiteral("pinch"), QStringLiteral("Grab pinch gesture."));
+    parser.addOption(pinchGestureOption);
+    const QCommandLineOption swipeGestureOption(QStringLiteral("swipe"), QStringLiteral("Grab swipe gesture."));
+    parser.addOption(swipeGestureOption);
     parser.process(QApplication::arguments());
+    optIgnoreTouch = parser.isSet(ignoreTouchOption);
+    if (parser.isSet(tapGestureOption))
+        optGestures.append(Qt::TapGesture);
+    if (parser.isSet(tapAndHoldGestureOption))
+        optGestures.append(Qt::TapAndHoldGesture);
+    if (parser.isSet(panGestureOption))
+        optGestures.append(Qt::PanGesture);
+    if (parser.isSet(pinchGestureOption))
+        optGestures.append(Qt::PinchGesture);
+    if (parser.isSet(swipeGestureOption))
+        optGestures.append(Qt::SwipeGesture);
 
     MainWindow w;
+    const QSize screenSize = QGuiApplication::primaryScreen()->availableGeometry().size();
+    w.resize(screenSize / 2);
+    const QSize sizeDiff = screenSize - w.size();
+    w.move(sizeDiff.width() / 2, sizeDiff.height() / 2);
     w.show();
-    const QSize pos = QGuiApplication::primaryScreen()->availableGeometry().size() - w.size();
-    w.move(pos.width() / 2, pos.height() / 2);
 
     EventTypeVector eventTypes;
-    eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease
-        << QEvent::MouseButtonDblClick
-        << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd;
+    if (!parser.isSet(noMouseLogOption))
+        eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick;
     if (parser.isSet(mouseMoveOption))
         eventTypes << QEvent::MouseMove;
+    if (!parser.isSet(noTouchLogOption))
+        eventTypes << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd;
+    if (!optGestures.isEmpty())
+        eventTypes << QEvent::Gesture << QEvent::GestureOverride;
     QObject *filterTarget = parser.isSet(globalFilterOption)
             ? static_cast<QObject *>(&a)
             : static_cast<QObject *>(w.touchWidget());
diff --git a/tools/configure/Makefile.mingw b/tools/configure/Makefile.mingw
index 40c2112132c160ef58ad1d52dc62a4a47d1d304f..539664e7d6e86d2dd9b730de45206ab3dbb98ad1 100644
--- a/tools/configure/Makefile.mingw
+++ b/tools/configure/Makefile.mingw
@@ -4,7 +4,7 @@ CONFSRC = $(TOOLSRC)/configure
 
 RAW_PCH       = configure_pch.h
 PCH           = $(RAW_PCH).gch/c++
-DEFINES       = -DUNICODE -DQT_NO_DATASTREAM -DQT_NO_CODECS -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NO_COMPRESS -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -D_CRT_SECURE_NO_DEPRECATE -DQT_BOOTSTRAPPED -DQT_BUILD_CONFIGURE -DCOMMERCIAL_VERSION
+DEFINES       = -DUNICODE -DQT_NO_DATASTREAM -DQT_NO_CODECS -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NO_COMPRESS -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -D_CRT_SECURE_NO_DEPRECATE -DQT_BOOTSTRAPPED -DQT_BUILD_CONFIGURE
 INCPATH       = -I"../../include" -I"../../include/QtCore" -I"../../include/QtCore/$(QTVERSION)" -I"../../include/QtCore/$(QTVERSION)/QtCore" -I"$(TOOLSRC)/shared" -I"$(QTSRC)mkspecs/win32-g++"
 CXXFLAGS_BARE = -fno-rtti -fno-exceptions -mthreads -Wall -Wextra $(DEFINES) $(INCPATH)
 CXXFLAGS      = -include $(RAW_PCH) $(CXXFLAGS_BARE)
@@ -48,6 +48,7 @@ OBJECTS = \
     qfsfileengine_win.o \
     qfsfileengine_iterator.o \
     qiodevice.o \
+    qringbuffer.o \
     qdebug.o \
     qtextstream.o \
     qlogging.o \
diff --git a/tools/configure/Makefile.win32 b/tools/configure/Makefile.win32
index b74b0bc82d27521cc41a7644ce03397e2f3c76c5..da5b430bb1d6fdc1feedc8545b187f5946ccc5b2 100644
--- a/tools/configure/Makefile.win32
+++ b/tools/configure/Makefile.win32
@@ -3,7 +3,7 @@ TOOLSRC = $(QTSRC)tools
 CONFSRC = $(TOOLSRC)\configure
 
 PCH           = configure_pch.pch
-DEFINES       = -DUNICODE -DQT_NO_CODECS -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NO_COMPRESS -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -D_CRT_SECURE_NO_DEPRECATE -DQT_BOOTSTRAPPED -DQT_BUILD_CONFIGURE -DCOMMERCIAL_VERSION
+DEFINES       = -DUNICODE -DQT_NO_CODECS -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NO_COMPRESS -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -D_CRT_SECURE_NO_DEPRECATE -DQT_BOOTSTRAPPED -DQT_BUILD_CONFIGURE
 INCPATH       = -I"..\..\include" -I"..\..\include\QtCore" -I"..\..\include\QtCore\$(QTVERSION)" -I"..\..\include\QtCore\$(QTVERSION)\QtCore" -I"$(TOOLSRC)\shared" -I"$(QTSRC)mkspecs\win32-msvc2008"
 CXXFLAGS_BARE = -nologo -Zc:wchar_t -W3 -GR -EHsc -w34100 -w34189 $(CFLAGS_CRT) $(EXTRA_CXXFLAGS) $(DEFINES) $(INCPATH)
 CXXFLAGS      = -FIconfigure_pch.h -Yuconfigure_pch.h -Fp$(PCH) -MP $(CXXFLAGS_BARE)
@@ -47,6 +47,7 @@ OBJECTS = \
     qfsfileengine_win.obj \
     qfsfileengine_iterator.obj \
     qiodevice.obj \
+    qringbuffer.obj \
     qdebug.obj \
     qtextstream.obj \
     qlogging.obj \
@@ -122,6 +123,7 @@ qfsfileengine.obj: $(CORESRC)\io\qfsfileengine.cpp $(PCH)
 qfsfileengine_win.obj: $(CORESRC)\io\qfsfileengine_win.cpp $(PCH)
 qfsfileengine_iterator.obj: $(CORESRC)\io\qfsfileengine_iterator.cpp $(PCH)
 qiodevice.obj: $(CORESRC)\io\qiodevice.cpp $(PCH)
+qringbuffer.obj: $(CORESRC)\tools\qringbuffer.cpp $(PCH)
 qdebug.obj: $(CORESRC)\io\qdebug.cpp $(PCH)
 qtextstream.obj: $(CORESRC)\io\qtextstream.cpp $(PCH)
 qtemporaryfile.obj: $(CORESRC)\io\qtemporaryfile.cpp $(PCH)
diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro
index d3237d472b3fec705e969a0a6af688529f0f4589..939c9ea5ab6531c1b60f9ee180e48faebb22a4e8 100644
--- a/tools/configure/configure.pro
+++ b/tools/configure/configure.pro
@@ -68,6 +68,7 @@ HEADERS  = configureapp.h environment.h tools.h\
            $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \
            $$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
            $$QT_SOURCE_TREE/src/corelib/tools/qregexp.h \
+           $$QT_SOURCE_TREE/src/corelib/tools/qringbuffer_p.h \
            $$QT_SOURCE_TREE/src/corelib/tools/qstring.h \
            $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \
            $$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.h \
@@ -119,6 +120,7 @@ SOURCES  = main.cpp configureapp.cpp environment.cpp tools.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
+           $$QT_SOURCE_TREE/src/corelib/tools/qringbuffer.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qstring_compat.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
@@ -132,5 +134,3 @@ SOURCES  = main.cpp configureapp.cpp environment.cpp tools.cpp \
            $$QT_SOURCE_TREE/src/corelib/plugin/quuid.cpp \
            $$QT_SOURCE_TREE/src/corelib/tools/qcryptographichash.cpp \
            $$QT_SOURCE_TREE/tools/shared/windows/registry.cpp
-
-DEFINES += COMMERCIAL_VERSION
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index c0e98507c7ad501224e71a1690f2b274188bd229..3bf0546ac1628e8ab51979526bb102d1e8db8de8 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -34,9 +34,7 @@
 
 #include "configureapp.h"
 #include "environment.h"
-#ifdef COMMERCIAL_VERSION
-#  include "tools.h"
-#endif
+#include "tools.h"
 
 #include <qdir.h>
 #include <qdiriterator.h>
@@ -244,6 +242,8 @@ Configure::Configure(int& argc, char** argv)
 
     dictionary[ "USE_GOLD_LINKER" ] = "no";
 
+    dictionary[ "ENABLE_NEW_DTAGS" ] = "no";
+
     dictionary[ "SHARED" ]          = "yes";
 
     dictionary[ "STATIC_RUNTIME" ]  = "no";
@@ -471,6 +471,10 @@ void Configure::parseCmdLine()
             dictionary[ "USE_GOLD_LINKER" ] = "yes";
         else if (configCmdLine.at(i) == "-no-use-gold-linker")
             dictionary[ "USE_GOLD_LINKER" ] = "no";
+        else if (configCmdLine.at(i) == "-enable-new-dtags")
+            dictionary[ "ENABLE_NEW_DTAGS" ] = "yes";
+        else if (configCmdLine.at(i) == "-disable-new-dtags")
+            dictionary[ "ENABLE_NEW_DTAGS" ] = "no";
         else if (configCmdLine.at(i) == "-shared")
             dictionary[ "SHARED" ] = "yes";
         else if (configCmdLine.at(i) == "-static")
@@ -1793,6 +1797,9 @@ bool Configure::displayHelp()
         desc("USE_GOLD_LINKER", "yes", "-use-gold-linker",                  "Link using the GNU gold linker (gcc only).");
         desc("USE_GOLD_LINKER", "no", "-no-use-gold-linker",                "Do not link using the GNU gold linker.\n");
 
+        desc("ENABLE_NEW_DTAGS", "yes", "-enable-new-dtags", "Use new DTAGS for RPATH (Linux only).");
+        desc("ENABLE_NEW_DTAGS", "no", "-disable-new-dtags", "Do not use new DTAGS for RPATH.\n");
+
         desc("SHARED", "yes",   "-shared",              "Create and use shared Qt libraries.");
         desc("SHARED", "no",    "-static",              "Create and use static Qt libraries.\n");
 
@@ -2675,6 +2682,9 @@ void Configure::generateOutputVars()
     if (dictionary[ "USE_GOLD_LINKER" ] == "yes")
         qmakeConfig += "use_gold_linker";
 
+    if (dictionary[ "ENABLE_NEW_DTAGS" ] == "yes")
+        qmakeConfig += "enable_new_dtags";
+
     if (dictionary[ "SHARED" ] == "no")
         qtConfig += "static";
     else
@@ -3030,16 +3040,6 @@ void Configure::generateOutputVars()
     if (!qmakeStylePlugins.isEmpty())
         qmakeVars += QString("style-plugins  += ") + qmakeStylePlugins.join(' ');
 
-    if (dictionary["QMAKESPEC"].endsWith("-g++")) {
-        QString includepath = qgetenv("INCLUDE");
-        const bool hasSh = !QStandardPaths::findExecutable(QStringLiteral("sh.exe")).isEmpty();
-        QChar separator = (!includepath.contains(":\\") && hasSh ? QChar(':') : QChar(';'));
-        qmakeVars += QString("TMPPATH            = $$quote($$(INCLUDE))");
-        qmakeVars += QString("QMAKE_INCDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
-        qmakeVars += QString("TMPPATH            = $$quote($$(LIB))");
-        qmakeVars += QString("QMAKE_LIBDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
-    }
-
     if (!dictionary[ "QMAKESPEC" ].length()) {
         cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl
              << "be defined as an environment variable, or specified as an" << endl
@@ -3458,6 +3458,14 @@ void Configure::generateQConfigPri()
                      << "QT_MINOR_VERSION = " << dictionary["VERSION_MINOR"] << endl
                      << "QT_PATCH_VERSION = " << dictionary["VERSION_PATCH"] << endl;
 
+        configStream << endl
+                     << "QT_EDITION = " << dictionary["EDITION"] << endl;
+
+        if (dictionary["EDITION"] != "OpenSource" && dictionary["EDITION"] != "Preview") {
+            configStream << "QT_LICHECK = " << dictionary["LICHECK"] << endl;
+            configStream << "QT_RELEASE_DATE = " << dictionary["RELEASEDATE"] << endl;
+        }
+
         if (!dictionary["CFG_SYSROOT"].isEmpty() && dictionary["CFG_GCC_SYSROOT"] == "yes") {
             configStream << endl
                          << "# sysroot" << endl
@@ -4379,8 +4387,10 @@ bool Configure::showLicense(QString orgLicenseFile)
     bool showLgpl2 = true;
     QString licenseFile = orgLicenseFile;
     QString theLicense;
-    if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
-        if (platform() != ANDROID || dictionary["ANDROID_STYLE_ASSETS"] == "no") {
+    if (dictionary["EDITION"] == "OpenSource") {
+        if (platform() != WINDOWS_RT
+                && platform() != WINDOWS_CE
+                && (platform() != ANDROID || dictionary["ANDROID_STYLE_ASSETS"] == "no")) {
             theLicense = "GNU Lesser General Public License (LGPL) version 2.1"
                          "\nor the GNU Lesser General Public License (LGPL) version 3";
         } else {
@@ -4402,7 +4412,7 @@ bool Configure::showLicense(QString orgLicenseFile)
         cout << "You are licensed to use this software under the terms of" << endl
              << "the " << theLicense << "." << endl
              << endl;
-        if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
+        if (dictionary["EDITION"] == "OpenSource") {
             cout << "Type '3' to view the Lesser GNU General Public License version 3 (LGPLv3)." << endl;
             if (showLgpl2)
                 cout << "Type 'L' to view the Lesser GNU General Public License version 2.1 (LGPLv2.1)." << endl;
@@ -4421,7 +4431,7 @@ bool Configure::showLicense(QString orgLicenseFile)
         } else if (accept == 'n') {
             return false;
         } else {
-            if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
+            if (dictionary["EDITION"] == "OpenSource") {
                 if (accept == '3')
                     licenseFile = orgLicenseFile + "/LICENSE.LGPLv3";
                 else
@@ -4497,19 +4507,9 @@ void Configure::readLicense()
         cout << endl << "Cannot find the GPL license files! Please download the Open Source version of the library." << endl;
         dictionary["DONE"] = "error";
     }
-#ifdef COMMERCIAL_VERSION
     else {
         Tools::checkLicense(dictionary, sourcePath, buildPath);
     }
-#else // !COMMERCIAL_VERSION
-    else {
-        cout << endl << "Error: This is the Open Source version of Qt."
-             << endl << "If you want to use Enterprise features of Qt,"
-             << endl << "information use the contact form at http://www.qt.io/contact-us"
-             << endl << "to purchase a license." << endl << endl;
-        dictionary["DONE"] = "error";
-    }
-#endif
 }
 
 void Configure::reloadCmdLine()
diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp
index 63c1e8a1f0b34f79c730905e97d2b20f871a97b5..11064a757dda8adb4ae8e88bf24427df29a5fc00 100644
--- a/tools/configure/environment.cpp
+++ b/tools/configure/environment.cpp
@@ -611,9 +611,9 @@ QStringList Environment::headerPaths(Compiler compiler)
             foreach (const QFileInfo &version, mingwLibDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot))
                 headerPaths += version.absoluteFilePath() + QLatin1String("/include");
         }
+    } else {
+        headerPaths = splitPathList(QString::fromLocal8Bit(getenv("INCLUDE")));
     }
-    // MinGW: Although gcc doesn't care about INCLUDE, qmake automatically adds it via -I
-    headerPaths += splitPathList(QString::fromLocal8Bit(getenv("INCLUDE")));
 
     // Add Direct X SDK for ANGLE
     const QString directXSdk = detectDirectXSdk();
@@ -627,9 +627,9 @@ QStringList Environment::libraryPaths(Compiler compiler)
     QStringList libraryPaths;
     if (compiler == CC_MINGW) {
         libraryPaths = mingwPaths(detectMinGW(), "lib");
+    } else {
+        libraryPaths = splitPathList(QString::fromLocal8Bit(qgetenv("LIB")));
     }
-    // MinGW: Although gcc doesn't care about LIB, qmake automatically adds it via -L
-    libraryPaths += splitPathList(QString::fromLocal8Bit(qgetenv("LIB")));
 
     // Add Direct X SDK for ANGLE
     const QString directXSdk = detectDirectXSdk();
diff --git a/tools/configure/tools.cpp b/tools/configure/tools.cpp
index 83d969ce16f9a96288f3350ac6aaa303de4b30e9..095e798332f9492fb6157c82fe0a8bf08acfdf7a 100644
--- a/tools/configure/tools.cpp
+++ b/tools/configure/tools.cpp
@@ -54,6 +54,8 @@ void Tools::checkLicense(QMap<QString,QString> &dictionary,
         return;
     }
 
+    dictionary["LICHECK"] = "licheck.exe";
+
     const QString licenseChecker =
         QDir::toNativeSeparators(sourcePath + "/bin/licheck.exe");