Submitted By:            Pierre Labastie <pierre_dot_labastie_at_neuf_dot_fr>
Date:                    2023-01-05
Initial Package Version: 5.15.8
Upstream Status:         Applied (according to KDE)
Origin:                  KDE patch set
Description:             Patch set maintained by the KDE folks
see https://dot.kde.org/2021/04/06/announcing-kdes-qt-5-patch-collection
Patch generated using the procedure in
https://wiki.linuxfromscratch.org/blfs/ticket/17476#comment:3

Submodule qtbase 4ee4fc18..9cf586d6:
diff --git a/qtbase/mkspecs/common/android/qplatformdefs.h b/qtbase/mkspecs/common/android/qplatformdefs.h
index f75bc4093b..2bd59410d4 100644
--- a/qtbase/mkspecs/common/android/qplatformdefs.h
+++ b/qtbase/mkspecs/common/android/qplatformdefs.h
@@ -144,11 +144,7 @@
 #define QT_SIGNAL_ARGS          int
 #define QT_SIGNAL_IGNORE        SIG_IGN
 
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
 #define QT_SOCKLEN_T            socklen_t
-#else
-#define QT_SOCKLEN_T            int
-#endif
 
 #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
 #define QT_SNPRINTF             ::snprintf
diff --git a/qtbase/mkspecs/features/mac/sdk.mk b/qtbase/mkspecs/features/mac/sdk.mk
index f30b5830b4..a32ceacb6c 100644
--- a/qtbase/mkspecs/features/mac/sdk.mk
+++ b/qtbase/mkspecs/features/mac/sdk.mk
@@ -1,6 +1,6 @@
 
 ifeq ($(QT_MAC_SDK_NO_VERSION_CHECK),)
-    CHECK_SDK_COMMAND = /usr/bin/xcrun --sdk $(EXPORT_QMAKE_MAC_SDK) -show-sdk-version 2>&1
+    CHECK_SDK_COMMAND = /usr/bin/xcrun --sdk $(EXPORT_QMAKE_MAC_SDK) -show-sdk-version 2>/dev/null
     CURRENT_MAC_SDK_VERSION := $(shell DEVELOPER_DIR=$(EXPORT_QMAKE_XCODE_DEVELOPER_PATH) $(CHECK_SDK_COMMAND))
     ifneq ($(CURRENT_MAC_SDK_VERSION),$(EXPORT_QMAKE_MAC_SDK_VERSION))
         # We don't want to complain about out of date SDK unless the target needs to be remade.
diff --git a/qtbase/mkspecs/linux-clang/qplatformdefs.h b/qtbase/mkspecs/linux-clang/qplatformdefs.h
index a818d973f0..c1ab72fbc6 100644
--- a/qtbase/mkspecs/linux-clang/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-clang/qplatformdefs.h
@@ -79,14 +79,6 @@
 #define QT_USE_XOPEN_LFS_EXTENSIONS
 #include "../common/posix/qplatformdefs.h"
 
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T            socklen_t
-#else
-#define QT_SOCKLEN_T            int
-#endif
-
 #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
 #define QT_SNPRINTF             ::snprintf
 #define QT_VSNPRINTF            ::vsnprintf
diff --git a/qtbase/mkspecs/linux-g++/qplatformdefs.h b/qtbase/mkspecs/linux-g++/qplatformdefs.h
index 13523f0702..4d2750d9ec 100644
--- a/qtbase/mkspecs/linux-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-g++/qplatformdefs.h
@@ -79,14 +79,6 @@
 #define QT_USE_XOPEN_LFS_EXTENSIONS
 #include "../common/posix/qplatformdefs.h"
 
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ < 2)
-#define QT_SOCKLEN_T            int
-#else
-#define QT_SOCKLEN_T            socklen_t
-#endif
-
 #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
 #define QT_SNPRINTF             ::snprintf
 #define QT_VSNPRINTF            ::vsnprintf
diff --git a/qtbase/mkspecs/linux-llvm/qplatformdefs.h b/qtbase/mkspecs/linux-llvm/qplatformdefs.h
index dc750ab1ef..d3cc39b47f 100644
--- a/qtbase/mkspecs/linux-llvm/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-llvm/qplatformdefs.h
@@ -80,14 +80,6 @@
 #define QT_USE_XOPEN_LFS_EXTENSIONS
 #include "../common/posix/qplatformdefs.h"
 
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T            socklen_t
-#else
-#define QT_SOCKLEN_T            int
-#endif
-
 #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
 #define QT_SNPRINTF             ::snprintf
 #define QT_VSNPRINTF            ::vsnprintf
diff --git a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
index 4c4e53da2a..83baffb3e3 100644
--- a/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/linux-lsb-g++/qplatformdefs.h
@@ -85,16 +85,9 @@
 #include "../common/posix/qplatformdefs.h"
 
 #undef QT_OPEN_LARGEFILE
-#undef QT_SOCKLEN_T
 
 #define QT_OPEN_LARGEFILE       0
 
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T            socklen_t
-#else
-#define QT_SOCKLEN_T            int
-#endif
-
 #ifndef SIOCGIFBRDADDR
 #  define SIOCGIFBRDADDR 0x8919
 #endif
diff --git a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
index 4339ea2b23..6007af0055 100644
--- a/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
+++ b/qtbase/mkspecs/lynxos-g++/qplatformdefs.h
@@ -72,14 +72,6 @@
 
 #include "../common/posix/qplatformdefs.h"
 
-#undef QT_SOCKLEN_T
-
-#if defined(__GLIBC__) && (__GLIBC__ >= 2)
-#define QT_SOCKLEN_T            socklen_t
-#else
-#define QT_SOCKLEN_T            int
-#endif
-
 #if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
 #define QT_SNPRINTF             ::snprintf
 #define QT_VSNPRINTF            ::vsnprintf
diff --git a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
index c3c184258f..32af3f8f29 100644
--- a/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
+++ b/qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
@@ -10,6 +10,7 @@
 #include "libANGLE/HandleAllocator.h"
 
 #include <algorithm>
+#include <limits>
 
 #include "common/debug.h"
 
diff --git a/qtbase/src/3rdparty/forkfd/forkfd_linux.c b/qtbase/src/3rdparty/forkfd/forkfd_linux.c
index ffe0e9a5e2..b1f5408d11 100644
--- a/qtbase/src/3rdparty/forkfd/forkfd_linux.c
+++ b/qtbase/src/3rdparty/forkfd/forkfd_linux.c
@@ -82,7 +82,8 @@ static int sys_clone(unsigned long cloneflags, int *ptid)
     return syscall(__NR_clone, cloneflags, child_stack, stack_size, ptid, newtls, ctid);
 #elif defined(__arc__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     defined(__nds32__) || defined(__hppa__) || defined(__powerpc__) || defined(__i386__) || \
-    defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv)
+    defined(__x86_64__) || defined(__xtensa__) || defined(__alpha__) || defined(__riscv) || \
+    defined(__loongarch__)
     /* ctid and newtls are inverted on CONFIG_CLONE_BACKWARDS architectures,
      * but since both values are 0, there's no harm. */
     return syscall(__NR_clone, cloneflags, child_stack, ptid, ctid, newtls);
diff --git a/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 5792b5b2f5..2f74750fcf 100644
--- a/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/qtbase/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -116,6 +116,7 @@ public class QtNative
     public static QtThread m_qtThread = new QtThread();
     private static HashMap<String, Uri> m_cachedUris = new HashMap<String, Uri>();
     private static ArrayList<String> m_knownDirs = new ArrayList<String>();
+    private static final String NoPermissionErrorMessage = "No permissions to open Uri";
 
     private static final Runnable runPendingCppRunnablesRunnable = new Runnable() {
         @Override
@@ -193,11 +194,10 @@ public class QtNative
                     return iterUri;
             }
 
-            // Android 6 and earlier could still manage to open the file so we can return the
-            // parsed uri here
-            if (Build.VERSION.SDK_INT < 24)
-                return parsedUri;
-            return null;
+            // if we only have transient permissions on uri all the above will fail,
+            // but we will be able to read the file anyway, so continue with uri here anyway
+            // and check for SecurityExceptions later
+            return parsedUri;
         } catch (SecurityException e) {
             e.printStackTrace();
             return null;
@@ -244,7 +244,7 @@ public class QtNative
         int error = -1;
 
         if (uri == null) {
-            Log.e(QtTAG, "openFdForContentUrl(): No permissions to open Uri");
+            Log.e(QtTAG, "openFdForContentUrl(): " + NoPermissionErrorMessage);
             return error;
         }
 
@@ -254,12 +254,13 @@ public class QtNative
             return fdDesc.detachFd();
         } catch (FileNotFoundException e) {
             e.printStackTrace();
-            return error;
         } catch (IllegalArgumentException e) {
             Log.e(QtTAG, "openFdForContentUrl(): Invalid Uri");
             e.printStackTrace();
-            return error;
+        } catch (SecurityException e) {
+            Log.e(QtTAG, NoPermissionErrorMessage);
         }
+        return error;
     }
 
     public static long getSize(Context context, String contentUrl)
@@ -270,7 +271,7 @@ public class QtNative
             uri = getUriWithValidPermission(context, contentUrl, "r");
 
         if (uri == null) {
-            Log.e(QtTAG, "getSize(): No permissions to open Uri");
+            Log.e(QtTAG, NoPermissionErrorMessage);
             return size;
         } else if (!m_cachedUris.containsKey(contentUrl)) {
             m_cachedUris.put(contentUrl, uri);
@@ -288,12 +289,13 @@ public class QtNative
         } catch (IllegalArgumentException e) {
             Log.e(QtTAG, "getSize(): Invalid Uri");
             e.printStackTrace();
-            return size;
         }  catch (UnsupportedOperationException e) {
             Log.e(QtTAG, "getSize(): Unsupported operation for given Uri");
             e.printStackTrace();
-            return size;
+        } catch (SecurityException e) {
+            Log.e(QtTAG, NoPermissionErrorMessage);
         }
+        return size;
     }
 
     public static boolean checkFileExists(Context context, String contentUrl)
@@ -303,7 +305,7 @@ public class QtNative
         if (uri == null)
             uri = getUriWithValidPermission(context, contentUrl, "r");
         if (uri == null) {
-            Log.e(QtTAG, "checkFileExists(): No permissions to open Uri");
+            Log.e(QtTAG, NoPermissionErrorMessage);
             return exists;
         } else {
             if (!m_cachedUris.containsKey(contentUrl))
@@ -321,12 +323,13 @@ public class QtNative
         } catch (IllegalArgumentException e) {
             Log.e(QtTAG, "checkFileExists(): Invalid Uri");
             e.printStackTrace();
-            return exists;
         } catch (UnsupportedOperationException e) {
             Log.e(QtTAG, "checkFileExists(): Unsupported operation for given Uri");
             e.printStackTrace();
-            return false;
+        } catch (SecurityException e) {
+            Log.e(QtTAG, NoPermissionErrorMessage);
         }
+        return exists;
     }
 
     public static boolean checkIfWritable(Context context, String contentUrl)
@@ -344,7 +347,7 @@ public class QtNative
             uri = getUriWithValidPermission(context, contentUrl, "r");
         }
         if (uri == null) {
-            Log.e(QtTAG, "isDir(): No permissions to open Uri");
+            Log.e(QtTAG, NoPermissionErrorMessage);
             return isDir;
         } else {
             if (!m_cachedUris.containsKey(contentUrl))
@@ -374,12 +377,13 @@ public class QtNative
         } catch (IllegalArgumentException e) {
             Log.e(QtTAG, "checkIfDir(): Invalid Uri");
             e.printStackTrace();
-            return false;
         } catch (UnsupportedOperationException e) {
             Log.e(QtTAG, "checkIfDir(): Unsupported operation for given Uri");
             e.printStackTrace();
-            return false;
+        } catch (SecurityException e) {
+            Log.e(QtTAG, NoPermissionErrorMessage);
         }
+        return false;
     }
     public static String[] listContentsFromTreeUri(Context context, String contentUrl)
     {
diff --git a/qtbase/src/concurrent/qtconcurrentreducekernel.h b/qtbase/src/concurrent/qtconcurrentreducekernel.h
index 8f9a938952..a98dedef2e 100644
--- a/qtbase/src/concurrent/qtconcurrentreducekernel.h
+++ b/qtbase/src/concurrent/qtconcurrentreducekernel.h
@@ -212,11 +212,13 @@ public:
 
     inline bool shouldThrottle()
     {
+        std::lock_guard<QMutex> locker(mutex);
         return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount));
     }
 
     inline bool shouldStartThread()
     {
+        std::lock_guard<QMutex> locker(mutex);
         return (resultsMapSize <= (ReduceQueueStartLimit * threadCount));
     }
 };
diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
index ea6ce3ac42..7f91a2ba68 100644
--- a/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
+++ b/qtbase/src/concurrent/qtconcurrentthreadengine.cpp
@@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThreaded()
     finish();
 }
 
+void ThreadEngineBase::startBlocking()
+{
+    start();
+    barrier.acquire();
+    startThreads();
+
+    bool throttled = false;
+#ifndef QT_NO_EXCEPTIONS
+    try {
+#endif
+        while (threadFunction() == ThrottleThread) {
+            if (threadThrottleExit()) {
+                throttled = true;
+                break;
+            }
+        }
+#ifndef QT_NO_EXCEPTIONS
+    } catch (QException &e) {
+        handleException(e);
+    } catch (...) {
+        handleException(QUnhandledException());
+    }
+#endif
+
+    if (throttled == false) {
+        barrier.release();
+    }
+
+    barrier.wait();
+    finish();
+    exceptionStore.throwPossibleException();
+}
+
 void ThreadEngineBase::startThread()
 {
     startThreadInternal();
diff --git a/qtbase/src/concurrent/qtconcurrentthreadengine.h b/qtbase/src/concurrent/qtconcurrentthreadengine.h
index 7c30cebdbc..a4c8548cc4 100644
--- a/qtbase/src/concurrent/qtconcurrentthreadengine.h
+++ b/qtbase/src/concurrent/qtconcurrentthreadengine.h
@@ -91,6 +91,7 @@ public:
     ThreadEngineBase();
     virtual ~ThreadEngineBase();
     void startSingleThreaded();
+    void startBlocking();
     void startThread();
     bool isCanceled();
     void waitForResume();
@@ -143,6 +144,15 @@ public:
         return result();
     }
 
+    // Runs the user algorithm using multiple threads.
+    // This function blocks until the algorithm is finished,
+    // and then returns the result.
+    T *startBlocking()
+    {
+        ThreadEngineBase::startBlocking();
+        return result();
+    }
+
     // Runs the user algorithm using multiple threads.
     // Does not block, returns a future.
     QFuture<T> startAsynchronously()
@@ -223,6 +233,13 @@ class ThreadEngineStarter : public ThreadEngineStarterBase<T>
 public:
     ThreadEngineStarter(TypedThreadEngine *eng)
         : Base(eng) { }
+
+    T startBlocking()
+    {
+        T t = *this->threadEngine->startBlocking();
+        delete this->threadEngine;
+        return t;
+    }
 };
 
 // Full template specialization where T is void.
@@ -232,6 +249,12 @@ class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
 public:
     ThreadEngineStarter(ThreadEngine<void> *_threadEngine)
         : ThreadEngineStarterBase<void>(_threadEngine) {}
+
+    void startBlocking()
+    {
+        this->threadEngine->startBlocking();
+        delete this->threadEngine;
+    }
 };
 
 //! [qtconcurrentthreadengine-1]
diff --git a/qtbase/src/corelib/animation/qvariantanimation.cpp b/qtbase/src/corelib/animation/qvariantanimation.cpp
index 98b02f0202..eac1524107 100644
--- a/qtbase/src/corelib/animation/qvariantanimation.cpp
+++ b/qtbase/src/corelib/animation/qvariantanimation.cpp
@@ -276,7 +276,9 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
 
     const qreal startProgress = currentInterval.start.first;
     const qreal endProgress = currentInterval.end.first;
-    const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
+    const qreal localProgress =
+            qIsNull(progress - startProgress) ? 0.0 // avoid 0/0 below
+            /* else */                        : (progress - startProgress) / (endProgress - startProgress);
 
     QVariant ret = q->interpolated(currentInterval.start.second,
                                    currentInterval.end.second,
diff --git a/qtbase/src/corelib/global/qnamespace.h b/qtbase/src/corelib/global/qnamespace.h
index ad4150b317..bf19b1627b 100644
--- a/qtbase/src/corelib/global/qnamespace.h
+++ b/qtbase/src/corelib/global/qnamespace.h
@@ -1864,7 +1864,7 @@ public:
     QT_Q_ENUM(TimerType)
     QT_Q_ENUM(ScrollPhase)
     QT_Q_ENUM(MouseEventSource)
-    QT_Q_FLAG(MouseEventFlag)
+    QT_Q_FLAG(MouseEventFlags)
     QT_Q_ENUM(ChecksumType)
     QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy)
     QT_Q_ENUM(TabFocusBehavior)
diff --git a/qtbase/src/corelib/global/qrandom.cpp b/qtbase/src/corelib/global/qrandom.cpp
index 10672c1f92..25f87c7e6a 100644
--- a/qtbase/src/corelib/global/qrandom.cpp
+++ b/qtbase/src/corelib/global/qrandom.cpp
@@ -383,7 +383,6 @@ struct QRandomGenerator::SystemAndGlobalGenerators
 
         constexpr SystemAndGlobalGenerators g = {};
         Q_UNUSED(g);
-        Q_STATIC_ASSERT(std::is_literal_type<SystemAndGlobalGenerators>::value);
 #endif
     }
 
diff --git a/qtbase/src/corelib/io/qbuffer.cpp b/qtbase/src/corelib/io/qbuffer.cpp
index 595fcd2724..032c0ddd4b 100644
--- a/qtbase/src/corelib/io/qbuffer.cpp
+++ b/qtbase/src/corelib/io/qbuffer.cpp
@@ -41,6 +41,8 @@
 #include <QtCore/qmetaobject.h>
 #include "private/qiodevice_p.h"
 
+#include <limits>
+
 QT_BEGIN_NAMESPACE
 
 /** QBufferPrivate **/
@@ -366,7 +368,9 @@ qint64 QBuffer::size() const
 bool QBuffer::seek(qint64 pos)
 {
     Q_D(QBuffer);
-    if (pos > d->buf->size() && isWritable()) {
+    const auto oldBufSize = d->buf->size();
+    constexpr qint64 MaxSeekPos = (std::numeric_limits<decltype(oldBufSize)>::max)();
+    if (pos <= MaxSeekPos && pos > oldBufSize && isWritable()) {
         if (seek(d->buf->size())) {
             const qint64 gapSize = pos - d->buf->size();
             if (write(QByteArray(gapSize, 0)) != gapSize) {
@@ -377,7 +381,7 @@ bool QBuffer::seek(qint64 pos)
             return false;
         }
     } else if (pos > d->buf->size() || pos < 0) {
-        qWarning("QBuffer::seek: Invalid pos: %d", int(pos));
+        qWarning("QBuffer::seek: Invalid pos: %lld", pos);
         return false;
     }
     return QIODevice::seek(pos);
diff --git a/qtbase/src/corelib/io/qfilesystemengine_win.cpp b/qtbase/src/corelib/io/qfilesystemengine_win.cpp
index 81d3a71986..c86ed1f9b0 100644
--- a/qtbase/src/corelib/io/qfilesystemengine_win.cpp
+++ b/qtbase/src/corelib/io/qfilesystemengine_win.cpp
@@ -664,14 +664,14 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
     return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath());
 }
 
-#if defined(Q_CC_MINGW) && WINVER < 0x0602 //  Windows 8 onwards
+#if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8 //  Windows 8 onwards
 
 typedef struct _FILE_ID_INFO {
     ULONGLONG VolumeSerialNumber;
     FILE_ID_128 FileId;
 } FILE_ID_INFO, *PFILE_ID_INFO;
 
-#endif // if defined (Q_CC_MINGW) && WINVER < 0x0602
+#endif // if defined(Q_CC_MINGW) && WINVER < 0x0602 && _WIN32_WINNT < _WIN32_WINNT_WIN8
 
 // File ID for Windows up to version 7 and FAT32 drives
 static inline QByteArray fileId(HANDLE handle)
diff --git a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 94d9d06bcb..27e0b13b0b 100644
--- a/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/qtbase/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -366,7 +366,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
     // qDebug("QInotifyFileSystemWatcherEngine::readFromInotify");
 
     int buffSize = 0;
-    ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
+    if (ioctl(inotifyFd, FIONREAD, (char *) &buffSize) == -1 || buffSize == 0)
+        return;
+
     QVarLengthArray<char, 4096> buffer(buffSize);
     buffSize = read(inotifyFd, buffer.data(), buffSize);
     char *at = buffer.data();
diff --git a/qtbase/src/corelib/io/qlockfile_win.cpp b/qtbase/src/corelib/io/qlockfile_win.cpp
index 277f8d4230..38ecef5550 100644
--- a/qtbase/src/corelib/io/qlockfile_win.cpp
+++ b/qtbase/src/corelib/io/qlockfile_win.cpp
@@ -48,6 +48,8 @@
 #include "QtCore/qdebug.h"
 #include "QtCore/qthread.h"
 
+#include "private/qsystemlibrary_p.h"
+
 QT_BEGIN_NAMESPACE
 
 static inline bool fileExists(const wchar_t *fileName)
@@ -150,7 +152,7 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
 #if !defined(Q_OS_WINRT)
     typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
 
-    HMODULE hPsapi = LoadLibraryA("psapi");
+    HMODULE hPsapi = QSystemLibrary::load(L"psapi");
     if (!hPsapi)
         return QString();
     GetModuleFileNameExFunc qGetModuleFileNameEx = reinterpret_cast<GetModuleFileNameExFunc>(
diff --git a/qtbase/src/corelib/io/qprocess_unix.cpp b/qtbase/src/corelib/io/qprocess_unix.cpp
index 50390e57f5..15c8f30745 100644
--- a/qtbase/src/corelib/io/qprocess_unix.cpp
+++ b/qtbase/src/corelib/io/qprocess_unix.cpp
@@ -1,7 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2022 Intel Corporation.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
@@ -422,14 +422,15 @@ void QProcessPrivate::startProcess()
     // Add the program name to the argument list.
     argv[0] = nullptr;
     if (!program.contains(QLatin1Char('/'))) {
+        // findExecutable() returns its argument if it's an absolute path,
+        // otherwise it searches $PATH; returns empty if not found (we handle
+        // that case much later)
         const QString &exeFilePath = QStandardPaths::findExecutable(program);
-        if (!exeFilePath.isEmpty()) {
-            const QByteArray &tmp = QFile::encodeName(exeFilePath);
-            argv[0] = ::strdup(tmp.constData());
-        }
-    }
-    if (!argv[0])
+        const QByteArray &tmp = QFile::encodeName(exeFilePath);
+        argv[0] = ::strdup(tmp.constData());
+    } else {
         argv[0] = ::strdup(encodedProgramName.constData());
+    }
 
     // Add every argument to the list
     for (int i = 0; i < arguments.count(); ++i)
@@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint64 *pid)
                 envp = _q_dupEnvironment(environment.d.constData()->vars, &envc);
             }
 
-            QByteArray tmp;
             if (!program.contains(QLatin1Char('/'))) {
+                // findExecutable() returns its argument if it's an absolute path,
+                // otherwise it searches $PATH; returns empty if not found (we handle
+                // that case much later)
                 const QString &exeFilePath = QStandardPaths::findExecutable(program);
-                if (!exeFilePath.isEmpty())
-                    tmp = QFile::encodeName(exeFilePath);
+                const QByteArray &tmp = QFile::encodeName(exeFilePath);
+                argv[0] = ::strdup(tmp.constData());
+            } else {
+                argv[0] = ::strdup(QFile::encodeName(program));
             }
-            if (tmp.isEmpty())
-                tmp = QFile::encodeName(program);
-            argv[0] = tmp.data();
 
             if (envp)
                 qt_safe_execve(argv[0], argv, envp);
diff --git a/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp b/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp
index 3a79c502af..997a634e76 100644
--- a/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -3196,9 +3196,8 @@ bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int s
     destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
     d->changes.push(destinationChange);
 
-    d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
-
     emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, QPrivateSignal());
+    d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
     return true;
 }
 
@@ -3231,7 +3230,6 @@ void QAbstractItemModel::endMoveColumns()
       adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
 
     d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
-
     emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, QPrivateSignal());
 }
 
diff --git a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index dc6379d9fb..c5e287ee84 100644
--- a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -939,8 +939,9 @@ void QSortFilterProxyModelPrivate::insert_source_items(
                 q->beginInsertColumns(proxy_parent, proxy_start, proxy_end);
         }
 
-        for (int i = 0; i < source_items.size(); ++i)
-            proxy_to_source.insert(proxy_start + i, source_items.at(i));
+        // TODO: use the range QList::insert() overload once it is implemented (QTBUG-58633).
+        proxy_to_source.insert(proxy_start, source_items.size(), 0);
+        std::copy(source_items.cbegin(), source_items.cend(), proxy_to_source.begin() + proxy_start);
 
         build_source_to_proxy_mapping(proxy_to_source, source_to_proxy);
 
@@ -3123,8 +3124,9 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
 
     if (d->filter_data.isEmpty())
         return true;
+
+    int column_count = d->model->columnCount(source_parent);
     if (d->filter_column == -1) {
-        int column_count = d->model->columnCount(source_parent);
         for (int column = 0; column < column_count; ++column) {
             QModelIndex source_index = d->model->index(source_row, column, source_parent);
             QString key = d->model->data(source_index, d->filter_role).toString();
@@ -3133,9 +3135,10 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
         }
         return false;
     }
-    QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
-    if (!source_index.isValid()) // the column may not exist
+
+    if (d->filter_column >= column_count) // the column may not exist
         return true;
+    QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
     QString key = d->model->data(source_index, d->filter_role).toString();
     return d->filter_data.hasMatch(key);
 }
diff --git a/qtbase/src/corelib/kernel/qcoreapplication.cpp b/qtbase/src/corelib/kernel/qcoreapplication.cpp
index ca2864df83..132b2eae52 100644
--- a/qtbase/src/corelib/kernel/qcoreapplication.cpp
+++ b/qtbase/src/corelib/kernel/qcoreapplication.cpp
@@ -1157,7 +1157,7 @@ static bool doNotify(QObject *receiver, QEvent *event)
 bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
 {
     // We can't access the application event filters outside of the main thread (race conditions)
-    Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());
+    Q_ASSERT(receiver->d_func()->threadData.loadAcquire()->thread.loadRelaxed() == mainThread());
 
     if (extraData) {
         // application event filters are only called for objects in the GUI thread
diff --git a/qtbase/src/corelib/kernel/qobject.cpp b/qtbase/src/corelib/kernel/qobject.cpp
index 1eb79138d9..36cd780ee1 100644
--- a/qtbase/src/corelib/kernel/qobject.cpp
+++ b/qtbase/src/corelib/kernel/qobject.cpp
@@ -1010,7 +1010,7 @@ QObject::~QObject()
         emit destroyed(this);
     }
 
-    if (d->declarativeData) {
+    if (!d->isDeletingChildren && d->declarativeData) {
         if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
             if (QAbstractDeclarativeData::destroyed_qml1)
                 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
@@ -1580,7 +1580,7 @@ void QObject::moveToThread(QThread *targetThread)
 
     QThreadData *currentData = QThreadData::current();
     QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
-    QThreadData *thisThreadData = d->threadData.loadRelaxed();
+    QThreadData *thisThreadData = d->threadData.loadAcquire();
     if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
         // one exception to the rule: we allow moving objects with no thread affinity to the current thread
         currentData = d->threadData;
@@ -2620,7 +2620,7 @@ int QObject::receivers(const char *signal) const
         if (!d->isSignalConnected(signal_index))
             return receivers;
 
-        if (d->declarativeData && QAbstractDeclarativeData::receivers) {
+        if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::receivers) {
             receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
                                                              signal_index);
         }
diff --git a/qtbase/src/corelib/kernel/qobject_p.h b/qtbase/src/corelib/kernel/qobject_p.h
index 0b827a52ca..13ffb88999 100644
--- a/qtbase/src/corelib/kernel/qobject_p.h
+++ b/qtbase/src/corelib/kernel/qobject_p.h
@@ -444,7 +444,7 @@ inline void QObjectPrivate::checkForIncompatibleLibraryVersion(int version) cons
 
 inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
 {
-    return declarativeData && QAbstractDeclarativeData::isSignalConnected
+    return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
             && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
 }
 
diff --git a/qtbase/src/corelib/kernel/qtranslator.cpp b/qtbase/src/corelib/kernel/qtranslator.cpp
index 2812ffb7ea..bc0177c5ec 100644
--- a/qtbase/src/corelib/kernel/qtranslator.cpp
+++ b/qtbase/src/corelib/kernel/qtranslator.cpp
@@ -902,7 +902,7 @@ static QString getMessage(const uchar *m, const uchar *end, const char *context,
             goto end;
         case Tag_Translation: {
             int len = read32(m);
-            if (len % 1)
+            if (len & 1)
                 return QString();
             m += 4;
             if (!numerus--) {
diff --git a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
index 9de22cef33..ff868a3268 100644
--- a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
@@ -389,20 +389,23 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
         // Disambiguate conflicting extensions (if magic matching found something)
         if (candidateByData.isValid() && magicAccuracy > 0) {
             const QString sniffedMime = candidateByData.name();
-            // If the sniffedMime matches a glob match, use it
+            // If the sniffedMime matches a highest-weight glob match, use it
             if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
                 *accuracyPtr = 100;
                 return candidateByData;
             }
-            for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) {
+            for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) {
                 if (inherits(m, sniffedMime)) {
                     // We have magic + pattern pointing to this, so it's a pretty good match
                     *accuracyPtr = 100;
                     return mimeTypeForName(m);
                 }
             }
-            *accuracyPtr = magicAccuracy;
-            return candidateByData;
+            if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) {
+                // No glob, use magic
+                *accuracyPtr = magicAccuracy;
+                return candidateByData;
+            }
         }
     }
 
diff --git a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
index a81112d227..fa8f4c545d 100644
--- a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -83,7 +83,10 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
     }
     if (!m_matchingMimeTypes.contains(mimeType)) {
         m_matchingMimeTypes.append(mimeType);
-        m_allMatchingMimeTypes.append(mimeType);
+        if (replace)
+            m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first
+        else
+            m_allMatchingMimeTypes.append(mimeType);
         m_knownSuffixLength = knownSuffixLength;
     }
 }
@@ -94,7 +97,7 @@ QMimeGlobPattern::PatternType QMimeGlobPattern::detectPatternType(const QString
     if (!patternLength)
         return OtherPattern;
 
-    const bool starCount = pattern.count(QLatin1Char('*')) == 1;
+    const int starCount = pattern.count(QLatin1Char('*'));
     const bool hasSquareBracket = pattern.indexOf(QLatin1Char('[')) != -1;
     const bool hasQuestionMark = pattern.indexOf(QLatin1Char('?')) != -1;
 
@@ -106,10 +109,10 @@ QMimeGlobPattern::PatternType QMimeGlobPattern::detectPatternType(const QString
             // Patterns like "README*" (well this is currently the only one like that...)
             if (pattern.at(patternLength - 1) == QLatin1Char('*'))
                 return PrefixPattern;
-        }
-        // Names without any wildcards like "README"
-        if (starCount == 0)
+        } else if (starCount == 0) {
+            // Names without any wildcards like "README"
             return LiteralPattern;
+        }
     }
 
     if (pattern == QLatin1String("[0-9][0-9][0-9].vdr"))
diff --git a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
index 258dddf8cb..4642d0f2d0 100644
--- a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
@@ -244,15 +244,18 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM
     const QString lowerFileName = fileName.toLower();
     // Check literals (e.g. "Makefile")
     matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName);
-    // Check complex globs (e.g. "callgrind.out[0-9]*")
-    matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
     // Check the very common *.txt cases with the suffix tree
-    const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
-    const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
-    const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
-    matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
+    if (result.m_matchingMimeTypes.isEmpty()) {
+        const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
+        const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
+        const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+        matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
+        if (result.m_matchingMimeTypes.isEmpty())
+            matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+    }
+    // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*")
     if (result.m_matchingMimeTypes.isEmpty())
-        matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+        matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
 }
 
 void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
diff --git a/qtbase/src/corelib/serialization/qjsonparser.cpp b/qtbase/src/corelib/serialization/qjsonparser.cpp
index 17e6f111ab..2e40b6c8fb 100644
--- a/qtbase/src/corelib/serialization/qjsonparser.cpp
+++ b/qtbase/src/corelib/serialization/qjsonparser.cpp
@@ -379,10 +379,30 @@ error:
     return QCborValue();
 }
 
+// We need to retain the _last_ value for any duplicate keys and we need to deref containers.
+// Therefore the manual implementation of std::unique().
+template<typename Iterator, typename Compare, typename Assign>
+static Iterator customAssigningUniqueLast(Iterator first, Iterator last,
+                                          Compare compare, Assign assign)
+{
+    first = std::adjacent_find(first, last, compare);
+    if (first == last)
+        return last;
+
+    Iterator result = first;
+    while (++first != last) {
+        if (!compare(*result, *first))
+            ++result;
+        if (result != first)
+            assign(*result, *first);
+    }
+
+    return ++result;
+}
+
 static void sortContainer(QCborContainerPrivate *container)
 {
     using Forward = QJsonPrivate::KeyIterator;
-    using Reverse = std::reverse_iterator<Forward>;
     using Value = Forward::value_type;
 
     auto compare = [container](const Value &a, const Value &b)
@@ -420,17 +440,31 @@ static void sortContainer(QCborContainerPrivate *container)
         }
     };
 
-    std::sort(Forward(container->elements.begin()), Forward(container->elements.end()),
-              [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
+    // The elements' containers are owned by the outer container, not by the elements themselves.
+    auto move = [](Forward::reference target, Forward::reference source)
+    {
+        QtCbor::Element &targetValue = target.value();
+
+        // If the target has a container, deref it before overwriting, so that we don't leak.
+        if (targetValue.flags & QtCbor::Element::IsContainer)
+            targetValue.container->deref();
+
+        // Do not move, so that we can clear the value afterwards.
+        target = source;
+
+        // Clear the source value, so that we don't store the same container twice.
+        source.value() = QtCbor::Element();
+    };
+
+    std::stable_sort(
+                Forward(container->elements.begin()), Forward(container->elements.end()),
+                [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
 
-    // We need to retain the _last_ value for any duplicate keys. Therefore the reverse dance here.
-    auto it = std::unique(Reverse(container->elements.end()), Reverse(container->elements.begin()),
-                          [&compare](const Value &a, const Value &b) {
-        return compare(a, b) == 0;
-    }).base().elementsIterator();
+    Forward result = customAssigningUniqueLast(
+                Forward(container->elements.begin()),  Forward(container->elements.end()),
+                [&compare](const Value &a, const Value &b) { return compare(a, b) == 0; }, move);
 
-    // The erase from beginning is expensive but hopefully rare.
-    container->elements.erase(container->elements.begin(), it);
+    container->elements.erase(result.elementsIterator(), container->elements.end());
 }
 
 
diff --git a/qtbase/src/corelib/serialization/qxmlstream.cpp b/qtbase/src/corelib/serialization/qxmlstream.cpp
index b2f846544d..7cd457ba3a 100644
--- a/qtbase/src/corelib/serialization/qxmlstream.cpp
+++ b/qtbase/src/corelib/serialization/qxmlstream.cpp
@@ -980,7 +980,7 @@ inline uint QXmlStreamReaderPrivate::peekChar()
 bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
 {
     int pos = textBuffer.size();
-    int oldLineNumber = lineNumber;
+    const auto oldLineNumber = lineNumber;
 
     uint c;
     while ((c = getChar()) != StreamEOF) {
diff --git a/qtbase/src/corelib/text/qstring.cpp b/qtbase/src/corelib/text/qstring.cpp
index 3e88ab4859..8deeae47bb 100644
--- a/qtbase/src/corelib/text/qstring.cpp
+++ b/qtbase/src/corelib/text/qstring.cpp
@@ -12312,7 +12312,7 @@ static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
     const auto needle = needle0.data();
     const auto *end = haystack;
     haystack += from;
-    const std::size_t sl_minus_1 = sl - 1;
+    const std::size_t sl_minus_1 = sl ? sl - 1 : 0;
     const auto *n = needle + sl_minus_1;
     const auto *h = haystack + sl_minus_1;
     std::size_t hashNeedle = 0, hashHaystack = 0;
diff --git a/qtbase/src/corelib/text/qstringiterator_p.h b/qtbase/src/corelib/text/qstringiterator_p.h
index 219589b6e4..1d0c66cc78 100644
--- a/qtbase/src/corelib/text/qstringiterator_p.h
+++ b/qtbase/src/corelib/text/qstringiterator_p.h
@@ -61,6 +61,8 @@ class QStringIterator
 {
     QString::const_iterator i, pos, e;
     Q_STATIC_ASSERT((std::is_same<QString::const_iterator, const QChar *>::value));
+    static bool less(const QChar *lhs, const QChar *rhs) noexcept
+    { return std::less<QString::const_iterator>{}(lhs, rhs); }
 public:
     explicit QStringIterator(QStringView string, qsizetype idx = 0)
         : i(string.begin()),
@@ -95,7 +97,8 @@ public:
 
     inline void setPosition(QString::const_iterator position)
     {
-        Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
+        Q_ASSERT_X(!less(position, i) && !less(e, position),
+                   Q_FUNC_INFO, "position out of bounds");
         pos = position;
     }
 
@@ -103,7 +106,7 @@ public:
 
     inline bool hasNext() const
     {
-        return pos < e;
+        return less(pos, e);
     }
 
     inline void advance()
@@ -120,16 +123,20 @@ public:
     {
         Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
 
-        if (Q_UNLIKELY((pos++)->isHighSurrogate()))
+        if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
+            Q_ASSERT(hasNext() && pos->isLowSurrogate());
             ++pos;
+        }
     }
 
     inline uint peekNextUnchecked() const
     {
         Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
 
-        if (Q_UNLIKELY(pos->isHighSurrogate()))
+        if (Q_UNLIKELY(pos->isHighSurrogate())) {
+            Q_ASSERT(less(pos + 1, e) && pos[1].isLowSurrogate());
             return QChar::surrogateToUcs4(pos[0], pos[1]);
+        }
 
         return pos->unicode();
     }
@@ -155,8 +162,10 @@ public:
         Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
 
         const QChar cur = *pos++;
-        if (Q_UNLIKELY(cur.isHighSurrogate()))
+        if (Q_UNLIKELY(cur.isHighSurrogate())) {
+            Q_ASSERT(hasNext() && pos->isLowSurrogate());
             return QChar::surrogateToUcs4(cur, *pos++);
+        }
         return cur.unicode();
     }
 
@@ -166,7 +175,7 @@ public:
 
         const QChar uc = *pos++;
         if (Q_UNLIKELY(uc.isSurrogate())) {
-            if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate()))
+            if (Q_LIKELY(uc.isHighSurrogate() && hasNext() && pos->isLowSurrogate()))
                 return QChar::surrogateToUcs4(uc, *pos++);
             return invalidAs;
         }
@@ -178,7 +187,7 @@ public:
 
     inline bool hasPrevious() const
     {
-        return pos > i;
+        return less(i, pos);
     }
 
     inline void recede()
@@ -196,16 +205,20 @@ public:
     {
         Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
 
-        if (Q_UNLIKELY((--pos)->isLowSurrogate()))
+        if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
+            Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
             --pos;
+        }
     }
 
     inline uint peekPreviousUnchecked() const
     {
         Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
 
-        if (Q_UNLIKELY(pos[-1].isLowSurrogate()))
+        if (Q_UNLIKELY(pos[-1].isLowSurrogate())) {
+            Q_ASSERT(less(i + 1, pos) && pos[-2].isHighSurrogate());
             return QChar::surrogateToUcs4(pos[-2], pos[-1]);
+        }
         return pos[-1].unicode();
     }
 
@@ -230,8 +243,10 @@ public:
         Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
 
         const QChar cur = *--pos;
-        if (Q_UNLIKELY(cur.isLowSurrogate()))
+        if (Q_UNLIKELY(cur.isLowSurrogate())) {
+            Q_ASSERT(hasPrevious() && pos[-1].isHighSurrogate());
             return QChar::surrogateToUcs4(*--pos, cur);
+        }
         return cur.unicode();
     }
 
@@ -241,7 +256,7 @@ public:
 
         const QChar uc = *--pos;
         if (Q_UNLIKELY(uc.isSurrogate())) {
-            if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate()))
+            if (Q_LIKELY(uc.isLowSurrogate() && hasPrevious() && pos[-1].isHighSurrogate()))
                 return QChar::surrogateToUcs4(*--pos, uc);
             return invalidAs;
         }
diff --git a/qtbase/src/corelib/thread/qfutex_p.h b/qtbase/src/corelib/thread/qfutex_p.h
index f287b752d7..e294537787 100644
--- a/qtbase/src/corelib/thread/qfutex_p.h
+++ b/qtbase/src/corelib/thread/qfutex_p.h
@@ -52,6 +52,7 @@
 //
 
 #include <qglobal.h>
+#include <QtCore/qtsan_impl.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -106,16 +107,13 @@ namespace QtLinuxFutex {
     inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
                         int *addr2 = nullptr, int val3 = 0) noexcept
     {
-        // A futex call ensures total ordering on the futex words
-        // (in either success or failure of the call). Instruct TSAN accordingly,
-        // as TSAN does not understand the futex(2) syscall.
-        _q_tsan_release(addr, addr2);
+        QtTsan::futexRelease(addr, addr2);
 
         // we use __NR_futex because some libcs (like Android's bionic) don't
         // provide SYS_futex etc.
         int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
 
-        _q_tsan_acquire(addr, addr2);
+        QtTsan::futexAcquire(addr, addr2);
 
         return result;
     }
diff --git a/qtbase/src/corelib/thread/qmutex.cpp b/qtbase/src/corelib/thread/qmutex.cpp
index 310d1cb14f..7097122d8e 100644
--- a/qtbase/src/corelib/thread/qmutex.cpp
+++ b/qtbase/src/corelib/thread/qmutex.cpp
@@ -152,6 +152,7 @@ public:
 
 /*!
     \enum QMutex::RecursionMode
+    \obsolete Use QRecursiveMutex to create a recursive mutex.
 
     \value Recursive  In this mode, a thread can lock the same mutex
                       multiple times and the mutex won't be unlocked
@@ -173,6 +174,7 @@ public:
 
 /*!
     Constructs a new mutex. The mutex is created in an unlocked state.
+    \obsolete Use QRecursiveMutex to create a recursive mutex.
 
     If \a mode is QMutex::Recursive, a thread can lock the same mutex
     multiple times and the mutex won't be unlocked until a
@@ -197,7 +199,7 @@ QMutex::QMutex(RecursionMode mode)
 QMutex::~QMutex()
 {
     QMutexData *d = d_ptr.loadRelaxed();
-    if (isRecursive()) {
+    if (QBasicMutex::isRecursive()) {
         delete static_cast<QRecursiveMutexPrivate *>(d);
     } else if (d) {
 #ifndef QT_LINUX_FUTEX
diff --git a/qtbase/src/corelib/thread/qmutex.h b/qtbase/src/corelib/thread/qmutex.h
index 73c9e00663..1bae573a03 100644
--- a/qtbase/src/corelib/thread/qmutex.h
+++ b/qtbase/src/corelib/thread/qmutex.h
@@ -42,6 +42,7 @@
 
 #include <QtCore/qglobal.h>
 #include <QtCore/qatomic.h>
+#include <QtCore/qtsan_impl.h>
 #include <new>
 
 #if __has_include(<chrono>)
@@ -77,19 +78,37 @@ public:
 
     // BasicLockable concept
     inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
+        QtTsan::mutexPreLock(this, 0u);
+
         if (!fastTryLock())
             lockInternal();
+
+        QtTsan::mutexPostLock(this, 0u, 0);
     }
 
     // BasicLockable concept
     inline void unlock() noexcept {
         Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
+
+        QtTsan::mutexPreUnlock(this, 0u);
+
         if (!fastTryUnlock())
             unlockInternal();
+
+        QtTsan::mutexPostUnlock(this, 0u);
     }
 
     bool tryLock() noexcept {
-        return fastTryLock();
+        unsigned tsanFlags = QtTsan::TryLock;
+        QtTsan::mutexPreLock(this, tsanFlags);
+
+        const bool success = fastTryLock();
+
+        if (!success)
+            tsanFlags |= QtTsan::TryLockFailed;
+        QtTsan::mutexPostLock(this, tsanFlags, 0);
+
+        return success;
     }
 
     // Lockable concept
@@ -134,8 +153,16 @@ public:
 #else
     QMutex() { d_ptr.storeRelaxed(nullptr); }
 #endif
+#if QT_DEPRECATED_SINCE(5,15)
     enum RecursionMode { NonRecursive, Recursive };
+    QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex")
     explicit QMutex(RecursionMode mode);
+
+    QT_DEPRECATED_VERSION_X(5, 15, "Use QRecursiveMutex instead of a recursive QMutex")
+    bool isRecursive() const noexcept
+    { return QBasicMutex::isRecursive(); }
+#endif
+
     ~QMutex();
 
     // BasicLockable concept
@@ -166,9 +193,6 @@ public:
     }
 #endif
 
-    bool isRecursive() const noexcept
-    { return QBasicMutex::isRecursive(); }
-
 private:
     Q_DISABLE_COPY(QMutex)
     friend class QMutexLocker;
diff --git a/qtbase/src/corelib/thread/qreadwritelock.cpp b/qtbase/src/corelib/thread/qreadwritelock.cpp
index 8c28507d5a..9dd8503116 100644
--- a/qtbase/src/corelib/thread/qreadwritelock.cpp
+++ b/qtbase/src/corelib/thread/qreadwritelock.cpp
@@ -155,7 +155,7 @@ QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
 */
 QReadWriteLock::~QReadWriteLock()
 {
-    auto d = d_ptr.loadRelaxed();
+    auto d = d_ptr.loadAcquire();
     if (isUncontendedLocked(d)) {
         qWarning("QReadWriteLock: destroying locked QReadWriteLock");
         return;
@@ -445,7 +445,7 @@ void QReadWriteLock::unlock()
 /*! \internal  Helper for QWaitCondition::wait */
 QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
 {
-    QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
+    QReadWriteLockPrivate *d = d_ptr.loadAcquire();
     switch (quintptr(d) & StateMask) {
     case StateLockedForRead: return LockedForRead;
     case StateLockedForWrite: return LockedForWrite;
@@ -453,6 +453,7 @@ QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() co
 
     if (!d)
         return Unlocked;
+    const auto lock = qt_scoped_lock(d->mutex);
     if (d->writerCount > 1)
         return RecursivelyLocked;
     else if (d->writerCount == 1)
diff --git a/qtbase/src/corelib/thread/qsemaphore.cpp b/qtbase/src/corelib/thread/qsemaphore.cpp
index 1d01fc1b28..3ecdee3747 100644
--- a/qtbase/src/corelib/thread/qsemaphore.cpp
+++ b/qtbase/src/corelib/thread/qsemaphore.cpp
@@ -354,7 +354,12 @@ void QSemaphore::release(int n)
         quintptr nn = unsigned(n);
         if (futexHasWaiterCount)
             nn |= quint64(nn) << 32;    // token count replicated in high word
-        quintptr prevValue = u.fetchAndAddRelease(nn);
+        quintptr prevValue = u.loadRelaxed();
+        quintptr newValue;
+        do { // loop just to ensure the operations are done atomically
+            newValue = prevValue + nn;
+            newValue &= (futexNeedsWakeAllBit - 1);
+        } while (!u.testAndSetRelease(prevValue, newValue, prevValue));
         if (futexNeedsWake(prevValue)) {
 #ifdef FUTEX_OP
             if (futexHasWaiterCount) {
@@ -376,7 +381,6 @@ void QSemaphore::release(int n)
                 quint32 oparg = 0;
                 quint32 cmp = FUTEX_OP_CMP_NE;
                 quint32 cmparg = 0;
-                u.fetchAndAndRelease(futexNeedsWakeAllBit - 1);
                 futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg));
                 return;
             }
@@ -388,7 +392,6 @@ void QSemaphore::release(int n)
             //    its acquisition anyway, so it has to wait;
             // 2) it did not see the new counter value, in which case its
             //    futexWait will fail.
-            u.fetchAndAndRelease(futexNeedsWakeAllBit - 1);
             if (futexHasWaiterCount) {
                 futexWakeAll(*futexLow32(&u));
                 futexWakeAll(*futexHigh32(&u));
diff --git a/qtbase/src/corelib/thread/qthread_p.h b/qtbase/src/corelib/thread/qthread_p.h
index b2d1628e6e..f32f6f0460 100644
--- a/qtbase/src/corelib/thread/qthread_p.h
+++ b/qtbase/src/corelib/thread/qthread_p.h
@@ -174,7 +174,7 @@ public:
     int returnCode;
 
     uint stackSize;
-    QThread::Priority priority;
+    std::underlying_type<QThread::Priority>::type priority;
 
     static QThread *threadForId(int id);
 
@@ -213,6 +213,13 @@ public:
             QCoreApplication::instance()->postEvent(q_ptr, new QEvent(QEvent::Quit));
         }
     }
+
+#ifndef Q_OS_INTEGRITY
+private:
+    // Used in QThread(Private)::start to avoid racy access to QObject::objectName,
+    // unset afterwards. On INTEGRITY we set the thread name before starting it.
+    QString objectName;
+#endif
 };
 
 #else // QT_CONFIG(thread)
diff --git a/qtbase/src/corelib/thread/qthread_unix.cpp b/qtbase/src/corelib/thread/qthread_unix.cpp
index 56a8e0a038..610117a640 100644
--- a/qtbase/src/corelib/thread/qthread_unix.cpp
+++ b/qtbase/src/corelib/thread/qthread_unix.cpp
@@ -169,8 +169,7 @@ static void set_thread_data(QThreadData *data)
 
 static void clear_thread_data()
 {
-    currentThreadData = nullptr;
-    pthread_setspecific(current_thread_data_key, nullptr);
+    set_thread_data(nullptr);
 }
 
 template <typename T>
@@ -296,7 +295,7 @@ void *QThreadPrivate::start(void *arg)
             QMutexLocker locker(&thr->d_func()->mutex);
 
             // do we need to reset the thread priority?
-            if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
+            if (thr->d_func()->priority & ThreadPriorityResetFlag) {
                 thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
             }
 
@@ -316,10 +315,10 @@ void *QThreadPrivate::start(void *arg)
             // Sets the name of the current thread. We can only do this
             // when the thread is starting, as we don't have a cross
             // platform way of setting the name of an arbitrary thread.
-            if (Q_LIKELY(thr->objectName().isEmpty()))
+            if (Q_LIKELY(thr->d_func()->objectName.isEmpty()))
                 setCurrentThreadName(thr->metaObject()->className());
             else
-                setCurrentThreadName(thr->objectName().toLocal8Bit());
+                setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
         }
 #endif
 
@@ -671,7 +670,7 @@ void QThread::start(Priority priority)
                 // could not set scheduling hints, fallback to inheriting them
                 // we'll try again from inside the thread
                 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
-                d->priority = Priority(priority | ThreadPriorityResetFlag);
+                d->priority = static_cast<std::underlying_type<QThread::Priority>::type>(priority) | ThreadPriorityResetFlag;
             }
             break;
         }
@@ -702,7 +701,10 @@ void QThread::start(Priority priority)
         pthread_attr_setthreadname(&attr, metaObject()->className());
     else
         pthread_attr_setthreadname(&attr, objectName().toLocal8Bit());
+#else
+    d->objectName = objectName();
 #endif
+
     pthread_t threadId;
     int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
     if (code == EPERM) {
diff --git a/qtbase/src/corelib/thread/qthread_win.cpp b/qtbase/src/corelib/thread/qthread_win.cpp
index bc70e3178a..4e76972498 100644
--- a/qtbase/src/corelib/thread/qthread_win.cpp
+++ b/qtbase/src/corelib/thread/qthread_win.cpp
@@ -394,10 +394,9 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
 
 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT)
     // sets the name of the current thread.
-    QByteArray objectName = thr->objectName().toLocal8Bit();
-    qt_set_thread_name(HANDLE(-1),
-                       objectName.isEmpty() ?
-                       thr->metaObject()->className() : objectName.constData());
+    qt_set_thread_name(HANDLE(-1), thr->d_func()->objectName.isEmpty()
+                        ? thr->metaObject()->className()
+                        : std::exchange(thr->d_func()->objectName, {}).toLocal8Bit().constData());
 #endif
 
     emit thr->started(QThread::QPrivateSignal());
@@ -503,6 +502,7 @@ void QThread::start(Priority priority)
     if (d->running)
         return;
 
+    d->objectName = objectName();
     d->running = true;
     d->finished = false;
     d->exited = false;
@@ -548,7 +548,7 @@ void QThread::start(Priority priority)
 
     int prio;
     d->priority = priority;
-    switch (d->priority) {
+    switch (priority) {
     case IdlePriority:
         prio = THREAD_PRIORITY_IDLE;
         break;
@@ -686,7 +686,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
 
     int prio;
     priority = threadPriority;
-    switch (priority) {
+    switch (threadPriority) {
     case QThread::IdlePriority:
         prio = THREAD_PRIORITY_IDLE;
         break;
diff --git a/qtbase/src/corelib/thread/qtsan_impl.h b/qtbase/src/corelib/thread/qtsan_impl.h
new file mode 100644
index 0000000000..580a738b91
--- /dev/null
+++ b/qtbase/src/corelib/thread/qtsan_impl.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTSAN_IMPL_H
+#define QTSAN_IMPL_H
+
+#include <QtCore/qglobal.h>
+
+#if (__has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && __has_include(<sanitizer/tsan_interface.h>)
+#  define QT_BUILDING_UNDER_TSAN
+#  include <sanitizer/tsan_interface.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QtTsan {
+#ifdef QT_BUILDING_UNDER_TSAN
+inline void futexAcquire(void *addr, void *addr2 = nullptr)
+{
+    // A futex call ensures total ordering on the futex words
+    // (in either success or failure of the call). Instruct TSAN accordingly,
+    // as TSAN does not understand the futex(2) syscall (or equivalent).
+    ::__tsan_acquire(addr);
+    if (addr2)
+        ::__tsan_acquire(addr2);
+}
+
+inline void futexRelease(void *addr, void *addr2 = nullptr)
+{
+    if (addr2)
+        ::__tsan_release(addr2);
+    ::__tsan_release(addr);
+}
+
+inline void mutexPreLock(void *addr, unsigned flags)
+{
+    ::__tsan_mutex_pre_lock(addr, flags);
+}
+
+inline void mutexPostLock(void *addr, unsigned flags, int recursion)
+{
+    ::__tsan_mutex_post_lock(addr, flags, recursion);
+}
+
+inline void mutexPreUnlock(void *addr, unsigned flags)
+{
+    ::__tsan_mutex_pre_unlock(addr, flags);
+}
+
+inline void mutexPostUnlock(void *addr, unsigned flags)
+{
+    ::__tsan_mutex_post_unlock(addr, flags);
+}
+
+enum : unsigned {
+    MutexWriteReentrant = ::__tsan_mutex_write_reentrant,
+    TryLock = ::__tsan_mutex_try_lock,
+    TryLockFailed = ::__tsan_mutex_try_lock_failed,
+};
+#else
+inline void futexAcquire(void *, void * = nullptr) {}
+inline void futexRelease(void *, void * = nullptr) {}
+
+enum : unsigned {
+    MutexWriteReentrant,
+    TryLock,
+    TryLockFailed,
+};
+inline void mutexPreLock(void *, unsigned) {}
+inline void mutexPostLock(void *, unsigned, int) {}
+inline void mutexPreUnlock(void *, unsigned) {}
+inline void mutexPostUnlock(void *, unsigned) {}
+#endif // QT_BUILDING_UNDER_TSAN
+} // namespace QtTsan
+
+QT_END_NAMESPACE
+
+#endif // QTSAN_IMPL_H
diff --git a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
index 88b058f410..0f1da4dc9b 100644
--- a/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/qtbase/src/corelib/thread/qwaitcondition_unix.cpp
@@ -213,7 +213,7 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
 {
     if (! mutex)
         return false;
-    if (mutex->isRecursive()) {
+    if (static_cast<QBasicMutex *>(mutex)->isRecursive()) {
         qWarning("QWaitCondition: cannot wait on recursive mutexes");
         return false;
     }
diff --git a/qtbase/src/corelib/time/qdatetime.cpp b/qtbase/src/corelib/time/qdatetime.cpp
index ec12569e3f..2c0b098079 100644
--- a/qtbase/src/corelib/time/qdatetime.cpp
+++ b/qtbase/src/corelib/time/qdatetime.cpp
@@ -43,6 +43,7 @@
 #if QT_CONFIG(datetimeparser)
 #include "private/qdatetimeparser_p.h"
 #endif
+#include <private/qnumeric_p.h>
 
 #include "qdatastream.h"
 #include "qset.h"
@@ -1429,9 +1430,11 @@ QDate QDate::addDays(qint64 ndays) const
     if (isNull())
         return QDate();
 
-    // Due to limits on minJd() and maxJd() we know that any overflow
-    // will be invalid and caught by fromJulianDay().
-    return fromJulianDay(jd + ndays);
+    qint64 r;
+    if (Q_UNLIKELY(add_overflow(jd, ndays, &r)))
+        return QDate();
+    else
+        return fromJulianDay(r);
 }
 
 /*!
diff --git a/qtbase/src/corelib/time/qtimezone.cpp b/qtbase/src/corelib/time/qtimezone.cpp
index 0309e43e52..3d451696a1 100644
--- a/qtbase/src/corelib/time/qtimezone.cpp
+++ b/qtbase/src/corelib/time/qtimezone.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
+** Copyright (C) 2020 John Layt <jlayt@kde.org>
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
@@ -975,9 +975,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
 }
 
 #ifndef QT_NO_DATASTREAM
+// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
+static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }
+
 QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
 {
-    tz.d->serialize(ds);
+    if (tz.isValid())
+        tz.d->serialize(ds);
+    else
+        ds << invalidId();
     return ds;
 }
 
@@ -985,7 +991,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
 {
     QString ianaId;
     ds >> ianaId;
-    if (ianaId == QLatin1String("OffsetFromUtc")) {
+    if (ianaId == invalidId()) {
+        tz = QTimeZone();
+    } else if (ianaId == QLatin1String("OffsetFromUtc")) {
         int utcOffset;
         QString name;
         QString abbreviation;
diff --git a/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp b/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp
index b1611d7ddb..a7a6a72ccf 100644
--- a/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/qtbase/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -42,6 +42,7 @@
 #include "qtimezone.h"
 #include "qtimezoneprivate_p.h"
 #include "private/qlocale_tools_p.h"
+#include "private/qlocking_p.h"
 
 #include <QtCore/QDataStream>
 #include <QtCore/QDateTime>
@@ -62,6 +63,10 @@
 
 QT_BEGIN_NAMESPACE
 
+#if QT_CONFIG(icu)
+static QBasicMutex s_icu_mutex;
+#endif
+
 /*
     Private
 
@@ -670,6 +675,9 @@ QTzTimeZonePrivate::~QTzTimeZonePrivate()
 
 QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
 {
+#if QT_CONFIG(icu)
+    const auto lock = qt_scoped_lock(s_icu_mutex);
+#endif
     return new QTzTimeZonePrivate(*this);
 }
 
@@ -913,12 +921,14 @@ QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
                                         const QLocale &locale) const
 {
 #if QT_CONFIG(icu)
+    auto lock = qt_unique_lock(s_icu_mutex);
     if (!m_icu)
         m_icu = new QIcuTimeZonePrivate(m_id);
     // TODO small risk may not match if tran times differ due to outdated files
     // TODO Some valid TZ names are not valid ICU names, use translation table?
     if (m_icu->isValid())
         return m_icu->displayName(atMSecsSinceEpoch, nameType, locale);
+    lock.unlock();
 #else
     Q_UNUSED(nameType)
     Q_UNUSED(locale)
@@ -932,12 +942,14 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
                                         const QLocale &locale) const
 {
 #if QT_CONFIG(icu)
+    auto lock = qt_unique_lock(s_icu_mutex);
     if (!m_icu)
         m_icu = new QIcuTimeZonePrivate(m_id);
     // TODO small risk may not match if tran times differ due to outdated files
     // TODO Some valid TZ names are not valid ICU names, use translation table?
     if (m_icu->isValid())
         return m_icu->displayName(timeType, nameType, locale);
+    lock.unlock();
 #else
     Q_UNUSED(timeType)
     Q_UNUSED(nameType)
diff --git a/qtbase/src/corelib/tools/qarraydata.h b/qtbase/src/corelib/tools/qarraydata.h
index dcd95924c1..d01739e7e6 100644
--- a/qtbase/src/corelib/tools/qarraydata.h
+++ b/qtbase/src/corelib/tools/qarraydata.h
@@ -42,6 +42,7 @@
 
 #include <QtCore/qrefcount.h>
 #include <string.h>
+#include <cstdint>
 
 QT_BEGIN_NAMESPACE
 
@@ -58,14 +59,14 @@ struct Q_CORE_EXPORT QArrayData
     {
         Q_ASSERT(size == 0
                 || offset < 0 || size_t(offset) >= sizeof(QArrayData));
-        return reinterpret_cast<char *>(this) + offset;
+        return reinterpret_cast<void *> (reinterpret_cast<uintptr_t>(this) + offset);
     }
 
     const void *data() const
     {
         Q_ASSERT(size == 0
                 || offset < 0 || size_t(offset) >= sizeof(QArrayData));
-        return reinterpret_cast<const char *>(this) + offset;
+        return reinterpret_cast<void *> (reinterpret_cast<uintptr_t>(this) + offset);
     }
 
     // This refers to array data mutability, not "header data" represented by
diff --git a/qtbase/src/corelib/tools/qfreelist_p.h b/qtbase/src/corelib/tools/qfreelist_p.h
index 5ba23b344b..9974102136 100644
--- a/qtbase/src/corelib/tools/qfreelist_p.h
+++ b/qtbase/src/corelib/tools/qfreelist_p.h
@@ -161,7 +161,7 @@ class QFreeList
                 return i;
             x -= size;
         }
-        Q_ASSERT(false);
+        Q_UNREACHABLE();
         return -1;
     }
 
diff --git a/qtbase/src/corelib/tools/qversionnumber.h b/qtbase/src/corelib/tools/qversionnumber.h
index d43b86ba51..2843f2b043 100644
--- a/qtbase/src/corelib/tools/qversionnumber.h
+++ b/qtbase/src/corelib/tools/qversionnumber.h
@@ -273,10 +273,10 @@ public:
 
     Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const;
 #if QT_STRINGVIEW_LEVEL < 2
-    Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr);
+    Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr);
 #endif
-    Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
-    Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
+    Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
+    Q_REQUIRED_RESULT Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
 
 private:
 #ifndef QT_NO_DATASTREAM
diff --git a/qtbase/src/dbus/qdbusintegrator.cpp b/qtbase/src/dbus/qdbusintegrator.cpp
index 5b66ce971b..28a3b0ffea 100644
--- a/qtbase/src/dbus/qdbusintegrator.cpp
+++ b/qtbase/src/dbus/qdbusintegrator.cpp
@@ -1135,7 +1135,13 @@ void QDBusConnectionPrivate::closeConnection()
         }
     }
 
-    qDeleteAll(pendingCalls);
+    for (auto it = pendingCalls.begin(); it != pendingCalls.end(); ++it) {
+        auto call = *it;
+        if (!call->ref.deref()) {
+            delete call;
+        }
+    }
+    pendingCalls.clear();
 
     // Disconnect all signals from signal hooks and from the object tree to
     // avoid QObject::destroyed being sent to dbus daemon thread which has
@@ -2584,6 +2590,11 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa
         if (mo)
             return mo;
     }
+    if (path.isEmpty()) {
+        error = QDBusError(QDBusError::InvalidObjectPath, QLatin1String("Object path cannot be empty"));
+        lastError = error;
+        return nullptr;
+    }
 
     // introspect the target object
     QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
diff --git a/qtbase/src/dbus/qdbusmetaobject.cpp b/qtbase/src/dbus/qdbusmetaobject.cpp
index 5265568f42..7e9f0f1acc 100644
--- a/qtbase/src/dbus/qdbusmetaobject.cpp
+++ b/qtbase/src/dbus/qdbusmetaobject.cpp
@@ -210,6 +210,9 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature,
         } else if (signature == "a{ss}") {
             result.name = "QMap<QString,QString>";
             type = qMetaTypeId<QMap<QString, QString> >();
+        } else if (signature == "aay") {
+            result.name = "QByteArrayList";
+            type = qMetaTypeId<QByteArrayList>();
         } else {
             result.name = "{D-Bus type \"" + signature + "\"}";
             type = registerComplexDBusType(result.name);
diff --git a/qtbase/src/gui/accessible/qaccessible.cpp b/qtbase/src/gui/accessible/qaccessible.cpp
index d705bfccb5..0caf3c808c 100644
--- a/qtbase/src/gui/accessible/qaccessible.cpp
+++ b/qtbase/src/gui/accessible/qaccessible.cpp
@@ -54,6 +54,7 @@
 #include <QtCore/qdebug.h>
 #include <QtCore/qloggingcategory.h>
 #include <QtCore/qmetaobject.h>
+#include <QtCore/private/qmetaobject_p.h>
 #include <QtCore/qhash.h>
 #include <private/qfactoryloader_p.h>
 
@@ -681,6 +682,25 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
     // Create a QAccessibleInterface for the object class. Start by the most
     // derived class and walk up the class hierarchy.
     const QMetaObject *mo = object->metaObject();
+    const auto *objectPriv = QObjectPrivate::get(object);
+    /*
+     We do not want to cache each and every QML metaobject (Button_QMLTYPE_124,
+     Button_QMLTYPE_125, etc.). Those dynamic metaobjects shouldn't have an
+     accessible interface in any case. Instead, we start the whole checking
+     with the first non-dynamic meta-object. To avoid potential regressions
+     in other areas of Qt that also use dynamic metaobjects, we only do this
+     for objects that are QML-related (approximated by checking whether they
+     have ddata set).
+    */
+    const bool qmlRelated = !objectPriv->isDeletingChildren &&
+                            objectPriv->declarativeData;
+    while (qmlRelated && mo) {
+        auto mop = QMetaObjectPrivate::get(mo);
+        if (!mop || !(mop->flags & DynamicMetaObject))
+            break;
+
+        mo = mo->superClass();
+    };
     while (mo) {
         const QString cn = QLatin1String(mo->className());
 
@@ -696,14 +716,15 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
         // Find a QAccessiblePlugin (factory) for the class name. If there's
         // no entry in the cache try to create it using the plugin loader.
         if (!qAccessiblePlugins()->contains(cn)) {
+            QAccessiblePlugin *factory = nullptr; // 0 means "no plugin found". This is cached as well.
             const int index = loader()->indexOf(cn);
-            if (index != -1) {
-                QAccessiblePlugin *factory = qobject_cast<QAccessiblePlugin *>(loader()->instance(index));
-                qAccessiblePlugins()->insert(cn, factory);
-            }
+            if (index != -1)
+                factory = qobject_cast<QAccessiblePlugin *>(loader()->instance(index));
+            qAccessiblePlugins()->insert(cn, factory);
         }
 
         // At this point the cache should contain a valid factory pointer or 0:
+        Q_ASSERT(qAccessiblePlugins()->contains(cn));
         QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn);
         if (factory) {
             QAccessibleInterface *result = factory->create(cn, object);
diff --git a/qtbase/src/gui/configure.json b/qtbase/src/gui/configure.json
index 1f08795c57..12c95742d2 100644
--- a/qtbase/src/gui/configure.json
+++ b/qtbase/src/gui/configure.json
@@ -834,7 +834,8 @@
                     "// embedded devices, are not intended to be used together with X. EGL support",
                     "// has to be disabled in plugins like xcb in this case since the native display,",
                     "// window and pixmap types will be different than what an X-based platform",
-                    "// plugin would expect."
+                    "// plugin would expect.",
+                    "#define USE_X11"
                 ],
                 "include": [ "EGL/egl.h", "X11/Xlib.h" ],
                 "main": [
diff --git a/qtbase/src/gui/image/qbmphandler.cpp b/qtbase/src/gui/image/qbmphandler.cpp
index 96f1e8cb1d..0e73bbbdb0 100644
--- a/qtbase/src/gui/image/qbmphandler.cpp
+++ b/qtbase/src/gui/image/qbmphandler.cpp
@@ -150,16 +150,42 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
     return s;
 }
 
-static int calc_shift(uint mask)
+static uint calc_shift(uint mask)
 {
-    int result = 0;
-    while (mask && !(mask & 1)) {
+    uint result = 0;
+    while ((mask >= 0x100) || (!(mask & 1) && mask)) {
         result++;
         mask >>= 1;
     }
     return result;
 }
 
+static uint calc_scale(uint low_mask)
+{
+    uint result = 8;
+    while (low_mask && result) {
+        result--;
+        low_mask >>= 1;
+    }
+    return result;
+}
+
+static inline uint apply_scale(uint value, uint scale)
+{
+    if (!(scale & 0x07)) // return immediately if scale == 8 or 0
+        return value;
+
+    uint filled = 8 - scale;
+    uint result = value << scale;
+
+    do {
+        result |= result >> filled;
+        filled <<= 1;
+    } while (filled < 8);
+
+    return result;
+}
+
 static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf)
 {
     // read BMP file header
@@ -222,14 +248,14 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
     uint green_mask = 0;
     uint blue_mask = 0;
     uint alpha_mask = 0;
-    int red_shift = 0;
-    int green_shift = 0;
-    int blue_shift = 0;
-    int alpha_shift = 0;
-    int red_scale = 0;
-    int green_scale = 0;
-    int blue_scale = 0;
-    int alpha_scale = 0;
+    uint red_shift = 0;
+    uint green_shift = 0;
+    uint blue_shift = 0;
+    uint alpha_shift = 0;
+    uint red_scale = 0;
+    uint green_scale = 0;
+    uint blue_scale = 0;
+    uint alpha_scale = 0;
 
     if (!d->isSequential())
         d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap or masks
@@ -308,19 +334,19 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
         red_shift = calc_shift(red_mask);
         if (((red_mask >> red_shift) + 1) == 0)
             return false;
-        red_scale = 256 / ((red_mask >> red_shift) + 1);
+        red_scale = calc_scale(red_mask >> red_shift);
         green_shift = calc_shift(green_mask);
         if (((green_mask >> green_shift) + 1) == 0)
             return false;
-        green_scale = 256 / ((green_mask >> green_shift) + 1);
+        green_scale = calc_scale(green_mask >> green_shift);
         blue_shift = calc_shift(blue_mask);
         if (((blue_mask >> blue_shift) + 1) == 0)
             return false;
-        blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
+        blue_scale = calc_scale(blue_mask >> blue_shift);
         alpha_shift = calc_shift(alpha_mask);
         if (((alpha_mask >> alpha_shift) + 1) == 0)
             return false;
-        alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
+        alpha_scale = calc_scale(alpha_mask >> alpha_shift);
     } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
         blue_mask = 0x000000ff;
         green_mask = 0x0000ff00;
@@ -328,17 +354,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
         blue_shift = 0;
         green_shift = 8;
         red_shift = 16;
-        blue_scale = green_scale = red_scale = 1;
+        blue_scale = green_scale = red_scale = 0;
     } else if (comp == BMP_RGB && nbits == 16) {
         blue_mask = 0x001f;
         green_mask = 0x03e0;
         red_mask = 0x7c00;
         blue_shift = 0;
-        green_shift = 2;
-        red_shift = 7;
-        red_scale = 1;
-        green_scale = 1;
-        blue_scale = 8;
+        green_shift = 5;
+        red_shift = 10;
+        blue_scale = green_scale = red_scale = 3;
     }
 
 #if 0
@@ -544,10 +568,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
                     c |= *(uchar*)(b+2)<<16;
                 if (nbits > 24)
                     c |= *(uchar*)(b+3)<<24;
-                *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale,
-                                        ((c & green_mask) >> green_shift) * green_scale,
-                                        ((c & blue_mask) >> blue_shift) * blue_scale,
-                                        transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff);
+                *p++ = qRgba(apply_scale((c & red_mask) >> red_shift, red_scale),
+                             apply_scale((c & green_mask) >> green_shift, green_scale),
+                             apply_scale((c & blue_mask) >> blue_shift, blue_scale),
+                             transp ? apply_scale((c & alpha_mask) >> alpha_shift, alpha_scale) : 0xff);
                 b += nbits/8;
             }
         }
diff --git a/qtbase/src/gui/image/qimage.cpp b/qtbase/src/gui/image/qimage.cpp
index 7152ac1607..0df772564c 100644
--- a/qtbase/src/gui/image/qimage.cpp
+++ b/qtbase/src/gui/image/qimage.cpp
@@ -4694,6 +4694,8 @@ QImage QImage::smoothScaled(int w, int h) const {
 static QImage rotated90(const QImage &image)
 {
     QImage out(image.height(), image.width(), image.format());
+    if (out.isNull())
+        return out;
     copyMetadata(&out, image);
     if (image.colorCount() > 0)
         out.setColorTable(image.colorTable());
@@ -4722,6 +4724,8 @@ static QImage rotated180(const QImage &image)
         return image.mirrored(true, true);
 
     QImage out(image.width(), image.height(), image.format());
+    if (out.isNull())
+        return out;
     copyMetadata(&out, image);
     if (image.colorCount() > 0)
         out.setColorTable(image.colorTable());
@@ -4734,6 +4738,8 @@ static QImage rotated180(const QImage &image)
 static QImage rotated270(const QImage &image)
 {
     QImage out(image.height(), image.width(), image.format());
+    if (out.isNull())
+        return out;
     copyMetadata(&out, image);
     if (image.colorCount() > 0)
         out.setColorTable(image.colorTable());
diff --git a/qtbase/src/gui/kernel/qcursor.cpp b/qtbase/src/gui/kernel/qcursor.cpp
index d6ccaff8ed..455088241c 100644
--- a/qtbase/src/gui/kernel/qcursor.cpp
+++ b/qtbase/src/gui/kernel/qcursor.cpp
@@ -251,7 +251,8 @@ void QCursor::setPos(QScreen *screen, int x, int y)
 {
     if (screen) {
         if (QPlatformCursor *cursor = screen->handle()->cursor()) {
-            const QPoint devicePos = QHighDpi::toNativePixels(QPoint(x, y), screen);
+            const QPoint pos(x, y);
+            const QPoint devicePos = QHighDpi::toNativePixels(pos, screen->virtualSiblingAt(pos));
             // Need to check, since some X servers generate null mouse move
             // events, causing looping in applications which call setPos() on
             // every mouse move event.
diff --git a/qtbase/src/gui/kernel/qhighdpiscaling.cpp b/qtbase/src/gui/kernel/qhighdpiscaling.cpp
index 9bbf2773a9..3ac4a4d8b6 100644
--- a/qtbase/src/gui/kernel/qhighdpiscaling.cpp
+++ b/qtbase/src/gui/kernel/qhighdpiscaling.cpp
@@ -580,9 +580,8 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
     else
         qNamedScreenScaleFactors()->insert(name, factor);
 
-    // hack to force re-evaluation of screen geometry
     if (screen->handle())
-        screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor
+        screen->d_func()->updateLogicalDpi();
 }
 
 QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen)
diff --git a/qtbase/src/gui/kernel/qkeysequence.cpp b/qtbase/src/gui/kernel/qkeysequence.cpp
index a75b8ef920..4f2d294739 100644
--- a/qtbase/src/gui/kernel/qkeysequence.cpp
+++ b/qtbase/src/gui/kernel/qkeysequence.cpp
@@ -701,6 +701,10 @@ static const struct {
     { Qt::Key_TouchpadToggle,  QT_TRANSLATE_NOOP("QShortcut", "Touchpad Toggle") },
     { Qt::Key_TouchpadOn,  QT_TRANSLATE_NOOP("QShortcut", "Touchpad On") },
     { Qt::Key_TouchpadOff,  QT_TRANSLATE_NOOP("QShortcut", "Touchpad Off") },
+    { Qt::Key_Shift,  QT_TRANSLATE_NOOP("QShortcut", "Shift") },
+    { Qt::Key_Control,  QT_TRANSLATE_NOOP("QShortcut", "Control") },
+    { Qt::Key_Alt,  QT_TRANSLATE_NOOP("QShortcut", "Alt") },
+    { Qt::Key_Meta,  QT_TRANSLATE_NOOP("QShortcut", "Meta") },
 
 };
 static Q_CONSTEXPR int numKeyNames = sizeof keyname / sizeof *keyname;
diff --git a/qtbase/src/gui/kernel/qplatformservices.cpp b/qtbase/src/gui/kernel/qplatformservices.cpp
index fdc6a6c4aa..ac47f98c5d 100644
--- a/qtbase/src/gui/kernel/qplatformservices.cpp
+++ b/qtbase/src/gui/kernel/qplatformservices.cpp
@@ -55,6 +55,19 @@ QT_BEGIN_NAMESPACE
     \brief The QPlatformServices provides the backend for desktop-related functionality.
 */
 
+/*!
+    \enum QPlatformServices::Capability
+
+    Capabilities are used to determine a specific platform service's availability.
+
+    \value ColorPickingFromScreen The platform natively supports color picking from screen.
+    This capability indicates that the platform supports "opaque" color picking, where the
+    platform implements a complete user experience for color picking and outputs a color.
+    This is in contrast to the application implementing the color picking user experience
+    (taking care of showing a cross hair, instructing the platform integration to obtain
+    the color at a given pixel, etc.). The related service function is pickColor().
+ */
+
 QPlatformServices::QPlatformServices()
 { }
 
@@ -85,5 +98,16 @@ QByteArray QPlatformServices::desktopEnvironment() const
     return QByteArray("UNKNOWN");
 }
 
+QPlatformServiceColorPicker *QPlatformServices::colorPicker(QWindow *parent)
+{
+    Q_UNUSED(parent);
+    return nullptr;
+}
+
+bool QPlatformServices::hasCapability(Capability capability) const
+{
+    Q_UNUSED(capability)
+    return false;
+}
 
 QT_END_NAMESPACE
diff --git a/qtbase/src/gui/kernel/qplatformservices.h b/qtbase/src/gui/kernel/qplatformservices.h
index 5de96cfa7d..a8b2a4ce71 100644
--- a/qtbase/src/gui/kernel/qplatformservices.h
+++ b/qtbase/src/gui/kernel/qplatformservices.h
@@ -50,16 +50,32 @@
 //
 
 #include <QtGui/qtguiglobal.h>
+#include <QtCore/qobject.h>
 
 QT_BEGIN_NAMESPACE
 
 class QUrl;
+class QWindow;
+
+class Q_GUI_EXPORT QPlatformServiceColorPicker : public QObject
+{
+    Q_OBJECT
+public:
+    using QObject::QObject;
+    virtual void pickColor() = 0;
+Q_SIGNALS:
+    void colorPicked(const QColor &color);
+};
 
 class Q_GUI_EXPORT QPlatformServices
 {
 public:
     Q_DISABLE_COPY_MOVE(QPlatformServices)
 
+    enum Capability {
+        ColorPicking,
+    };
+
     QPlatformServices();
     virtual ~QPlatformServices() { }
 
@@ -67,6 +83,10 @@ public:
     virtual bool openDocument(const QUrl &url);
 
     virtual QByteArray desktopEnvironment() const;
+
+    virtual bool hasCapability(Capability capability) const;
+
+    virtual QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr);
 };
 
 QT_END_NAMESPACE
diff --git a/qtbase/src/gui/kernel/qplatformtheme.cpp b/qtbase/src/gui/kernel/qplatformtheme.cpp
index 71521c0339..2325873245 100644
--- a/qtbase/src/gui/kernel/qplatformtheme.cpp
+++ b/qtbase/src/gui/kernel/qplatformtheme.cpp
@@ -163,6 +163,8 @@ QT_BEGIN_NAMESPACE
 
     \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.
 
+    \value ButtonPressKeys (QList<Qt::Key>) A list of keys that can be used to press buttons via keyboard input.
+
     \sa themeHint(), QStyle::pixelMetric()
 */
 
@@ -563,6 +565,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
         }
     case MouseQuickSelectionThreshold:
         return QVariant(10);
+    case ButtonPressKeys:
+        return QVariant::fromValue(QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Select }));
     }
     return QVariant();
 }
diff --git a/qtbase/src/gui/kernel/qplatformtheme.h b/qtbase/src/gui/kernel/qplatformtheme.h
index 3185fc4541..7e6c9d5740 100644
--- a/qtbase/src/gui/kernel/qplatformtheme.h
+++ b/qtbase/src/gui/kernel/qplatformtheme.h
@@ -120,7 +120,8 @@ public:
         TouchDoubleTapDistance,
         ShowShortcutsInContextMenus,
         IconFallbackSearchPaths,
-        MouseQuickSelectionThreshold
+        MouseQuickSelectionThreshold,
+        ButtonPressKeys
     };
 
     enum DialogType {
diff --git a/qtbase/src/gui/kernel/qscreen.cpp b/qtbase/src/gui/kernel/qscreen.cpp
index 8e0eb35116..5d172a58dd 100644
--- a/qtbase/src/gui/kernel/qscreen.cpp
+++ b/qtbase/src/gui/kernel/qscreen.cpp
@@ -77,6 +77,12 @@ QScreen::QScreen(QPlatformScreen *screen)
     d->setPlatformScreen(screen);
 }
 
+void QScreenPrivate::updateLogicalDpi()
+{
+    logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
+    updateGeometriesWithSignals(); // updates geometries based on scale factor
+}
+
 void QScreenPrivate::updateGeometriesWithSignals()
 {
     const QRect oldGeometry = geometry;
diff --git a/qtbase/src/gui/kernel/qscreen_p.h b/qtbase/src/gui/kernel/qscreen_p.h
index 7da542c25e..e50fc3190b 100644
--- a/qtbase/src/gui/kernel/qscreen_p.h
+++ b/qtbase/src/gui/kernel/qscreen_p.h
@@ -70,6 +70,7 @@ public:
         geometry = platformScreen->deviceIndependentGeometry();
         availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft());
     }
+    void updateLogicalDpi();
 
     void updatePrimaryOrientation();
     void updateGeometriesWithSignals();
diff --git a/qtbase/src/gui/painting/qblendfunctions_p.h b/qtbase/src/gui/painting/qblendfunctions_p.h
index 080da98ec4..6997d62b3c 100644
--- a/qtbase/src/gui/painting/qblendfunctions_p.h
+++ b/qtbase/src/gui/painting/qblendfunctions_p.h
@@ -246,25 +246,32 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
                                   int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
                                   Blender blender)
 {
-    int fromY = qMax(qRound(topY), clip.top());
-    int toY = qMin(qRound(bottomY), clip.top() + clip.height());
+    qint64 fromY = qMax(qRound(topY), clip.top());
+    qint64 toY = qMin(qRound(bottomY), clip.top() + clip.height());
     if (fromY >= toY)
         return;
 
     qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
     qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
-    int dx_l = int(leftSlope * 0x10000);
-    int dx_r = int(rightSlope * 0x10000);
-    int x_l = int((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
-    int x_r = int((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
-
-    int fromX, toX, x1, x2, u, v, i, ii;
+    qint64 dx_l = qint64(leftSlope * 0x10000);
+    qint64 dx_r = qint64(rightSlope * 0x10000);
+    qint64 x_l = qint64((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
+    qint64 x_r = qint64((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
+
+    qint64 sourceRectTop = qint64(sourceRect.top());
+    qint64 sourceRectLeft = qint64(sourceRect.left());
+    qint64 sourceRectWidth = qint64(sourceRect.width());
+    qint64 sourceRectHeight = qint64(sourceRect.height());
+    qint64 clipLeft = qint64(clip.left());
+    qint64 clipWidth = qint64(clip.width());
+
+    qint64 fromX, toX, x1, x2, u, v, i, ii;
     DestT *line;
-    for (int y = fromY; y < toY; ++y) {
+    for (qint64 y = fromY; y < toY; ++y) {
         line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
 
-        fromX = qMax(x_l >> 16, clip.left());
-        toX = qMin(x_r >> 16, clip.left() + clip.width());
+        fromX = qMax(x_l >> 16, clipLeft);
+        toX = qMin(x_r >> 16, clipLeft + clipWidth);
         if (fromX < toX) {
             // Because of rounding, we can get source coordinates outside the source image.
             // Clamp these coordinates to the source rect to avoid segmentation fault and
@@ -275,10 +282,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
             u = x1 * dudx + y * dudy + u0;
             v = x1 * dvdx + y * dvdy + v0;
             for (; x1 < toX; ++x1) {
-                int uu = u >> 16;
-                int vv = v >> 16;
-                if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
-                    && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+                qint64 uu = u >> 16;
+                qint64 vv = v >> 16;
+                if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
+                    && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
                     break;
                 }
                 u += dudx;
@@ -290,10 +297,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
             u = (x2 - 1) * dudx + y * dudy + u0;
             v = (x2 - 1) * dvdx + y * dvdy + v0;
             for (; x2 > x1; --x2) {
-                int uu = u >> 16;
-                int vv = v >> 16;
-                if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
-                    && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+                qint64 uu = u >> 16;
+                qint64 vv = v >> 16;
+                if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
+                    && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
                     break;
                 }
                 u -= dudx;
@@ -308,8 +315,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
             // Beginning of the scan line, with per-pixel checks.
             i = x1 - fromX;
             while (i) {
-                int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
-                int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+                qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
+                qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
                 blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
                 u += dudx;
                 v += dvdx;
@@ -348,8 +355,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
             // End of the scan line, with per-pixel checks.
             i = toX - x2;
             while (i) {
-                int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
-                int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+                qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
+                qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
                 blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
                 u += dudx;
                 v += dvdx;
diff --git a/qtbase/src/gui/painting/qcolortrclut_p.h b/qtbase/src/gui/painting/qcolortrclut_p.h
index 76a6a60803..24fd522e6c 100644
--- a/qtbase/src/gui/painting/qcolortrclut_p.h
+++ b/qtbase/src/gui/painting/qcolortrclut_p.h
@@ -118,6 +118,7 @@ public:
         return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257);
 #endif
     }
+    QRgba64 toLinear64(QRgba64) const = delete;
 
     QRgb toLinear(QRgb rgb32) const
     {
diff --git a/qtbase/src/gui/painting/qdrawhelper.cpp b/qtbase/src/gui/painting/qdrawhelper.cpp
index a61793508a..5ba2d277b7 100644
--- a/qtbase/src/gui/painting/qdrawhelper.cpp
+++ b/qtbase/src/gui/painting/qdrawhelper.cpp
@@ -6091,7 +6091,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
 static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile)
 {
     // Do a gammacorrected RGB alphablend...
-    const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst;
+    const QRgba64 dlinear = colorProfile ? colorProfile->toLinear(dst) : dst;
 
     QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
 
diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp
index 283923de52..f08eb9cbee 100644
--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp
+++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp
@@ -560,31 +560,6 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
     QRasterPaintEngineState *s = state();
     // FALCON: get rid of this line, see drawImage call below.
     s->matrix = matrix;
-    QTransform::TransformationType txop = s->matrix.type();
-
-    switch (txop) {
-
-    case QTransform::TxNone:
-        s->flags.int_xform = true;
-        break;
-
-    case QTransform::TxTranslate:
-        s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
-                            && qreal(int(s->matrix.dy())) == s->matrix.dy();
-        break;
-
-    case QTransform::TxScale:
-        s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
-                            && qreal(int(s->matrix.dy())) == s->matrix.dy()
-                            && qreal(int(s->matrix.m11())) == s->matrix.m11()
-                            && qreal(int(s->matrix.m22())) == s->matrix.m22();
-        break;
-
-    default: // shear / perspective...
-        s->flags.int_xform = false;
-        break;
-    }
-
     s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale);
 
     ensureOutlineMapper();
@@ -617,7 +592,6 @@ QRasterPaintEngineState::QRasterPaintEngineState()
     flags.bilinear = false;
     flags.legacy_rounding = false;
     flags.fast_text = true;
-    flags.int_xform = true;
     flags.tx_noshear = true;
     flags.fast_images = true;
 
@@ -1793,7 +1767,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
     QRectF cpRect = path.controlPointRect();
     const QRectF pathDeviceRect = s->matrix.mapRect(cpRect);
     // Skip paths that by conservative estimates are completely outside the paint device.
-    if (!pathDeviceRect.intersects(QRectF(d->deviceRect)))
+    if (!pathDeviceRect.intersects(QRectF(d->deviceRect)) || !pathDeviceRect.isValid())
         return;
 
     ProcessSpans blend = d->getBrushFunc(pathDeviceRect, &s->brushData);
diff --git a/qtbase/src/gui/painting/qpaintengine_raster_p.h b/qtbase/src/gui/painting/qpaintengine_raster_p.h
index 089aadc3f7..bf7363d5aa 100644
--- a/qtbase/src/gui/painting/qpaintengine_raster_p.h
+++ b/qtbase/src/gui/painting/qpaintengine_raster_p.h
@@ -111,7 +111,6 @@ public:
         uint bilinear : 1;
         uint legacy_rounding : 1;
         uint fast_text : 1;
-        uint int_xform : 1;
         uint tx_noshear : 1;
         uint fast_images : 1;
     };
diff --git a/qtbase/src/gui/painting/qpainterpath.cpp b/qtbase/src/gui/painting/qpainterpath.cpp
index f9544a3241..d80fafeaf1 100644
--- a/qtbase/src/gui/painting/qpainterpath.cpp
+++ b/qtbase/src/gui/painting/qpainterpath.cpp
@@ -1253,7 +1253,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
 
         if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
             QGlyphLayout glyphs = eng->shapedGlyphs(&si);
-            QFontEngine *fe = f.d->engineForScript(si.analysis.script);
+            QFontEngine *fe = eng->fontEngine(si);
             Q_ASSERT(fe);
             fe->addOutlineToPath(x, y, glyphs, this,
                                  si.analysis.bidiLevel % 2
diff --git a/qtbase/src/gui/painting/qpathclipper_p.h b/qtbase/src/gui/painting/qpathclipper_p.h
index 9444a87b71..18f64c5e8c 100644
--- a/qtbase/src/gui/painting/qpathclipper_p.h
+++ b/qtbase/src/gui/painting/qpathclipper_p.h
@@ -156,7 +156,7 @@ public:
     int vertex(Direction direction) const;
 
 private:
-    int m_next[2][2];
+    int m_next[2][2] = { { -1, -1 }, { -1, -1 } };
 };
 
 class QPathSegments
@@ -296,10 +296,6 @@ inline QPathEdge::QPathEdge(int a, int b)
     , angle(0)
     , invAngle(0)
 {
-    m_next[0][0] = -1;
-    m_next[1][0] = -1;
-    m_next[0][0] = -1;
-    m_next[1][0] = -1;
 }
 
 inline int QPathEdge::next(Traversal traversal, Direction direction) const
diff --git a/qtbase/src/gui/painting/qpdf.cpp b/qtbase/src/gui/painting/qpdf.cpp
index 3066744f1b..2c8d3c3b53 100644
--- a/qtbase/src/gui/painting/qpdf.cpp
+++ b/qtbase/src/gui/painting/qpdf.cpp
@@ -2760,6 +2760,8 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
         return gradientBrush(brush, matrix, gStateObject);
     }
 
+    matrix = brush.transform() * matrix;
+
     if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
         *gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity),
                                                qRound(pen.color().alpha() * opacity));
diff --git a/qtbase/src/gui/painting/qstroker.cpp b/qtbase/src/gui/painting/qstroker.cpp
index cb5d395e80..3b6357a893 100644
--- a/qtbase/src/gui/painting/qstroker.cpp
+++ b/qtbase/src/gui/painting/qstroker.cpp
@@ -1182,6 +1182,7 @@ void QDashStroker::processCurrentSubpath()
         // Check if the entire line should be clipped away or simplified
         bool clipIt = clipping && !lineIntersectsRect(prev, e, clip_tl, clip_br);
         bool skipDashing = elen * invSumLength > repetitionLimit();
+        int maxDashes = dashCount;
         if (skipDashing || clipIt) {
             // Cut away full dash sequences.
             elen -= std::floor(elen * invSumLength) * sumLength;
@@ -1196,7 +1197,7 @@ void QDashStroker::processCurrentSubpath()
                     pos = estop; // move pos to next path element
                     done = true;
                 } else { // Dash is on this line
-                    pos = dpos + estart;
+                    pos = --maxDashes > 0 ? dpos + estart : estop;
                     done = pos >= estop;
                     if (++idash >= dashCount)
                         idash = 0;
diff --git a/qtbase/src/gui/painting/qt_attribution.json b/qtbase/src/gui/painting/qt_attribution.json
index 7b16e8c211..0e87d30aa2 100644
--- a/qtbase/src/gui/painting/qt_attribution.json
+++ b/qtbase/src/gui/painting/qt_attribution.json
@@ -10,7 +10,7 @@
         "Homepage": "http://www.freetype.org",
         "License": "Freetype Project License or GNU General Public License v2.0 only",
         "LicenseId": "FTL or GPL-2.0",
-        "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT",
+        "LicenseFile": "../../3rdparty/freetype/LICENSE.TXT",
         "Copyright": "Copyright 2000-2016 by David Turner, Robert Wilhelm, and Werner Lemberg."
     },
     {
diff --git a/qtbase/src/gui/rhi/qshader_p_p.h b/qtbase/src/gui/rhi/qshader_p_p.h
index ec9d25971f..4a5a7a6d51 100644
--- a/qtbase/src/gui/rhi/qshader_p_p.h
+++ b/qtbase/src/gui/rhi/qshader_p_p.h
@@ -68,13 +68,13 @@ struct Q_GUI_EXPORT QShaderPrivate
     {
     }
 
-    QShaderPrivate(const QShaderPrivate *other)
+    QShaderPrivate(const QShaderPrivate &other)
         : ref(1),
-          qsbVersion(other->qsbVersion),
-          stage(other->stage),
-          desc(other->desc),
-          shaders(other->shaders),
-          bindings(other->bindings)
+          qsbVersion(other.qsbVersion),
+          stage(other.stage),
+          desc(other.desc),
+          shaders(other.shaders),
+          bindings(other.bindings)
     {
     }
 
diff --git a/qtbase/src/gui/rhi/qshaderdescription_p_p.h b/qtbase/src/gui/rhi/qshaderdescription_p_p.h
index ec2b0b6b4c..3da33a8a2b 100644
--- a/qtbase/src/gui/rhi/qshaderdescription_p_p.h
+++ b/qtbase/src/gui/rhi/qshaderdescription_p_p.h
@@ -63,16 +63,16 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
         localSize[0] = localSize[1] = localSize[2] = 0;
     }
 
-    QShaderDescriptionPrivate(const QShaderDescriptionPrivate *other)
+    QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other)
         : ref(1),
-          inVars(other->inVars),
-          outVars(other->outVars),
-          uniformBlocks(other->uniformBlocks),
-          pushConstantBlocks(other->pushConstantBlocks),
-          storageBlocks(other->storageBlocks),
-          combinedImageSamplers(other->combinedImageSamplers),
-          storageImages(other->storageImages),
-          localSize(other->localSize)
+          inVars(other.inVars),
+          outVars(other.outVars),
+          uniformBlocks(other.uniformBlocks),
+          pushConstantBlocks(other.pushConstantBlocks),
+          storageBlocks(other.storageBlocks),
+          combinedImageSamplers(other.combinedImageSamplers),
+          storageImages(other.storageImages),
+          localSize(other.localSize)
     {
     }
 
diff --git a/qtbase/src/gui/text/qfontdatabase.cpp b/qtbase/src/gui/text/qfontdatabase.cpp
index a657a8c516..4fc0100958 100644
--- a/qtbase/src/gui/text/qfontdatabase.cpp
+++ b/qtbase/src/gui/text/qfontdatabase.cpp
@@ -983,7 +983,7 @@ QFontEngine *loadSingleEngine(int script,
         if (style->key.stretch != 0 && request.stretch != 0
             && (request.styleName.isEmpty() || request.styleName != style->styleName)) {
             def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch;
-        } else {
+        } else if (request.stretch == QFont::AnyStretch) {
             def.stretch = 100;
         }
 
diff --git a/qtbase/src/gui/text/qtextdocumentlayout.cpp b/qtbase/src/gui/text/qtextdocumentlayout.cpp
index f3e6ea2100..72267e9380 100644
--- a/qtbase/src/gui/text/qtextdocumentlayout.cpp
+++ b/qtbase/src/gui/text/qtextdocumentlayout.cpp
@@ -2123,7 +2123,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
 {
     Q_Q(const QTextDocumentLayout);
     const QTextBlockFormat blockFormat = bl.blockFormat();
-    const QTextCharFormat charFormat = QTextCursor(bl).charFormat();
+    const QTextCharFormat charFormat = bl.charFormat();
     QFont font(charFormat.font());
     if (q->paintDevice())
         font = QFont(font, q->paintDevice());
diff --git a/qtbase/src/gui/text/qtextengine.cpp b/qtbase/src/gui/text/qtextengine.cpp
index ce4abac472..a6c66e5d2d 100644
--- a/qtbase/src/gui/text/qtextengine.cpp
+++ b/qtbase/src/gui/text/qtextengine.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtGui module of the Qt Toolkit.
@@ -1565,6 +1565,12 @@ void QTextEngine::shapeText(int item) const
         // Overwrite with 0 token to indicate failure
         QGlyphLayout g = availableGlyphs(&si);
         g.glyphs[0] = 0;
+        g.attributes[0].clusterStart = true;
+
+        ushort *log_clusters = logClusters(&si);
+        for (int i = 0; i < itemLength; ++i)
+            log_clusters[i] = 0;
+
         return;
     }
 
diff --git a/qtbase/src/gui/util/qdesktopservices.cpp b/qtbase/src/gui/util/qdesktopservices.cpp
index fbb63a9408..4d5fafaaa7 100644
--- a/qtbase/src/gui/util/qdesktopservices.cpp
+++ b/qtbase/src/gui/util/qdesktopservices.cpp
@@ -54,6 +54,8 @@
 #include <qpa/qplatformintegration.h>
 #include <qdir.h>
 
+#include <QtCore/private/qlocking_p.h>
+
 QT_BEGIN_NAMESPACE
 
 class QOpenUrlHandlerRegistry : public QObject
@@ -81,6 +83,7 @@ Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry)
 
 void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
 {
+    const auto lock = qt_scoped_lock(mutex);
     HandlerHash::Iterator it = handlers.begin();
     while (it != handlers.end()) {
         if (it->receiver == handler) {
@@ -294,7 +297,8 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c
     h.name = method;
     registry->handlers.insert(scheme.toLower(), h);
     QObject::connect(receiver, SIGNAL(destroyed(QObject*)),
-                     registry, SLOT(handlerDestroyed(QObject*)));
+                     registry, SLOT(handlerDestroyed(QObject*)),
+                     Qt::DirectConnection);
 }
 
 /*!
diff --git a/qtbase/src/gui/util/qpkmhandler.cpp b/qtbase/src/gui/util/qpkmhandler.cpp
index e0c3b75efe..3414f9d8ba 100644
--- a/qtbase/src/gui/util/qpkmhandler.cpp
+++ b/qtbase/src/gui/util/qpkmhandler.cpp
@@ -57,7 +57,7 @@ struct PkmType
     quint32 bytesPerBlock;
 };
 
-static PkmType typeMap[5] = {
+static constexpr PkmType typeMap[5] = {
     { 0x8D64,  8 },   // GL_ETC1_RGB8_OES
     { 0x9274,  8 },   // GL_COMPRESSED_RGB8_ETC2
     { 0, 0 },         // unused (obsolete)
diff --git a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
index b6be93147a..6e69b4c4d3 100644
--- a/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/qtbase/src/network/access/qnetworkreplyfileimpl.cpp
@@ -89,9 +89,10 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
         // we handle only local files
         QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString());
         setError(QNetworkReply::ProtocolInvalidOperationError, msg);
+        setFinished(true); // We're finished, will emit finished() after ctor is done.
         QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
             Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
-        fileOpenFinished(false);
+        QMetaObject::invokeMethod(this, [this](){ fileOpenFinished(false); }, Qt::QueuedConnection);
         return;
     }
 #endif
diff --git a/qtbase/src/network/access/qnetworkreplyimpl.cpp b/qtbase/src/network/access/qnetworkreplyimpl.cpp
index bcdf6ee2f1..3b6deb82bd 100644
--- a/qtbase/src/network/access/qnetworkreplyimpl.cpp
+++ b/qtbase/src/network/access/qnetworkreplyimpl.cpp
@@ -680,7 +680,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data)
     // read until EOF from data
     if (Q_UNLIKELY(copyDevice)) {
         qCritical("QNetworkReplyImpl: copy from QIODevice already in progress -- "
-                  "backend probly needs to be fixed");
+                  "backend probably needs to be fixed");
         return;
     }
 
diff --git a/qtbase/src/network/kernel/qauthenticator.cpp b/qtbase/src/network/kernel/qauthenticator.cpp
index d9fe7bc47b..ccd04b294a 100644
--- a/qtbase/src/network/kernel/qauthenticator.cpp
+++ b/qtbase/src/network/kernel/qauthenticator.cpp
@@ -50,6 +50,7 @@
 #include <qstring.h>
 #include <qdatetime.h>
 #include <qrandom.h>
+#include "private/qsystemlibrary_p.h"
 
 #ifdef Q_OS_WIN
 #include <qmutex.h>
@@ -1563,7 +1564,7 @@ static bool q_SSPI_library_load()
 
     // Initialize security interface
     if (pSecurityFunctionTable == nullptr) {
-        securityDLLHandle = LoadLibrary(L"secur32.dll");
+        securityDLLHandle = QSystemLibrary::load(L"secur32");
         if (securityDLLHandle != nullptr) {
             INIT_SECURITY_INTERFACE pInitSecurityInterface =
                 reinterpret_cast<INIT_SECURITY_INTERFACE>(
diff --git a/qtbase/src/network/kernel/qhostinfo_unix.cpp b/qtbase/src/network/kernel/qhostinfo_unix.cpp
index 9b0a2ee669..73679c9ef1 100644
--- a/qtbase/src/network/kernel/qhostinfo_unix.cpp
+++ b/qtbase/src/network/kernel/qhostinfo_unix.cpp
@@ -122,7 +122,6 @@ static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym)
 
 LibResolv::LibResolv()
 {
-    QLibrary lib;
 #ifdef LIBRESOLV_SO
     lib.setFileName(QStringLiteral(LIBRESOLV_SO));
     if (!lib.load())
diff --git a/qtbase/src/network/socket/qsocks5socketengine.cpp b/qtbase/src/network/socket/qsocks5socketengine.cpp
index 3a046fd116..97fadca0b3 100644
--- a/qtbase/src/network/socket/qsocks5socketengine.cpp
+++ b/qtbase/src/network/socket/qsocks5socketengine.cpp
@@ -1296,7 +1296,7 @@ void QSocks5SocketEnginePrivate::_q_udpSocketReadNotification()
         int pos = 0;
         const char *buf = inBuf.constData();
         if (inBuf.size() < 4) {
-            QSOCKS5_D_DEBUG << "bugus udp data, discarding";
+            QSOCKS5_D_DEBUG << "bogus udp data, discarding";
             return;
         }
         QSocks5RevivedDatagram datagram;
diff --git a/qtbase/src/network/ssl/qsslcontext_openssl.cpp b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
index c9f202f573..c992da9d8e 100644
--- a/qtbase/src/network/ssl/qsslcontext_openssl.cpp
+++ b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
@@ -409,7 +409,7 @@ init_context:
         break;
     case QSsl::DtlsV1_0OrLater:
         minVersion = DTLS1_VERSION;
-        maxVersion = DTLS_MAX_VERSION;
+        maxVersion = 0;
         break;
     case QSsl::DtlsV1_2:
         minVersion = DTLS1_2_VERSION;
@@ -417,7 +417,7 @@ init_context:
         break;
     case QSsl::DtlsV1_2OrLater:
         minVersion = DTLS1_2_VERSION;
-        maxVersion = DTLS_MAX_VERSION;
+        maxVersion = 0;
         break;
     case QSsl::TlsV1_3OrLater:
 #ifdef TLS1_3_VERSION
@@ -455,7 +455,7 @@ init_context:
     }
 
     // Enable bug workarounds.
-    long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+    qssloptions options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
     q_SSL_CTX_set_options(sslContext->ctx, options);
 
     // Tell OpenSSL to release memory early
diff --git a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
index aaf8741130..b58935372c 100644
--- a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+++ b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
@@ -59,57 +59,6 @@
 
 QT_BEGIN_NAMESPACE
 
-#ifdef OPENSSL_NO_DEPRECATED_3_0
-
-static int q_DH_check(DH *dh, int *status)
-{
-    // DH_check was first deprecated in OpenSSL 3.0.0, as low-level
-    // API; the EVP_PKEY family of functions was advised as an alternative.
-    // As of now EVP_PKEY_params_check ends up calling ... DH_check,
-    // which is good enough.
-
-    Q_ASSERT(dh);
-    Q_ASSERT(status);
-
-    EVP_PKEY *key = q_EVP_PKEY_new();
-    if (!key) {
-        qCWarning(lcSsl, "EVP_PKEY_new failed");
-        QSslSocketBackendPrivate::logAndClearErrorQueue();
-        return 0;
-    }
-    const auto keyDeleter = qScopeGuard([key](){
-        q_EVP_PKEY_free(key);
-    });
-    if (!q_EVP_PKEY_set1_DH(key, dh)) {
-        qCWarning(lcSsl, "EVP_PKEY_set1_DH failed");
-        QSslSocketBackendPrivate::logAndClearErrorQueue();
-        return 0;
-    }
-
-    EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr);
-    if (!keyCtx) {
-        qCWarning(lcSsl, "EVP_PKEY_CTX_new failed");
-        QSslSocketBackendPrivate::logAndClearErrorQueue();
-        return 0;
-    }
-    const auto ctxDeleter = qScopeGuard([keyCtx]{
-        q_EVP_PKEY_CTX_free(keyCtx);
-    });
-
-    const int result = q_EVP_PKEY_param_check(keyCtx);
-    QSslSocketBackendPrivate::logAndClearErrorQueue();
-    // Note: unlike DH_check, we cannot obtain the 'status',
-    // if the 'result' is 0 (actually the result is 1 only
-    // if this 'status' was 0). We could probably check the
-    // errors from the error queue, but it's not needed anyway
-    // - see the 'isSafeDH' below, how it returns immediately
-    // on 0.
-    Q_UNUSED(status)
-
-    return result;
-}
-#endif // OPENSSL_NO_DEPRECATED_3_0
-
 static bool isSafeDH(DH *dh)
 {
     int status = 0;
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl.cpp b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
index 37fad2a68f..8f6858c867 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
@@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe
 // Defined in qsslsocket.cpp
 void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers);
 
-long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
+qssloptions QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
 {
-    long options;
+    qssloptions options;
     if (protocol == QSsl::TlsV1SslV3)
         options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
     else if (protocol == QSsl::SecureProtocols)
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
index 4103de23e8..5547589256 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_p.h
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
@@ -107,6 +107,12 @@
 
 QT_BEGIN_NAMESPACE
 
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+typedef uint64_t qssloptions;
+#else
+typedef unsigned long qssloptions;
+#endif
+
 struct QSslErrorEntry {
     int code;
     int depth;
@@ -171,7 +177,7 @@ public:
     QVector<QSslError> ocspErrors;
     QByteArray ocspResponseDer;
 
-    Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+    Q_AUTOTEST_EXPORT static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
     static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
     static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
     static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
index e53fb279f0..459ccd0b19 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -148,7 +148,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return)
 DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return)
 DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return)
 DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return)
-DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
 DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
 DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
 DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
@@ -158,7 +157,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM
 DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
 DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return)
 DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
-DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
+DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return)
 DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return)
 DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return)
 #ifdef TLS1_3_VERSION
@@ -371,7 +370,15 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr
 DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
 DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
 DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return)
+
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return)
+DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return)
+#else
 DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return)
+DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
 DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
 DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return)
 DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return)
@@ -492,9 +499,7 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return)
 DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG)
 DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return)
 DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return)
-#ifndef OPENSSL_NO_DEPRECATED_3_0
 DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return)
-#endif // OPENSSL_NO_DEPRECATED_3_0
 DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return)
 
 #ifndef OPENSSL_NO_EC
@@ -868,7 +873,6 @@ bool q_resolveOpenSslSymbols()
     RESOLVEFUNC(EVP_PKEY_CTX_new)
     RESOLVEFUNC(EVP_PKEY_param_check)
     RESOLVEFUNC(EVP_PKEY_CTX_free)
-    RESOLVEFUNC(EVP_PKEY_base_id)
     RESOLVEFUNC(RSA_bits)
     RESOLVEFUNC(OPENSSL_sk_new_null)
     RESOLVEFUNC(OPENSSL_sk_push)
@@ -1107,7 +1111,15 @@ bool q_resolveOpenSslSymbols()
     RESOLVEFUNC(SSL_version)
     RESOLVEFUNC(SSL_get_error)
     RESOLVEFUNC(SSL_get_peer_cert_chain)
+
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+    RESOLVEFUNC(SSL_get1_peer_certificate)
+    RESOLVEFUNC(EVP_PKEY_get_base_id)
+#else
     RESOLVEFUNC(SSL_get_peer_certificate)
+    RESOLVEFUNC(EVP_PKEY_base_id)
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
     RESOLVEFUNC(SSL_get_verify_result)
     RESOLVEFUNC(SSL_new)
     RESOLVEFUNC(SSL_get_SSL_CTX)
@@ -1206,9 +1218,7 @@ bool q_resolveOpenSslSymbols()
     RESOLVEFUNC(DH_free)
     RESOLVEFUNC(d2i_DHparams)
     RESOLVEFUNC(i2d_DHparams)
-#ifndef OPENSSL_NO_DEPRECATED_3_0
     RESOLVEFUNC(DH_check)
-#endif // OPENSSL_NO_DEPRECATED_3_0
     RESOLVEFUNC(BN_bin2bn)
 
 #ifndef OPENSSL_NO_EC
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 95e8897a3b..27aeffa18a 100644
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -237,7 +237,6 @@ Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
 EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
 void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
-int q_EVP_PKEY_base_id(EVP_PKEY *a);
 int q_RSA_bits(RSA *a);
 Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
 Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
@@ -246,7 +245,7 @@ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
 Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
 Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
 int q_SSL_session_reused(SSL *a);
-unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
+qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op);
 int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
 size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
 size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
@@ -510,7 +509,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
 int q_SSL_version(const SSL *a);
 int q_SSL_get_error(SSL *a, int b);
 STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
-X509 *q_SSL_get_peer_certificate(SSL *a);
 long q_SSL_get_verify_result(const SSL *a);
 SSL *q_SSL_new(SSL_CTX *a);
 SSL_CTX *q_SSL_get_SSL_CTX(SSL *a);
@@ -582,10 +580,7 @@ DH *q_DH_new();
 void q_DH_free(DH *dh);
 DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length);
 int q_i2d_DHparams(DH *a, unsigned char **p);
-
-#ifndef OPENSSL_NO_DEPRECATED_3_0
 int q_DH_check(DH *dh, int *codes);
-#endif // OPENSSL_NO_DEPRECATED_3_0
 
 BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
 #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh)
@@ -754,6 +749,17 @@ void q_CRYPTO_free(void *str, const char *file, int line);
 int q_SSL_CTX_get_security_level(const SSL_CTX *ctx);
 void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
 
+// Here we have the ones that make difference between OpenSSL pre/post v3:
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+X509 *q_SSL_get1_peer_certificate(SSL *a);
+#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate
+int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey);
+#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id
+#else
+X509 *q_SSL_get_peer_certificate(SSL *a);
+int q_EVP_PKEY_base_id(EVP_PKEY *a);
+#endif // OPENSSL_VERSION_MAJOR >= 3
+
 QT_END_NAMESPACE
 
 #endif
diff --git a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
index bf37d07fd8..dbd42fb799 100644
--- a/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
+++ b/qtbase/src/platformsupport/eglconvenience/qt_egl_p.h
@@ -61,7 +61,11 @@
 # if !defined(Q_OS_INTEGRITY)
 #  define WIN_INTERFACE_CUSTOM   // NV
 # endif // Q_OS_INTEGRITY
-#endif  // QT_EGL_NO_X11
+#else // QT_EGL_NO_X11
+// If one has an eglplatform.h with https://github.com/KhronosGroup/EGL-Registry/pull/130
+// that needs USE_X11 to be defined.
+# define USE_X11
+#endif
 
 #ifdef QT_EGL_WAYLAND
 # define WAYLAND // NV
diff --git a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index 159b490ce0..00aa80cd58 100644
--- a/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -567,6 +567,8 @@ void QFontconfigDatabase::populateFontDatabase()
         fonts = FcFontList(nullptr, pattern, os);
         FcObjectSetDestroy(os);
         FcPatternDestroy(pattern);
+        if (!fonts)
+            return;
     }
 
     for (int i = 0; i < fonts->nfont; i++)
diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
index b713c19447..7cb9a8c79a 100644
--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
+++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
@@ -95,6 +95,7 @@ static constexpr const auto KeyTbl = qMakeArray(
         Xkb2Qt<XKB_KEY_Clear,                   Qt::Key_Delete>,
         Xkb2Qt<XKB_KEY_Pause,                   Qt::Key_Pause>,
         Xkb2Qt<XKB_KEY_Print,                   Qt::Key_Print>,
+        Xkb2Qt<XKB_KEY_Sys_Req,                 Qt::Key_SysReq>,
         Xkb2Qt<0x1005FF60,                      Qt::Key_SysReq>,         // hardcoded Sun SysReq
         Xkb2Qt<0x1007ff00,                      Qt::Key_SysReq>,         // hardcoded X386 SysReq
 
@@ -471,7 +472,7 @@ QVector<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event)
     } else if (event->modifiers() & Qt::KeypadModifier) {
         if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
             keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0));
-    } else if (isLatin(qtKey) && event->text().isUpper()) {
+    } else if (isLatin1(qtKey) && event->text().isUpper()) {
         keysyms.append(qtKey);
     }
 
@@ -523,7 +524,7 @@ int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifie
         // With standard shortcuts we should prefer a latin character, this is
         // for checks like "some qkeyevent == QKeySequence::Copy" to work even
         // when using for example 'russian' keyboard layout.
-        if (!QXkbCommon::isLatin(keysym)) {
+        if (!QXkbCommon::isLatin1(keysym)) {
             xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
             if (latinKeysym != XKB_KEY_NoSymbol)
                 keysym = latinKeysym;
@@ -546,7 +547,7 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
     } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
         // numeric keypad keys
         qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
-    } else if (QXkbCommon::isLatin(keysym)) {
+    } else if (QXkbCommon::isLatin1(keysym)) {
         qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
     } else {
         // check if we have a direct mapping
@@ -678,7 +679,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
         Qt::KeyboardModifiers neededMods = ModsTbl[i];
         if ((modifiers & neededMods) == neededMods) {
             if (i == 8) {
-                if (isLatin(baseQtKey))
+                if (isLatin1(baseQtKey))
                     continue;
                 // add a latin key as a fall back key
                 sym = lookupLatinKeysym(state, keycode);
@@ -733,7 +734,7 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap)
     for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
         for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
             xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
-            if (keysyms && isLatin(keysyms[0]))
+            if (keysyms && isLatin1(keysyms[0]))
                 nrLatinKeys++;
             if (nrLatinKeys > 10) // arbitrarily chosen threshold
                 return;
@@ -766,7 +767,7 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco
         xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
         if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
             continue;
-        if (isLatin(syms[0])) {
+        if (isLatin1(syms[0])) {
             sym = syms[0];
             break;
         }
diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
index 561eae03db..8389bd8f5a 100644
--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
+++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
@@ -94,8 +94,8 @@ public:
     static void verifyHasLatinLayout(xkb_keymap *keymap);
     static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
 
-    static bool isLatin(xkb_keysym_t sym) {
-        return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
+    static bool isLatin1(xkb_keysym_t sym) {
+        return sym <= 0xff;
     }
     static bool isKeypad(xkb_keysym_t sym) {
         return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
diff --git a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 8cd7f9b368..406f84663f 100644
--- a/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/qtbase/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -318,7 +318,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
 
     if (current < 0 && crtc_mode.clock != 0) {
         modes << crtc_mode;
-        current = mode.size() - 1;
+        current = modes.size() - 1;
     }
 
     if (configuration == OutputConfigCurrent)
diff --git a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 9153fd20bb..255ea5e33e 100644
--- a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -194,6 +194,9 @@ QString AtSpiAdaptor::introspect(const QString &path) const
                 "      <arg direction=\"out\" type=\"(so)\"/>\n"
                 "      <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
                 "    </method>\n"
+                "    <method name=\"GetAccessibleId\">\n"
+                "      <arg direction=\"out\" type=\"s\"/>\n"
+                "    </method>\n"
                 "  </interface>\n"
                 );
 
@@ -913,8 +916,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
     }
     case QAccessible::NameChanged: {
         if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) {
-            QString path = pathForInterface(event->accessibleInterface());
-            QVariantList args = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
+            QAccessibleInterface *iface = event->accessibleInterface();
+            if (!iface) {
+                qCDebug(lcAccessibilityAtspi,
+                        "NameChanged event from invalid accessible.");
+                return;
+            }
+
+            QString path = pathForInterface(iface);
+            QVariantList args = packDBusSignalArguments(
+                QLatin1String("accessible-name"), 0, 0,
+                QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
             sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
                            QLatin1String("PropertyChange"), args);
         }
@@ -922,8 +934,17 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
     }
     case QAccessible::DescriptionChanged: {
         if (sendObject || sendObject_property_change || sendObject_property_change_accessible_description) {
-            QString path = pathForInterface(event->accessibleInterface());
-            QVariantList args = packDBusSignalArguments(QLatin1String("accessible-description"), 0, 0, variantForPath(path));
+            QAccessibleInterface *iface = event->accessibleInterface();
+            if (!iface) {
+                qCDebug(lcAccessibilityAtspi,
+                        "DescriptionChanged event from invalid accessible.");
+                return;
+            }
+
+            QString path = pathForInterface(iface);
+            QVariantList args = packDBusSignalArguments(
+                QLatin1String("accessible-description"), 0, 0,
+                QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Description))));
             sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
                            QLatin1String("PropertyChange"), args);
         }
@@ -1038,7 +1059,9 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
                 // Combo Box with AT-SPI likes to be special
                 // It requires a name-change to update caches and then selection-changed
                 QString path = pathForInterface(iface);
-                QVariantList args1 = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
+                QVariantList args1 = packDBusSignalArguments(
+                    QLatin1String("accessible-name"), 0, 0,
+                    QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
                 sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
                                QLatin1String("PropertyChange"), args1);
                 QVariantList args2 = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(0))));
@@ -1358,6 +1381,26 @@ void AtSpiAdaptor::registerApplication()
     delete registry;
 }
 
+namespace {
+QString accessibleIdForAccessible(QAccessibleInterface *accessible)
+{
+    QString result;
+    while (accessible) {
+        if (!result.isEmpty())
+            result.prepend(QLatin1Char('.'));
+        if (auto obj = accessible->object()) {
+            const QString name = obj->objectName();
+            if (!name.isEmpty())
+                result.prepend(name);
+            else
+                result.prepend(QString::fromUtf8(obj->metaObject()->className()));
+        }
+        accessible = accessible->parent();
+    }
+    return result;
+}
+} // namespace
+
 // Accessible
 bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
 {
@@ -1441,6 +1484,9 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
             children << ref;
         }
         connection.send(message.createReply(QVariant::fromValue(children)));
+    } else if (function == QLatin1String("GetAccessibleId")) {
+        sendReply(connection, message,
+                  QVariant::fromValue(QDBusVariant(accessibleIdForAccessible(interface))));
     } else {
         qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
         return false;
diff --git a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index 45ddc8e496..cc734abc63 100644
--- a/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/qtbase/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -69,6 +69,21 @@ QT_BEGIN_NAMESPACE
 DBusConnection::DBusConnection(QObject *parent)
     : QObject(parent), m_a11yConnection(QString()), m_enabled(false)
 {
+    // If the bus is explicitly set via env var it overrides everything else.
+    QByteArray addressEnv = qgetenv("AT_SPI_BUS_ADDRESS");
+    if (!addressEnv.isEmpty()) {
+        // Only connect on next loop run, connections to our enabled signal are
+        // only established after the ctor returns.
+        QMetaObject::invokeMethod(
+                this,
+                [this, addressEnv] {
+                    m_enabled = true;
+                    connectA11yBus(QString::fromLocal8Bit(addressEnv));
+                },
+                Qt::QueuedConnection);
+        return;
+    }
+
     // Start monitoring if "org.a11y.Bus" is registered as DBus service.
     QDBusConnection c = QDBusConnection::sessionBus();
     if (!c.isConnected()) {
diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
index 1a3cab275d..2abe039126 100644
--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices.cpp
@@ -51,6 +51,9 @@
 #include <QtCore/QStandardPaths>
 #include <QtCore/QUrl>
 
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+
 #if QT_CONFIG(dbus)
 // These QtCore includes are needed for xdg-desktop-portal support
 #include <QtCore/private/qcore_unix_p.h>
@@ -58,6 +61,8 @@
 #include <QtCore/QFileInfo>
 #include <QtCore/QUrlQuery>
 
+#include <QtGui/QColor>
+
 #include <QtDBus/QDBusConnection>
 #include <QtDBus/QDBusMessage>
 #include <QtDBus/QDBusPendingCall>
@@ -142,6 +147,8 @@ static inline bool detectWebBrowser(const QByteArray &desktop,
     }
 
     if (desktop == QByteArray("KDE")) {
+        if (checkExecutable(QStringLiteral("kde-open5"), browser))
+            return true;
         // Konqueror launcher
         if (checkExecutable(QStringLiteral("kfmclient"), browser)) {
             browser->append(QLatin1String(" exec"));
@@ -296,8 +303,135 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
 
     return QDBusConnection::sessionBus().call(message);
 }
+
+namespace {
+struct XDGDesktopColor
+{
+    double r = 0;
+    double g = 0;
+    double b = 0;
+
+    QColor toQColor() const
+    {
+        constexpr auto rgbMax = 255;
+        return { static_cast<int>(r * rgbMax), static_cast<int>(g * rgbMax),
+                 static_cast<int>(b * rgbMax) };
+    }
+};
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, XDGDesktopColor &myStruct)
+{
+    argument.beginStructure();
+    argument >> myStruct.r >> myStruct.g >> myStruct.b;
+    argument.endStructure();
+    return argument;
+}
+
+class XdgDesktopPortalColorPicker : public QPlatformServiceColorPicker
+{
+    Q_OBJECT
+public:
+    XdgDesktopPortalColorPicker(const QString &parentWindowId, QWindow *parent)
+        : QPlatformServiceColorPicker(parent), m_parentWindowId(parentWindowId)
+    {
+    }
+
+    void pickColor() override
+    {
+        // DBus signature:
+        // PickColor (IN   s      parent_window,
+        //            IN   a{sv}  options
+        //            OUT  o      handle)
+        // Options:
+        // handle_token (s) -  A string that will be used as the last element of the @handle.
+
+        QDBusMessage message = QDBusMessage::createMethodCall(
+                QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"),
+                QStringLiteral("org.freedesktop.portal.Screenshot"), QStringLiteral("PickColor"));
+        message << m_parentWindowId << QVariantMap();
+
+        QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+        auto watcher = new QDBusPendingCallWatcher(pendingCall, this);
+        connect(watcher, &QDBusPendingCallWatcher::finished, this,
+                [this](QDBusPendingCallWatcher *watcher) {
+                    watcher->deleteLater();
+                    QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+                    if (reply.isError()) {
+                        qWarning("DBus call to pick color failed: %s",
+                                 qPrintable(reply.error().message()));
+                        Q_EMIT colorPicked({});
+                    } else {
+                        QDBusConnection::sessionBus().connect(
+                                QStringLiteral("org.freedesktop.portal.Desktop"), reply.value().path(),
+                                QStringLiteral("org.freedesktop.portal.Request"), QStringLiteral("Response"), this,
+                                // clang-format off
+                                SLOT(gotColorResponse(uint,QVariantMap))
+                                // clang-format on
+                        );
+                    }
+                });
+    }
+
+private Q_SLOTS:
+    void gotColorResponse(uint result, const QVariantMap &map)
+    {
+        if (result != 0)
+            return;
+        XDGDesktopColor color{};
+        map.value(QStringLiteral("color")).value<QDBusArgument>() >> color;
+        Q_EMIT colorPicked(color.toQColor());
+        deleteLater();
+    }
+
+private:
+    const QString m_parentWindowId;
+};
+} // namespace
+
 #endif // QT_CONFIG(dbus)
 
+QGenericUnixServices::QGenericUnixServices()
+{
+#if QT_CONFIG(dbus)
+    if (qEnvironmentVariableIntValue("QT_NO_XDG_DESKTOP_PORTAL") > 0) {
+        return;
+    }
+    QDBusMessage message = QDBusMessage::createMethodCall(
+            QStringLiteral("org.freedesktop.portal.Desktop"), QStringLiteral("/org/freedesktop/portal/desktop"),
+            QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get"));
+    message << QStringLiteral("org.freedesktop.portal.Screenshot")
+            << QStringLiteral("version");
+
+    QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+    auto watcher = new QDBusPendingCallWatcher(pendingCall);
+    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher,
+                     [this](QDBusPendingCallWatcher *watcher) {
+                         watcher->deleteLater();
+                         QDBusPendingReply<QVariant> reply = *watcher;
+                         if (!reply.isError() && reply.value().toUInt() >= 2)
+                             m_hasScreenshotPortalWithColorPicking = true;
+                     });
+
+#endif
+}
+
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+#if QT_CONFIG(dbus)
+    // Make double sure that we are in a wayland environment. In particular check
+    // WAYLAND_DISPLAY so also XWayland apps benefit from portal-based color picking.
+    // Outside wayland we'll rather rely on other means than the XDG desktop portal.
+    if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")
+        || QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) {
+        return new XdgDesktopPortalColorPicker(portalWindowIdentifier(parent), parent);
+    }
+    return nullptr;
+#else
+    Q_UNUSED(parent);
+    return nullptr;
+#endif
+}
+
 QByteArray QGenericUnixServices::desktopEnvironment() const
 {
     static const QByteArray result = detectDesktopEnvironment();
@@ -352,6 +486,8 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
 }
 
 #else
+QGenericUnixServices::QGenericUnixServices() = default;
+
 QByteArray QGenericUnixServices::desktopEnvironment() const
 {
     return QByteArrayLiteral("UNKNOWN");
@@ -371,6 +507,30 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
     return false;
 }
 
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+    Q_UNUSED(parent);
+    return nullptr;
+}
+
 #endif // QT_NO_MULTIPROCESS
 
+QString QGenericUnixServices::portalWindowIdentifier(QWindow *window)
+{
+    if (QGuiApplication::platformName() == QLatin1String("xcb"))
+        return QStringLiteral("x11:") + QString::number(window->winId(), 16);
+    return QString();
+}
+
+bool QGenericUnixServices::hasCapability(Capability capability) const
+{
+    switch (capability) {
+    case Capability::ColorPicking:
+        return m_hasScreenshotPortalWithColorPicking;
+    }
+    return false;
+}
+
 QT_END_NAMESPACE
+
+#include "qgenericunixservices.moc"
diff --git a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
index 8ac3de6f03..30924e64bd 100644
--- a/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
+++ b/qtbase/src/platformsupport/services/genericunix/qgenericunixservices_p.h
@@ -59,16 +59,21 @@ QT_BEGIN_NAMESPACE
 class QGenericUnixServices : public QPlatformServices
 {
 public:
-    QGenericUnixServices() {}
+    QGenericUnixServices();
 
     QByteArray desktopEnvironment() const override;
 
+    bool hasCapability(Capability capability) const override;
     bool openUrl(const QUrl &url) override;
     bool openDocument(const QUrl &url) override;
+    QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr) override;
+
+    virtual QString portalWindowIdentifier(QWindow *window);
 
 private:
     QString m_webBrowser;
     QString m_documentLauncher;
+    bool m_hasScreenshotPortalWithColorPicking = false;
 };
 
 QT_END_NAMESPACE
diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
index 09470bccc6..cc7c7d4d8a 100644
--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
+++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
@@ -69,6 +69,7 @@ const QString MenuBarPath = QLatin1String("/MenuBar");
 */
 QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName)
     : QObject(parent)
+    , m_serviceName(serviceName)
     , m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
                                         : QDBusConnection::connectToBus(QDBusConnection::SessionBus, serviceName))
     , m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
@@ -83,6 +84,12 @@ QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &service
 #endif
 }
 
+QDBusMenuConnection::~QDBusMenuConnection()
+{
+  if (!m_serviceName.isEmpty() && m_connection.isConnected())
+      QDBusConnection::disconnectFromBus(m_serviceName);
+}
+
 void QDBusMenuConnection::dbusError(const QDBusError &error)
 {
     qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error;
@@ -105,13 +112,7 @@ void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item)
 
 bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
 {
-    bool success = connection().registerService(item->instanceId());
-    if (!success) {
-        qWarning() << "failed to register service" << item->instanceId();
-        return false;
-    }
-
-    success = connection().registerObject(StatusNotifierItemPath, item);
+    bool success = connection().registerObject(StatusNotifierItemPath, item);
     if (!success) {
         unregisterTrayIcon(item);
         qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath;
@@ -126,21 +127,18 @@ bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
 
 bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item)
 {
+    Q_UNUSED(item);
     QDBusMessage registerMethod = QDBusMessage::createMethodCall(
                 StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService,
                 QLatin1String("RegisterStatusNotifierItem"));
-    registerMethod.setArguments(QVariantList() << item->instanceId());
+    registerMethod.setArguments(QVariantList() << m_connection.baseService());
     return m_connection.callWithCallback(registerMethod, this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
 }
 
-bool QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
+void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
 {
     unregisterTrayIconMenu(item);
     connection().unregisterObject(StatusNotifierItemPath);
-    bool success = connection().unregisterService(item->instanceId());
-    if (!success)
-        qWarning() << "failed to unregister service" << item->instanceId();
-    return success;
 }
 #endif // QT_NO_SYSTEMTRAYICON
 
diff --git a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
index f484795fbb..97bdfabb85 100644
--- a/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
+++ b/qtbase/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
@@ -70,6 +70,7 @@ class QDBusMenuConnection : public QObject
 
 public:
     QDBusMenuConnection(QObject *parent = nullptr, const QString &serviceName = QString());
+    ~QDBusMenuConnection();
     QDBusConnection connection() const { return m_connection; }
     QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; }
     bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
@@ -78,7 +79,7 @@ public:
     void unregisterTrayIconMenu(QDBusTrayIcon *item);
     bool registerTrayIcon(QDBusTrayIcon *item);
     bool registerTrayIconWithWatcher(QDBusTrayIcon *item);
-    bool unregisterTrayIcon(QDBusTrayIcon *item);
+    void unregisterTrayIcon(QDBusTrayIcon *item);
 #endif // QT_NO_SYSTEMTRAYICON
 
 Q_SIGNALS:
@@ -90,6 +91,7 @@ private Q_SLOTS:
     void dbusError(const QDBusError &error);
 
 private:
+    QString m_serviceName;
     QDBusConnection m_connection;
     QDBusServiceWatcher *m_dbusWatcher;
     bool m_statusNotifierHostRegistered;
diff --git a/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp b/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
index bede70975a..76bfec5e5a 100644
--- a/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
+++ b/qtbase/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
@@ -71,8 +71,12 @@ Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray")
 static QString iconTempPath()
 {
     QString tempPath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
-    if (!tempPath.isEmpty())
+    if (!tempPath.isEmpty()) {
+        QString flatpakId = qEnvironmentVariable("FLATPAK_ID");
+        if (!flatpakId.isEmpty() && QFileInfo::exists(QLatin1String("/.flatpak-info")))
+            tempPath += QLatin1String("/app/") + flatpakId;
         return tempPath;
+    }
 
     tempPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
 
diff --git a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index cb1b39db64..6e01af052c 100644
--- a/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/qtbase/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -755,6 +755,9 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
         return QVariant(QChar(0x2022));
     case QPlatformTheme::UiEffects:
         return QVariant(int(HoverEffect));
+    case QPlatformTheme::ButtonPressKeys:
+        return QVariant::fromValue(
+                QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
     default:
         break;
     }
diff --git a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
index 98e05195ee..1e92f43dec 100644
--- a/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
+++ b/qtbase/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
@@ -343,8 +343,7 @@ void QEglFSCursor::paintOnScreen()
     // screens are siblings of each other. When not enabled, the sibling list
     // only contains m_screen itself.
     for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
-        if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot)
-            && QOpenGLContext::currentContext()->screen() == screen->screen())
+        if (screen->geometry().contains(cr.topLeft().toPoint() + m_cursor.hotSpot))
         {
             cr.translate(-screen->geometry().topLeft());
             const QSize screenSize = screen->geometry().size();
@@ -468,11 +467,12 @@ void QEglFSCursor::draw(const QRectF &r)
 {
     StateSaver stateSaver;
 
-    QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
-    if (!gfx.program) {
-        // one time initialization
+    // one time initialization
+    if (!QOpenGLFunctions::d_ptr)
         initializeOpenGLFunctions();
 
+    QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
+    if (!gfx.program) {
         createShaderPrograms();
 
         if (!gfx.atlasTexture) {
diff --git a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
index 645a0ae2e9..3e0e406f1a 100644
--- a/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
+++ b/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp
@@ -179,7 +179,7 @@ void QEglFSKmsEventReader::create(QEglFSKmsDevice *device)
 
     m_device = device;
 
-    qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d",
+    qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d",
             m_device, m_device->fd());
 
     m_thread = new QEglFSKmsEventReaderThread(m_device->fd());
diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index 141fb68a23..d4294d425a 100644
--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -122,11 +122,13 @@ QOffscreenIntegration::QOffscreenIntegration()
 #endif
     m_services.reset(new QPlatformServices);
 
-    QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen);
+    m_screen = new QOffscreenScreen;
+    QWindowSystemInterface::handleScreenAdded(m_screen);
 }
 
 QOffscreenIntegration::~QOffscreenIntegration()
 {
+    QWindowSystemInterface::handleScreenRemoved(m_screen);
 }
 
 void QOffscreenIntegration::initialize()
diff --git a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
index 0ea90f6c2f..fe00fde07c 100644
--- a/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
+++ b/qtbase/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -84,6 +84,7 @@ protected:
 #endif
     QScopedPointer<QPlatformInputContext> m_inputContext;
     QScopedPointer<QPlatformServices> m_services;
+    QPlatformScreen *m_screen;
     mutable QScopedPointer<QPlatformNativeInterface> m_nativeInterface;
 };
 
diff --git a/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp b/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 6fa5a8a2b3..1f49f0aefd 100644
--- a/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/qtbase/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -48,6 +48,7 @@
 #include <qpa/qplatformnativeinterface.h>
 #include <QtPlatformHeaders/qwglnativecontext.h>
 
+#include <private/qsystemlibrary_p.h>
 #include <algorithm>
 
 #include <wingdi.h>
@@ -162,19 +163,25 @@ QFunctionPointer QWindowsOpengl32DLL::resolve(const char *name)
 
 bool QWindowsOpengl32DLL::init(bool softwareRendering)
 {
-    const QByteArray opengl32 = QByteArrayLiteral("opengl32.dll");
-    const QByteArray swopengl = QByteArrayLiteral("opengl32sw.dll");
+    const QByteArray opengl32 = QByteArrayLiteral("opengl32");
+    const QByteArray swopengl = QByteArrayLiteral("opengl32sw");
+    bool useSystemLib = false;
 
     QByteArray openglDll = qgetenv("QT_OPENGL_DLL");
-    if (openglDll.isEmpty())
+    if (openglDll.isEmpty()) {
         openglDll = softwareRendering ? swopengl : opengl32;
+        useSystemLib = !softwareRendering;
+    }
 
     openglDll = openglDll.toLower();
     m_nonOpengl32 = openglDll != opengl32;
 
     qCDebug(lcQpaGl) << "Qt: Using WGL and OpenGL from" << openglDll;
 
-    m_lib = ::LoadLibraryA(openglDll.constData());
+    if (useSystemLib)
+        m_lib = QSystemLibrary::load((wchar_t*)(QString::fromLatin1(openglDll).utf16()));
+    else
+        m_lib = LoadLibraryA(openglDll.constData());
     if (!m_lib) {
         qErrnoWarning(::GetLastError(), "Failed to load %s", openglDll.constData());
         return false;
@@ -184,7 +191,7 @@ bool QWindowsOpengl32DLL::init(bool softwareRendering)
         // Load opengl32.dll always. GDI functions like ChoosePixelFormat do
         // GetModuleHandle for opengl32.dll and behave differently (and call back into
         // opengl32) when the module is present. This is fine for dummy contexts and windows.
-        ::LoadLibraryA("opengl32.dll");
+        QSystemLibrary::load(L"opengl32");
     }
 
     wglCreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(resolve("wglCreateContext"));
diff --git a/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp b/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp
index d7d186e804..9eb4011bf2 100644
--- a/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/qtbase/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -49,6 +49,7 @@
 #include <QtCore/qstandardpaths.h>
 #include <QtCore/qlibraryinfo.h>
 #include <QtCore/qhash.h>
+#include <private/qsystemlibrary_p.h>
 
 #ifndef QT_NO_OPENGL
 #include <private/qopengl_p.h>
@@ -396,7 +397,7 @@ bool QWindowsOpenGLTester::testDesktopGL()
 
     // Test #1: Load opengl32.dll and try to resolve an OpenGL 2 function.
     // This will typically fail on systems that do not have a real OpenGL driver.
-    lib = LoadLibraryA("opengl32.dll");
+    lib = QSystemLibrary::load(L"opengl32");
     if (lib) {
         CreateContext = reinterpret_cast<CreateContextType>(
             reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglCreateContext")));
diff --git a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
index 1afa00cfc9..118af6ce73 100644
--- a/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
+++ b/qtbase/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
@@ -41,6 +41,7 @@
 
 #include <QRect>
 #include <QList>
+#include <QMap>
 #include <QDebug>
 
 #include <qmath.h>
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
index 9e2a37a6a1..e6e175a118 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -488,12 +488,12 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err
     uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
     uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
 
-    qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
-             message,
-             int(error->error_code), xcb_errors[clamped_error_code],
-             int(error->sequence), int(error->resource_id),
-             int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
-             int(error->minor_code));
+    qCDebug(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+            message,
+            int(error->error_code), xcb_errors[clamped_error_code],
+            int(error->sequence), int(error->resource_id),
+            int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
+            int(error->minor_code));
 }
 
 static Qt::MouseButtons translateMouseButtons(int s)
@@ -702,6 +702,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
             QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
             if (virtualDesktop)
                 virtualDesktop->updateWorkArea();
+        } else if (propertyNotify->atom == atom(QXcbAtom::_NET_SUPPORTED)) {
+            m_wmSupport->updateNetWMAtoms();
         } else {
             HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
         }
@@ -750,7 +752,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
                 case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
                     xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
                     if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
-                        m_keyboard->updateKeymap(ev);
+                        m_keyboard->updateKeymap();
                     break;
                 }
                 default:
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
index 76869ced60..02d2eebb56 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -274,8 +274,7 @@ QPlatformWindow *QXcbIntegration::createForeignWindow(QWindow *window, WId nativ
 #ifndef QT_NO_OPENGL
 QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
 {
-    QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
-    QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
+    QXcbGlIntegration *glIntegration = defaultConnection()->glIntegration();
     if (!glIntegration) {
         qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
         return nullptr;
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index efecd7e2d1..e8286381a2 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -365,17 +365,6 @@ void QXcbKeyboard::updateKeymap(xcb_mapping_notify_event_t *event)
     updateKeymap();
 }
 
-void QXcbKeyboard::updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event)
-{
-    if (!event)
-        return;
-
-    if (event->deviceID != event->oldDeviceID)
-        m_config = false;
-
-    updateKeymap();
-}
-
 void QXcbKeyboard::updateKeymap()
 {
     KeysymModifierMap keysymMods;
@@ -383,6 +372,8 @@ void QXcbKeyboard::updateKeymap()
         keysymMods = keysymsToModifiers();
     updateModifiers(keysymMods);
 
+    m_config = true;
+
     if (!m_xkbContext) {
         m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES));
         if (!m_xkbContext) {
@@ -398,13 +389,8 @@ void QXcbKeyboard::updateKeymap()
     if (connection()->hasXKB()) {
         m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(),
                                                          core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS));
-        if (m_xkbKeymap) {
-            if (m_config)
-                m_xkbState.reset(xkb_state_new(m_xkbKeymap.get()));
-            else
-                m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
-
-        }
+        if (m_xkbKeymap)
+            m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
     } else {
         m_xkbKeymap.reset(keymapFromCore(keysymMods));
         if (m_xkbKeymap)
@@ -425,8 +411,6 @@ void QXcbKeyboard::updateKeymap()
     updateXKBMods();
 
     QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get());
-
-    m_config = true;
 }
 
 QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h
index b652c85fe3..0ee08aeff2 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -69,7 +69,6 @@ public:
 
     Qt::KeyboardModifiers translateModifiers(int s) const;
     void updateKeymap(xcb_mapping_notify_event_t *event);
-    void updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event);
     void updateKeymap();
     QList<int> possibleKeys(const QKeyEvent *event) const;
 
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
index ffda7b6a57..863e961f4c 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -564,11 +564,6 @@ void QXcbWindow::setGeometry(const QRect &rect)
 {
     QPlatformWindow::setGeometry(rect);
 
-    if (shouldDeferTask(Task::SetGeometry)) {
-        m_deferredGeometry = rect;
-        return;
-    }
-
     propagateSizeHints();
 
     QXcbScreen *currentScreen = xcbScreen();
@@ -693,9 +688,6 @@ void QXcbWindow::setVisible(bool visible)
 
 void QXcbWindow::show()
 {
-    if (shouldDeferTask(Task::Map))
-        return;
-
     if (window()->isTopLevel()) {
 
         // update WM_NORMAL_HINTS
@@ -706,7 +698,7 @@ void QXcbWindow::show()
         if (isTransient(window())) {
             const QWindow *tp = window()->transientParent();
             if (tp && tp->handle())
-                transientXcbParent = static_cast<const QXcbWindow *>(tp->handle())->winId();
+                transientXcbParent = tp->handle()->winId();
             // Default to client leader if there is no transient parent, else modal dialogs can
             // be hidden by their parents.
             if (!transientXcbParent)
@@ -746,10 +738,6 @@ void QXcbWindow::show()
 
 void QXcbWindow::hide()
 {
-    if (shouldDeferTask(Task::Unmap))
-        return;
-
-    m_wmStateValid = false;
     xcb_unmap_window(xcb_connection(), m_window);
 
     // send synthetic UnmapNotify event according to icccm 4.1.4
@@ -909,9 +897,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
 
 void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
 {
-    if (shouldDeferTask(Task::SetWindowFlags))
-        return;
-
     Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
 
     if (type == Qt::ToolTip)
@@ -941,8 +926,6 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
 
     setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
     updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus);
-
-    m_isWmManagedWindow = !(flags & Qt::X11BypassWindowManagerHint);
 }
 
 void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
@@ -1142,9 +1125,6 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
     if (state == m_windowState)
         return;
 
-    if (shouldDeferTask(Task::SetWindowState))
-        return;
-
     // unset old state
     if (m_windowState & Qt::WindowMinimized)
         xcb_map_window(xcb_connection(), m_window);
@@ -1350,6 +1330,12 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
     }
 
     if (!icon_data.isEmpty()) {
+        // Ignore icon exceeding maximum xcb request length
+        if (icon_data.size() > xcb_get_maximum_request_length(xcb_connection())) {
+            qWarning("Ignoring window icon: Size %llu exceeds maximum xcb request length %u.",
+                     icon_data.size(), xcb_get_maximum_request_length(xcb_connection()));
+            return;
+        }
         xcb_change_property(xcb_connection(),
                             XCB_PROP_MODE_REPLACE,
                             m_window,
@@ -1639,7 +1625,7 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W
         break;
     }
 
-    if ((flags & Qt::FramelessWindowHint) && !(type & QXcbWindowFunctions::KdeOverride)) {
+    if ((flags & Qt::FramelessWindowHint) && !(types & QXcbWindowFunctions::KdeOverride)) {
         // override netwm type - quick and easy for KDE noborder
         atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
     }
@@ -1894,10 +1880,6 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
     if (event->window == m_window) {
         m_mapped = false;
         QWindowSystemInterface::handleExposeEvent(window(), QRegion());
-        if (!m_isWmManagedWindow || parent()) {
-            m_wmStateValid = true;
-            handleDeferredTasks();
-        }
     }
 }
 
@@ -2212,98 +2194,30 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
     handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time);
 }
 
-bool QXcbWindow::shouldDeferTask(Task task)
-{
-    if (m_wmStateValid)
-        return false;
-
-    m_deferredTasks.append(task);
-    return true;
-}
-
-void QXcbWindow::handleDeferredTasks()
-{
-    Q_ASSERT(m_wmStateValid == true);
-    if (m_deferredTasks.isEmpty())
-        return;
-
-    bool map = false;
-    bool unmap = false;
-
-    QVector<Task> tasks;
-    for (auto taskIt = m_deferredTasks.rbegin(); taskIt != m_deferredTasks.rend(); ++taskIt) {
-        if (!tasks.contains(*taskIt))
-            tasks.prepend(*taskIt);
-    }
-
-    for (Task task : tasks) {
-        switch (task) {
-        case Task::Map:
-            map = true;
-            unmap = false;
-            break;
-        case Task::Unmap:
-            unmap = true;
-            map = false;
-            break;
-        case Task::SetGeometry:
-            setGeometry(m_deferredGeometry);
-            break;
-        case Task::SetWindowFlags:
-            setWindowFlags(window()->flags());
-            break;
-        case Task::SetWindowState:
-            setWindowState(window()->windowState());
-            break;
-        }
-    }
-    m_deferredTasks.clear();
-
-    if (map) {
-        Q_ASSERT(unmap == false);
-        show();
-    }
-    if (unmap) {
-        Q_ASSERT(map == false);
-        hide();
-    }
-}
-
 void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
 {
     connection()->setTime(event->time);
 
-    const bool wmStateChanged = event->atom == atom(QXcbAtom::WM_STATE);
-    const bool netWmStateChanged = event->atom == atom(QXcbAtom::_NET_WM_STATE);
-    if (netWmStateChanged || wmStateChanged) {
-        if (wmStateChanged && !m_wmStateValid && m_isWmManagedWindow) {
-            // ICCCM 4.1.4
-            // Clients that want to re-use a client window (e.g. by mapping it again)
-            // after withdrawing it must wait for the withdrawal to be complete before
-            // proceeding. The preferred method for doing this is for clients to wait for
-            // a window manager to update or remove the WM_STATE property.
-            m_wmStateValid = true;
-            handleDeferredTasks();
-        }
-        if (event->state == XCB_PROPERTY_DELETE)
+    const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
+
+    if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
+        if (propertyDeleted)
             return;
 
-        if (wmStateChanged) {
+        Qt::WindowStates newState = Qt::WindowNoState;
+
+        if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
             auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
                                      0, m_window, atom(QXcbAtom::WM_STATE),
                                      XCB_ATOM_ANY, 0, 1024);
             if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
-                auto data = static_cast<const quint32 *>(xcb_get_property_value(reply.get()));
-                if (reply->length != 0) {
-                    const bool changedToWithdrawn = data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN;
-                    const bool changedToIconic = data[0] == XCB_ICCCM_WM_STATE_ICONIC;
-                    m_minimized = changedToIconic || (changedToWithdrawn && m_minimized);
-                }
+                const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
+                if (reply->length != 0)
+                    m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC
+                                   || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
             }
         }
 
-        // _NET_WM_STATE handling
-        Qt::WindowStates newState = Qt::WindowNoState;
         const NetWmStates states = netWmStates();
         // _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
         // not be visible on the screen if its desktop/viewport were active and its coordinates were
@@ -2325,6 +2239,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
             if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
                 connection()->setMouseGrabber(nullptr);
         }
+        return;
     } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
         m_dirtyFrameMargins = true;
     }
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbwindow.h b/qtbase/src/plugins/platforms/xcb/qxcbwindow.h
index 55af9279b1..6f5c1f5ed9 100644
--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.h
@@ -74,14 +74,6 @@ public:
 
     Q_DECLARE_FLAGS(NetWmStates, NetWmState)
 
-    enum Task {
-        Map,
-        Unmap,
-        SetGeometry,
-        SetWindowFlags,
-        SetWindowState
-    };
-
     QXcbWindow(QWindow *window);
     ~QXcbWindow();
 
@@ -151,9 +143,6 @@ public:
 
     QXcbWindow *toWindow() override;
 
-    bool shouldDeferTask(Task task);
-    void handleDeferredTasks();
-
     void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
                           Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source);
 
@@ -292,11 +281,6 @@ protected:
     int m_swapInterval = -1;
 
     qreal m_sizeHintsScaleFactor = 1.0;
-
-    bool m_wmStateValid = true;
-    QVector<Task> m_deferredTasks;
-    bool m_isWmManagedWindow = true;
-    QRect m_deferredGeometry;
 };
 
 class QXcbForeignWindow : public QXcbWindow
diff --git a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
index d9d117faeb..640b49daa0 100644
--- a/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
+++ b/qtbase/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
@@ -85,6 +85,7 @@ QGtk3MenuItem::QGtk3MenuItem()
       m_checkable(false),
       m_checked(false),
       m_enabled(true),
+      m_exclusive(false),
       m_underline(false),
       m_invalid(true),
       m_menu(nullptr),
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
index 0048bbc1e6..396e7f6d1c 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -102,15 +102,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile
 class QXdgDesktopPortalFileDialogPrivate
 {
 public:
-    QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
+    QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
         : nativeFileDialog(nativeFileDialog)
+        , fileChooserPortalVersion(fileChooserPortalVersion)
     { }
 
-    WId winId = 0;
-    bool directoryMode = false;
-    bool modal = false;
-    bool multipleFiles = false;
-    bool saveFile = false;
+    QEventLoop loop;
     QString acceptLabel;
     QString directory;
     QString title;
@@ -121,19 +118,27 @@ public:
     QString selectedMimeTypeFilter;
     QString selectedNameFilter;
     QStringList selectedFiles;
-    QPlatformFileDialogHelper *nativeFileDialog = nullptr;
+    std::unique_ptr<QPlatformFileDialogHelper> nativeFileDialog;
+    uint fileChooserPortalVersion = 0;
+    bool failedToOpen = false;
+    bool directoryMode = false;
+    bool multipleFiles = false;
+    bool saveFile = false;
 };
 
-QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
+QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
     : QPlatformFileDialogHelper()
-    , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
+    , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
 {
     Q_D(QXdgDesktopPortalFileDialog);
 
     if (d->nativeFileDialog) {
-        connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept()));
-        connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject()));
+        connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
+        connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
     }
+
+    d->loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+    d->loop.connect(this, SIGNAL(reject()), SLOT(quit()));
 }
 
 QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
@@ -177,7 +182,7 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
     setDirectory(options()->initialDirectory());
 }
 
-void QXdgDesktopPortalFileDialog::openPortal()
+void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
 {
     Q_D(QXdgDesktopPortalFileDialog);
 
@@ -185,13 +190,13 @@ void QXdgDesktopPortalFileDialog::openPortal()
                                                           QLatin1String("/org/freedesktop/portal/desktop"),
                                                           QLatin1String("org.freedesktop.portal.FileChooser"),
                                                           d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
-    QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16);
+    QString parentWindowId = QLatin1String("x11:") + QString::number(parent ? parent->winId() : 0, 16);
 
     QVariantMap options;
     if (!d->acceptLabel.isEmpty())
         options.insert(QLatin1String("accept_label"), d->acceptLabel);
 
-    options.insert(QLatin1String("modal"), d->modal);
+    options.insert(QLatin1String("modal"), windowModality != Qt::NonModal);
     options.insert(QLatin1String("multiple"), d->multipleFiles);
     options.insert(QLatin1String("directory"), d->directoryMode);
 
@@ -290,10 +295,18 @@ void QXdgDesktopPortalFileDialog::openPortal()
 
     QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
-    connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+    connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher *watcher) {
         QDBusPendingReply<QDBusObjectPath> reply = *watcher;
-        if (reply.isError()) {
-            Q_EMIT reject();
+        // Any error means the dialog is not shown and we need to fallback
+        d->failedToOpen = reply.isError();
+        if (d->failedToOpen) {
+            if (d->nativeFileDialog) {
+                d->nativeFileDialog->show(windowFlags, windowModality, parent);
+                if (d->loop.isRunning())
+                    d->nativeFileDialog->exec();
+            } else {
+                Q_EMIT reject();
+            }
         } else {
             QDBusConnection::sessionBus().connect(nullptr,
                                                   reply.value().path(),
@@ -302,6 +315,7 @@ void QXdgDesktopPortalFileDialog::openPortal()
                                                   this,
                                                   SLOT(gotResponse(uint,QVariantMap)));
         }
+        watcher->deleteLater();
     });
 }
 
@@ -326,7 +340,7 @@ QUrl QXdgDesktopPortalFileDialog::directory() const
 {
     Q_D(const QXdgDesktopPortalFileDialog);
 
-    if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+    if (d->nativeFileDialog && useNativeFileDialog())
         return d->nativeFileDialog->directory();
 
     return d->directory;
@@ -348,7 +362,7 @@ QList<QUrl> QXdgDesktopPortalFileDialog::selectedFiles() const
 {
     Q_D(const QXdgDesktopPortalFileDialog);
 
-    if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+    if (d->nativeFileDialog && useNativeFileDialog())
         return d->nativeFileDialog->selectedFiles();
 
     QList<QUrl> files;
@@ -403,16 +417,13 @@ void QXdgDesktopPortalFileDialog::exec()
 {
     Q_D(QXdgDesktopPortalFileDialog);
 
-    if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) {
+    if (d->nativeFileDialog && useNativeFileDialog()) {
         d->nativeFileDialog->exec();
         return;
     }
 
     // HACK we have to avoid returning until we emit that the dialog was accepted or rejected
-    QEventLoop loop;
-    loop.connect(this, SIGNAL(accept()), SLOT(quit()));
-    loop.connect(this, SIGNAL(reject()), SLOT(quit()));
-    loop.exec();
+    d->loop.exec();
 }
 
 void QXdgDesktopPortalFileDialog::hide()
@@ -429,13 +440,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
 
     initializeDialog();
 
-    d->modal = windowModality != Qt::NonModal;
-    d->winId = parent ? parent->winId() : 0;
-
-    if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+    if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
         return d->nativeFileDialog->show(windowFlags, windowModality, parent);
 
-    openPortal();
+    openPortal(windowFlags, windowModality, parent);
 
     return true;
 }
@@ -465,4 +473,21 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
     }
 }
 
+bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const
+{
+    Q_D(const QXdgDesktopPortalFileDialog);
+
+    if (d->failedToOpen && fallbackType != OpenFallback)
+        return true;
+
+    if (d->fileChooserPortalVersion < 3) {
+        if (options()->fileMode() == QFileDialogOptions::Directory)
+            return true;
+        else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
+            return true;
+    }
+
+    return false;
+}
+
 QT_END_NAMESPACE
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
index 4f4de96ecf..65e22a5cf2 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
@@ -51,6 +51,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
     Q_OBJECT
     Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
 public:
+    enum FallbackType {
+        GenericFallback,
+        OpenFallback
+    };
+
     enum ConditionType : uint {
         GlobalPattern = 0,
         MimeType = 1
@@ -69,7 +74,7 @@ public:
     };
     typedef QVector<Filter> FilterList;
 
-    QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
+    QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
     ~QXdgDesktopPortalFileDialog();
 
     bool defaultNameFilterDisables() const override;
@@ -92,7 +97,8 @@ private Q_SLOTS:
 
 private:
     void initializeDialog();
-    void openPortal();
+    void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
+    bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
 
     QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
 };
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
index fb324afbd8..b809503122 100644
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -111,6 +111,7 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
         if (reply.isValid()) {
             d->fileChooserPortalVersion = reply.value().toUInt();
         }
+        watcher->deleteLater();
     });
 }
 
@@ -152,11 +153,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
 {
     Q_D(const QXdgDesktopPortalTheme);
 
-    if (type == FileDialog) {
+    if (type == FileDialog && d->fileChooserPortalVersion) {
         // Older versions of FileChooser portal don't support opening directories, therefore we fallback
         // to native file dialog opened inside the sandbox to open a directory.
-        if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
-            return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
+        if (d->baseTheme->usePlatformNativeDialog(type))
+            return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
+                                                   d->fileChooserPortalVersion);
 
         return new QXdgDesktopPortalFileDialog;
     }
diff --git a/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp b/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp
index 43d5e119ad..1f9cbc4565 100644
--- a/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp
+++ b/qtbase/src/plugins/printsupport/cups/qcupsprintengine.cpp
@@ -89,8 +89,10 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v
         break;
     case PPK_Duplex: {
         QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
-        if (mode != d->duplex && d->m_printDevice.supportedDuplexModes().contains(mode))
+        if (d->m_printDevice.supportedDuplexModes().contains(mode)) {
             d->duplex = mode;
+            d->duplexRequestedExplicitly = true;
+        }
         break;
     }
     case PPK_PrinterName:
@@ -277,9 +279,12 @@ void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter)
     m_printDevice.swap(printDevice);
     printerName = m_printDevice.id();
 
-    // Check if new printer supports current settings, otherwise us defaults
-    if (duplex != QPrint::DuplexAuto && !m_printDevice.supportedDuplexModes().contains(duplex))
+    // in case a duplex value was explicitly set, check if new printer supports current value,
+    // otherwise use device default
+    if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) {
         duplex = m_printDevice.defaultDuplexMode();
+        duplexRequestedExplicitly = false;
+    }
     QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color;
     if (!m_printDevice.supportedColorModes().contains(colorMode))
         grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
diff --git a/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h b/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h
index c021b0c643..8f81fe478d 100644
--- a/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/qtbase/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -100,6 +100,7 @@ private:
     QStringList cupsOptions;
     QString cupsTempFile;
     QPrint::DuplexMode duplex;
+    bool duplexRequestedExplicitly = false;
 };
 
 QT_END_NAMESPACE
diff --git a/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
index 67e7154fa6..40876152e5 100644
--- a/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
+++ b/qtbase/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
@@ -817,7 +817,7 @@ bool QIBaseResultPrivate::writeArray(int column, const QList<QVariant> &list)
     ba.resize(int(bufLen));
 
     if (list.size() > arraySize) {
-        error = QLatin1String("Array size missmatch: size of %1 is %2, size of provided list is %3");
+        error = QLatin1String("Array size mismatch: size of %1 is %2, size of provided list is %3");
         error = error.arg(QLatin1String(sqlname)).arg(arraySize).arg(list.size());
         q->setLastError(QSqlError(error, QLatin1String(""), QSqlError::StatementError));
         return false;
diff --git a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 7ca055eea2..6bc9d46755 100644
--- a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -223,7 +223,7 @@ public:
     struct QMyField
     {
         char *outField = nullptr;
-        MYSQL_FIELD *myField = nullptr;
+        const MYSQL_FIELD *myField = nullptr;
         QMetaType::Type type = QMetaType::UnknownType;
         my_bool nullIndicator = false;
         ulong bufLength = 0ul;
@@ -361,7 +361,7 @@ static bool qIsInteger(int t)
 void QMYSQLResultPrivate::bindBlobs()
 {
     int i;
-    MYSQL_FIELD *fieldInfo;
+    const MYSQL_FIELD *fieldInfo;
     MYSQL_BIND *bind;
 
     for(i = 0; i < fields.count(); ++i) {
@@ -379,7 +379,6 @@ void QMYSQLResultPrivate::bindBlobs()
 bool QMYSQLResultPrivate::bindInValues()
 {
     MYSQL_BIND *bind;
-    char *field;
     int i = 0;
 
     if (!meta)
@@ -392,35 +391,34 @@ bool QMYSQLResultPrivate::bindInValues()
     inBinds = new MYSQL_BIND[fields.size()];
     memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND));
 
-    MYSQL_FIELD *fieldInfo;
+    const MYSQL_FIELD *fieldInfo;
 
     while((fieldInfo = mysql_fetch_field(meta))) {
+        bind = &inBinds[i];
+
         QMyField &f = fields[i];
         f.myField = fieldInfo;
-
+        bind->buffer_length = f.bufLength = fieldInfo->length + 1;
+        bind->buffer_type = fieldInfo->type;
         f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags);
         if (qIsBlob(fieldInfo->type)) {
             // the size of a blob-field is available as soon as we call
             // mysql_stmt_store_result()
             // after mysql_stmt_exec() in QMYSQLResult::exec()
-            fieldInfo->length = 0;
+            bind->buffer_length = f.bufLength = 0;
             hasBlobs = true;
         } else if (qIsInteger(f.type)) {
-            fieldInfo->length = 8;
+            bind->buffer_length = f.bufLength = 8;
         } else {
-            fieldInfo->type = MYSQL_TYPE_STRING;
+            bind->buffer_type = MYSQL_TYPE_STRING;
         }
-        bind = &inBinds[i];
-        field = new char[fieldInfo->length + 1];
-        memset(field, 0, fieldInfo->length + 1);
 
-        bind->buffer_type = fieldInfo->type;
-        bind->buffer = field;
-        bind->buffer_length = f.bufLength = fieldInfo->length + 1;
         bind->is_null = &f.nullIndicator;
         bind->length = &f.bufLength;
         bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0;
-        f.outField=field;
+
+        char *field = new char[bind->buffer_length + 1]{};
+        bind->buffer = f.outField = field;
 
         ++i;
     }
@@ -1369,20 +1367,20 @@ bool QMYSQLDriver::open(const QString& db,
     }
 
 #if MYSQL_VERSION_ID >= 50007
-    if (mysql_get_client_version() >= 50503 && mysql_get_server_version(d->mysql) >= 50503) {
-        // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters)
-        mysql_set_character_set(d->mysql, "utf8mb4");
+    // force the communication to be utf8mb4 (only utf8mb4 supports 4-byte characters)
+    if (mysql_set_character_set(d->mysql, "utf8mb4")) {
+        // this failed, try forcing it to utf (BMP only)
+        if (mysql_set_character_set(d->mysql, "utf8"))
+            qWarning() << "MySQL: Unable to set the client character set to utf8.";
 #if QT_CONFIG(textcodec)
-        d->tc = QTextCodec::codecForName("UTF-8");
+        else
+            d->tc = codec(d->mysql);
 #endif
-    } else
-    {
-        // force the communication to be utf8
-        mysql_set_character_set(d->mysql, "utf8");
+    }
 #if QT_CONFIG(textcodec)
-        d->tc = codec(d->mysql);
+    else
+        d->tc = QTextCodec::codecForName("UTF-8");
 #endif
-    }
 #endif  // MYSQL_VERSION_ID >= 50007
 
     d->preparedQuerysEnabled = checkPreparedQueries(d->mysql);
diff --git a/qtbase/src/printsupport/dialogs/images/print-24.png b/qtbase/src/printsupport/dialogs/images/printer-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/print-24.png
rename to src/printsupport/dialogs/images/printer-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/print-32.png b/qtbase/src/printsupport/dialogs/images/printer-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/print-32.png
rename to src/printsupport/dialogs/images/printer-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-sided-24.png
rename to src/printsupport/dialogs/images/view-pages-facing-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-sided-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-facing-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-sided-32.png
rename to src/printsupport/dialogs/images/view-pages-facing-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-multi-24.png
rename to src/printsupport/dialogs/images/view-pages-overview-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-multi-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-overview-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-multi-32.png
rename to src/printsupport/dialogs/images/view-pages-overview-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-24.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-one-24.png
rename to src/printsupport/dialogs/images/view-pages-single-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/view-page-one-32.png b/qtbase/src/printsupport/dialogs/images/view-pages-single-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/view-page-one-32.png
rename to src/printsupport/dialogs/images/view-pages-single-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-page-24.png
rename to src/printsupport/dialogs/images/zoom-fit-page-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-page-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-page-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-page-32.png
rename to src/printsupport/dialogs/images/zoom-fit-page-32.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-24.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-24.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-width-24.png
rename to src/printsupport/dialogs/images/zoom-fit-width-24.png
diff --git a/qtbase/src/printsupport/dialogs/images/fit-width-32.png b/qtbase/src/printsupport/dialogs/images/zoom-fit-width-32.png
similarity index 100%
rename from src/printsupport/dialogs/images/fit-width-32.png
rename to src/printsupport/dialogs/images/zoom-fit-width-32.png
diff --git a/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
index 78e5b8d1ef..2a28516719 100644
--- a/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
+++ b/qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
@@ -532,6 +532,7 @@ void QPageSetupWidget::updateWidget()
 void QPageSetupWidget::setupPrinter() const
 {
     m_printer->setPageLayout(m_pageLayout);
+    m_printer->setPageOrientation(m_pageLayout.orientation());
 #if QT_CONFIG(cups)
     QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(m_ui.pagesPerSheetCombo->currentData()
 );
diff --git a/qtbase/src/printsupport/dialogs/qprintdialog.qrc b/qtbase/src/printsupport/dialogs/qprintdialog.qrc
index 5a579baa55..10b8e1d341 100644
--- a/qtbase/src/printsupport/dialogs/qprintdialog.qrc
+++ b/qtbase/src/printsupport/dialogs/qprintdialog.qrc
@@ -1,9 +1,9 @@
 <!DOCTYPE RCC><RCC version="1.0">
 <qresource prefix="/qt-project.org/dialogs/qprintpreviewdialog">
-<file>images/fit-page-24.png</file>
-<file>images/fit-page-32.png</file>
-<file>images/fit-width-24.png</file>
-<file>images/fit-width-32.png</file>
+<file>images/zoom-fit-page-24.png</file>
+<file>images/zoom-fit-page-32.png</file>
+<file>images/zoom-fit-width-24.png</file>
+<file>images/zoom-fit-width-32.png</file>
 <file>images/go-first-24.png</file>
 <file>images/go-first-32.png</file>
 <file>images/go-last-24.png</file>
@@ -18,14 +18,14 @@
 <file>images/layout-portrait-32.png</file>
 <file>images/page-setup-24.png</file>
 <file>images/page-setup-32.png</file>
-<file>images/print-24.png</file>
-<file>images/print-32.png</file>
-<file>images/view-page-multi-24.png</file>
-<file>images/view-page-multi-32.png</file>
-<file>images/view-page-one-24.png</file>
-<file>images/view-page-one-32.png</file>
-<file>images/view-page-sided-24.png</file>
-<file>images/view-page-sided-32.png</file>
+<file>images/printer-24.png</file>
+<file>images/printer-32.png</file>
+<file>images/view-pages-overview-24.png</file>
+<file>images/view-pages-overview-32.png</file>
+<file>images/view-pages-single-24.png</file>
+<file>images/view-pages-single-32.png</file>
+<file>images/view-pages-facing-24.png</file>
+<file>images/view-pages-facing-32.png</file>
 <file>images/zoom-in-24.png</file>
 <file>images/zoom-in-32.png</file>
 <file>images/zoom-out-24.png</file>
diff --git a/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp b/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp
index c5b845f4ec..5a5ba1d0a8 100644
--- a/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/qtbase/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -702,13 +702,14 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
         else
             options.grayscale->setChecked(true);
 
-        // keep duplex value explicitly set by user, if any, and selected printer supports it;
-        // use device default otherwise
+        // duplex priorities to be as follows:
+        // 1) a user-selected duplex value in the dialog has highest prority
+        // 2) duplex value set in the QPrinter
         QPrint::DuplexMode duplex;
         if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
             duplex = explicitDuplexMode;
         else
-            duplex = top->d->m_currentPrintDevice.defaultDuplexMode();
+            duplex = static_cast<QPrint::DuplexMode>(p->duplex());
         switch (duplex) {
         case QPrint::DuplexNone:
             options.noDuplex->setChecked(true); break;
@@ -1242,10 +1243,10 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
             QString filename = widget.filename->text();
             widget.filename->setText(filename);
             widget.lOutput->setEnabled(true);
-            if (optionsPane)
-                optionsPane->selectPrinter(QPrinter::PdfFormat);
             printer->setOutputFormat(QPrinter::PdfFormat);
             m_currentPrintDevice = QPrintDevice();
+            if (optionsPane)
+                optionsPane->selectPrinter(QPrinter::PdfFormat);
             return;
         }
     }
diff --git a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
index 39575d5f57..23b7e89538 100644
--- a/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/qtbase/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -352,7 +352,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
 static inline void qt_setupActionIcon(QAction *action, QLatin1String name)
 {
     QLatin1String imagePrefix(":/qt-project.org/dialogs/qprintpreviewdialog/images/");
-    QIcon icon;
+    QIcon icon = QIcon::fromTheme(name);
     icon.addFile(imagePrefix + name + QLatin1String("-24.png"), QSize(24, 24));
     icon.addFile(imagePrefix + name + QLatin1String("-32.png"), QSize(32, 32));
     action->setIcon(icon);
@@ -383,8 +383,8 @@ void QPrintPreviewDialogPrivate::setupActions()
     fitPageAction->setObjectName(QLatin1String("fitPageAction"));
     fitWidthAction->setCheckable(true);
     fitPageAction->setCheckable(true);
-    qt_setupActionIcon(fitWidthAction, QLatin1String("fit-width"));
-    qt_setupActionIcon(fitPageAction, QLatin1String("fit-page"));
+    qt_setupActionIcon(fitWidthAction, QLatin1String("zoom-fit-width"));
+    qt_setupActionIcon(fitPageAction, QLatin1String("zoom-fit-page"));
     QObject::connect(fitGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_fit(QAction*)));
 
     // Zoom
@@ -410,9 +410,9 @@ void QPrintPreviewDialogPrivate::setupActions()
     singleModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show single page"));
     facingModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show facing pages"));
     overviewModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show overview of all pages"));
-    qt_setupActionIcon(singleModeAction, QLatin1String("view-page-one"));
-    qt_setupActionIcon(facingModeAction, QLatin1String("view-page-sided"));
-    qt_setupActionIcon(overviewModeAction, QLatin1String("view-page-multi"));
+    qt_setupActionIcon(singleModeAction, QLatin1String("view-pages-single"));
+    qt_setupActionIcon(facingModeAction, QLatin1String("view-pages-facing"));
+    qt_setupActionIcon(overviewModeAction, QLatin1String("view-pages-overview"));
     singleModeAction->setObjectName(QLatin1String("singleModeAction"));
     facingModeAction->setObjectName(QLatin1String("facingModeAction"));
     overviewModeAction->setObjectName(QLatin1String("overviewModeAction"));
@@ -426,7 +426,7 @@ void QPrintPreviewDialogPrivate::setupActions()
     printerGroup = new QActionGroup(q);
     printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
     pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
-    qt_setupActionIcon(printAction, QLatin1String("print"));
+    qt_setupActionIcon(printAction, QLatin1String("printer"));
     qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
     QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
     QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
diff --git a/qtbase/src/sql/kernel/qsqlquery.cpp b/qtbase/src/sql/kernel/qsqlquery.cpp
index 32c6166c79..60afef10c3 100644
--- a/qtbase/src/sql/kernel/qsqlquery.cpp
+++ b/qtbase/src/sql/kernel/qsqlquery.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtSql module of the Qt Toolkit.
@@ -377,6 +377,10 @@ bool QSqlQuery::exec(const QString& query)
     QElapsedTimer t;
     t.start();
 #endif
+    if (!driver()) {
+        qWarning("QSqlQuery::exec: called before driver has been set up");
+        return false;
+    }
     if (d->ref.loadRelaxed() != 1) {
         bool fo = isForwardOnly();
         *this = QSqlQuery(driver()->createResult());
diff --git a/qtbase/src/testlib/qabstractitemmodeltester.cpp b/qtbase/src/testlib/qabstractitemmodeltester.cpp
index 8efb9c53d4..ce062f66d7 100644
--- a/qtbase/src/testlib/qabstractitemmodeltester.cpp
+++ b/qtbase/src/testlib/qabstractitemmodeltester.cpp
@@ -454,7 +454,7 @@ void QAbstractItemModelTesterPrivate::parent()
 
     // Common error test #2, make sure that a second level index has a parent
     // that is the first level index.
-    if (model->rowCount(topIndex) > 0) {
+    if (model->rowCount(topIndex) > 0 && model->columnCount(topIndex) > 0) {
         QModelIndex childIndex = model->index(0, 0, topIndex);
         MODELTESTER_VERIFY(childIndex.isValid());
         MODELTESTER_COMPARE(model->parent(childIndex), topIndex);
diff --git a/qtbase/src/testlib/qasciikey.cpp b/qtbase/src/testlib/qasciikey.cpp
index 9a308da2bc..93498b256f 100644
--- a/qtbase/src/testlib/qasciikey.cpp
+++ b/qtbase/src/testlib/qasciikey.cpp
@@ -498,6 +498,11 @@ char QTest::keyToAscii(Qt::Key key)
     case Qt::Key_LaunchE : return 0; // = 0x10b0,
     case Qt::Key_LaunchF : return 0; // = 0x10b1,
 
+    // Keypad navigation keys
+    case Qt::Key_Select : return 0; // = 0x01010000
+    case Qt::Key_Yes : return 0; // = 0x01010001
+    case Qt::Key_No : return 0; // = 0x01010002
+
     default: QTEST_ASSERT(false); return 0;
     }
 }
diff --git a/qtbase/src/testlib/qtestresult.cpp b/qtbase/src/testlib/qtestresult.cpp
index 88028aac6e..2e89930776 100644
--- a/qtbase/src/testlib/qtestresult.cpp
+++ b/qtbase/src/testlib/qtestresult.cpp
@@ -251,7 +251,8 @@ bool QTestResult::verify(bool statement, const char *statementStr,
 {
     QTEST_ASSERT(statementStr);
 
-    char msg[1024] = {'\0'};
+    char msg[1024];
+    msg[0] = '\0';
 
     if (QTestLog::verboseLevel() >= 2) {
         qsnprintf(msg, 1024, "QVERIFY(%s)", statementStr);
@@ -309,7 +310,8 @@ static bool compareHelper(bool success, const char *failureMsg,
                           bool hasValues = true)
 {
     const size_t maxMsgLen = 1024;
-    char msg[maxMsgLen] = {'\0'};
+    char msg[maxMsgLen];
+    msg[0] = '\0';
 
     QTEST_ASSERT(expected);
     QTEST_ASSERT(actual);
diff --git a/qtbase/src/widgets/dialogs/qcolordialog.cpp b/qtbase/src/widgets/dialogs/qcolordialog.cpp
index 4247731275..cb325be85c 100644
--- a/qtbase/src/widgets/dialogs/qcolordialog.cpp
+++ b/qtbase/src/widgets/dialogs/qcolordialog.cpp
@@ -78,7 +78,10 @@
 #include "qwindow.h"
 
 #include "private/qdialog_p.h"
+#include "private/qguiapplication_p.h"
 
+#include <qpa/qplatformservices.h>
+#include <qpa/qplatformintegration.h>
 #include <algorithm>
 
 QT_BEGIN_NAMESPACE
@@ -1611,6 +1614,20 @@ void QColorDialogPrivate::_q_newStandard(int r, int c)
 void QColorDialogPrivate::_q_pickScreenColor()
 {
     Q_Q(QColorDialog);
+
+    auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
+    if (platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {
+        if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) {
+            q->connect(colorPicker, &QPlatformServiceColorPicker::colorPicked, q,
+                       [q, colorPicker](const QColor &color) {
+                           colorPicker->deleteLater();
+                           q->setCurrentColor(color);
+                       });
+            colorPicker->pickColor();
+            return;
+        }
+    }
+
     if (!colorPickingEventFilter)
         colorPickingEventFilter = new QColorPickingEventFilter(this, q);
     q->installEventFilter(colorPickingEventFilter);
diff --git a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
index e120817edc..8ea36b5427 100644
--- a/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/qtbase/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -400,12 +400,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
         const QString tooltip = index.isValid() ?
               d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision) :
               QString();
-        QRect rect;
-        if (index.isValid()) {
-            const QRect r = view->visualRect(index);
-            rect = QRect(view->mapToGlobal(r.topLeft()), r.size());
-        }
-        QToolTip::showText(he->globalPos(), tooltip, view, rect);
+        QToolTip::showText(he->globalPos(), tooltip, view->viewport(), option.rect);
         event->setAccepted(!tooltip.isEmpty());
         break;
         }
diff --git a/qtbase/src/widgets/itemviews/qlistview.cpp b/qtbase/src/widgets/itemviews/qlistview.cpp
index 2b34476642..eebfaa030e 100644
--- a/qtbase/src/widgets/itemviews/qlistview.cpp
+++ b/qtbase/src/widgets/itemviews/qlistview.cpp
@@ -3386,6 +3386,7 @@ void QIconModeViewBase::updateContentsSize()
 */
 void QListView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
 {
+    QAbstractItemView::currentChanged(current, previous);
 #ifndef QT_NO_ACCESSIBILITY
     if (QAccessible::isActive()) {
         if (current.isValid()) {
@@ -3396,7 +3397,6 @@ void QListView::currentChanged(const QModelIndex &current, const QModelIndex &pr
         }
     }
 #endif
-    QAbstractItemView::currentChanged(current, previous);
 }
 
 /*!
diff --git a/qtbase/src/widgets/itemviews/qtableview.cpp b/qtbase/src/widgets/itemviews/qtableview.cpp
index 934ac581b2..f79bb24249 100644
--- a/qtbase/src/widgets/itemviews/qtableview.cpp
+++ b/qtbase/src/widgets/itemviews/qtableview.cpp
@@ -1013,6 +1013,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &
 int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const
 {
     Q_Q(const QTableView);
+    const int oldHint = hint;
     QWidget *editor = editorForIndex(index).widget.data();
     if (editor && persistent.contains(editor)) {
         hint = qMax(hint, editor->sizeHint().width());
@@ -1021,6 +1022,17 @@ int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, con
         hint = qBound(min, hint, max);
     }
     hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width());
+
+    if (hasSpans()) {
+        auto span = spans.spanAt(index.column(), index.row());
+        if (span && span->m_left == index.column() && span->m_top == index.row()) {
+            // spans are screwed up when sections are moved
+            const auto left = logicalColumn(span->m_left);
+            for (int i = 1; i <= span->width(); ++i)
+               hint -= q->columnWidth(visualColumn(left + i));
+        }
+        hint = std::max(hint, oldHint);
+    }
     return hint;
 }
 
@@ -1053,6 +1065,11 @@ int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QS
         option.rect.setHeight(height);
         option.rect.setX(q->columnViewportPosition(index.column()));
         option.rect.setWidth(q->columnWidth(index.column()));
+        if (hasSpans()) {
+            auto span = spans.spanAt(index.column(), index.row());
+            if (span && span->m_left == index.column() && span->m_top == index.row())
+                option.rect.setWidth(std::max(option.rect.width(), visualSpanRect(*span).width()));
+        }
         // 1px less space when grid is shown (see drawCell)
         if (showGrid)
             option.rect.setWidth(option.rect.width() - 1);
diff --git a/qtbase/src/widgets/kernel/qaction.h b/qtbase/src/widgets/kernel/qaction.h
index 258a1ea0a0..737c1e8285 100644
--- a/qtbase/src/widgets/kernel/qaction.h
+++ b/qtbase/src/widgets/kernel/qaction.h
@@ -81,7 +81,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject
     Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
     Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
     Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
-    Q_PROPERTY(Priority priority READ priority WRITE setPriority)
+    Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY changed)
 
 public:
     // note this is copied into qplatformmenu.h, which must stay in sync
diff --git a/qtbase/src/widgets/kernel/qwidget.cpp b/qtbase/src/widgets/kernel/qwidget.cpp
index 9eba1e001e..26f6d27e18 100644
--- a/qtbase/src/widgets/kernel/qwidget.cpp
+++ b/qtbase/src/widgets/kernel/qwidget.cpp
@@ -5296,7 +5296,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
         QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
                                                          (source->d_func());
         if (!sourced->context) {
-            const QRegion effectRgn(rgn.boundingRect());
+            const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
             QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
             sourced->context = &context;
             if (!sharedPainter) {
@@ -5328,6 +5328,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
         }
     }
 #endif // QT_CONFIG(graphicseffect)
+    flags = flags & ~UseEffectRegionBounds;
 
     const bool alsoOnScreen = flags & DrawPaintOnScreen;
     const bool recursive = flags & DrawRecursive;
diff --git a/qtbase/src/widgets/kernel/qwidget_p.h b/qtbase/src/widgets/kernel/qwidget_p.h
index eef6b8fa2c..c432f4b5d5 100644
--- a/qtbase/src/widgets/kernel/qwidget_p.h
+++ b/qtbase/src/widgets/kernel/qwidget_p.h
@@ -229,7 +229,8 @@ public:
         DontSubtractOpaqueChildren = 0x10,
         DontDrawOpaqueChildren = 0x20,
         DontDrawNativeChildren = 0x40,
-        DontSetCompositionMode = 0x80
+        DontSetCompositionMode = 0x80,
+        UseEffectRegionBounds = 0x100
     };
     Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag)
     Q_FLAG(DrawWidgetFlags)
diff --git a/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp b/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp
index 02880b34da..0d44e1326d 100644
--- a/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp
+++ b/qtbase/src/widgets/kernel/qwidgetrepaintmanager.cpp
@@ -1018,7 +1018,8 @@ void QWidgetRepaintManager::paintAndFlush()
 
     // Paint the rest with composition.
     if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
-        QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
+        QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive
+                | QWidgetPrivate::UseEffectRegionBounds;
         tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, nullptr, this);
     }
 
diff --git a/qtbase/src/widgets/styles/qfusionstyle.cpp b/qtbase/src/widgets/styles/qfusionstyle.cpp
index f4345d97c4..962912c838 100644
--- a/qtbase/src/widgets/styles/qfusionstyle.cpp
+++ b/qtbase/src/widgets/styles/qfusionstyle.cpp
@@ -1772,14 +1772,6 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
             proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
         }
         break;
-    case CE_PushButtonLabel:
-        if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
-            QStyleOptionButton b(*button);
-            // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
-            b.state &= ~(State_On | State_Sunken);
-            QCommonStyle::drawControl(element, &b, painter, widget);
-        }
-        break;
     case CE_MenuBarEmptyArea:
         painter->save();
     {
diff --git a/qtbase/src/widgets/util/qcompleter.cpp b/qtbase/src/widgets/util/qcompleter.cpp
index 18b24063d8..ef7207a8a3 100644
--- a/qtbase/src/widgets/util/qcompleter.cpp
+++ b/qtbase/src/widgets/util/qcompleter.cpp
@@ -1120,6 +1120,8 @@ void QCompleter::setModel(QAbstractItemModel *model)
 {
     Q_D(QCompleter);
     QAbstractItemModel *oldModel = d->proxy->sourceModel();
+    if (oldModel == model)
+        return;
 #if QT_CONFIG(filesystemmodel)
     if (qobject_cast<const QFileSystemModel *>(oldModel))
         setCompletionRole(Qt::EditRole); // QTBUG-54642, clear FileNameRole set by QFileSystemModel
diff --git a/qtbase/src/widgets/widgets/qabstractbutton.cpp b/qtbase/src/widgets/widgets/qabstractbutton.cpp
index a128b23950..dc40bf62fb 100644
--- a/qtbase/src/widgets/widgets/qabstractbutton.cpp
+++ b/qtbase/src/widgets/widgets/qabstractbutton.cpp
@@ -56,6 +56,7 @@
 #ifndef QT_NO_ACCESSIBILITY
 #include "qaccessible.h"
 #endif
+#include <qpa/qplatformtheme.h>
 
 #include <algorithm>
 
@@ -1076,19 +1077,19 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e)
 {
     Q_D(QAbstractButton);
     bool next = true;
-    switch (e->key()) {
-    case Qt::Key_Enter:
-    case Qt::Key_Return:
-        e->ignore();
-        break;
-    case Qt::Key_Select:
-    case Qt::Key_Space:
-        if (!e->isAutoRepeat()) {
-            setDown(true);
-            repaint();
-            d->emitPressed();
-        }
-        break;
+
+    const auto key = static_cast<Qt::Key>(e->key());
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(key) && !e->isAutoRepeat()) {
+        setDown(true);
+        repaint();
+        d->emitPressed();
+        return;
+    }
+
+    switch (key) {
     case Qt::Key_Up:
         next = false;
         Q_FALLTHROUGH();
@@ -1153,15 +1154,15 @@ void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
     if (!e->isAutoRepeat())
         d->repeatTimer.stop();
 
-    switch (e->key()) {
-    case Qt::Key_Select:
-    case Qt::Key_Space:
-        if (!e->isAutoRepeat() && d->down)
-            d->click();
-        break;
-    default:
-        e->ignore();
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(static_cast<Qt::Key>(e->key())) && !e->isAutoRepeat() && d->down) {
+        d->click();
+        return;
     }
+
+    e->ignore();
 }
 
 /*!\reimp
diff --git a/qtbase/src/widgets/widgets/qcombobox.cpp b/qtbase/src/widgets/widgets/qcombobox.cpp
index 7a496c27e0..0a3d96647b 100644
--- a/qtbase/src/widgets/widgets/qcombobox.cpp
+++ b/qtbase/src/widgets/widgets/qcombobox.cpp
@@ -3352,7 +3352,23 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
 
     Move move = NoMove;
     int newIndex = currentIndex();
-    switch (e->key()) {
+
+    bool pressLikeButton = !d->lineEdit;
+#ifdef QT_KEYPAD_NAVIGATION
+    pressLikeButton |= QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus();
+#endif
+    auto key = static_cast<Qt::Key>(e->key());
+    if (pressLikeButton) {
+        const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                             ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                             .value<QList<Qt::Key>>();
+        if (buttonPressKeys.contains(key)) {
+            showPopup();
+            return;
+        }
+    }
+
+    switch (key) {
     case Qt::Key_Up:
         if (e->modifiers() & Qt::ControlModifier)
             break; // pass to line edit for auto completion
@@ -3394,26 +3410,11 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
             return;
         }
         break;
-    case Qt::Key_Space:
-        if (!d->lineEdit) {
-            showPopup();
-            return;
-        }
-        break;
-    case Qt::Key_Enter:
-    case Qt::Key_Return:
     case Qt::Key_Escape:
         if (!d->lineEdit)
             e->ignore();
         break;
 #ifdef QT_KEYPAD_NAVIGATION
-    case Qt::Key_Select:
-        if (QApplicationPrivate::keypadNavigationEnabled()
-                && (!hasEditFocus() || !d->lineEdit)) {
-            showPopup();
-            return;
-        }
-        break;
     case Qt::Key_Left:
     case Qt::Key_Right:
         if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())
diff --git a/qtbase/src/widgets/widgets/qdatetimeedit_p.h b/qtbase/src/widgets/widgets/qdatetimeedit_p.h
index d36b6f8f9a..e0df5b5158 100644
--- a/qtbase/src/widgets/widgets/qdatetimeedit_p.h
+++ b/qtbase/src/widgets/widgets/qdatetimeedit_p.h
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtWidgets module of the Qt Toolkit.
diff --git a/qtbase/src/widgets/widgets/qgroupbox.cpp b/qtbase/src/widgets/widgets/qgroupbox.cpp
index 02a0bed325..3f3eccc370 100644
--- a/qtbase/src/widgets/widgets/qgroupbox.cpp
+++ b/qtbase/src/widgets/widgets/qgroupbox.cpp
@@ -54,6 +54,8 @@
 #include "qaccessible.h"
 #endif
 #include <private/qwidget_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
 
 #include "qdebug.h"
 
@@ -360,7 +362,10 @@ bool QGroupBox::event(QEvent *e)
         return true;
     case QEvent::KeyPress: {
         QKeyEvent *k = static_cast<QKeyEvent*>(e);
-        if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+        const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                             ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                             .value<QList<Qt::Key>>();
+        if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast<Qt::Key>(k->key()))) {
             d->pressedControl = QStyle::SC_GroupBoxCheckBox;
             update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this));
             return true;
@@ -369,7 +374,10 @@ bool QGroupBox::event(QEvent *e)
     }
     case QEvent::KeyRelease: {
         QKeyEvent *k = static_cast<QKeyEvent*>(e);
-        if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+        const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                             ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                             .value<QList<Qt::Key>>();
+        if (!k->isAutoRepeat() && buttonPressKeys.contains(static_cast<Qt::Key>(k->key()))) {
             bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
                            || d->pressedControl == QStyle::SC_GroupBoxCheckBox);
             d->pressedControl = QStyle::SC_None;
diff --git a/qtbase/src/widgets/widgets/qlabel.cpp b/qtbase/src/widgets/widgets/qlabel.cpp
index 30ff80cbb0..cf2605c17c 100644
--- a/qtbase/src/widgets/widgets/qlabel.cpp
+++ b/qtbase/src/widgets/widgets/qlabel.cpp
@@ -421,9 +421,6 @@ void QLabel::setPixmap(const QPixmap &pixmap)
         d->pixmap = new QPixmap(pixmap);
     }
 
-    if (d->pixmap->depth() == 1 && !d->pixmap->mask())
-        d->pixmap->setMask(*((QBitmap *)d->pixmap));
-
     d->updateLabel();
 }
 
diff --git a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
index 493c094cc1..d5f4b59017 100644
--- a/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
+++ b/qtbase/src/widgets/widgets/qtoolbararealayout.cpp
@@ -1367,7 +1367,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*
                 item.widgetItem = new QWidgetItemV2(toolBar);
                 toolBar->setOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
                 toolBar->setVisible(shown & 1);
-                toolBar->d_func()->setWindowState(floating, true, rect);
+                toolBar->d_func()->setWindowState(floating, false, rect);
 
                 item.preferredSize = item.size;
                 line.toolBarItems.append(item);
diff --git a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
index 212c0a2e13..3c77b1ba0b 100644
--- a/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
+++ b/qtbase/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -126,8 +126,7 @@ public:
 
 void tst_QtConcurrentIterateKernel::instantiate()
 {
-    auto future = startThreadEngine(new PrintFor(0, 40)).startAsynchronously();
-    future.waitForFinished();
+    startThreadEngine(new PrintFor(0, 40)).startBlocking();
     QCOMPARE(iterations.loadRelaxed(), 40);
 }
 
@@ -166,10 +165,8 @@ void tst_QtConcurrentIterateKernel::stresstest()
     const int times = 50;
     for (int i = 0; i < times; ++i) {
         counter.storeRelaxed(0);
-        // ThreadEngine will delete f when it finishes
-        auto f = new CountFor(0, iterations);
-        auto future = f->startAsynchronously();
-        future.waitForFinished();
+        CountFor f(0, iterations);
+        f.startBlocking();
         QCOMPARE(counter.loadRelaxed(), iterations);
     }
 }
@@ -177,11 +174,8 @@ void tst_QtConcurrentIterateKernel::stresstest()
 void tst_QtConcurrentIterateKernel::noIterations()
 {
     const int times = 20000;
-    for (int i = 0; i < times; ++i) {
-        auto future = startThreadEngine(new IterateKernel<TestIterator, void>(0, 0))
-                              .startAsynchronously();
-        future.waitForFinished();
-    }
+    for (int i = 0; i < times; ++i)
+        startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)).startBlocking();
 }
 
 QMutex threadsMutex;
@@ -236,10 +230,8 @@ void tst_QtConcurrentIterateKernel::throttling()
 
     threads.clear();
 
-    // ThreadEngine will delete f when it finishes
-    auto f = new ThrottleFor(0, totalIterations);
-    auto future = f->startAsynchronously();
-    future.waitForFinished();
+    ThrottleFor f(0, totalIterations);
+    f.startBlocking();
 
     QCOMPARE(iterations.loadRelaxed(), totalIterations);
 
diff --git a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
index ac7be7acdd..81bc64c8d9 100644
--- a/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
+++ b/qtbase/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -65,9 +65,16 @@ public:
 
 void tst_QtConcurrentThreadEngine::runDirectly()
 {
-    PrintUser *engine = new PrintUser();
-    QFuture<void> f = engine->startAsynchronously();
-    f.waitForFinished();
+    {
+        PrintUser engine;
+        engine.startSingleThreaded();
+        engine.startBlocking();
+    }
+    {
+        PrintUser *engine = new PrintUser();
+        QFuture<void> f = engine->startAsynchronously();
+        f.waitForFinished();
+    }
 }
 
 class StringResultUser : public ThreadEngine<QString>
@@ -99,10 +106,8 @@ public:
 
 void tst_QtConcurrentThreadEngine::result()
 {
-    // ThreadEngine will delete 'engine' when it finishes
-    auto engine = new StringResultUser();
-    auto future = engine->startAsynchronously();
-    QCOMPARE(future.result(), QString("Foo"));
+    StringResultUser engine;
+    QCOMPARE(*engine.startBlocking(), QString("Foo"));
 }
 
 class VoidResultUser : public ThreadEngine<void>
@@ -128,9 +133,17 @@ public:
 
 void tst_QtConcurrentThreadEngine::runThroughStarter()
 {
-    ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
-    QFuture<QString> f = starter.startAsynchronously();
-    QCOMPARE(f.result(), QString("Foo"));
+    {
+        ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
+        QFuture<QString>  f = starter.startAsynchronously();
+        QCOMPARE(f.result(), QString("Foo"));
+    }
+
+    {
+        ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
+        QString str = starter.startBlocking();
+        QCOMPARE(str, QString("Foo"));
+    }
 }
 
 class CancelUser : public ThreadEngine<void>
@@ -213,6 +226,12 @@ void tst_QtConcurrentThreadEngine::throttle()
         f.waitForFinished();
         QCOMPARE(count.loadRelaxed(), 0);
     }
+
+    for (int i = 0; i < repeats; ++i) {
+        ThrottleAlwaysUser t;
+        t.startBlocking();
+        QCOMPARE(count.loadRelaxed(), 0);
+    }
 }
 
 QSet<QThread *> threads;
@@ -249,17 +268,35 @@ void tst_QtConcurrentThreadEngine::threadCount()
 {
     const int repeats = 10;
     for (int i = 0; i < repeats; ++i) {
+        ThreadCountUser t;
+        t.startBlocking();
+        int count = threads.count();
+        int count_expected = QThreadPool::globalInstance()->maxThreadCount() + 1; // +1 for the main thread.
+        if (count != count_expected)
+            QEXPECT_FAIL("", "QTBUG-23333", Abort);
+        QCOMPARE(count, count_expected);
+
         (new ThreadCountUser())->startAsynchronously().waitForFinished();
-        const auto count = threads.count();
-        const auto maxThreadCount = QThreadPool::globalInstance()->maxThreadCount();
-        QVERIFY(count <= maxThreadCount);
-        QVERIFY(!threads.contains(QThread::currentThread()));
+        count = threads.count();
+        count_expected = QThreadPool::globalInstance()->maxThreadCount();
+        if (count != count_expected)
+            QEXPECT_FAIL("", "QTBUG-23333", Abort);
+        QCOMPARE(count, count_expected);
     }
 
     // Set the finish flag immediately, this should give us one thread only.
     for (int i = 0; i < repeats; ++i) {
+        ThreadCountUser t(true /*finishImmediately*/);
+        t.startBlocking();
+        int count = threads.count();
+        if (count != 1)
+            QEXPECT_FAIL("", "QTBUG-23333", Abort);
+        QCOMPARE(count, 1);
+
         (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished();
-        const auto count = threads.count();
+        count = threads.count();
+        if (count != 1)
+            QEXPECT_FAIL("", "QTBUG-23333", Abort);
         QCOMPARE(count, 1);
         QVERIFY(!threads.contains(QThread::currentThread()));
     }
@@ -400,6 +437,7 @@ public:
 
 void tst_QtConcurrentThreadEngine::exceptions()
 {
+    // Asynchronous mode:
     {
         bool caught = false;
         try  {
@@ -412,6 +450,32 @@ void tst_QtConcurrentThreadEngine::exceptions()
         QVERIFY2(caught, "did not get exception");
     }
 
+    // Blocking mode:
+    // test throwing the exception from a worker thread.
+    {
+        bool caught = false;
+        try  {
+            QtConcurrentExceptionThrower e(QThread::currentThread());
+            e.startBlocking();
+        } catch (const QException &) {
+            caught = true;
+        }
+        QVERIFY2(caught, "did not get exception");
+    }
+
+    // test throwing the exception from the main thread (different code path)
+    {
+        bool caught = false;
+        try  {
+            QtConcurrentExceptionThrower e(0);
+            e.startBlocking();
+        } catch (const QException &) {
+            caught = true;
+        }
+        QVERIFY2(caught, "did not get exception");
+    }
+
+    // Asynchronous mode:
     {
         bool caught = false;
         try  {
@@ -423,6 +487,31 @@ void tst_QtConcurrentThreadEngine::exceptions()
         }
         QVERIFY2(caught, "did not get exception");
     }
+
+    // Blocking mode:
+    // test throwing the exception from a worker thread.
+    {
+        bool caught = false;
+        try  {
+            UnrelatedExceptionThrower e(QThread::currentThread());
+            e.startBlocking();
+        } catch (const QUnhandledException &) {
+            caught = true;
+        }
+        QVERIFY2(caught, "did not get exception");
+    }
+
+    // test throwing the exception from the main thread (different code path)
+    {
+        bool caught = false;
+        try  {
+            UnrelatedExceptionThrower e(0);
+            e.startBlocking();
+        } catch (const QUnhandledException &) {
+            caught = true;
+        }
+        QVERIFY2(caught, "did not get exception");
+    }
 }
 
 #endif
diff --git a/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
index 4968742110..f4c3fb711d 100644
--- a/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
+++ b/qtbase/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
@@ -42,6 +42,7 @@ private slots:
     void writeBlock_data();
     void writeBlock();
     void seek();
+    void invalidSeeks();
     void seekTest_data();
     void seekTest();
     void read_rawdata();
@@ -286,6 +287,29 @@ void tst_QBuffer::seek()
     QCOMPARE(buffer.size(), pos);
 }
 
+void tst_QBuffer::invalidSeeks()
+{
+    if constexpr (sizeof(qsizetype) == sizeof(qint64)) {
+        // sizeof(qsizetype) == sizeof(qint64), so +1 would overflow
+        QSKIP("This is a 32-bit-only test.");
+    } else {
+        QBuffer buffer;
+        buffer.open(QIODevice::WriteOnly);
+        QCOMPARE(buffer.buffer().size(), qsizetype(0));
+        QCOMPARE(buffer.pos(), qint64(0));
+        constexpr qint64 MaxQByteArrayCapacity = (std::numeric_limits<qsizetype>::max)();
+        // this should fail fast, not after trying to allocate nearly 2 GiB of data,
+        // potentially crashing in the process:
+        QVERIFY(!buffer.seek(2 * MaxQByteArrayCapacity - 1));
+        QCOMPARE(buffer.buffer().size(), qsizetype(0));
+        QCOMPARE(buffer.pos(), qint64(0));
+        // ditto:
+        QVERIFY(!buffer.seek(MaxQByteArrayCapacity + 1));
+        QCOMPARE(buffer.buffer().size(), qsizetype(0));
+        QCOMPARE(buffer.pos(), qint64(0));
+    }
+}
+
 void tst_QBuffer::seekTest_data()
 {
     writeBlock_data();
diff --git a/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index da5327594c..4a04e0f7c6 100644
--- a/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -561,7 +561,8 @@ protected:
     qint64 readData(char *data, qint64 maxSize) override
     {
         maxSize = qMin(maxSize, qint64(buf->size() - offset));
-        memcpy(data, buf->constData() + offset, maxSize);
+        if (maxSize > 0)
+            memcpy(data, buf->constData() + offset, maxSize);
         offset += maxSize;
         return maxSize;
     }
@@ -604,13 +605,15 @@ protected:
     qint64 readData(char *data, qint64 maxSize) override
     {
         maxSize = qMin(maxSize, qint64(buf.size() - pos()));
-        memcpy(data, buf.constData() + pos(), maxSize);
+        if (maxSize > 0)
+            memcpy(data, buf.constData() + pos(), maxSize);
         return maxSize;
     }
     qint64 writeData(const char *data, qint64 maxSize) override
     {
         maxSize = qMin(maxSize, qint64(buf.size() - pos()));
-        memcpy(buf.data() + pos(), data, maxSize);
+        if (maxSize > 0)
+            memcpy(buf.data() + pos(), data, maxSize);
         return maxSize;
     }
 
diff --git a/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index db60bead64..f345a44414 100644
--- a/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/qtbase/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -1,7 +1,8 @@
 /****************************************************************************
 **
 ** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2020 Intel Corporation.
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 Intel Corporation.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the test suite of the Qt Toolkit.
@@ -150,6 +151,8 @@ private slots:
     void startStopStartStopBuffers();
     void processEventsInAReadyReadSlot_data();
     void processEventsInAReadyReadSlot();
+    void startFromCurrentWorkingDir_data();
+    void startFromCurrentWorkingDir();
 
     // keep these at the end, since they use lots of processes and sometimes
     // caused obscure failures to occur in tests that followed them (esp. on the Mac)
@@ -2731,5 +2734,94 @@ void tst_QProcess::finishProcessBeforeReadingDone_deprecated()
 
 #endif
 
+enum class ChdirMode {
+    None = 0,
+    InParent,
+    InChild
+};
+Q_DECLARE_METATYPE(ChdirMode)
+
+void tst_QProcess::startFromCurrentWorkingDir_data()
+{
+    qRegisterMetaType<ChdirMode>();
+    QTest::addColumn<QString>("programPrefix");
+    QTest::addColumn<ChdirMode>("chdirMode");
+    QTest::addColumn<bool>("success");
+
+    constexpr bool IsWindows = true
+#ifdef Q_OS_UNIX
+            && false
+#endif
+            ;
+
+    // baseline: trying to execute the directory, this can't possibly succeed!
+    QTest::newRow("plain-same-cwd") << QString() << ChdirMode::None << false;
+
+    // cross-platform behavior: neither OS searches the setWorkingDirectory()
+    // dir without "./"
+    QTest::newRow("plain-child-chdir") << QString() << ChdirMode::InChild << false;
+
+    // cross-platform behavior: both OSes search the parent's CWD with "./"
+    QTest::newRow("prefixed-parent-chdir") << "./" << ChdirMode::InParent << true;
+
+    // opposite behaviors: Windows searches the parent's CWD and Unix searches
+    // the child's with "./"
+    QTest::newRow("prefixed-child-chdir") << "./" << ChdirMode::InChild << !IsWindows;
+
+    // Windows searches the parent's CWD without "./"
+    QTest::newRow("plain-parent-chdir") << QString() << ChdirMode::InParent << IsWindows;
+}
+
+void tst_QProcess::startFromCurrentWorkingDir()
+{
+    QFETCH(QString, programPrefix);
+    QFETCH(ChdirMode, chdirMode);
+    QFETCH(bool, success);
+
+    QProcess process;
+    qRegisterMetaType<QProcess::ProcessError>();
+    QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
+    QVERIFY(errorSpy.isValid());
+
+    // both the dir name and the executable name
+    const QString target = QStringLiteral("testProcessNormal");
+    process.setProgram(programPrefix + target);
+
+#ifdef Q_OS_UNIX
+    // Reset PATH, to be sure it doesn't contain . or the empty path.
+    // We can't do this on Windows because DLLs are searched in PATH
+    // and Windows always searches "." anyway.
+    auto restoreEnv = qScopeGuard([old = qgetenv("PATH")] {
+        qputenv("PATH", old);
+    });
+    qputenv("PATH", "/");
+#endif
+
+    switch (chdirMode) {
+    case ChdirMode::InParent: {
+        auto restoreCwd = qScopeGuard([old = QDir::currentPath()] {
+            QDir::setCurrent(old);
+        });
+        QVERIFY(QDir::setCurrent(target));
+        process.start();
+        break;
+    }
+    case ChdirMode::InChild:
+        process.setWorkingDirectory(target);
+        Q_FALLTHROUGH();
+    case ChdirMode::None:
+        process.start();
+        break;
+    }
+
+    QCOMPARE(process.waitForStarted(), success);
+    QCOMPARE(errorSpy.count(), int(!success));
+    if (success) {
+        QVERIFY(process.waitForFinished());
+    } else {
+        QCOMPARE(process.error(), QProcess::FailedToStart);
+    }
+}
+
 QTEST_MAIN(tst_QProcess)
 #include "tst_qprocess.moc"
diff --git a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
index e1ea7a4552..90972caa57 100644
--- a/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
+++ b/qtbase/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
@@ -117,6 +117,7 @@ private Q_SLOTS:
     void shouldPropagateDropAfterLastRow_data();
     void shouldPropagateDropAfterLastRow();
     void qtbug91788();
+    void qtbug91878();
 
 private:
     QStandardItemModel mod;
@@ -843,6 +844,22 @@ void tst_QConcatenateTablesProxyModel::qtbug91788()
     QCOMPARE(proxyConcat.columnCount(), 0);
 }
 
+void tst_QConcatenateTablesProxyModel::qtbug91878()
+{
+    QStandardItemModel m;
+    m.setRowCount(4);
+    m.setColumnCount(4);
+
+    QConcatenateTablesProxyModel pm;
+    QSortFilterProxyModel proxyFilter;
+    proxyFilter.setSourceModel(&pm);
+    proxyFilter.setFilterFixedString("something");
+    pm.addSourceModel(&m);  // This should not assert
+
+    QCOMPARE(pm.columnCount(), 4);
+    QCOMPARE(pm.rowCount(), 4);
+}
+
 QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel)
 
 #include "tst_qconcatenatetablesproxymodel.moc"
diff --git a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 9bd66c0835..ed4a0bae5d 100644
--- a/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/qtbase/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -158,6 +158,7 @@ private slots:
     void nullReceiver();
     void functorReferencesConnection();
     void disconnectDisconnects();
+    void declarativeData();
 };
 
 struct QObjectCreatedOnShutdown
@@ -7679,5 +7680,81 @@ void tst_QObject::disconnectDisconnects()
 Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value);
 Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value);
 
+#ifdef QT_BUILD_INTERNAL
+/*
+    Since QObjectPrivate stores the declarativeData pointer in a union with the pointer
+    to the currently destroyed child, calls to the QtDeclarative handlers need to be
+    correctly guarded. QTBUG-105286
+*/
+namespace QtDeclarative {
+static QAbstractDeclarativeData *theData;
+
+static void destroyed(QAbstractDeclarativeData *data, QObject *)
+{
+    QCOMPARE(data, theData);
+}
+static void signalEmitted(QAbstractDeclarativeData *data, QObject *, int, void **)
+{
+    QCOMPARE(data, theData);
+}
+// we can't use QCOMPARE in the next two functions, as they don't return void
+static int receivers(QAbstractDeclarativeData *data, const QObject *, int)
+{
+    QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+    return 0;
+}
+static bool isSignalConnected(QAbstractDeclarativeData *data, const QObject *, int)
+{
+    QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+    return true;
+}
+
+class Object : public QObject
+{
+    Q_OBJECT
+public:
+    using QObject::QObject;
+    ~Object()
+    {
+        if (Object *p = static_cast<Object *>(parent()))
+            p->emitSignal();
+    }
+
+    void emitSignal()
+    {
+        emit theSignal();
+    }
+
+signals:
+    void theSignal();
+};
+
+}
+#endif
+
+void tst_QObject::declarativeData()
+{
+#ifdef QT_BUILD_INTERNAL
+    QScopedValueRollback destroyed(QAbstractDeclarativeData::destroyed,
+                                   QtDeclarative::destroyed);
+    QScopedValueRollback signalEmitted(QAbstractDeclarativeData::signalEmitted,
+                                       QtDeclarative::signalEmitted);
+    QScopedValueRollback receivers(QAbstractDeclarativeData::receivers,
+                                   QtDeclarative::receivers);
+    QScopedValueRollback isSignalConnected(QAbstractDeclarativeData::isSignalConnected,
+                                           QtDeclarative::isSignalConnected);
+
+    QtDeclarative::Object p;
+    QObjectPrivate *priv = QObjectPrivate::get(&p);
+    priv->declarativeData = QtDeclarative::theData = new QAbstractDeclarativeData;
+
+    connect(&p, &QtDeclarative::Object::theSignal, &p, []{
+    });
+
+    QtDeclarative::Object *child = new QtDeclarative::Object;
+    child->setParent(&p);
+#endif
+}
+
 QTEST_MAIN(tst_QObject)
 #include "tst_qobject.moc"
diff --git a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index 0ea422ecbc..1a3256534b 100644
--- a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -70,15 +70,15 @@ static inline QString testSuiteWarning()
 
     QString result;
     QTextStream str(&result);
-    str << "\nCannot find the shared-mime-info test suite\nstarting from: "
+    str << "\nCannot find the shared-mime-info test suite\nin the parent of: "
         << QDir::toNativeSeparators(QDir::currentPath()) << "\n"
            "cd " << QDir::toNativeSeparators(QStringLiteral("tests/auto/corelib/mimetypes/qmimedatabase")) << "\n"
-           "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-10.zip\n"
-           "unzip Release-1-10.zip\n";
+           "wget https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/2.1/shared-mime-info-2.1.zip\n"
+           "unzip shared-mime-info-2.1.zip\n";
 #ifdef Q_OS_WIN
-    str << "mkdir testfiles\nxcopy /s Release-1-10 s-m-i\n";
+    str << "mkdir testfiles\nxcopy /s shared-mime-info-2.1 s-m-i\n";
 #else
-    str << "ln -s Release-1-10 s-m-i\n";
+    str << "ln -s shared-mime-info-2.1 s-m-i\n";
 #endif
     return result;
 }
@@ -154,7 +154,7 @@ void tst_QMimeDatabase::initTestCase()
     QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage), qPrintable(errorMessage));
 #endif
 
-    m_testSuite = QFINDTESTDATA("s-m-i/tests");
+    m_testSuite = QFINDTESTDATA("s-m-i/tests/mime-detection");
     if (m_testSuite.isEmpty())
         qWarning("%s", qPrintable(testSuiteWarning()));
 
@@ -611,7 +611,7 @@ void tst_QMimeDatabase::allMimeTypes()
     QVERIFY(!lst.isEmpty());
 
     // Hardcoding this is the only way to check both providers find the same number of mimetypes.
-    QCOMPARE(lst.count(), 779);
+    QCOMPARE(lst.count(), 811);
 
     foreach (const QMimeType &mime, lst) {
         const QString name = mime.name();
@@ -631,10 +631,9 @@ void tst_QMimeDatabase::suffixes_data()
 
     QTest::newRow("mimetype with a single pattern") << "application/pdf" << "*.pdf" << "pdf";
     QTest::newRow("mimetype with multiple patterns") << "application/x-kpresenter" << "*.kpr;*.kpt" << "kpr";
-    QTest::newRow("jpeg") << "image/jpeg" << "*.jpe;*.jpg;*.jpeg" << "jpeg";
-    //if (KMimeType::sharedMimeInfoVersion() > KDE_MAKE_VERSION(0, 60, 0)) {
-        QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp";
-    //}
+    // The preferred suffix for image/jpeg is *.jpg, as per https://bugs.kde.org/show_bug.cgi?id=176737
+    QTest::newRow("jpeg") << "image/jpeg" << "*.jpe;*.jpg;*.jpeg" << "jpg";
+    QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp";
     QTest::newRow("oasis text mimetype") << "application/vnd.oasis.opendocument.text" << "*.odt" << "odt";
     QTest::newRow("oasis presentation mimetype") << "application/vnd.oasis.opendocument.presentation" << "*.odp" << "odp";
     QTest::newRow("mimetype with multiple patterns") << "text/plain" << "*.asc;*.txt;*,v" << "txt";
diff --git a/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 3e58dd03cc..c8f82ef5d5 100644
--- a/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/qtbase/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -176,6 +176,8 @@ private Q_SLOTS:
     void fromToVariantConversions_data();
     void fromToVariantConversions();
 
+    void noLeakOnNameClash();
+
 private:
     QString testDataDir;
 };
@@ -3685,5 +3687,23 @@ void tst_QtJson::fromToVariantConversions()
     }
 }
 
+void tst_QtJson::noLeakOnNameClash()
+{
+    QJsonDocument doc = QJsonDocument::fromJson("{\"\":{\"\":0},\"\":0}");
+    QVERIFY(!doc.isNull());
+    const QJsonObject obj = doc.object();
+
+    // Removed the duplicate key.
+    QCOMPARE(obj.length(), 1);
+
+    // Retained the last of the duplicates.
+    const QJsonValue val = obj.begin().value();
+    QVERIFY(val.isDouble());
+    QCOMPARE(val.toDouble(), 0.0);
+
+    // It should not leak.
+    // In particular it should not forget to deref the container for the inner object.
+}
+
 QTEST_MAIN(tst_QtJson)
 #include "tst_qtjson.moc"
diff --git a/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index a59b58d57f..241c3e84ac 100644
--- a/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
+++ b/qtbase/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -63,6 +63,7 @@ private slots:
     void isValidId_data();
     void isValidId();
     void malformed();
+    void serialize();
     // Backend tests
     void utcTest();
     void icuTest();
@@ -947,6 +948,33 @@ void tst_QTimeZone::malformed()
         barf.offsetFromUtc(now);
 }
 
+void tst_QTimeZone::serialize()
+{
+    int parts = 0;
+#ifndef QT_NO_DEBUG_STREAM
+    qDebug() << QTimeZone(); // to verify no crash
+    parts++;
+#endif
+#ifndef QT_NO_DATASTREAM
+    QByteArray blob;
+    {
+        QDataStream stream(&blob, QIODevice::WriteOnly);
+        stream << QTimeZone("Europe/Oslo") << QTimeZone(420) << QTimeZone() << qint64(-1);
+    }
+    QDataStream stream(&blob, QIODevice::ReadOnly);
+    QTimeZone invalid, offset, oslo;
+    qint64 minusone;
+    stream >> oslo >> offset >> invalid >> minusone;
+    QCOMPARE(oslo, QTimeZone("Europe/Oslo"));
+    QCOMPARE(offset, QTimeZone(420));
+    QVERIFY(!invalid.isValid());
+    QCOMPARE(minusone, qint64(-1));
+    parts++;
+#endif
+    if (!parts)
+        QSKIP("No serialization enabled");
+}
+
 void tst_QTimeZone::utcTest()
 {
 #ifdef QT_BUILD_INTERNAL
diff --git a/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp b/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
index 05480c6dd2..70f4c75756 100644
--- a/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
+++ b/qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
@@ -324,6 +324,13 @@ void tst_QDBusInterface::notValid()
 
     QVERIFY(!interface.isValid());
     QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
+
+    // With a connection, but empty/null service and path specified
+    QDBusConnection con = QDBusConnection::sessionBus();
+    QVERIFY(con.isConnected());
+    QDBusInterface iface({}, {}, {}, con);
+    QVERIFY(!iface.isValid());
+    QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
 }
 
 void tst_QDBusInterface::notValidDerived()
diff --git a/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
index 874468c954..04ceb4ab65 100644
--- a/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
+++ b/qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
@@ -507,6 +507,10 @@ void tst_QKeySequence::toStringFromKeycode_data()
     QTest::newRow("Ctrl+Alt+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::AltModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Alt+Num+Del";
     QTest::newRow("Ctrl+Ins") << QKeySequence(Qt::ControlModifier | Qt::Key_Insert) << "Ctrl+Ins";
     QTest::newRow("Ctrl+Num+Ins(1)") << QKeySequence(Qt::Key_Insert | Qt::KeypadModifier | Qt::ControlModifier) << "Ctrl+Num+Ins";
+    QTest::newRow("Ctrl") << QKeySequence(Qt::Key_Control) << "Control";
+    QTest::newRow("Alt") << QKeySequence(Qt::Key_Alt) << "Alt";
+    QTest::newRow("Shift") << QKeySequence(Qt::Key_Shift) << "Shift";
+    QTest::newRow("Meta") << QKeySequence(Qt::Key_Meta) << "Meta";
 }
 
 void tst_QKeySequence::toStringFromKeycode()
diff --git a/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 15e0ecadaa..b4eca74283 100644
--- a/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/qtbase/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -81,6 +81,8 @@ private slots:
     void registerOpenTypePreferredNamesSystem();
     void registerOpenTypePreferredNamesApplication();
 
+    void stretchRespected();
+
 private:
     QString m_ledFont;
     QString m_testFont;
@@ -355,6 +357,28 @@ static QString testString()
     return QStringLiteral("foo bar");
 }
 
+void tst_QFontDatabase::stretchRespected()
+{
+    int italicId = QFontDatabase::addApplicationFont(m_testFontItalic);
+    QVERIFY(italicId != -1);
+
+    QVERIFY(!QFontDatabase::applicationFontFamilies(italicId).isEmpty());
+
+    QString italicFontName = QFontDatabase::applicationFontFamilies(italicId).first();
+
+    QFont italicFont = QFontDatabase().font(italicFontName,
+                                            QString::fromLatin1("Italic"), 14);
+    QVERIFY(italicFont.italic());
+
+    QFont italicStretchedFont = italicFont;
+    italicStretchedFont.setStretch( 400 );
+
+    QVERIFY(QFontMetricsF(italicFont).horizontalAdvance(QStringLiteral("foobar")) <
+            QFontMetricsF(italicStretchedFont).horizontalAdvance(QStringLiteral("foobar")));
+
+    QFontDatabase::removeApplicationFont(italicId);
+}
+
 void tst_QFontDatabase::condensedFontWidthNoFontMerging()
 {
     int regularFontId = QFontDatabase::addApplicationFont(m_testFont);
diff --git a/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 3d4a094c43..b423e11a99 100644
--- a/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/qtbase/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -281,6 +281,7 @@ private Q_SLOTS:
     void ioGetFromFileSpecial();
     void ioGetFromFile_data();
     void ioGetFromFile();
+    void ioGetFromFileUrl();
     void ioGetFromFtp_data();
     void ioGetFromFtp();
     void ioGetFromFtpWithReuse();
@@ -3300,6 +3301,18 @@ void tst_QNetworkReply::ioGetFromFile()
     QCOMPARE(reader.data, data);
 }
 
+void tst_QNetworkReply::ioGetFromFileUrl()
+{
+    // This immediately fails on non-windows platforms:
+    QNetworkRequest request(QUrl("file://unc-server/some/path"));
+    QNetworkReplyPtr reply(manager.get(request));
+    QSignalSpy finishedSpy(reply.get(), &QNetworkReply::finished);
+    // QTBUG-105618: This would, on non-Windows platforms, never happen because the signal
+    // was emitted before the constructor finished, leaving no chance at all to connect to the
+    // signal
+    QVERIFY(finishedSpy.wait());
+}
+
 void tst_QNetworkReply::ioGetFromFtp_data()
 {
     QTest::addColumn<QString>("fileName");
diff --git a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert
index 069fa6b341..4cc4d9a5ea 100644
--- a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert
+++ b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.cert
@@ -1,75 +1,34 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number: 0 (0x0)
-        Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=NO, ST=Oslo, L=Nydalen, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
-        Validity
-            Not Before: Dec  4 01:10:32 2007 GMT
-            Not After : Apr 21 01:10:32 2035 GMT
-        Subject: C=NO, ST=Oslo, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-            RSA Public Key: (1024 bit)
-                Modulus (1024 bit):
-                    00:a7:c8:a0:4a:c4:19:05:1b:66:ba:32:e2:d2:f1:
-                    1c:6f:17:82:e4:39:2e:01:51:90:db:04:34:32:11:
-                    21:c2:0d:6f:59:d8:53:90:54:3f:83:8f:a9:d3:b3:
-                    d5:ee:1a:9b:80:ae:c3:25:c9:5e:a5:af:4b:60:05:
-                    aa:a0:d1:91:01:1f:ca:04:83:e3:58:1c:99:32:45:
-                    84:70:72:58:03:98:4a:63:8b:41:f5:08:49:d2:91:
-                    02:60:6b:e4:64:fe:dd:a0:aa:74:08:e9:34:4c:91:
-                    5f:12:3d:37:4d:54:2c:ad:7f:5b:98:60:36:02:8c:
-                    3b:f6:45:f3:27:6a:9b:94:9d
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Basic Constraints: 
-                CA:FALSE
-            Netscape Comment: 
-                OpenSSL Generated Certificate
-            X509v3 Subject Key Identifier: 
-                21:85:04:3D:23:01:66:E5:F7:9F:1A:84:24:8A:AF:0A:79:F4:E5:AC
-            X509v3 Authority Key Identifier: 
-                DirName:/C=NO/ST=Oslo/L=Nydalen/O=Nokia Corporation and/or its subsidiary(-ies)/OU=Development/CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
-                serial:8E:A8:B4:E8:91:B7:54:2E
-
-    Signature Algorithm: sha1WithRSAEncryption
-        6d:57:5f:d1:05:43:f0:62:05:ec:2a:71:a5:dc:19:08:f2:c4:
-        a6:bd:bb:25:d9:ca:89:01:0e:e4:cf:1f:c1:8c:c8:24:18:35:
-        53:59:7b:c0:43:b4:32:e6:98:b2:a6:ef:15:05:0b:48:5f:e1:
-        a0:0c:97:a9:a1:77:d8:35:18:30:bc:a9:8f:d3:b7:54:c7:f1:
-        a9:9e:5d:e6:19:bf:f6:3c:5b:2b:d8:e4:3e:62:18:88:8b:d3:
-        24:e1:40:9b:0c:e6:29:16:62:ab:ea:05:24:70:36:aa:55:93:
-        ef:02:81:1b:23:10:a2:04:eb:56:95:75:fc:f8:94:b1:5d:42:
-        c5:3f:36:44:85:5d:3a:2e:90:46:8a:a2:b9:6f:87:ae:0c:15:
-        40:19:31:90:fc:3b:25:bb:ae:f1:66:13:0d:85:90:d9:49:34:
-        8f:f2:5d:f9:7a:db:4d:5d:27:f6:76:9d:35:8c:06:a6:4c:a3:
-        b1:b2:b6:6f:1d:d7:a3:00:fd:72:eb:9e:ea:44:a1:af:21:34:
-        7d:c7:42:e2:49:91:19:8b:c0:ad:ba:82:80:a8:71:70:f4:35:
-        31:91:63:84:20:95:e9:60:af:64:8b:cc:ff:3d:8a:76:74:3d:
-        c8:55:6d:e4:8e:c3:2b:1c:e8:42:18:ae:9f:e6:6b:9c:34:06:
-        ec:6a:f2:c3
 -----BEGIN CERTIFICATE-----
-MIIEEzCCAvugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMCTk8x
-DTALBgNVBAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xs
-dGVjaCBBU0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50
-cm9sbC5ubzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbTAe
-Fw0wNzEyMDQwMTEwMzJaFw0zNTA0MjEwMTEwMzJaMGMxCzAJBgNVBAYTAk5PMQ0w
-CwYDVQQIEwRPc2xvMRYwFAYDVQQKEw1Ucm9sbHRlY2ggQVNBMRQwEgYDVQQLEwtE
-ZXZlbG9wbWVudDEXMBUGA1UEAxMOZmx1a2UudHJvbGwubm8wgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBAKfIoErEGQUbZroy4tLxHG8XguQ5LgFRkNsENDIRIcIN
-b1nYU5BUP4OPqdOz1e4am4CuwyXJXqWvS2AFqqDRkQEfygSD41gcmTJFhHByWAOY
-SmOLQfUISdKRAmBr5GT+3aCqdAjpNEyRXxI9N01ULK1/W5hgNgKMO/ZF8ydqm5Sd
-AgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
-IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIYUEPSMBZuX3nxqEJIqv
-Cnn05awwgbsGA1UdIwSBszCBsKGBoqSBnzCBnDELMAkGA1UEBhMCTk8xDTALBgNV
-BAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xsdGVjaCBB
-U0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50cm9sbC5u
-bzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbYIJAI6otOiR
-t1QuMA0GCSqGSIb3DQEBBQUAA4IBAQBtV1/RBUPwYgXsKnGl3BkI8sSmvbsl2cqJ
-AQ7kzx/BjMgkGDVTWXvAQ7Qy5piypu8VBQtIX+GgDJepoXfYNRgwvKmP07dUx/Gp
-nl3mGb/2PFsr2OQ+YhiIi9Mk4UCbDOYpFmKr6gUkcDaqVZPvAoEbIxCiBOtWlXX8
-+JSxXULFPzZEhV06LpBGiqK5b4euDBVAGTGQ/Dslu67xZhMNhZDZSTSP8l35ettN
-XSf2dp01jAamTKOxsrZvHdejAP1y657qRKGvITR9x0LiSZEZi8CtuoKAqHFw9DUx
-kWOEIJXpYK9ki8z/PYp2dD3IVW3kjsMrHOhCGK6f5mucNAbsavLD
+MIIF6zCCA9OgAwIBAgIUfo9amJtJGWqWE6f+SkAO85zkGr4wDQYJKoZIhvcNAQEL
+BQAwgYMxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARPc2xvMQ0wCwYDVQQHDARPc2xv
+MRcwFQYDVQQKDA5UaGUgUXQgQ29tcGFueTEMMAoGA1UECwwDUiZEMRIwEAYDVQQD
+DAlIMiBUZXN0ZXIxGzAZBgkqhkiG9w0BCQEWDG1pbmltaUBxdC5pbzAgFw0yMDEw
+MjYxMjAxMzFaGA8yMTIwMTAwMjEyMDEzMVowgYMxCzAJBgNVBAYTAk5PMQ0wCwYD
+VQQIDARPc2xvMQ0wCwYDVQQHDARPc2xvMRcwFQYDVQQKDA5UaGUgUXQgQ29tcGFu
+eTEMMAoGA1UECwwDUiZEMRIwEAYDVQQDDAlIMiBUZXN0ZXIxGzAZBgkqhkiG9w0B
+CQEWDG1pbmltaUBxdC5pbzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AOiUp5+E4blouKH7q+rVNR8NoYX2XkBW+q+rpy1zu5ssRSzbqxAjDx9dkht7Qlnf
+VlDT00JvpOWdeuPon5915edQRsY4Unl6mKH29ra3OtUa1/yCJXsGVJTKCj7k4Bxb
+5mZzb/fTlZntMLdTIBMfUbw62FKir1WjKIcJ9fCoG8JaGeKVO4Rh5p0ezd4UUUId
+r1BXl5Nqdqy2vTMsEDnjOsD3egkv8I2SKN4O6n/C3wWYpMOWYZkGoZiKz7rJs/i/
+ez7bsV7JlwdzTlhpJzkcOSVFBP6JlEOxTNNxZ1wtKy7PtZGmsSSATq2e6+bw38Ae
+Op0XnzzqcGjtDDofBmT7OFzZWjS9VZS6+DOOe2QHWle1nCHcHyH4ku6IRlsr9xkR
+NAIlOfnvHHxqJUenoeaZ4oQDjCBKS1KXygJO/tL7BLTQVn/xK1EmPvKNnjzWk4tR
+PnibUhhs5635qpOU/YPqFBh1JjVruZbsWcDAhRcew0uxONXOa9E+4lttQ9ySYa1A
+LvWqJuAX7gu2BsBMLyqfm811YnA7CIFMyO+HlqmkLFfv5L/xIRAXR7l26YGO0VwX
+CGjMfz4NVPMMke4nB7qa9NkpXQBQKMms3Qzd5JW0Hy9Ruj5O8GPcFZmV0twjd1uJ
+PD/cAjkWLaXjdNsJ16QWc2nghQRS6HYqKRX6j+CXOxupAgMBAAGjUzBRMB0GA1Ud
+DgQWBBRSCOU58j9NJZkMamt623qyCrhN3TAfBgNVHSMEGDAWgBRSCOU58j9NJZkM
+amt623qyCrhN3TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCq
+q4jxsWeNDv5Nq14hJtF9HB+ZL64zcZtRjJP1YgNs0QppKICmjPOL2nIMGmI/jKrs
+0eGAL/9XXNVHPxm1OPOncvimMMmU6emZfpMdEtTfKP43+Pg9HgKRjLoQp406vGeQ
+8ki/mbBhrItVPgEm3tu2AFA02XTYi+YxCI9kRZLGkM3FbgtOuTLPl0Z9y+kiPc9F
+uCSC03anBEqv+vDSI8+wODymQ/IJ3Jyz1lxIRDfp4qAekmy0jU2c91VOHHEmOmqq
+kqygGFRdwbe99m9yP63r6q0b5K3X2UnJ6bns0hmTwThYwpVPXLU8jdaTddbMukN2
+/Ef96Tsw8nWOEOPMySHOTIPgwyZRp26b0kA9EmhLwOP401SxXVQCmSRmtwNagmtg
+jJKmZoYBN+//D45ibK8z6Q0oOm9P+Whf/uUXehcRxBxyV3xz7k0wKGQbHj/ddwcy
+IUoIN4lrAlib+lK170kTKN352PDmrpo2gmIzPEsfurKAIMSelDl6H+kih16BtZ8y
+Nz6fh9Soqrg3OSAware8pxV7k51crBMoPLN78KoRV8MFCK4K7Fddq4rRISq6hiXq
+r1nsjoEPuKM9huprmZVZe9t5YcDa2I+wb3IiE3uwpZbAdaLDyQ5n6F/qpsiIkZXn
+gtcF7oqpG5oYrwCcZ53y/ezUgUg7PlSz2XwAGvQtgg==
 -----END CERTIFICATE-----
diff --git a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key
index 9d1664d609..337ce541a6 100644
--- a/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key
+++ b/qtbase/tests/auto/network/ssl/qsslsocket/certs/fluke.key
@@ -1,15 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQCnyKBKxBkFG2a6MuLS8RxvF4LkOS4BUZDbBDQyESHCDW9Z2FOQ
-VD+Dj6nTs9XuGpuArsMlyV6lr0tgBaqg0ZEBH8oEg+NYHJkyRYRwclgDmEpji0H1
-CEnSkQJga+Rk/t2gqnQI6TRMkV8SPTdNVCytf1uYYDYCjDv2RfMnapuUnQIDAQAB
-AoGANFzLkanTeSGNFM0uttBipFT9F4a00dqHz6JnO7zXAT26I5r8sU1pqQBb6uLz
-/+Qz5Zwk8RUAQcsMRgJetuPQUb0JZjF6Duv24hNazqXBCu7AZzUenjafwmKC/8ri
-KpX3fTwqzfzi//FKGgbXQ80yykSSliDL3kn/drATxsLCgQECQQDXhEFWLJ0vVZ1s
-1Ekf+3NITE+DR16X+LQ4W6vyEHAjTbaNWtcTKdAWLA2l6N4WAAPYSi6awm+zMxx4
-VomVTsjdAkEAx0z+e7natLeFcrrq8pbU+wa6SAP1VfhQWKitxL1e7u/QO90NCpxE
-oQYKzMkmmpOOFjQwEMAy1dvFMbm4LHlewQJAC/ksDBaUcQHHqjktCtrUb8rVjAyW
-A8lscckeB2fEYyG5J6dJVaY4ClNOOs5yMDS2Afk1F6H/xKvtQ/5CzInA/QJATDub
-K+BPU8jO9q+gpuIi3VIZdupssVGmCgObVCHLakG4uO04y9IyPhV9lA9tALtoIf4c
-VIvv5fWGXBrZ48kZAQJBAJmVCdzQxd9LZI5vxijUCj5EI4e+x5DRqVUvyP8KCZrC
-AiNyoDP85T+hBZaSXK3aYGpVwelyj3bvo1GrTNwNWLw=
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDolKefhOG5aLih
++6vq1TUfDaGF9l5AVvqvq6ctc7ubLEUs26sQIw8fXZIbe0JZ31ZQ09NCb6TlnXrj
+6J+fdeXnUEbGOFJ5epih9va2tzrVGtf8giV7BlSUygo+5OAcW+Zmc2/305WZ7TC3
+UyATH1G8OthSoq9VoyiHCfXwqBvCWhnilTuEYeadHs3eFFFCHa9QV5eTanastr0z
+LBA54zrA93oJL/CNkijeDup/wt8FmKTDlmGZBqGYis+6ybP4v3s+27FeyZcHc05Y
+aSc5HDklRQT+iZRDsUzTcWdcLSsuz7WRprEkgE6tnuvm8N/AHjqdF5886nBo7Qw6
+HwZk+zhc2Vo0vVWUuvgzjntkB1pXtZwh3B8h+JLuiEZbK/cZETQCJTn57xx8aiVH
+p6HmmeKEA4wgSktSl8oCTv7S+wS00FZ/8StRJj7yjZ481pOLUT54m1IYbOet+aqT
+lP2D6hQYdSY1a7mW7FnAwIUXHsNLsTjVzmvRPuJbbUPckmGtQC71qibgF+4LtgbA
+TC8qn5vNdWJwOwiBTMjvh5appCxX7+S/8SEQF0e5dumBjtFcFwhozH8+DVTzDJHu
+Jwe6mvTZKV0AUCjJrN0M3eSVtB8vUbo+TvBj3BWZldLcI3dbiTw/3AI5Fi2l43Tb
+CdekFnNp4IUEUuh2KikV+o/glzsbqQIDAQABAoICAFw1q6tr5I48vY7DF+rXsuLn
+5ZUWE1IQ6fzB4lr72nJv/9EEGnMgYzt9PpMUsD6vdCpBgS2C0+6RHArFzJtNA+RM
+iHLIG7K7702veyr/xBx/MwiSlMeMv/XpkFxVI6E6skMGG2s3AMXxKvJTy5CpRx+I
+eQFyLG+Ya1X2lgJes/q+/CpAHkOjCOpcLySQC5NZ74q734V7nSdmn+Zs3tYEh+O/
+eiuwTP/j5b38Te5vVTqDxTciJPmljmXLCwa0N100lWlbcpvw8qbqiTI2Jm3XCbUE
+AzHjW9vmrF3cRS1fXxKFGShw3SRqlkbxjfeWoi8qDPUBS4m8LOr8qG9Wo5Nfon0z
+zLP4bci3zHDvVcaaZrrsUBs/yZbg+Dgka1DmX7ekmeccr2yTdKDFgPupYUyxVbTl
+a9ZLJysjFD7rgBv1ZclHonLp6Vbm+ZoTqvteo4ikAy6L9RtBWJ23XEK34PkP/+c5
+2vWZaOrnjSeBHbFce8cdJSxqWpP+eSCI5I9XbDrYFIsQ/gqKgtzDKy2ihJ2Y8STL
+yO4hyFPFjxc+Gg4/P2PpmT5CY2ty44M0BWs+JGW96CJPrrplf2lmQUQJj5LZY66X
+Z/4C9L7ZYtKZ+bs5SvU46yWugAvQZX22Xm9xLXWyVXRdx3bj+3M3fDnF9di/zdbh
+CgLx7oWPNrXc7FCajnn9AoIBAQD5FMYwRpw9NWT9WDxQwx+cSI4Icbd88ByTW63S
+LzeRwZA0J9/SfwO+aBRupzc9GkGXCiZcGMw3AGsCtig8yFlw8E5KnzN7KlftDMnM
+9NUxxzlR8VwKyLnZfG7sDTl057ZlUujnqhmt/F8F7dIy7FVO1dE/8nngA+FYTCOG
+UZdGjwyBDlDM0JJdUWGY3xslutcpCDN5mzSTKjy9drMvImAshRawxRF6WBpn7vr2
+nC6vciqfx1Mzx1vyk0Jm0ilaydDdLMADjt/iL4Nkr0BEs4k+UzQiKDwp8gu7abQ1
+eBfxd9Iar4htQa2I1Ewl6P01G/q+ZYwgHhJ9RVn4AxQXefILAoIBAQDvCouORdQX
+C8wsyp7MwXlF/3NQeNN5/+B2mhbxrBOf7PmMCXLnkRWcjwJtzypWFqJ0sqai/2+0
+bqbMcjX5maT8stT2shl3zXe/Ejt2e3TBYpc1tyuses8Kb5BMU8hu6tTd3G2CMXpD
+dT6DVemJZCTtwj9aBNIxSizvlgMolJnCpzhPnlfHSI6E+g3m/LTTo3HwbjMSw/Uq
+irgjOpI2wSBB6LZPSgjvfcYPRyWUk16L4A5uSX0cADnovDFLa5/h0wJvN/OoCSQg
+rLCXG5E18EyL5Wc58BCY1ZvxmjG3lQtgPxYu2Jwc36R/y/JKlxW5suER5ZNpbbD4
+uOyTt2VxMQ2bAoIBAQC5+MzRFqdo/AjfL5Y5JrbfVTzXCTDa09xCGd16ZU60QTWN
++4ed/r+o1sUKqUcRFB2MzEM/2DQBjQpZB/CbEWvWa1XJWXxypXbowveZU+QqOnmN
+uQvj8WLyA3o+PNF9e9QvauwCrHpn8VpxbtPWuaYoKnUFreFZZQxHhPGxRBIS2JOZ
+eDrT8ZaWnkCkh1AZp5smQ71LOprSlmKrg4jd1GjCVMxQR5N5KXbtyv0OTCZ/UFqK
+2aRBsMPyJgkaBChkZPLRcKwc+/wlQRx1fHQb14DNTApMxoXFO7eOwqmOkpAt9iyl
+SBIwoS0UUI5ab88+bBmXNvKcuFdNuQ4nowTJUn9pAoIBADMNkILBXSvS5DeIyuO2
+Sp1tkoZUV+5NfPY3sMDK3KIibaW/+t+EOBZo4L7tKQCb8vRzl21mmsfxfgRaPDbj
+3r3tv9g0b4YLxxBy52pFscj/soXRai17SS7UZwA2QK+XzgDYbDcLNC6mIsTQG4Gx
+dsWk3/zs3KuUSQaehmwrWK+fIUK38c1pLK8v7LoxrLkqxlHwZ04RthHw8KTthH7X
+Pnl1J0LF8CSeOyfWLSuPUfkT0GEzptnNHpEbaHfQM6R6eaGhVJPF6AZme4y6YYgg
+m2ihhSt1n0XVEWpHYWjxFy3mK2mz75unFC4LM+NEY2p2zuUQoCw7NjnY3QYrfCnx
+rRMCggEAXeXsMSLFjjyuoL7iKbAxo52HD/P0fBoy58LyRcwfNVr0lvYan4pYEx+o
+KijIh9K16PqXZXKMA9v003B+ulmF8bJ7SddCZ5NGvnFhUTDe4DdTKgp2RuwQ3Bsc
+3skPIDbhVETyOLCtys34USHrq8U/0DlGY3eLRfxw9GnbKxSBGa/KEu/qQLPNUo50
+7xHZDg7GKeC3kqNJeqKM9rkp0VzIGkEnaD9127LeNDmERDfftxJzFoC/THvUBLfU
+6Sus2ZYwRE8VFvKC30Q45t/c54X3IuhYvAuiCuTmyfE4ruyzyOwKzhUkeeLq1APX
+g0veFbyfzlJ0q8qzD/iffqqIa2ZSmQ==
+-----END PRIVATE KEY-----
diff --git a/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
index 7ba3715e13..752aa122f6 100644
--- a/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
+++ b/qtbase/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
@@ -179,6 +179,7 @@ void tst_QAccessibilityLinux::initTestCase()
     QVERIFY(!address.isEmpty());
 
     m_window = new AccessibleTestWindow();
+    m_window->setObjectName("mainWindow"_L1);
     m_window->show();
 
     QVERIFY(QTest::qWaitForWindowExposed(m_window));
@@ -236,8 +237,11 @@ bool hasState(QDBusInterface *interface, AtspiStateType state)
 void tst_QAccessibilityLinux::testLabel()
 {
     QLabel *l = new QLabel(m_window);
+    l->setObjectName("theObjectName"_L1);
     l->setText("Hello A11y");
     m_window->addWidget(l);
+    auto a11yEmpty = new QLabel(m_window);
+    m_window->addWidget(l);
 
     // Application
     QCOMPARE(getParent(mainWindow), QLatin1String(ATSPI_DBUS_PATH_ROOT));
@@ -249,6 +253,8 @@ void tst_QAccessibilityLinux::testLabel()
     QCOMPARE(getChildren(labelInterface).count(), 0);
     QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label"));
     QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u);
+    QCOMPARE(labelInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(),
+             QLatin1String("mainWindow.theObjectName"));
     QCOMPARE(getParent(labelInterface), mainWindow->path());
     QVERIFY(!hasState(labelInterface, ATSPI_STATE_EDITABLE));
     QVERIFY(hasState(labelInterface, ATSPI_STATE_READ_ONLY));
@@ -256,7 +262,12 @@ void tst_QAccessibilityLinux::testLabel()
     l->setText("New text");
     QCOMPARE(labelInterface->property("Name").toString(), l->text());
 
+    auto *a11yEmptyInterface = getInterface(children.at(1), "org.a11y.atspi.Accessible");
+    QCOMPARE(a11yEmptyInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(),
+             QLatin1String("mainWindow.QLabel"));
+
     m_window->clearChildren();
+    delete a11yEmptyInterface;
     delete labelInterface;
 }
 
diff --git a/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 76df61c892..6d6d65b791 100644
--- a/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/qtbase/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the test suite of the Qt Toolkit.
@@ -68,6 +68,8 @@ private slots:
     void query_exec();
     void execErrorRecovery_data() { generic_data(); }
     void execErrorRecovery();
+    void prematureExec_data() { generic_data(); }
+    void prematureExec();
     void first_data() { generic_data(); }
     void first();
     void next_data() { generic_data(); }
@@ -2770,6 +2772,35 @@ void tst_QSqlQuery::execErrorRecovery()
     QVERIFY_SQL( q, exec() );
 }
 
+void tst_QSqlQuery::prematureExec()
+{
+    QFETCH(QString, dbName);
+    // We only want the engine name, for addDatabase():
+    int cut = dbName.indexOf(QChar('@'));
+    if (cut < 0)
+        QSKIP("Failed to parse database type out of name");
+    dbName.truncate(cut);
+    cut = dbName.indexOf(QChar('_'));
+    if (cut >= 0)
+        dbName = dbName.mid(cut + 1);
+
+    auto db = QSqlDatabase::addDatabase(dbName);
+    QSqlQuery q(db);
+
+    QTest::ignoreMessage(QtWarningMsg,
+                         "QSqlDatabasePrivate::removeDatabase: connection "
+                         "'qt_sql_default_connection' is still in use, all "
+                         "queries will cease to work.");
+    QTest::ignoreMessage(QtWarningMsg,
+                         "QSqlDatabasePrivate::addDatabase: duplicate connection name "
+                         "'qt_sql_default_connection', old connection removed.");
+    auto otherDb = QSqlDatabase::addDatabase(dbName);
+
+    QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::exec: called before driver has been set up");
+    // QTBUG-100037: shouldn't crash !
+    QVERIFY(!q.exec("select stuff from TheVoid"));
+}
+
 void tst_QSqlQuery::lastInsertId()
 {
     QFETCH( QString, dbName );
diff --git a/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
index 4aa3f8d60b..d2050a61aa 100644
--- a/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
+++ b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
@@ -115,6 +115,10 @@ void tst_QAbstractItemModelTester::standardItemModelZeroColumns()
     // QTBUG-92886
     model.insertRows(0, 5);
     model.removeRows(1, 2);
+
+    const QModelIndex parentIndex = model.index(0, 0);
+    model.insertRows(0, 5, parentIndex);
+    model.removeRows(1, 2, parentIndex);
 }
 
 void tst_QAbstractItemModelTester::testInsertThroughProxy()
diff --git a/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json b/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json
index 12a4a22a19..ce518e78fb 100644
--- a/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json
+++ b/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json
@@ -668,50 +668,6 @@
         "inputFile": "task192552.h",
         "outputRevision": 67
     },
-    {
-        "classes": [
-            {
-                "className": "InlineSlotsWithThrowDeclaration",
-                "object": true,
-                "qualifiedClassName": "InlineSlotsWithThrowDeclaration",
-                "slots": [
-                    {
-                        "access": "public",
-                        "name": "a",
-                        "returnType": "void"
-                    },
-                    {
-                        "access": "public",
-                        "name": "b",
-                        "returnType": "void"
-                    },
-                    {
-                        "access": "public",
-                        "name": "c",
-                        "returnType": "void"
-                    },
-                    {
-                        "access": "public",
-                        "name": "d",
-                        "returnType": "void"
-                    },
-                    {
-                        "access": "public",
-                        "name": "e",
-                        "returnType": "void"
-                    }
-                ],
-                "superClasses": [
-                    {
-                        "access": "public",
-                        "name": "QObject"
-                    }
-                ]
-            }
-        ],
-        "inputFile": "task189996.h",
-        "outputRevision": 67
-    },
     {
         "classes": [
             {
diff --git a/qtbase/tests/auto/tools/moc/moc.pro b/qtbase/tests/auto/tools/moc/moc.pro
index c324b3a8cd..4aceb78dc0 100644
--- a/qtbase/tests/auto/tools/moc/moc.pro
+++ b/qtbase/tests/auto/tools/moc/moc.pro
@@ -15,7 +15,7 @@ cross_compile: DEFINES += MOC_CROSS_COMPILED
 HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-newlines.h oldstyle-casts.h \
            slots-with-void-template.h qinvokable.h namespaced-flags.h trigraphs.h \
            escapes-in-string-literals.h cstyle-enums.h qprivateslots.h gadgetwithnoenums.h \
-           dir-in-include-path.h single_function_keyword.h task192552.h task189996.h \
+           dir-in-include-path.h single_function_keyword.h task192552.h \
            task234909.h task240368.h pure-virtual-signals.h cxx11-enums.h \
            cxx11-final-classes.h \
            cxx11-explicit-override-control.h \
diff --git a/qtbase/tests/auto/tools/moc/task189996.h b/qtbase/tests/auto/tools/moc/task189996.h
deleted file mode 100644
index f94a051b3a..0000000000
--- a/qtbase/tests/auto/tools/moc/task189996.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-// inline functions can have throw declarations
-
-#ifndef TASK189996_H
-#define TASK189996_H
-
-#include <QObject>
-
-class InlineSlotsWithThrowDeclaration : public QObject
-{
-    Q_OBJECT
-
-public slots:
-    void a() throw() { }
-    void b() const throw() { }
-    void c() throw();
-    void d() throw(int) { }
-    void e() const throw(int,double) { }
-};
-
-#endif
diff --git a/qtbase/tests/auto/tools/moc/tst_moc.cpp b/qtbase/tests/auto/tools/moc/tst_moc.cpp
index c716aead21..15dd9e41e5 100644
--- a/qtbase/tests/auto/tools/moc/tst_moc.cpp
+++ b/qtbase/tests/auto/tools/moc/tst_moc.cpp
@@ -631,7 +631,6 @@ public:
 private slots:
     void initTestCase();
 
-    void slotWithException() throw(MyStruct);
     void dontStripNamespaces();
     void oldStyleCasts();
     void warnOnExtraSignalSlotQualifiaction();
@@ -673,7 +672,6 @@ private slots:
     void templateGtGt();
     void qprivateslots();
     void qprivateproperties();
-    void inlineSlotsWithThrowDeclaration();
     void warnOnPropertyWithoutREAD();
     void constructors();
     void typenameWithUnsigned();
@@ -784,12 +782,6 @@ void tst_Moc::initTestCase()
 #endif
 }
 
-void tst_Moc::slotWithException() throw(MyStruct)
-{
-    // be happy
-    QVERIFY(true);
-}
-
 void tst_Moc::dontStripNamespaces()
 {
     Sender sender;
@@ -824,7 +816,7 @@ void tst_Moc::oldStyleCasts()
 
     QStringList args;
     args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
-         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-";
     proc.start("gcc", args);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -894,7 +886,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension()
 
     QStringList args;
     args << "-c" << "-x" << "c++" << "-I" << ".."
-         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-";
     proc.start("gcc", args);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -1174,7 +1166,7 @@ void tst_Moc::ignoreOptionClashes()
     QStringList gccArgs;
     gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
          << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null"
-         << "-fPIC" << "-std=c++11" <<  "-";
+         << "-fPIC" << "-std=c++1z" <<  "-";
     proc.start("gcc", gccArgs);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
@@ -1593,21 +1585,6 @@ void tst_Moc::qprivateproperties()
 
 }
 
-#include "task189996.h"
-
-void InlineSlotsWithThrowDeclaration::c() throw() {}
-
-void tst_Moc::inlineSlotsWithThrowDeclaration()
-{
-    InlineSlotsWithThrowDeclaration tst;
-    const QMetaObject *mobj = tst.metaObject();
-    QVERIFY(mobj->indexOfSlot("a()") != -1);
-    QVERIFY(mobj->indexOfSlot("b()") != -1);
-    QVERIFY(mobj->indexOfSlot("c()") != -1);
-    QVERIFY(mobj->indexOfSlot("d()") != -1);
-    QVERIFY(mobj->indexOfSlot("e()") != -1);
-}
-
 void tst_Moc::warnOnPropertyWithoutREAD()
 {
 #ifdef MOC_CROSS_COMPILED
@@ -1869,7 +1846,7 @@ void tst_Moc::notifyError()
 
     QStringList args;
     args << "-c" << "-x" << "c++" << "-I" << "."
-         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++1z" << "-";
     proc.start("gcc", args);
     QVERIFY(proc.waitForStarted());
     proc.write(mocOut);
diff --git a/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index c355ee9665..88c09de8e0 100644
--- a/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/qtbase/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -251,6 +251,7 @@ private slots:
     void testResetCachedSizeHint();
     void statusTips();
     void testRemovingColumnsViaLayoutChanged();
+    void testModelMovingColumns();
 
 protected:
     void setupTestData(bool use_reset_model = false);
@@ -360,6 +361,12 @@ public:
         endRemoveColumns();
     }
 
+    void moveColumn(int from, int to)
+    {
+        beginMoveColumns(QModelIndex(), from, from, QModelIndex(), to);
+        endMoveColumns();
+    }
+
     void cleanup()
     {
         emit layoutAboutToBeChanged();
@@ -3627,5 +3634,18 @@ void tst_QHeaderView::testRemovingColumnsViaLayoutChanged()
     // The main point of this test is that the section-size restoring code didn't go out of bounds.
 }
 
+void tst_QHeaderView::testModelMovingColumns()
+{
+    QtTestModel model(10, 10);
+    QHeaderView hv(Qt::Horizontal);
+    hv.setModel(&model);
+    hv.resizeSections(QHeaderView::ResizeToContents);
+    hv.show();
+
+    QPersistentModelIndex index3 = model.index(0, 3);
+    model.moveColumn(3, 1);
+    QCOMPARE(index3.column(), 1);
+}
+
 QTEST_MAIN(tst_QHeaderView)
 #include "tst_qheaderview.moc"
diff --git a/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 761357b252..06bb706074 100644
--- a/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/qtbase/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -397,6 +397,7 @@ private slots:
     void checkHeaderMinSize();
 
     void resizeToContents();
+    void resizeToContentsSpans();
 
     void tabFocus();
     void bigModel();
@@ -3721,6 +3722,70 @@ void tst_QTableView::resizeToContents()
 
 }
 
+
+class SpanModel : public QAbstractTableModel
+{
+public:
+    SpanModel(bool sectionsMoved)
+        : _sectionsMoved(sectionsMoved)
+    {}
+    int columnCount(const QModelIndex & = {}) const override { return 2; }
+    int rowCount(const QModelIndex & = {}) const override { return 1; }
+    QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
+    {
+        if (role != Qt::DisplayRole)
+            return QVariant();
+        const int col = _sectionsMoved ? 1 - idx.column() : idx.column();
+        if (col == 0)
+            return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
+        return QVariant();
+    }
+private:
+    bool _sectionsMoved;
+};
+
+
+void tst_QTableView::resizeToContentsSpans()
+{
+    SpanModel model1(false);
+    SpanModel model2(true);
+    QTableView view1, view2, view3;
+    view1.setModel(&model1);
+    view2.setModel(&model2);
+    view2.horizontalHeader()->moveSection(0, 1);
+    view3.setModel(&model1);
+
+    view1.setSpan(0, 0, 1, 2);
+    view2.setSpan(0, 1, 1, 2);
+    view1.show();
+    view2.show();
+    view3.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&view1));
+    QVERIFY(QTest::qWaitForWindowExposed(&view2));
+    QVERIFY(QTest::qWaitForWindowExposed(&view3));
+    view1.setColumnWidth(0, 100);
+    view1.setColumnWidth(1, 100);
+    view2.setColumnWidth(0, 100);
+    view2.setColumnWidth(1, 100);
+    view3.setColumnWidth(0, 200);
+
+    view1.resizeRowToContents(0);
+    view2.resizeRowToContents(0);
+    view3.resizeRowToContents(0);
+    QCOMPARE(view1.rowHeight(0), view3.rowHeight(0));
+    QCOMPARE(view2.rowHeight(0), view3.rowHeight(0));
+
+    view3.resizeColumnToContents(0);
+    view3.resizeRowToContents(0);
+    // height should be only 1 text line for easy testing
+    view1.setRowHeight(0, view3.verticalHeader()->sectionSize(0));
+    view2.setRowHeight(0, view3.verticalHeader()->sectionSize(0));
+    view1.resizeColumnToContents(0);
+    view2.resizeColumnToContents(1);
+    QCOMPARE(view1.columnWidth(0), view3.columnWidth(0) - view1.columnWidth(1));
+    QCOMPARE(view2.columnWidth(0), view3.columnWidth(0) - view2.columnWidth(1));
+}
+
 QT_BEGIN_NAMESPACE
 extern bool Q_WIDGETS_EXPORT qt_tab_all_widgets(); // qapplication.cpp
 QT_END_NAMESPACE
diff --git a/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index a3b8ef78d8..4955cebd5d 100644
--- a/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/qtbase/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -1498,7 +1498,7 @@ void tst_QApplication::desktopSettingsAware()
     environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1");
     testProcess.setEnvironment(environment);
 #endif
-    testProcess.start("desktopsettingsaware_helper");
+    testProcess.start("./desktopsettingsaware_helper");
     QVERIFY2(testProcess.waitForStarted(),
              qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString())));
     QVERIFY(testProcess.waitForFinished(10000));
@@ -2452,7 +2452,7 @@ void tst_QApplication::qtbug_12673()
 #if QT_CONFIG(process)
     QProcess testProcess;
     QStringList arguments;
-    testProcess.start("modal_helper", arguments);
+    testProcess.start("./modal_helper", arguments);
     QVERIFY2(testProcess.waitForStarted(),
              qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString())));
     QVERIFY(testProcess.waitForFinished(20000));
diff --git a/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp b/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp
index eb108a40de..dca5528c1b 100644
--- a/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp
+++ b/qtbase/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp
@@ -41,6 +41,7 @@
 
 #include <private/qguiapplication_p.h>
 #include <qpa/qplatformintegration.h>
+#include <qpa/qplatformtheme.h>
 
 class tst_QAbstractButton : public QObject
 {
@@ -76,6 +77,8 @@ private slots:
     void keyNavigation();
 #endif
 
+    void buttonPressKeys();
+
 protected slots:
     void onClicked();
     void onToggled( bool on );
@@ -269,7 +272,13 @@ void tst_QAbstractButton::setAutoRepeat()
         QCOMPARE(press_count, click_count);
         QVERIFY(click_count > 1);
         break;
-    case 4:
+    case 4: {
+        const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                             ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                             .value<QList<Qt::Key>>();
+        if (buttonPressKeys.contains(Qt::Key_Enter)) {
+            QSKIP("platform theme has Key_Enter in ButtonPressKeys");
+        }
         // check that pressing ENTER has no effect when autorepeat is false
         testWidget->setDown( false );
         testWidget->setAutoRepeat( false );
@@ -286,7 +295,14 @@ void tst_QAbstractButton::setAutoRepeat()
 
         QVERIFY( click_count == 0 );
         break;
-    case 5:
+    }
+    case 5: {
+        const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                             ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                             .value<QList<Qt::Key>>();
+        if (buttonPressKeys.contains(Qt::Key_Enter)) {
+            QSKIP("platform theme has Key_Enter in ButtonPressKeys");
+        }
         // check that pressing ENTER has no effect when autorepeat is true
         testWidget->setDown( false );
         testWidget->setAutoRepeat( true );
@@ -304,6 +320,7 @@ void tst_QAbstractButton::setAutoRepeat()
 
         QVERIFY( click_count == 0 );
         break;
+    }
     case 6:
         // verify autorepeat is off by default.
         MyButton tmp( 0);
@@ -651,5 +668,16 @@ void tst_QAbstractButton::keyNavigation()
 }
 #endif
 
+void tst_QAbstractButton::buttonPressKeys()
+{
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    for (int i = 0; i < buttonPressKeys.length(); ++i) {
+        QTest::keyClick(testWidget, buttonPressKeys[i]);
+        QCOMPARE(click_count, i + 1);
+    }
+}
+
 QTEST_MAIN(tst_QAbstractButton)
 #include "tst_qabstractbutton.moc"
diff --git a/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 32437050f5..46b5af6d63 100644
--- a/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/qtbase/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -168,6 +168,7 @@ private slots:
     void checkMenuItemPosWhenStyleSheetIsSet();
     void checkEmbeddedLineEditWhenStyleSheetIsSet();
     void propagateStyleChanges();
+    void buttonPressKeys();
 
 private:
     PlatformInputContext m_platformInputContext;
@@ -1682,6 +1683,16 @@ void tst_QComboBox::setModel()
     QCOMPARE(box.rootModelIndex(), rootModelIndex);
     box.setModel(box.model());
     QCOMPARE(box.rootModelIndex(), rootModelIndex);
+
+    // check that setting the same model as the completer's doesn't crash
+    QCompleter *completer = new QCompleter(&box);
+    box.setEditable(true);
+    box.setCompleter(completer);
+    auto *listModel = new QStringListModel({ "one", "two" }, completer);
+    completer->setModel(listModel);
+    QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
+    box.setModel(listModel);
+    QCOMPARE(listModel->rowCount(), 2); // make sure it wasn't deleted
 }
 
 void tst_QComboBox::setCustomModelAndView()
@@ -3632,5 +3643,24 @@ void tst_QComboBox::propagateStyleChanges()
     QVERIFY(frameStyle.inquired);
 }
 
+void tst_QComboBox::buttonPressKeys()
+{
+    QComboBox comboBox;
+    comboBox.setEditable(false);
+    comboBox.addItem(QString::number(1));
+    comboBox.addItem(QString::number(2));
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    for (int i = 0; i < buttonPressKeys.length(); ++i) {
+        QTest::keyClick(&comboBox, buttonPressKeys[i]);
+        // On some platforms, a window will not be immediately visible,
+        // but take some event-loop iterations to complete.
+        // Using QTRY_VERIFY to deal with that.
+        QTRY_VERIFY(comboBox.view()->isVisible());
+        comboBox.hidePopup();
+    }
+}
+
 QTEST_MAIN(tst_QComboBox)
 #include "tst_qcombobox.moc"
diff --git a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro
index be3cfcd104..c228fdfcca 100644
--- a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro
+++ b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/qcommandlinkbutton.pro
@@ -1,6 +1,6 @@
 CONFIG += testcase
 TARGET = tst_qcommandlinkbutton
-QT += widgets testlib
+QT += widgets testlib gui-private
 SOURCES  += tst_qcommandlinkbutton.cpp
 
 
diff --git a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp
index 0044d33c66..4cf06296e4 100644
--- a/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp
+++ b/qtbase/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp
@@ -40,6 +40,9 @@
 #include <QGridLayout>
 #include <QPainter>
 
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
+
 class tst_QCommandLinkButton : public QObject
 {
     Q_OBJECT
@@ -223,6 +226,13 @@ void tst_QCommandLinkButton::setAutoRepeat()
     // check that pressing ENTER has no effect
     resetCounters();
     testWidget->setDown( false );
+    // Skip after reset if ButtonPressKeys has Key_Enter
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(Qt::Key_Enter)) {
+        return;
+    }
     testWidget->setAutoRepeat( false );
     QTest::keyPress( testWidget, Qt::Key_Enter );
 
@@ -255,6 +265,14 @@ void tst_QCommandLinkButton::pressed()
     QCOMPARE( press_count, (uint)1 );
     QCOMPARE( release_count, (uint)1 );
 
+    // Skip if ButtonPressKeys has Key_Enter
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(Qt::Key_Enter)) {
+        return;
+    }
+
     QTest::keyPress( testWidget,Qt::Key_Enter );
     QCOMPARE( press_count, (uint)1 );
     QCOMPARE( release_count, (uint)1 );
diff --git a/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro b/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro
index 4a5e76ff65..a235fa1fac 100644
--- a/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro
+++ b/qtbase/tests/auto/widgets/widgets/qgroupbox/qgroupbox.pro
@@ -1,6 +1,6 @@
 CONFIG += testcase
 TARGET = tst_qgroupbox
-QT += widgets testlib
+QT += widgets testlib gui-private
 SOURCES  += tst_qgroupbox.cpp
 
 
diff --git a/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
index 4fb5d262ca..d8d7562b73 100644
--- a/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
+++ b/qtbase/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
@@ -35,6 +35,9 @@
 #include <QRadioButton>
 #include <QDialog>
 
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
+
 #include "qgroupbox.h"
 
 class tst_QGroupBox : public QObject
@@ -69,6 +72,7 @@ private slots:
     void propagateFocus();
     void task_QTBUG_19170_ignoreMouseReleaseEvent();
     void task_QTBUG_15519_propagateMouseEvents();
+    void buttonPressKeys();
 
 private:
     bool checked;
@@ -610,6 +614,20 @@ void tst_QGroupBox::task_QTBUG_15519_propagateMouseEvents()
     QCOMPARE(parent.mouseMoved, true);
 }
 
+void tst_QGroupBox::buttonPressKeys()
+{
+    QGroupBox groupBox;
+    groupBox.setCheckable(true);
+    QSignalSpy clickedSpy(&groupBox, &QGroupBox::clicked);
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    for (int i = 0; i < buttonPressKeys.length(); ++i) {
+        QTest::keyClick(&groupBox, buttonPressKeys[i]);
+        QCOMPARE(clickedSpy.length(), i + 1);
+    }
+}
+
 void tst_QGroupBox::sendMouseMoveEvent(QWidget *widget, const QPoint &localPos)
 {
     // Send a MouseMove event without actually moving the pointer
diff --git a/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro b/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro
index 353ad06ca2..e55f6148f2 100644
--- a/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro
+++ b/qtbase/tests/auto/widgets/widgets/qpushbutton/qpushbutton.pro
@@ -1,6 +1,6 @@
 CONFIG += testcase
 TARGET = tst_qpushbutton
-QT += widgets testlib
+QT += widgets testlib gui-private
 SOURCES  += tst_qpushbutton.cpp
 
 
diff --git a/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
index e818514a79..4043e9326a 100644
--- a/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
+++ b/qtbase/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
@@ -41,6 +41,9 @@
 #include <QStyleFactory>
 #include <QTabWidget>
 
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
+
 class tst_QPushButton : public QObject
 {
 Q_OBJECT
@@ -212,6 +215,13 @@ void tst_QPushButton::autoRepeat()
     // check that pressing ENTER has no effect
     resetCounters();
     testWidget->setDown( false );
+    // Skip after reset if ButtonPressKeys has Key_Enter
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(Qt::Key_Enter)) {
+        return;
+    }
     testWidget->setAutoRepeat( false );
     QTest::keyPress( testWidget, Qt::Key_Enter );
 
@@ -247,6 +257,14 @@ void tst_QPushButton::pressed()
     QCOMPARE( press_count, (uint)1 );
     QCOMPARE( release_count, (uint)1 );
 
+    // Skip if ButtonPressKeys has Key_Enter
+    const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+                                         ->themeHint(QPlatformTheme::ButtonPressKeys)
+                                         .value<QList<Qt::Key>>();
+    if (buttonPressKeys.contains(Qt::Key_Enter)) {
+        return;
+    }
+
     QTest::keyPress( testWidget,Qt::Key_Enter );
     QCOMPARE( press_count, (uint)1 );
     QCOMPARE( release_count, (uint)1 );
diff --git a/qtbase/tests/manual/rhi/cubemap_render/buildshader.bat b/qtbase/tests/manual/rhi/cubemap_render/buildshader.bat
old mode 100755
new mode 100644
Submodule qtconnectivity e957d481..056294c0:
diff --git a/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp b/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp
index e2635fae..a8b8e3b9 100644
--- a/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp
+++ b/qtconnectivity/src/bluetooth/bluez/hcimanager.cpp
@@ -563,9 +563,11 @@ void HciManager::handleHciAclPacket(const quint8 *data, int size)
 
 void HciManager::handleLeMetaEvent(const quint8 *data)
 {
-    // Spec v4.2, Vol 2, part E, 7.7.65ff
+    // Spec v5.3, Vol 4, part E, 7.7.65.*
     switch (*data) {
-    case 0x1: {
+    case 0x1: // HCI_LE_Connection_Complete
+    case 0xA: // HCI_LE_Enhanced_Connection_Complete
+    {
         const quint16 handle = bt_get_le16(data + 2);
         emit connectionComplete(handle);
         break;
diff --git a/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 6a93143b..4a18cfc7 100644
--- a/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -320,7 +320,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceD
             for (const QBluetoothUuid &id : serviceClassUuids) {
                 if (id.minimumSize() == 16) {
                     serviceInfo.setServiceUuid(id);
-                    serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Custom Service"));
+                    if (serviceInfo.serviceName().isEmpty()) {
+                        serviceInfo.setServiceName(
+                                    QBluetoothServiceDiscoveryAgent::tr("Custom Service"));
+                    }
                     QBluetoothServiceInfo::Sequence modSeq =
                             serviceInfo.attribute(QBluetoothServiceInfo::ServiceClassIds).value<QBluetoothServiceInfo::Sequence>();
                     modSeq.removeOne(QVariant::fromValue(id));
@@ -334,8 +337,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceD
                 qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString()
                                      << serviceInfo.serviceName() << serviceInfo.serviceUuid()
                                      << ">>>" << serviceInfo.serviceClassUuids();
-
-                emit q->serviceDiscovered(serviceInfo);
+                // Use queued connection to allow us finish the service looping; the application
+                // might call stop() when it has detected the service-of-interest.
+                QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection,
+                                          Q_ARG(QBluetoothServiceInfo, serviceInfo));
             }
         }
     }
diff --git a/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp b/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp
index e4d85447..aadd4755 100644
--- a/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp
+++ b/qtconnectivity/src/bluetooth/qbluetoothsocket.cpp
@@ -593,7 +593,7 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
 bool QBluetoothSocket::canReadLine() const
 {
     Q_D(const QBluetoothSocketBase);
-    return d->canReadLine();
+    return d->canReadLine() || QIODevice::canReadLine();
 }
 
 /*!
diff --git a/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp b/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
index 084aa958..d6aa17a7 100644
--- a/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
+++ b/qtconnectivity/src/bluetooth/qbluetoothsocket_bluezdbus.cpp
@@ -284,6 +284,10 @@ void QBluetoothSocketPrivateBluezDBus::connectToService(
         return;
     }
 
+    if (service.socketProtocol() != QBluetoothServiceInfo::Protocol::UnknownProtocol)
+        socketType = service.socketProtocol();
+    qCDebug(QT_BT_BLUEZ) << "Socket protocol used:" << socketType;
+
     connectToService(service.device().address(), targetService, openMode);
 }
 
diff --git a/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp b/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp
index 05bc1a0f..a7b5ef1f 100644
--- a/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp
+++ b/qtconnectivity/tests/auto/qbluetoothsocket/tst_qbluetoothsocket.cpp
@@ -142,7 +142,7 @@ void tst_QBluetoothSocket::initTestCase()
     qDebug() << "Starting discovery";
 
     sda->setUuidFilter(QBluetoothUuid(QString(TEST_SERVICE_UUID)));
-    sda->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);
+    sda->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
 
     for (int connectTime = MaxConnectTime; !done_discovery && connectTime > 0; connectTime -= 1000)
         QTest::qWait(1000);
Submodule qtdeclarative f5701f0d..8defe7bf:
diff --git a/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h b/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h
index b65b994d6c..15a8cd6878 100644
--- a/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h
+++ b/qtdeclarative/src/qml/common/qqmljsfixedpoolarray_p.h
@@ -86,7 +86,7 @@ public:
         if (QTypeInfo<T>::isComplex) {
             for (int i = 0; i < count; ++i)
                 new (data + i) T(vector.at(i));
-        } else {
+        } else if (count) {
             memcpy(data, static_cast<const void*>(vector.constData()), count * sizeof(T));
         }
     }
diff --git a/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp b/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e57cdd8278..94613598af 100644
--- a/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1145,8 +1145,7 @@ void Heap::QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markSta
 void QObjectWrapper::destroyObject(bool lastCall)
 {
     Heap::QObjectWrapper *h = d();
-    if (!h->internalClass)
-        return; // destroyObject already got called
+    Q_ASSERT(h->internalClass);
 
     if (h->object()) {
         QQmlData *ddata = QQmlData::get(h->object(), false);
@@ -1176,7 +1175,7 @@ void QObjectWrapper::destroyObject(bool lastCall)
         }
     }
 
-    h->~Data();
+    h->destroy();
 }
 
 
diff --git a/qtdeclarative/src/qml/memory/qv4mm.cpp b/qtdeclarative/src/qml/memory/qv4mm.cpp
index 06caf04e5a..da149a67c4 100644
--- a/qtdeclarative/src/qml/memory/qv4mm.cpp
+++ b/qtdeclarative/src/qml/memory/qv4mm.cpp
@@ -981,7 +981,7 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt
 
     if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) {
         for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
-            if (!it.value().isNullOrUndefined())
+            if (it.value().isNullOrUndefined())
                 it = multiplyWrappedQObjects->erase(it);
             else
                 ++it;
diff --git a/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp b/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp
index 2079a8ed04..a577cb2351 100644
--- a/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp
@@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel()
                       q,  QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
     qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
                       q,  QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)),
+                      q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int)));
+    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+                      q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
+    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
+                      q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
     qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
                       q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
     qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
@@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
                         q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
     QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
                         q, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+    QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q,
+                        SLOT(_q_columnsInserted(QModelIndex,int,int)));
+    QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q,
+                        SLOT(_q_columnsRemoved(QModelIndex,int,int)));
+    QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q,
+                        SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
     QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
                         q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
     QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
@@ -1973,6 +1985,38 @@ void QQmlDelegateModel::_q_rowsMoved(
     }
 }
 
+void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end)
+{
+    Q_D(QQmlDelegateModel);
+    Q_UNUSED(end);
+    if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
+        // mark all items as changed
+        _q_itemsChanged(0, d->m_count, QVector<int>());
+    }
+}
+
+void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end)
+{
+    Q_D(QQmlDelegateModel);
+    Q_UNUSED(end);
+    if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
+        // mark all items as changed
+        _q_itemsChanged(0, d->m_count, QVector<int>());
+    }
+}
+
+void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end,
+                                        const QModelIndex &destination, int column)
+{
+    Q_D(QQmlDelegateModel);
+    Q_UNUSED(end);
+    if ((parent == d->m_adaptorModel.rootIndex && start == 0)
+        || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
+        // mark all items as changed
+        _q_itemsChanged(0, d->m_count, QVector<int>());
+    }
+}
+
 void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
 {
     Q_D(QQmlDelegateModel);
diff --git a/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h b/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h
index 8aab4badca..d140bfbaaf 100644
--- a/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h
+++ b/qtdeclarative/src/qmlmodels/qqmldelegatemodel_p.h
@@ -152,6 +152,9 @@ private Q_SLOTS:
     void _q_itemsMoved(int from, int to, int count);
     void _q_modelReset();
     void _q_rowsInserted(const QModelIndex &,int,int);
+    void _q_columnsInserted(const QModelIndex &, int, int);
+    void _q_columnsRemoved(const QModelIndex &, int, int);
+    void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
     void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
     void _q_rowsRemoved(const QModelIndex &,int,int);
     void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
diff --git a/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp b/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp
index 85719fdc80..78e2ab302c 100644
--- a/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/qtdeclarative/src/quick/accessible/qaccessiblequickitem.cpp
@@ -46,6 +46,7 @@
 #include "QtQuick/private/qquicktextinput_p.h"
 #include "QtQuick/private/qquickaccessibleattached_p.h"
 #include "QtQuick/qquicktextdocument.h"
+#include "QtQuick/qquickrendercontrol.h"
 QT_BEGIN_NAMESPACE
 
 #if QT_CONFIG(accessibility)
@@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
 
 QWindow *QAccessibleQuickItem::window() const
 {
-    return item()->window();
+    QQuickWindow *window = item()->window();
+
+    // For QQuickWidget the above window will be the offscreen QQuickWindow,
+    // which is not a part of the accessibility tree. Detect this case and
+    // return the window for the QQuickWidget instead.
+    if (window && !window->handle()) {
+        if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) {
+            if (QWindow *renderWindow = renderControl->renderWindow(nullptr))
+                return renderWindow;
+        }
+    }
+
+    return window;
 }
 
 int QAccessibleQuickItem::childCount() const
@@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
 QAccessibleInterface *QAccessibleQuickItem::parent() const
 {
     QQuickItem *parent = item()->parentItem();
-    QQuickWindow *window = item()->window();
-    QQuickItem *ci = window ? window->contentItem() : nullptr;
+    QQuickWindow *itemWindow = item()->window();
+    QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr;
     while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci)
         parent = parent->parentItem();
 
     if (parent) {
         if (parent == ci) {
-            // Jump out to the scene widget if the parent is the root item.
-            // There are two root items, QQuickWindow::rootItem and
-            // QQuickView::declarativeRoot. The former is the true root item,
-            // but is not a part of the accessibility tree. Check if we hit
-            // it here and return an interface for the scene instead.
-            return QAccessible::queryAccessibleInterface(window);
+            // Jump out to the window if the parent is the root item
+            return QAccessible::queryAccessibleInterface(window());
         } else {
             while (parent && !parent->d_func()->isAccessible)
                 parent = parent->parentItem();
@@ -188,7 +197,7 @@ QAccessible::State QAccessibleQuickItem::state() const
     QRect viewRect_ = viewRect();
     QRect itemRect = rect();
 
-    if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
+    if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
         state.invisible = true;
     if (!viewRect_.intersects(itemRect))
         state.offscreen = true;
@@ -201,6 +210,10 @@ QAccessible::State QAccessibleQuickItem::state() const
     if (role() == QAccessible::EditableText)
         if (auto ti = qobject_cast<QQuickTextInput *>(item()))
             state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal;
+    if (!item()->isEnabled()) {
+        state.focusable = false;
+        state.disabled = true;
+    }
     return state;
 }
 
diff --git a/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h b/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h
index 39ffcaf39c..8baa01330c 100644
--- a/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h
+++ b/qtdeclarative/src/quick/accessible/qaccessiblequickview_p.h
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
 
 #if QT_CONFIG(accessibility)
 
-class QAccessibleQuickWindow : public QAccessibleObject
+class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject
 {
 public:
     QAccessibleQuickWindow(QQuickWindow *object);
diff --git a/qtdeclarative/src/quick/items/qquickdrag.cpp b/qtdeclarative/src/quick/items/qquickdrag.cpp
index 8321fcfeed..383078b3b9 100644
--- a/qtdeclarative/src/quick/items/qquickdrag.cpp
+++ b/qtdeclarative/src/quick/items/qquickdrag.cpp
@@ -481,7 +481,9 @@ void QQuickDragAttached::setKeys(const QStringList &keys)
     \qmlattachedproperty stringlist QtQuick::Drag::mimeData
     \since 5.2
 
-    This property holds a map of mimeData that is used during startDrag.
+    This property holds a map from mime type to data that is used during startDrag.
+    The mime data needs to be a \c string, or an \c ArrayBuffer with the data encoded
+    according to the mime type.
 */
 
 QVariantMap QQuickDragAttached::mimeData() const
@@ -766,8 +768,12 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
     QDrag *drag = new QDrag(source ? source : q);
     QMimeData *mimeData = new QMimeData();
 
-    for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it)
-        mimeData->setData(it.key(), it.value().toString().toUtf8());
+    for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) {
+        if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QByteArray)
+            mimeData->setData(it.key(), it.value().toByteArray());
+        else
+            mimeData->setData(it.key(), it.value().toString().toUtf8());
+    }
 
     drag->setMimeData(mimeData);
     if (pixmapLoader.isReady()) {
diff --git a/qtdeclarative/src/quick/items/qquickitem.cpp b/qtdeclarative/src/quick/items/qquickitem.cpp
index 75f1457816..dec0ae19ae 100644
--- a/qtdeclarative/src/quick/items/qquickitem.cpp
+++ b/qtdeclarative/src/quick/items/qquickitem.cpp
@@ -59,6 +59,7 @@
 #include <QtCore/private/qnumeric_p.h>
 #include <QtGui/qpa/qplatformtheme.h>
 #include <QtCore/qloggingcategory.h>
+#include <QtCore/private/qduplicatetracker_p.h>
 
 #include <private/qqmlglobal_p.h>
 #include <private/qqmlengine_p.h>
@@ -2326,6 +2327,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
 QQuickItem::~QQuickItem()
 {
     Q_D(QQuickItem);
+    d->inDestructor = true;
 
     if (d->windowRefCount > 1)
         d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
@@ -2526,6 +2528,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
     QQuickItem *current = item;
     qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
     qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
+    QDuplicateTracker<QQuickItem *> cycleDetector;
     do {
         qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
         qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
@@ -2592,7 +2595,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
         // traversed all of the chain (by compare the [current] item with [startItem])
         // Since the [startItem] might be promoted to its parent if it is invisible,
         // we still have to check [current] item with original start item
-        if ((current == startItem || current == originalStartItem) && from == firstFromItem) {
+        // We might also run into a cycle before we reach firstFromItem again
+        // but note that we have to ignore current if we are meant to skip it
+        if (((current == startItem || current == originalStartItem) && from == firstFromItem) ||
+                (!skip && cycleDetector.hasSeen(current))) {
             // wrapped around, avoid endless loops
             if (item == contentItem) {
                 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
@@ -2689,9 +2695,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
 
         const bool wasVisible = isVisible();
         op->removeChild(this);
-        if (wasVisible) {
+        if (wasVisible && !op->inDestructor)
             emit oldParentItem->visibleChildrenChanged();
-        }
     } else if (d->window) {
         QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
     }
@@ -2768,8 +2773,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
 
     d->itemChange(ItemParentHasChanged, d->parentItem);
 
-    emit parentChanged(d->parentItem);
-    if (isVisible() && d->parentItem)
+    if (!d->inDestructor)
+        emit parentChanged(d->parentItem);
+    if (isVisible() && d->parentItem && !QQuickItemPrivate::get(d->parentItem)->inDestructor)
         emit d->parentItem->visibleChildrenChanged();
 }
 
@@ -2965,7 +2971,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
 
     itemChange(QQuickItem::ItemChildRemovedChange, child);
 
-    emit q->childrenChanged();
+    if (!inDestructor)
+        emit q->childrenChanged();
 }
 
 void QQuickItemPrivate::refWindow(QQuickWindow *c)
@@ -3194,6 +3201,7 @@ QQuickItemPrivate::QQuickItemPrivate()
     , touchEnabled(false)
 #endif
     , hasCursorHandler(false)
+    , inDestructor(false)
     , dirtyAttributes(0)
     , nextDirtyItem(nullptr)
     , prevDirtyItem(nullptr)
@@ -5120,6 +5128,13 @@ void QQuickItem::componentComplete()
         d->addToDirtyList();
         QQuickWindowPrivate::get(d->window)->dirtyItem(this);
     }
+
+#if QT_CONFIG(accessibility)
+    if (d->isAccessible && d->effectiveVisible) {
+        QAccessibleEvent ev(this, QAccessible::ObjectShow);
+        QAccessible::updateAccessibility(&ev);
+    }
+#endif
 }
 
 QQuickStateGroup *QQuickItemPrivate::_states()
@@ -6106,9 +6121,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
         QAccessible::updateAccessibility(&ev);
     }
 #endif
-    emit q->visibleChanged();
-    if (childVisibilityChanged)
-        emit q->visibleChildrenChanged();
+    if (!inDestructor) {
+        emit q->visibleChanged();
+        if (childVisibilityChanged)
+            emit q->visibleChildrenChanged();
+    }
 
     return true;    // effective visibility DID change
 }
@@ -6157,6 +6174,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
     }
 
     itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable);
+#if QT_CONFIG(accessibility)
+    if (isAccessible) {
+        QAccessible::State changedState;
+        changedState.disabled = true;
+        changedState.focusable = true;
+        QAccessibleStateChangeEvent ev(q, changedState);
+        QAccessible::updateAccessibility(&ev);
+    }
+#endif
     emit q->enabledChanged();
 }
 
diff --git a/qtdeclarative/src/quick/items/qquickitem_p.h b/qtdeclarative/src/quick/items/qquickitem_p.h
index 841d91bb40..ade8fb61f2 100644
--- a/qtdeclarative/src/quick/items/qquickitem_p.h
+++ b/qtdeclarative/src/quick/items/qquickitem_p.h
@@ -472,6 +472,7 @@ public:
     bool replayingPressEvent:1;
     bool touchEnabled:1;
     bool hasCursorHandler:1;
+    quint32 inDestructor:1; // has entered ~QQuickItem
 
     enum DirtyType {
         TransformOrigin         = 0x00000001,
diff --git a/qtdeclarative/src/quick/items/qquickitemview.cpp b/qtdeclarative/src/quick/items/qquickitemview.cpp
index 010a0152e1..f8ad168a17 100644
--- a/qtdeclarative/src/quick/items/qquickitemview.cpp
+++ b/qtdeclarative/src/quick/items/qquickitemview.cpp
@@ -1785,7 +1785,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to)
 
     do {
         bufferPause.stop();
-        if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) {
+        if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) {
             currentChanges.reset();
             bufferedChanges.reset();
             releaseVisibleItems(reusableFlag);
diff --git a/qtdeclarative/src/quick/items/qquickmousearea_p_p.h b/qtdeclarative/src/quick/items/qquickmousearea_p_p.h
index fba383e268..0d63618622 100644
--- a/qtdeclarative/src/quick/items/qquickmousearea_p_p.h
+++ b/qtdeclarative/src/quick/items/qquickmousearea_p_p.h
@@ -61,7 +61,6 @@ QT_BEGIN_NAMESPACE
 
 class QQuickMouseEvent;
 class QQuickMouseArea;
-class QQuickPointerMask;
 class QQuickMouseAreaPrivate : public QQuickItemPrivate
 {
     Q_DECLARE_PUBLIC(QQuickMouseArea)
@@ -100,7 +99,6 @@ public:
 #if QT_CONFIG(quick_draganddrop)
     QQuickDrag *drag;
 #endif
-    QPointer<QQuickPointerMask> mask;
     QPointF startScene;
     QPointF targetStartPos;
     QPointF lastPos;
diff --git a/qtdeclarative/src/quick/items/qquicktext.cpp b/qtdeclarative/src/quick/items/qquicktext.cpp
index 6230186933..e823ca1095 100644
--- a/qtdeclarative/src/quick/items/qquicktext.cpp
+++ b/qtdeclarative/src/quick/items/qquicktext.cpp
@@ -2168,7 +2168,7 @@ void QQuickText::resetMaximumLineCount()
     <img src="" align="top,middle,bottom" width="" height=""> - inline images
     <ol type="">, <ul type=""> and <li> - ordered and unordered lists
     <pre></pre> - preformatted
-    &gt; &lt; &amp;
+    &gt; &lt; &amp; &quot; &nbsp; &apos;
     \endcode
 
     \c Text.StyledText parser is strict, requiring tags to be correctly nested.
diff --git a/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
index eb4db0f85e..2325a2665b 100644
--- a/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
+++ b/qtdeclarative/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
@@ -446,7 +446,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
 
         const char *textureRecord = allocatorData;
         for (int i = 0; i < textureCount; ++i, textureRecord += Qtdf::TextureRecordSize) {
-            if (textureRecord + Qtdf::TextureRecordSize > qtdfTableEnd) {
+            if (qtdfTableEnd - textureRecord < Qtdf::TextureRecordSize) {
                 qWarning("qtdf table too small in font '%s'.",
                          qPrintable(font.familyName()));
                 return false;
@@ -462,7 +462,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
 
         const char *glyphRecord = textureRecord;
         for (quint32 i = 0; i < glyphCount; ++i, glyphRecord += Qtdf::GlyphRecordSize) {
-            if (glyphRecord + Qtdf::GlyphRecordSize > qtdfTableEnd) {
+            if (qtdfTableEnd - glyphRecord < Qtdf:: GlyphRecordSize) {
                 qWarning("qtdf table too small in font '%s'.",
                          qPrintable(font.familyName()));
                 return false;
@@ -512,8 +512,8 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
 
             int width = texInfo->allocatedArea.width();
             int height = texInfo->allocatedArea.height();
-            qint64 size = width * height;
-            if (reinterpret_cast<const char *>(textureData + size) > qtdfTableEnd) {
+            qint64 size = qint64(width) * height;
+            if (qtdfTableEnd - reinterpret_cast<const char *>(textureData) < size) {
                 qWarning("qtdf table too small in font '%s'.",
                          qPrintable(font.familyName()));
                 return false;
diff --git a/qtdeclarative/src/quick/util/qquickstyledtext.cpp b/qtdeclarative/src/quick/util/qquickstyledtext.cpp
index d531fc9205..a25af90414 100644
--- a/qtdeclarative/src/quick/util/qquickstyledtext.cpp
+++ b/qtdeclarative/src/quick/util/qquickstyledtext.cpp
@@ -564,6 +564,8 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI
                 textOut += QChar(60);
             else if (entity == QLatin1String("amp"))
                 textOut += QChar(38);
+            else if (entity == QLatin1String("apos"))
+                textOut += QChar(39);
             else if (entity == QLatin1String("quot"))
                 textOut += QChar(34);
             else if (entity == QLatin1String("nbsp"))
diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp
new file mode 100644
index 0000000000..8a1c901880
--- /dev/null
+++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblequickwidget_p.h"
+
+#include "qquickwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget)
+: QAccessibleWidget(widget)
+, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow)
+{
+    // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a
+    // QAccessibleQuickWidgetOffscreenWindow (defined below). This means
+    // it will return the Quick item child interfaces, which is what's needed here
+    // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children).
+}
+
+QAccessibleInterface *QAccessibleQuickWidget::child(int index) const
+{
+    return m_accessibleWindow.child(index);
+}
+
+int QAccessibleQuickWidget::childCount() const
+{
+    return m_accessibleWindow.childCount();
+}
+
+int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const
+{
+    return m_accessibleWindow.indexOfChild(iface);
+}
+
+QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const
+{
+    return m_accessibleWindow.childAt(x, y);
+}
+
+QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window)
+:QAccessibleQuickWindow(window)
+{
+
+}
+
+QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const
+{
+    Q_UNUSED(index);
+    return nullptr;
+}
+
+int QAccessibleQuickWidgetOffscreenWindow::childCount() const
+{
+    return 0;
+}
+
+int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const
+{
+    Q_UNUSED(iface);
+    return -1;
+}
+
+QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const
+{
+    Q_UNUSED(x);
+    Q_UNUSED(y);
+    return nullptr;
+}
+
+#endif // accessibility
+
+QT_END_NAMESPACE
diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h
new file mode 100644
index 0000000000..7c2ab930e0
--- /dev/null
+++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidget_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEQUICKWIDGET_H
+#define QACCESSIBLEQUICKWIDGET_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickwidget.h"
+#include <QtWidgets/qaccessiblewidget.h>
+
+#include <private/qaccessiblequickview_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+// These classes implement the QQuickWiget accessibility switcharoo,
+// where the child items of the QQuickWidgetOffscreenWindow are reported
+// as child accessible interfaces of the QAccessibleQuickWidget.
+class QAccessibleQuickWidget: public QAccessibleWidget
+{
+public:
+    QAccessibleQuickWidget(QQuickWidget* widget);
+
+    QAccessibleInterface *child(int index) const override;
+    int childCount() const override;
+    int indexOfChild(const QAccessibleInterface *iface) const override;
+    QAccessibleInterface *childAt(int x, int y) const override;
+
+private:
+    QAccessibleQuickWindow m_accessibleWindow;
+    Q_DISABLE_COPY(QAccessibleQuickWidget)
+};
+
+class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow
+{
+public:
+    QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window);
+    QAccessibleInterface *child(int index) const override;
+    int childCount() const override;
+    int indexOfChild(const QAccessibleInterface *iface) const override;
+    QAccessibleInterface *childAt(int x, int y) const override;
+};
+
+#endif // accessibility
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
new file mode 100644
index 0000000000..7ba88a1769
--- /dev/null
+++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblequickwidgetfactory_p.h"
+#include "qaccessiblequickwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object)
+{
+    if (classname == QLatin1String("QQuickWidget")) {
+        return new QAccessibleQuickWidget(qobject_cast<QQuickWidget *>(object));
+    } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) {
+        return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast<QQuickWindow *>(object));
+    }
+    return 0;
+}
+
+#endif // accessibility
+
+QT_END_NAMESPACE
+
diff --git a/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
new file mode 100644
index 0000000000..8c63b09f81
--- /dev/null
+++ b/qtdeclarative/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H
+#define QACCESSIBLEQUICKWIDGETFACTORY_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(accessibility)
+
+QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object);
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/qtdeclarative/src/quickwidgets/qquickwidget.cpp b/qtdeclarative/src/quickwidgets/qquickwidget.cpp
index 39780f8de3..9c97b43518 100644
--- a/qtdeclarative/src/quickwidgets/qquickwidget.cpp
+++ b/qtdeclarative/src/quickwidgets/qquickwidget.cpp
@@ -39,6 +39,7 @@
 
 #include "qquickwidget.h"
 #include "qquickwidget_p.h"
+#include "qaccessiblequickwidgetfactory_p.h"
 
 #include "private/qquickwindow_p.h"
 #include "private/qquickitem_p.h"
@@ -75,9 +76,16 @@
 
 QT_BEGIN_NAMESPACE
 
+QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
+:QQuickWindow(dd, control)
+{
+    setTitle(QString::fromLatin1("Offscreen"));
+    setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
+}
+
 // override setVisble to prevent accidental offscreen window being created
 // by base class.
-class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate {
+class QQuickWidgetOffscreenWindowPrivate: public QQuickWindowPrivate {
 public:
     void setVisible(bool visible) override {
         Q_Q(QWindow);
@@ -105,9 +113,8 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
     Q_Q(QQuickWidget);
 
     renderControl = new QQuickWidgetRenderControl(q);
-    offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
-    offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
-    offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
+    offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
+    offscreenWindow->setScreen(q->screen());
     // Do not call create() on offscreenWindow.
 
     // Check if the Software Adaptation is being used
@@ -138,6 +145,10 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
     QWidget::connect(offscreenWindow, &QQuickWindow::focusObjectChanged, q, &QQuickWidget::propagateFocusObjectChanged);
     QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
     QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
+
+#if QT_CONFIG(accessibility)
+    QAccessible::installFactory(&qAccessibleQuickWidgetFactory);
+#endif
 }
 
 void QQuickWidgetPrivate::ensureEngine() const
@@ -901,9 +912,7 @@ void QQuickWidgetPrivate::createContext()
 
         context = new QOpenGLContext;
         context->setFormat(offscreenWindow->requestedFormat());
-        const QWindow *win = q->window()->windowHandle();
-        if (win && win->screen())
-            context->setScreen(win->screen());
+        context->setScreen(q->screen());
         QOpenGLContext *shareContext = qt_gl_global_share_context();
         if (!shareContext)
             shareContext = QWidgetPrivate::get(q->window())->shareContext();
@@ -1520,19 +1529,16 @@ bool QQuickWidget::event(QEvent *e)
         d->handleWindowChange();
         break;
 
-    case QEvent::ScreenChangeInternal:
-        if (QWindow *window = this->window()->windowHandle()) {
-            QScreen *newScreen = window->screen();
-
-            if (d->offscreenWindow)
-                d->offscreenWindow->setScreen(newScreen);
-            if (d->offscreenSurface)
-                d->offscreenSurface->setScreen(newScreen);
+    case QEvent::ScreenChangeInternal: {
+        QScreen *newScreen = screen();
+        if (d->offscreenWindow)
+            d->offscreenWindow->setScreen(newScreen);
+        if (d->offscreenSurface)
+            d->offscreenSurface->setScreen(newScreen);
 #if QT_CONFIG(opengl)
-            if (d->context)
-                d->context->setScreen(newScreen);
+        if (d->context)
+            d->context->setScreen(newScreen);
 #endif
-        }
 
         if (d->useSoftwareRenderer
 #if QT_CONFIG(opengl)
@@ -1545,7 +1551,7 @@ bool QQuickWidget::event(QEvent *e)
             d->render(true);
         }
         break;
-
+    }
     case QEvent::Show:
     case QEvent::Move:
         d->updatePosition();
diff --git a/qtdeclarative/src/quickwidgets/qquickwidget_p.h b/qtdeclarative/src/quickwidgets/qquickwidget_p.h
index 881f7f9220..1a946bcc71 100644
--- a/qtdeclarative/src/quickwidgets/qquickwidget_p.h
+++ b/qtdeclarative/src/quickwidgets/qquickwidget_p.h
@@ -148,6 +148,14 @@ public:
     bool forceFullUpdate;
 };
 
+class QQuickWidgetOffscreenWindow: public QQuickWindow
+{
+    Q_OBJECT
+
+public:
+    QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control);
+};
+
 QT_END_NAMESPACE
 
 #endif // QQuickWidget_P_H
diff --git a/qtdeclarative/src/quickwidgets/quickwidgets.pro b/qtdeclarative/src/quickwidgets/quickwidgets.pro
index 2438e577ae..85d156b8a3 100644
--- a/qtdeclarative/src/quickwidgets/quickwidgets.pro
+++ b/qtdeclarative/src/quickwidgets/quickwidgets.pro
@@ -7,9 +7,13 @@ DEFINES   += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FO
 HEADERS += \
     qquickwidget.h \
     qquickwidget_p.h \
-    qtquickwidgetsglobal.h
+    qtquickwidgetsglobal.h \
+    qaccessiblequickwidget_p.h \
+    qaccessiblequickwidgetfactory_p.h
 
 SOURCES += \
-    qquickwidget.cpp
+    qquickwidget.cpp \
+    qaccessiblequickwidget.cpp \
+    qaccessiblequickwidgetfactory.cpp
 
 load(qt_module)
diff --git a/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 3b7d74df63..b75bf820d5 100644
--- a/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/qtdeclarative/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -102,6 +102,7 @@ private slots:
     void valueConversion_RegularExpression();
     void castWithMultipleInheritance();
     void collectGarbage();
+    void collectGarbageNestedWrappersTwoEngines();
     void gcWithNestedDataStructure();
     void stacktrace();
     void numberParsing_data();
@@ -1809,6 +1810,44 @@ void tst_QJSEngine::collectGarbage()
     QVERIFY(ptr.isNull());
 }
 
+class TestObjectContainer : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QObject *dummy MEMBER m_dummy CONSTANT)
+
+public:
+    TestObjectContainer() : m_dummy(new QObject(this)) {}
+
+private:
+    QObject *m_dummy;
+};
+
+void tst_QJSEngine::collectGarbageNestedWrappersTwoEngines()
+{
+    QJSEngine engine1;
+    QJSEngine engine2;
+
+    TestObjectContainer container;
+    QQmlEngine::setObjectOwnership(&container, QQmlEngine::CppOwnership);
+
+    engine1.globalObject().setProperty("foobar", engine1.newQObject(&container));
+    engine2.globalObject().setProperty("foobar", engine2.newQObject(&container));
+
+    engine1.evaluate("foobar.dummy.baz = 42");
+    engine2.evaluate("foobar.dummy.baz = 43");
+
+    QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
+    QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
+
+    engine1.collectGarbage();
+    engine2.collectGarbage();
+
+    // The GC should not collect dummy object wrappers neither in engine1 nor engine2, we
+    // verify that by checking whether the baz property still has its previous value.
+    QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
+    QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
+}
+
 void tst_QJSEngine::gcWithNestedDataStructure()
 {
     // The GC must be able to traverse deeply nested objects, otherwise this
diff --git a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
new file mode 100644
index 0000000000..206133bb39
--- /dev/null
+++ b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.8
+
+ListView {
+    id: root
+    width: 200
+    height: 200
+
+    delegate: Text {
+        text: display
+    }
+}
diff --git a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index 35f1e2c94d..1722447830 100644
--- a/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/qtdeclarative/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -27,6 +27,8 @@
 ****************************************************************************/
 
 #include <QtTest/qtest.h>
+#include <QtCore/QConcatenateTablesProxyModel>
+#include <QtGui/QStandardItemModel>
 #include <QtQml/qqmlcomponent.h>
 #include <QtQmlModels/private/qqmldelegatemodel_p.h>
 #include <QtQuick/qquickview.h>
@@ -47,6 +49,7 @@ private slots:
     void filterOnGroup_removeWhenCompleted();
     void qtbug_86017();
     void contextAccessedByHandler();
+    void redrawUponColumnChange();
 };
 
 class AbstractItemModel : public QAbstractItemModel
@@ -186,6 +189,30 @@ void tst_QQmlDelegateModel::contextAccessedByHandler()
     QVERIFY(root->property("works").toBool());
 }
 
+void tst_QQmlDelegateModel::redrawUponColumnChange()
+{
+    QStandardItemModel m1;
+    m1.appendRow({
+            new QStandardItem("Banana"),
+            new QStandardItem("Coconut"),
+    });
+
+    QQuickView view(testFileUrl("redrawUponColumnChange.qml"));
+    QCOMPARE(view.status(), QQuickView::Ready);
+    view.show();
+    QQuickItem *root = view.rootObject();
+    root->setProperty("model", QVariant::fromValue<QObject *>(&m1));
+
+    QObject *item = root->property("currentItem").value<QObject *>();
+    QVERIFY(item);
+    QCOMPARE(item->property("text").toString(), "Banana");
+
+    QVERIFY(root);
+    m1.removeColumn(0);
+
+    QCOMPARE(item->property("text").toString(), "Coconut");
+}
+
 QTEST_MAIN(tst_QQmlDelegateModel)
 
 #include "tst_qqmldelegatemodel.moc"
diff --git a/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index 5d635aa63b..824fd89e5b 100644
--- a/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/qtdeclarative/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -76,10 +76,10 @@ void tst_qv4mm::multiWrappedQObjects()
         QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
         QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
 
-        // Moves the additional WeakValue from m_multiplyWrappedQObjects to
-        // m_pendingFreedObjectWrapperValue. It's still alive after all.
+        // The additional WeakValue from m_multiplyWrappedQObjects hasn't been moved
+        // to m_pendingFreedObjectWrapperValue yet. It's still alive after all.
         engine1.memoryManager->runGC();
-        QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 2);
+        QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
 
         // engine2 doesn't own the object as engine1 was the first to wrap it above.
         // Therefore, no effect here.
diff --git a/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml b/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml
new file mode 100644
index 0000000000..889e480f3b
--- /dev/null
+++ b/qtdeclarative/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.6
+
+Item {
+    visible: true
+    Item {
+        visible: false
+        Item {
+            objectName: "hiddenChild"
+            activeFocusOnTab: true
+            focus: true
+        }
+    }
+}
diff --git a/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index c8f251dbe1..c8ef36ee68 100644
--- a/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/qtdeclarative/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -67,6 +67,7 @@ private slots:
     void activeFocusOnTab10();
     void activeFocusOnTab_infiniteLoop_data();
     void activeFocusOnTab_infiniteLoop();
+    void activeFocusOnTab_infiniteLoopControls();
 
     void nextItemInFocusChain();
     void nextItemInFocusChain2();
@@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop()
     QCOMPARE(item, window->rootObject());
 }
 
+
+void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls()
+{
+    auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml");
+    QScopedPointer<QQuickView>window(new QQuickView());
+    window->setSource(source);
+    window->show();
+    QVERIFY(window->errors().isEmpty());
+    QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang
+}
+
 void tst_QQuickItem::nextItemInFocusChain()
 {
     if (!qt_tab_all_widgets())
Submodule qtdoc c0c7bf07...79d6ef69:
Submodule qtimageformats 2dcf2899..abe44c0f:
diff --git a/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp b/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
index dde783c..1bf9074 100644
--- a/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
+++ b/qtimageformats/src/plugins/imageformats/icns/qicnshandler.cpp
@@ -462,8 +462,12 @@ static bool parseIconEntryInfo(ICNSEntry &icon)
     if (isIconCompressed(icon))
         return true;
     // Icon depth:
-    if (!depth.isEmpty())
-        icon.depth = ICNSEntry::Depth(depth.toUInt());
+    if (!depth.isEmpty()) {
+        const uint depthUInt = depth.toUInt();
+        if (depthUInt > 32)
+            return false;
+        icon.depth = ICNSEntry::Depth(depthUInt);
+    }
     // Try mono if depth not found
     if (icon.depth == ICNSEntry::DepthUnknown)
         icon.depth = ICNSEntry::DepthMono;
@@ -515,6 +519,9 @@ static bool parseIconEntryInfo(ICNSEntry &icon)
         }
         icon.height = icon.width;
     }
+    // Sanity check
+    if (icon.width == 0 || icon.width > 4096)
+        return false;
     return true;
 }
 
@@ -685,7 +692,7 @@ bool QICNSHandler::canRead() const
 bool QICNSHandler::read(QImage *outImage)
 {
     QImage img;
-    if (!ensureScanned()) {
+    if (!ensureScanned() || m_currentIconIndex >= m_icons.size()) {
         qWarning("QICNSHandler::read(): The device wasn't parsed properly!");
         return false;
     }
@@ -892,7 +899,7 @@ bool QICNSHandler::scanDevice()
             return false;
 
         const qint64 blockDataOffset = device()->pos();
-        if (!isBlockHeaderValid(blockHeader)) {
+        if (!isBlockHeaderValid(blockHeader, ICNSBlockHeaderSize + filelength - blockDataOffset)) {
             qWarning("QICNSHandler::scanDevice(): Failed, bad header at pos %s. OSType \"%s\", length %u",
                      QByteArray::number(blockDataOffset).constData(),
                      nameFromOSType(blockHeader.ostype).constData(), blockHeader.length);
@@ -927,11 +934,14 @@ bool QICNSHandler::scanDevice()
         case ICNSBlockHeader::TypeOdrp:
             // Icns container seems to have an embedded icon variant container
             // Let's start a scan for entries
-            while (device()->pos() < nextBlockOffset) {
+            while (!stream.atEnd() && device()->pos() < nextBlockOffset) {
                 ICNSBlockHeader icon;
                 stream >> icon;
+                if (stream.status() != QDataStream::Ok)
+                    return false;
                 // Check for incorrect variant entry header and stop scan
-                if (!isBlockHeaderValid(icon, blockDataLength))
+                quint64 remaining = blockDataLength - (device()->pos() - blockDataOffset);
+                if (!isBlockHeaderValid(icon, ICNSBlockHeaderSize + remaining))
                     break;
                 if (!addEntry(icon, device()->pos(), blockHeader.ostype))
                     return false;
@@ -1003,7 +1013,7 @@ bool QICNSHandler::scanDevice()
             break;
         }
     }
-    return true;
+    return (m_icons.size() > 0);
 }
 
 const ICNSEntry &QICNSHandler::getIconMask(const ICNSEntry &icon) const
diff --git a/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp b/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
index 5082023..cb34374 100644
--- a/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
+++ b/qtimageformats/src/plugins/imageformats/jp2/qjp2handler.cpp
@@ -43,6 +43,7 @@
 #include "qimage.h"
 #include "qvariant.h"
 #include "qcolor.h"
+#include "qimagereader.h"
 
 #include <jasper/jasper.h>
 #include <math.h> // for pow
@@ -333,16 +334,46 @@ private:
 Jpeg2000JasperReader::Jpeg2000JasperReader(QIODevice *iod, SubFormat format)
     : jasperOk(true), ioDevice(iod), format(format), hasAlpha(false)
 {
+#if JAS_VERSION_MAJOR < 3
     if (jas_init()) {
         jasperOk = false;
         qDebug("Jasper Library initialization failed");
     }
+#else
+    jas_conf_clear();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+    jas_conf_set_max_mem_usage(QImageReader::allocationLimit() * 1024 * 1024);
+#else
+    // 128MB seems to be enough.
+    jas_conf_set_max_mem_usage(128 * 1024 * 1024);
+#endif
+    if (jas_init_library()) {
+        jasperOk = false;
+        qDebug("Jasper library initialization failed");
+    }
+    if (jas_init_thread()) {
+        jas_cleanup_library();
+        jasperOk = false;
+        qDebug("Jasper thread initialization failed");
+    }
+#endif
 }
 
 Jpeg2000JasperReader::~Jpeg2000JasperReader()
 {
+#if JAS_VERSION_MAJOR < 3
     if (jasperOk)
         jas_cleanup();
+#else
+    if (jasperOk) {
+        if (jas_cleanup_thread()) {
+            qDebug("Jasper thread cleanup failed");
+        }
+        if (jas_cleanup_library()) {
+            qDebug("Jasper library cleanup failed");
+        }
+    }
+#endif
 }
 
 /*! \internal
@@ -857,7 +888,7 @@ bool Jpeg2000JasperReader::write(const QImage &image, int quality)
     }
 
     // Open an empty jasper stream that grows automatically
-    jas_stream_t * memory_stream = jas_stream_memopen(0, -1);
+    jas_stream_t * memory_stream = jas_stream_memopen(0, 0);
 
     // Jasper wants a non-const string.
     char *str = qstrdup(jasperFormatString.toLatin1().constData());
diff --git a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 1386750..ac8956c 100644
--- a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -361,6 +361,8 @@ bool QTiffHandler::read(QImage *image)
     }
 
     TIFF *const tiff = d->tiff;
+    if (TIFFIsTiled(tiff) && TIFFTileSize64(tiff) > uint64_t(image->sizeInBytes())) // Corrupt image
+        return false;
     const quint32 width = d->size.width();
     const quint32 height = d->size.height();
 
diff --git a/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp b/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
index 82d38cb..d02eb05 100644
--- a/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
+++ b/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
@@ -45,6 +45,7 @@
 #include <qdebug.h>
 #include <qpainter.h>
 #include <qvariant.h>
+#include <QtEndian>
 
 static const int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
 
@@ -102,21 +103,23 @@ bool QWebpHandler::ensureScanned() const
 
     m_scanState = ScanError;
 
-    if (device()->isSequential()) {
-        qWarning() << "Sequential devices are not supported";
+    QWebpHandler *that = const_cast<QWebpHandler *>(this);
+    const int headerBytesNeeded = sizeof(WebPBitstreamFeatures);
+    QByteArray header = device()->peek(headerBytesNeeded);
+    if (header.size() < headerBytesNeeded)
         return false;
-    }
 
-    qint64 oldPos = device()->pos();
-    device()->seek(0);
-
-    QWebpHandler *that = const_cast<QWebpHandler *>(this);
-    QByteArray header = device()->peek(sizeof(WebPBitstreamFeatures));
+    // We do no random access during decoding, just a readAll() of the whole image file. So if
+    // if it is all available already, we can accept a sequential device. The riff header contains
+    // the file size minus 8 bytes header
+    qint64 byteSize = qFromLittleEndian<quint32>(header.constData() + 4);
+    if (device()->isSequential() && device()->bytesAvailable() < byteSize + 8) {
+        qWarning() << "QWebpHandler: Insufficient data available in sequential device";
+        return false;
+    }
     if (WebPGetFeatures((const uint8_t*)header.constData(), header.size(), &(that->m_features)) == VP8_STATUS_OK) {
         if (m_features.has_animation) {
             // For animation, we have to read and scan whole file to determine loop count and images count
-            device()->seek(oldPos);
-
             if (that->ensureDemuxer()) {
                 that->m_loop = WebPDemuxGetI(m_demuxer, WEBP_FF_LOOP_COUNT);
                 that->m_frameCount = WebPDemuxGetI(m_demuxer, WEBP_FF_FRAME_COUNT);
@@ -126,17 +129,13 @@ bool QWebpHandler::ensureScanned() const
                 if (that->m_features.has_alpha)
                     that->m_composited->fill(Qt::transparent);
 
-                // We do not reset device position since we have read in all data
                 m_scanState = ScanSuccess;
-                return true;
             }
         } else {
             m_scanState = ScanSuccess;
         }
     }
 
-    device()->seek(oldPos);
-
     return m_scanState == ScanSuccess;
 }
 
@@ -159,7 +158,7 @@ bool QWebpHandler::ensureDemuxer()
 
 bool QWebpHandler::read(QImage *image)
 {
-    if (!ensureScanned() || device()->isSequential() || !ensureDemuxer())
+    if (!ensureScanned() || !ensureDemuxer())
         return false;
 
     QRect prevFrameRect;
Submodule qtlocation 98a5c511..f991e28c:
diff --git a/qtlocation/src/location/configure.json b/qtlocation/src/location/configure.json
index 6d01a9a3..d1e623a1 100644
--- a/qtlocation/src/location/configure.json
+++ b/qtlocation/src/location/configure.json
@@ -9,7 +9,7 @@
             "label": "Qt.labs.location experimental QML plugin",
             "purpose": "Provides experimental QtLocation QML types",
             "section": "Location",
-            "condition": "config.opengl",
+            "condition": "features.opengl",
             "output": [ "privateFeature" ]
         },
         "geoservices_osm": {
diff --git a/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
index a978573d..11e1466f 100644
--- a/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
+++ b/qtlocation/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
@@ -158,7 +158,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind
     if (!root)
         return;
 
-    if (m_mapObjectsRootNode && m_mapObjectsRootNode->parent())
+    if (m_mapObjectsRootNode && !m_mapObjectsRootNode->parent())
         root->appendChildNode(m_mapObjectsRootNode.get());
 
     if (!m_mapObjectsRootNode) {
diff --git a/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
index 5a40467e..d123c6a8 100644
--- a/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
@@ -59,8 +59,10 @@ QT_BEGIN_NAMESPACE
 static const QString kPrefixEsri(QStringLiteral("esri."));
 static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
 
-static const QString kUrlGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates"));
-static const QString kUrlReverseGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode"));
+static const QString kUrlGeocode(QStringLiteral("https://geocode.arcgis.com/arcgis/rest/services/"
+                                                "World/GeocodeServer/findAddressCandidates"));
+static const QString kUrlReverseGeocode(QStringLiteral(
+        "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode"));
 
 static QString addressToQuery(const QGeoAddress &address)
 {
diff --git a/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
index 17492d94..96c12b1b 100644
--- a/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
@@ -46,7 +46,8 @@
 
 QT_BEGIN_NAMESPACE
 
-// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
+// JSON reference:
+// https://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
 
 static const QString kErrorMessage(QStringLiteral("Error %1: %2."));
 static const QString kErrorJson(QStringLiteral("Error: invalide JSON document."));
diff --git a/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
index 8cadfb29..92b6bb13 100644
--- a/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/georoutereply_esri.cpp
@@ -44,7 +44,8 @@
 
 QT_BEGIN_NAMESPACE
 
-// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
+// JSON reference:
+// https://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
 
 GeoRouteReplyEsri::GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request,
                                      QObject *parent) :
diff --git a/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
index 0e6bc2c7..ed613f4b 100644
--- a/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
@@ -48,7 +48,8 @@ static const QString kPrefixEsri(QStringLiteral("esri."));
 static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
 static const QString kParamToken(kPrefixEsri + QStringLiteral("token"));
 
-static const QString kUrlRouting(QStringLiteral("http://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve"));
+static const QString kUrlRouting(QStringLiteral(
+        "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve"));
 
 GeoRoutingManagerEngineEsri::GeoRoutingManagerEngineEsri(const QVariantMap &parameters,
                                                          QGeoServiceProvider::Error *error,
@@ -70,7 +71,8 @@ GeoRoutingManagerEngineEsri::~GeoRoutingManagerEngineEsri()
 {
 }
 
-// REST reference: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
+// REST reference:
+// https://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
 
 QGeoRouteReply *GeoRoutingManagerEngineEsri::calculateRoute(const QGeoRouteRequest &request)
 {
@@ -125,7 +127,7 @@ void GeoRoutingManagerEngineEsri::replyError(QGeoRouteReply::Error errorCode, co
 QString GeoRoutingManagerEngineEsri::preferedDirectionLangage()
 {
     // list of supported langages is defined in:
-    // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
+    // https://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
     const QStringList supportedLanguages = {
         "ar", // Generate directions in Arabic
         "cs", // Generate directions in Czech
diff --git a/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
index 5d15835d..24148f95 100644
--- a/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
@@ -230,7 +230,8 @@ QGeoMap *GeoTiledMappingManagerEngineEsri::createMap()
 // ${y} = Y
 // ${token} = Token
 
-// template = 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png'
+// template =
+// 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png'
 
 bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider::Error *error,
                                                             QString *errorString,
diff --git a/qtlocation/src/plugins/geoservices/esri/maps.json b/qtlocation/src/plugins/geoservices/esri/maps.json
index 8167ae7d..862e087d 100644
--- a/qtlocation/src/plugins/geoservices/esri/maps.json
+++ b/qtlocation/src/plugins/geoservices/esri/maps.json
@@ -6,8 +6,8 @@
             "description": "ArcGIS Online World Street Map",
             "mobile": true,
             "night": false,
-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=3b93337983e9436f8db950e38a8629af'>Esri</a> contributors"
+            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=3b93337983e9436f8db950e38a8629af'>Esri</a> contributors"
         },
 
         {
@@ -16,8 +16,8 @@
             "": "ArcGIS Online World Imagery",
             "mobile": true,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'>Esri</a> contributors"
         },
 
         {
@@ -26,8 +26,8 @@
             "description": "ArcGIS Online World Terrain Base",
             "mobile": false,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=c61ad8ab017d49e1a82f580ee1298931'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=c61ad8ab017d49e1a82f580ee1298931'>Esri</a> contributors"
         },
 
         {
@@ -36,8 +36,8 @@
             "description": "ArcGIS Online World Topography",
             "mobile": true,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=30e5fe3149c34df1ba922e6f5bbf808f'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=30e5fe3149c34df1ba922e6f5bbf808f'>Esri</a> contributors"
         },
 
         {
@@ -46,8 +46,8 @@
             "description": "This map presents land cover and detailed topographic maps for the United States.",
             "mobile": true,
             "night": false,
-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=99cd5fbd98934028802b4f797c4b1732'>Esri</a> contributors"
+            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=99cd5fbd98934028802b4f797c4b1732'>Esri</a> contributors"
         },
 
         {
@@ -56,8 +56,8 @@
             "description": "National Geographic World Map",
             "mobile": false,
             "night": false,
-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=b9b1b422198944fbbd5250b3241691b6'>Esri</a> contributors"
+            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=b9b1b422198944fbbd5250b3241691b6'>Esri</a> contributors"
         },
 
         {
@@ -66,8 +66,8 @@
             "description": "Thematic content providing a neutral background with minimal colors",
             "mobile": true,
             "night": false,
-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=ed712cb1db3e4bae9e85329040fb9a49'>Esri</a> contributors"
+            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=ed712cb1db3e4bae9e85329040fb9a49'>Esri</a> contributors"
         },
 
         {
@@ -76,8 +76,8 @@
             "description": "Natural Earth physical map for the world",
             "mobile": false,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=c4ec722a1cd34cf0a23904aadf8923a0'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=c4ec722a1cd34cf0a23904aadf8923a0'>Esri</a> contributors"
         },
 
         {
@@ -86,8 +86,8 @@
             "description": "Portrays surface elevation as shaded relief",
             "mobile": false,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=9c5370d0b54f4de1b48a3792d7377ff2'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=9c5370d0b54f4de1b48a3792d7377ff2'>Esri</a> contributors"
         },
 
         {
@@ -96,8 +96,8 @@
             "description": "This map is designed to be used as a basemap by marine GIS professionals and as a reference map by anyone interested in ocean data",
             "mobile": false,
             "night": false,
-            "url": "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=1e126e7520f9466c9ca28b8f28b5e500'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=1e126e7520f9466c9ca28b8f28b5e500'>Esri</a> contributors"
         },
 
         {
@@ -106,8 +106,8 @@
             "description": "Thematic content providing a neutral background with minimal colors",
             "mobile": false,
             "night": true,
-            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=a284a9b99b3446a3910d4144a50990f6'>Esri</a> contributors"
+            "url": "https://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=a284a9b99b3446a3910d4144a50990f6'>Esri</a> contributors"
         },
 
         {
@@ -116,8 +116,8 @@
             "description": "DeLorme’s topographic basemap is a seamless global data set that portrays transportation, hydrography, jurisdiction boundaries, and major geographic features",
             "mobile": false,
             "night": false,
-            "url": "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer",
-            "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=b165c3df453e4be6b5ac4fdb241effbe'>Esri</a> contributors"
+            "url": "https://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer",
+            "copyrightText": "&copy; <a href='https://www.arcgis.com/home/item.html?id=b165c3df453e4be6b5ac4fdb241effbe'>Esri</a> contributors"
         }
     ]
 }
diff --git a/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp b/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
index 3858ddf5..af66f28e 100644
--- a/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
+++ b/qtlocation/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
@@ -63,8 +63,10 @@ static const QString kCountriesKey(QStringLiteral("detailedCountries"));
 static const QString kLocalizedNamesKey(QStringLiteral("localizedNames"));
 static const QString kMaxLocationsKey(QStringLiteral("maxLocations"));
 
-static const QUrl kUrlGeocodeServer("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer?f=pjson");
-static const QUrl kUrlFindAddressCandidates("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates");
+static const QUrl kUrlGeocodeServer(
+        "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer?f=pjson");
+static const QUrl kUrlFindAddressCandidates("https://geocode.arcgis.com/arcgis/rest/services/World/"
+                                            "GeocodeServer/findAddressCandidates");
 
 PlaceManagerEngineEsri::PlaceManagerEngineEsri(const QVariantMap &parameters, QGeoServiceProvider::Error *error,
                                                QString *errorString) :
Submodule qtmultimedia f0344079..0d7cc33a:
diff --git a/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp b/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
index 2b5325132..b68b4af1b 100644
--- a/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
+++ b/qtmultimedia/src/plugins/pulseaudio/qaudioinput_pulse.cpp
@@ -402,6 +402,8 @@ int QPulseAudioInput::bytesReady() const
 
 qint64 QPulseAudioInput::read(char *data, qint64 len)
 {
+    Q_ASSERT(data != nullptr || len == 0);
+
     m_bytesAvailable = checkBytesReady();
 
     setError(QAudio::NoError);
@@ -411,7 +413,8 @@ qint64 QPulseAudioInput::read(char *data, qint64 len)
 
     if (!m_pullMode && !m_tempBuffer.isEmpty()) {
         readBytes = qMin(static_cast<int>(len), m_tempBuffer.size());
-        memcpy(data, m_tempBuffer.constData(), readBytes);
+        if (readBytes)
+            memcpy(data, m_tempBuffer.constData(), readBytes);
         m_totalTimeValue += readBytes;
 
         if (readBytes < m_tempBuffer.size()) {
@@ -502,9 +505,10 @@ qint64 QPulseAudioInput::read(char *data, qint64 len)
 
 void QPulseAudioInput::applyVolume(const void *src, void *dest, int len)
 {
+    Q_ASSERT((src && dest) || len == 0);
     if (m_volume < 1.f)
         QAudioHelperInternal::qMultiplySamples(m_volume, m_format, src, dest, len);
-    else
+    else if (len)
         memcpy(dest, src, len);
 }
 
Submodule qtpim 02efef5e...f9a8f0fc (commits not present)
Submodule qtquick3d b85cf622..47defc8b:
diff --git a/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro b/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
index ca5c499e..174a075b 100644
--- a/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
+++ b/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
@@ -10,7 +10,7 @@ QT_FOR_CONFIG += assetimporters-private
 include($$OUT_PWD/../qtassetimporters-config.pri)
 
 qtConfig(system-assimp):!if(cross_compile:host_build) {
-    QMAKE_USE_PRIVATE += assimp
+    QMAKE_USE_PRIVATE += quick3d-assimp
 } else {
     include(../../../3rdparty/assimp/assimp.pri)
 }
Submodule qtquickcontrols2 3a657dc0..56ce8233:
diff --git a/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp b/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
index e5fe734f7..e36922775 100644
--- a/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
+++ b/qtquickcontrols2/src/imports/platform/widgets/qwidgetplatformmenu.cpp
@@ -38,6 +38,7 @@
 #include "qwidgetplatformmenuitem_p.h"
 
 #include <QtGui/qwindow.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
 #include <QtWidgets/qmenu.h>
 #include <QtWidgets/qaction.h>
 
@@ -145,7 +146,7 @@ void QWidgetPlatformMenu::showPopup(const QWindow *window, const QRect &targetRe
 
     QPoint targetPos = targetRect.bottomLeft();
     if (window)
-        targetPos = window->mapToGlobal(targetPos);
+        targetPos = window->mapToGlobal(QHighDpi::fromNativeLocalPosition(targetPos, window));
 
     const QWidgetPlatformMenuItem *widgetItem = qobject_cast<const QWidgetPlatformMenuItem *>(item);
     m_menu->popup(targetPos, widgetItem ? widgetItem->action() : nullptr);
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
index 950e4e099..b81fbea0b 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
@@ -387,6 +387,17 @@ void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item)
         emit q->implicitIndicatorHeightChanged();
 }
 
+void QQuickAbstractButtonPrivate::itemDestroyed(QQuickItem *item)
+{
+    Q_Q(QQuickAbstractButton);
+    QQuickControlPrivate::itemDestroyed(item);
+    if (item == indicator) {
+        indicator = nullptr;
+        emit q->implicitIndicatorWidthChanged();
+        emit q->implicitIndicatorHeightChanged();
+    }
+}
+
 QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
 {
     Q_Q(const QQuickAbstractButton);
@@ -1176,6 +1187,12 @@ QAccessible::Role QQuickAbstractButton::accessibleRole() const
     }
     return QAccessible::Button;
 }
+
+void QQuickAbstractButton::accessiblePressAction()
+{
+    Q_D(QQuickAbstractButton);
+    d->trigger();
+}
 #endif
 
 QT_END_NAMESPACE
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
index 0fa48980e..ab66220d0 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
+++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p.h
@@ -209,6 +209,7 @@ protected:
 #if QT_CONFIG(accessibility)
     void accessibilityActiveChanged(bool active) override;
     QAccessible::Role accessibleRole() const override;
+    Q_INVOKABLE void accessiblePressAction();
 #endif
 
 private:
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
index 9291c1a87..b729720f2 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
+++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton_p_p.h
@@ -109,6 +109,7 @@ public:
 
     void itemImplicitWidthChanged(QQuickItem *item) override;
     void itemImplicitHeightChanged(QQuickItem *item) override;
+    void itemDestroyed(QQuickItem *item) override;
 
     // copied from qabstractbutton.cpp
     static const int AUTO_REPEAT_DELAY = 300;
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp b/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
index 2041e7741..8610cdfae 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickaction.cpp
@@ -145,7 +145,7 @@ int QQuickActionPrivate::ShortcutEntry::shortcutId() const
 
 void QQuickActionPrivate::ShortcutEntry::grab(const QKeySequence &shortcut, bool enabled)
 {
-    if (shortcut.isEmpty())
+    if (shortcut.isEmpty() || m_shortcutId)
         return;
 
     Qt::ShortcutContext context = Qt::WindowShortcut; // TODO
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp b/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
index f38c2b09c..6eed2a024 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickcontainer.cpp
@@ -225,6 +225,7 @@ void QQuickContainerPrivate::cleanup()
     QObject::disconnect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged);
     QObject::disconnect(contentModel, &QQmlObjectModel::childrenChanged, q, &QQuickContainer::contentChildrenChanged);
     delete contentModel;
+    contentModel = nullptr;
 }
 
 QQuickItem *QQuickContainerPrivate::itemAt(int index) const
@@ -436,7 +437,7 @@ void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty<QQuickItem>
 void QQuickContainerPrivate::updateContentWidth()
 {
     Q_Q(QQuickContainer);
-    if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth))
+    if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth) || !contentModel)
         return;
 
     contentWidth = implicitContentWidth;
@@ -446,7 +447,7 @@ void QQuickContainerPrivate::updateContentWidth()
 void QQuickContainerPrivate::updateContentHeight()
 {
     Q_Q(QQuickContainer);
-    if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight))
+    if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight) || !contentModel)
         return;
 
     contentHeight = implicitContentHeight;
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp b/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
index bbbd0e622..1f4b47343 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
@@ -845,6 +845,13 @@ void QQuickControlPrivate::executeBackground(bool complete)
         quickCompleteDeferred(q, backgroundName(), background);
 }
 
+/*
+    \internal
+
+    Hides an item that was replaced by a newer one, rather than
+    deleting it, as the item is typically created in QML and hence
+    we don't own it.
+*/
 void QQuickControlPrivate::hideOldItem(QQuickItem *item)
 {
     if (!item)
@@ -863,6 +870,29 @@ void QQuickControlPrivate::hideOldItem(QQuickItem *item)
 #endif
 }
 
+/*
+    \internal
+
+    Named "unhide" because it's used for cases where an item
+    that was previously hidden by \l hideOldItem() wants to be
+    shown by a control again, such as a ScrollBar in ScrollView.
+*/
+void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item)
+{
+    Q_ASSERT(item);
+    qCDebug(lcItemManagement) << "unhiding old item" << item;
+
+    item->setVisible(true);
+    item->setParentItem(control);
+
+#if QT_CONFIG(accessibility)
+    // Add the item back in to the accessibility tree.
+    QQuickAccessibleAttached *accessible = accessibleAttached(item);
+    if (accessible)
+        accessible->setIgnored(false);
+#endif
+}
+
 void QQuickControlPrivate::updateBaselineOffset()
 {
     Q_Q(QQuickControl);
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h b/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
index 8e979079e..a6e624c91 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
+++ b/qtquickcontrols2/src/quicktemplates2/qquickcontrol_p_p.h
@@ -173,6 +173,7 @@ public:
     virtual void executeBackground(bool complete = false);
 
     static void hideOldItem(QQuickItem *item);
+    static void unhideOldItem(QQuickControl *control, QQuickItem *item);
 
     void updateBaselineOffset();
 
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp b/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
index e6db14eb5..6197d1547 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -237,7 +237,7 @@ static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment
 void QQuickDialogButtonBoxPrivate::resizeContent()
 {
     Q_Q(QQuickDialogButtonBox);
-    if (!contentItem)
+    if (!contentItem || !contentModel)
         return;
 
     QRectF geometry = q->boundingRect().adjusted(q->leftPadding(), q->topPadding(), -q->rightPadding(), -q->bottomPadding());
@@ -322,6 +322,9 @@ void QQuickDialogButtonBoxPrivate::updateLayout()
 qreal QQuickDialogButtonBoxPrivate::getContentWidth() const
 {
     Q_Q(const QQuickDialogButtonBox);
+    if (!contentModel)
+        return 0;
+
     const int count = contentModel->count();
     const qreal totalSpacing = qMax(0, count - 1) * spacing;
     qreal totalWidth = totalSpacing;
@@ -341,6 +344,9 @@ qreal QQuickDialogButtonBoxPrivate::getContentWidth() const
 qreal QQuickDialogButtonBoxPrivate::getContentHeight() const
 {
     Q_Q(const QQuickDialogButtonBox);
+    if (!contentModel)
+        return 0;
+
     const int count = contentModel->count();
     qreal maxHeight = 0;
     for (int i = 0; i < count; ++i) {
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp b/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
index 91bd59184..0ce518f84 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickoverlay.cpp
@@ -399,8 +399,11 @@ void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
     Q_D(QQuickOverlay);
     QQuickItem::itemChange(change, data);
 
-    if (change == ItemChildAddedChange || change == ItemChildRemovedChange)
+    if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
         setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
+        if (data.item->parent() == d->mouseGrabberPopup)
+            d->setMouseGrabberPopup(nullptr);
+    }
 }
 
 void QQuickOverlay::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp b/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
index 4e2f509db..1c4b308cd 100644
--- a/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
+++ b/qtquickcontrols2/src/quicktemplates2/qquickscrollbar.cpp
@@ -797,6 +797,14 @@ void QQuickScrollBarAttachedPrivate::initHorizontal()
     if (parent && parent == flickable->parentItem())
         horizontal->stackAfter(flickable);
 
+    // If a scroll bar was previously hidden (due to e.g. setting a new contentItem
+    // on a ScrollView), we need to make sure that we un-hide it.
+    // We don't bother checking if the item is actually the old one, because
+    // if it's not, all of the things the function does (setting parent, visibility, etc.)
+    // should be no-ops anyway.
+    if (auto control = qobject_cast<QQuickControl*>(q_ptr->parent()))
+        QQuickControlPrivate::unhideOldItem(control, horizontal);
+
     layoutHorizontal();
     horizontal->setSize(area->property("widthRatio").toReal());
     horizontal->setPosition(area->property("xPosition").toReal());
@@ -818,6 +826,9 @@ void QQuickScrollBarAttachedPrivate::initVertical()
     if (parent && parent == flickable->parentItem())
         vertical->stackAfter(flickable);
 
+    if (auto control = qobject_cast<QQuickControl*>(q_ptr->parent()))
+        QQuickControlPrivate::unhideOldItem(control, vertical);
+
     layoutVertical();
     vertical->setSize(area->property("heightRatio").toReal());
     vertical->setPosition(area->property("yPosition").toReal());
diff --git a/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml b/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
index 0e8b08352..cd4931184 100644
--- a/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
+++ b/qtquickcontrols2/tests/auto/controls/data/tst_scrollview.qml
@@ -576,4 +576,51 @@ TestCase {
         verify(newHorizontalScrollBar.visible)
         verify(!oldHorizontalScrollBar.visible)
     }
+
+    Component {
+        id: bindingToContentItemAndStandaloneFlickable
+
+        Item {
+            width: 200
+            height: 200
+
+            property alias scrollView: scrollView
+
+            ScrollView {
+                id: scrollView
+                anchors.fill: parent
+                contentItem: listView
+
+                property Item someBinding: contentItem
+            }
+            ListView {
+                id: listView
+                model: 10
+                delegate: ItemDelegate {
+                    text: modelData
+                    width: listView.width
+                }
+            }
+        }
+    }
+
+    // Tests that scroll bars show up for a ScrollView where
+    // - its contentItem is declared as a standalone, separate item
+    // - there is a binding to contentItem (which causes a default Flickable to be created)
+    function test_bindingToContentItemAndStandaloneFlickable() {
+        let root = createTemporaryObject(bindingToContentItemAndStandaloneFlickable, testCase)
+        verify(root)
+
+        let control = root.scrollView
+        let verticalScrollBar = control.ScrollBar.vertical
+        let horizontalScrollBar = control.ScrollBar.horizontal
+        compare(verticalScrollBar.parent, control)
+        compare(horizontalScrollBar.parent, control)
+        verify(verticalScrollBar.visible)
+        verify(horizontalScrollBar.visible)
+
+        mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50)
+        verify(verticalScrollBar.active)
+        verify(horizontalScrollBar.active)
+    }
 }
diff --git a/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml b/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
index b3fab41ca..10b6baa02 100644
--- a/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
+++ b/qtquickcontrols2/tests/auto/controls/data/tst_switch.qml
@@ -608,4 +608,27 @@ TestCase {
         mouseClick(control.indicator)
         verify(control.activeFocus)
     }
+
+    Component {
+        id: deletionOrder1
+        Item {
+            Image { id: innerImage }
+            Switch { indicator: innerImage }
+        }
+    }
+
+    Component {
+        id: deletionOrder2
+        Item {
+            Switch { indicator: innerImage }
+            Image { id: innerImage }
+        }
+    }
+
+    function test_deletionOrder() {
+        var control1 = createTemporaryObject(deletionOrder1, testCase)
+        verify(control1)
+        var control2 = createTemporaryObject(deletionOrder2, testCase)
+        verify(control2)
+    }
 }
diff --git a/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml b/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml
new file mode 100644
index 000000000..9e4598b9f
--- /dev/null
+++ b/qtquickcontrols2/tests/auto/qquickpopup/data/releaseAfterExitTransition.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+ApplicationWindow {
+    id: window
+    width: 400
+    height: 400
+    title: "releaseAfterExitTransition"
+
+    property alias popup: popup
+    property alias modalPopup: modalPopup
+
+    Popup {
+        id: popup
+        y: parent.height - height
+        width: 50
+        height: 50
+    }
+
+    Popup {
+        id: modalPopup
+        modal: true
+        y: parent.height - height
+        width: 50
+        height: 50
+        exit:  Transition { PauseAnimation { duration: 100 } }
+    }
+}
diff --git a/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp b/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
index 54952d128..3d50e2dd4 100644
--- a/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
+++ b/qtquickcontrols2/tests/auto/qquickpopup/tst_qquickpopup.cpp
@@ -100,6 +100,7 @@ private slots:
     void invisibleToolTipOpen();
     void centerInOverlayWithinStackViewItem();
     void destroyDuringExitTransition();
+    void releaseAfterExitTransition();
 };
 
 void tst_QQuickPopup::initTestCase()
@@ -1575,6 +1576,34 @@ void tst_QQuickPopup::destroyDuringExitTransition()
     QVERIFY(!button->isDown());
 }
 
+void tst_QQuickPopup::releaseAfterExitTransition()
+{
+    QQuickApplicationHelper helper(this, "releaseAfterExitTransition.qml");
+    QVERIFY2(helper.ready, helper.failureMessage());
+
+    QQuickWindow *window = helper.window;
+    window->show();
+    QVERIFY(QTest::qWaitForWindowActive(window));
+
+    QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+    QQuickPopup *modalPopup = window->property("modalPopup").value<QQuickPopup *>();
+    QQuickPopup *popup = window->property("popup").value<QQuickPopup *>();
+
+    modalPopup->open();
+    QTRY_VERIFY(modalPopup->isOpened());
+
+    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
+    // wait until the transition is finished and the overlay hides itself
+    QTRY_VERIFY(!overlay->isVisible());
+    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
+
+    popup->open();
+    QTRY_VERIFY(popup->isOpened());
+    QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1));
+    QTRY_VERIFY(!popup->isOpened());
+}
+
+
 QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup)
 
 #include "tst_qquickpopup.moc"
Submodule qtscript 5be95f96...4d8e4bd2 (commits not present)
Submodule qtspeech 17fc9fde..255845e2:
diff --git a/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp b/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
index 6eb74b8..bcc7dd1 100644
--- a/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
+++ b/qtspeech/src/plugins/tts/speechdispatcher/qtexttospeech_speechd.cpp
@@ -357,7 +357,9 @@ QVector<QLocale> QTextToSpeechEngineSpeechd::availableLocales() const
 
 QVector<QVoice> QTextToSpeechEngineSpeechd::availableVoices() const
 {
-    return m_voices.values(m_currentLocale.name()).toVector();
+    QList<QVoice> resultList = m_voices.values(m_currentLocale.name());
+    std::reverse(resultList.begin(), resultList.end());
+    return resultList.toVector();
 }
 
 // We have no way of knowing our own client_id since speech-dispatcher seems to be incomplete
Submodule qtsvg 0c05780e..a7a0f249:
diff --git a/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp b/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
index 561e77e..12e0574 100644
--- a/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
+++ b/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
@@ -191,6 +191,8 @@ bool QSvgIOHandler::read(QImage *image)
             }
         }
         if (!finalSize.isEmpty()) {
+            if (qMax(finalSize.width(), finalSize.height()) > 0xffff)
+                return false; // Assume corrupted file
             image->fill(d->backColor.rgba());
             QPainter p(image);
             d->r.render(&p, bounds);
diff --git a/qtsvg/src/svg/qsvghandler.cpp b/qtsvg/src/svg/qsvghandler.cpp
index a5f877f..8dda563 100644
--- a/qtsvg/src/svg/qsvghandler.cpp
+++ b/qtsvg/src/svg/qsvghandler.cpp
@@ -1393,9 +1393,10 @@ static void parseFont(QSvgNode *node,
         case FontSizeNone:
             break;
         case FontSizeValue: {
-            QSvgHandler::LengthType dummy; // should always be pixel size
-            fontStyle->setSize(qMin(parseLength(attributes.fontSize, dummy, handler),
-                                    qreal(0xffff)));
+            QSvgHandler::LengthType type;
+            qreal fs = parseLength(attributes.fontSize, type, handler);
+            fs = convertToPixels(fs, true, type);
+            fontStyle->setSize(qMin(fs, qreal(0xffff)));
         }
             break;
         default:
@@ -2513,6 +2514,8 @@ static bool parseAnimateTransformNode(QSvgNode *parent,
             ++s;
         }
     }
+    if (vals.count() % 3 != 0)
+        return false;
 
     bool ok = true;
     int begin = parseClockValue(beginStr, &ok);
@@ -2576,6 +2579,8 @@ static QSvgNode *createCircleNode(QSvgNode *parent,
     qreal ncx = toDouble(cx);
     qreal ncy = toDouble(cy);
     qreal nr  = toDouble(r);
+    if (nr < 0.0)
+        return nullptr;
 
     QRectF rect(ncx-nr, ncy-nr, nr*2, nr*2);
     QSvgNode *circle = new QSvgCircle(parent, rect);
@@ -3046,15 +3051,16 @@ static QSvgStyleProperty *createRadialGradientNode(QSvgNode *node,
 
     qreal ncx = 0.5;
     qreal ncy = 0.5;
-    qreal nr  = 0.5;
     if (!cx.isEmpty())
         ncx = toDouble(cx);
     if (!cy.isEmpty())
         ncy = toDouble(cy);
+
+    qreal nr = 0.0;
     if (!r.isEmpty())
         nr = toDouble(r);
-    if (nr < 0.5)
-        nr = 0.5;
+    if (nr <= 0.0)
+        return nullptr;
 
     qreal nfx = ncx;
     if (!fx.isEmpty())
@@ -3350,7 +3356,9 @@ static QSvgNode *createTextNode(QSvgNode *parent,
     //### editable and rotate not handled
     QSvgHandler::LengthType type;
     qreal nx = parseLength(x, type, handler);
+    nx = convertToPixels(nx, true, type);
     qreal ny = parseLength(y, type, handler);
+    ny = convertToPixels(ny, true, type);
 
     QSvgNode *text = new QSvgText(parent, QPointF(nx, ny));
     return text;
@@ -3691,9 +3699,7 @@ void QSvgHandler::parse()
         case QXmlStreamReader::EndElement:
             endElement(xml->name());
             ++remainingUnfinishedElements;
-            // if we are using somebody else's qxmlstreamreader
-            // we should not read until the end of the stream
-            done = !m_ownsReader && (xml->name() == QLatin1String("svg"));
+            done = (xml->name() == QLatin1String("svg"));
             break;
         case QXmlStreamReader::Characters:
             characters(xml->text());
diff --git a/qtsvg/src/svg/qsvgstructure.cpp b/qtsvg/src/svg/qsvgstructure.cpp
index b89608b..89c9e4e 100644
--- a/qtsvg/src/svg/qsvgstructure.cpp
+++ b/qtsvg/src/svg/qsvgstructure.cpp
@@ -255,9 +255,13 @@ inline static bool isSupportedSvgFeature(const QString &str)
     };
 
     if (str.length() <= MAX_WORD_LENGTH && str.length() >= MIN_WORD_LENGTH) {
+        const char16_t unicode44 = str.at(44).unicode();
+        const char16_t unicode45 = str.at(45).unicode();
+        if (unicode44 >= sizeof(asso_values) || unicode45 >= sizeof(asso_values))
+            return false;
         const int key = str.length()
-                        + asso_values[str.at(45).unicode()]
-                        + asso_values[str.at(44).unicode()];
+                        + asso_values[unicode45]
+                        + asso_values[unicode44];
         if (key <= MAX_HASH_VALUE && key >= 0)
             return str == QLatin1String(wordlist[key]);
     }
diff --git a/qtsvg/src/svg/qsvgtinydocument.cpp b/qtsvg/src/svg/qsvgtinydocument.cpp
index 63d0797..19e7154 100644
--- a/qtsvg/src/svg/qsvgtinydocument.cpp
+++ b/qtsvg/src/svg/qsvgtinydocument.cpp
@@ -433,8 +433,16 @@ void QSvgTinyDocument::draw(QPainter *p, QSvgExtraStates &)
     draw(p);
 }
 
+static bool isValidMatrix(const QTransform &transform)
+{
+    qreal determinant = transform.determinant();
+    return qIsFinite(determinant);
+}
+
 void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect, const QRectF &sourceRect)
 {
+    QTransform oldTransform = p->worldTransform();
+
     QRectF target = targetRect;
     if (target.isEmpty()) {
         QPaintDevice *dev = p->device();
@@ -487,6 +495,9 @@ void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect,
         }
 #endif
     }
+
+    if (!isValidMatrix(p->worldTransform()))
+        p->setWorldTransform(oldTransform);
 }
 
 QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const
diff --git a/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 36c76ec..db71e02 100644
--- a/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/qtsvg/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -86,6 +86,8 @@ private slots:
     void oss_fuzz_23731();
     void oss_fuzz_24131();
     void oss_fuzz_24738();
+    void illegalAnimateTransform_data();
+    void illegalAnimateTransform();
 
 #ifndef QT_NO_COMPRESS
     void testGzLoading();
@@ -1646,5 +1648,22 @@ void tst_QSvgRenderer::oss_fuzz_24738()
     QSvgRenderer().load(QByteArray("<svg><path d=\"a 2 1e-212.....\">"));
 }
 
+void tst_QSvgRenderer::illegalAnimateTransform_data()
+{
+    QTest::addColumn<QByteArray>("svg");
+
+    QTest::newRow("case1") << QByteArray("<svg><animateTransform type=\"rotate\" begin=\"1\" dur=\"2\" values=\"8,0,5,0\">");
+    QTest::newRow("case2") << QByteArray("<svg><animateTransform type=\"rotate\" begin=\"1\" dur=\"2\" values=\"1,2\">");
+    QTest::newRow("case3") << QByteArray("<svg><animateTransform type=\"rotate\" begin=\"1\" dur=\"2\" from=\".. 5 2\" to=\"f\">");
+    QTest::newRow("case4") << QByteArray("<svg><animateTransform type=\"scale\" begin=\"1\" dur=\"2\" by=\"--,..\">");
+}
+
+void tst_QSvgRenderer::illegalAnimateTransform()
+{
+    QFETCH(QByteArray, svg);
+    QSvgRenderer renderer;
+    QVERIFY(!renderer.load(svg)); // also shouldn't assert
+}
+
 QTEST_MAIN(tst_QSvgRenderer)
 #include "tst_qsvgrenderer.moc"
Submodule qttools 6914f7c8..090e526e:
diff --git a/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp b/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
index feab1e2d5..cbfb82507 100644
--- a/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
+++ b/qttools/src/assistant/qhelpgenerator/helpgenerator.cpp
@@ -445,7 +445,9 @@ bool HelpGeneratorPrivate::insertFiles(const QStringList &files, const QString &
     if (filterSetId < 0)
         return false;
     ++filterSetId;
-    for (int attId : qAsConst(filterAtts)) {
+    QList<int> attValues = filterAtts.values();
+    std::sort(attValues.begin(), attValues.end());
+    for (int attId : qAsConst(attValues)) {
         m_query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable "
             "VALUES(?, ?)"));
         m_query->bindValue(0, filterSetId);
Submodule qtwayland dfb0129c..2904e1b3:
diff --git a/qtwayland/src/client/configure.json b/qtwayland/src/client/configure.json
index 2f424580..29222357 100644
--- a/qtwayland/src/client/configure.json
+++ b/qtwayland/src/client/configure.json
@@ -149,8 +149,7 @@
                     "#endif"
                 ]
             },
-            "libs": "-ldrm",
-            "use": "egl"
+            "use": "drm egl"
         },
         "vulkan-server-buffer": {
             "label": "Vulkan Buffer Sharing",
@@ -168,7 +167,8 @@
                     "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
                     "return 0;"
                 ]
-            }
+            },
+            "use": "wayland-client"
         },
         "egl_1_5-wayland": {
             "label": "EGL 1.5 with Wayland Platform",
@@ -183,7 +183,7 @@
                     "eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, (struct wl_display *)(nullptr), nullptr);"
                 ]
             },
-            "use": "egl"
+            "use": "egl wayland-client"
         }
     },
 
diff --git a/qtwayland/src/client/global/qwaylandclientextension.cpp b/qtwayland/src/client/global/qwaylandclientextension.cpp
index 125b1e19..edccfe63 100644
--- a/qtwayland/src/client/global/qwaylandclientextension.cpp
+++ b/qtwayland/src/client/global/qwaylandclientextension.cpp
@@ -74,7 +74,10 @@ void QWaylandClientExtensionPrivate::handleRegistryGlobal(void *data, ::wl_regis
 void QWaylandClientExtension::addRegistryListener()
 {
     Q_D(QWaylandClientExtension);
-    d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
+    if (!d->registered) {
+        d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
+        d->registered = true;
+    }
 }
 
 QWaylandClientExtension::QWaylandClientExtension(const int ver)
@@ -88,6 +91,13 @@ QWaylandClientExtension::QWaylandClientExtension(const int ver)
     QMetaObject::invokeMethod(this, "addRegistryListener", Qt::QueuedConnection);
 }
 
+QWaylandClientExtension::~QWaylandClientExtension()
+{
+    Q_D(QWaylandClientExtension);
+    if (d->registered && !QCoreApplication::closingDown())
+        d->waylandIntegration->display()->removeListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
+}
+
 QtWaylandClient::QWaylandIntegration *QWaylandClientExtension::integration() const
 {
     Q_D(const QWaylandClientExtension);
diff --git a/qtwayland/src/client/global/qwaylandclientextension.h b/qtwayland/src/client/global/qwaylandclientextension.h
index 98272e57..5bd28398 100644
--- a/qtwayland/src/client/global/qwaylandclientextension.h
+++ b/qtwayland/src/client/global/qwaylandclientextension.h
@@ -63,6 +63,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtension : public QObject
     Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
 public:
     QWaylandClientExtension(const int version);
+    ~QWaylandClientExtension();
 
     QtWaylandClient::QWaylandIntegration *integration() const;
     int version() const;
diff --git a/qtwayland/src/client/global/qwaylandclientextension_p.h b/qtwayland/src/client/global/qwaylandclientextension_p.h
index 69cc46a0..9091efbe 100644
--- a/qtwayland/src/client/global/qwaylandclientextension_p.h
+++ b/qtwayland/src/client/global/qwaylandclientextension_p.h
@@ -68,6 +68,7 @@ public:
     QtWaylandClient::QWaylandIntegration *waylandIntegration = nullptr;
     int version = -1;
     bool active = false;
+    bool registered = false;
 };
 
 class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
diff --git a/qtwayland/src/client/qwaylanddatadevice.cpp b/qtwayland/src/client/qwaylanddatadevice.cpp
index 7e2e3308..e3e60ed5 100644
--- a/qtwayland/src/client/qwaylanddatadevice.cpp
+++ b/qtwayland/src/client/qwaylanddatadevice.cpp
@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
 
 QWaylandDataDevice::~QWaylandDataDevice()
 {
+    if (wl_data_device_get_version(object()) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
+        release();
 }
 
 QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
@@ -110,7 +112,7 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
     return m_dragOffer.data();
 }
 
-bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
+bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon)
 {
     auto *seat = m_display->currentInputDevice();
     auto *origin = seat->pointerFocus();
@@ -123,7 +125,28 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
     }
 
     m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
+
+    if (wl_data_device_get_version(object()) >= 3)
+        m_dragSource->set_actions(dropActionsToWl(supportedActions));
+
     connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
+    connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
+            auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+            // in old versions drop action is not set, so we guess
+            if (wl_data_source_get_version(m_dragSource->object()) < 3) {
+                drag->setResponse(accepted);
+            } else {
+                QPlatformDropQtResponse response(accepted, action);
+                drag->setResponse(response);
+            }
+    });
+    connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this, [](bool accepted, Qt::DropAction action) {
+        QPlatformDropQtResponse response(accepted, action);
+        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response);
+    });
+    connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() {
+        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
+    });
 
     start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
     return true;
@@ -152,7 +175,7 @@ void QWaylandDataDevice::data_device_drop()
         supportedActions = drag->supportedActions();
     } else if (m_dragOffer) {
         dragData = m_dragOffer->mimeData();
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+        supportedActions = m_dragOffer->supportedActions();
     } else {
         return;
     }
@@ -162,7 +185,11 @@ void QWaylandDataDevice::data_device_drop()
                                                                           QGuiApplication::keyboardModifiers());
 
     if (drag) {
-        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
+        auto drag =  static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+        drag->setDropResponse(response);
+        drag->finishDrag();
+    } else if (m_dragOffer) {
+        m_dragOffer->finish();
     }
 }
 
@@ -186,7 +213,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
         supportedActions = drag->supportedActions();
     } else if (m_dragOffer) {
         dragData = m_dragOffer->mimeData();
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+        supportedActions = m_dragOffer->supportedActions();
     }
 
     const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
@@ -197,11 +224,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
         static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
     }
 
-    if (response.isAccepted()) {
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
-    } else {
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
-    }
+    sendResponse(supportedActions, response);
 }
 
 void QWaylandDataDevice::data_device_leave()
@@ -235,10 +258,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
         supportedActions = drag->supportedActions();
     } else {
         dragData = m_dragOffer->mimeData();
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+        supportedActions = m_dragOffer->supportedActions();
     }
 
-    QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
+    const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
                                                                           QGuiApplication::mouseButtons(),
                                                                           QGuiApplication::keyboardModifiers());
 
@@ -246,11 +269,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
         static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
     }
 
-    if (response.isAccepted()) {
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
-    } else {
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
-    }
+    sendResponse(supportedActions, response);
 }
 #endif // QT_CONFIG(draganddrop)
 
@@ -277,14 +296,10 @@ void QWaylandDataDevice::selectionSourceCancelled()
 #if QT_CONFIG(draganddrop)
 void QWaylandDataDevice::dragSourceCancelled()
 {
+    static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
     m_dragSource.reset();
 }
 
-void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
-{
-    static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
-}
-
 QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
 {
     QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y));
@@ -297,6 +312,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
     }
     return pnt;
 }
+
+void QWaylandDataDevice::sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response)
+{
+    if (response.isAccepted()) {
+        if (wl_data_device_get_version(object()) >= 3)
+            m_dragOffer->set_actions(dropActionsToWl(supportedActions), dropActionsToWl(response.acceptedAction()));
+
+        m_dragOffer->accept(m_enterSerial, m_dragOffer->firstFormat());
+    } else {
+        m_dragOffer->accept(m_enterSerial, QString());
+    }
+}
+
+int QWaylandDataDevice::dropActionsToWl(Qt::DropActions actions)
+{
+
+    int wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+    if (actions & Qt::CopyAction)
+        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+    if (actions & (Qt::MoveAction | Qt::TargetMoveAction))
+        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+
+    // wayland does not support LinkAction at the time of writing
+    return wlActions;
+}
+
+
 #endif // QT_CONFIG(draganddrop)
 
 }
diff --git a/qtwayland/src/client/qwaylanddatadevice_p.h b/qtwayland/src/client/qwaylanddatadevice_p.h
index 16c3ad28..801dcc2c 100644
--- a/qtwayland/src/client/qwaylanddatadevice_p.h
+++ b/qtwayland/src/client/qwaylanddatadevice_p.h
@@ -64,6 +64,7 @@ QT_REQUIRE_CONFIG(wayland_datadevice);
 QT_BEGIN_NAMESPACE
 
 class QMimeData;
+class QPlatformDragQtResponse;
 class QWindow;
 
 namespace QtWaylandClient {
@@ -89,7 +90,7 @@ public:
 
 #if QT_CONFIG(draganddrop)
     QWaylandDataOffer *dragOffer() const;
-    bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
+    bool startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon);
     void cancelDrag();
 #endif
 
@@ -109,13 +110,16 @@ private Q_SLOTS:
 
 #if QT_CONFIG(draganddrop)
     void dragSourceCancelled();
-    void dragSourceTargetChanged(const QString &mimeType);
 #endif
 
 private:
 #if QT_CONFIG(draganddrop)
     QPoint calculateDragPosition(int x, int y, QWindow *wnd) const;
 #endif
+    void sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response);
+
+    static int dropActionsToWl(Qt::DropActions dropActions);
+
 
     QWaylandDisplay *m_display = nullptr;
     QWaylandInputDevice *m_inputDevice = nullptr;
diff --git a/qtwayland/src/client/qwaylanddatadevicemanager.cpp b/qtwayland/src/client/qwaylanddatadevicemanager.cpp
index 35d67307..6dc4f77f 100644
--- a/qtwayland/src/client/qwaylanddatadevicemanager.cpp
+++ b/qtwayland/src/client/qwaylanddatadevicemanager.cpp
@@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE
 
 namespace QtWaylandClient {
 
-QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
-    : wl_data_device_manager(display->wl_registry(), id, 1)
+QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id)
+    : wl_data_device_manager(display->wl_registry(), id, qMin(version, 3))
     , m_display(display)
 {
     // Create transfer devices for all input devices.
diff --git a/qtwayland/src/client/qwaylanddatadevicemanager_p.h b/qtwayland/src/client/qwaylanddatadevicemanager_p.h
index bd05c0fb..510d9be4 100644
--- a/qtwayland/src/client/qwaylanddatadevicemanager_p.h
+++ b/qtwayland/src/client/qwaylanddatadevicemanager_p.h
@@ -68,7 +68,7 @@ class QWaylandInputDevice;
 class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
 {
 public:
-    QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
+    QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id);
     ~QWaylandDataDeviceManager() override;
 
     QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
diff --git a/qtwayland/src/client/qwaylanddataoffer.cpp b/qtwayland/src/client/qwaylanddataoffer.cpp
index 2297e8a1..fe0ea8c9 100644
--- a/qtwayland/src/client/qwaylanddataoffer.cpp
+++ b/qtwayland/src/client/qwaylanddataoffer.cpp
@@ -82,6 +82,15 @@ QMimeData *QWaylandDataOffer::mimeData()
     return m_mimeData.data();
 }
 
+Qt::DropActions QWaylandDataOffer::supportedActions() const
+{
+    if (wl_data_offer_get_version(const_cast<::wl_data_offer*>(object())) < 3) {
+        return Qt::MoveAction | Qt::CopyAction;
+    }
+
+    return m_supportedActions;
+}
+
 void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd)
 {
     receive(mimeType, fd);
@@ -93,6 +102,22 @@ void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
     m_mimeData->appendFormat(mime_type);
 }
 
+void QWaylandDataOffer::data_offer_action(uint32_t dnd_action)
+{
+    Q_UNUSED(dnd_action);
+    // This is the compositor telling the drag target what action it should perform
+    // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
+}
+
+void QWaylandDataOffer::data_offer_source_actions(uint32_t source_actions)
+{
+    m_supportedActions = Qt::DropActions();
+    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+        m_supportedActions |= Qt::MoveAction;
+    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+        m_supportedActions |= Qt::CopyAction;
+}
+
 QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
     : m_dataOffer(dataOffer)
 {
@@ -163,17 +188,18 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
 
 int QWaylandMimeData::readData(int fd, QByteArray &data) const
 {
-    fd_set readset;
-    FD_ZERO(&readset);
-    FD_SET(fd, &readset);
-    struct timeval timeout;
+    struct pollfd readset;
+    readset.fd = fd;
+    readset.events = POLLIN;
+    struct timespec timeout;
     timeout.tv_sec = 1;
-    timeout.tv_usec = 0;
+    timeout.tv_nsec = 0;
+
 
     Q_FOREVER {
-        int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
+        int ready = qt_safe_poll(&readset, 1, &timeout);
         if (ready < 0) {
-            qWarning() << "QWaylandDataOffer: select() failed";
+            qWarning() << "QWaylandDataOffer: qt_safe_poll() failed";
             return -1;
         } else if (ready == 0) {
             qWarning("QWaylandDataOffer: timeout reading from pipe");
diff --git a/qtwayland/src/client/qwaylanddataoffer_p.h b/qtwayland/src/client/qwaylanddataoffer_p.h
index 9cf1483c..6f667398 100644
--- a/qtwayland/src/client/qwaylanddataoffer_p.h
+++ b/qtwayland/src/client/qwaylanddataoffer_p.h
@@ -82,6 +82,7 @@ public:
     explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
     ~QWaylandDataOffer() override;
     QMimeData *mimeData() override;
+    Qt::DropActions supportedActions() const;
 
     QString firstFormat() const;
 
@@ -89,10 +90,13 @@ public:
 
 protected:
     void data_offer_offer(const QString &mime_type) override;
+    void data_offer_source_actions(uint32_t source_actions) override;
+    void data_offer_action(uint32_t dnd_action) override;
 
 private:
     QWaylandDisplay *m_display = nullptr;
     QScopedPointer<QWaylandMimeData> m_mimeData;
+    Qt::DropActions m_supportedActions;
 };
 
 
diff --git a/qtwayland/src/client/qwaylanddatasource.cpp b/qtwayland/src/client/qwaylanddatasource.cpp
index f45122fb..5599cbd4 100644
--- a/qtwayland/src/client/qwaylanddatasource.cpp
+++ b/qtwayland/src/client/qwaylanddatasource.cpp
@@ -101,7 +101,32 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
 
 void QWaylandDataSource::data_source_target(const QString &mime_type)
 {
-    Q_EMIT targetChanged(mime_type);
+    m_accepted = !mime_type.isEmpty();
+    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
+}
+
+void QWaylandDataSource::data_source_action(uint32_t action)
+{
+    Qt::DropAction qtAction = Qt::IgnoreAction;
+
+    if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+        qtAction = Qt::MoveAction;
+    else if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+        qtAction = Qt::CopyAction;
+
+    m_dropAction = qtAction;
+    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
+}
+
+void QWaylandDataSource::data_source_dnd_finished()
+{
+    Q_EMIT finished();
+}
+
+void QWaylandDataSource::data_source_dnd_drop_performed()
+{
+
+    Q_EMIT dndDropped(m_accepted, m_dropAction);
 }
 
 }
diff --git a/qtwayland/src/client/qwaylanddatasource_p.h b/qtwayland/src/client/qwaylanddatasource_p.h
index 25afff79..96f07bc3 100644
--- a/qtwayland/src/client/qwaylanddatasource_p.h
+++ b/qtwayland/src/client/qwaylanddatasource_p.h
@@ -77,17 +77,25 @@ public:
     QMimeData *mimeData() const;
 
 Q_SIGNALS:
-    void targetChanged(const QString &mime_type);
     void cancelled();
+    void finished();
+
+    void dndResponseUpdated(bool accepted, Qt::DropAction action);
+    void dndDropped(bool accepted, Qt::DropAction action);
 
 protected:
     void data_source_cancelled() override;
     void data_source_send(const QString &mime_type, int32_t fd) override;
     void data_source_target(const QString &mime_type) override;
+    void data_source_dnd_drop_performed() override;
+    void data_source_dnd_finished() override;
+    void data_source_action(uint32_t action) override;
 
 private:
     QWaylandDisplay *m_display = nullptr;
     QMimeData *m_mime_data = nullptr;
+    bool m_accepted = false;
+    Qt::DropAction m_dropAction = Qt::IgnoreAction;
 };
 
 }
diff --git a/qtwayland/src/client/qwaylanddisplay.cpp b/qtwayland/src/client/qwaylanddisplay.cpp
index f10c1f79..c01e238b 100644
--- a/qtwayland/src/client/qwaylanddisplay.cpp
+++ b/qtwayland/src/client/qwaylanddisplay.cpp
@@ -85,10 +85,203 @@
 
 #include <errno.h>
 
+#include <tuple> // for std::tie
+
+static void checkWaylandError(struct wl_display *display)
+{
+    int ecode = wl_display_get_error(display);
+    if ((ecode == EPIPE || ecode == ECONNRESET)) {
+        // special case this to provide a nicer error
+        qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+    } else {
+        qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
+    }
+    _exit(1);
+}
+
 QT_BEGIN_NAMESPACE
 
 namespace QtWaylandClient {
 
+class EventThread : public QThread
+{
+    Q_OBJECT
+public:
+    enum OperatingMode {
+        EmitToDispatch, // Emit the signal, allow dispatching in a differnt thread.
+        SelfDispatch, // Dispatch the events inside this thread.
+    };
+
+    EventThread(struct wl_display * wl, struct wl_event_queue * ev_queue,
+                OperatingMode mode)
+        : m_fd(wl_display_get_fd(wl))
+        , m_pipefd{ -1, -1 }
+        , m_wldisplay(wl)
+        , m_wlevqueue(ev_queue)
+        , m_mode(mode)
+        , m_reading(true)
+        , m_quitting(false)
+    {
+        setObjectName(QStringLiteral("WaylandEventThread"));
+    }
+
+    void readAndDispatchEvents()
+    {
+        /*
+         * Dispatch pending events and flush the requests at least once. If the event thread
+         * is not reading, try to call _prepare_read() to allow the event thread to poll().
+         * If that fails, re-try dispatch & flush again until _prepare_read() is successful.
+         *
+         * This allow any call to readAndDispatchEvents() to start event thread's polling,
+         * not only the one issued from event thread's waitForReading(), which means functions
+         * called from dispatch_pending() can safely spin an event loop.
+         */
+        for (;;) {
+            if (dispatchQueuePending() < 0) {
+                checkWaylandError(m_wldisplay);
+                return;
+            }
+
+            wl_display_flush(m_wldisplay);
+
+            // We have to check if event thread is reading every time we dispatch
+            // something, as that may recursively call this function.
+            if (m_reading.loadAcquire())
+                break;
+
+            if (prepareReadQueue() == 0) {
+                QMutexLocker l(&m_mutex);
+                m_reading.storeRelease(true);
+                m_cond.wakeOne();
+                break;
+            }
+        }
+    }
+
+    void stop()
+    {
+        // We have to both write to the pipe and set the flag, as the thread may be
+        // either in the poll() or waiting for _prepare_read().
+        if (m_pipefd[1] != -1 && write(m_pipefd[1], "\0", 1) == -1)
+            qWarning("Failed to write to the pipe: %s.", strerror(errno));
+
+        {
+            QMutexLocker l(&m_mutex);
+            m_quitting = true;
+            m_cond.wakeOne();
+        }
+
+        wait();
+    }
+
+Q_SIGNALS:
+    void needReadAndDispatch();
+
+protected:
+    void run() override
+    {
+        // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets
+        // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore.
+        struct Pipe
+        {
+            Pipe(int *fds)
+                : fds(fds)
+            {
+                if (qt_safe_pipe(fds) != 0)
+                    qWarning("Pipe creation failed. Quitting may hang.");
+            }
+            ~Pipe()
+            {
+                if (fds[0] != -1) {
+                    close(fds[0]);
+                    close(fds[1]);
+                }
+            }
+
+            int *fds;
+        } pipe(m_pipefd);
+
+        // Make the main thread call wl_prepare_read(), dispatch the pending messages and flush the
+        // outbound ones. Wait until it's done before proceeding, unless we're told to quit.
+        while (waitForReading()) {
+            pollfd fds[2] = { { m_fd, POLLIN, 0 }, { m_pipefd[0], POLLIN, 0 } };
+            poll(fds, 2, -1);
+
+            if (fds[1].revents & POLLIN) {
+                // we don't really care to read the byte that was written here since we're closing down
+                wl_display_cancel_read(m_wldisplay);
+                break;
+            }
+
+            if (fds[0].revents & POLLIN)
+                wl_display_read_events(m_wldisplay);
+                // The polll was succesfull and the event thread did the wl_display_read_events(). On the next iteration of the loop
+                // the event sent to the main thread will cause it to dispatch the messages just read, unless the loop exits in which
+                // case we don't care anymore about them.
+            else
+                wl_display_cancel_read(m_wldisplay);
+        }
+    }
+
+private:
+    bool waitForReading()
+    {
+        Q_ASSERT(QThread::currentThread() == this);
+
+        m_reading.storeRelease(false);
+
+        if (m_mode == SelfDispatch) {
+            readAndDispatchEvents();
+        } else {
+            Q_EMIT needReadAndDispatch();
+
+            QMutexLocker lock(&m_mutex);
+            // m_reading might be set from our emit or some other invocation of
+            // readAndDispatchEvents().
+            while (!m_reading.loadRelaxed() && !m_quitting)
+                m_cond.wait(&m_mutex);
+        }
+
+        return !m_quitting;
+    }
+
+    int dispatchQueuePending()
+    {
+        if (m_wlevqueue)
+            return wl_display_dispatch_queue_pending(m_wldisplay, m_wlevqueue);
+        else
+            return wl_display_dispatch_pending(m_wldisplay);
+    }
+
+    int prepareReadQueue()
+    {
+        if (m_wlevqueue)
+            return wl_display_prepare_read_queue(m_wldisplay, m_wlevqueue);
+        else
+            return wl_display_prepare_read(m_wldisplay);
+    }
+
+    int m_fd;
+    int m_pipefd[2];
+    wl_display *m_wldisplay;
+    wl_event_queue *m_wlevqueue;
+    OperatingMode m_mode;
+
+    /* Concurrency note when operating in EmitToDispatch mode:
+     * m_reading is set to false inside event thread's waitForReading(), and is
+     * set to true inside main thread's readAndDispatchEvents().
+     * The lock is not taken when setting m_reading to false, as the main thread
+     * is not actively waiting for it to turn false. However, the lock is taken
+     * inside readAndDispatchEvents() before setting m_reading to true,
+     * as the event thread is actively waiting for it under the wait condition.
+     */
+
+    QAtomicInteger<bool> m_reading;
+    bool m_quitting;
+    QMutex m_mutex;
+    QWaitCondition m_cond;
+};
+
 Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging
 
 struct wl_surface *QWaylandDisplay::createSurface(void *handle)
@@ -158,17 +351,16 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
     if (!mXkbContext)
         qCWarning(lcQpaWayland, "failed to create xkb context");
 #endif
-
-    forceRoundTrip();
-
-    if (!mWaitingScreens.isEmpty()) {
-        // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
-        forceRoundTrip();
-    }
 }
 
 QWaylandDisplay::~QWaylandDisplay(void)
 {
+    if (m_eventThread)
+        m_eventThread->stop();
+
+    if (m_frameEventQueueThread)
+        m_frameEventQueueThread->stop();
+
     if (mSyncCallback)
         wl_callback_destroy(mSyncCallback);
 
@@ -187,6 +379,21 @@ QWaylandDisplay::~QWaylandDisplay(void)
 #endif
     if (mDisplay)
         wl_display_disconnect(mDisplay);
+
+    if (m_frameEventQueue)
+        wl_event_queue_destroy(m_frameEventQueue);
+}
+
+// Steps which is called just after constructor. This separates registry_global() out of the constructor
+// so that factory functions in integration can be overridden.
+void QWaylandDisplay::initialize()
+{
+    forceRoundTrip();
+
+    if (!mWaitingScreens.isEmpty()) {
+        // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
+        forceRoundTrip();
+    }
 }
 
 void QWaylandDisplay::ensureScreen()
@@ -203,98 +410,37 @@ void QWaylandDisplay::ensureScreen()
 
 void QWaylandDisplay::checkError() const
 {
-    int ecode = wl_display_get_error(mDisplay);
-    if ((ecode == EPIPE || ecode == ECONNRESET)) {
-        // special case this to provide a nicer error
-        qWarning("The Wayland connection broke. Did the Wayland compositor die?");
-    } else {
-        qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
-    }
-    _exit(1);
+    checkWaylandError(mDisplay);
 }
 
+// Called in main thread, either from queued signal or directly.
 void QWaylandDisplay::flushRequests()
 {
-    if (wl_display_prepare_read(mDisplay) == 0) {
-        wl_display_read_events(mDisplay);
-    }
-
-    if (wl_display_dispatch_pending(mDisplay) < 0)
-        checkError();
-
-    {
-        QReadLocker locker(&m_frameQueueLock);
-        for (const FrameQueue &q : mExternalQueues) {
-            QMutexLocker locker(q.mutex);
-            while (wl_display_prepare_read_queue(mDisplay, q.queue) != 0)
-                wl_display_dispatch_queue_pending(mDisplay, q.queue);
-            wl_display_read_events(mDisplay);
-            wl_display_dispatch_queue_pending(mDisplay, q.queue);
-        }
-    }
-
-    wl_display_flush(mDisplay);
-}
-
-void QWaylandDisplay::blockingReadEvents()
-{
-    if (wl_display_dispatch(mDisplay) < 0)
-        checkError();
-}
-
-void QWaylandDisplay::destroyFrameQueue(const QWaylandDisplay::FrameQueue &q)
-{
-    QWriteLocker locker(&m_frameQueueLock);
-    auto it = std::find_if(mExternalQueues.begin(),
-                           mExternalQueues.end(),
-                           [&q] (const QWaylandDisplay::FrameQueue &other){ return other.queue == q.queue; });
-    Q_ASSERT(it != mExternalQueues.end());
-    mExternalQueues.erase(it);
-    if (q.queue != nullptr)
-        wl_event_queue_destroy(q.queue);
-    delete q.mutex;
+    m_eventThread->readAndDispatchEvents();
 }
 
-QWaylandDisplay::FrameQueue QWaylandDisplay::createFrameQueue()
+// We have to wait until we have an eventDispatcher before creating the eventThread,
+// otherwise forceRoundTrip() may block inside _events_read() because eventThread is
+// polling.
+void QWaylandDisplay::initEventThread()
 {
-    QWriteLocker locker(&m_frameQueueLock);
-    FrameQueue q{createEventQueue()};
-    mExternalQueues.append(q);
-    return q;
-}
+    m_eventThread.reset(
+            new EventThread(mDisplay, /* default queue */ nullptr, EventThread::EmitToDispatch));
+    connect(m_eventThread.get(), &EventThread::needReadAndDispatch, this,
+            &QWaylandDisplay::flushRequests, Qt::QueuedConnection);
+    m_eventThread->start();
 
-wl_event_queue *QWaylandDisplay::createEventQueue()
-{
-    return wl_display_create_queue(mDisplay);
+    // wl_display_disconnect() free this.
+    m_frameEventQueue = wl_display_create_queue(mDisplay);
+    m_frameEventQueueThread.reset(
+            new EventThread(mDisplay, m_frameEventQueue, EventThread::SelfDispatch));
+    m_frameEventQueueThread->start();
 }
 
-void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bool ()> condition, int timeout)
+void QWaylandDisplay::blockingReadEvents()
 {
-    if (!condition())
-        return;
-
-    QElapsedTimer timer;
-    timer.start();
-    struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN);
-    while (timeout == -1 || timer.elapsed() < timeout) {
-        while (wl_display_prepare_read_queue(mDisplay, queue) != 0)
-            wl_display_dispatch_queue_pending(mDisplay, queue);
-
-        wl_display_flush(mDisplay);
-
-        const int remaining = qMax(timeout - timer.elapsed(), 0ll);
-        const int pollTimeout = timeout == -1 ? -1 : remaining;
-        if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0)
-            wl_display_read_events(mDisplay);
-        else
-            wl_display_cancel_read(mDisplay);
-
-        if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
-            checkError();
-
-        if (!condition())
-            break;
-    }
+    if (wl_display_dispatch(mDisplay) < 0)
+        checkWaylandError(mDisplay);
 }
 
 QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
@@ -345,7 +491,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
     if (interface == QStringLiteral("wl_output")) {
         mWaitingScreens << new QWaylandScreen(this, version, id);
     } else if (interface == QStringLiteral("wl_compositor")) {
-        mCompositorVersion = qMin((int)version, 3);
+        mCompositorVersion = qMin((int)version, 4);
         mCompositor.init(registry, id, mCompositorVersion);
     } else if (interface == QStringLiteral("wl_shm")) {
         mShm.reset(new QWaylandShm(this, version, id));
@@ -354,7 +500,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
         mInputDevices.append(inputDevice);
 #if QT_CONFIG(wayland_datadevice)
     } else if (interface == QStringLiteral("wl_data_device_manager")) {
-        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
+        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id));
 #endif
     } else if (interface == QStringLiteral("qt_surface_extension")) {
         mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
@@ -369,6 +515,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
 #if QT_CONFIG(wayland_client_primary_selection)
     } else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
         mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
+        for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
+            inputDevice->setPrimarySelectionDevice(mPrimarySelectionManager->createDevice(inputDevice));
 #endif
     } else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
         mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
@@ -427,6 +575,13 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
                     inputDevice->setTextInput(nullptr);
                 mWaylandIntegration->reconfigureInputContext();
             }
+#if QT_CONFIG(wayland_client_primary_selection)
+            if (global.interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
+                mPrimarySelectionManager.reset();
+                for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices))
+                    inputDevice->setPrimarySelectionDevice(nullptr);
+            }
+#endif
             mGlobals.removeAt(i);
             break;
         }
@@ -452,9 +607,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
 
 void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
 {
-    std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
+    auto iter = std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
         return (l.listener == listener && l.data == data);
     });
+    mRegistryListeners.erase(iter, mRegistryListeners.end());
 }
 
 uint32_t QWaylandDisplay::currentTimeMillisec()
@@ -467,50 +623,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
     return 0;
 }
 
-static void
-sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
-{
-    Q_UNUSED(serial)
-    bool *done = static_cast<bool *>(data);
-
-    *done = true;
-
-    // If the wl_callback done event is received after the condition check in the while loop in
-    // forceRoundTrip(), but before the call to processEvents, the call to processEvents may block
-    // forever if no more events are posted (eventhough the callback is handled in response to the
-    // aboutToBlock signal). Hence, we wake up the event dispatcher so forceRoundTrip may return.
-    // (QTBUG-64696)
-    if (auto *dispatcher = QThread::currentThread()->eventDispatcher())
-        dispatcher->wakeUp();
-
-    wl_callback_destroy(callback);
-}
-
-static const struct wl_callback_listener sync_listener = {
-    sync_callback
-};
-
 void QWaylandDisplay::forceRoundTrip()
 {
-    // wl_display_roundtrip() works on the main queue only,
-    // but we use a separate one, so basically reimplement it here
-    int ret = 0;
-    bool done = false;
-    wl_callback *callback = wl_display_sync(mDisplay);
-    wl_callback_add_listener(callback, &sync_listener, &done);
-    flushRequests();
-    if (QThread::currentThread()->eventDispatcher()) {
-        while (!done && ret >= 0) {
-            QThread::currentThread()->eventDispatcher()->processEvents(QEventLoop::WaitForMoreEvents);
-            ret = wl_display_dispatch_pending(mDisplay);
-        }
-    } else {
-        while (!done && ret >= 0)
-            ret = wl_display_dispatch(mDisplay);
-    }
-
-    if (ret == -1 && !done)
-        wl_callback_destroy(callback);
+     wl_display_roundtrip(mDisplay);
 }
 
 bool QWaylandDisplay::supportsWindowDecoration() const
@@ -574,14 +689,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
     if (mLastKeyboardFocus == keyboardFocus)
         return;
 
-    if (mWaylandIntegration->mShellIntegration) {
-        mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus);
-    } else {
-        if (keyboardFocus)
-            handleWindowActivated(keyboardFocus);
-        if (mLastKeyboardFocus)
-            handleWindowDeactivated(mLastKeyboardFocus);
-    }
+    if (keyboardFocus)
+        handleWindowActivated(keyboardFocus);
+    if (mLastKeyboardFocus)
+        handleWindowDeactivated(mLastKeyboardFocus);
 
     mLastKeyboardFocus = keyboardFocus;
 }
@@ -600,6 +711,19 @@ void QWaylandDisplay::handleWaylandSync()
     QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
     if (activeWindow != QGuiApplication::focusWindow())
         QWindowSystemInterface::handleWindowActivated(activeWindow);
+
+    if (!activeWindow) {
+        if (lastInputDevice()) {
+#if QT_CONFIG(clipboard)
+            if (auto *dataDevice = lastInputDevice()->dataDevice())
+                dataDevice->invalidateSelectionOffer();
+#endif
+#if QT_CONFIG(wayland_client_primary_selection)
+            if (auto *device = lastInputDevice()->primarySelectionDevice())
+                device->invalidateSelectionOffer();
+#endif
+        }
+    }
 }
 
 const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
@@ -626,6 +750,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
     return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
 }
 
+bool QWaylandDisplay::isKeyboardAvailable() const
+{
+    return std::any_of(
+            mInputDevices.constBegin(), mInputDevices.constEnd(),
+            [this](const QWaylandInputDevice *device) { return device->keyboard() != nullptr; });
+}
+
 #if QT_CONFIG(cursor)
 
 QWaylandCursor *QWaylandDisplay::waylandCursor()
@@ -652,4 +783,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
 
 } // namespace QtWaylandClient
 
+#include "qwaylanddisplay.moc"
+
 QT_END_NAMESPACE
diff --git a/qtwayland/src/client/qwaylanddisplay_p.h b/qtwayland/src/client/qwaylanddisplay_p.h
index 3b092bc8..42bc661d 100644
--- a/qtwayland/src/client/qwaylanddisplay_p.h
+++ b/qtwayland/src/client/qwaylanddisplay_p.h
@@ -109,6 +109,7 @@ class QWaylandSurface;
 class QWaylandShellIntegration;
 class QWaylandCursor;
 class QWaylandCursorTheme;
+class EventThread;
 
 typedef void (*RegistryListener)(void *data,
                                  struct wl_registry *registry,
@@ -120,15 +121,11 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland
     Q_OBJECT
 
 public:
-    struct FrameQueue {
-        FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {}
-        wl_event_queue *queue;
-        QMutex *mutex;
-    };
-
     QWaylandDisplay(QWaylandIntegration *waylandIntegration);
     ~QWaylandDisplay(void) override;
 
+    void initialize();
+
 #if QT_CONFIG(xkbcommon)
     struct xkb_context *xkbContext() const { return mXkbContext.get(); }
 #endif
@@ -210,11 +207,11 @@ public:
     void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
     void handleWindowDestroyed(QWaylandWindow *window);
 
-    wl_event_queue *createEventQueue();
-    FrameQueue createFrameQueue();
-    void destroyFrameQueue(const FrameQueue &q);
-    void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
+    wl_event_queue *frameEventQueue() { return m_frameEventQueue; };
+
+    bool isKeyboardAvailable() const;
 
+    void initEventThread();
 public slots:
     void blockingReadEvents();
     void flushRequests();
@@ -237,6 +234,9 @@ private:
     };
 
     struct wl_display *mDisplay = nullptr;
+    QScopedPointer<EventThread> m_eventThread;
+    wl_event_queue *m_frameEventQueue = nullptr;
+    QScopedPointer<EventThread> m_frameEventQueueThread;
     QtWayland::wl_compositor mCompositor;
     QScopedPointer<QWaylandShm> mShm;
     QList<QWaylandScreen *> mWaitingScreens;
@@ -273,11 +273,9 @@ private:
     QWaylandInputDevice *mLastInputDevice = nullptr;
     QPointer<QWaylandWindow> mLastInputWindow;
     QPointer<QWaylandWindow> mLastKeyboardFocus;
-    QVector<QWaylandWindow *> mActiveWindows;
-    QVector<FrameQueue> mExternalQueues;
+    QList<QWaylandWindow *> mActiveWindows;
     struct wl_callback *mSyncCallback = nullptr;
     static const wl_callback_listener syncCallbackListener;
-    QReadWriteLock m_frameQueueLock;
 
     bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
 
diff --git a/qtwayland/src/client/qwaylanddnd.cpp b/qtwayland/src/client/qwaylanddnd.cpp
index 6535aa16..7c53f5fa 100644
--- a/qtwayland/src/client/qwaylanddnd.cpp
+++ b/qtwayland/src/client/qwaylanddnd.cpp
@@ -66,7 +66,7 @@ void QWaylandDrag::startDrag()
 {
     QBasicDrag::startDrag();
     QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
-    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
+    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), drag()->supportedActions(), icon)) {
         icon->addAttachOffset(-drag()->hotSpot());
     } else {
         // Cancelling immediately does not work, since the event loop for QDrag::exec is started
@@ -80,6 +80,9 @@ void QWaylandDrag::cancel()
     QBasicDrag::cancel();
 
     m_display->currentInputDevice()->dataDevice()->cancelDrag();
+
+    if (drag())
+        drag()->deleteLater();
 }
 
 void QWaylandDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
@@ -103,33 +106,41 @@ void QWaylandDrag::endDrag()
     m_display->currentInputDevice()->handleEndDrag();
 }
 
-void QWaylandDrag::updateTarget(const QString &mimeType)
+void QWaylandDrag::setResponse(bool accepted)
 {
-    setCanDrop(!mimeType.isEmpty());
-
-    if (canDrop()) {
-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
-    } else {
-        updateCursor(Qt::IgnoreAction);
-    }
+    // This method is used for old DataDevices where the drag action is not communicated
+    Qt::DropAction action = defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers());
+    setResponse(QPlatformDropQtResponse(accepted, action));
 }
 
-void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
+void QWaylandDrag::setResponse(const QPlatformDropQtResponse &response)
 {
     setCanDrop(response.isAccepted());
 
     if (canDrop()) {
-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
+        updateCursor(response.acceptedAction());
     } else {
         updateCursor(Qt::IgnoreAction);
     }
 }
 
-void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
+void QWaylandDrag::setDropResponse(const QPlatformDropQtResponse &response)
 {
     setExecutedDropAction(response.acceptedAction());
+}
+
+void QWaylandDrag::finishDrag()
+{
     QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
     eventFilter(shapedPixmapWindow(), &event);
+
+    if (drag())
+        drag()->deleteLater();
+}
+
+bool QWaylandDrag::ownsDragObject() const
+{
+    return true;
 }
 
 }
diff --git a/qtwayland/src/client/qwaylanddnd_p.h b/qtwayland/src/client/qwaylanddnd_p.h
index 474fe2ab..46f629ac 100644
--- a/qtwayland/src/client/qwaylanddnd_p.h
+++ b/qtwayland/src/client/qwaylanddnd_p.h
@@ -71,9 +71,10 @@ public:
     QWaylandDrag(QWaylandDisplay *display);
     ~QWaylandDrag() override;
 
-    void updateTarget(const QString &mimeType);
-    void setResponse(const QPlatformDragQtResponse &response);
-    void finishDrag(const QPlatformDropQtResponse &response);
+    void setResponse(bool accepted);
+    void setResponse(const QPlatformDropQtResponse &response);
+    void setDropResponse(const QPlatformDropQtResponse &response);
+    void finishDrag();
 
 protected:
     void startDrag() override;
@@ -82,6 +83,7 @@ protected:
     void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
     void endDrag() override;
 
+    bool ownsDragObject() const override;
 
 private:
     QWaylandDisplay *m_display = nullptr;
diff --git a/qtwayland/src/client/qwaylandinputdevice.cpp b/qtwayland/src/client/qwaylandinputdevice.cpp
index 613fe862..4b90de84 100644
--- a/qtwayland/src/client/qwaylandinputdevice.cpp
+++ b/qtwayland/src/client/qwaylandinputdevice.cpp
@@ -685,6 +685,11 @@ public:
 
 void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surface *surface)
 {
+    invalidateFocus();
+    mButtons = Qt::NoButton;
+
+    mParent->mTime = time;
+
     // The event may arrive after destroying the window, indicated by
     // a null surface.
     if (!surface)
@@ -696,11 +701,6 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
 
     if (!QWaylandWindow::mouseGrab())
         setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos));
-
-    invalidateFocus();
-    mButtons = Qt::NoButton;
-
-    mParent->mTime = time;
 }
 
 class MotionEvent : public QWaylandPointerEvent
@@ -1300,14 +1300,6 @@ void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
 void QWaylandInputDevice::Keyboard::handleFocusLost()
 {
     mFocus = nullptr;
-#if QT_CONFIG(clipboard)
-    if (auto *dataDevice = mParent->dataDevice())
-        dataDevice->invalidateSelectionOffer();
-#endif
-#if QT_CONFIG(wayland_client_primary_selection)
-    if (auto *device = mParent->primarySelectionDevice())
-        device->invalidateSelectionOffer();
-#endif
     mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
     mRepeatTimer.stop();
 }
@@ -1396,6 +1388,7 @@ void QWaylandInputDevice::Touch::touch_cancel()
     if (touchExt)
         touchExt->touchCanceled();
 
+    mFocus = nullptr;
     QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice);
 }
 
diff --git a/qtwayland/src/client/qwaylandintegration.cpp b/qtwayland/src/client/qwaylandintegration.cpp
index c53ccb78..54861600 100644
--- a/qtwayland/src/client/qwaylandintegration.cpp
+++ b/qtwayland/src/client/qwaylandintegration.cpp
@@ -125,6 +125,9 @@ QWaylandIntegration::QWaylandIntegration()
 #endif
 
     reconfigureInputContext();
+
+    QWaylandWindow::fixedToplevelPositions =
+            !qEnvironmentVariableIsSet("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
 }
 
 QWaylandIntegration::~QWaylandIntegration()
@@ -192,14 +195,18 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
 
 void QWaylandIntegration::initialize()
 {
+    mDisplay->initEventThread();
+
+    // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip()
+    mDisplay->initialize();
+
+    // But the aboutToBlock() and awake() should be connected after initializePlatform().
+    // Otherwise the connected flushRequests() may consumes up all events before processEvents starts to wait,
+    // so that processEvents(QEventLoop::WaitForMoreEvents) may be blocked in the forceRoundTrip().
     QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
     QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests()));
     QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests()));
 
-    int fd = wl_display_get_fd(mDisplay->wl_display());
-    QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data());
-    QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests()));
-
     // Qt does not support running with no screens
     mDisplay->ensureScreen();
 }
@@ -262,6 +269,14 @@ QWaylandDisplay *QWaylandIntegration::display() const
     return mDisplay.data();
 }
 
+Qt::KeyboardModifiers QWaylandIntegration::queryKeyboardModifiers() const
+{
+    if (auto *seat = mDisplay->currentInputDevice()) {
+        return seat->modifiers();
+    }
+    return Qt::NoModifier;
+}
+
 QList<int> QWaylandIntegration::possibleKeys(const QKeyEvent *event) const
 {
     if (auto *seat = mDisplay->currentInputDevice())
@@ -479,7 +494,7 @@ void QWaylandIntegration::reconfigureInputContext()
     }
 #endif
 
-    qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className();
+    qCDebug(lcQpaWayland) << "using input method:" << (inputContext() ? inputContext()->metaObject()->className() : "<none>");
 }
 
 QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName)
diff --git a/qtwayland/src/client/qwaylandintegration_p.h b/qtwayland/src/client/qwaylandintegration_p.h
index ff70ae25..73b80658 100644
--- a/qtwayland/src/client/qwaylandintegration_p.h
+++ b/qtwayland/src/client/qwaylandintegration_p.h
@@ -107,6 +107,8 @@ public:
 
     QWaylandDisplay *display() const;
 
+    Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+
     QList<int> possibleKeys(const QKeyEvent *event) const override;
 
     QStringList themeNames() const override;
diff --git a/qtwayland/src/client/qwaylandprimaryselectionv1.cpp b/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
index 832f9678..ea508771 100644
--- a/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
+++ b/qtwayland/src/client/qwaylandprimaryselectionv1.cpp
@@ -54,11 +54,6 @@ QWaylandPrimarySelectionDeviceManagerV1::QWaylandPrimarySelectionDeviceManagerV1
     : zwp_primary_selection_device_manager_v1(display->wl_registry(), id, qMin(version, uint(1)))
     , m_display(display)
 {
-    // Create devices for all seats.
-    // This only works if we get the global before all devices
-    const auto seats = m_display->inputDevices();
-    for (auto *seat : seats)
-        seat->setPrimarySelectionDevice(createDevice(seat));
 }
 
 QWaylandPrimarySelectionDeviceV1 *QWaylandPrimarySelectionDeviceManagerV1::createDevice(QWaylandInputDevice *seat)
diff --git a/qtwayland/src/client/qwaylandscreen.cpp b/qtwayland/src/client/qwaylandscreen.cpp
index 6cb337de..5537dafd 100644
--- a/qtwayland/src/client/qwaylandscreen.cpp
+++ b/qtwayland/src/client/qwaylandscreen.cpp
@@ -60,7 +60,7 @@ QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandDisplay* display,
 }
 
 QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id)
-    : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2))
+    : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 3))
     , m_outputId(id)
     , mWaylandDisplay(waylandDisplay)
     , mOutputName(QStringLiteral("Screen%1").arg(id))
@@ -72,7 +72,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin
         qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor,"
                                 << "QScreen may not work correctly";
         mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc.
-        mOutputDone = true; // Fake the done event
+        mProcessedEvents |= OutputDoneEvent; // Fake the done event
         maybeInitialize();
     }
 }
@@ -81,16 +81,29 @@ QWaylandScreen::~QWaylandScreen()
 {
     if (zxdg_output_v1::isInitialized())
         zxdg_output_v1::destroy();
+    if (wl_output::isInitialized() && wl_output_get_version(wl_output::object()) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
+        wl_output::release();
+}
+
+uint QWaylandScreen::requiredEvents() const
+{
+    uint ret = OutputDoneEvent;
+
+    if (mWaylandDisplay->xdgOutputManager()) {
+        ret |= XdgOutputNameEvent;
+
+        if (mWaylandDisplay->xdgOutputManager()->version() < 3)
+            ret |= XdgOutputDoneEvent;
+    }
+    return ret;
 }
 
 void QWaylandScreen::maybeInitialize()
 {
     Q_ASSERT(!mInitialized);
 
-    if (!mOutputDone)
-        return;
-
-    if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone)
+    const uint requiredEvents = this->requiredEvents();
+    if ((mProcessedEvents & requiredEvents) != requiredEvents)
         return;
 
     mInitialized = true;
@@ -276,9 +289,8 @@ void QWaylandScreen::output_scale(int32_t factor)
 
 void QWaylandScreen::output_done()
 {
-    mOutputDone = true;
-    if (zxdg_output_v1::isInitialized() && mWaylandDisplay->xdgOutputManager()->version() >= 3)
-        mXdgOutputDone = true;
+    mProcessedEvents |= OutputDoneEvent;
+
     if (mInitialized) {
         updateOutputProperties();
         if (zxdg_output_v1::isInitialized())
@@ -339,7 +351,7 @@ void QWaylandScreen::zxdg_output_v1_done()
     if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3))
         qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor";
 
-    mXdgOutputDone = true;
+    mProcessedEvents |= XdgOutputDoneEvent;
     if (mInitialized)
         updateXdgOutputProperties();
     else
@@ -348,7 +360,11 @@ void QWaylandScreen::zxdg_output_v1_done()
 
 void QWaylandScreen::zxdg_output_v1_name(const QString &name)
 {
+    if (Q_UNLIKELY(mInitialized))
+        qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor";
+
     mOutputName = name;
+    mProcessedEvents |= XdgOutputNameEvent;
 }
 
 void QWaylandScreen::updateXdgOutputProperties()
diff --git a/qtwayland/src/client/qwaylandscreen_p.h b/qtwayland/src/client/qwaylandscreen_p.h
index df1c94f2..050cfdc0 100644
--- a/qtwayland/src/client/qwaylandscreen_p.h
+++ b/qtwayland/src/client/qwaylandscreen_p.h
@@ -116,6 +116,13 @@ public:
     static QWaylandScreen *fromWlOutput(::wl_output *output);
 
 private:
+    enum Event : uint {
+        XdgOutputDoneEvent = 0x1,
+        OutputDoneEvent = 0x2,
+        XdgOutputNameEvent = 0x4,
+    };
+    uint requiredEvents() const;
+
     void output_mode(uint32_t flags, int width, int height, int refresh) override;
     void output_geometry(int32_t x, int32_t y,
                          int32_t width, int32_t height,
@@ -148,8 +155,7 @@ private:
     QSize mPhysicalSize;
     QString mOutputName;
     Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
-    bool mOutputDone = false;
-    bool mXdgOutputDone = false;
+    uint mProcessedEvents = 0;
     bool mInitialized = false;
 
 #if QT_CONFIG(cursor)
diff --git a/qtwayland/src/client/qwaylandshmbackingstore.cpp b/qtwayland/src/client/qwaylandshmbackingstore.cpp
index dc7ff670..41cffdf7 100644
--- a/qtwayland/src/client/qwaylandshmbackingstore.cpp
+++ b/qtwayland/src/client/qwaylandshmbackingstore.cpp
@@ -52,6 +52,7 @@
 
 #include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
 
+#include <fcntl.h>
 #include <unistd.h>
 #include <sys/mman.h>
 
@@ -61,6 +62,9 @@
 #  ifndef MFD_CLOEXEC
 #    define MFD_CLOEXEC     0x0001U
 #  endif
+#  ifndef MFD_ALLOW_SEALING
+#    define MFD_ALLOW_SEALING 0x0002U
+#  endif
 #endif
 
 QT_BEGIN_NAMESPACE
@@ -74,8 +78,10 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
     int alloc = stride * size.height();
     int fd = -1;
 
-#ifdef SYS_memfd_create
-    fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC);
+#if defined(SYS_memfd_create) && defined(F_SEAL_SEAL)
+    fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+    if (fd >= 0)
+        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
 #endif
 
     QScopedPointer<QFile> filePointer;
diff --git a/qtwayland/src/client/qwaylandwindow.cpp b/qtwayland/src/client/qwaylandwindow.cpp
index cb82857a..fb2c59dc 100644
--- a/qtwayland/src/client/qwaylandwindow.cpp
+++ b/qtwayland/src/client/qwaylandwindow.cpp
@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
 QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
     : QPlatformWindow(window)
     , mDisplay(display)
-    , mFrameQueue(mDisplay->createFrameQueue())
     , mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
 {
     {
@@ -95,9 +94,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
 
 QWaylandWindow::~QWaylandWindow()
 {
-    mDisplay->destroyFrameQueue(mFrameQueue);
-    mDisplay->handleWindowDestroyed(this);
-
     delete mWindowDecoration;
 
     if (mSurface)
@@ -243,6 +239,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
 
 void QWaylandWindow::reset()
 {
+    closeChildPopups();
     delete mShellSurface;
     mShellSurface = nullptr;
     delete mSubSurfaceWindow;
@@ -255,17 +252,22 @@ void QWaylandWindow::reset()
         mSurface.reset();
     }
 
-    if (mFrameCallback) {
-        wl_callback_destroy(mFrameCallback);
-        mFrameCallback = nullptr;
-    }
+    {
+        QMutexLocker lock(&mFrameSyncMutex);
+        if (mFrameCallback) {
+            wl_callback_destroy(mFrameCallback);
+            mFrameCallback = nullptr;
+        }
 
-    mFrameCallbackElapsedTimer.invalidate();
-    mWaitingForFrameCallback = false;
+        mFrameCallbackElapsedTimer.invalidate();
+        mWaitingForFrameCallback = false;
+    }
     mFrameCallbackTimedOut = false;
 
     mMask = QRegion();
     mQueuedBuffer = nullptr;
+
+    mDisplay->handleWindowDestroyed(this);
 }
 
 QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
@@ -351,19 +353,25 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
     }
 }
 
-void QWaylandWindow::setGeometry(const QRect &rect)
+void QWaylandWindow::setGeometry(const QRect &r)
 {
+    auto rect = r;
+    if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+        && window()->type() != Qt::ToolTip) {
+        rect.moveTo(screen()->geometry().topLeft());
+    }
     setGeometry_helper(rect);
 
     if (window()->isVisible() && rect.isValid()) {
         if (mWindowDecoration)
             mWindowDecoration->update();
 
-        if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize)
+        if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize) {
+            QMutexLocker lock(&mResizeLock);
             mResizeDirty = true;
-        else
+        } else {
             QWindowSystemInterface::handleGeometryChange(window(), geometry());
-
+        }
         mSentInitialResize = true;
     }
     QRect exposeGeometry(QPoint(), geometry().size());
@@ -374,7 +382,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
         mShellSurface->setWindowGeometry(windowContentGeometry());
 
     if (isOpaque() && mMask.isEmpty())
-        setOpaqueArea(rect);
+        setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
 }
 
 void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
@@ -399,21 +407,6 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
     mLastExposeGeometry = rect;
 }
 
-
-static QVector<QPointer<QWaylandWindow>> activePopups;
-
-void QWaylandWindow::closePopups(QWaylandWindow *parent)
-{
-    while (!activePopups.isEmpty()) {
-        auto popup = activePopups.takeLast();
-        if (popup.isNull())
-            continue;
-        if (popup.data() == parent)
-            return;
-        popup->reset();
-    }
-}
-
 QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
 {
     QReadLocker lock(&mSurfaceLock);
@@ -433,10 +426,7 @@ void QWaylandWindow::setVisible(bool visible)
     lastVisible = visible;
 
     if (visible) {
-        if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
-            activePopups << this;
         initWindow();
-        mDisplay->flushRequests();
 
         setGeometry(windowGeometry());
         // Don't flush the events here, or else the newly visible window may start drawing, but since
@@ -444,7 +434,6 @@ void QWaylandWindow::setVisible(bool visible)
         // QWaylandShmBackingStore::beginPaint().
     } else {
         sendExposeEvent(QRect());
-        closePopups(this);
         reset();
     }
 }
@@ -556,12 +545,12 @@ void QWaylandWindow::sendRecursiveExposeEvent()
 
 void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
 {
-    Q_ASSERT(!buffer->committed());
     QReadLocker locker(&mSurfaceLock);
     if (mSurface == nullptr)
         return;
 
     if (buffer) {
+        Q_ASSERT(!buffer->committed());
         handleUpdate();
         buffer->setBusy();
 
@@ -583,7 +572,11 @@ void QWaylandWindow::damage(const QRect &rect)
     if (mSurface == nullptr)
         return;
 
-    mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+    const int s = scale();
+    if (mDisplay->compositorVersion() >= 4)
+        mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
+    else
+        mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
 }
 
 void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
@@ -619,8 +612,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
         return;
 
     attachOffset(buffer);
-    for (const QRect &rect: damage)
-        mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+    if (mDisplay->compositorVersion() >= 4) {
+        const int s = scale();
+        for (const QRect &rect: damage)
+            mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
+    } else {
+        for (const QRect &rect: damage)
+            mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
+    }
     Q_ASSERT(!buffer->committed());
     buffer->setCommitted();
     mSurface->commit();
@@ -635,42 +634,53 @@ void QWaylandWindow::commit()
 
 const wl_callback_listener QWaylandWindow::callbackListener = {
     [](void *data, wl_callback *callback, uint32_t time) {
-        Q_UNUSED(callback);
         Q_UNUSED(time);
         auto *window = static_cast<QWaylandWindow*>(data);
-        window->handleFrameCallback();
+        window->handleFrameCallback(callback);
     }
 };
 
-void QWaylandWindow::handleFrameCallback()
+void QWaylandWindow::handleFrameCallback(wl_callback* callback)
 {
+    QMutexLocker locker(&mFrameSyncMutex);
+    if (!mFrameCallback) {
+        // This means the callback is already unset by QWaylandWindow::reset.
+        // The wl_callback object will be destroyed there too.
+        return;
+    }
+    Q_ASSERT(callback == mFrameCallback);
+    wl_callback_destroy(callback);
+    mFrameCallback = nullptr;
+
     mWaitingForFrameCallback = false;
     mFrameCallbackElapsedTimer.invalidate();
 
     // The rest can wait until we can run it on the correct thread
-    if (!mWaitingForUpdateDelivery) {
-        auto doHandleExpose = [this]() {
-            bool wasExposed = isExposed();
-            mFrameCallbackTimedOut = false;
-            if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
-                sendExposeEvent(QRect(QPoint(), geometry().size()));
-            if (wasExposed && hasPendingUpdateRequest())
-                deliverUpdateRequest();
-
-            mWaitingForUpdateDelivery = false;
-        };
+    auto doHandleExpose = [this]() {
+        mWaitingForUpdateDelivery.storeRelease(false);
+        bool wasExposed = isExposed();
+        mFrameCallbackTimedOut = false;
+        if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
+            sendExposeEvent(QRect(QPoint(), geometry().size()));
+        if (wasExposed && hasPendingUpdateRequest())
+            deliverUpdateRequest();
+    };
 
+    if (mWaitingForUpdateDelivery.testAndSetAcquire(false, true)) {
         // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync()
         // in the single-threaded case.
-        mWaitingForUpdateDelivery = true;
         QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection);
     }
+
+    mFrameSyncWait.notify_all();
 }
 
 bool QWaylandWindow::waitForFrameSync(int timeout)
 {
-    QMutexLocker locker(mFrameQueue.mutex);
-    mDisplay->dispatchQueueWhile(mFrameQueue.queue, [&]() { return mWaitingForFrameCallback; }, timeout);
+    QMutexLocker locker(&mFrameSyncMutex);
+
+    QDeadlineTimer deadline(timeout);
+    while (mWaitingForFrameCallback && mFrameSyncWait.wait(&mFrameSyncMutex, deadline)) { }
 
     if (mWaitingForFrameCallback) {
         qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
@@ -868,6 +878,17 @@ bool QWaylandWindow::createDecoration()
             subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
         }
         sendExposeEvent(QRect(QPoint(), geometry().size()));
+
+        // This is a special case where the buffer is recreated, but since
+        // the content rect remains the same, the widgets remain the same
+        // size and are not redrawn, leaving the new buffer empty. As a simple
+        // work-around, we trigger a full extra update whenever the client-side
+        // window decorations are toggled while the window is showing.
+        // Note: createDecoration() is sometimes called from the render thread
+        // of Qt Quick. This is essentially wrong and could potentially cause problems,
+        // but until the underlying issue has been fixed, we have to use invokeMethod()
+        // here to avoid asserts.
+        QMetaObject::invokeMethod(window(), &QWindow::requestUpdate);
     }
 
     return mWindowDecoration;
@@ -1023,6 +1044,13 @@ void QWaylandWindow::handleScreensChanged()
 
     QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
     mLastReportedScreen = newScreen;
+    if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+        && window()->type() != Qt::ToolTip
+        && geometry().topLeft() != newScreen->geometry().topLeft()) {
+        auto geometry = this->geometry();
+        geometry.moveTo(newScreen->geometry().topLeft());
+        setGeometry(geometry);
+    }
 
     int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
     if (scale != mScale) {
@@ -1094,10 +1122,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
     return true;
 }
 
+Qt::WindowStates QWaylandWindow::windowStates() const
+{
+    return mLastReportedWindowStates;
+}
+
 void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
 {
     createDecoration();
-    QWindowSystemInterface::handleWindowStateChanged(window(), states, mLastReportedWindowStates);
+    Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
+    Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
+    QWindowSystemInterface::handleWindowStateChanged(window(), statesWithoutActive,
+                                                     lastStatesWithoutActive);
     mLastReportedWindowStates = states;
 }
 
@@ -1139,19 +1175,24 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
     if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
         return;
 
-    bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
-    if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
-        killTimer(mFrameCallbackCheckIntervalTimerId);
-        mFrameCallbackCheckIntervalTimerId = -1;
-    }
-    if (mFrameCallbackElapsedTimer.isValid() && callbackTimerExpired) {
-        mFrameCallbackElapsedTimer.invalidate();
+    {
+        QMutexLocker lock(&mFrameSyncMutex);
 
-        qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
-        mFrameCallbackTimedOut = true;
-        mWaitingForUpdate = false;
-        sendExposeEvent(QRect());
+        bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
+        if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
+            killTimer(mFrameCallbackCheckIntervalTimerId);
+            mFrameCallbackCheckIntervalTimerId = -1;
+        }
+        if (!mFrameCallbackElapsedTimer.isValid() || !callbackTimerExpired) {
+            return;
+        }
+        mFrameCallbackElapsedTimer.invalidate();
     }
+
+    qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
+    mFrameCallbackTimedOut = true;
+    mWaitingForUpdate = false;
+    sendExposeEvent(QRect());
 }
 
 void QWaylandWindow::requestUpdate()
@@ -1160,8 +1201,11 @@ void QWaylandWindow::requestUpdate()
     Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
 
     // If we have a frame callback all is good and will be taken care of there
-    if (mWaitingForFrameCallback)
-        return;
+    {
+        QMutexLocker locker(&mFrameSyncMutex);
+        if (mWaitingForFrameCallback)
+            return;
+    }
 
     // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
     // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
@@ -1174,7 +1218,12 @@ void QWaylandWindow::requestUpdate()
     // so use invokeMethod to delay the delivery a bit.
     QMetaObject::invokeMethod(this, [this] {
         // Things might have changed in the meantime
-        if (hasPendingUpdateRequest() && !mWaitingForFrameCallback)
+        {
+            QMutexLocker locker(&mFrameSyncMutex);
+            if (mWaitingForFrameCallback)
+                return;
+        }
+        if (hasPendingUpdateRequest())
             deliverUpdateRequest();
     }, Qt::QueuedConnection);
 }
@@ -1185,19 +1234,18 @@ void QWaylandWindow::requestUpdate()
 void QWaylandWindow::handleUpdate()
 {
     qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
+
     // TODO: Should sync subsurfaces avoid requesting frame callbacks?
     QReadLocker lock(&mSurfaceLock);
     if (!mSurface)
         return;
 
-    if (mFrameCallback) {
-        wl_callback_destroy(mFrameCallback);
-        mFrameCallback = nullptr;
-    }
+    QMutexLocker locker(&mFrameSyncMutex);
+    if (mWaitingForFrameCallback)
+        return;
 
-    QMutexLocker locker(mFrameQueue.mutex);
     struct ::wl_surface *wrappedSurface = reinterpret_cast<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
-    wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mFrameQueue.queue);
+    wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mDisplay->frameEventQueue());
     mFrameCallback = wl_surface_frame(wrappedSurface);
     wl_proxy_wrapper_destroy(wrappedSurface);
     wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
@@ -1207,6 +1255,8 @@ void QWaylandWindow::handleUpdate()
     // Start a timer for handling the case when the compositor stops sending frame callbacks.
     if (mFrameCallbackTimeout > 0) {
         QMetaObject::invokeMethod(this, [this] {
+            QMutexLocker locker(&mFrameSyncMutex);
+
             if (mWaitingForFrameCallback) {
                 if (mFrameCallbackCheckIntervalTimerId < 0)
                     mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
@@ -1267,6 +1317,20 @@ void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
     wl_region_destroy(region);
 }
 
+void QWaylandWindow::addChildPopup(QWaylandWindow *surface) {
+    mChildPopups.append(surface);
+}
+
+void QWaylandWindow::removeChildPopup(QWaylandWindow *surface) {
+    mChildPopups.removeAll(surface);
+}
+
+void QWaylandWindow::closeChildPopups() {
+    while (!mChildPopups.isEmpty()) {
+        auto popup = mChildPopups.takeLast();
+        popup->reset();
+    }
+}
 }
 
 QT_END_NAMESPACE
diff --git a/qtwayland/src/client/qwaylandwindow_p.h b/qtwayland/src/client/qwaylandwindow_p.h
index 01337cff..2f219d8c 100644
--- a/qtwayland/src/client/qwaylandwindow_p.h
+++ b/qtwayland/src/client/qwaylandwindow_p.h
@@ -98,6 +98,9 @@ public:
     QWaylandWindow(QWindow *window, QWaylandDisplay *display);
     ~QWaylandWindow() override;
 
+    // Keep Toplevels position on the top left corner of their screen
+    static inline bool fixedToplevelPositions = true;
+
     virtual WindowType windowType() const = 0;
     virtual void ensureSize();
     WId winId() const override;
@@ -148,6 +151,7 @@ public:
     void setWindowState(Qt::WindowStates states) override;
     void setWindowFlags(Qt::WindowFlags flags) override;
     void handleWindowStatesChanged(Qt::WindowStates states);
+    Qt::WindowStates windowStates() const;
 
     void raise() override;
     void lower() override;
@@ -206,6 +210,10 @@ public:
     void handleUpdate();
     void deliverUpdateRequest() override;
 
+    void addChildPopup(QWaylandWindow* child);
+    void removeChildPopup(QWaylandWindow* child);
+    void closeChildPopups();
+
 public slots:
     void applyConfigure();
 
@@ -215,7 +223,11 @@ signals:
 
 protected:
     QWaylandDisplay *mDisplay = nullptr;
+
+    // mSurface can be written by the main thread. Other threads should claim a read lock for access
+    mutable QReadWriteLock mSurfaceLock;
     QScopedPointer<QWaylandSurface> mSurface;
+
     QWaylandShellSurface *mShellSurface = nullptr;
     QWaylandSubSurface *mSubSurfaceWindow = nullptr;
     QVector<QWaylandSubSurface *> mChildren;
@@ -225,13 +237,14 @@ protected:
     Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
 
     WId mWindowId;
-    bool mWaitingForFrameCallback = false;
     bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
-    bool mWaitingForUpdateDelivery = false;
     int mFrameCallbackCheckIntervalTimerId = -1;
-    QElapsedTimer mFrameCallbackElapsedTimer;
-    struct ::wl_callback *mFrameCallback = nullptr;
-    QWaylandDisplay::FrameQueue mFrameQueue;
+    QAtomicInt mWaitingForUpdateDelivery = false;
+
+    bool mWaitingForFrameCallback = false; // Protected by mFrameSyncMutex
+    QElapsedTimer mFrameCallbackElapsedTimer; // Protected by mFrameSyncMutex
+    struct ::wl_callback *mFrameCallback = nullptr; // Protected by mFrameSyncMutex
+    QMutex mFrameSyncMutex;
     QWaitCondition mFrameSyncWait;
 
     // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
@@ -261,6 +274,8 @@ protected:
     QWaylandBuffer *mQueuedBuffer = nullptr;
     QRegion mQueuedBufferDamage;
 
+    QList<QPointer<QWaylandWindow>> mChildPopups;
+
 private:
     void setGeometry_helper(const QRect &rect);
     void initWindow();
@@ -283,12 +298,10 @@ private:
     QRect mLastExposeGeometry;
 
     static const wl_callback_listener callbackListener;
-    void handleFrameCallback();
+    void handleFrameCallback(struct ::wl_callback* callback);
 
     static QWaylandWindow *mMouseGrab;
 
-    mutable QReadWriteLock mSurfaceLock;
-
     friend class QWaylandSubSurface;
 };
 
diff --git a/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h b/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
index ccad0048..4cc9b3b8 100644
--- a/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
+++ b/qtwayland/src/client/shellintegration/qwaylandshellintegration_p.h
@@ -73,11 +73,10 @@ public:
         return true;
     }
     virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0;
+    // kept for binary compat with layer-shell-qt
     virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
-        if (newFocus)
-            m_display->handleWindowActivated(newFocus);
-        if (oldFocus)
-            m_display->handleWindowDeactivated(oldFocus);
+        Q_UNUSED(newFocus);
+        Q_UNUSED(oldFocus);
     }
     virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) {
         Q_UNUSED(resource);
diff --git a/qtwayland/src/compositor/configure.json b/qtwayland/src/compositor/configure.json
index bcfd5215..da95d07b 100644
--- a/qtwayland/src/compositor/configure.json
+++ b/qtwayland/src/compositor/configure.json
@@ -7,6 +7,31 @@
     "testDir": "../../config.tests",
 
     "libraries": {
+        "wayland-client": {
+            "label": "Wayland client library",
+            "headers": "wayland-version.h",
+            "test": {
+                "main": [
+                    "#if WAYLAND_VERSION_MAJOR < 1",
+                    "# error Wayland 1.8.0 or higher required",
+                    "#endif",
+                    "#if WAYLAND_VERSION_MAJOR == 1",
+                    "# if WAYLAND_VERSION_MINOR < 8",
+                    "#  error Wayland 1.8.0 or higher required",
+                    "# endif",
+                    "# if WAYLAND_VERSION_MINOR == 8",
+                    "#  if WAYLAND_VERSION_MICRO < 0",
+                    "#   error Wayland 1.8.0 or higher required",
+                    "#  endif",
+                    "# endif",
+                    "#endif"
+                 ]
+            },
+            "sources": [
+                { "type": "pkgConfig", "args": "wayland-client" },
+                "-lwayland-client"
+            ]
+        },
         "wayland-server": {
             "label": "wayland-server",
             "headers": "wayland-version.h",
@@ -151,8 +176,7 @@
                     "#endif"
                 ]
             },
-            "libs": "-ldrm",
-            "use": "egl"
+            "use": "drm egl"
         },
         "dmabuf-client-buffer": {
             "label": "Linux Client dma-buf Buffer Sharing",
@@ -176,8 +200,7 @@
                     "return 0;"
                 ]
             },
-            "libs": "-ldrm",
-            "use": "egl"
+            "use": "drm egl"
         },
         "vulkan-server-buffer": {
             "label": "Vulkan Buffer Sharing",
@@ -195,7 +218,8 @@
                     "exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
                     "return 0;"
                 ]
-            }
+            },
+            "use": "wayland-client"
         }
     },
 
diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
index 7889f575..64140672 100644
--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
+++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
@@ -40,6 +40,7 @@
 #include "qwaylandeglwindow.h"
 
 #include <QtWaylandClient/private/qwaylandscreen_p.h>
+#include <QtWaylandClient/private/qwaylandsurface_p.h>
 #include "qwaylandglcontext.h"
 
 #include <QtEglSupport/private/qeglconvenience_p.h>
@@ -124,6 +125,7 @@ void QWaylandEglWindow::updateSurface(bool create)
         }
         mOffset = QPoint();
     } else {
+        QReadLocker locker(&mSurfaceLock);
         if (m_waylandEglWindow) {
             int current_width, current_height;
             static bool disableResizeCheck = qgetenv("QT_WAYLAND_DISABLE_RESIZECHECK").toInt();
@@ -131,14 +133,16 @@ void QWaylandEglWindow::updateSurface(bool create)
             if (!disableResizeCheck) {
                 wl_egl_window_get_attached_size(m_waylandEglWindow, &current_width, &current_height);
             }
-            if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height())) {
+            if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height()) || m_requestedSize != sizeWithMargins) {
                 wl_egl_window_resize(m_waylandEglWindow, sizeWithMargins.width(), sizeWithMargins.height(), mOffset.x(), mOffset.y());
+                m_requestedSize = sizeWithMargins;
                 mOffset = QPoint();
 
                 m_resize = true;
             }
-        } else if (create && wlSurface()) {
-            m_waylandEglWindow = wl_egl_window_create(wlSurface(), sizeWithMargins.width(), sizeWithMargins.height());
+        } else if (create && mSurface) {
+            m_waylandEglWindow = wl_egl_window_create(mSurface->object(), sizeWithMargins.width(), sizeWithMargins.height());
+            m_requestedSize = sizeWithMargins;
         }
 
         if (!m_eglSurface && m_waylandEglWindow && create) {
diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
index 5b1f4d56..0079dfef 100644
--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
+++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
@@ -88,6 +88,7 @@ private:
     mutable QOpenGLFramebufferObject *m_contentFBO = nullptr;
 
     QSurfaceFormat m_format;
+    QSize m_requestedSize;
 };
 
 }
diff --git a/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
index 56a710c3..c6a8b6c6 100644
--- a/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
+++ b/qtwayland/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
@@ -41,6 +41,8 @@
 #include <QtCore/QTextStream>
 #include <QtGui/QOpenGLTexture>
 
+#include <array>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
diff --git a/qtwayland/src/plugins/decorations/bradient/main.cpp b/qtwayland/src/plugins/decorations/bradient/main.cpp
index e75fda3c..fa885143 100644
--- a/qtwayland/src/plugins/decorations/bradient/main.cpp
+++ b/qtwayland/src/plugins/decorations/bradient/main.cpp
@@ -164,13 +164,10 @@ void QWaylandBradientDecoration::paint(QPaintDevice *device)
     // Window icon
     QIcon icon = waylandWindow()->windowIcon();
     if (!icon.isNull()) {
-        QPixmap pixmap = icon.pixmap(QSize(128, 128));
-        QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-
         QRectF iconRect(0, 0, 22, 22);
-        p.drawPixmap(iconRect.adjusted(margins().left() + BUTTON_SPACING, 4,
-                                       margins().left() + BUTTON_SPACING, 4),
-                     scaled, iconRect);
+        iconRect.adjust(margins().left() + BUTTON_SPACING, 4,
+                        margins().left() + BUTTON_SPACING, 4),
+        icon.paint(&p, iconRect.toRect());
     }
 
     // Window title
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
index 85d25e3c..60bdd491 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
@@ -47,18 +47,21 @@ QT_BEGIN_NAMESPACE
 
 namespace QtWaylandClient {
 
-QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window)
+QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window)
     : QWaylandShellSurface(window)
     , QtWayland::xdg_popup_v5(popup)
+    , m_parent(parent)
     , m_window(window)
 {
     if (window->display()->windowExtension())
         m_extendedWindow = new QWaylandExtendedSurface(window);
+    m_parent->addChildPopup(m_window);
 }
 
 QWaylandXdgPopupV5::~QWaylandXdgPopupV5()
 {
     xdg_popup_destroy(object());
+    m_parent->removeChildPopup(m_window);
     delete m_extendedWindow;
 }
 
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
index 7494f6a6..d85f130b 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
@@ -70,7 +70,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgPopupV5 : public QWaylandShellSurface
 {
     Q_OBJECT
 public:
-    QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window);
+    QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window);
     ~QWaylandXdgPopupV5() override;
 
 protected:
@@ -78,6 +78,7 @@ protected:
 
 private:
     QWaylandExtendedSurface *m_extendedWindow = nullptr;
+    QWaylandWindow *m_parent = nullptr;
     QWaylandWindow *m_window = nullptr;
 };
 
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
index 7e242c4a..def8452a 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
@@ -84,7 +84,7 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, Q
     int x = position.x() + parentWindow->frameMargins().left();
     int y = position.y() + parentWindow->frameMargins().top();
 
-    auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), window);
+    auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), parentWindow, window);
     m_popups.append(window);
     QObject::connect(popup, &QWaylandXdgPopupV5::destroyed, [this, window](){
         m_popups.removeOne(window);
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
index 4e25949f..cfc60939 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
@@ -85,13 +85,6 @@ QWaylandShellSurface *QWaylandXdgShellV5Integration::createShellSurface(QWayland
     return m_xdgShell->createXdgSurface(window);
 }
 
-void QWaylandXdgShellV5Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
-    if (newFocus && qobject_cast<QWaylandXdgPopupV5 *>(newFocus->shellSurface()))
-        m_display->handleWindowActivated(newFocus);
-    if (oldFocus && qobject_cast<QWaylandXdgPopupV5 *>(oldFocus->shellSurface()))
-        m_display->handleWindowDeactivated(oldFocus);
-}
-
 }
 
 QT_END_NAMESPACE
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
index ce6bdb9e..aed88670 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
@@ -67,7 +67,6 @@ public:
     QWaylandXdgShellV5Integration() {}
     bool initialize(QWaylandDisplay *display) override;
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
 
 private:
     QScopedPointer<QWaylandXdgShellV5> m_xdgShell;
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
index 8c371661..151c78e3 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
@@ -174,6 +174,7 @@ QWaylandXdgSurfaceV6::Popup::Popup(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdg
     , m_xdgSurface(xdgSurface)
     , m_parent(parent)
 {
+    m_parent->window()->addChildPopup(m_xdgSurface->window());
 }
 
 QWaylandXdgSurfaceV6::Popup::~Popup()
@@ -181,6 +182,8 @@ QWaylandXdgSurfaceV6::Popup::~Popup()
     if (isInitialized())
         destroy();
 
+    m_parent->window()->removeChildPopup(m_xdgSurface->window());
+
     if (m_grabbing) {
         auto *shell = m_xdgSurface->m_shell;
         Q_ASSERT(shell->m_topmostGrabbingPopup == this);
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
index 03164316..e8da8ba1 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
@@ -68,20 +68,6 @@ QWaylandShellSurface *QWaylandXdgShellV6Integration::createShellSurface(QWayland
     return m_xdgShell->getXdgSurface(window);
 }
 
-void QWaylandXdgShellV6Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
-{
-    if (newFocus) {
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(newFocus->shellSurface());
-        if (xdgSurface && !xdgSurface->handlesActiveState())
-            m_display->handleWindowActivated(newFocus);
-    }
-    if (oldFocus && qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface())) {
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface());
-        if (xdgSurface && !xdgSurface->handlesActiveState())
-            m_display->handleWindowDeactivated(oldFocus);
-    }
-}
-
 }
 
 QT_END_NAMESPACE
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
index 261f8cbb..c1bcd5c6 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
@@ -65,7 +65,6 @@ public:
     QWaylandXdgShellV6Integration() {}
     bool initialize(QWaylandDisplay *display) override;
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
 
 private:
     QScopedPointer<QWaylandXdgShellV6> m_xdgShell;
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index f3e3c330..fa6d5808 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -67,11 +67,6 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
 
 QWaylandXdgSurface::Toplevel::~Toplevel()
 {
-    if (m_applied.states & Qt::WindowActive) {
-        QWaylandWindow *window = m_xdgSurface->window();
-        window->display()->handleWindowDeactivated(window);
-    }
-
     // The protocol spec requires that the decoration object is deleted before xdg_toplevel.
     delete m_decoration;
     m_decoration = nullptr;
@@ -85,16 +80,15 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
     if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
         m_normalSize = m_xdgSurface->m_window->windowFrameGeometry().size();
 
-    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive))
+    if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)
+        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
         m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
 
-    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive))
+    if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)
+        && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
         m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
 
-    // TODO: none of the other plugins send WindowActive either, but is it on purpose?
-    Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
-
-    m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
+    m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
 
     if (m_pending.size.isEmpty()) {
         // An empty size in the configure means it's up to the client to choose the size
@@ -105,8 +99,6 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
         m_xdgSurface->m_window->resizeFromApplyConfigure(m_pending.size);
     }
 
-    m_xdgSurface->setSizeHints();
-
     m_applied = m_pending;
     qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
 }
@@ -203,12 +195,17 @@ QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResi
                 | ((edges & Qt::RightEdge) ? resize_edge_right : 0));
 }
 
-QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent,
+QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent,
                                  QtWayland::xdg_positioner *positioner)
-    : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object()))
-    , m_xdgSurface(xdgSurface)
+    : m_xdgSurface(xdgSurface)
+    , m_parentXdgSurface(qobject_cast<QWaylandXdgSurface *>(parent->shellSurface()))
     , m_parent(parent)
 {
+
+    init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr, positioner->object()));
+    if (m_parent) {
+        m_parent->addChildPopup(m_xdgSurface->window());
+    }
 }
 
 QWaylandXdgSurface::Popup::~Popup()
@@ -216,10 +213,24 @@ QWaylandXdgSurface::Popup::~Popup()
     if (isInitialized())
         destroy();
 
+    if (m_parent) {
+        m_parent->removeChildPopup(m_xdgSurface->window());
+    }
+
     if (m_grabbing) {
         auto *shell = m_xdgSurface->m_shell;
         Q_ASSERT(shell->m_topmostGrabbingPopup == this);
-        shell->m_topmostGrabbingPopup = m_parent->m_popup;
+        shell->m_topmostGrabbingPopup = m_parentXdgSurface ? m_parentXdgSurface->m_popup : nullptr;
+        m_grabbing = false;
+
+        // Synthesize Qt enter/leave events for popup
+        QWindow *leave = nullptr;
+        if (m_xdgSurface && m_xdgSurface->window())
+            leave = m_xdgSurface->window()->window();
+        QWindowSystemInterface::handleLeaveEvent(leave);
+
+        if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos()))
+            QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
     }
 }
 
@@ -257,6 +268,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
                 m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
         }
     }
+    setSizeHints();
 }
 
 QWaylandXdgSurface::~QWaylandXdgSurface()
@@ -400,8 +412,6 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
 {
     Q_ASSERT(!m_toplevel && !m_popup);
 
-    auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(parent->shellSurface());
-
     auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner());
     // set_popup expects a position relative to the parent
     QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
@@ -414,8 +424,9 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
     positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left);
     positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right);
     positioner->set_size(m_window->geometry().width(), m_window->geometry().height());
-    m_popup = new Popup(this, parentXdgSurface, positioner);
+    m_popup = new Popup(this, parent, positioner);
     positioner->destroy();
+
     delete positioner;
 }
 
@@ -437,6 +448,23 @@ void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevic
     }
     setPopup(parent);
     m_popup->grab(device, serial);
+
+    // Synthesize Qt enter/leave events for popup
+    if (!parent)
+        return;
+    QWindow *current = QGuiApplication::topLevelAt(QCursor::pos());
+    QWindow *leave = parent->window();
+    if (current != leave)
+        return;
+
+    QWindowSystemInterface::handleLeaveEvent(leave);
+
+    QWindow *enter = nullptr;
+    if (m_popup && m_popup->m_xdgSurface && m_popup->m_xdgSurface->window())
+        enter = m_popup->m_xdgSurface->window()->window();
+
+    if (enter)
+        QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
 }
 
 void QWaylandXdgSurface::xdg_surface_configure(uint32_t serial)
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
index 96785205..4b518f0a 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
@@ -131,14 +131,15 @@ private:
 
     class Popup : public QtWayland::xdg_popup {
     public:
-        Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner);
+        Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent, QtWayland::xdg_positioner *positioner);
         ~Popup() override;
 
         void grab(QWaylandInputDevice *seat, uint serial);
         void xdg_popup_popup_done() override;
 
         QWaylandXdgSurface *m_xdgSurface = nullptr;
-        QWaylandXdgSurface *m_parent = nullptr;
+        QWaylandXdgSurface *m_parentXdgSurface = nullptr;
+        QWaylandWindow *m_parent = nullptr;
         bool m_grabbing = false;
     };
 
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
index 8769d971..da0dd6a7 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
@@ -69,20 +69,6 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi
     return m_xdgShell->getXdgSurface(window);
 }
 
-void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
-{
-    if (newFocus) {
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(newFocus->shellSurface());
-        if (xdgSurface && !xdgSurface->handlesActiveState())
-            m_display->handleWindowActivated(newFocus);
-    }
-    if (oldFocus && qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface())) {
-        auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface());
-        if (xdgSurface && !xdgSurface->handlesActiveState())
-            m_display->handleWindowDeactivated(oldFocus);
-    }
-}
-
 }
 
 QT_END_NAMESPACE
diff --git a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
index b6caa6c9..2f929f98 100644
--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
@@ -65,7 +65,6 @@ public:
     QWaylandXdgShellIntegration() {}
     bool initialize(QWaylandDisplay *display) override;
     QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
-    void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
 
 private:
     QScopedPointer<QWaylandXdgShell> m_xdgShell;
diff --git a/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp b/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
index 526d0ef4..f50ccf30 100644
--- a/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
+++ b/qtwayland/src/shared/qwaylandinputmethodeventbuilder.cpp
@@ -39,7 +39,10 @@
 
 #include "qwaylandinputmethodeventbuilder_p.h"
 
+#include <QBrush>
+#include <QGuiApplication>
 #include <QInputMethod>
+#include <QPalette>
 #include <QTextCharFormat>
 
 #ifdef QT_BUILD_WAYLANDCOMPOSITOR_LIB
@@ -81,32 +84,38 @@ void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t
     QTextCharFormat format;
 
     switch (style) {
-    case 0:
-    case 1:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_NONE:
+        break;
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_DEFAULT:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_UNDERLINE:
         format.setFontUnderline(true);
         format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
         break;
-    case 2:
-    case 3:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_ACTIVE:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INACTIVE:
         format.setFontWeight(QFont::Bold);
         format.setFontUnderline(true);
         format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
         break;
-    case 4:
-        format.setFontUnderline(true);
-        format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
-        m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_HIGHLIGHT:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_SELECTION:
+        {
+            format.setFontUnderline(true);
+            format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+            QPalette palette = qApp->palette();
+            format.setBackground(QBrush(palette.color(QPalette::Active, QPalette::Highlight)));
+            format.setForeground(QBrush(palette.color(QPalette::Active, QPalette::HighlightedText)));
+            m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
+        }
         break;
-    case 5:
+    case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INCORRECT:
         format.setFontUnderline(true);
         format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
         format.setUnderlineColor(QColor(Qt::red));
         m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
         break;
-//    case QtWayland::wl_text_input::preedit_style_selection:
-//    case QtWayland::wl_text_input::preedit_style_none:
     default:
         break;
     }
@@ -153,7 +162,7 @@ QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &t
 
     if (m_preeditCursor < 0) {
         attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
-    } else if (m_preeditCursor > 0) {
+    } else {
         attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
     }
 
diff --git a/qtwayland/src/shared/qwaylandmimehelper.cpp b/qtwayland/src/shared/qwaylandmimehelper.cpp
index a5fdd34d..e2fe1928 100644
--- a/qtwayland/src/shared/qwaylandmimehelper.cpp
+++ b/qtwayland/src/shared/qwaylandmimehelper.cpp
@@ -60,7 +60,7 @@ QByteArray QWaylandMimeHelper::getByteArray(QMimeData *mimeData, const QString &
             buf.open(QIODevice::ReadWrite);
             QByteArray fmt = "BMP";
             if (mimeType.startsWith(QLatin1String("image/"))) {
-                QByteArray imgFmt = mimeType.mid(6).toUpper().toLatin1();
+                QByteArray imgFmt = mimeType.mid(6).toLower().toLatin1();
                 if (QImageWriter::supportedImageFormats().contains(imgFmt))
                     fmt = imgFmt;
             }
@@ -74,7 +74,7 @@ QByteArray QWaylandMimeHelper::getByteArray(QMimeData *mimeData, const QString &
         QList<QUrl> urls = mimeData->urls();
         for (int i = 0; i < urls.count(); ++i) {
             content.append(urls.at(i).toEncoded());
-            content.append('\n');
+            content.append("\r\n");
         }
     } else {
         content = mimeData->data(mimeType);
diff --git a/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
index 1568b3b9..067410d0 100644
--- a/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
+++ b/qtwayland/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
@@ -35,7 +35,7 @@
 
 using namespace MockCompositor;
 
-constexpr int dataDeviceVersion = 1;
+constexpr int dataDeviceVersion = 3;
 
 class DataDeviceCompositor : public DefaultCompositor {
 public:
diff --git a/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp b/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
index 9312c2e5..2ea382f1 100644
--- a/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
+++ b/qtwayland/tests/auto/client/seatv5/tst_seatv5.cpp
@@ -73,6 +73,7 @@ private slots:
     void multiTouch();
     void multiTouchUpAndMotionFrame();
     void tapAndMoveInSameFrame();
+    void cancelTouch();
 };
 
 void tst_seatv5::bindsToSeat()
@@ -646,5 +647,34 @@ void tst_seatv5::tapAndMoveInSameFrame()
     QTRY_COMPARE(window.m_events.last().touchPoints.first().state(), Qt::TouchPointState::TouchPointReleased);
 }
 
+void tst_seatv5::cancelTouch()
+{
+    TouchWindow window;
+    QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
+
+    exec([=] {
+        auto *t = touch();
+        auto *c = client();
+        t->sendDown(xdgToplevel()->surface(), {32, 32}, 1);
+        t->sendFrame(c);
+        t->sendCancel(c);
+        t->sendFrame(c);
+    });
+
+    QTRY_VERIFY(!window.m_events.empty());
+    {
+        auto e = window.m_events.takeFirst();
+        QCOMPARE(e.type, QEvent::TouchBegin);
+        QCOMPARE(e.touchPointStates, Qt::TouchPointPressed);
+        QCOMPARE(e.touchPoints.length(), 1);
+        QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
+    }
+    {
+        auto e = window.m_events.takeFirst();
+        QCOMPARE(e.type, QEvent::TouchCancel);
+        QCOMPARE(e.touchPoints.length(), 0);
+    }
+}
+
 QCOMPOSITOR_TEST_MAIN(tst_seatv5)
 #include "tst_seatv5.moc"
diff --git a/qtwayland/tests/auto/client/shared/corecompositor.cpp b/qtwayland/tests/auto/client/shared/corecompositor.cpp
index 5c6c83ba..fa9b7662 100644
--- a/qtwayland/tests/auto/client/shared/corecompositor.cpp
+++ b/qtwayland/tests/auto/client/shared/corecompositor.cpp
@@ -27,6 +27,7 @@
 ****************************************************************************/
 
 #include "corecompositor.h"
+#include <thread>
 
 namespace MockCompositor {
 
diff --git a/qtwayland/tests/auto/client/shared/coreprotocol.cpp b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
index 0d988521..d1a2e7cb 100644
--- a/qtwayland/tests/auto/client/shared/coreprotocol.cpp
+++ b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
@@ -451,6 +451,13 @@ void Touch::sendFrame(wl_client *client)
         send_frame(r->handle);
 }
 
+void Touch::sendCancel(wl_client *client)
+{
+    const auto touchResources = resourceMap().values(client);
+    for (auto *r : touchResources)
+        send_cancel(r->handle);
+}
+
 uint Keyboard::sendEnter(Surface *surface)
 {
     auto serial = m_seat->m_compositor->nextSerial();
diff --git a/qtwayland/tests/auto/client/shared/coreprotocol.h b/qtwayland/tests/auto/client/shared/coreprotocol.h
index a1af137a..210d8ddb 100644
--- a/qtwayland/tests/auto/client/shared/coreprotocol.h
+++ b/qtwayland/tests/auto/client/shared/coreprotocol.h
@@ -158,7 +158,7 @@ class WlCompositor : public Global, public QtWaylandServer::wl_compositor
 {
     Q_OBJECT
 public:
-    explicit WlCompositor(CoreCompositor *compositor, int version = 3)
+    explicit WlCompositor(CoreCompositor *compositor, int version = 4)
         : QtWaylandServer::wl_compositor(compositor->m_display, version)
         , m_compositor(compositor)
     {}
@@ -364,6 +364,7 @@ public:
     uint sendUp(wl_client *client, int id);
     void sendMotion(wl_client *client, const QPointF &position, int id);
     void sendFrame(wl_client *client);
+    void sendCancel(wl_client *client);
 
     Seat *m_seat = nullptr;
 };
diff --git a/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp b/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
index a415cbf5..b1d3d07d 100644
--- a/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
+++ b/qtwayland/tests/auto/client/shared_old/mockcompositor.cpp
@@ -342,7 +342,7 @@ Compositor::Compositor(MockCompositor *mockCompositor)
         exit(EXIT_FAILURE);
     }
 
-    wl_global_create(m_display, &wl_compositor_interface, 1, this, bindCompositor);
+    wl_global_create(m_display, &wl_compositor_interface, 4, this, bindCompositor);
 
     m_data_device_manager.reset(new DataDeviceManager(this, m_display));
 
diff --git a/qtwayland/tests/auto/client/shared_old/mocksurface.cpp b/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
index e9df5f90..c3246e4a 100644
--- a/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
+++ b/qtwayland/tests/auto/client/shared_old/mocksurface.cpp
@@ -125,6 +125,16 @@ void Surface::surface_damage(Resource *resource,
     Q_UNUSED(height);
 }
 
+void Surface::surface_damage_buffer(Resource *resource,
+                                    int32_t x, int32_t y, int32_t width, int32_t height)
+{
+    Q_UNUSED(resource);
+    Q_UNUSED(x);
+    Q_UNUSED(y);
+    Q_UNUSED(width);
+    Q_UNUSED(height);
+}
+
 void Surface::surface_frame(Resource *resource,
                             uint32_t callback)
 {
diff --git a/qtwayland/tests/auto/client/shared_old/mocksurface.h b/qtwayland/tests/auto/client/shared_old/mocksurface.h
index 949dc23d..d176837e 100644
--- a/qtwayland/tests/auto/client/shared_old/mocksurface.h
+++ b/qtwayland/tests/auto/client/shared_old/mocksurface.h
@@ -65,6 +65,8 @@ protected:
                         struct wl_resource *buffer, int x, int y) override;
     void surface_damage(Resource *resource,
                         int32_t x, int32_t y, int32_t width, int32_t height) override;
+    void surface_damage_buffer(Resource *resource,
+                               int32_t x, int32_t y, int32_t width, int32_t height) override;
     void surface_frame(Resource *resource,
                        uint32_t callback) override;
     void surface_commit(Resource *resource) override;
diff --git a/qtwayland/tests/auto/client/surface/tst_surface.cpp b/qtwayland/tests/auto/client/surface/tst_surface.cpp
index 95e4e609..60c672ce 100644
--- a/qtwayland/tests/auto/client/surface/tst_surface.cpp
+++ b/qtwayland/tests/auto/client/surface/tst_surface.cpp
@@ -129,6 +129,10 @@ void tst_surface::waitForFrameCallbackGl()
     // Make sure we follow frame callbacks for some frames
     for (int i = 0; i < 5; ++i) {
         xdgPingAndWaitForPong(); // Make sure things have happened on the client
+        if (!qEnvironmentVariableIntValue("QT_WAYLAND_DISABLE_WINDOWDECORATION") && i == 0) {
+            QCOMPARE(bufferSpy.count(), 1);
+            bufferSpy.removeFirst();
+        }
         exec([&] {
             QVERIFY(bufferSpy.empty()); // Make sure no extra buffers have arrived
             QVERIFY(!xdgToplevel()->surface()->m_waitingFrameCallbacks.empty());
diff --git a/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp b/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
index 2277bbb8..747875b4 100644
--- a/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
+++ b/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
@@ -31,6 +31,7 @@
 #include <QtGui/QOpenGLWindow>
 #include <QtGui/qpa/qplatformnativeinterface.h>
 #include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
 
 using namespace MockCompositor;
 
@@ -45,6 +46,7 @@ private slots:
     void configureStates();
     void popup();
     void tooltipOnPopup();
+    void tooltipAndSiblingPopup();
     void switchPopups();
     void hidePopupParent();
     void pongs();
@@ -138,6 +140,7 @@ void tst_xdgshell::configureSize()
 
 void tst_xdgshell::configureStates()
 {
+    QVERIFY(qputenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", "0"));
     QRasterWindow window;
     window.resize(64, 48);
     window.show();
@@ -154,9 +157,12 @@ void tst_xdgshell::configureStates()
     // Toplevel windows don't know their position on xdg-shell
 //    QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
 
-//    QEXPECT_FAIL("", "configure has already been acked, we shouldn't have to wait for isActive", Continue);
-//    QVERIFY(window.isActive());
-    QTRY_VERIFY(window.isActive()); // Just make sure it eventually get's set correctly
+    // window.windowstate() is driven by keyboard focus, however for decorations we want to follow
+    // XDGShell this is internal to QtWayland so it is queried directly
+    auto waylandWindow = static_cast<QtWaylandClient::QWaylandWindow *>(window.handle());
+    Q_ASSERT(waylandWindow);
+    QTRY_VERIFY(waylandWindow->windowStates().testFlag(
+            Qt::WindowActive)); // Just make sure it eventually get's set correctly
 
     const QSize screenSize(640, 480);
     const uint maximizedSerial = exec([=] {
@@ -186,6 +192,7 @@ void tst_xdgshell::configureStates()
     QCOMPARE(window.windowStates(), Qt::WindowNoState);
     QCOMPARE(window.frameGeometry().size(), windowedSize);
 //    QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
+    QVERIFY(qunsetenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT"));
 }
 
 void tst_xdgshell::popup()
@@ -340,6 +347,92 @@ void tst_xdgshell::tooltipOnPopup()
     QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
 }
 
+void tst_xdgshell::tooltipAndSiblingPopup()
+{
+    class ToolTip : public QRasterWindow {
+    public:
+        explicit ToolTip(QWindow *parent) {
+            setTransientParent(parent);
+            setFlags(Qt::ToolTip);
+            resize(100, 100);
+            show();
+        }
+        void mousePressEvent(QMouseEvent *event) override {
+            QRasterWindow::mousePressEvent(event);
+            m_popup = new QRasterWindow;
+            m_popup->setTransientParent(transientParent());
+            m_popup->setFlags(Qt::Popup);
+            m_popup->resize(100, 100);
+            m_popup->show();
+        }
+
+        QRasterWindow *m_popup = nullptr;
+    };
+
+    class Window : public QRasterWindow {
+    public:
+        void mousePressEvent(QMouseEvent *event) override {
+            QRasterWindow::mousePressEvent(event);
+            m_tooltip = new ToolTip(this);
+        }
+        ToolTip *m_tooltip = nullptr;
+    };
+
+    Window window;
+    window.resize(200, 200);
+    window.show();
+
+    QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
+    exec([=] { xdgToplevel()->sendCompleteConfigure(); });
+    QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial);
+
+    exec([=] {
+        auto *surface = xdgToplevel()->surface();
+        auto *p = pointer();
+        auto *c = client();
+        p->sendEnter(surface, {100, 100});
+        p->sendFrame(c);
+        p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
+        p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
+        p->sendFrame(c);
+        p->sendLeave(surface);
+        p->sendFrame(c);
+    });
+
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup());
+    exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
+    QCOMPOSITOR_TRY_VERIFY(!xdgPopup()->m_grabbed);
+
+    exec([=] {
+        auto *surface = xdgPopup()->surface();
+        auto *p = pointer();
+        auto *c = client();
+        p->sendEnter(surface, {100, 100});
+        p->sendFrame(c);
+        p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
+        p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
+        p->sendFrame(c);
+    });
+
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1));
+    exec([=] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_xdgSurface->m_committedConfigureSerial);
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_grabbed);
+
+    // Close the middle tooltip (it should not close the sibling popup)
+    window.m_tooltip->close();
+
+    QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
+    // Verify the remaining xdg surface is a grab popup..
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup(0));
+    QCOMPOSITOR_TRY_VERIFY(xdgPopup(0)->m_grabbed);
+
+    window.m_tooltip->m_popup->close();
+    QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
+    QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
+}
+
 // QTBUG-65680
 void tst_xdgshell::switchPopups()
 {
@@ -505,7 +598,7 @@ void tst_xdgshell::minMaxSize()
     window.show();
     QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
 
-    exec([=] { xdgToplevel()->sendCompleteConfigure(); });
+    // we don't roundtrip with our configuration the initial commit should be correct
 
     QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(100, 100));
     QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(1000, 1000));
Submodule qtwebchannel 618422ee..f8949655:
diff --git a/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp b/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
index 536eb5c..898d769 100644
--- a/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
+++ b/qtwebchannel/src/webchannel/qmetaobjectpublisher.cpp
@@ -186,8 +186,6 @@ Q_DECLARE_TYPEINFO(OverloadResolutionCandidate, Q_MOVABLE_TYPE);
 QMetaObjectPublisher::QMetaObjectPublisher(QWebChannel *webChannel)
     : QObject(webChannel)
     , webChannel(webChannel)
-    , signalHandler(this)
-    , clientIsIdle(false)
     , blockUpdates(false)
     , propertyUpdatesInitialized(false)
 {
@@ -301,17 +299,17 @@ QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object, QWeb
     return data;
 }
 
-void QMetaObjectPublisher::setClientIsIdle(bool isIdle)
+void QMetaObjectPublisher::setClientIsIdle(bool isIdle, QWebChannelAbstractTransport *transport)
 {
-    if (clientIsIdle == isIdle) {
-        return;
-    }
-    clientIsIdle = isIdle;
-    if (!isIdle && timer.isActive()) {
-        timer.stop();
-    } else if (isIdle && !timer.isActive()) {
-        timer.start(PROPERTY_UPDATE_INTERVAL, this);
-    }
+    transportState[transport].clientIsIdle = isIdle;
+    if (isIdle)
+        sendEnqueuedPropertyUpdates(transport);
+}
+
+bool QMetaObjectPublisher::isClientIdle(QWebChannelAbstractTransport *transport)
+{
+    auto found = transportState.find(transport);
+    return found != transportState.end() && found.value().clientIsIdle;
 }
 
 QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport *transport)
@@ -333,6 +331,7 @@ QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport
 
 void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object, const QJsonObject &objectInfo)
 {
+    auto *signalHandler = signalHandlerFor(object);
     foreach (const QJsonValue &propertyInfoVar, objectInfo[KEY_PROPERTIES].toArray()) {
         const QJsonArray &propertyInfo = propertyInfoVar.toArray();
         if (propertyInfo.size() < 2) {
@@ -353,19 +352,19 @@ void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object
 
         // Only connect for a property update once
         if (connectedProperties.isEmpty()) {
-            signalHandler.connectTo(object, signalIndex);
+            signalHandler->connectTo(object, signalIndex);
         }
 
         connectedProperties.insert(propertyIndex);
     }
 
     // also always connect to destroyed signal
-    signalHandler.connectTo(object, s_destroyedSignalIndex);
+    signalHandler->connectTo(object, s_destroyedSignalIndex);
 }
 
 void QMetaObjectPublisher::sendPendingPropertyUpdates()
 {
-    if (blockUpdates || !clientIsIdle || pendingPropertyUpdates.isEmpty()) {
+    if (blockUpdates) {
         return;
     }
 
@@ -415,18 +414,19 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
 
     // data does not contain specific updates
     if (!data.isEmpty()) {
-        setClientIsIdle(false);
-
         message[KEY_DATA] = data;
-        broadcastMessage(message);
+        enqueueBroadcastMessage(message);
     }
 
     // send every property update which is not supposed to be broadcasted
     const QHash<QWebChannelAbstractTransport*, QJsonArray>::const_iterator suend = specificUpdates.constEnd();
     for (QHash<QWebChannelAbstractTransport*, QJsonArray>::const_iterator it = specificUpdates.constBegin(); it != suend; ++it) {
         message[KEY_DATA] = it.value();
-        it.key()->sendMessage(message);
+        enqueueMessage(message, it.key());
     }
+
+    for (auto state = transportState.begin(); state != transportState.end(); ++state)
+        sendEnqueuedPropertyUpdates(state.key());
 }
 
 QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const QMetaMethod &method,
@@ -572,7 +572,7 @@ void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signal
         }
     } else {
         pendingPropertyUpdates[object][signalIndex] = arguments;
-        if (clientIsIdle && !blockUpdates && !timer.isActive()) {
+        if (!blockUpdates && !timer.isActive()) {
             timer.start(PROPERTY_UPDATE_INTERVAL, this);
         }
     }
@@ -590,7 +590,7 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object)
     // only remove from handler when we initialized the property updates
     // cf: https://bugreports.qt.io/browse/QTBUG-60250
     if (propertyUpdatesInitialized) {
-        signalHandler.remove(object);
+        signalHandlerFor(object)->remove(object);
         signalToPropertyMap.remove(object);
     }
     pendingPropertyUpdates.remove(object);
@@ -852,6 +852,52 @@ void QMetaObjectPublisher::broadcastMessage(const QJsonObject &message) const
     }
 }
 
+void QMetaObjectPublisher::enqueueBroadcastMessage(const QJsonObject &message)
+{
+    if (webChannel->d_func()->transports.isEmpty()) {
+        qWarning("QWebChannel is not connected to any transports, cannot send message: %s",
+                 QJsonDocument(message).toJson().constData());
+        return;
+    }
+
+    for (auto *transport : webChannel->d_func()->transports) {
+        auto &state = transportState[transport];
+        state.queuedMessages.append(message);
+    }
+}
+
+void QMetaObjectPublisher::enqueueMessage(const QJsonObject &message,
+                                          QWebChannelAbstractTransport *transport)
+{
+    auto &state = transportState[transport];
+    state.queuedMessages.append(message);
+}
+
+void QMetaObjectPublisher::sendEnqueuedPropertyUpdates(QWebChannelAbstractTransport *transport)
+{
+    auto found = transportState.find(transport);
+    if (found != transportState.end() && found.value().clientIsIdle
+        && !found.value().queuedMessages.isEmpty()) {
+
+        // If the client is connected with an in-process transport, it can
+        // happen that a message triggers a subsequent property change. In
+        // that case, we need to ensure that the queued messages have already
+        // been cleared; otherwise the recursive call will send everythig again.
+        // Case in point: The qmlwebchannel tests fail if we don't clear the
+        // queued messages before sending them out.
+        // For that same reason set the client to "busy" (aka non-idle) just
+        // right before sending out the messages; otherwise a potential
+        // "Idle" type message will not correctly restore the Idle state.
+        const auto messages = std::move(found.value().queuedMessages);
+        Q_ASSERT(found.value().queuedMessages.isEmpty());
+        found.value().clientIsIdle = false;
+
+        for (const auto &message : messages) {
+            transport->sendMessage(message);
+        }
+    }
+}
+
 void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport)
 {
     if (!webChannel->d_func()->transports.contains(transport)) {
@@ -866,7 +912,7 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel
 
     const MessageType type = toType(message.value(KEY_TYPE));
     if (type == TypeIdle) {
-        setClientIsIdle(true);
+        setClientIsIdle(true, transport);
     } else if (type == TypeInit) {
         if (!message.contains(KEY_ID)) {
             qWarning("JSON message object is missing the id property: %s",
@@ -913,9 +959,9 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel
                 return;
             transport->sendMessage(createResponse(message.value(KEY_ID), wrapResult(result, transport)));
         } else if (type == TypeConnectToSignal) {
-            signalHandler.connectTo(object, message.value(KEY_SIGNAL).toInt(-1));
+            signalHandlerFor(object)->connectTo(object, message.value(KEY_SIGNAL).toInt(-1));
         } else if (type == TypeDisconnectFromSignal) {
-            signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1));
+            signalHandlerFor(object)->disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1));
         } else if (type == TypeSetProperty) {
             setProperty(object, message.value(KEY_PROPERTY).toInt(-1),
                         message.value(KEY_VALUE));
@@ -931,6 +977,7 @@ void QMetaObjectPublisher::setBlockUpdates(bool block)
     blockUpdates = block;
 
     if (!blockUpdates) {
+        timer.start(PROPERTY_UPDATE_INTERVAL, this);
         sendPendingPropertyUpdates();
     } else if (timer.isActive()) {
         timer.stop();
@@ -948,4 +995,15 @@ void QMetaObjectPublisher::timerEvent(QTimerEvent *event)
     }
 }
 
+SignalHandler<QMetaObjectPublisher> *QMetaObjectPublisher::signalHandlerFor(const QObject *object)
+{
+    auto thread = object->thread();
+    auto it = signalHandlers.find(thread);
+    if (it == signalHandlers.end()) {
+        it = signalHandlers.emplace(thread, this).first;
+        it->second.moveToThread(thread);
+    }
+    return &it->second;
+}
+
 QT_END_NAMESPACE
diff --git a/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h b/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
index bbd9875..4713ef1 100644
--- a/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
+++ b/qtwebchannel/src/webchannel/qmetaobjectpublisher_p.h
@@ -59,6 +59,9 @@
 #include <QBasicTimer>
 #include <QPointer>
 #include <QJsonObject>
+#include <QQueue>
+
+#include <unordered_map>
 
 #include "qwebchannelglobal.h"
 
@@ -109,17 +112,36 @@ public:
      */
     void broadcastMessage(const QJsonObject &message) const;
 
+    /**
+     * Enqueue the given @p message to all known transports.
+     */
+    void enqueueBroadcastMessage(const QJsonObject &message);
+
+    /**
+     * Enqueue the given @p message to @p transport.
+     */
+    void enqueueMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport);
+
+    /**
+     * If client for given @p transport is idle, send queued messaged to @p transport and then mark
+     * the client as not idle.
+     */
+    void sendEnqueuedPropertyUpdates(QWebChannelAbstractTransport *transport);
+
     /**
      * Serialize the QMetaObject of @p object and return it in JSON form.
      */
     QJsonObject classInfoForObject(const QObject *object, QWebChannelAbstractTransport *transport);
 
     /**
-     * Set the client to idle or busy, based on the value of @p isIdle.
-     *
-     * When the value changed, start/stop the property update timer accordingly.
+     * Set the client to idle or busy for a single @p transport, based on the value of @p isIdle.
+     */
+    void setClientIsIdle(bool isIdle, QWebChannelAbstractTransport *transport);
+
+    /**
+     * Check that client is idle for @p transport.
      */
-    void setClientIsIdle(bool isIdle);
+    bool isClientIdle(QWebChannelAbstractTransport *transport);
 
     /**
      * Initialize clients by sending them the class information of the registered objects.
@@ -272,10 +294,18 @@ private:
     friend class TestWebChannel;
 
     QWebChannel *webChannel;
-    SignalHandler<QMetaObjectPublisher> signalHandler;
+    std::unordered_map<const QThread*, SignalHandler<QMetaObjectPublisher>> signalHandlers;
+    SignalHandler<QMetaObjectPublisher> *signalHandlerFor(const QObject *object);
 
-    // true when the client is idle, false otherwise
-    bool clientIsIdle;
+    struct TransportState
+    {
+        TransportState() : clientIsIdle(false) { }
+        // true when the client is idle, false otherwise
+        bool clientIsIdle;
+        // messages to send
+        QQueue<QJsonObject> queuedMessages;
+    };
+    QHash<QWebChannelAbstractTransport *, TransportState> transportState;
 
     // true when no property updates should be sent, false otherwise
     bool blockUpdates;
diff --git a/qtwebchannel/src/webchannel/signalhandler_p.h b/qtwebchannel/src/webchannel/signalhandler_p.h
index 27afadb..d77373c 100644
--- a/qtwebchannel/src/webchannel/signalhandler_p.h
+++ b/qtwebchannel/src/webchannel/signalhandler_p.h
@@ -56,6 +56,7 @@
 #include <QVector>
 #include <QMetaMethod>
 #include <QDebug>
+#include <QThread>
 
 QT_BEGIN_NAMESPACE
 
@@ -71,6 +72,7 @@ static const int s_destroyedSignalIndex = QObject::staticMetaObject.indexOfMetho
 template<class Receiver>
 class SignalHandler : public QObject
 {
+    Q_DISABLE_COPY(SignalHandler)
 public:
     SignalHandler(Receiver *receiver, QObject *parent = 0);
 
@@ -268,6 +270,7 @@ int SignalHandler<Receiver>::qt_metacall(QMetaObject::Call call, int methodId, v
     if (call == QMetaObject::InvokeMetaMethod) {
         const QObject *object = sender();
         Q_ASSERT(object);
+        Q_ASSERT(QThread::currentThread() == object->thread());
         Q_ASSERT(senderSignalIndex() == methodId);
         Q_ASSERT(m_connectionsCounter.contains(object));
         Q_ASSERT(m_connectionsCounter.value(object).contains(methodId));
diff --git a/qtwebchannel/tests/auto/qml/testwebchannel.cpp b/qtwebchannel/tests/auto/qml/testwebchannel.cpp
index 9891687..3ca81c2 100644
--- a/qtwebchannel/tests/auto/qml/testwebchannel.cpp
+++ b/qtwebchannel/tests/auto/qml/testwebchannel.cpp
@@ -46,7 +46,11 @@ TestWebChannel::~TestWebChannel()
 
 bool TestWebChannel::clientIsIdle() const
 {
-    return QWebChannel::d_func()->publisher->clientIsIdle;
+    for (auto *transport : QWebChannel::d_func()->transports) {
+        if (QWebChannel::d_func()->publisher->isClientIdle(transport))
+            return true;
+    }
+    return false;
 }
 
 QT_END_NAMESPACE
diff --git a/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp b/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
index 181da9e..37f989a 100644
--- a/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
+++ b/qtwebchannel/tests/auto/webchannel/tst_webchannel.cpp
@@ -785,7 +785,7 @@ void TestWebChannel::testTransportWrapObjectProperties()
     DummyTransport *dummyTransport = new DummyTransport(this);
     channel.connectTo(dummyTransport);
     channel.d_func()->publisher->initializeClient(dummyTransport);
-    channel.d_func()->publisher->setClientIsIdle(true);
+    channel.d_func()->publisher->setClientIsIdle(true, dummyTransport);
 
     QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.size(), 0);
 
@@ -943,8 +943,6 @@ void TestWebChannel::testInfiniteRecursion()
 
 void TestWebChannel::testAsyncObject()
 {
-    QSKIP("This test is broken. See QTBUG-80729");
-
     QWebChannel channel;
     channel.connectTo(m_dummyTransport);
 
@@ -990,6 +988,50 @@ void TestWebChannel::testAsyncObject()
     thread.wait();
 }
 
+void TestWebChannel::testPropertyMultipleTransports()
+{
+    DummyTransport transport1;
+    DummyTransport transport2;
+
+    QWebChannel channel;
+    QMetaObjectPublisher *publisher = channel.d_func()->publisher;
+
+    TestObject testObj;
+    testObj.setObjectName("testObject");
+    channel.registerObject(testObj.objectName(), &testObj);
+    channel.connectTo(&transport1);
+    channel.connectTo(&transport2);
+
+    testObj.setProp("Hello");
+
+    publisher->initializeClient(&transport1);
+    publisher->initializeClient(&transport2);
+    publisher->setClientIsIdle(true, &transport1);
+    QCOMPARE(publisher->isClientIdle(&transport1), true);
+    QCOMPARE(publisher->isClientIdle(&transport2), false);
+    QVERIFY(transport1.messagesSent().isEmpty());
+    QVERIFY(transport2.messagesSent().isEmpty());
+
+    testObj.setProp("World");
+    QTRY_COMPARE_WITH_TIMEOUT(transport1.messagesSent().size(), 1u, 2000);
+    QCOMPARE(transport2.messagesSent().size(), 0u);
+    publisher->setClientIsIdle(true, &transport2);
+    QTRY_COMPARE_WITH_TIMEOUT(transport2.messagesSent().size(), 1u, 2000);
+    QCOMPARE(publisher->isClientIdle(&transport1), false);
+    QCOMPARE(publisher->isClientIdle(&transport2), false);
+
+    testObj.setProp("!!!");
+    publisher->setClientIsIdle(true, &transport2);
+    QCOMPARE(publisher->isClientIdle(&transport2), true);
+    QCOMPARE(publisher->isClientIdle(&transport1), false);
+    QTRY_COMPARE_WITH_TIMEOUT(transport2.messagesSent().size(), 2u, 2000);
+    QCOMPARE(transport1.messagesSent().size(), 1u);
+    publisher->setClientIsIdle(true, &transport1);
+    QTRY_COMPARE_WITH_TIMEOUT(transport1.messagesSent().size(), 2u, 2000);
+    QCOMPARE(publisher->isClientIdle(&transport1), false);
+    QCOMPARE(publisher->isClientIdle(&transport2), false);
+}
+
 class FunctionWrapper : public QObject
 {
     Q_OBJECT
@@ -1082,7 +1124,7 @@ void TestWebChannel::benchInitializeClients()
 
         publisher->propertyUpdatesInitialized = false;
         publisher->signalToPropertyMap.clear();
-        publisher->signalHandler.clear();
+        publisher->signalHandlers.clear();
     }
 }
 
@@ -1107,7 +1149,7 @@ void TestWebChannel::benchPropertyUpdates()
             obj->change();
         }
 
-        channel.d_func()->publisher->clientIsIdle = true;
+        channel.d_func()->publisher->setClientIsIdle(true, m_dummyTransport);
         channel.d_func()->publisher->sendPendingPropertyUpdates();
     }
 }
diff --git a/qtwebchannel/tests/auto/webchannel/tst_webchannel.h b/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
index eae21f4..dd4e690 100644
--- a/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
+++ b/qtwebchannel/tests/auto/webchannel/tst_webchannel.h
@@ -348,6 +348,7 @@ private slots:
     void testJsonToVariant();
     void testInfiniteRecursion();
     void testAsyncObject();
+    void testPropertyMultipleTransports();
     void testDeletionDuringMethodInvocation_data();
     void testDeletionDuringMethodInvocation();
 
Submodule qtwebengine f328054d...38e0df6c (commits not present)
Submodule qtwebsockets 65850954..63fb8da1:
diff --git a/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp b/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
index 2affdd5..95f1194 100644
--- a/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
+++ b/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp
@@ -273,6 +273,7 @@ void QWebSocketDataProcessor::clear()
     if (!m_pConverterState)
         m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull |
                                                            QTextCodec::IgnoreHeader);
+    frame.clear();
 }
 
 /*!
diff --git a/qtwebsockets/src/websockets/qwebsocketprotocol.cpp b/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
index df87a93..d0465f1 100644
--- a/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
+++ b/qtwebsockets/src/websockets/qwebsocketprotocol.cpp
@@ -210,7 +210,7 @@ void QWebSocketProtocol::mask(char *payload, quint64 size, quint32 maskingKey)
                             quint8((maskingKey & 0x0000FF00u) >> 8),
                             quint8((maskingKey & 0x000000FFu))
                           };
-    int i = 0;
+    quint64 i = 0;
     while (size-- > 0)
         *payload++ ^= mask[i++ % 4];
 }
