11158 lines
461 KiB
Diff
11158 lines
461 KiB
Diff
Submodule qtbase 8ad94db9..2529f7f0:
|
|
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/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/corelib/global/qendian.h b/qtbase/src/corelib/global/qendian.h
|
|
index e9e51c4b93..85f72c494d 100644
|
|
--- a/qtbase/src/corelib/global/qendian.h
|
|
+++ b/qtbase/src/corelib/global/qendian.h
|
|
@@ -330,9 +330,9 @@ public:
|
|
}
|
|
|
|
static Q_DECL_CONSTEXPR QSpecialInteger max()
|
|
- { return QSpecialInteger(std::numeric_limits<T>::max()); }
|
|
+ { return QSpecialInteger((std::numeric_limits<T>::max)()); }
|
|
static Q_DECL_CONSTEXPR QSpecialInteger min()
|
|
- { return QSpecialInteger(std::numeric_limits<T>::min()); }
|
|
+ { return QSpecialInteger((std::numeric_limits<T>::min)()); }
|
|
};
|
|
|
|
template<typename T>
|
|
diff --git a/qtbase/src/corelib/global/qendian_p.h b/qtbase/src/corelib/global/qendian_p.h
|
|
index 5421a452d9..1b310a65b5 100644
|
|
--- a/qtbase/src/corelib/global/qendian_p.h
|
|
+++ b/qtbase/src/corelib/global/qendian_p.h
|
|
@@ -171,16 +171,16 @@ public:
|
|
operator Type() const noexcept
|
|
{
|
|
if (std::is_signed<Type>::value) {
|
|
- UnsignedType i = S::fromSpecial(storage->val);
|
|
+ UnsignedType i = S::fromSpecial(m_storage->val);
|
|
i <<= (sizeof(Type) * 8) - width - pos;
|
|
Type t = Type(i);
|
|
t >>= (sizeof(Type) * 8) - width;
|
|
return t;
|
|
}
|
|
- return (S::fromSpecial(storage->val) & mask()) >> pos;
|
|
+ return (S::fromSpecial(m_storage->val) & mask()) >> pos;
|
|
}
|
|
|
|
- bool operator!() const noexcept { return !(storage->val & S::toSpecial(mask())); }
|
|
+ bool operator!() const noexcept { return !(m_storage->val & S::toSpecial(mask())); }
|
|
|
|
static constexpr UnsignedType mask() noexcept
|
|
{
|
|
@@ -192,21 +192,21 @@ private:
|
|
friend class QSpecialIntegerBitfieldUnion;
|
|
friend class QSpecialIntegerAccessor<S, pos, width, T>;
|
|
|
|
- explicit QSpecialIntegerConstAccessor(Storage *storage) : storage(storage) {}
|
|
+ explicit QSpecialIntegerConstAccessor(Storage *storage) : m_storage(storage) {}
|
|
|
|
friend bool operator==(const QSpecialIntegerConstAccessor<S, pos, width, T> &i,
|
|
const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept
|
|
{
|
|
- return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) == 0;
|
|
+ return ((i.m_storage->val ^ j.m_storage->val) & S::toSpecial(mask())) == 0;
|
|
}
|
|
|
|
friend bool operator!=(const QSpecialIntegerConstAccessor<S, pos, width, T> &i,
|
|
const QSpecialIntegerConstAccessor<S, pos, width, T> &j) noexcept
|
|
{
|
|
- return ((i.storage->val ^ j.storage->val) & S::toSpecial(mask())) != 0;
|
|
+ return ((i.m_storage->val ^ j.m_storage->val) & S::toSpecial(mask())) != 0;
|
|
}
|
|
|
|
- Storage *storage;
|
|
+ Storage *m_storage;
|
|
};
|
|
|
|
template<class S, int pos, int width, class T>
|
|
@@ -224,22 +224,22 @@ public:
|
|
|
|
QSpecialIntegerAccessor &operator=(Type t)
|
|
{
|
|
- UnsignedType i = S::fromSpecial(storage->val);
|
|
+ UnsignedType i = S::fromSpecial(m_storage->val);
|
|
i &= ~Const::mask();
|
|
i |= (UnsignedType(t) << pos) & Const::mask();
|
|
- storage->val = S::toSpecial(i);
|
|
+ m_storage->val = S::toSpecial(i);
|
|
return *this;
|
|
}
|
|
|
|
- operator Const() { return Const(storage); }
|
|
+ operator Const() { return Const(m_storage); }
|
|
|
|
private:
|
|
template<class Storage, typename... Accessors>
|
|
friend class QSpecialIntegerBitfieldUnion;
|
|
|
|
- explicit QSpecialIntegerAccessor(Storage *storage) : storage(storage) {}
|
|
+ explicit QSpecialIntegerAccessor(Storage *storage) : m_storage(storage) {}
|
|
|
|
- Storage *storage;
|
|
+ Storage *m_storage;
|
|
};
|
|
|
|
template<class S, typename... Accessors>
|
|
diff --git a/qtbase/src/corelib/global/qglobal.cpp b/qtbase/src/corelib/global/qglobal.cpp
|
|
index 5ad82c259d..ecf7b1efaa 100644
|
|
--- a/qtbase/src/corelib/global/qglobal.cpp
|
|
+++ b/qtbase/src/corelib/global/qglobal.cpp
|
|
@@ -97,6 +97,10 @@
|
|
# include <private/qcore_mac_p.h>
|
|
#endif
|
|
|
|
+#if defined(Q_OS_MACOS)
|
|
+#include <QtCore/qversionnumber.h>
|
|
+#endif
|
|
+
|
|
#ifdef Q_OS_UNIX
|
|
#include <sys/utsname.h>
|
|
#include <private/qcore_unix_p.h>
|
|
@@ -2133,6 +2137,15 @@ QT_WARNING_POP
|
|
static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
|
|
{
|
|
#ifdef Q_OS_MACOS
|
|
+ if (version.majorVersion() == 13)
|
|
+ return "Ventura";
|
|
+ if (version.majorVersion() == 12)
|
|
+ return "Monterey";
|
|
+ // Compare against predefined constant to handle 10.16/11.0
|
|
+ if (QVersionNumber(QOperatingSystemVersion::MacOSBigSur.majorVersion(),
|
|
+ QOperatingSystemVersion::MacOSBigSur.minorVersion(), QOperatingSystemVersion::MacOSBigSur.microVersion()).isPrefixOf(
|
|
+ QVersionNumber(version.majorVersion(), version.minorVersion(), version.microVersion())))
|
|
+ return "Big Sur";
|
|
if (version.majorVersion() == 10) {
|
|
switch (version.minorVersion()) {
|
|
case 9:
|
|
@@ -2147,13 +2160,15 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
|
|
return "High Sierra";
|
|
case 14:
|
|
return "Mojave";
|
|
+ case 15:
|
|
+ return "Catalina";
|
|
}
|
|
}
|
|
// unknown, future version
|
|
#else
|
|
Q_UNUSED(version);
|
|
#endif
|
|
- return 0;
|
|
+ return nullptr;
|
|
}
|
|
#endif
|
|
|
|
@@ -2278,7 +2293,7 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
|
|
}
|
|
#undef Q_WINVER
|
|
// unknown, future version
|
|
- return 0;
|
|
+ return nullptr;
|
|
}
|
|
|
|
#endif
|
|
diff --git a/qtbase/src/corelib/global/qnamespace.h b/qtbase/src/corelib/global/qnamespace.h
|
|
index deab11f729..486b63fa3f 100644
|
|
--- a/qtbase/src/corelib/global/qnamespace.h
|
|
+++ b/qtbase/src/corelib/global/qnamespace.h
|
|
@@ -1867,7 +1867,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.h b/qtbase/src/corelib/global/qrandom.h
|
|
index 445b520c76..4c216eeb65 100644
|
|
--- a/qtbase/src/corelib/global/qrandom.h
|
|
+++ b/qtbase/src/corelib/global/qrandom.h
|
|
@@ -169,8 +169,8 @@ public:
|
|
void seed(quint32 s = 1) { *this = { s }; }
|
|
void seed(std::seed_seq &sseq) noexcept { *this = { sseq }; }
|
|
Q_CORE_EXPORT void discard(unsigned long long z);
|
|
- static Q_DECL_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
|
|
- static Q_DECL_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
|
|
+ static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
|
+ static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
|
|
|
static inline Q_DECL_CONST_FUNCTION QRandomGenerator *system();
|
|
static inline Q_DECL_CONST_FUNCTION QRandomGenerator *global();
|
|
@@ -245,8 +245,8 @@ public:
|
|
QRandomGenerator::discard(z * 2);
|
|
}
|
|
|
|
- static Q_DECL_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
|
|
- static Q_DECL_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
|
|
+ static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
|
+ static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
|
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system();
|
|
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global();
|
|
static Q_CORE_EXPORT QRandomGenerator64 securelySeeded();
|
|
diff --git a/qtbase/src/corelib/io/qfilesystemengine_win.cpp b/qtbase/src/corelib/io/qfilesystemengine_win.cpp
|
|
index 002f720926..e6f118a5c4 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/qsavefile_p.h b/qtbase/src/corelib/io/qsavefile_p.h
|
|
index 3f81df9ae2..81a662133a 100644
|
|
--- a/qtbase/src/corelib/io/qsavefile_p.h
|
|
+++ b/qtbase/src/corelib/io/qsavefile_p.h
|
|
@@ -51,7 +51,7 @@
|
|
// We mean it.
|
|
//
|
|
|
|
-#include <QtCore/qglobal.h>
|
|
+#include <QtCore/qsavefile.h>
|
|
|
|
#ifndef QT_NO_TEMPORARYFILE
|
|
|
|
diff --git a/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp
|
|
index 3d7fe43cd3..f2871a2da7 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);
|
|
|
|
@@ -3131,8 +3132,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();
|
|
@@ -3141,9 +3143,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/qdeadlinetimer.h b/qtbase/src/corelib/kernel/qdeadlinetimer.h
|
|
index 99e09eb31f..e0dcb8d3aa 100644
|
|
--- a/qtbase/src/corelib/kernel/qdeadlinetimer.h
|
|
+++ b/qtbase/src/corelib/kernel/qdeadlinetimer.h
|
|
@@ -66,7 +66,7 @@ public:
|
|
Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) noexcept
|
|
: t1(0), t2(0), type(type_) {}
|
|
Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept
|
|
- : t1(std::numeric_limits<qint64>::max()), t2(0), type(type_) {}
|
|
+ : t1((std::numeric_limits<qint64>::max)()), t2(0), type(type_) {}
|
|
explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
|
|
|
|
void swap(QDeadlineTimer &other) noexcept
|
|
diff --git a/qtbase/src/corelib/kernel/qobject_p.h b/qtbase/src/corelib/kernel/qobject_p.h
|
|
index 13ffb88999..325a974f30 100644
|
|
--- a/qtbase/src/corelib/kernel/qobject_p.h
|
|
+++ b/qtbase/src/corelib/kernel/qobject_p.h
|
|
@@ -220,7 +220,7 @@ public:
|
|
s = s->previous;
|
|
}
|
|
}
|
|
- Sender *previous;
|
|
+ Sender *previous = nullptr;
|
|
QObject *receiver;
|
|
QObject *sender;
|
|
int signal;
|
|
diff --git a/qtbase/src/corelib/kernel/qtranslator.cpp b/qtbase/src/corelib/kernel/qtranslator.cpp
|
|
index bdcd016630..e4375e7e40 100644
|
|
--- a/qtbase/src/corelib/kernel/qtranslator.cpp
|
|
+++ b/qtbase/src/corelib/kernel/qtranslator.cpp
|
|
@@ -907,7 +907,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..34591fc667 100644
|
|
--- a/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
|
|
+++ b/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
|
|
@@ -46,6 +46,9 @@
|
|
#include "qmimeprovider_p.h"
|
|
#include "qmimetype_p.h"
|
|
|
|
+#include <private/qduplicatetracker_p.h>
|
|
+#include <private/qfilesystementry_p.h>
|
|
+
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QFileInfo>
|
|
#include <QtCore/QSet>
|
|
@@ -389,20 +392,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;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -428,6 +434,7 @@ QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
|
|
bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
|
|
{
|
|
const QString resolvedParent = resolveAlias(parent);
|
|
+ QDuplicateTracker<QString> seen;
|
|
std::stack<QString, QStringList> toCheck;
|
|
toCheck.push(mime);
|
|
while (!toCheck.empty()) {
|
|
@@ -436,8 +443,11 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
|
|
const QString mimeName = toCheck.top();
|
|
toCheck.pop();
|
|
const auto parentList = parents(mimeName);
|
|
- for (const QString &par : parentList)
|
|
- toCheck.push(resolveAlias(par));
|
|
+ for (const QString &par : parentList) {
|
|
+ const QString resolvedPar = resolveAlias(par);
|
|
+ if (!seen.hasSeen(resolvedPar))
|
|
+ toCheck.push(resolvedPar);
|
|
+ }
|
|
}
|
|
return false;
|
|
}
|
|
diff --git a/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp b/qtbase/src/corelib/mimetypes/qmimeglobpattern.cpp
|
|
index b1de8907b2..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;
|
|
}
|
|
}
|
|
diff --git a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
|
|
index 258dddf8cb..5125704cf1 100644
|
|
--- a/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
|
|
+++ b/qtbase/src/corelib/mimetypes/qmimeprovider.cpp
|
|
@@ -242,21 +242,28 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM
|
|
return;
|
|
Q_ASSERT(m_cacheFile);
|
|
const QString lowerFileName = fileName.toLower();
|
|
+ int numMatches = 0;
|
|
// 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);
|
|
+ numMatches = matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), 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())
|
|
- matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
|
|
+ if (numMatches == 0) {
|
|
+ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
|
|
+ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
|
|
+ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
|
|
+ if (matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false)) {
|
|
+ ++numMatches;
|
|
+ } else if (matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true)) {
|
|
+ ++numMatches;
|
|
+ }
|
|
+ }
|
|
+ // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*")
|
|
+ if (numMatches == 0)
|
|
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
|
|
}
|
|
|
|
-void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
|
|
+int QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
|
|
{
|
|
+ int numMatches = 0;
|
|
const int numGlobs = cacheFile->getUint32(off);
|
|
//qDebug() << "Loading" << numGlobs << "globs from" << cacheFile->file.fileName() << "at offset" << cacheFile->globListOffset;
|
|
for (int i = 0; i < numGlobs; ++i) {
|
|
@@ -272,9 +279,12 @@ void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile
|
|
//qDebug() << pattern << mimeType << weight << caseSensitive;
|
|
QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
|
|
|
|
- if (glob.matchFileName(fileName))
|
|
+ if (glob.matchFileName(fileName)) {
|
|
result.addMatch(QLatin1String(mimeType), weight, pattern);
|
|
+ ++numMatches;
|
|
+ }
|
|
}
|
|
+ return numMatches;
|
|
}
|
|
|
|
bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBinaryProvider::CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck)
|
|
diff --git a/qtbase/src/corelib/mimetypes/qmimeprovider_p.h b/qtbase/src/corelib/mimetypes/qmimeprovider_p.h
|
|
index f9c8ef384c..5b328a7d5e 100644
|
|
--- a/qtbase/src/corelib/mimetypes/qmimeprovider_p.h
|
|
+++ b/qtbase/src/corelib/mimetypes/qmimeprovider_p.h
|
|
@@ -115,7 +115,7 @@ public:
|
|
private:
|
|
struct CacheFile;
|
|
|
|
- void matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
|
|
+ int matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
|
|
bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck);
|
|
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
|
|
QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
|
|
diff --git a/qtbase/src/corelib/mimetypes/qmimetype.cpp b/qtbase/src/corelib/mimetypes/qmimetype.cpp
|
|
index 0c0de63961..d6a351262b 100644
|
|
--- a/qtbase/src/corelib/mimetypes/qmimetype.cpp
|
|
+++ b/qtbase/src/corelib/mimetypes/qmimetype.cpp
|
|
@@ -376,14 +376,17 @@ QStringList QMimeType::parentMimeTypes() const
|
|
static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
|
|
{
|
|
const QStringList parents = QMimeDatabasePrivate::instance()->mimeParents(mime);
|
|
+ QStringList newParents;
|
|
for (const QString &parent : parents) {
|
|
// I would use QSet, but since order matters I better not
|
|
- if (!allParents.contains(parent))
|
|
+ if (!allParents.contains(parent)) {
|
|
allParents.append(parent);
|
|
+ newParents.append(parent);
|
|
+ }
|
|
}
|
|
// We want a breadth-first search, so that the least-specific parent (octet-stream) is last
|
|
// This means iterating twice, unfortunately.
|
|
- for (const QString &parent : parents)
|
|
+ for (const QString &parent : newParents)
|
|
collectParentMimeTypes(parent, allParents);
|
|
}
|
|
|
|
diff --git a/qtbase/src/corelib/plugin/qlibrary.cpp b/qtbase/src/corelib/plugin/qlibrary.cpp
|
|
index 5d2f024267..45b5a3fe27 100644
|
|
--- a/qtbase/src/corelib/plugin/qlibrary.cpp
|
|
+++ b/qtbase/src/corelib/plugin/qlibrary.cpp
|
|
@@ -526,7 +526,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
|
|
if (pHnd.loadRelaxed())
|
|
return;
|
|
|
|
- loadHintsInt.storeRelaxed(lh);
|
|
+ loadHintsInt.fetchAndOrRelaxed(lh);
|
|
}
|
|
|
|
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
|
@@ -538,6 +538,13 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
|
|
|
void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
|
|
{
|
|
+ // Set the load hints directly for a dummy if this object is not associated
|
|
+ // with a file. Such object is not shared between multiple instances.
|
|
+ if (fileName.isEmpty()) {
|
|
+ loadHintsInt.storeRelaxed(lh);
|
|
+ return;
|
|
+ }
|
|
+
|
|
// this locks a global mutex
|
|
QMutexLocker lock(&qt_library_mutex);
|
|
mergeLoadHints(lh);
|
|
@@ -1166,6 +1173,10 @@ QString QLibrary::errorString() const
|
|
lazy symbol resolution, and will not export external symbols for resolution
|
|
in other dynamically-loaded libraries.
|
|
|
|
+ \note Hints can only be cleared when this object is not associated with a
|
|
+ file. Hints can only be added once the file name is set (\a hints will
|
|
+ be or'ed with the old hints).
|
|
+
|
|
\note Setting this property after the library has been loaded has no effect
|
|
and loadHints() will not reflect those changes.
|
|
|
|
diff --git a/qtbase/src/corelib/plugin/qpluginloader.cpp b/qtbase/src/corelib/plugin/qpluginloader.cpp
|
|
index 0a63b93762..02b8c588be 100644
|
|
--- a/qtbase/src/corelib/plugin/qpluginloader.cpp
|
|
+++ b/qtbase/src/corelib/plugin/qpluginloader.cpp
|
|
@@ -105,6 +105,8 @@ QT_BEGIN_NAMESPACE
|
|
\sa QLibrary, {Plug & Paint Example}
|
|
*/
|
|
|
|
+static constexpr QLibrary::LoadHints defaultLoadHints = QLibrary::PreventUnloadHint;
|
|
+
|
|
/*!
|
|
\class QStaticPlugin
|
|
\inmodule QtCore
|
|
@@ -155,7 +157,7 @@ QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
|
|
: QObject(parent), d(nullptr), did_load(false)
|
|
{
|
|
setFileName(fileName);
|
|
- setLoadHints(QLibrary::PreventUnloadHint);
|
|
+ setLoadHints(defaultLoadHints);
|
|
}
|
|
|
|
/*!
|
|
@@ -357,7 +359,7 @@ static QString locatePlugin(const QString& fileName)
|
|
void QPluginLoader::setFileName(const QString &fileName)
|
|
{
|
|
#if defined(QT_SHARED)
|
|
- QLibrary::LoadHints lh = QLibrary::PreventUnloadHint;
|
|
+ QLibrary::LoadHints lh = defaultLoadHints;
|
|
if (d) {
|
|
lh = d->loadHints();
|
|
d->release();
|
|
@@ -414,15 +416,21 @@ QString QPluginLoader::errorString() const
|
|
void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
|
|
{
|
|
if (!d) {
|
|
- d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
|
|
+ d = QLibraryPrivate::findOrCreate({}, {}, loadHints); // ugly, but we need a d-ptr
|
|
d->errorString.clear();
|
|
+ } else {
|
|
+ d->setLoadHints(loadHints);
|
|
}
|
|
- d->setLoadHints(loadHints);
|
|
}
|
|
|
|
QLibrary::LoadHints QPluginLoader::loadHints() const
|
|
{
|
|
- return d ? d->loadHints() : QLibrary::LoadHints();
|
|
+ // Not having a d-pointer means that the user hasn't called
|
|
+ // setLoadHints() / setFileName() yet. In setFileName() we will
|
|
+ // then force defaultLoadHints on loading, so we must return them
|
|
+ // from here as well.
|
|
+
|
|
+ return d ? d->loadHints() : defaultLoadHints;
|
|
}
|
|
|
|
#endif // QT_CONFIG(library)
|
|
diff --git a/qtbase/src/corelib/serialization/qcborvalue.cpp b/qtbase/src/corelib/serialization/qcborvalue.cpp
|
|
index 89a928d348..3a8c2cb9ec 100644
|
|
--- a/qtbase/src/corelib/serialization/qcborvalue.cpp
|
|
+++ b/qtbase/src/corelib/serialization/qcborvalue.cpp
|
|
@@ -2123,7 +2123,8 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
|
|
Q_ASSERT(n == -1 || container == nullptr);
|
|
if (n < 0)
|
|
dd = container;
|
|
- return dd ? QCborArray(*dd) : defaultValue;
|
|
+ // return QCborArray(*dd); but that's UB if dd is nullptr
|
|
+ return dd ? QCborArray(*dd) : QCborArray();
|
|
}
|
|
|
|
/*!
|
|
@@ -2165,7 +2166,8 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
|
|
Q_ASSERT(n == -1 || container == nullptr);
|
|
if (n < 0)
|
|
dd = container;
|
|
- return dd ? QCborMap(*dd) : defaultValue;
|
|
+ // return QCborMap(*dd); but that's UB if dd is nullptr
|
|
+ return dd ? QCborMap(*dd) : QCborMap();
|
|
}
|
|
|
|
/*!
|
|
diff --git a/qtbase/src/corelib/serialization/qtextstream_p.h b/qtbase/src/corelib/serialization/qtextstream_p.h
|
|
index 172824d27d..994e2da1a0 100644
|
|
--- a/qtbase/src/corelib/serialization/qtextstream_p.h
|
|
+++ b/qtbase/src/corelib/serialization/qtextstream_p.h
|
|
@@ -73,14 +73,14 @@ public:
|
|
disconnect();
|
|
if (device)
|
|
connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
|
|
- this->stream = stream;
|
|
+ m_stream = stream;
|
|
}
|
|
|
|
public Q_SLOTS:
|
|
- inline void flushStream() { stream->flush(); }
|
|
+ void flushStream() { m_stream->flush(); }
|
|
|
|
private:
|
|
- QTextStream *stream;
|
|
+ QTextStream *m_stream;
|
|
};
|
|
#endif
|
|
|
|
diff --git a/qtbase/src/corelib/serialization/qxmlstream.g b/qtbase/src/corelib/serialization/qxmlstream.g
|
|
index 8c6a1a5887..18fbf14c03 100644
|
|
--- a/qtbase/src/corelib/serialization/qxmlstream.g
|
|
+++ b/qtbase/src/corelib/serialization/qxmlstream.g
|
|
@@ -1512,8 +1512,8 @@ attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute
|
|
attribute ::= qname space_opt EQ space_opt attribute_value;
|
|
/.
|
|
case $rule_number: {
|
|
- QStringRef prefix = symPrefix(1);
|
|
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
|
|
+ const QStringRef prfx = symPrefix(1);
|
|
+ if (prfx.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
|
|
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
|
|
namespaceDeclaration.prefix.clear();
|
|
|
|
@@ -1563,7 +1563,7 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
|
|
attribute.value.pos = pos;
|
|
attribute.value.len = n;
|
|
}
|
|
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
|
|
+ if (prfx == QLatin1String("xmlns") && namespaceProcessing) {
|
|
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
|
|
QStringRef namespacePrefix = symString(attribute.key);
|
|
QStringRef namespaceUri = symString(attribute.value);
|
|
diff --git a/qtbase/src/corelib/serialization/qxmlstream_p.h b/qtbase/src/corelib/serialization/qxmlstream_p.h
|
|
index be7b1fe665..fd8fcca4e1 100644
|
|
--- a/qtbase/src/corelib/serialization/qxmlstream_p.h
|
|
+++ b/qtbase/src/corelib/serialization/qxmlstream_p.h
|
|
@@ -1722,8 +1722,8 @@ bool QXmlStreamReaderPrivate::parse()
|
|
break;
|
|
|
|
case 229: {
|
|
- QStringRef prefix = symPrefix(1);
|
|
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
|
|
+ const QStringRef prfx = symPrefix(1);
|
|
+ if (prfx.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
|
|
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
|
|
namespaceDeclaration.prefix.clear();
|
|
|
|
@@ -1773,7 +1773,7 @@ bool QXmlStreamReaderPrivate::parse()
|
|
attribute.value.pos = pos;
|
|
attribute.value.len = n;
|
|
}
|
|
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
|
|
+ if (prfx == QLatin1String("xmlns") && namespaceProcessing) {
|
|
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
|
|
QStringRef namespacePrefix = symString(attribute.key);
|
|
QStringRef namespaceUri = symString(attribute.value);
|
|
diff --git a/qtbase/src/corelib/text/qbytearray.h b/qtbase/src/corelib/text/qbytearray.h
|
|
index f4c335ca93..e1bcdc3e68 100644
|
|
--- a/qtbase/src/corelib/text/qbytearray.h
|
|
+++ b/qtbase/src/corelib/text/qbytearray.h
|
|
@@ -102,8 +102,10 @@ Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len);
|
|
Q_CORE_EXPORT int qstrnicmp(const char *, qsizetype, const char *, qsizetype = -1);
|
|
|
|
// implemented in qvsnprintf.cpp
|
|
-Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
|
|
-Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
|
|
+Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
|
+ Q_ATTRIBUTE_FORMAT_PRINTF(3, 0);
|
|
+Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...)
|
|
+ Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
|
|
|
|
// qChecksum: Internet checksum
|
|
Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len); // ### Qt 6: Remove
|
|
diff --git a/qtbase/src/corelib/text/qlocale_data_p.h b/qtbase/src/corelib/text/qlocale_data_p.h
|
|
index c5e6a0d461..c613e4e537 100644
|
|
--- a/qtbase/src/corelib/text/qlocale_data_p.h
|
|
+++ b/qtbase/src/corelib/text/qlocale_data_p.h
|
|
@@ -1340,7 +1340,7 @@ static const QLocaleData locale_data[] = {
|
|
{ 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 166,5 , 166,5 , 176,5 , 176,5 , 415,8 , 402,13 , 209,6 , 226,13 , 2022,21 , 1980,28 , 2008,14 , 2022,21 , 1980,28 , 2008,14 , 58,2 , 55,2 , 283,3 , 5,17 , 22,23 , {77,79,80}, 137,4 , 3174,13 , 4,4 , 13,6 , 589,4 , 602,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
|
|
{ 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 166,5 , 166,5 , 171,5 , 171,5 , 394,8 , 423,14 , 209,6 , 226,13 , 2022,21 , 1980,28 , 2008,14 , 2022,21 , 1980,28 , 2008,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 6,1 , 3187,13 , 4,4 , 13,6 , 589,4 , 611,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
|
|
{ 26, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Corsican/Latin/France
|
|
- { 27, 7, 54, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 159,7 , 159,7 , 437,13 , 450,19 , 37,5 , 87,12 , 2043,28 , 2071,58 , 2129,14 , 2043,28 , 2071,58 , 2143,14 , 0,2 , 0,2 , 286,7 , 5,17 , 22,23 , {72,82,75}, 141,3 , 3200,60 , 19,5 , 4,0 , 613,8 , 621,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
|
|
+ { 27, 7, 54, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 159,7 , 159,7 , 437,13 , 450,19 , 37,5 , 87,12 , 2043,28 , 2071,58 , 2129,14 , 2043,28 , 2071,58 , 2143,14 , 0,2 , 0,2 , 286,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 19,5 , 4,0 , 613,8 , 621,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
|
|
{ 27, 7, 27, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 159,7 , 159,7 , 469,9 , 450,19 , 37,5 , 87,12 , 2043,28 , 2071,58 , 2143,14 , 2043,28 , 2071,58 , 2143,14 , 0,2 , 0,2 , 286,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 3260,85 , 19,5 , 4,0 , 613,8 , 629,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina
|
|
{ 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 181,7 , 181,7 , 156,8 , 478,17 , 55,4 , 59,9 , 2157,21 , 2178,49 , 2227,14 , 2157,21 , 2178,49 , 2227,14 , 60,4 , 57,4 , 293,5 , 5,17 , 22,23 , {67,90,75}, 146,2 , 3345,68 , 19,5 , 4,0 , 648,7 , 655,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic
|
|
{ 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 188,8 , 188,8 , 495,10 , 505,23 , 239,5 , 244,10 , 2241,28 , 2269,51 , 2320,14 , 2334,35 , 2269,51 , 2320,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 148,3 , 3413,42 , 19,5 , 4,0 , 660,5 , 665,7 , 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark
|
|
diff --git a/qtbase/src/corelib/text/qlocale_p.h b/qtbase/src/corelib/text/qlocale_p.h
|
|
index 322eca4362..bcf400527a 100644
|
|
--- a/qtbase/src/corelib/text/qlocale_p.h
|
|
+++ b/qtbase/src/corelib/text/qlocale_p.h
|
|
@@ -256,7 +256,7 @@ public:
|
|
{
|
|
if (qIsInf(d))
|
|
return float(d);
|
|
- if (std::fabs(d) > std::numeric_limits<float>::max()) {
|
|
+ if (std::fabs(d) > double{(std::numeric_limits<float>::max)()}) {
|
|
if (ok)
|
|
*ok = false;
|
|
const float huge = std::numeric_limits<float>::infinity();
|
|
diff --git a/qtbase/src/corelib/text/qstringiterator_p.h b/qtbase/src/corelib/text/qstringiterator_p.h
|
|
index b31c7673c2..731a241407 100644
|
|
--- a/qtbase/src/corelib/text/qstringiterator_p.h
|
|
+++ b/qtbase/src/corelib/text/qstringiterator_p.h
|
|
@@ -123,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(pos < e && 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(pos + 1 < e && pos[1].isLowSurrogate());
|
|
return QChar::surrogateToUcs4(pos[0], pos[1]);
|
|
+ }
|
|
|
|
return pos->unicode();
|
|
}
|
|
@@ -158,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(pos < e && pos->isLowSurrogate());
|
|
return QChar::surrogateToUcs4(cur, *pos++);
|
|
+ }
|
|
return cur.unicode();
|
|
}
|
|
|
|
@@ -199,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(pos > i && 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(pos > i + 1 && pos[-2].isHighSurrogate());
|
|
return QChar::surrogateToUcs4(pos[-2], pos[-1]);
|
|
+ }
|
|
return pos[-1].unicode();
|
|
}
|
|
|
|
@@ -233,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(pos > i && pos[-1].isHighSurrogate());
|
|
return QChar::surrogateToUcs4(*--pos, cur);
|
|
+ }
|
|
return cur.unicode();
|
|
}
|
|
|
|
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/qfutureinterface.h b/qtbase/src/corelib/thread/qfutureinterface.h
|
|
index e4cc46e929..5a39bb8a90 100644
|
|
--- a/qtbase/src/corelib/thread/qfutureinterface.h
|
|
+++ b/qtbase/src/corelib/thread/qfutureinterface.h
|
|
@@ -281,7 +281,7 @@ template <>
|
|
class QFutureInterface<void> : public QFutureInterfaceBase
|
|
{
|
|
public:
|
|
- explicit QFutureInterface<void>(State initialState = NoState)
|
|
+ explicit QFutureInterface(State initialState = NoState)
|
|
: QFutureInterfaceBase(initialState)
|
|
{ }
|
|
|
|
diff --git a/qtbase/src/corelib/thread/qfuturewatcher_p.h b/qtbase/src/corelib/thread/qfuturewatcher_p.h
|
|
index ead247b040..2911e0fafe 100644
|
|
--- a/qtbase/src/corelib/thread/qfuturewatcher_p.h
|
|
+++ b/qtbase/src/corelib/thread/qfuturewatcher_p.h
|
|
@@ -51,6 +51,8 @@
|
|
// We mean it.
|
|
//
|
|
|
|
+#include <QtCore/qfuturewatcher.h>
|
|
+
|
|
#include "qfutureinterface_p.h"
|
|
#include <qlist.h>
|
|
|
|
@@ -60,7 +62,6 @@ QT_REQUIRE_CONFIG(future);
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
-class QFutureWatcherBase;
|
|
class QFutureWatcherBasePrivate : public QObjectPrivate,
|
|
public QFutureCallOutInterface
|
|
{
|
|
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/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/qtimezoneprivate_p.h b/qtbase/src/corelib/time/qtimezoneprivate_p.h
|
|
index cf2a690f50..fb9fb1528b 100644
|
|
--- a/qtbase/src/corelib/time/qtimezoneprivate_p.h
|
|
+++ b/qtbase/src/corelib/time/qtimezoneprivate_p.h
|
|
@@ -137,10 +137,10 @@ public:
|
|
virtual void serialize(QDataStream &ds) const;
|
|
|
|
// Static Utility Methods
|
|
- static inline qint64 maxMSecs() { return std::numeric_limits<qint64>::max(); }
|
|
- static inline qint64 minMSecs() { return std::numeric_limits<qint64>::min() + 1; }
|
|
- static inline qint64 invalidMSecs() { return std::numeric_limits<qint64>::min(); }
|
|
- static inline qint64 invalidSeconds() { return std::numeric_limits<int>::min(); }
|
|
+ static inline qint64 maxMSecs() { return (std::numeric_limits<qint64>::max)(); }
|
|
+ static inline qint64 minMSecs() { return (std::numeric_limits<qint64>::min)() + 1; }
|
|
+ static inline qint64 invalidMSecs() { return (std::numeric_limits<qint64>::min)(); }
|
|
+ static inline qint64 invalidSeconds() { return (std::numeric_limits<int>::min)(); }
|
|
static Data invalidData();
|
|
static QTimeZone::OffsetData invalidOffsetData();
|
|
static QTimeZone::OffsetData toOffsetData(const Data &data);
|
|
diff --git a/qtbase/src/corelib/tools/qbitarray.h b/qtbase/src/corelib/tools/qbitarray.h
|
|
index eaed17413d..7934b55164 100644
|
|
--- a/qtbase/src/corelib/tools/qbitarray.h
|
|
+++ b/qtbase/src/corelib/tools/qbitarray.h
|
|
@@ -84,9 +84,9 @@ public:
|
|
bool toggleBit(int i);
|
|
|
|
bool at(int i) const;
|
|
- QBitRef operator[](int i);
|
|
+ inline QBitRef operator[](int i);
|
|
bool operator[](int i) const;
|
|
- QBitRef operator[](uint i);
|
|
+ inline QBitRef operator[](uint i);
|
|
bool operator[](uint i) const;
|
|
|
|
QBitArray& operator&=(const QBitArray &);
|
|
@@ -156,9 +156,9 @@ public:
|
|
QBitRef& operator=(bool val) { a.setBit(i, val); return *this; }
|
|
};
|
|
|
|
-inline QBitRef QBitArray::operator[](int i)
|
|
+QBitRef QBitArray::operator[](int i)
|
|
{ Q_ASSERT(i >= 0); return QBitRef(*this, i); }
|
|
-inline QBitRef QBitArray::operator[](uint i)
|
|
+QBitRef QBitArray::operator[](uint i)
|
|
{ return QBitRef(*this, i); }
|
|
|
|
|
|
diff --git a/qtbase/src/corelib/tools/qduplicatetracker_p.h b/qtbase/src/corelib/tools/qduplicatetracker_p.h
|
|
index 68284fb916..140fc31a34 100644
|
|
--- a/qtbase/src/corelib/tools/qduplicatetracker_p.h
|
|
+++ b/qtbase/src/corelib/tools/qduplicatetracker_p.h
|
|
@@ -52,7 +52,7 @@
|
|
|
|
#include <qglobal.h>
|
|
|
|
-#if QT_HAS_INCLUDE(<memory_resource>) && __cplusplus > 201402L
|
|
+#if defined(__cpp_lib_memory_resource) && __cplusplus > 201402L
|
|
# include <unordered_set>
|
|
# include <memory_resource>
|
|
#else
|
|
@@ -78,7 +78,7 @@ class QDuplicateTracker {
|
|
QSet<T> set = makeQSet();
|
|
int setSize = 0;
|
|
#endif
|
|
- Q_DISABLE_COPY_MOVE(QDuplicateTracker);
|
|
+ Q_DISABLE_COPY_MOVE(QDuplicateTracker)
|
|
public:
|
|
QDuplicateTracker() = default;
|
|
void reserve(int n) { set.reserve(n); }
|
|
diff --git a/qtbase/src/dbus/qdbusintegrator.cpp b/qtbase/src/dbus/qdbusintegrator.cpp
|
|
index a4cbfecc98..9ccbbbb37d 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
|
|
diff --git a/qtbase/src/gui/configure.json b/qtbase/src/gui/configure.json
|
|
index ed6e419f49..1f0e0534a5 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/itemmodels/qstandarditemmodel.cpp b/qtbase/src/gui/itemmodels/qstandarditemmodel.cpp
|
|
index fc9424763e..a3e0853fa8 100644
|
|
--- a/qtbase/src/gui/itemmodels/qstandarditemmodel.cpp
|
|
+++ b/qtbase/src/gui/itemmodels/qstandarditemmodel.cpp
|
|
@@ -3113,13 +3113,13 @@ QStringList QStandardItemModel::mimeTypes() const
|
|
*/
|
|
QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
|
|
{
|
|
- QMimeData *data = QAbstractItemModel::mimeData(indexes);
|
|
- if(!data)
|
|
+ std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes));
|
|
+ if (!data)
|
|
return nullptr;
|
|
|
|
const QString format = qStandardItemModelDataListMimeType();
|
|
if (!mimeTypes().contains(format))
|
|
- return data;
|
|
+ return data.release();
|
|
QByteArray encoded;
|
|
QDataStream stream(&encoded, QIODevice::WriteOnly);
|
|
|
|
@@ -3172,7 +3172,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
|
|
}
|
|
|
|
data->setData(format, encoded);
|
|
- return data;
|
|
+ return data.release();
|
|
}
|
|
|
|
|
|
diff --git a/qtbase/src/gui/kernel/qhighdpiscaling.cpp b/qtbase/src/gui/kernel/qhighdpiscaling.cpp
|
|
index 85ff58c14c..a433e94c22 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 56cd2d02bc..d448429f6c 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 a11388fdb6..aed480e875 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 990272b0c2..d371dd60ab 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/kernel/qshapedpixmapdndwindow.cpp b/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
|
|
index bb0d8e4ee7..b98fcc61e7 100644
|
|
--- a/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
|
|
+++ b/qtbase/src/gui/kernel/qshapedpixmapdndwindow.cpp
|
|
@@ -56,7 +56,7 @@ QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen)
|
|
QSurfaceFormat format;
|
|
format.setAlphaBufferSize(8);
|
|
setFormat(format);
|
|
- setFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint
|
|
+ setFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint
|
|
| Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
|
|
}
|
|
|
|
diff --git a/qtbase/src/gui/kernel/qwindow.cpp b/qtbase/src/gui/kernel/qwindow.cpp
|
|
index fa3a0243a6..c2f7dc6776 100644
|
|
--- a/qtbase/src/gui/kernel/qwindow.cpp
|
|
+++ b/qtbase/src/gui/kernel/qwindow.cpp
|
|
@@ -644,7 +644,7 @@ bool QWindow::isVisible() const
|
|
into an actual native surface. However, the window remains hidden until setVisible() is called.
|
|
|
|
Note that it is not usually necessary to call this function directly, as it will be implicitly
|
|
- called by show(), setVisible(), and other functions that require access to the platform
|
|
+ called by show(), setVisible(), winId(), and other functions that require access to the platform
|
|
resources.
|
|
|
|
Call destroy() to free the platform resources if necessary.
|
|
diff --git a/qtbase/src/gui/opengl/qopengltexture.cpp b/qtbase/src/gui/opengl/qopengltexture.cpp
|
|
index 5490ad8025..afd3d8dbe6 100644
|
|
--- a/qtbase/src/gui/opengl/qopengltexture.cpp
|
|
+++ b/qtbase/src/gui/opengl/qopengltexture.cpp
|
|
@@ -3725,6 +3725,12 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
|
|
return;
|
|
}
|
|
|
|
+ QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
|
|
+ if (glImage.isNull()) {
|
|
+ qWarning("QOpenGLTexture::setData() failed to convert image");
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (context->isOpenGLES() && context->format().majorVersion() < 3)
|
|
setFormat(QOpenGLTexture::RGBAFormat);
|
|
else
|
|
@@ -3735,7 +3741,6 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
|
|
allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
|
|
|
|
// Upload pixel data and generate mipmaps
|
|
- QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
|
|
QOpenGLPixelTransferOptions uploadOptions;
|
|
uploadOptions.setAlignment(1);
|
|
setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions);
|
|
diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp
|
|
index 38bad9a6b0..a04160791b 100644
|
|
--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp
|
|
+++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp
|
|
@@ -3462,16 +3462,18 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSp
|
|
// Boundaries
|
|
int w = image.width();
|
|
int h = image.height();
|
|
- int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height());
|
|
- int ymin = qMax(qRound(pos.y()), 0);
|
|
- int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width());
|
|
- int xmin = qMax(qRound(pos.x()), 0);
|
|
+ int px = qRound(pos.x());
|
|
+ int py = qRound(pos.y());
|
|
+ int ymax = qMin(py + h, d->rasterBuffer->height());
|
|
+ int ymin = qMax(py, 0);
|
|
+ int xmax = qMin(px + w, d->rasterBuffer->width());
|
|
+ int xmin = qMax(px, 0);
|
|
|
|
- int x_offset = xmin - qRound(pos.x());
|
|
+ int x_offset = xmin - px;
|
|
|
|
QImage::Format format = image.format();
|
|
for (int y = ymin; y < ymax; ++y) {
|
|
- const uchar *src = image.scanLine(y - qRound(pos.y()));
|
|
+ const uchar *src = image.scanLine(y - py);
|
|
if (format == QImage::Format_MonoLSB) {
|
|
for (int x = 0; x < xmax - xmin; ++x) {
|
|
int src_x = x + x_offset;
|
|
@@ -3860,7 +3862,7 @@ void QClipData::initialize()
|
|
return;
|
|
|
|
if (!m_clipLines)
|
|
- m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
|
|
+ m_clipLines = (ClipLine *)calloc(clipSpanHeight, sizeof(ClipLine));
|
|
|
|
Q_CHECK_PTR(m_clipLines);
|
|
QT_TRY {
|
|
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/qpathsimplifier.cpp b/qtbase/src/gui/painting/qpathsimplifier.cpp
|
|
index 256a2fefe7..60018c1857 100644
|
|
--- a/qtbase/src/gui/painting/qpathsimplifier.cpp
|
|
+++ b/qtbase/src/gui/painting/qpathsimplifier.cpp
|
|
@@ -164,11 +164,15 @@ QPoint IntersectionPoint::round() const
|
|
|
|
// Return positive value if 'p' is to the right of the line 'v1'->'v2', negative if left of the
|
|
// line and zero if exactly on the line.
|
|
-// The returned value is the z-component of the qCross product between 'v2-v1' and 'p-v1',
|
|
-// which is twice the signed area of the triangle 'p'->'v1'->'v2' (positive for CW order).
|
|
-inline int pointDistanceFromLine(const QPoint &p, const QPoint &v1, const QPoint &v2)
|
|
+// The returned value is the sign of the cross product between 'v2-v1' and 'p-v1'.
|
|
+inline int pointSideOfLine(const QPoint &p, const QPoint &v1, const QPoint &v2)
|
|
{
|
|
- return cross(v2 - v1, p - v1);
|
|
+ qint64 ux = qint64(v2.x()) - v1.x();
|
|
+ qint64 uy = qint64(v2.y()) - v1.y();
|
|
+ qint64 vx = qint64(p.x()) - v1.x();
|
|
+ qint64 vy = qint64(p.y()) - v1.y();
|
|
+ qint64 c = (ux * vy) - (uy * vx);
|
|
+ return (c > 0) ? 1 : (c < 0) ? -1 : 0;
|
|
}
|
|
|
|
IntersectionPoint intersectionPoint(const QPoint &u1, const QPoint &u2,
|
|
@@ -345,7 +349,7 @@ private:
|
|
|
|
void initElements(const QVectorPath &path, const QTransform &matrix);
|
|
void removeIntersections();
|
|
- void connectElements();
|
|
+ bool connectElements();
|
|
void fillIndices();
|
|
BVHNode *buildTree(Element **elements, int elementCount);
|
|
bool intersectNodes(QDataBuffer<Element *> &elements, BVHNode *elementNode, BVHNode *treeNode);
|
|
@@ -490,11 +494,17 @@ PathSimplifier::PathSimplifier(const QVectorPath &path, QDataBuffer<QPoint> &ver
|
|
{
|
|
m_points->reset();
|
|
m_indices->reset();
|
|
+ bool ok = true;
|
|
initElements(path, matrix);
|
|
if (!m_elements.isEmpty()) {
|
|
removeIntersections();
|
|
- connectElements();
|
|
- fillIndices();
|
|
+ ok = connectElements();
|
|
+ if (ok)
|
|
+ fillIndices();
|
|
+ }
|
|
+ if (!ok) {
|
|
+ m_points->reset();
|
|
+ m_indices->reset();
|
|
}
|
|
}
|
|
|
|
@@ -679,7 +689,7 @@ void PathSimplifier::removeIntersections()
|
|
m_bvh.free(); // The bounding volume hierarchy is not needed anymore.
|
|
}
|
|
|
|
-void PathSimplifier::connectElements()
|
|
+bool PathSimplifier::connectElements()
|
|
{
|
|
Q_ASSERT(!m_elements.isEmpty());
|
|
QDataBuffer<Event> events(m_elements.size() * 2);
|
|
@@ -859,7 +869,8 @@ void PathSimplifier::connectElements()
|
|
}
|
|
|
|
if (!orderedElements.isEmpty()) {
|
|
- Q_ASSERT((orderedElements.size() & 1) == 0);
|
|
+ if (orderedElements.size() & 1) // Unexpected path structure
|
|
+ return false;
|
|
int i = 0;
|
|
Element *firstElement = orderedElements.at(0);
|
|
if (m_points->at(firstElement->indices[0]) != eventPoint) {
|
|
@@ -885,6 +896,7 @@ void PathSimplifier::connectElements()
|
|
Q_ASSERT((element->next == 0) == (element->previous == 0));
|
|
}
|
|
#endif
|
|
+ return true;
|
|
}
|
|
|
|
void PathSimplifier::fillIndices()
|
|
@@ -1420,19 +1432,19 @@ bool PathSimplifier::elementIsLeftOf(const Element *left, const Element *right)
|
|
return true;
|
|
if (leftU.x() > qMax(rightL.x(), rightU.x()))
|
|
return false;
|
|
- int d = pointDistanceFromLine(leftU, rightL, rightU);
|
|
+ int d = pointSideOfLine(leftU, rightL, rightU);
|
|
// d < 0: left, d > 0: right, d == 0: on top
|
|
if (d == 0) {
|
|
- d = pointDistanceFromLine(leftL, rightL, rightU);
|
|
+ d = pointSideOfLine(leftL, rightL, rightU);
|
|
if (d == 0) {
|
|
if (right->degree > Element::Line) {
|
|
- d = pointDistanceFromLine(leftL, rightL, m_points->at(right->indices[1]));
|
|
+ d = pointSideOfLine(leftL, rightL, m_points->at(right->indices[1]));
|
|
if (d == 0)
|
|
- d = pointDistanceFromLine(leftL, rightL, m_points->at(right->indices[2]));
|
|
+ d = pointSideOfLine(leftL, rightL, m_points->at(right->indices[2]));
|
|
} else if (left->degree > Element::Line) {
|
|
- d = pointDistanceFromLine(m_points->at(left->indices[1]), rightL, rightU);
|
|
+ d = pointSideOfLine(m_points->at(left->indices[1]), rightL, rightU);
|
|
if (d == 0)
|
|
- d = pointDistanceFromLine(m_points->at(left->indices[2]), rightL, rightU);
|
|
+ d = pointSideOfLine(m_points->at(left->indices[2]), rightL, rightU);
|
|
}
|
|
}
|
|
}
|
|
@@ -1452,13 +1464,13 @@ QPair<PathSimplifier::RBNode *, PathSimplifier::RBNode *> PathSimplifier::outerB
|
|
Q_ASSERT(point >= v2 && point <= v1);
|
|
if (point == v1 || point == v2)
|
|
break;
|
|
- int d = pointDistanceFromLine(point, v1, v2);
|
|
+ int d = pointSideOfLine(point, v1, v2);
|
|
if (d == 0) {
|
|
if (element->degree == Element::Line)
|
|
break;
|
|
- d = pointDistanceFromLine(point, v1, m_points->at(element->indices[1]));
|
|
+ d = pointSideOfLine(point, v1, m_points->at(element->indices[1]));
|
|
if (d == 0)
|
|
- d = pointDistanceFromLine(point, v1, m_points->at(element->indices[2]));
|
|
+ d = pointSideOfLine(point, v1, m_points->at(element->indices[2]));
|
|
Q_ASSERT(d != 0);
|
|
}
|
|
if (d < 0) {
|
|
@@ -1484,7 +1496,7 @@ QPair<PathSimplifier::RBNode *, PathSimplifier::RBNode *> PathSimplifier::outerB
|
|
Q_ASSERT(point >= v2 && point <= v1);
|
|
bool equal = (point == v1 || point == v2);
|
|
if (!equal) {
|
|
- int d = pointDistanceFromLine(point, v1, v2);
|
|
+ int d = pointSideOfLine(point, v1, v2);
|
|
Q_ASSERT(d >= 0);
|
|
equal = (d == 0 && element->degree == Element::Line);
|
|
}
|
|
@@ -1505,7 +1517,7 @@ QPair<PathSimplifier::RBNode *, PathSimplifier::RBNode *> PathSimplifier::outerB
|
|
Q_ASSERT(point >= v2 && point <= v1);
|
|
bool equal = (point == v1 || point == v2);
|
|
if (!equal) {
|
|
- int d = pointDistanceFromLine(point, v1, v2);
|
|
+ int d = pointSideOfLine(point, v1, v2);
|
|
Q_ASSERT(d <= 0);
|
|
equal = (d == 0 && element->degree == Element::Line);
|
|
}
|
|
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/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/qdistancefield.cpp b/qtbase/src/gui/text/qdistancefield.cpp
|
|
index c843e3b706..71d9763210 100644
|
|
--- a/qtbase/src/gui/text/qdistancefield.cpp
|
|
+++ b/qtbase/src/gui/text/qdistancefield.cpp
|
|
@@ -508,6 +508,11 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path
|
|
QDataBuffer<quint32> pathIndices(0);
|
|
QDataBuffer<QPoint> pathVertices(0);
|
|
qSimplifyPath(path, pathVertices, pathIndices, transform);
|
|
+ if (pathVertices.isEmpty()) {
|
|
+ qCWarning(lcDistanceField) << "Unexpected glyph path structure, bailing out";
|
|
+ memset(data->data, 0, data->nbytes);
|
|
+ return;
|
|
+ }
|
|
|
|
const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5
|
|
const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5
|
|
diff --git a/qtbase/src/gui/text/qfontdatabase.cpp b/qtbase/src/gui/text/qfontdatabase.cpp
|
|
index 2011f935a9..7aa6228948 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/qtextengine.cpp b/qtbase/src/gui/text/qtextengine.cpp
|
|
index 6336fadf74..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.
|
|
diff --git a/qtbase/src/gui/text/qtextlayout.cpp b/qtbase/src/gui/text/qtextlayout.cpp
|
|
index 70f6ab285b..a0c847459c 100644
|
|
--- a/qtbase/src/gui/text/qtextlayout.cpp
|
|
+++ b/qtbase/src/gui/text/qtextlayout.cpp
|
|
@@ -1336,13 +1336,16 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
|
|
bool rightToLeft = d->isRightToLeft();
|
|
if (itm >= 0) {
|
|
const QScriptItem &si = d->layoutData->items.at(itm);
|
|
- if (si.ascent >= 0)
|
|
- base = si.ascent;
|
|
- if (si.descent >= 0)
|
|
- descent = si.descent;
|
|
+ // objects need some special treatment as they can have special alignment or be floating
|
|
+ if (si.analysis.flags != QScriptAnalysis::Object) {
|
|
+ if (si.ascent > 0)
|
|
+ base = si.ascent;
|
|
+ if (si.descent > 0)
|
|
+ descent = si.descent;
|
|
+ }
|
|
rightToLeft = si.analysis.bidiLevel % 2;
|
|
}
|
|
- qreal y = position.y() + (sl.y + sl.base() + sl.descent - base - descent).toReal();
|
|
+ qreal y = position.y() + (sl.y + sl.base() - base).toReal();
|
|
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
|
|
&& (p->transform().type() > QTransform::TxTranslate);
|
|
if (toggleAntialiasing)
|
|
diff --git a/qtbase/src/gui/util/qktxhandler.cpp b/qtbase/src/gui/util/qktxhandler.cpp
|
|
index 7eda4c46fb..2853e46c3d 100644
|
|
--- a/qtbase/src/gui/util/qktxhandler.cpp
|
|
+++ b/qtbase/src/gui/util/qktxhandler.cpp
|
|
@@ -73,7 +73,7 @@ struct KTXHeader {
|
|
quint32 bytesOfKeyValueData;
|
|
};
|
|
|
|
-static const quint32 headerSize = sizeof(KTXHeader);
|
|
+static constexpr quint32 qktxh_headerSize = sizeof(KTXHeader);
|
|
|
|
// Currently unused, declared for future reference
|
|
struct KTXKeyValuePairItem {
|
|
@@ -103,11 +103,36 @@ struct KTXMipmapLevel {
|
|
*/
|
|
};
|
|
|
|
-bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
|
|
+static bool qAddOverflow(quint32 v1, quint32 v2, quint32 *r) {
|
|
+ // unsigned additions are well-defined
|
|
+ *r = v1 + v2;
|
|
+ return v1 > quint32(v1 + v2);
|
|
+}
|
|
+
|
|
+// Returns the nearest multiple of 4 greater than or equal to 'value'
|
|
+static bool nearestMultipleOf4(quint32 value, quint32 *result)
|
|
+{
|
|
+ constexpr quint32 rounding = 4;
|
|
+ *result = 0;
|
|
+ if (qAddOverflow(value, rounding - 1, result))
|
|
+ return true;
|
|
+ *result &= ~(rounding - 1);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// Returns a slice with prechecked bounds
|
|
+static QByteArray safeSlice(const QByteArray& array, quint32 start, quint32 length)
|
|
{
|
|
- Q_UNUSED(suffix)
|
|
+ quint32 end = 0;
|
|
+ if (qAddOverflow(start, length, &end) || end > quint32(array.length()))
|
|
+ return {};
|
|
+ return QByteArray(array.data() + start, length);
|
|
+}
|
|
|
|
- return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0);
|
|
+bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
|
|
+{
|
|
+ Q_UNUSED(suffix);
|
|
+ return block.startsWith(QByteArray::fromRawData(ktxIdentifier, KTX_IDENTIFIER_LENGTH));
|
|
}
|
|
|
|
QTextureFileData QKtxHandler::read()
|
|
@@ -115,42 +140,97 @@ QTextureFileData QKtxHandler::read()
|
|
if (!device())
|
|
return QTextureFileData();
|
|
|
|
- QByteArray buf = device()->readAll();
|
|
- const quint32 dataSize = quint32(buf.size());
|
|
- if (dataSize < headerSize || !canRead(QByteArray(), buf)) {
|
|
- qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
|
|
+ const QByteArray buf = device()->readAll();
|
|
+ if (size_t(buf.size()) > std::numeric_limits<quint32>::max()) {
|
|
+ qWarning(lcQtGuiTextureIO, "Too big KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ if (!canRead(QByteArray(), buf)) {
|
|
+ qWarning(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ if (buf.size() < qsizetype(qktxh_headerSize)) {
|
|
+ qWarning(lcQtGuiTextureIO, "Invalid KTX header size in %s", logName().constData());
|
|
return QTextureFileData();
|
|
}
|
|
|
|
- const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData());
|
|
- if (!checkHeader(*header)) {
|
|
- qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
|
|
+ KTXHeader header;
|
|
+ memcpy(&header, buf.data(), qktxh_headerSize);
|
|
+ if (!checkHeader(header)) {
|
|
+ qWarning(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
|
|
return QTextureFileData();
|
|
}
|
|
|
|
QTextureFileData texData;
|
|
texData.setData(buf);
|
|
|
|
- texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight)));
|
|
- texData.setGLFormat(decode(header->glFormat));
|
|
- texData.setGLInternalFormat(decode(header->glInternalFormat));
|
|
- texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
|
|
-
|
|
- texData.setNumLevels(decode(header->numberOfMipmapLevels));
|
|
- quint32 offset = headerSize + decode(header->bytesOfKeyValueData);
|
|
- const int maxLevels = qMin(texData.numLevels(), 32); // Cap iterations in case of corrupt file.
|
|
- for (int i = 0; i < maxLevels; i++) {
|
|
- if (offset + sizeof(KTXMipmapLevel) > dataSize) // Corrupt file; avoid oob read
|
|
- break;
|
|
- const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel *>(buf.constData() + offset);
|
|
- quint32 levelLen = decode(level->imageSize);
|
|
- texData.setDataOffset(offset + sizeof(KTXMipmapLevel::imageSize), i);
|
|
- texData.setDataLength(levelLen, i);
|
|
- offset += sizeof(KTXMipmapLevel::imageSize) + levelLen + (3 - ((levelLen + 3) % 4));
|
|
+ texData.setSize(QSize(decode(header.pixelWidth), decode(header.pixelHeight)));
|
|
+ texData.setGLFormat(decode(header.glFormat));
|
|
+ texData.setGLInternalFormat(decode(header.glInternalFormat));
|
|
+ texData.setGLBaseInternalFormat(decode(header.glBaseInternalFormat));
|
|
+
|
|
+ texData.setNumLevels(decode(header.numberOfMipmapLevels));
|
|
+
|
|
+ const quint32 bytesOfKeyValueData = decode(header.bytesOfKeyValueData);
|
|
+ quint32 headerKeyValueSize;
|
|
+ if (qAddOverflow(qktxh_headerSize, bytesOfKeyValueData, &headerKeyValueSize)) {
|
|
+ qWarning(lcQtGuiTextureIO, "Overflow in size of key value data in header of KTX file %s",
|
|
+ logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ if (headerKeyValueSize >= quint32(buf.size())) {
|
|
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ // Technically, any number of levels is allowed but if the value is bigger than
|
|
+ // what is possible in KTX V2 (and what makes sense) we return an error.
|
|
+ // maxLevels = log2(max(width, height, depth))
|
|
+ const int maxLevels = (sizeof(quint32) * 8)
|
|
+ - qCountLeadingZeroBits(std::max(
|
|
+ { header.pixelWidth, header.pixelHeight, header.pixelDepth }));
|
|
+
|
|
+ if (texData.numLevels() > maxLevels) {
|
|
+ qWarning(lcQtGuiTextureIO, "Too many levels in KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ quint32 offset = headerKeyValueSize;
|
|
+ for (int level = 0; level < texData.numLevels(); level++) {
|
|
+ const auto imageSizeSlice = safeSlice(buf, offset, sizeof(quint32));
|
|
+ if (imageSizeSlice.isEmpty()) {
|
|
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ const quint32 imageSize = decode(qFromUnaligned<quint32>(imageSizeSlice.data()));
|
|
+ offset += sizeof(quint32); // overflow checked indirectly above
|
|
+
|
|
+ texData.setDataOffset(offset, level);
|
|
+ texData.setDataLength(imageSize, level);
|
|
+
|
|
+ // Add image data and padding to offset
|
|
+ quint32 padded = 0;
|
|
+ if (nearestMultipleOf4(imageSize, &padded)) {
|
|
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ quint32 offsetNext;
|
|
+ if (qAddOverflow(offset, padded, &offsetNext)) {
|
|
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
|
+ return QTextureFileData();
|
|
+ }
|
|
+
|
|
+ offset = offsetNext;
|
|
}
|
|
|
|
if (!texData.isValid()) {
|
|
- qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData());
|
|
+ qWarning(lcQtGuiTextureIO, "Invalid values in header of KTX file %s",
|
|
+ logName().constData());
|
|
return QTextureFileData();
|
|
}
|
|
|
|
@@ -191,7 +271,7 @@ bool QKtxHandler::checkHeader(const KTXHeader &header)
|
|
(decode(header.numberOfFaces) == 1));
|
|
}
|
|
|
|
-quint32 QKtxHandler::decode(quint32 val)
|
|
+quint32 QKtxHandler::decode(quint32 val) const
|
|
{
|
|
return inverseEndian ? qbswap<quint32>(val) : val;
|
|
}
|
|
diff --git a/qtbase/src/gui/util/qktxhandler_p.h b/qtbase/src/gui/util/qktxhandler_p.h
|
|
index 19f7b0e79a..8da990aaac 100644
|
|
--- a/qtbase/src/gui/util/qktxhandler_p.h
|
|
+++ b/qtbase/src/gui/util/qktxhandler_p.h
|
|
@@ -68,7 +68,7 @@ public:
|
|
|
|
private:
|
|
bool checkHeader(const KTXHeader &header);
|
|
- quint32 decode(quint32 val);
|
|
+ quint32 decode(quint32 val) const;
|
|
|
|
bool inverseEndian = false;
|
|
};
|
|
diff --git a/qtbase/src/gui/util/qshadergenerator.cpp b/qtbase/src/gui/util/qshadergenerator.cpp
|
|
index 1ec25ccd7b..20ed6abc3a 100644
|
|
--- a/qtbase/src/gui/util/qshadergenerator.cpp
|
|
+++ b/qtbase/src/gui/util/qshadergenerator.cpp
|
|
@@ -492,7 +492,7 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
|
int end = begin + 1;
|
|
char endChar = line.at(end);
|
|
const int size = line.size();
|
|
- while (end < size && (std::isalnum(endChar) || endChar == '_')) {
|
|
+ while (end < size && (std::isalnum(uchar(endChar)) || endChar == '_')) {
|
|
++end;
|
|
endChar = line.at(end);
|
|
}
|
|
diff --git a/qtbase/src/gui/util/qshaderlanguage.cpp b/qtbase/src/gui/util/qshaderlanguage.cpp
|
|
index efd607ba60..9399d6efcc 100644
|
|
--- a/qtbase/src/gui/util/qshaderlanguage.cpp
|
|
+++ b/qtbase/src/gui/util/qshaderlanguage.cpp
|
|
@@ -52,3 +52,5 @@ void qt_register_ShaderLanguage_enums()
|
|
}
|
|
|
|
QT_END_NAMESPACE
|
|
+
|
|
+#include "moc_qshaderlanguage_p.cpp"
|
|
diff --git a/qtbase/src/network/access/http2/hpacktable.cpp b/qtbase/src/network/access/http2/hpacktable.cpp
|
|
index fddb5feca5..315f3e2344 100644
|
|
--- a/qtbase/src/network/access/http2/hpacktable.cpp
|
|
+++ b/qtbase/src/network/access/http2/hpacktable.cpp
|
|
@@ -40,6 +40,7 @@
|
|
#include "hpacktable_p.h"
|
|
|
|
#include <QtCore/qdebug.h>
|
|
+#include <QtCore/private/qnumeric_p.h>
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
@@ -62,8 +63,10 @@ HeaderSize entry_size(const QByteArray &name, const QByteArray &value)
|
|
// for counting the number of references to the name and value would have
|
|
// 32 octets of overhead."
|
|
|
|
- const unsigned sum = unsigned(name.size() + value.size());
|
|
- if (std::numeric_limits<unsigned>::max() - 32 < sum)
|
|
+ size_t sum;
|
|
+ if (add_overflow(size_t(name.size()), size_t(value.size()), &sum))
|
|
+ return HeaderSize();
|
|
+ if (sum > (std::numeric_limits<unsigned>::max() - 32))
|
|
return HeaderSize();
|
|
return HeaderSize(true, quint32(sum + 32));
|
|
}
|
|
diff --git a/qtbase/src/network/access/qhttp2protocolhandler.cpp b/qtbase/src/network/access/qhttp2protocolhandler.cpp
|
|
index 39dd460881..926f3134a0 100644
|
|
--- a/qtbase/src/network/access/qhttp2protocolhandler.cpp
|
|
+++ b/qtbase/src/network/access/qhttp2protocolhandler.cpp
|
|
@@ -46,10 +46,12 @@
|
|
#include <private/qnoncontiguousbytedevice_p.h>
|
|
|
|
#include <QtNetwork/qabstractsocket.h>
|
|
+
|
|
#include <QtCore/qloggingcategory.h>
|
|
#include <QtCore/qendian.h>
|
|
#include <QtCore/qdebug.h>
|
|
#include <QtCore/qlist.h>
|
|
+#include <QtCore/private/qnumeric_p.h>
|
|
#include <QtCore/qurl.h>
|
|
|
|
#include <qhttp2configuration.h>
|
|
@@ -124,8 +126,10 @@ std::vector<uchar> assemble_hpack_block(const std::vector<Http2::Frame> &frames)
|
|
std::vector<uchar> hpackBlock;
|
|
|
|
quint32 total = 0;
|
|
- for (const auto &frame : frames)
|
|
- total += frame.hpackBlockSize();
|
|
+ for (const auto &frame : frames) {
|
|
+ if (add_overflow(total, frame.hpackBlockSize(), &total))
|
|
+ return hpackBlock;
|
|
+ }
|
|
|
|
if (!total)
|
|
return hpackBlock;
|
|
@@ -371,12 +375,12 @@ bool QHttp2ProtocolHandler::sendRequest()
|
|
}
|
|
}
|
|
|
|
- if (!prefaceSent && !sendClientPreface())
|
|
- return false;
|
|
-
|
|
if (!requests.size())
|
|
return true;
|
|
|
|
+ if (!prefaceSent && !sendClientPreface())
|
|
+ return false;
|
|
+
|
|
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
|
|
// Check what was promised/pushed, maybe we do not have to send a request
|
|
// and have a response already?
|
|
diff --git a/qtbase/src/network/access/qhttpmultipart_p.h b/qtbase/src/network/access/qhttpmultipart_p.h
|
|
index ead1eadf3b..e45f7545a4 100644
|
|
--- a/qtbase/src/network/access/qhttpmultipart_p.h
|
|
+++ b/qtbase/src/network/access/qhttpmultipart_p.h
|
|
@@ -54,7 +54,9 @@
|
|
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
|
#include "QtCore/qshareddata.h"
|
|
#include "qnetworkrequest_p.h" // for deriving QHttpPartPrivate from QNetworkHeadersPrivate
|
|
+
|
|
#include "private/qobject_p.h"
|
|
+#include <QtCore/qiodevice.h>
|
|
|
|
QT_REQUIRE_CONFIG(http);
|
|
|
|
diff --git a/qtbase/src/network/access/qhttpnetworkconnectionchannel.cpp b/qtbase/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
index 7620ca1647..13f9630c65 100644
|
|
--- a/qtbase/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
+++ b/qtbase/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
@@ -255,6 +255,10 @@ void QHttpNetworkConnectionChannel::abort()
|
|
bool QHttpNetworkConnectionChannel::sendRequest()
|
|
{
|
|
Q_ASSERT(!protocolHandler.isNull());
|
|
+ if (waitingForPotentialAbort) {
|
|
+ needInvokeSendRequest = true;
|
|
+ return false; // this return value is unused
|
|
+ }
|
|
return protocolHandler->sendRequest();
|
|
}
|
|
|
|
@@ -267,21 +271,28 @@ bool QHttpNetworkConnectionChannel::sendRequest()
|
|
void QHttpNetworkConnectionChannel::sendRequestDelayed()
|
|
{
|
|
QMetaObject::invokeMethod(this, [this] {
|
|
- Q_ASSERT(!protocolHandler.isNull());
|
|
if (reply)
|
|
- protocolHandler->sendRequest();
|
|
+ sendRequest();
|
|
}, Qt::ConnectionType::QueuedConnection);
|
|
}
|
|
|
|
void QHttpNetworkConnectionChannel::_q_receiveReply()
|
|
{
|
|
Q_ASSERT(!protocolHandler.isNull());
|
|
+ if (waitingForPotentialAbort) {
|
|
+ needInvokeReceiveReply = true;
|
|
+ return;
|
|
+ }
|
|
protocolHandler->_q_receiveReply();
|
|
}
|
|
|
|
void QHttpNetworkConnectionChannel::_q_readyRead()
|
|
{
|
|
Q_ASSERT(!protocolHandler.isNull());
|
|
+ if (waitingForPotentialAbort) {
|
|
+ needInvokeReadyRead = true;
|
|
+ return;
|
|
+ }
|
|
protocolHandler->_q_readyRead();
|
|
}
|
|
|
|
@@ -1289,7 +1300,18 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|
// Similar to HTTP/1.1 counterpart below:
|
|
const auto &pairs = spdyRequestsToSend.values(); // (request, reply)
|
|
const auto &pair = pairs.first();
|
|
+ waitingForPotentialAbort = true;
|
|
emit pair.second->encrypted();
|
|
+
|
|
+ // We don't send or handle any received data until any effects from
|
|
+ // emitting encrypted() have been processed. This is necessary
|
|
+ // because the user may have called abort(). We may also abort the
|
|
+ // whole connection if the request has been aborted and there is
|
|
+ // no more requests to send.
|
|
+ QMetaObject::invokeMethod(this,
|
|
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
|
|
+ Qt::QueuedConnection);
|
|
+
|
|
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
|
|
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
|
|
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
|
@@ -1307,6 +1329,26 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|
}
|
|
}
|
|
|
|
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
|
|
+{
|
|
+ Q_ASSERT(connection->connectionType() > QHttpNetworkConnection::ConnectionTypeHTTP);
|
|
+
|
|
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
|
|
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
|
|
+ // effects from emitting encrypted() have been processed.
|
|
+ // This function is called after encrypted() was emitted, so check for changes.
|
|
+
|
|
+ if (!reply && spdyRequestsToSend.isEmpty())
|
|
+ abort();
|
|
+ waitingForPotentialAbort = false;
|
|
+ if (needInvokeReadyRead)
|
|
+ _q_readyRead();
|
|
+ if (needInvokeReceiveReply)
|
|
+ _q_receiveReply();
|
|
+ if (needInvokeSendRequest)
|
|
+ sendRequest();
|
|
+}
|
|
+
|
|
void QHttpNetworkConnectionChannel::requeueSpdyRequests()
|
|
{
|
|
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
|
diff --git a/qtbase/src/network/access/qhttpnetworkconnectionchannel_p.h b/qtbase/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
index d8ac3979d1..eac4446492 100644
|
|
--- a/qtbase/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
+++ b/qtbase/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
@@ -107,6 +107,10 @@ public:
|
|
QAbstractSocket *socket;
|
|
bool ssl;
|
|
bool isInitialized;
|
|
+ bool waitingForPotentialAbort = false;
|
|
+ bool needInvokeReceiveReply = false;
|
|
+ bool needInvokeReadyRead = false;
|
|
+ bool needInvokeSendRequest = false;
|
|
ChannelState state;
|
|
QHttpNetworkRequest request; // current request, only used for HTTP
|
|
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
|
|
@@ -187,6 +191,8 @@ public:
|
|
void closeAndResendCurrentRequest();
|
|
void resendCurrentRequest();
|
|
|
|
+ void checkAndResumeCommunication();
|
|
+
|
|
bool isSocketBusy() const;
|
|
bool isSocketWriting() const;
|
|
bool isSocketWaiting() const;
|
|
diff --git a/qtbase/src/network/configure.json b/qtbase/src/network/configure.json
|
|
index 271ff164ac..ffba2d1eea 100644
|
|
--- a/qtbase/src/network/configure.json
|
|
+++ b/qtbase/src/network/configure.json
|
|
@@ -53,7 +53,7 @@
|
|
},
|
|
"headers": "proxy.h",
|
|
"sources": [
|
|
- "-lproxy"
|
|
+ { "type": "pkgConfig", "args": "libproxy-1.0" }
|
|
]
|
|
},
|
|
"openssl_headers": {
|
|
diff --git a/qtbase/src/network/ssl/qsslcontext_openssl.cpp b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
|
|
index c30192a4eb..e4bb61ecb5 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
|
|
diff --git a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
|
|
index 333b09e9c1..0f7343c9d9 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_mac.cpp b/qtbase/src/network/ssl/qsslsocket_mac.cpp
|
|
index 77e847e972..e38a5e75de 100644
|
|
--- a/qtbase/src/network/ssl/qsslsocket_mac.cpp
|
|
+++ b/qtbase/src/network/ssl/qsslsocket_mac.cpp
|
|
@@ -468,6 +468,7 @@ void QSslSocketBackendPrivate::disconnectFromHost()
|
|
if (context) {
|
|
if (!shutdown) {
|
|
SSLClose(context);
|
|
+ context.reset(nullptr);
|
|
shutdown = true;
|
|
}
|
|
}
|
|
diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
|
index 0ace951c77..6a9a3ef3b3 100644
|
|
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
|
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
|
@@ -499,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
|
|
@@ -1220,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 5e9faae291..bf165f67ad 100644
|
|
--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
|
|
+++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
|
|
@@ -598,10 +598,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)
|
|
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 d3d793efc3..089fd39927 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
|
|
|
|
diff --git a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
|
|
index 8389bd8f5a..55c46de8cd 100644
|
|
--- a/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
|
|
+++ b/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
|
|
@@ -98,7 +98,46 @@ public:
|
|
return sym <= 0xff;
|
|
}
|
|
static bool isKeypad(xkb_keysym_t sym) {
|
|
- return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
|
|
+ switch (sym) {
|
|
+ case XKB_KEY_KP_Space:
|
|
+ case XKB_KEY_KP_Tab:
|
|
+ case XKB_KEY_KP_Enter:
|
|
+ case XKB_KEY_KP_F1:
|
|
+ case XKB_KEY_KP_F2:
|
|
+ case XKB_KEY_KP_F3:
|
|
+ case XKB_KEY_KP_F4:
|
|
+ case XKB_KEY_KP_Home:
|
|
+ case XKB_KEY_KP_Left:
|
|
+ case XKB_KEY_KP_Up:
|
|
+ case XKB_KEY_KP_Right:
|
|
+ case XKB_KEY_KP_Down:
|
|
+ case XKB_KEY_KP_Prior:
|
|
+ case XKB_KEY_KP_Next:
|
|
+ case XKB_KEY_KP_End:
|
|
+ case XKB_KEY_KP_Begin:
|
|
+ case XKB_KEY_KP_Insert:
|
|
+ case XKB_KEY_KP_Delete:
|
|
+ case XKB_KEY_KP_Equal:
|
|
+ case XKB_KEY_KP_Multiply:
|
|
+ case XKB_KEY_KP_Add:
|
|
+ case XKB_KEY_KP_Separator:
|
|
+ case XKB_KEY_KP_Subtract:
|
|
+ case XKB_KEY_KP_Decimal:
|
|
+ case XKB_KEY_KP_Divide:
|
|
+ case XKB_KEY_KP_0:
|
|
+ case XKB_KEY_KP_1:
|
|
+ case XKB_KEY_KP_2:
|
|
+ case XKB_KEY_KP_3:
|
|
+ case XKB_KEY_KP_4:
|
|
+ case XKB_KEY_KP_5:
|
|
+ case XKB_KEY_KP_6:
|
|
+ case XKB_KEY_KP_7:
|
|
+ case XKB_KEY_KP_8:
|
|
+ case XKB_KEY_KP_9:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
}
|
|
|
|
static void setXkbContext(QPlatformInputContext *inputContext, struct xkb_context *context);
|
|
diff --git a/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
|
|
index 9153fd20bb..d30ed5b6dc 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;
|
|
@@ -1560,11 +1606,12 @@ bool AtSpiAdaptor::inheritsQAction(QObject *object)
|
|
// Component
|
|
static QAccessibleInterface * getWindow(QAccessibleInterface * interface)
|
|
{
|
|
- if (interface->role() == QAccessible::Window)
|
|
+ if (interface->role() == QAccessible::Dialog || interface->role() == QAccessible::Window)
|
|
return interface;
|
|
|
|
QAccessibleInterface * parent = interface->parent();
|
|
- while (parent && parent->role() != QAccessible::Window)
|
|
+ while (parent && parent->role() != QAccessible::Dialog
|
|
+ && parent->role() != QAccessible::Window)
|
|
parent = parent->parent();
|
|
|
|
return parent;
|
|
@@ -1582,7 +1629,7 @@ static QRect getRelativeRect(QAccessibleInterface *interface)
|
|
wr = window->rect();
|
|
|
|
cr.setX(cr.x() - wr.x());
|
|
- cr.setY(cr.x() - wr.y());
|
|
+ cr.setY(cr.y() - wr.y());
|
|
}
|
|
return cr;
|
|
}
|
|
@@ -1836,7 +1883,7 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
|
|
uint coordType = message.arguments().at(2).toUInt();
|
|
if (coordType == ATSPI_COORD_TYPE_WINDOW) {
|
|
QWindow *win = interface->window();
|
|
- point -= QPoint(win->x(), win->y());
|
|
+ point += QPoint(win->x(), win->y());
|
|
}
|
|
int offset = interface->textInterface()->offsetAtPoint(point);
|
|
sendReply(connection, message, offset);
|
|
@@ -2393,13 +2440,14 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
|
|
if (cols > 0) {
|
|
row = index / cols;
|
|
col = index % cols;
|
|
- QAccessibleTableCellInterface *cell = interface->tableInterface()->cellAt(row, col)->tableCellInterface();
|
|
- if (cell) {
|
|
- row = cell->rowIndex();
|
|
- col = cell->columnIndex();
|
|
- rowExtents = cell->rowExtent();
|
|
- colExtents = cell->columnExtent();
|
|
- isSelected = cell->isSelected();
|
|
+ QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, col);
|
|
+ QAccessibleTableCellInterface *cellIface = cell ? cell->tableCellInterface() : nullptr;
|
|
+ if (cellIface) {
|
|
+ row = cellIface->rowIndex();
|
|
+ col = cellIface->columnIndex();
|
|
+ rowExtents = cellIface->rowExtent();
|
|
+ colExtents = cellIface->columnExtent();
|
|
+ isSelected = cellIface->isSelected();
|
|
success = true;
|
|
}
|
|
}
|
|
@@ -2410,12 +2458,22 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
|
|
} else if (function == QLatin1String("GetColumnExtentAt")) {
|
|
int row = message.arguments().at(0).toInt();
|
|
int column = message.arguments().at(1).toInt();
|
|
- connection.send(message.createReply(interface->tableInterface()->cellAt(row, column)->tableCellInterface()->columnExtent()));
|
|
+ int columnExtent = 0;
|
|
+ QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column);
|
|
+ QAccessibleTableCellInterface *cellIface = cell ? cell->tableCellInterface() : nullptr;
|
|
+ if (cellIface)
|
|
+ columnExtent = cellIface->columnExtent();
|
|
+ connection.send(message.createReply(columnExtent));
|
|
|
|
} else if (function == QLatin1String("GetRowExtentAt")) {
|
|
int row = message.arguments().at(0).toInt();
|
|
int column = message.arguments().at(1).toInt();
|
|
- connection.send(message.createReply(interface->tableInterface()->cellAt(row, column)->tableCellInterface()->rowExtent()));
|
|
+ int rowExtent = 0;
|
|
+ QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column);
|
|
+ QAccessibleTableCellInterface *cellIface = cell ? cell->tableCellInterface() : nullptr;
|
|
+ if (cellIface)
|
|
+ rowExtent = cellIface->rowExtent();
|
|
+ connection.send(message.createReply(rowExtent));
|
|
|
|
} else if (function == QLatin1String("GetColumnHeader")) {
|
|
int column = message.arguments().at(0).toInt();
|
|
@@ -2455,8 +2513,12 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
|
|
} else if (function == QLatin1String("IsSelected")) {
|
|
int row = message.arguments().at(0).toInt();
|
|
int column = message.arguments().at(1).toInt();
|
|
- QAccessibleTableCellInterface* cell = interface->tableInterface()->cellAt(row, column)->tableCellInterface();
|
|
- connection.send(message.createReply(cell->isSelected()));
|
|
+ bool isSelected = false;
|
|
+ QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column);
|
|
+ QAccessibleTableCellInterface *cellIface = cell ? cell->tableCellInterface() : nullptr;
|
|
+ if (cellIface)
|
|
+ isSelected = cellIface->isSelected();
|
|
+ connection.send(message.createReply(isSelected));
|
|
} else if (function == QLatin1String("AddColumnSelection")) {
|
|
int column = message.arguments().at(0).toInt();
|
|
connection.send(message.createReply(interface->tableInterface()->selectColumn(column)));
|
|
diff --git a/qtbase/src/platformsupport/linuxaccessibility/bridge.cpp b/qtbase/src/platformsupport/linuxaccessibility/bridge.cpp
|
|
index fdc8cd3198..b17e1749c8 100644
|
|
--- a/qtbase/src/platformsupport/linuxaccessibility/bridge.cpp
|
|
+++ b/qtbase/src/platformsupport/linuxaccessibility/bridge.cpp
|
|
@@ -229,7 +229,11 @@ static RoleMapping map[] = {
|
|
//: Role of an accessible object
|
|
{ QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down") },
|
|
//: Role of an accessible object
|
|
+#if ATSPI_ROLE_COUNT > 130
|
|
+ { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON_MENU, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
|
|
+#else
|
|
{ QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
|
|
+#endif
|
|
//: Role of an accessible object - a button that expands a grid.
|
|
{ QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down grid") },
|
|
//: Role of an accessible object - blank space between other objects.
|
|
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 f0d1722c95..47ef7d2b5c 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>
|
|
@@ -205,8 +210,7 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
|
|
// handle_token (s) - A string that will be used as the last element of the @handle.
|
|
// writable (b) - Whether to allow the chosen application to write to the file.
|
|
|
|
-#ifdef O_PATH
|
|
- const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
|
|
+ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
|
|
if (fd != -1) {
|
|
QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
|
|
QLatin1String("/org/freedesktop/portal/desktop"),
|
|
@@ -216,16 +220,13 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
|
|
QDBusUnixFileDescriptor descriptor;
|
|
descriptor.giveFileDescriptor(fd);
|
|
|
|
- const QVariantMap options = {{QLatin1String("writable"), true}};
|
|
+ const QVariantMap options = {};
|
|
|
|
// FIXME parent_window_id
|
|
message << QString() << QVariant::fromValue(descriptor) << options;
|
|
|
|
return QDBusConnection::sessionBus().call(message);
|
|
}
|
|
-#else
|
|
- Q_UNUSED(url)
|
|
-#endif
|
|
|
|
return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
|
|
}
|
|
@@ -298,8 +299,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();
|
|
@@ -354,6 +482,8 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
|
|
}
|
|
|
|
#else
|
|
+QGenericUnixServices::QGenericUnixServices() = default;
|
|
+
|
|
QByteArray QGenericUnixServices::desktopEnvironment() const
|
|
{
|
|
return QByteArrayLiteral("UNKNOWN");
|
|
@@ -373,6 +503,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/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/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/xcb/qxcbconnection.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
index 013ca7369f..631ade2ec7 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
@@ -706,6 +706,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);
|
|
}
|
|
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
|
|
index ec099101f5..9cee3bc5e1 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
|
|
@@ -165,7 +165,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
|
// Screen has been disabled
|
|
auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
|
|
output.output, output.config_timestamp);
|
|
- if (outputInfo->crtc == XCB_NONE) {
|
|
+ if (!outputInfo || outputInfo->crtc == XCB_NONE) {
|
|
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
|
|
destroyScreen(screen);
|
|
} else {
|
|
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/qtbase/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
index 1ced02f31d..5c8298a49d 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
@@ -1255,16 +1255,14 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
|
|
if (Q_LIKELY(useValuators)) {
|
|
const qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.x(), physicalScreenArea.width());
|
|
global.setX(value);
|
|
- // mapFromGlobal is ok for nested/embedded windows, but works only with whole-number QPoint;
|
|
- // so map it first, then add back the sub-pixel position
|
|
- local.setX(window->mapFromGlobal(QPoint(int(value), 0)).x() + (value - int(value)));
|
|
+ local.setX(xcbWindow->mapFromGlobal(QPoint(int(value), 0)).x() + (value - int(value)));
|
|
}
|
|
break;
|
|
case QXcbAtom::AbsY:
|
|
if (Q_LIKELY(useValuators)) {
|
|
qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.y(), physicalScreenArea.height());
|
|
global.setY(value);
|
|
- local.setY(window->mapFromGlobal(QPoint(0, int(value))).y() + (value - int(value)));
|
|
+ local.setY(xcbWindow->mapFromGlobal(QPoint(0, int(value))).y() + (value - int(value)));
|
|
}
|
|
break;
|
|
case QXcbAtom::AbsPressure:
|
|
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
|
index 4210bf428e..4635c199d0 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
|
@@ -300,7 +300,7 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
|
|
#endif // !QT_NO_CURSOR
|
|
|
|
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
|
|
- : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false)
|
|
+ : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false), m_callbackForPropertyRegistered(false)
|
|
{
|
|
#if QT_CONFIG(cursor)
|
|
// see NUM_BITMAPS in libXcursor/src/xcursorint.h
|
|
@@ -343,7 +343,7 @@ QXcbCursor::~QXcbCursor()
|
|
{
|
|
xcb_connection_t *conn = xcb_connection();
|
|
|
|
- if (m_gtkCursorThemeInitialized) {
|
|
+ if (m_callbackForPropertyRegistered) {
|
|
m_screen->xSettings()->removeCallbackForHandle(this);
|
|
}
|
|
|
|
@@ -562,8 +562,10 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
|
|
xcb_cursor_t cursor = XCB_NONE;
|
|
|
|
#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
|
|
- if (m_screen->xSettings()->initialized())
|
|
+ if (!m_callbackForPropertyRegistered && m_screen->xSettings()->initialized()) {
|
|
m_screen->xSettings()->registerCallbackForProperty("Gtk/CursorThemeName",cursorThemePropertyChanged,this);
|
|
+ m_callbackForPropertyRegistered = true;
|
|
+ }
|
|
|
|
// Try Xcursor first
|
|
if (cshape >= 0 && cshape <= Qt::LastCursor) {
|
|
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.h b/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
|
|
index 0b238823f0..82fb47e55d 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.h
|
|
@@ -122,6 +122,7 @@ private:
|
|
void *handle);
|
|
#endif
|
|
bool m_gtkCursorThemeInitialized;
|
|
+ bool m_callbackForPropertyRegistered;
|
|
};
|
|
|
|
QT_END_NAMESPACE
|
|
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/qxcbwindow.cpp b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
index 066874dc66..ed8c4ebd8f 100644
|
|
--- a/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
+++ b/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
@@ -539,6 +539,8 @@ void QXcbWindow::destroy()
|
|
doFocusOut();
|
|
if (connection()->mouseGrabber() == this)
|
|
connection()->setMouseGrabber(nullptr);
|
|
+ if (connection()->mousePressWindow() == this)
|
|
+ connection()->setMousePressWindow(nullptr);
|
|
|
|
if (m_syncCounter && connection()->hasXSync())
|
|
xcb_sync_destroy_counter(xcb_connection(), m_syncCounter);
|
|
@@ -1297,6 +1299,7 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
|
|
m_embedded = false;
|
|
}
|
|
xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y());
|
|
+ connection()->sync();
|
|
}
|
|
|
|
void QXcbWindow::setWindowTitle(const QString &title)
|
|
@@ -1345,9 +1348,10 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
|
|
|
|
if (!icon_data.isEmpty()) {
|
|
// Ignore icon exceeding maximum xcb request length
|
|
- if (size_t(icon_data.size()) > xcb_get_maximum_request_length(xcb_connection())) {
|
|
- qWarning("Ignoring window icon: Size %d exceeds maximum xcb request length %u.",
|
|
- icon_data.size(), xcb_get_maximum_request_length(xcb_connection()));
|
|
+ if (quint64(icon_data.size()) > quint64(xcb_get_maximum_request_length(xcb_connection()))) {
|
|
+ qWarning() << "Ignoring window icon" << icon_data.size()
|
|
+ << "exceeds maximum xcb request length"
|
|
+ << xcb_get_maximum_request_length(xcb_connection());
|
|
return;
|
|
}
|
|
xcb_change_property(xcb_connection(),
|
|
diff --git a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
|
|
index c6596c35de..8987e3efd0 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;
|
|
@@ -122,11 +119,16 @@ public:
|
|
QString selectedNameFilter;
|
|
QStringList selectedFiles;
|
|
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);
|
|
|
|
@@ -134,6 +136,9 @@ QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelp
|
|
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);
|
|
|
|
@@ -293,10 +298,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(),
|
|
@@ -330,7 +343,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;
|
|
@@ -352,7 +365,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;
|
|
@@ -407,16 +420,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()
|
|
@@ -433,13 +443,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;
|
|
}
|
|
@@ -469,6 +476,23 @@ 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
|
|
|
|
#include "moc_qxdgdesktopportalfiledialog_p.cpp"
|
|
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 2fc3167fd5..b809503122 100644
|
|
--- a/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
|
|
+++ b/qtbase/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
|
|
@@ -153,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/sqldrivers/mysql/qsql_mysql.cpp b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
|
|
index e0c72fa240..309bbdad57 100644
|
|
--- a/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
|
|
+++ b/qtbase/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
|
|
@@ -1370,20 +1370,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/plugins/sqldrivers/odbc/qsql_odbc.cpp b/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
|
|
index 8e2e883652..d147774055 100644
|
|
--- a/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
|
|
+++ b/qtbase/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
|
|
@@ -745,10 +745,15 @@ static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, int i, QString *errorMess
|
|
f.setAutoValue(isAutoValue(hStmt, i));
|
|
QVarLengthArray<SQLTCHAR> tableName(TABLENAMESIZE);
|
|
SQLSMALLINT tableNameLen;
|
|
- r = SQLColAttribute(hStmt, i + 1, SQL_DESC_BASE_TABLE_NAME, tableName.data(),
|
|
- TABLENAMESIZE, &tableNameLen, 0);
|
|
+ r = SQLColAttribute(hStmt,
|
|
+ i + 1,
|
|
+ SQL_DESC_BASE_TABLE_NAME,
|
|
+ tableName.data(),
|
|
+ SQLSMALLINT(tableName.size() * sizeof(SQLTCHAR)), // SQLColAttribute needs/returns size in bytes
|
|
+ &tableNameLen,
|
|
+ 0);
|
|
if (r == SQL_SUCCESS)
|
|
- f.setTableName(fromSQLTCHAR(tableName, tableNameLen));
|
|
+ f.setTableName(fromSQLTCHAR(tableName, tableNameLen / sizeof(SQLTCHAR)));
|
|
return f;
|
|
}
|
|
|
|
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/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/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/testlib/qabstractitemmodeltester.cpp b/qtbase/src/testlib/qabstractitemmodeltester.cpp
|
|
index 1cd18b98bb..41219a7e23 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/widgets/dialogs/qcolordialog.cpp b/qtbase/src/widgets/dialogs/qcolordialog.cpp
|
|
index 4247731275..30445fa069 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
|
|
@@ -801,6 +804,10 @@ QColorLuminancePicker::~QColorLuminancePicker()
|
|
|
|
void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)
|
|
{
|
|
+ if (m->buttons() == Qt::NoButton) {
|
|
+ m->ignore();
|
|
+ return;
|
|
+ }
|
|
setVal(y2val(m->y()));
|
|
}
|
|
void QColorLuminancePicker::mousePressEvent(QMouseEvent *m)
|
|
@@ -935,6 +942,10 @@ void QColorPicker::setCol(int h, int s)
|
|
void QColorPicker::mouseMoveEvent(QMouseEvent *m)
|
|
{
|
|
QPoint p = m->pos() - contentsRect().topLeft();
|
|
+ if (m->buttons() == Qt::NoButton) {
|
|
+ m->ignore();
|
|
+ return;
|
|
+ }
|
|
setCol(p);
|
|
emit newCol(hue, sat);
|
|
}
|
|
@@ -1611,6 +1622,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 fab44923de..79254e052f 100644
|
|
--- a/qtbase/src/widgets/itemviews/qlistview.cpp
|
|
+++ b/qtbase/src/widgets/itemviews/qlistview.cpp
|
|
@@ -3389,6 +3389,7 @@ void QIconModeViewBase::updateContentsSize()
|
|
*/
|
|
void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
|
{
|
|
+ QAbstractItemView::currentChanged(current, previous);
|
|
#ifndef QT_NO_ACCESSIBILITY
|
|
if (QAccessible::isActive()) {
|
|
if (current.isValid()) {
|
|
@@ -3399,7 +3400,6 @@ void QListView::currentChanged(const QModelIndex ¤t, 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 d120c41dc9..09d34005a7 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/styles/qfusionstyle.cpp b/qtbase/src/widgets/styles/qfusionstyle.cpp
|
|
index a225d4b563..35e2769ac4 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/qsystemtrayicon.cpp b/qtbase/src/widgets/util/qsystemtrayicon.cpp
|
|
index 203fcbc443..e9b2724903 100644
|
|
--- a/qtbase/src/widgets/util/qsystemtrayicon.cpp
|
|
+++ b/qtbase/src/widgets/util/qsystemtrayicon.cpp
|
|
@@ -208,7 +208,7 @@ void QSystemTrayIcon::setContextMenu(QMenu *menu)
|
|
if (oldMenu != menu && d->qpa_sys) {
|
|
// Show the QMenu-based menu for QPA plugins that do not provide native menus
|
|
if (oldMenu && !oldMenu->platformMenu())
|
|
- QObject::disconnect(d->qpa_sys, &QPlatformSystemTrayIcon::contextMenuRequested, menu, nullptr);
|
|
+ QObject::disconnect(d->qpa_sys, &QPlatformSystemTrayIcon::contextMenuRequested, oldMenu, nullptr);
|
|
if (menu && !menu->platformMenu()) {
|
|
QObject::connect(d->qpa_sys, &QPlatformSystemTrayIcon::contextMenuRequested,
|
|
menu,
|
|
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 422082da6c..5692c6e82b 100644
|
|
--- a/qtbase/src/widgets/widgets/qcombobox.cpp
|
|
+++ b/qtbase/src/widgets/widgets/qcombobox.cpp
|
|
@@ -3354,7 +3354,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
|
|
@@ -3396,26 +3412,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/qcombobox_p.h b/qtbase/src/widgets/widgets/qcombobox_p.h
|
|
index 45580ba943..2a97f56791 100644
|
|
--- a/qtbase/src/widgets/widgets/qcombobox_p.h
|
|
+++ b/qtbase/src/widgets/widgets/qcombobox_p.h
|
|
@@ -429,7 +429,7 @@ public:
|
|
int minimumContentsLength = 0;
|
|
int indexBeforeChange = -1;
|
|
int maxVisibleItems = 10;
|
|
- int maxCount = std::numeric_limits<int>::max();
|
|
+ int maxCount = (std::numeric_limits<int>::max)();
|
|
int modelColumn = 0;
|
|
int placeholderIndex = -1;
|
|
bool shownOnce : 1;
|
|
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/qdial.cpp b/qtbase/src/widgets/widgets/qdial.cpp
|
|
index 8f774a3cc7..ec5cec0d82 100644
|
|
--- a/qtbase/src/widgets/widgets/qdial.cpp
|
|
+++ b/qtbase/src/widgets/widgets/qdial.cpp
|
|
@@ -94,6 +94,8 @@ int QDialPrivate::bound(int val) const
|
|
if (wrapping) {
|
|
if ((val >= minimum) && (val <= maximum))
|
|
return val;
|
|
+ if (minimum == maximum)
|
|
+ return minimum;
|
|
val = minimum + ((val - minimum) % (maximum - minimum));
|
|
if (val < minimum)
|
|
val += maximum - minimum;
|
|
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/qlineedit_p.cpp b/qtbase/src/widgets/widgets/qlineedit_p.cpp
|
|
index 80c9258da4..3fa0f29d28 100644
|
|
--- a/qtbase/src/widgets/widgets/qlineedit_p.cpp
|
|
+++ b/qtbase/src/widgets/widgets/qlineedit_p.cpp
|
|
@@ -434,7 +434,7 @@ void QLineEditIconButton::animateShow(bool visible)
|
|
|
|
void QLineEditIconButton::startOpacityAnimation(qreal endValue)
|
|
{
|
|
- QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"));
|
|
+ QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"), this);
|
|
connect(animation, &QPropertyAnimation::finished, this, &QLineEditIconButton::onAnimationFinished);
|
|
|
|
animation->setDuration(160);
|
|
diff --git a/qtbase/src/widgets/widgets/qtoolbutton.cpp b/qtbase/src/widgets/widgets/qtoolbutton.cpp
|
|
index e380cb647b..9953db73af 100644
|
|
--- a/qtbase/src/widgets/widgets/qtoolbutton.cpp
|
|
+++ b/qtbase/src/widgets/widgets/qtoolbutton.cpp
|
|
@@ -982,7 +982,15 @@ QAction *QToolButton::defaultAction() const
|
|
return d->defaultAction;
|
|
}
|
|
|
|
-
|
|
+/*!
|
|
+ \reimp
|
|
+ */
|
|
+void QToolButton::checkStateSet()
|
|
+{
|
|
+ Q_D(QToolButton);
|
|
+ if (d->defaultAction && d->defaultAction->isCheckable())
|
|
+ d->defaultAction->setChecked(isChecked());
|
|
+}
|
|
|
|
/*!
|
|
\reimp
|
|
diff --git a/qtbase/src/widgets/widgets/qtoolbutton.h b/qtbase/src/widgets/widgets/qtoolbutton.h
|
|
index 52bd2d5f7a..82b5d7924f 100644
|
|
--- a/qtbase/src/widgets/widgets/qtoolbutton.h
|
|
+++ b/qtbase/src/widgets/widgets/qtoolbutton.h
|
|
@@ -118,6 +118,7 @@ protected:
|
|
void changeEvent(QEvent *) override;
|
|
|
|
bool hitButton(const QPoint &pos) const override;
|
|
+ void checkStateSet() override;
|
|
void nextCheckState() override;
|
|
void initStyleOption(QStyleOptionToolButton *option) const;
|
|
|
|
diff --git a/qtbase/sync.profile b/qtbase/sync.profile
|
|
index 0292bf0dc2..7dd0177b90 100644
|
|
--- a/qtbase/sync.profile
|
|
+++ b/qtbase/sync.profile
|
|
@@ -77,7 +77,7 @@
|
|
"qsql.h" => "QtSql/qtsqlglobal.h"
|
|
},
|
|
"QtDBus" => {
|
|
- "qdbusmacros.h" => "QtDbus/qtdbusglobal.h"
|
|
+ "qdbusmacros.h" => "QtDBus/qtdbusglobal.h"
|
|
},
|
|
"QtTest" => {
|
|
"qtest_global.h" => "QtTest/qttestglobal.h"
|
|
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/mimetypes/qmimedatabase/circular-inheritance.xml b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/circular-inheritance.xml
|
|
new file mode 100644
|
|
index 0000000000..466f039803
|
|
--- /dev/null
|
|
+++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/circular-inheritance.xml
|
|
@@ -0,0 +1,13 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
|
+ <mime-type type="application/ecmascript">
|
|
+ <comment>It's more accurate to say that ECMAScript is a subset of JavaScript</comment>
|
|
+ <sub-class-of type="text/javascript"/>
|
|
+ <glob pattern="*.js"/>
|
|
+ </mime-type>
|
|
+ <mime-type type="text/javascript">
|
|
+ <comment>than to say that JavaScript is a subset of ECMAScript</comment>
|
|
+ <sub-class-of type="application/ecmascript"/>
|
|
+ <glob pattern="*.js"/>
|
|
+ </mime-type>
|
|
+</mime-info>
|
|
diff --git a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
|
|
index 1002d0195d..49dbb0a8ba 100644
|
|
--- a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
|
|
+++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
|
|
@@ -3,10 +3,12 @@
|
|
<file alias="yast2-metapackage-handler-mimetypes.xml">yast2-metapackage-handler-mimetypes.xml</file>
|
|
<file alias="qml-again.xml">qml-again.xml</file>
|
|
<file alias="text-x-objcsrc.xml">text-x-objcsrc.xml</file>
|
|
+ <file alias="text-plain-subclass.xml">text-plain-subclass.xml</file>
|
|
<file alias="test.qml">test.qml</file>
|
|
<file>invalid-magic1.xml</file>
|
|
<file>invalid-magic2.xml</file>
|
|
<file>invalid-magic3.xml</file>
|
|
+ <file>circular-inheritance.xml</file>
|
|
<file>magic-and-hierarchy.xml</file>
|
|
<file>magic-and-hierarchy.foo</file>
|
|
<file>magic-and-hierarchy2.foo</file>
|
|
diff --git a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml
|
|
new file mode 100644
|
|
index 0000000000..7b5cb7506d
|
|
--- /dev/null
|
|
+++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml
|
|
@@ -0,0 +1,15 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
|
+ <mime-type type="text/x-microdvd">
|
|
+ <comment>MicroDVD subtitles</comment>
|
|
+ <sub-class-of type="text/plain"/>
|
|
+ <magic priority="50">
|
|
+ <match type="string" value="{1}" offset="0"/>
|
|
+ <match type="string" value="{0}" offset="0"/>
|
|
+ <match type="string" value="}{" offset="0:6"/>
|
|
+ </magic>
|
|
+ <generic-icon name="text-x-generic"/>
|
|
+ <glob pattern="*.sub"/>
|
|
+ <glob pattern="*.txt"/>
|
|
+ </mime-type>
|
|
+</mime-info>
|
|
diff --git a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
|
|
index 0ea422ecbc..d2dd8d340b 100644
|
|
--- a/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
|
|
+++ b/qtbase/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
|
|
@@ -49,10 +49,12 @@ static const char *const additionalMimeFiles[] = {
|
|
"yast2-metapackage-handler-mimetypes.xml",
|
|
"qml-again.xml",
|
|
"text-x-objcsrc.xml",
|
|
+ "text-plain-subclass.xml",
|
|
"invalid-magic1.xml",
|
|
"invalid-magic2.xml",
|
|
"invalid-magic3.xml",
|
|
"magic-and-hierarchy.xml",
|
|
+ "circular-inheritance.xml",
|
|
0
|
|
};
|
|
|
|
@@ -70,15 +72,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 +156,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()));
|
|
|
|
@@ -390,6 +392,13 @@ void tst_QMimeDatabase::inheritance()
|
|
const QMimeType mswordTemplate = db.mimeTypeForName(QString::fromLatin1("application/msword-template"));
|
|
QVERIFY(mswordTemplate.isValid());
|
|
QVERIFY(mswordTemplate.inherits(QLatin1String("application/msword")));
|
|
+
|
|
+ // Check that buggy type definitions that have circular inheritance don't cause an infinite
|
|
+ // loop, especially when resolving a conflict between the file's name and its contents
|
|
+ const QMimeType ecmascript = db.mimeTypeForName(QString::fromLatin1("application/ecmascript"));
|
|
+ QVERIFY(ecmascript.allAncestors().contains("text/plain"));
|
|
+ const QMimeType javascript = db.mimeTypeForFileNameAndData("xml.js", "<?xml?>");
|
|
+ QVERIFY(javascript.inherits(QString::fromLatin1("text/javascript")));
|
|
}
|
|
|
|
void tst_QMimeDatabase::aliases()
|
|
@@ -611,7 +620,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 +640,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";
|
|
@@ -1070,6 +1078,8 @@ void tst_QMimeDatabase::installNewLocalMimeType()
|
|
QVERIFY(objcsrc.isValid());
|
|
QCOMPARE(objcsrc.globPatterns(), QStringList());
|
|
}
|
|
+ QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.txt"), QMimeDatabase::MatchExtension).name(),
|
|
+ QString::fromLatin1("text/plain"));
|
|
|
|
// Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs").
|
|
const QString qmlTestFile = QLatin1String(RESOURCE_PREFIX "test.qml");
|
|
diff --git a/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h b/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h
|
|
index ca2ceed7a9..624316dfdb 100644
|
|
--- a/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h
|
|
+++ b/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h
|
|
@@ -35,7 +35,7 @@
|
|
class Plugin1 : public QObject, public PluginInterface1
|
|
{
|
|
Q_OBJECT
|
|
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface1")
|
|
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface1" FILE "plugin1.json")
|
|
Q_INTERFACES(PluginInterface1)
|
|
|
|
public:
|
|
diff --git a/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.json b/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.json
|
|
new file mode 100644
|
|
index 0000000000..ce67846d48
|
|
--- /dev/null
|
|
+++ b/qtbase/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.json
|
|
@@ -0,0 +1,5 @@
|
|
+{
|
|
+ "Keys": [
|
|
+ "plugin1"
|
|
+ ]
|
|
+}
|
|
diff --git a/qtbase/tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp b/qtbase/tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp
|
|
index 9fa61804b3..88ada1b806 100644
|
|
--- a/qtbase/tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp
|
|
+++ b/qtbase/tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp
|
|
@@ -31,6 +31,7 @@
|
|
#include <QtCore/qfileinfo.h>
|
|
#include <QtCore/qplugin.h>
|
|
#include <private/qfactoryloader_p.h>
|
|
+#include <private/qlibrary_p.h>
|
|
#include "plugin1/plugininterface1.h"
|
|
#include "plugin2/plugininterface2.h"
|
|
|
|
@@ -52,6 +53,7 @@ public slots:
|
|
|
|
private slots:
|
|
void usingTwoFactoriesFromSameDir();
|
|
+ void multiplePaths();
|
|
};
|
|
|
|
static const char binFolderC[] = "bin";
|
|
@@ -92,5 +94,30 @@ void tst_QFactoryLoader::usingTwoFactoriesFromSameDir()
|
|
QCOMPARE(plugin2->pluginName(), QLatin1String("Plugin2 ok"));
|
|
}
|
|
|
|
+void tst_QFactoryLoader::multiplePaths()
|
|
+{
|
|
+#if !QT_CONFIG(library) || !(defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)) || defined(Q_OS_ANDROID)
|
|
+ QSKIP("Test not applicable in this configuration.");
|
|
+#else
|
|
+ const QString binFolder = QFINDTESTDATA(binFolderC);
|
|
+
|
|
+ QTemporaryDir dir;
|
|
+ QVERIFY(dir.isValid());
|
|
+
|
|
+ QString pluginsPath = QFileInfo(binFolder, binFolderC).absolutePath();
|
|
+ QString linkPath = dir.filePath(binFolderC);
|
|
+ QVERIFY(QFile::link(pluginsPath, linkPath));
|
|
+
|
|
+ QCoreApplication::setLibraryPaths({ QFileInfo(binFolder).absolutePath(), dir.path() });
|
|
+
|
|
+ const QString suffix = QLatin1Char('/') + QLatin1String(binFolderC);
|
|
+ QFactoryLoader loader1(PluginInterface1_iid, suffix);
|
|
+
|
|
+ QLibraryPrivate *library1 = loader1.library("plugin1");
|
|
+ QVERIFY(library1);
|
|
+ QCOMPARE(library1->loadHints(), QLibrary::PreventUnloadHint);
|
|
+#endif
|
|
+}
|
|
+
|
|
QTEST_MAIN(tst_QFactoryLoader)
|
|
#include "tst_qfactoryloader.moc"
|
|
diff --git a/qtbase/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/qtbase/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
|
|
index ce8057372c..833f68b1de 100644
|
|
--- a/qtbase/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
|
|
+++ b/qtbase/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
|
|
@@ -193,7 +193,9 @@ void tst_QPluginLoader::errorString()
|
|
QVERIFY(!unloaded);
|
|
}
|
|
|
|
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_HPUX)
|
|
+// A bug in QNX causes the test to crash on exit after attempting to load
|
|
+// a shared library with undefined symbols (tracked as QTBUG-114682).
|
|
+#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_HPUX) && !defined(Q_OS_QNX)
|
|
{
|
|
QPluginLoader loader( sys_qualifiedLibraryName("almostplugin")); //a plugin with unresolved symbols
|
|
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
|
@@ -243,10 +245,37 @@ void tst_QPluginLoader::loadHints()
|
|
QSKIP("This test requires Qt to create shared libraries.");
|
|
#endif
|
|
QPluginLoader loader;
|
|
- QCOMPARE(loader.loadHints(), QLibrary::LoadHints{}); //Do not crash
|
|
+ QCOMPARE(loader.loadHints(), QLibrary::PreventUnloadHint); //Do not crash
|
|
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
|
+ QCOMPARE(loader.loadHints(), QLibrary::ResolveAllSymbolsHint);
|
|
+ // We can clear load hints when file name is not set.
|
|
+ loader.setLoadHints(QLibrary::LoadHints{});
|
|
+ QCOMPARE(loader.loadHints(), QLibrary::LoadHints{});
|
|
+ // Set the hints again
|
|
+ loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
|
+ QCOMPARE(loader.loadHints(), QLibrary::ResolveAllSymbolsHint);
|
|
loader.setFileName( sys_qualifiedLibraryName("theplugin")); //a plugin
|
|
QCOMPARE(loader.loadHints(), QLibrary::ResolveAllSymbolsHint);
|
|
+
|
|
+ QPluginLoader loader4;
|
|
+ QCOMPARE(loader4.loadHints(), QLibrary::PreventUnloadHint);
|
|
+ loader4.setLoadHints(QLibrary::LoadHints{});
|
|
+ QCOMPARE(loader4.loadHints(), QLibrary::LoadHints{});
|
|
+ loader4.setFileName(sys_qualifiedLibraryName("theplugin"));
|
|
+ // Hints are merged with hints from the previous loader.
|
|
+ QCOMPARE(loader4.loadHints(), QLibrary::ResolveAllSymbolsHint);
|
|
+ // We cannot clear load hints after associating the loader with a file.
|
|
+ loader.setLoadHints(QLibrary::LoadHints{});
|
|
+ QCOMPARE(loader.loadHints(), QLibrary::ResolveAllSymbolsHint);
|
|
+
|
|
+ QPluginLoader loader2;
|
|
+ QCOMPARE(loader2.loadHints(), QLibrary::PreventUnloadHint);
|
|
+ loader2.setFileName(sys_qualifiedLibraryName("theplugin"));
|
|
+ // Hints are merged with hints from previous loaders.
|
|
+ QCOMPARE(loader2.loadHints(), QLibrary::PreventUnloadHint | QLibrary::ResolveAllSymbolsHint);
|
|
+
|
|
+ QPluginLoader loader3(sys_qualifiedLibraryName("theplugin"));
|
|
+ QCOMPARE(loader3.loadHints(), QLibrary::PreventUnloadHint | QLibrary::ResolveAllSymbolsHint);
|
|
}
|
|
|
|
void tst_QPluginLoader::deleteinstanceOnUnload()
|
|
diff --git a/qtbase/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/qtbase/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
|
|
index 533fb1c8aa..63ce77d67f 100644
|
|
--- a/qtbase/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
|
|
+++ b/qtbase/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
|
|
@@ -75,6 +75,7 @@ private slots:
|
|
void arrayStringElements();
|
|
void arraySelfAssign_data() { basics_data(); }
|
|
void arraySelfAssign();
|
|
+ void arrayNested();
|
|
|
|
void mapDefaultInitialization();
|
|
void mapEmptyInitializerList();
|
|
@@ -93,6 +94,7 @@ private slots:
|
|
void mapSelfAssign();
|
|
void mapComplexKeys_data() { basics_data(); }
|
|
void mapComplexKeys();
|
|
+ void mapNested();
|
|
|
|
void sorting();
|
|
|
|
@@ -1570,6 +1572,91 @@ void tst_QCborValue::mapComplexKeys()
|
|
QVERIFY(!m.contains(tagged));
|
|
}
|
|
|
|
+void tst_QCborValue::arrayNested()
|
|
+{
|
|
+ const QCborArray wrongArray = { false, nullptr, QCborValue() };
|
|
+ {
|
|
+ QCborArray a1 = { 42, 47 };
|
|
+ QCborArray a2 = { QCborValue(a1) };
|
|
+ QCOMPARE(a2.size(), 1);
|
|
+ const QCborValue &first = qAsConst(a2).first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first.toArray(wrongArray).size(), 2);
|
|
+ QCOMPARE(first.toArray(wrongArray).first(), 42);
|
|
+ QCOMPARE(first.toArray(wrongArray).last(), 47);
|
|
+ }
|
|
+ {
|
|
+ QCborArray a1 = { 42, 47 };
|
|
+ QCborArray a2 = { QCborValue(a1) };
|
|
+ QCOMPARE(a2.size(), 1);
|
|
+ QCborValueRef first = a2.first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first.toArray(wrongArray).size(), 2);
|
|
+ QCOMPARE(first.toArray(wrongArray).first(), 42);
|
|
+ QCOMPARE(first.toArray(wrongArray).last(), 47);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ QCborArray a1;
|
|
+ a1 = { QCborValue(a1) }; // insert it into itself
|
|
+ QCOMPARE(a1.size(), 1);
|
|
+ const QCborValue &first = qAsConst(a1).first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first, QCborArray());
|
|
+ QCOMPARE(first.toArray(wrongArray), QCborArray());
|
|
+ }
|
|
+ {
|
|
+ QCborArray a1;
|
|
+ a1 = { QCborValue(a1) }; // insert it into itself
|
|
+ QCborValueRef first = a1.first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first, QCborArray());
|
|
+ QCOMPARE(first.toArray(wrongArray), QCborArray());
|
|
+ }
|
|
+ {
|
|
+ QCborArray a1;
|
|
+ a1.append(a1); // insert into itself
|
|
+ QCOMPARE(a1.size(), 1);
|
|
+ const QCborValue &first = qAsConst(a1).first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first, QCborArray());
|
|
+ QCOMPARE(first.toArray(), QCborArray());
|
|
+ }
|
|
+ {
|
|
+ QCborArray a1;
|
|
+ a1.append(a1); // insert into itself
|
|
+ QCborValueRef first = a1.first();
|
|
+ QVERIFY(first.isArray());
|
|
+ QCOMPARE(first, QCborArray());
|
|
+ QCOMPARE(first.toArray(), QCborArray());
|
|
+ }
|
|
+}
|
|
+
|
|
+void tst_QCborValue::mapNested()
|
|
+{
|
|
+ const QCborMap wrongMap = { { -1, false }, {-2, nullptr }, { -3, QCborValue() } };
|
|
+ {
|
|
+ QCborMap m1 = { {1, 42}, {2, 47} };
|
|
+ QCborMap m2 = { { QString(), m1 } };
|
|
+ QCOMPARE(m2.size(), 1);
|
|
+ const QCborValue &first = m2.constBegin().value();
|
|
+ QVERIFY(first.isMap());
|
|
+ QCOMPARE(first.toMap(wrongMap).size(), 2);
|
|
+ QCOMPARE(first.toMap(wrongMap).begin().key(), 1);
|
|
+ QCOMPARE(first.toMap(wrongMap).begin().value(), 42);
|
|
+ }
|
|
+
|
|
+ {
|
|
+ QCborMap m1;
|
|
+ m1 = { { QString(), QCborValue(m1) } }; // insert it into itself
|
|
+ QCOMPARE(m1.size(), 1);
|
|
+ const QCborValue &first = m1.constBegin().value();
|
|
+ QVERIFY(first.isMap());
|
|
+ QCOMPARE(first, QCborMap());
|
|
+ QCOMPARE(first.toMap(wrongMap), QCborMap());
|
|
+ }
|
|
+}
|
|
+
|
|
void tst_QCborValue::sorting()
|
|
{
|
|
QCborValue vundef, vnull(nullptr);
|
|
diff --git a/qtbase/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/qtbase/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
|
|
index d8aa17d9ef..d539941378 100644
|
|
--- a/qtbase/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
|
|
+++ b/qtbase/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
|
|
@@ -869,7 +869,11 @@ void tst_QByteArray::qvsnprintf()
|
|
|
|
#ifndef Q_OS_WIN
|
|
memset(buf, 42, sizeof(buf));
|
|
+ QT_WARNING_PUSH
|
|
+ QT_WARNING_DISABLE_GCC("-Wformat-zero-length")
|
|
+ QT_WARNING_DISABLE_CLANG("-Wformat-zero-length")
|
|
QCOMPARE(::qsnprintf(buf, 10, ""), 0);
|
|
+ QT_WARNING_POP
|
|
#endif
|
|
}
|
|
|
|
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/painting/qpainter/tst_qpainter.cpp b/qtbase/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
|
|
index d7c3f95f1d..bfc77b0831 100644
|
|
--- a/qtbase/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
|
|
+++ b/qtbase/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
|
|
@@ -84,6 +84,7 @@ private slots:
|
|
#endif
|
|
void drawPixmapFragments();
|
|
void drawPixmapNegativeScale();
|
|
+ void drawPixmapRounding();
|
|
|
|
void drawLine_data();
|
|
void drawLine();
|
|
@@ -799,6 +800,16 @@ void tst_QPainter::drawPixmapNegativeScale()
|
|
QVERIFY(resultImage.pixel(12, 8) == qRgba(0, 0, 0, 255)); // and right strip is now black
|
|
}
|
|
|
|
+void tst_QPainter::drawPixmapRounding()
|
|
+{
|
|
+ // Just test that we don't assert
|
|
+ QBitmap bm(8, 8);
|
|
+ QImage out(64, 64, QImage::Format_RGB32);
|
|
+ QPainter p(&out);
|
|
+ qreal y = 26.499999999999996;
|
|
+ p.drawPixmap(QPointF(0, y), bm);
|
|
+}
|
|
+
|
|
void tst_QPainter::drawLine_data()
|
|
{
|
|
QTest::addColumn<QLine>("line");
|
|
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/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/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
|
|
index f6ad97a96b..61452dceae 100644
|
|
--- a/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
|
|
+++ b/qtbase/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
|
|
@@ -116,6 +116,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 18282505e4..ce518e78fb 100644
|
|
--- a/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json
|
|
+++ b/qtbase/tests/auto/tools/moc/allmocs_baseline_in.json
|
|
@@ -668,40 +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"
|
|
- }
|
|
- ],
|
|
- "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 ba9450c271..0000000000
|
|
--- a/qtbase/tests/auto/tools/moc/task189996.h
|
|
+++ /dev/null
|
|
@@ -1,45 +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() noexcept { }
|
|
- void b() const noexcept { }
|
|
- void c() noexcept;
|
|
-};
|
|
-
|
|
-#endif
|
|
diff --git a/qtbase/tests/auto/tools/moc/tst_moc.cpp b/qtbase/tests/auto/tools/moc/tst_moc.cpp
|
|
index cc465a213a..a9ab6ec4f3 100644
|
|
--- a/qtbase/tests/auto/tools/moc/tst_moc.cpp
|
|
+++ b/qtbase/tests/auto/tools/moc/tst_moc.cpp
|
|
@@ -671,7 +671,6 @@ private slots:
|
|
void templateGtGt();
|
|
void qprivateslots();
|
|
void qprivateproperties();
|
|
- void inlineSlotsWithThrowDeclaration();
|
|
void warnOnPropertyWithoutREAD();
|
|
void constructors();
|
|
void typenameWithUnsigned();
|
|
@@ -816,7 +815,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);
|
|
@@ -886,7 +885,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);
|
|
@@ -1166,7 +1165,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);
|
|
@@ -1585,19 +1584,6 @@ void tst_Moc::qprivateproperties()
|
|
|
|
}
|
|
|
|
-#include "task189996.h"
|
|
-
|
|
-void InlineSlotsWithThrowDeclaration::c() noexcept {}
|
|
-
|
|
-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);
|
|
-}
|
|
-
|
|
void tst_Moc::warnOnPropertyWithoutREAD()
|
|
{
|
|
#ifdef MOC_CROSS_COMPILED
|
|
@@ -1859,7 +1845,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/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/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 7af60ed757..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;
|
|
@@ -3642,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/qdial/tst_qdial.cpp b/qtbase/tests/auto/widgets/widgets/qdial/tst_qdial.cpp
|
|
index 356f773ae9..a014df3b15 100644
|
|
--- a/qtbase/tests/auto/widgets/widgets/qdial/tst_qdial.cpp
|
|
+++ b/qtbase/tests/auto/widgets/widgets/qdial/tst_qdial.cpp
|
|
@@ -42,6 +42,7 @@ private slots:
|
|
void valueChanged();
|
|
void sliderMoved();
|
|
void wrappingCheck();
|
|
+ void minEqualMaxValueOutsideRange();
|
|
};
|
|
|
|
// Testing get/set functions
|
|
@@ -194,5 +195,14 @@ void tst_QDial::wrappingCheck()
|
|
}
|
|
}
|
|
|
|
+// QTBUG-104641
|
|
+void tst_QDial::minEqualMaxValueOutsideRange()
|
|
+{
|
|
+ QDial dial;
|
|
+ dial.setRange(30, 30);
|
|
+ dial.setWrapping(true);
|
|
+ dial.setValue(45);
|
|
+}
|
|
+
|
|
QTEST_MAIN(tst_QDial)
|
|
#include "tst_qdial.moc"
|
|
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 qtcanvas3d 1319e096...00000000 (submodule deleted)
|
|
Submodule qtconnectivity b242dc4f..c8a0f0b1:
|
|
diff --git a/qtconnectivity/src/tools/sdpscanner/main.cpp b/qtconnectivity/src/tools/sdpscanner/main.cpp
|
|
index c39ff8f3..e005a70f 100644
|
|
--- a/qtconnectivity/src/tools/sdpscanner/main.cpp
|
|
+++ b/qtconnectivity/src/tools/sdpscanner/main.cpp
|
|
@@ -96,7 +96,8 @@ static void parseAttributeValues(sdp_data_t *data, int indentation, QByteArray &
|
|
xmlOutput.append(snBuffer);
|
|
break;
|
|
case SDP_UINT64:
|
|
- qsnprintf(snBuffer, BUFFER_SIZE, "<uint64 value=\"0x%016x\"/>\n", data->val.uint64);
|
|
+ qsnprintf(snBuffer, BUFFER_SIZE, "<uint64 value=\"0x%016llx\"/>\n",
|
|
+ qulonglong(data->val.uint64));
|
|
xmlOutput.append(snBuffer);
|
|
break;
|
|
case SDP_UINT128:
|
|
@@ -119,7 +120,8 @@ static void parseAttributeValues(sdp_data_t *data, int indentation, QByteArray &
|
|
xmlOutput.append(snBuffer);
|
|
break;
|
|
case SDP_INT64:
|
|
- qsnprintf(snBuffer, BUFFER_SIZE, "<int64 value=\"%d\"/>/n", data->val.int64);
|
|
+ qsnprintf(snBuffer, BUFFER_SIZE, "<int64 value=\"%lld\"/>/n",
|
|
+ qlonglong(data->val.int64));
|
|
xmlOutput.append(snBuffer);
|
|
break;
|
|
case SDP_INT128:
|
|
Submodule qtdeclarative abe4729e..e2b38659:
|
|
diff --git a/qtdeclarative/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/qtdeclarative/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
index b5c5f6a2b0..1a3d3cdf97 100644
|
|
--- a/qtdeclarative/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
+++ b/qtdeclarative/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
|
|
@@ -112,10 +112,7 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
|
|
if (result == MAP_FAILED)
|
|
CRASH();
|
|
|
|
- while (madvise(result, bytes, MADV_DONTNEED)) {
|
|
- if (errno != EAGAIN)
|
|
- CRASH();
|
|
- }
|
|
+ while (madvise(result, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
|
|
|
|
if (fd != -1)
|
|
close(fd);
|
|
@@ -248,8 +245,10 @@ void OSAllocator::decommit(void* address, size_t bytes)
|
|
mmap(address, bytes, PROT_NONE, MAP_FIXED | MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
#elif OS(LINUX)
|
|
while (madvise(address, bytes, MADV_DONTNEED)) {
|
|
- if (errno != EAGAIN)
|
|
- CRASH();
|
|
+ if (errno != EAGAIN) {
|
|
+ memset(address, 0, bytes); // We rely on madvise to zero-out the memory
|
|
+ break;
|
|
+ }
|
|
}
|
|
if (mprotect(address, bytes, PROT_NONE))
|
|
CRASH();
|
|
diff --git a/qtdeclarative/src/qml/jsruntime/qv4function.cpp b/qtdeclarative/src/qml/jsruntime/qv4function.cpp
|
|
index cf8a53cf9f..223e64271e 100644
|
|
--- a/qtdeclarative/src/qml/jsruntime/qv4function.cpp
|
|
+++ b/qtdeclarative/src/qml/jsruntime/qv4function.cpp
|
|
@@ -136,7 +136,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
|
|
if (duplicate == -1) {
|
|
parameterNames.append(QString::fromUtf8(param));
|
|
} else {
|
|
- const QString &dup = parameterNames[duplicate];
|
|
+ const QString dup = parameterNames[duplicate];
|
|
parameterNames.append(dup);
|
|
parameterNames[duplicate] =
|
|
QString(0xfffe) + QString::number(duplicate) + dup;
|
|
diff --git a/qtdeclarative/src/qml/qml/qqmldata_p.h b/qtdeclarative/src/qml/qml/qqmldata_p.h
|
|
index c44fb8608e..69dac27c9a 100644
|
|
--- a/qtdeclarative/src/qml/qml/qqmldata_p.h
|
|
+++ b/qtdeclarative/src/qml/qml/qqmldata_p.h
|
|
@@ -185,7 +185,7 @@ public:
|
|
private:
|
|
void layout(QQmlNotifierEndpoint*);
|
|
};
|
|
- QAtomicPointer<NotifyList> notifyList;
|
|
+ QAtomicPointer<NotifyList> notifyList = nullptr;
|
|
|
|
inline QQmlNotifierEndpoint *notify(int index) const;
|
|
void addNotify(int index, QQmlNotifierEndpoint *);
|
|
@@ -201,12 +201,12 @@ public:
|
|
QQmlContextData *outerContext = nullptr;
|
|
QQmlContextDataRef ownContext;
|
|
|
|
- QQmlAbstractBinding *bindings;
|
|
- QQmlBoundSignal *signalHandlers;
|
|
+ QQmlAbstractBinding *bindings = nullptr;
|
|
+ QQmlBoundSignal *signalHandlers = nullptr;
|
|
|
|
// Linked list for QQmlContext::contextObjects
|
|
- QQmlData *nextContextObject;
|
|
- QQmlData**prevContextObject;
|
|
+ QQmlData *nextContextObject = nullptr;
|
|
+ QQmlData**prevContextObject = nullptr;
|
|
|
|
inline bool hasBindingBit(int) const;
|
|
inline void setBindingBit(QObject *obj, int);
|
|
@@ -216,10 +216,10 @@ public:
|
|
inline void setPendingBindingBit(QObject *obj, int);
|
|
inline void clearPendingBindingBit(int);
|
|
|
|
- quint16 lineNumber;
|
|
- quint16 columnNumber;
|
|
+ quint16 lineNumber = 0;
|
|
+ quint16 columnNumber = 0;
|
|
|
|
- quint32 jsEngineId; // id of the engine that created the jsWrapper
|
|
+ quint32 jsEngineId = 0; // id of the engine that created the jsWrapper
|
|
|
|
struct DeferredData {
|
|
DeferredData();
|
|
@@ -240,7 +240,7 @@ public:
|
|
|
|
QQmlPropertyCache *propertyCache;
|
|
|
|
- QQmlGuardImpl *guards;
|
|
+ QQmlGuardImpl *guards = 0;
|
|
|
|
static QQmlData *get(const QObject *object, bool create = false) {
|
|
QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
|
|
@@ -289,7 +289,7 @@ public:
|
|
|
|
private:
|
|
// For attachedProperties
|
|
- mutable QQmlDataExtended *extendedData;
|
|
+ mutable QQmlDataExtended *extendedData = nullptr;
|
|
|
|
Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv);
|
|
Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object);
|
|
diff --git a/qtdeclarative/src/qml/qml/qqmlengine.cpp b/qtdeclarative/src/qml/qml/qqmlengine.cpp
|
|
index 2325c4c1e0..069e369319 100644
|
|
--- a/qtdeclarative/src/qml/qml/qqmlengine.cpp
|
|
+++ b/qtdeclarative/src/qml/qml/qqmlengine.cpp
|
|
@@ -725,11 +725,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
|
|
QQmlData::QQmlData()
|
|
: ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false),
|
|
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
|
|
- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
|
|
- bindingBitsArraySize(InlineBindingArraySize), notifyList(nullptr),
|
|
- bindings(nullptr), signalHandlers(nullptr), nextContextObject(nullptr), prevContextObject(nullptr),
|
|
- lineNumber(0), columnNumber(0), jsEngineId(0),
|
|
- propertyCache(nullptr), guards(nullptr), extendedData(nullptr)
|
|
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), dummy(0),
|
|
+ bindingBitsArraySize(InlineBindingArraySize), propertyCache(nullptr)
|
|
{
|
|
memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
|
|
init();
|
|
@@ -1591,17 +1588,22 @@ void qmlExecuteDeferred(QObject *object)
|
|
{
|
|
QQmlData *data = QQmlData::get(object);
|
|
|
|
- if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) {
|
|
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
|
|
+ if (!data
|
|
+ || !data->context
|
|
+ || !data->context->engine
|
|
+ || data->deferredData.isEmpty()
|
|
+ || data->wasDeleted(object)) {
|
|
+ return;
|
|
+ }
|
|
|
|
- QQmlComponentPrivate::DeferredState state;
|
|
- QQmlComponentPrivate::beginDeferred(ep, object, &state);
|
|
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
|
|
+ QQmlComponentPrivate::DeferredState state;
|
|
+ QQmlComponentPrivate::beginDeferred(ep, object, &state);
|
|
|
|
- // Release the reference for the deferral action (we still have one from construction)
|
|
- data->releaseDeferredData();
|
|
+ // Release the reference for the deferral action (we still have one from construction)
|
|
+ data->releaseDeferredData();
|
|
|
|
- QQmlComponentPrivate::completeDeferred(ep, &state);
|
|
- }
|
|
+ QQmlComponentPrivate::completeDeferred(ep, &state);
|
|
}
|
|
|
|
QQmlContext *qmlContext(const QObject *obj)
|
|
diff --git a/qtdeclarative/src/qml/qml/qqmlimport.cpp b/qtdeclarative/src/qml/qml/qqmlimport.cpp
|
|
index e7263d1850..289f11d006 100644
|
|
--- a/qtdeclarative/src/qml/qml/qqmlimport.cpp
|
|
+++ b/qtdeclarative/src/qml/qml/qqmlimport.cpp
|
|
@@ -2119,9 +2119,12 @@ void QQmlImportDatabase::addImportPath(const QString& path)
|
|
cPath.replace(Backslash, Slash);
|
|
}
|
|
|
|
- if (!cPath.isEmpty()
|
|
- && !fileImportPath.contains(cPath))
|
|
- fileImportPath.prepend(cPath);
|
|
+ if (!cPath.isEmpty()) {
|
|
+ if (fileImportPath.contains(cPath))
|
|
+ fileImportPath.move(fileImportPath.indexOf(cPath), 0);
|
|
+ else
|
|
+ fileImportPath.prepend(cPath);
|
|
+ }
|
|
}
|
|
|
|
/*!
|
|
diff --git a/qtdeclarative/src/qml/qml/qqmlvmemetaobject.cpp b/qtdeclarative/src/qml/qml/qqmlvmemetaobject.cpp
|
|
index 4fd2092fd3..0d59d197dc 100644
|
|
--- a/qtdeclarative/src/qml/qml/qqmlvmemetaobject.cpp
|
|
+++ b/qtdeclarative/src/qml/qml/qqmlvmemetaobject.cpp
|
|
@@ -254,7 +254,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
|
|
if (!pd)
|
|
return;
|
|
|
|
- if (pd->notifyIndex() != -1)
|
|
+ if (pd->notifyIndex() != -1 && ctxt->engine)
|
|
connect(target, pd->notifyIndex(), ctxt->engine);
|
|
}
|
|
|
|
diff --git a/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp b/qtdeclarative/src/qmlmodels/qqmldelegatemodel.cpp
|
|
index 3b57edfc5d..5b7e767ae2 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)),
|
|
@@ -1979,6 +1991,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 36b65f906c..99e6eff7c3 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();
|
|
@@ -193,7 +202,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;
|
|
@@ -206,6 +215,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 c655b4c327..8b139cb539 100644
|
|
--- a/qtdeclarative/src/quick/items/qquickitem.cpp
|
|
+++ b/qtdeclarative/src/quick/items/qquickitem.cpp
|
|
@@ -2328,6 +2328,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().
|
|
@@ -2695,9 +2696,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);
|
|
}
|
|
@@ -2774,8 +2774,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();
|
|
}
|
|
|
|
@@ -2971,7 +2972,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
|
|
|
|
itemChange(QQuickItem::ItemChildRemovedChange, child);
|
|
|
|
- emit q->childrenChanged();
|
|
+ if (!inDestructor)
|
|
+ emit q->childrenChanged();
|
|
}
|
|
|
|
void QQuickItemPrivate::refWindow(QQuickWindow *c)
|
|
@@ -3200,6 +3202,7 @@ QQuickItemPrivate::QQuickItemPrivate()
|
|
, touchEnabled(false)
|
|
#endif
|
|
, hasCursorHandler(false)
|
|
+ , inDestructor(false)
|
|
, dirtyAttributes(0)
|
|
, nextDirtyItem(nullptr)
|
|
, prevDirtyItem(nullptr)
|
|
@@ -5126,6 +5129,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()
|
|
@@ -6112,9 +6122,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
|
|
}
|
|
@@ -6163,6 +6175,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 d48b551064..6f329bd119 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/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/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 cf021d9a7c..b0117683f7 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();
|
|
@@ -1527,19 +1536,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)
|
|
@@ -1552,7 +1558,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/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 f0afdb16ca..e5daf2d28b 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>
|
|
@@ -48,6 +50,8 @@ private slots:
|
|
void qtbug_86017();
|
|
void contextAccessedByHandler();
|
|
void deleteRace();
|
|
+ void redrawUponColumnChange();
|
|
+ void deleteRace();
|
|
};
|
|
|
|
class AbstractItemModel : public QAbstractItemModel
|
|
@@ -187,6 +191,41 @@ void tst_QQmlDelegateModel::deleteRace()
|
|
QTRY_COMPARE(o->property("count").toInt(), 0);
|
|
}
|
|
|
|
+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");
|
|
+}
|
|
+
|
|
+void tst_QQmlDelegateModel::deleteRace()
|
|
+{
|
|
+ QQmlEngine engine;
|
|
+ QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
|
|
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
|
|
+ QScopedPointer<QObject> o(c.create());
|
|
+ QVERIFY(!o.isNull());
|
|
+ QTRY_COMPARE(o->property("count").toInt(), 2);
|
|
+ QTRY_COMPARE(o->property("count").toInt(), 0);
|
|
+}
|
|
+
|
|
QTEST_MAIN(tst_QQmlDelegateModel)
|
|
|
|
#include "tst_qqmldelegatemodel.moc"
|
|
diff --git a/qtdeclarative/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/qtdeclarative/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
|
|
index 9c865b3f73..1f788f7a7f 100644
|
|
--- a/qtdeclarative/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
|
|
+++ b/qtdeclarative/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
|
|
@@ -154,6 +154,11 @@ void tst_QQmlImport::importPathOrder()
|
|
engine.addImportPath(QT_QMLTEST_DATADIR);
|
|
expectedImportPaths.prepend(QT_QMLTEST_DATADIR);
|
|
QCOMPARE(expectedImportPaths, engine.importPathList());
|
|
+
|
|
+ // Add qml2Imports again to make it the first of the list
|
|
+ engine.addImportPath(qml2Imports);
|
|
+ expectedImportPaths.move(expectedImportPaths.indexOf(qml2Imports), 0);
|
|
+ QCOMPARE(expectedImportPaths, engine.importPathList());
|
|
}
|
|
|
|
Q_DECLARE_METATYPE(QQmlImports::ImportVersion)
|
|
diff --git a/qtdeclarative/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml b/qtdeclarative/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml
|
|
new file mode 100644
|
|
index 0000000000..38dfde41c3
|
|
--- /dev/null
|
|
+++ b/qtdeclarative/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml
|
|
@@ -0,0 +1,74 @@
|
|
+/****************************************************************************
|
|
+**
|
|
+** 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.
|
|
+**
|
|
+** $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
|
|
+import QtQuick.Controls 2
|
|
+ApplicationWindow {
|
|
+ visible: true
|
|
+ width: 640
|
|
+ height: 480
|
|
+
|
|
+ ListView {
|
|
+ anchors.fill: parent
|
|
+ model: 2
|
|
+
|
|
+ delegate: SwipeDelegate {
|
|
+ text: "Swipe me left (should not crash)"
|
|
+
|
|
+ swipe.right: Label {
|
|
+ text: "Release (should not crash)"
|
|
+ }
|
|
+
|
|
+ swipe.onCompleted: {
|
|
+ swipe.close()
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
Submodule qtdoc 2653ffbb...47e2864f:
|
|
Submodule qtdocgallery e36e6f0a...00000000 (submodule deleted)
|
|
Submodule qtfeedback 9ac8d8c2...00000000 (submodule deleted)
|
|
Submodule qtimageformats a9636f96..7b25a043:
|
|
diff --git a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
|
|
index f0dfe7f..5cb0522 100644
|
|
--- a/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
|
|
+++ b/qtimageformats/src/plugins/imageformats/tiff/qtiffhandler.cpp
|
|
@@ -38,13 +38,14 @@
|
|
****************************************************************************/
|
|
|
|
#include "qtiffhandler_p.h"
|
|
-#include <qvariant.h>
|
|
#include <qcolorspace.h>
|
|
#include <qdebug.h>
|
|
#include <qimage.h>
|
|
#include <qglobal.h>
|
|
#include <qbuffer.h>
|
|
#include <qfiledevice.h>
|
|
+#include <qvariant.h>
|
|
+#include <qvarlengtharray.h>
|
|
|
|
extern "C" {
|
|
#include "tiffio.h"
|
|
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 2bcec6f6..6e89db9f:
|
|
Submodule src/3rdparty/mapbox-gl-native d3101bbc...35d56672 (commits not present)
|
|
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/nokia/qgeocodingmanagerengine_nokia.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
|
|
index 68b2429e..deef29f9 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
|
|
@@ -66,11 +66,8 @@ QGeoCodingManagerEngineNokia::QGeoCodingManagerEngineNokia(
|
|
Q_ASSERT(networkManager);
|
|
m_networkManager->setParent(this);
|
|
|
|
- if (parameters.contains(QStringLiteral("here.token")))
|
|
- m_token = parameters.value(QStringLiteral("here.token")).toString();
|
|
-
|
|
- if (parameters.contains(QStringLiteral("here.app_id")))
|
|
- m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString();
|
|
+ if (parameters.contains(QStringLiteral("here.apiKey")))
|
|
+ m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
|
|
|
|
if (error)
|
|
*error = QGeoServiceProvider::NoError;
|
|
@@ -85,12 +82,9 @@ QString QGeoCodingManagerEngineNokia::getAuthenticationString() const
|
|
{
|
|
QString authenticationString;
|
|
|
|
- if (!m_token.isEmpty() && !m_applicationId.isEmpty()) {
|
|
- authenticationString += "?app_code=";
|
|
- authenticationString += m_token;
|
|
-
|
|
- authenticationString += "&app_id=";
|
|
- authenticationString += m_applicationId;
|
|
+ if (!m_apiKey.isEmpty()) {
|
|
+ authenticationString += "?apiKey=";
|
|
+ authenticationString += m_apiKey;
|
|
}
|
|
|
|
return authenticationString;
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h b/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
|
|
index 9e1564aa..a7cfd06a 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
|
|
@@ -82,8 +82,7 @@ private:
|
|
QGeoNetworkAccessManager *m_networkManager;
|
|
QGeoUriProvider *m_uriProvider;
|
|
QGeoUriProvider *m_reverseGeocodingUriProvider;
|
|
- QString m_token;
|
|
- QString m_applicationId;
|
|
+ QString m_apiKey;
|
|
};
|
|
|
|
QT_END_NAMESPACE
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeoerror_messages.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeoerror_messages.cpp
|
|
index 576ecd43..f49e0905 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeoerror_messages.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeoerror_messages.cpp
|
|
@@ -39,7 +39,7 @@
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
const char NOKIA_PLUGIN_CONTEXT_NAME[] = "QtLocationQML";
|
|
-const char MISSED_CREDENTIALS[] = QT_TRANSLATE_NOOP("QtLocationQML", "Qt Location requires app_id and token parameters.\nPlease register at https://developer.here.com/ to get your personal application credentials.");
|
|
+const char MISSED_CREDENTIALS[] = QT_TRANSLATE_NOOP("QtLocationQML", "Qt Location requires apiKey parameter.\nPlease register at https://developer.here.com/ to get your personal application credentials.");
|
|
const char SAVING_PLACE_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Saving places is not supported.");
|
|
const char REMOVING_PLACE_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Removing places is not supported.");
|
|
const char SAVING_CATEGORY_NOT_SUPPORTED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Saving categories is not supported.");
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
|
|
index 73b998b1..a938096b 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
|
|
@@ -60,8 +60,7 @@ QGeoRoutingManagerEngineNokia::QGeoRoutingManagerEngineNokia(
|
|
Q_ASSERT(networkManager);
|
|
m_networkManager->setParent(this);
|
|
|
|
- m_appId = parameters.value(QStringLiteral("here.app_id")).toString();
|
|
- m_token = parameters.value(QStringLiteral("here.token")).toString();
|
|
+ m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
|
|
|
|
QGeoRouteRequest::FeatureTypes featureTypes;
|
|
featureTypes |= QGeoRouteRequest::TollFeature;
|
|
@@ -219,18 +218,16 @@ QStringList QGeoRoutingManagerEngineNokia::calculateRouteRequestString(const QGe
|
|
return QStringList();
|
|
QStringList requests;
|
|
|
|
- QString baseRequest = QStringLiteral("http://");
|
|
+ QString baseRequest = QStringLiteral("https://");
|
|
baseRequest += m_uriProvider->getCurrentHost();
|
|
baseRequest += QStringLiteral("/routing/7.2/calculateroute.xml");
|
|
|
|
baseRequest += QStringLiteral("?alternatives=");
|
|
baseRequest += QString::number(request.numberAlternativeRoutes());
|
|
|
|
- if (!m_appId.isEmpty() && !m_token.isEmpty()) {
|
|
- baseRequest += QStringLiteral("&app_id=");
|
|
- baseRequest += m_appId;
|
|
- baseRequest += QStringLiteral("&token=");
|
|
- baseRequest += m_token;
|
|
+ if (!m_apiKey.isEmpty()) {
|
|
+ baseRequest += QStringLiteral("&apiKey=");
|
|
+ baseRequest += m_apiKey;
|
|
}
|
|
|
|
const QList<QVariantMap> metadata = request.waypointsMetadata();
|
|
@@ -281,7 +278,7 @@ QStringList QGeoRoutingManagerEngineNokia::updateRouteRequestString(const QGeoRo
|
|
return QStringList();
|
|
QStringList requests;
|
|
|
|
- QString baseRequest = "http://";
|
|
+ QString baseRequest = "https://";
|
|
baseRequest += m_uriProvider->getCurrentHost();
|
|
baseRequest += "/routing/7.2/getroute.xml";
|
|
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h b/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h
|
|
index 9335bcac..67fb5825 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h
|
|
@@ -77,8 +77,7 @@ private:
|
|
|
|
QGeoNetworkAccessManager *m_networkManager;
|
|
QGeoUriProvider *m_uriProvider;
|
|
- QString m_appId;
|
|
- QString m_token;
|
|
+ QString m_apiKey;
|
|
};
|
|
|
|
QT_END_NAMESPACE
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
|
|
index e4ef86d6..2c53dd16 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
|
|
@@ -75,20 +75,15 @@ namespace
|
|
|
|
void checkUsageTerms(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString)
|
|
{
|
|
- QString appId, token;
|
|
+ const QString apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
|
|
|
|
- appId = parameters.value(QStringLiteral("here.app_id")).toString();
|
|
- token = parameters.value(QStringLiteral("here.token")).toString();
|
|
-
|
|
- if (isValidParameter(appId) && isValidParameter(token))
|
|
+ if (isValidParameter(apiKey))
|
|
return;
|
|
- else if (!isValidParameter(appId))
|
|
- qWarning() << "Invalid here.app_id";
|
|
else
|
|
- qWarning() << "Invalid here.token";
|
|
+ qWarning() << "Invalid here.apiKey";
|
|
|
|
- if (parameters.contains(QStringLiteral("app_id")) || parameters.contains(QStringLiteral("token")))
|
|
- qWarning() << QStringLiteral("Please prefix 'app_id' and 'token' with prefix 'here' (e.g.: 'here.app_id')");
|
|
+ if (parameters.contains(QStringLiteral("apiKey")))
|
|
+ qWarning() << QStringLiteral("Please prefix 'apiKey' with prefix 'here' (e.g.: 'here.apiKey')");
|
|
|
|
*error = QGeoServiceProvider::MissingRequiredParameterError;
|
|
*errorString = QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, MISSED_CREDENTIALS);
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
|
|
index d07a93ba..4cfd62f8 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
|
|
@@ -84,8 +84,7 @@ QGeoTileFetcherNokia::QGeoTileFetcherNokia(const QVariantMap ¶meters,
|
|
m_tileSize = qMax(tileSize.width(), tileSize.height());
|
|
m_networkManager->setParent(this);
|
|
|
|
- m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString();
|
|
- m_token = parameters.value(QStringLiteral("here.token")).toString();
|
|
+ m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
|
|
}
|
|
|
|
QGeoTileFetcherNokia::~QGeoTileFetcherNokia()
|
|
@@ -127,7 +126,7 @@ QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec, int ppi
|
|
if (!m_engineNokia)
|
|
return QString();
|
|
|
|
- static const QString http("http://");
|
|
+ static const QString http("https://");
|
|
static const QString path("/maptile/2.1/maptile/newest/");
|
|
static const QChar slash('/');
|
|
|
|
@@ -152,12 +151,9 @@ QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec, int ppi
|
|
static const QString slashpng("/png8");
|
|
requestString += slashpng;
|
|
|
|
- if (!m_token.isEmpty() && !m_applicationId.isEmpty()) { // TODO: remove the if
|
|
- requestString += "?token=";
|
|
- requestString += m_token;
|
|
-
|
|
- requestString += "&app_id=";
|
|
- requestString += m_applicationId;
|
|
+ if (!m_apiKey.isEmpty()) { // TODO: remove the if
|
|
+ requestString += "?apiKey=";
|
|
+ requestString += m_apiKey;
|
|
}
|
|
|
|
requestString += "&ppi=" + QString::number(ppi);
|
|
@@ -235,14 +231,9 @@ QString QGeoTileFetcherNokia::getLanguageString() const
|
|
// No "lg" param means that we want English.
|
|
}
|
|
|
|
-QString QGeoTileFetcherNokia::token() const
|
|
-{
|
|
- return m_token;
|
|
-}
|
|
-
|
|
-QString QGeoTileFetcherNokia::applicationId() const
|
|
+QString QGeoTileFetcherNokia::apiKey() const
|
|
{
|
|
- return m_applicationId;
|
|
+ return m_apiKey;
|
|
}
|
|
|
|
void QGeoTileFetcherNokia::copyrightsFetched()
|
|
@@ -271,19 +262,14 @@ void QGeoTileFetcherNokia::versionFetched()
|
|
|
|
void QGeoTileFetcherNokia::fetchCopyrightsData()
|
|
{
|
|
- QString copyrightUrl = QStringLiteral("http://");
|
|
+ QString copyrightUrl = QStringLiteral("https://");
|
|
|
|
copyrightUrl += m_baseUriProvider->getCurrentHost();
|
|
copyrightUrl += QStringLiteral("/maptile/2.1/copyright/newest?output=json");
|
|
|
|
- if (!token().isEmpty()) {
|
|
- copyrightUrl += QStringLiteral("&token=");
|
|
- copyrightUrl += token();
|
|
- }
|
|
-
|
|
- if (!applicationId().isEmpty()) {
|
|
- copyrightUrl += QStringLiteral("&app_id=");
|
|
- copyrightUrl += applicationId();
|
|
+ if (!apiKey().isEmpty()) {
|
|
+ copyrightUrl += QStringLiteral("&apiKey=");
|
|
+ copyrightUrl += apiKey();
|
|
}
|
|
|
|
QNetworkRequest netRequest((QUrl(copyrightUrl)));
|
|
@@ -303,19 +289,14 @@ void QGeoTileFetcherNokia::fetchCopyrightsData()
|
|
|
|
void QGeoTileFetcherNokia::fetchVersionData()
|
|
{
|
|
- QString versionUrl = QStringLiteral("http://");
|
|
+ QString versionUrl = QStringLiteral("https://");
|
|
|
|
versionUrl += m_baseUriProvider->getCurrentHost();
|
|
versionUrl += QStringLiteral("/maptile/2.1/version");
|
|
|
|
- if (!token().isEmpty()) {
|
|
- versionUrl += QStringLiteral("?token=");
|
|
- versionUrl += token();
|
|
- }
|
|
-
|
|
- if (!applicationId().isEmpty()) {
|
|
- versionUrl += QStringLiteral("&app_id=");
|
|
- versionUrl += applicationId();
|
|
+ if (!apiKey().isEmpty()) {
|
|
+ versionUrl += QStringLiteral("?apiKey=");
|
|
+ versionUrl += apiKey();
|
|
}
|
|
|
|
QNetworkRequest netRequest((QUrl(versionUrl)));
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h b/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
|
|
index 06d1bba9..ee0cb0e9 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
|
|
@@ -62,8 +62,7 @@ public:
|
|
|
|
QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec);
|
|
|
|
- QString token() const;
|
|
- QString applicationId() const;
|
|
+ QString apiKey() const;
|
|
|
|
public Q_SLOTS:
|
|
void copyrightsFetched();
|
|
@@ -82,11 +81,10 @@ private:
|
|
QGeoNetworkAccessManager *m_networkManager;
|
|
int m_tileSize;
|
|
int m_ppi;
|
|
- QString m_token;
|
|
QNetworkReply *m_copyrightsReply;
|
|
QNetworkReply *m_versionReply;
|
|
|
|
- QString m_applicationId;
|
|
+ QString m_apiKey;
|
|
QGeoUriProvider *m_baseUriProvider;
|
|
QGeoUriProvider *m_aerialUriProvider;
|
|
};
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qgeouriprovider.cpp b/qtlocation/src/plugins/geoservices/nokia/qgeouriprovider.cpp
|
|
index 7be90bb2..6a4f6986 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qgeouriprovider.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qgeouriprovider.cpp
|
|
@@ -61,7 +61,7 @@ QGeoUriProvider::QGeoUriProvider(
|
|
QString QGeoUriProvider::getCurrentHost() const
|
|
{
|
|
if (m_maxSubdomains) {
|
|
- QString result(m_firstSubdomain.toLatin1() + QRandomGenerator::global()->bounded(m_maxSubdomains));
|
|
+ QString result(static_cast<char>(m_firstSubdomain.toLatin1() + QRandomGenerator::global()->bounded(m_maxSubdomains)));
|
|
result += '.' + m_currentHost;
|
|
return result;
|
|
}
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
|
|
index c5c05a2e..4c6e9774 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
|
|
@@ -208,8 +208,7 @@ QPlaceManagerEngineNokiaV2::QPlaceManagerEngineNokiaV2(
|
|
|
|
m_locales.append(QLocale());
|
|
|
|
- m_appId = parameters.value(QStringLiteral("here.app_id")).toString();
|
|
- m_appCode = parameters.value(QStringLiteral("here.token")).toString();
|
|
+ m_apiKey = parameters.value(QStringLiteral("here.apiKey")).toString();
|
|
|
|
m_theme = parameters.value(IconThemeKey, QString()).toString();
|
|
|
|
@@ -237,7 +236,7 @@ QPlaceManagerEngineNokiaV2::~QPlaceManagerEngineNokiaV2() {}
|
|
|
|
QPlaceDetailsReply *QPlaceManagerEngineNokiaV2::getPlaceDetails(const QString &placeId)
|
|
{
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/places/") + placeId);
|
|
|
|
QUrlQuery queryItems;
|
|
@@ -268,7 +267,7 @@ QPlaceContentReply *QPlaceManagerEngineNokiaV2::getPlaceContent(const QPlaceCont
|
|
|
|
networkReply = sendRequest(u);
|
|
} else {
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/places/") + request.placeId() +
|
|
QStringLiteral("/media/"));
|
|
|
|
@@ -410,7 +409,7 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest
|
|
networkReply = sendRequest(u);
|
|
} else if (!query.searchTerm().isEmpty()) {
|
|
// search term query
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/discover/search"));
|
|
|
|
queryItems.addQueryItem(QStringLiteral("q"), query.searchTerm());
|
|
@@ -432,7 +431,7 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest
|
|
|
|
return reply;
|
|
} else if (!query.recommendationId().isEmpty()) {
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/places/") + query.recommendationId() +
|
|
QStringLiteral("/related/recommended"));
|
|
|
|
@@ -443,7 +442,7 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest
|
|
networkReply = sendRequest(requestUrl);
|
|
} else {
|
|
// category search
|
|
- QUrl requestUrl(QStringLiteral("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QStringLiteral("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/discover/explore"));
|
|
|
|
QStringList ids;
|
|
@@ -498,7 +497,7 @@ QPlaceSearchSuggestionReply *QPlaceManagerEngineNokiaV2::searchSuggestions(const
|
|
return reply;
|
|
}
|
|
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/suggest"));
|
|
|
|
QUrlQuery queryItems;
|
|
@@ -633,7 +632,7 @@ QPlaceReply *QPlaceManagerEngineNokiaV2::initializeCategories()
|
|
for (auto it = m_tempTree.keyBegin(), end = m_tempTree.keyEnd(); it != end; ++it) {
|
|
if (*it == QString())
|
|
continue;
|
|
- QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() +
|
|
+ QUrl requestUrl(QString::fromLatin1("https://") + m_uriProvider->getCurrentHost() +
|
|
QStringLiteral("/places/v1/categories/places/") + *it);
|
|
QNetworkReply *networkReply = sendRequest(requestUrl);
|
|
connect(networkReply, SIGNAL(finished()), this, SLOT(categoryReplyFinished()));
|
|
@@ -831,8 +830,7 @@ void QPlaceManagerEngineNokiaV2::categoryReplyError()
|
|
QNetworkReply *QPlaceManagerEngineNokiaV2::sendRequest(const QUrl &url)
|
|
{
|
|
QUrlQuery queryItems(url);
|
|
- queryItems.addQueryItem(QStringLiteral("app_id"), m_appId);
|
|
- queryItems.addQueryItem(QStringLiteral("app_code"), m_appCode);
|
|
+ queryItems.addQueryItem(QStringLiteral("apiKey"), m_apiKey);
|
|
|
|
QUrl requestUrl = url;
|
|
requestUrl.setQuery(queryItems);
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h b/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h
|
|
index cd632958..6784ce4f 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h
|
|
@@ -122,8 +122,7 @@ private:
|
|
QPointer<QPlaceCategoriesReplyHere> m_categoryReply;
|
|
QHash<QString, QNetworkReply *> m_categoryRequests;
|
|
|
|
- QString m_appId;
|
|
- QString m_appCode;
|
|
+ QString m_apiKey;
|
|
|
|
QString m_localDataPath;
|
|
QString m_theme;
|
|
diff --git a/qtlocation/src/plugins/geoservices/nokia/uri_constants.cpp b/qtlocation/src/plugins/geoservices/nokia/uri_constants.cpp
|
|
index 8db47beb..030006f5 100644
|
|
--- a/qtlocation/src/plugins/geoservices/nokia/uri_constants.cpp
|
|
+++ b/qtlocation/src/plugins/geoservices/nokia/uri_constants.cpp
|
|
@@ -37,11 +37,11 @@
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
-const QString ROUTING_HOST = QLatin1String("route.api.here.com");
|
|
-const QString GEOCODING_HOST = QLatin1String("geocoder.api.here.com");
|
|
-const QString REVERSE_GEOCODING_HOST = QLatin1String("reverse.geocoder.api.here.com");
|
|
-const QString PLACES_HOST = QLatin1String("places.api.here.com");
|
|
-const QString MAP_TILES_HOST = QLatin1String("1-4.base.maps.api.here.com");
|
|
-const QString MAP_TILES_HOST_AERIAL = QLatin1String("1-4.aerial.maps.api.here.com");
|
|
+const QString ROUTING_HOST = QLatin1String("route.ls.hereapi.com");
|
|
+const QString GEOCODING_HOST = QLatin1String("geocoder.ls.hereapi.com");
|
|
+const QString REVERSE_GEOCODING_HOST = QLatin1String("reverse.geocoder.ls.hereapi.com");
|
|
+const QString PLACES_HOST = QLatin1String("places.ls.hereapi.com");
|
|
+const QString MAP_TILES_HOST = QLatin1String("1-4.base.maps.ls.hereapi.com");
|
|
+const QString MAP_TILES_HOST_AERIAL = QLatin1String("1-4.aerial.maps.ls.hereapi.com");
|
|
|
|
QT_END_NAMESPACE
|
|
Submodule qtmultimedia 5dc0ed6f..b7c7ff4a:
|
|
diff --git a/qtmultimedia/src/gsttools/qgstvideorenderersink.cpp b/qtmultimedia/src/gsttools/qgstvideorenderersink.cpp
|
|
index 4000f2178..a446d93fe 100644
|
|
--- a/qtmultimedia/src/gsttools/qgstvideorenderersink.cpp
|
|
+++ b/qtmultimedia/src/gsttools/qgstvideorenderersink.cpp
|
|
@@ -368,7 +368,8 @@ static GstGLContext *gstGLDisplayContext(QAbstractVideoSurface *surface)
|
|
if (!nativeContext)
|
|
qWarning() << "Could not find resource for" << contextName;
|
|
|
|
- GstGLContext *appContext = gst_gl_context_new_wrapped(display, (guintptr)nativeContext, glPlatform, GST_GL_API_ANY);
|
|
+ GstGLAPI glApi = QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL ? GST_GL_API_OPENGL : GST_GL_API_GLES2;
|
|
+ GstGLContext *appContext = gst_gl_context_new_wrapped(display, (guintptr)nativeContext, glPlatform, glApi);
|
|
if (!appContext)
|
|
qWarning() << "Could not create wrappped context for platform:" << glPlatform;
|
|
|
|
diff --git a/qtmultimedia/src/multimediawidgets/multimediawidgets.pro b/qtmultimedia/src/multimediawidgets/multimediawidgets.pro
|
|
index 1919e8107..4c30d8fbf 100644
|
|
--- a/qtmultimedia/src/multimediawidgets/multimediawidgets.pro
|
|
+++ b/qtmultimedia/src/multimediawidgets/multimediawidgets.pro
|
|
@@ -2,8 +2,6 @@
|
|
TARGET = QtMultimediaWidgets
|
|
QT = core gui multimedia widgets-private
|
|
QT_PRIVATE += multimedia-private
|
|
-qtHaveModule(opengl): \
|
|
- QT_PRIVATE += opengl
|
|
|
|
PRIVATE_HEADERS += \
|
|
qvideowidget_p.h \
|
|
Submodule qtnetworkauth b7cb0184..0ca0165f:
|
|
diff --git a/qtnetworkauth/src/oauth/qabstractoauth.cpp b/qtnetworkauth/src/oauth/qabstractoauth.cpp
|
|
index 46985d6..09939ea 100644
|
|
--- a/qtnetworkauth/src/oauth/qabstractoauth.cpp
|
|
+++ b/qtnetworkauth/src/oauth/qabstractoauth.cpp
|
|
@@ -37,7 +37,6 @@
|
|
#include <QtCore/qurl.h>
|
|
#include <QtCore/qpair.h>
|
|
#include <QtCore/qstring.h>
|
|
-#include <QtCore/qdatetime.h>
|
|
#include <QtCore/qurlquery.h>
|
|
#include <QtCore/qjsondocument.h>
|
|
#include <QtCore/qmessageauthenticationcode.h>
|
|
@@ -46,6 +45,9 @@
|
|
#include <QtNetwork/qnetworkaccessmanager.h>
|
|
#include <QtNetwork/qnetworkreply.h>
|
|
|
|
+#include <QtCore/qrandom.h>
|
|
+#include <QtCore/private/qlocking_p.h>
|
|
+
|
|
#include <random>
|
|
|
|
Q_DECLARE_METATYPE(QAbstractOAuth::Error)
|
|
@@ -290,15 +292,19 @@ void QAbstractOAuthPrivate::setStatus(QAbstractOAuth::Status newStatus)
|
|
}
|
|
}
|
|
|
|
+static QBasicMutex prngMutex;
|
|
+Q_GLOBAL_STATIC_WITH_ARGS(std::mt19937, prng, (*QRandomGenerator::system()))
|
|
+
|
|
QByteArray QAbstractOAuthPrivate::generateRandomString(quint8 length)
|
|
{
|
|
- const char characters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
- static std::mt19937 randomEngine(QDateTime::currentDateTime().toMSecsSinceEpoch());
|
|
+ constexpr char characters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
std::uniform_int_distribution<int> distribution(0, sizeof(characters) - 2);
|
|
QByteArray data;
|
|
data.reserve(length);
|
|
+ auto lock = qt_unique_lock(prngMutex);
|
|
for (quint8 i = 0; i < length; ++i)
|
|
- data.append(characters[distribution(randomEngine)]);
|
|
+ data.append(characters[distribution(*prng)]);
|
|
+ lock.unlock();
|
|
return data;
|
|
}
|
|
|
|
@@ -614,6 +620,7 @@ void QAbstractOAuth::resourceOwnerAuthorization(const QUrl &url, const QVariantM
|
|
}
|
|
|
|
/*!
|
|
+ \threadsafe
|
|
Generates a random string which could be used as state or nonce.
|
|
The parameter \a length determines the size of the generated
|
|
string.
|
|
Submodule qtpim 02efef5e...00000000 (submodule deleted)
|
|
Submodule qtquick3d 336052ef..4db879b7:
|
|
diff --git a/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro b/qtquick3d/src/plugins/assetimporters/assimp/assimp.pro
|
|
index ca5c499ed..174a075bd 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 3e790bf2..8f244d09:
|
|
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 20cf59c1a..43af47a94 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquickabstractbutton.cpp
|
|
@@ -1201,6 +1201,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/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 a719efd34..768691dac 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquickcontrol.cpp
|
|
@@ -2334,12 +2334,13 @@ QAccessible::Role QQuickControl::accessibleRole() const
|
|
|
|
void QQuickControl::accessibilityActiveChanged(bool active)
|
|
{
|
|
+ Q_D(QQuickControl);
|
|
if (!active)
|
|
return;
|
|
|
|
QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true));
|
|
Q_ASSERT(accessibleAttached);
|
|
- accessibleAttached->setRole(accessibleRole());
|
|
+ accessibleAttached->setRole(d->effectiveAccessibleRole());
|
|
}
|
|
#endif
|
|
|
|
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp b/qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp
|
|
index e33c5c934..9afabd18a 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/qquicklabel.cpp b/qtquickcontrols2/src/quicktemplates2/qquicklabel.cpp
|
|
index 71b60a2bc..2bc621674 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquicklabel.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquicklabel.cpp
|
|
@@ -263,7 +263,7 @@ void QQuickLabelPrivate::accessibilityActiveChanged(bool active)
|
|
Q_Q(QQuickLabel);
|
|
QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
|
|
Q_ASSERT(accessibleAttached);
|
|
- accessibleAttached->setRole(accessibleRole());
|
|
+ accessibleAttached->setRole(effectiveAccessibleRole());
|
|
maybeSetAccessibleName(text);
|
|
}
|
|
|
|
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/qquickpopup.cpp b/qtquickcontrols2/src/quicktemplates2/qquickpopup.cpp
|
|
index 7df80a047..bfaa84e30 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquickpopup.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquickpopup.cpp
|
|
@@ -46,6 +46,7 @@
|
|
|
|
#include <QtQml/qqmlinfo.h>
|
|
#include <QtQuick/qquickitem.h>
|
|
+#include <QtQuick/private/qquickaccessibleattached_p.h>
|
|
#include <QtQuick/private/qquicktransition_p.h>
|
|
#include <QtQuick/private/qquickitem_p.h>
|
|
|
|
@@ -2720,6 +2721,19 @@ QPalette QQuickPopup::defaultPalette() const
|
|
}
|
|
|
|
#if QT_CONFIG(accessibility)
|
|
+QAccessible::Role QQuickPopup::effectiveAccessibleRole() const
|
|
+{
|
|
+ auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, false);
|
|
+
|
|
+ auto role = QAccessible::NoRole;
|
|
+ if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(attached))
|
|
+ role = accessibleAttached->role();
|
|
+ if (role == QAccessible::NoRole)
|
|
+ role = accessibleRole();
|
|
+
|
|
+ return role;
|
|
+}
|
|
+
|
|
QAccessible::Role QQuickPopup::accessibleRole() const
|
|
{
|
|
return QAccessible::Dialog;
|
|
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickpopup_p.h b/qtquickcontrols2/src/quicktemplates2/qquickpopup_p.h
|
|
index dc3ebf6f8..a3773be3e 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquickpopup_p.h
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquickpopup_p.h
|
|
@@ -454,7 +454,10 @@ protected:
|
|
virtual QPalette defaultPalette() const;
|
|
|
|
#if QT_CONFIG(accessibility)
|
|
+ QAccessible::Role effectiveAccessibleRole() const;
|
|
+private:
|
|
virtual QAccessible::Role accessibleRole() const;
|
|
+protected:
|
|
virtual void accessibilityActiveChanged(bool active);
|
|
#endif
|
|
|
|
diff --git a/qtquickcontrols2/src/quicktemplates2/qquickpopupitem.cpp b/qtquickcontrols2/src/quicktemplates2/qquickpopupitem.cpp
|
|
index 0069b9fc1..143c37fc3 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquickpopupitem.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquickpopupitem.cpp
|
|
@@ -404,7 +404,7 @@ QPalette QQuickPopupItem::defaultPalette() const
|
|
QAccessible::Role QQuickPopupItem::accessibleRole() const
|
|
{
|
|
Q_D(const QQuickPopupItem);
|
|
- return d->popup->accessibleRole();
|
|
+ return d->popup->effectiveAccessibleRole();
|
|
}
|
|
|
|
void QQuickPopupItem::accessibilityActiveChanged(bool active)
|
|
diff --git a/qtquickcontrols2/src/quicktemplates2/qquicktextarea.cpp b/qtquickcontrols2/src/quicktemplates2/qquicktextarea.cpp
|
|
index 64fc631dd..fba3f6b70 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquicktextarea.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquicktextarea.cpp
|
|
@@ -512,7 +512,7 @@ void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
|
|
Q_Q(QQuickTextArea);
|
|
QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
|
|
Q_ASSERT(accessibleAttached);
|
|
- accessibleAttached->setRole(accessibleRole());
|
|
+ accessibleAttached->setRole(effectiveAccessibleRole());
|
|
accessibleAttached->set_readOnly(q->isReadOnly());
|
|
accessibleAttached->setDescription(placeholder);
|
|
}
|
|
diff --git a/qtquickcontrols2/src/quicktemplates2/qquicktextfield.cpp b/qtquickcontrols2/src/quicktemplates2/qquicktextfield.cpp
|
|
index 8fa04bd3a..e83346cbd 100644
|
|
--- a/qtquickcontrols2/src/quicktemplates2/qquicktextfield.cpp
|
|
+++ b/qtquickcontrols2/src/quicktemplates2/qquicktextfield.cpp
|
|
@@ -359,7 +359,7 @@ void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active)
|
|
Q_Q(QQuickTextField);
|
|
QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
|
|
Q_ASSERT(accessibleAttached);
|
|
- accessibleAttached->setRole(accessibleRole());
|
|
+ accessibleAttached->setRole(effectiveAccessibleRole());
|
|
accessibleAttached->set_readOnly(m_readOnly);
|
|
accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
|
|
accessibleAttached->setDescription(placeholder);
|
|
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 qtrepotools ee34618d...00000000 (submodule deleted)
|
|
Submodule qtspeech 5e253d1e..fe7fc4f6:
|
|
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 ba3671e4..9c3d4062:
|
|
diff --git a/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp b/qtsvg/src/plugins/imageformats/svg/qsvgiohandler.cpp
|
|
index 561e77e9..12e05748 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 dd9b7164..222b6d89 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:
|
|
@@ -2578,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);
|
|
@@ -3048,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())
|
|
@@ -3352,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;
|
|
diff --git a/qtsvg/src/svg/qsvgstructure.cpp b/qtsvg/src/svg/qsvgstructure.cpp
|
|
index b89608b5..89c9e4ec 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]);
|
|
}
|
|
Submodule qtsystems 434af789...00000000 (submodule deleted)
|
|
Submodule qttools 62998610..15deb8f2:
|
|
diff --git a/qttools/src/assistant/help/help.pro b/qttools/src/assistant/help/help.pro
|
|
index 800c4a38d..7556f451b 100644
|
|
--- a/qttools/src/assistant/help/help.pro
|
|
+++ b/qttools/src/assistant/help/help.pro
|
|
@@ -1,7 +1,6 @@
|
|
TARGET = QtHelp
|
|
|
|
QT = core-private gui widgets sql
|
|
-QT_PRIVATE = network
|
|
|
|
DEFINES += QHELP_LIB
|
|
|
|
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);
|
|
diff --git a/qttools/src/assistant/qhelpgenerator/qhelpgenerator.pro b/qttools/src/assistant/qhelpgenerator/qhelpgenerator.pro
|
|
index bb22000c8..415347a00 100644
|
|
--- a/qttools/src/assistant/qhelpgenerator/qhelpgenerator.pro
|
|
+++ b/qttools/src/assistant/qhelpgenerator/qhelpgenerator.pro
|
|
@@ -1,4 +1,4 @@
|
|
-QT += network help-private
|
|
+QT += help-private
|
|
|
|
QTPLUGIN.platforms = qminimal
|
|
QTPLUGIN.sqldrivers = qsqlite
|
|
diff --git a/qttools/src/qdoc/clangcodeparser.cpp b/qttools/src/qdoc/clangcodeparser.cpp
|
|
index 539a603da..a41b99cec 100644
|
|
--- a/qttools/src/qdoc/clangcodeparser.cpp
|
|
+++ b/qttools/src/qdoc/clangcodeparser.cpp
|
|
@@ -1395,8 +1395,7 @@ void ClangCodeParser::buildPCH()
|
|
args_.push_back("-xc++");
|
|
CXTranslationUnit tu;
|
|
QString tmpHeader = pchFileDir_->path() + "/" + module;
|
|
- QFile tmpHeaderFile(tmpHeader);
|
|
- if (tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) {
|
|
+ { QFile tmpHeaderFile(tmpHeader); if (tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) {
|
|
QTextStream out(&tmpHeaderFile);
|
|
if (header.isEmpty()) {
|
|
for (auto it = allHeaders_.constKeyValueBegin();
|
|
@@ -1421,8 +1420,7 @@ void ClangCodeParser::buildPCH()
|
|
out << line << "\n";
|
|
}
|
|
}
|
|
- tmpHeaderFile.close();
|
|
- }
|
|
+ } }
|
|
if (printParsingErrors_ == 0)
|
|
qCWarning(lcQdoc) << "clang not printing errors; include paths were guessed";
|
|
CXErrorCode err =
|
|
Submodule qtwayland 7558876d..9340737a:
|
|
diff --git a/qtwayland/src/client/configure.json b/qtwayland/src/client/configure.json
|
|
index 73f23362..6247f85e 100644
|
|
--- a/qtwayland/src/client/configure.json
|
|
+++ b/qtwayland/src/client/configure.json
|
|
@@ -167,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",
|
|
@@ -182,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 966096a8..36609c08 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/qwaylandabstractdecoration.cpp b/qtwayland/src/client/qwaylandabstractdecoration.cpp
|
|
index b628930d..d15a7f9f 100644
|
|
--- a/qtwayland/src/client/qwaylandabstractdecoration.cpp
|
|
+++ b/qtwayland/src/client/qwaylandabstractdecoration.cpp
|
|
@@ -122,7 +122,7 @@ const QImage &QWaylandAbstractDecoration::contentImage()
|
|
if (d->m_isDirty) {
|
|
// Update the decoration backingstore
|
|
|
|
- const int bufferScale = waylandWindow()->scale();
|
|
+ const qreal bufferScale = waylandWindow()->scale();
|
|
const QSize imageSize = waylandWindow()->surfaceSize() * bufferScale;
|
|
d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
|
|
// Only scale by buffer scale, not QT_SCALE_FACTOR etc.
|
|
diff --git a/qtwayland/src/client/qwaylandcursor.cpp b/qtwayland/src/client/qwaylandcursor.cpp
|
|
index e4eca9d4..ba76ba2d 100644
|
|
--- a/qtwayland/src/client/qwaylandcursor.cpp
|
|
+++ b/qtwayland/src/client/qwaylandcursor.cpp
|
|
@@ -44,6 +44,7 @@
|
|
#include "qwaylandshmbackingstore_p.h"
|
|
|
|
#include <QtGui/QImageReader>
|
|
+#include <QBitmap>
|
|
#include <QDebug>
|
|
|
|
#include <wayland-cursor.h>
|
|
@@ -250,7 +251,27 @@ QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
|
|
QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor)
|
|
{
|
|
Q_ASSERT(cursor->shape() == Qt::BitmapCursor);
|
|
- const QImage &img = cursor->pixmap().toImage();
|
|
+
|
|
+ const QBitmap mask = cursor->mask(Qt::ReturnByValue);
|
|
+ QImage img;
|
|
+ if (cursor->pixmap().isNull())
|
|
+ img = cursor->bitmap(Qt::ReturnByValue).toImage();
|
|
+ else
|
|
+ img = cursor->pixmap().toImage();
|
|
+
|
|
+ // convert to supported format if necessary
|
|
+ if (!display->shm()->formatSupported(img.format())) {
|
|
+ if (mask.isNull()) {
|
|
+ img.convertTo(QImage::Format_RGB32);
|
|
+ } else {
|
|
+ // preserve mask
|
|
+ img.convertTo(QImage::Format_ARGB32);
|
|
+ QPixmap pixmap = QPixmap::fromImage(img);
|
|
+ pixmap.setMask(mask);
|
|
+ img = pixmap.toImage();
|
|
+ }
|
|
+ }
|
|
+
|
|
QSharedPointer<QWaylandShmBuffer> buffer(new QWaylandShmBuffer(display, img.size(), img.format()));
|
|
memcpy(buffer->image()->bits(), img.bits(), size_t(img.sizeInBytes()));
|
|
return buffer;
|
|
diff --git a/qtwayland/src/client/qwaylanddatadevice.cpp b/qtwayland/src/client/qwaylanddatadevice.cpp
|
|
index 4d2459d1..c57f1a49 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();
|
|
@@ -129,7 +131,31 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
|
mimeData->setData("application/x-qt-avoid-empty-placeholder", QByteArray("1"));
|
|
|
|
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());
|
|
+ if (!drag->currentDrag()) {
|
|
+ return;
|
|
+ }
|
|
+ // 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;
|
|
@@ -158,7 +184,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;
|
|
}
|
|
@@ -168,7 +194,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();
|
|
}
|
|
}
|
|
|
|
@@ -192,7 +222,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,
|
|
@@ -203,11 +233,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()
|
|
@@ -241,10 +267,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());
|
|
|
|
@@ -252,11 +278,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)
|
|
|
|
@@ -283,14 +305,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));
|
|
@@ -303,6 +321,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..0241a1df 100644
|
|
--- a/qtwayland/src/client/qwaylanddataoffer.cpp
|
|
+++ b/qtwayland/src/client/qwaylanddataoffer.cpp
|
|
@@ -56,6 +56,11 @@ static QString utf8Text()
|
|
return QStringLiteral("text/plain;charset=utf-8");
|
|
}
|
|
|
|
+static QString portalFileTransfer()
|
|
+{
|
|
+ return QStringLiteral("application/vnd.portal.filetransfer");
|
|
+}
|
|
+
|
|
QWaylandDataOffer::QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer)
|
|
: QtWayland::wl_data_offer(offer)
|
|
, m_display(display)
|
|
@@ -82,6 +87,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 +107,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)
|
|
{
|
|
@@ -157,23 +187,26 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
|
|
}
|
|
|
|
close(pipefd[0]);
|
|
- m_data.insert(mimeType, content);
|
|
+ if (mimeType != portalFileTransfer())
|
|
+ m_data.insert(mimeType, content);
|
|
+
|
|
return content;
|
|
}
|
|
|
|
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 c86c1416..321170a6 100644
|
|
--- a/qtwayland/src/client/qwaylanddatasource.cpp
|
|
+++ b/qtwayland/src/client/qwaylanddatasource.cpp
|
|
@@ -105,7 +105,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 520b3165..089c5485 100644
|
|
--- a/qtwayland/src/client/qwaylanddatasource_p.h
|
|
+++ b/qtwayland/src/client/qwaylanddatasource_p.h
|
|
@@ -75,16 +75,24 @@ public:
|
|
~QWaylandDataSource() override;
|
|
|
|
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:
|
|
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 8a6d5db1..737b539d 100644
|
|
--- a/qtwayland/src/client/qwaylanddisplay.cpp
|
|
+++ b/qtwayland/src/client/qwaylanddisplay.cpp
|
|
@@ -87,10 +87,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)
|
|
@@ -160,17 +353,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,10 +379,26 @@ QWaylandDisplay::~QWaylandDisplay(void)
|
|
#if QT_CONFIG(cursor)
|
|
qDeleteAll(mCursorThemes);
|
|
#endif
|
|
+
|
|
+ if (m_frameEventQueue)
|
|
+ wl_event_queue_destroy(m_frameEventQueue);
|
|
+
|
|
if (mDisplay)
|
|
wl_display_disconnect(mDisplay);
|
|
}
|
|
|
|
+// 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()
|
|
{
|
|
if (!mScreens.empty() || mPlaceholderScreen)
|
|
@@ -205,98 +413,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
|
|
@@ -347,7 +494,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));
|
|
@@ -356,7 +503,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));
|
|
@@ -373,6 +520,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));
|
|
@@ -431,6 +580,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;
|
|
}
|
|
@@ -456,9 +612,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()
|
|
@@ -471,50 +628,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
|
|
@@ -578,14 +694,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;
|
|
}
|
|
@@ -604,6 +716,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 = {
|
|
@@ -630,6 +755,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()
|
|
@@ -656,6 +788,8 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
|
|
|
|
} // namespace QtWaylandClient
|
|
|
|
+#include "qwaylanddisplay.moc"
|
|
+
|
|
QT_END_NAMESPACE
|
|
|
|
#include "moc_qwaylanddisplay_p.cpp"
|
|
diff --git a/qtwayland/src/client/qwaylanddisplay_p.h b/qtwayland/src/client/qwaylanddisplay_p.h
|
|
index 1bad8b67..cf91b924 100644
|
|
--- a/qtwayland/src/client/qwaylanddisplay_p.h
|
|
+++ b/qtwayland/src/client/qwaylanddisplay_p.h
|
|
@@ -111,6 +111,7 @@ class QWaylandSurface;
|
|
class QWaylandShellIntegration;
|
|
class QWaylandCursor;
|
|
class QWaylandCursorTheme;
|
|
+class EventThread;
|
|
|
|
typedef void (*RegistryListener)(void *data,
|
|
struct wl_registry *registry,
|
|
@@ -122,15 +123,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
|
|
@@ -214,11 +211,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();
|
|
@@ -241,6 +238,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;
|
|
@@ -279,11 +279,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 346c438c..278e31f9 100644
|
|
--- a/qtwayland/src/client/qwaylandinputdevice.cpp
|
|
+++ b/qtwayland/src/client/qwaylandinputdevice.cpp
|
|
@@ -92,11 +92,12 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
|
|
return;
|
|
}
|
|
mRepeatTimer.setInterval(1000 / mRepeatRate);
|
|
- handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
|
|
- mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
|
|
+ Qt::KeyboardModifiers modifiers = this->modifiers();
|
|
+ handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, modifiers,
|
|
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers,
|
|
mRepeatKey.text, true);
|
|
- handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, mRepeatKey.modifiers,
|
|
- mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
|
|
+ handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, modifiers,
|
|
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers,
|
|
mRepeatKey.text, true);
|
|
});
|
|
}
|
|
@@ -310,8 +311,7 @@ void QWaylandInputDevice::Pointer::updateCursor()
|
|
auto shape = seat()->mCursor.shape;
|
|
|
|
if (shape == Qt::BlankCursor) {
|
|
- if (mCursor.surface)
|
|
- mCursor.surface->hide();
|
|
+ getOrCreateCursorSurface()->hide();
|
|
return;
|
|
}
|
|
|
|
@@ -1271,8 +1271,6 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
|
|
mRepeatKey.code = code;
|
|
mRepeatKey.time = time;
|
|
mRepeatKey.text = text;
|
|
- mRepeatKey.modifiers = modifiers;
|
|
- mRepeatKey.nativeModifiers = mNativeModifiers;
|
|
mRepeatKey.nativeVirtualKey = sym;
|
|
mRepeatTimer.setInterval(mRepeatDelay);
|
|
mRepeatTimer.start();
|
|
@@ -1304,14 +1302,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();
|
|
}
|
|
@@ -1400,6 +1390,7 @@ void QWaylandInputDevice::Touch::touch_cancel()
|
|
if (touchExt)
|
|
touchExt->touchCanceled();
|
|
|
|
+ mFocus = nullptr;
|
|
QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice);
|
|
}
|
|
|
|
diff --git a/qtwayland/src/client/qwaylandinputdevice_p.h b/qtwayland/src/client/qwaylandinputdevice_p.h
|
|
index 5795f138..3b92567c 100644
|
|
--- a/qtwayland/src/client/qwaylandinputdevice_p.h
|
|
+++ b/qtwayland/src/client/qwaylandinputdevice_p.h
|
|
@@ -250,9 +250,7 @@ public:
|
|
uint32_t code;
|
|
uint32_t time;
|
|
QString text;
|
|
- Qt::KeyboardModifiers modifiers;
|
|
uint32_t nativeVirtualKey;
|
|
- uint32_t nativeModifiers;
|
|
} mRepeatKey;
|
|
|
|
QTimer mRepeatTimer;
|
|
diff --git a/qtwayland/src/client/qwaylandintegration.cpp b/qtwayland/src/client/qwaylandintegration.cpp
|
|
index d257e2e3..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())
|
|
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 7805dd73..dac532b2 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..145f933b 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
|
|
@@ -68,14 +72,16 @@ QT_BEGIN_NAMESPACE
|
|
namespace QtWaylandClient {
|
|
|
|
QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
|
|
- const QSize &size, QImage::Format format, int scale)
|
|
+ const QSize &size, QImage::Format format, qreal scale)
|
|
{
|
|
int stride = size.width() * 4;
|
|
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;
|
|
@@ -108,7 +114,7 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
|
|
QWaylandShm* shm = display->shm();
|
|
wl_shm_format wl_format = shm->formatFrom(format);
|
|
mImage = QImage(data, size.width(), size.height(), stride, format);
|
|
- mImage.setDevicePixelRatio(qreal(scale));
|
|
+ mImage.setDevicePixelRatio(scale);
|
|
|
|
mShmPool = wl_shm_create_pool(shm->object(), fd, alloc);
|
|
init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
|
|
@@ -180,8 +186,6 @@ void QWaylandShmBackingStore::beginPaint(const QRegion ®ion)
|
|
mPainting = true;
|
|
ensureSize();
|
|
|
|
- waylandWindow()->setCanResize(false);
|
|
-
|
|
if (mBackBuffer->image()->hasAlphaChannel()) {
|
|
QPainter p(paintDevice());
|
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
@@ -196,7 +200,6 @@ void QWaylandShmBackingStore::endPaint()
|
|
mPainting = false;
|
|
if (mPendingFlush)
|
|
flush(window(), mPendingRegion, QPoint());
|
|
- waylandWindow()->setCanResize(true);
|
|
}
|
|
|
|
void QWaylandShmBackingStore::ensureSize()
|
|
@@ -271,7 +274,7 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
|
|
void QWaylandShmBackingStore::resize(const QSize &size)
|
|
{
|
|
QMargins margins = windowDecorationMargins();
|
|
- int scale = waylandWindow()->scale();
|
|
+ qreal scale = waylandWindow()->scale();
|
|
QSize sizeWithMargins = (size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom())) * scale;
|
|
|
|
// We look for a free buffer to draw into. If the buffer is not the last buffer we used,
|
|
diff --git a/qtwayland/src/client/qwaylandshmbackingstore_p.h b/qtwayland/src/client/qwaylandshmbackingstore_p.h
|
|
index e01632da..f3fae438 100644
|
|
--- a/qtwayland/src/client/qwaylandshmbackingstore_p.h
|
|
+++ b/qtwayland/src/client/qwaylandshmbackingstore_p.h
|
|
@@ -71,7 +71,7 @@ class QWaylandWindow;
|
|
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
|
|
public:
|
|
QWaylandShmBuffer(QWaylandDisplay *display,
|
|
- const QSize &size, QImage::Format format, int scale = 1);
|
|
+ const QSize &size, QImage::Format format, qreal scale = 1);
|
|
~QWaylandShmBuffer() override;
|
|
QSize size() const override { return mImage.size(); }
|
|
int scale() const override { return int(mImage.devicePixelRatio()); }
|
|
diff --git a/qtwayland/src/client/qwaylandwindow.cpp b/qtwayland/src/client/qwaylandwindow.cpp
|
|
index d57094a7..7a9bccc1 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)
|
|
@@ -189,7 +185,7 @@ void QWaylandWindow::initWindow()
|
|
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
|
|
// to inform the compositor that high-resolution buffers will be provided.
|
|
if (mDisplay->compositorVersion() >= 3)
|
|
- mSurface->set_buffer_scale(scale());
|
|
+ mSurface->set_buffer_scale(mScale);
|
|
|
|
if (QScreen *s = window()->screen())
|
|
setOrientationMask(s->orientationUpdateMask());
|
|
@@ -204,6 +200,8 @@ void QWaylandWindow::initWindow()
|
|
mShellSurface->requestWindowStates(window()->windowStates());
|
|
handleContentOrientationChange(window()->contentOrientation());
|
|
mFlags = window()->flags();
|
|
+
|
|
+ mSurface->commit();
|
|
}
|
|
|
|
void QWaylandWindow::initializeWlSurface()
|
|
@@ -243,6 +241,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
|
|
|
|
void QWaylandWindow::reset()
|
|
{
|
|
+ closeChildPopups();
|
|
delete mShellSurface;
|
|
mShellSurface = nullptr;
|
|
delete mSubSurfaceWindow;
|
|
@@ -255,17 +254,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 +355,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 +384,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 +409,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 +428,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 +436,6 @@ void QWaylandWindow::setVisible(bool visible)
|
|
// QWaylandShmBackingStore::beginPaint().
|
|
} else {
|
|
sendExposeEvent(QRect());
|
|
- closePopups(this);
|
|
reset();
|
|
}
|
|
}
|
|
@@ -487,8 +478,6 @@ void QWaylandWindow::setMask(const QRegion &mask)
|
|
if (isOpaque())
|
|
setOpaqueArea(mMask);
|
|
}
|
|
-
|
|
- mSurface->commit();
|
|
}
|
|
|
|
void QWaylandWindow::applyConfigureWhenPossible()
|
|
@@ -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,16 @@ void QWaylandWindow::damage(const QRect &rect)
|
|
if (mSurface == nullptr)
|
|
return;
|
|
|
|
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
|
+ const qreal s = scale();
|
|
+ if (mDisplay->compositorVersion() >= 4) {
|
|
+ const QRect bufferRect =
|
|
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
|
|
+ .toAlignedRect();
|
|
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
|
|
+ bufferRect.height());
|
|
+ } else {
|
|
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
|
+ }
|
|
}
|
|
|
|
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
|
|
@@ -619,8 +617,19 @@ 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 qreal s = scale();
|
|
+ for (const QRect &rect : damage) {
|
|
+ const QRect bufferRect =
|
|
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
|
|
+ .toAlignedRect();
|
|
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
|
|
+ bufferRect.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 +644,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";
|
|
@@ -772,8 +792,6 @@ void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orient
|
|
Q_UNREACHABLE();
|
|
}
|
|
mSurface->set_buffer_transform(transform);
|
|
- // set_buffer_transform is double buffered, we need to commit.
|
|
- mSurface->commit();
|
|
}
|
|
|
|
void QWaylandWindow::setOrientationMask(Qt::ScreenOrientations mask)
|
|
@@ -1032,8 +1050,17 @@ void QWaylandWindow::handleScreensChanged()
|
|
if (newScreen == mLastReportedScreen)
|
|
return;
|
|
|
|
+ if (!newScreen->isPlaceholder() && !newScreen->QPlatformScreen::screen())
|
|
+ mDisplay->forceRoundTrip();
|
|
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) {
|
|
@@ -1087,14 +1114,14 @@ bool QWaylandWindow::isActive() const
|
|
return mDisplay->isWindowActivated(this);
|
|
}
|
|
|
|
-int QWaylandWindow::scale() const
|
|
+qreal QWaylandWindow::scale() const
|
|
{
|
|
- return mScale;
|
|
+ return devicePixelRatio();
|
|
}
|
|
|
|
qreal QWaylandWindow::devicePixelRatio() const
|
|
{
|
|
- return mScale;
|
|
+ return qreal(mScale);
|
|
}
|
|
|
|
bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
|
@@ -1108,10 +1135,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;
|
|
}
|
|
|
|
@@ -1153,19 +1188,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()
|
|
@@ -1174,8 +1214,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
|
|
@@ -1188,7 +1231,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);
|
|
}
|
|
@@ -1199,19 +1247,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);
|
|
@@ -1221,6 +1268,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);
|
|
@@ -1281,6 +1330,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..741f9e5c 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,13 +151,14 @@ 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;
|
|
|
|
void setMask(const QRegion ®ion) override;
|
|
|
|
- int scale() const;
|
|
+ qreal scale() const;
|
|
qreal devicePixelRatio() const override;
|
|
|
|
void requestActivateWindow() 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 c5b0f03e..031e4cc3 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",
|
|
@@ -193,7 +218,8 @@
|
|
"exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
|
|
"return 0;"
|
|
]
|
|
- }
|
|
+ },
|
|
+ "use": "wayland-client"
|
|
}
|
|
},
|
|
|
|
diff --git a/qtwayland/src/compositor/wayland_wrapper/qwldatadevice.cpp b/qtwayland/src/compositor/wayland_wrapper/qwldatadevice.cpp
|
|
index a3a795f9..f301678e 100644
|
|
--- a/qtwayland/src/compositor/wayland_wrapper/qwldatadevice.cpp
|
|
+++ b/qtwayland/src/compositor/wayland_wrapper/qwldatadevice.cpp
|
|
@@ -76,6 +76,9 @@ void DataDevice::sourceDestroyed(DataSource *source)
|
|
{
|
|
if (m_selectionSource == source)
|
|
m_selectionSource = nullptr;
|
|
+
|
|
+ if (m_dragDataSource == source)
|
|
+ m_dragDataSource = nullptr;
|
|
}
|
|
|
|
#if QT_CONFIG(draganddrop)
|
|
@@ -105,9 +108,11 @@ void DataDevice::setDragFocus(QWaylandSurface *focus, const QPointF &localPositi
|
|
if (m_dragDataSource && !offer)
|
|
return;
|
|
|
|
- send_enter(resource->handle, serial, focus->resource(),
|
|
- wl_fixed_from_double(localPosition.x()), wl_fixed_from_double(localPosition.y()),
|
|
- offer->resource()->handle);
|
|
+ if (offer) {
|
|
+ send_enter(resource->handle, serial, focus->resource(),
|
|
+ wl_fixed_from_double(localPosition.x()), wl_fixed_from_double(localPosition.y()),
|
|
+ offer->resource()->handle);
|
|
+ }
|
|
|
|
m_dragFocus = focus;
|
|
m_dragFocusResource = resource;
|
|
@@ -139,7 +144,7 @@ void DataDevice::drop()
|
|
if (m_dragFocusResource) {
|
|
send_drop(m_dragFocusResource->handle);
|
|
setDragFocus(nullptr, QPoint());
|
|
- } else {
|
|
+ } else if (m_dragDataSource) {
|
|
m_dragDataSource->cancel();
|
|
}
|
|
m_dragOrigin = nullptr;
|
|
@@ -155,6 +160,8 @@ void DataDevice::data_device_start_drag(Resource *resource, struct ::wl_resource
|
|
{
|
|
m_dragClient = resource->client();
|
|
m_dragDataSource = source ? DataSource::fromResource(source) : nullptr;
|
|
+ if (m_dragDataSource)
|
|
+ m_dragDataSource->setDevice(this);
|
|
m_dragOrigin = QWaylandSurface::fromResource(origin);
|
|
QWaylandDrag *drag = m_seat->drag();
|
|
setDragIcon(icon ? QWaylandSurface::fromResource(icon) : nullptr);
|
|
diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
|
|
index e00c28c3..95e8c666 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>
|
|
@@ -115,21 +116,25 @@ void QWaylandEglWindow::updateSurface(bool create)
|
|
}
|
|
mOffset = QPoint();
|
|
} else {
|
|
+ QReadLocker locker(&mSurfaceLock);
|
|
if (m_waylandEglWindow) {
|
|
- int current_width, current_height;
|
|
+ int current_width = 0;
|
|
+ int current_height = 0;
|
|
static bool disableResizeCheck = qgetenv("QT_WAYLAND_DISABLE_RESIZECHECK").toInt();
|
|
|
|
if (!disableResizeCheck) {
|
|
wl_egl_window_get_attached_size(m_waylandEglWindow, ¤t_width, ¤t_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 2fccbcea..ad1e5ee9 100644
|
|
--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
|
|
+++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
|
|
@@ -85,6 +85,7 @@ private:
|
|
mutable QOpenGLFramebufferObject *m_contentFBO = nullptr;
|
|
|
|
QSurfaceFormat m_format;
|
|
+ QSize m_requestedSize;
|
|
};
|
|
|
|
}
|
|
diff --git a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
|
index c1f45fa6..bbc63444 100644
|
|
--- a/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
|
+++ b/qtwayland/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
|
@@ -195,7 +195,7 @@ public:
|
|
QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
|
|
|
|
QSize surfaceSize = window->surfaceSize();
|
|
- int scale = window->scale() ;
|
|
+ qreal scale = window->scale() ;
|
|
glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale);
|
|
|
|
//Draw Decoration
|
|
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 49e9d953..9c6cbb81 100644
|
|
--- a/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
|
+++ b/qtwayland/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
|
@@ -44,6 +44,7 @@
|
|
#include <QtWaylandClient/private/qwaylandwindow_p.h>
|
|
#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
|
|
#include <QtWaylandClient/private/qwaylandscreen_p.h>
|
|
+#include <QtWaylandClient/private/qwaylandcursor_p.h>
|
|
#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
|
|
|
|
#include <QtGui/private/qwindow_p.h>
|
|
@@ -67,11 +68,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 +81,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 +100,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 +196,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 +214,14 @@ 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
|
|
@@ -228,8 +230,10 @@ QWaylandXdgSurface::Popup::~Popup()
|
|
leave = m_xdgSurface->window()->window();
|
|
QWindowSystemInterface::handleLeaveEvent(leave);
|
|
|
|
- if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos()))
|
|
- QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(QCursor::pos()), QCursor::pos());
|
|
+ if (QWindow *enter = QGuiApplication::topLevelAt(QCursor::pos())) {
|
|
+ const auto pos = m_xdgSurface->window()->display()->waylandCursor()->pos();
|
|
+ QWindowSystemInterface::handleEnterEvent(enter, enter->handle()->mapFromGlobal(pos), pos);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -267,6 +271,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
|
|
m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
|
|
}
|
|
}
|
|
+ setSizeHints();
|
|
}
|
|
|
|
QWaylandXdgSurface::~QWaylandXdgSurface()
|
|
@@ -365,9 +370,6 @@ bool QWaylandXdgSurface::wantsDecorations() const
|
|
void QWaylandXdgSurface::propagateSizeHints()
|
|
{
|
|
setSizeHints();
|
|
-
|
|
- if (m_toplevel && m_window)
|
|
- m_window->commit();
|
|
}
|
|
|
|
void QWaylandXdgSurface::setWindowGeometry(const QRect &rect)
|
|
@@ -382,10 +384,10 @@ void QWaylandXdgSurface::setSizeHints()
|
|
const int minHeight = qMax(0, m_window->windowMinimumSize().height());
|
|
m_toplevel->set_min_size(minWidth, minHeight);
|
|
|
|
- int maxWidth = qMax(0, m_window->windowMaximumSize().width());
|
|
+ int maxWidth = qMax(minWidth, m_window->windowMaximumSize().width());
|
|
if (maxWidth == QWINDOWSIZE_MAX)
|
|
maxWidth = 0;
|
|
- int maxHeight = qMax(0, m_window->windowMaximumSize().height());
|
|
+ int maxHeight = qMax(minHeight, m_window->windowMaximumSize().height());
|
|
if (maxHeight == QWINDOWSIZE_MAX)
|
|
maxHeight = 0;
|
|
m_toplevel->set_max_size(maxWidth, maxHeight);
|
|
@@ -410,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
|
|
@@ -426,8 +426,9 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
|
|
positioner->set_size(m_window->geometry().width(), m_window->geometry().height());
|
|
positioner->set_constraint_adjustment(QtWayland::xdg_positioner::constraint_adjustment_slide_x
|
|
| QtWayland::xdg_positioner::constraint_adjustment_slide_y);
|
|
- m_popup = new Popup(this, parentXdgSurface, positioner);
|
|
+ m_popup = new Popup(this, parent, positioner);
|
|
positioner->destroy();
|
|
+
|
|
delete positioner;
|
|
}
|
|
|
|
@@ -464,8 +465,10 @@ void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevic
|
|
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());
|
|
+ if (enter) {
|
|
+ const auto pos = m_popup->m_xdgSurface->window()->display()->waylandCursor()->pos();
|
|
+ QWindowSystemInterface::handleEnterEvent(enter, enter->handle()->mapFromGlobal(pos), 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/qwaylandmimehelper.cpp b/qtwayland/src/shared/qwaylandmimehelper.cpp
|
|
index c5266ab3..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;
|
|
}
|
|
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/coreprotocol.cpp b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
|
|
index 0d988521..53e12291 100644
|
|
--- a/qtwayland/tests/auto/client/shared/coreprotocol.cpp
|
|
+++ b/qtwayland/tests/auto/client/shared/coreprotocol.cpp
|
|
@@ -185,6 +185,8 @@ void Output::output_bind_resource(QtWaylandServer::wl_output::Resource *resource
|
|
|
|
if (m_version >= WL_OUTPUT_DONE_SINCE_VERSION)
|
|
wl_output::send_done(resource->handle);
|
|
+
|
|
+ Q_EMIT outputBound(resource);
|
|
}
|
|
|
|
// Seat stuff
|
|
@@ -451,6 +453,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..00c439e1 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)
|
|
{}
|
|
@@ -273,6 +273,9 @@ public:
|
|
OutputData m_data;
|
|
int m_version = 1; // TODO: remove on libwayland upgrade
|
|
|
|
+Q_SIGNALS:
|
|
+ void outputBound(Resource *resource);
|
|
+
|
|
protected:
|
|
void output_bind_resource(Resource *resource) override;
|
|
};
|
|
@@ -364,6 +367,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/xdgoutput/tst_xdgoutput.cpp b/qtwayland/tests/auto/client/xdgoutput/tst_xdgoutput.cpp
|
|
index 20f762e0..2a0cad1d 100644
|
|
--- a/qtwayland/tests/auto/client/xdgoutput/tst_xdgoutput.cpp
|
|
+++ b/qtwayland/tests/auto/client/xdgoutput/tst_xdgoutput.cpp
|
|
@@ -55,6 +55,7 @@ private slots:
|
|
void primaryScreen();
|
|
void overrideGeometry();
|
|
void changeGeometry();
|
|
+ void outputCreateEnterRace();
|
|
};
|
|
|
|
void tst_xdgoutput::cleanup()
|
|
@@ -134,5 +135,39 @@ void tst_xdgoutput::changeGeometry()
|
|
exec([&] { remove(output(1)); });
|
|
}
|
|
|
|
+void tst_xdgoutput::outputCreateEnterRace()
|
|
+{
|
|
+ m_config.autoConfigure = true;
|
|
+ m_config.autoEnter = false;
|
|
+ QRasterWindow window;
|
|
+ QSignalSpy screenChanged(&window, &QWindow::screenChanged);
|
|
+ window.resize(400, 320);
|
|
+ window.show();
|
|
+ QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
|
|
+ exec([=] { xdgToplevel()->surface()->sendEnter(output(0));});
|
|
+
|
|
+ QTRY_COMPARE(QGuiApplication::screens().size(), 1);
|
|
+ QScreen *primaryScreen = QGuiApplication::screens().first();
|
|
+ QCOMPARE(window.screen(), primaryScreen);
|
|
+
|
|
+ auto *out = exec([=] {
|
|
+ return add<Output>();
|
|
+ });
|
|
+
|
|
+ // In Compositor Thread
|
|
+ connect(out, &Output::outputBound, this, [this](QtWaylandServer::wl_output::Resource *resource){
|
|
+ auto surface = xdgToplevel()->surface();
|
|
+ surface->sendLeave(output(0));
|
|
+ surface->QtWaylandServer::wl_surface::send_enter(surface->resource()->handle, resource->handle);
|
|
+ }, Qt::DirectConnection);
|
|
+
|
|
+ QTRY_COMPARE(QGuiApplication::screens().size(), 2);
|
|
+ QTRY_COMPARE(window.screen(), QGuiApplication::screens()[1]);
|
|
+
|
|
+ exec([=] { remove(out); });
|
|
+ m_config.autoConfigure = false;
|
|
+ m_config.autoEnter = true;
|
|
+}
|
|
+
|
|
QCOMPOSITOR_TEST_MAIN(tst_xdgoutput)
|
|
#include "tst_xdgoutput.moc"
|
|
diff --git a/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp b/qtwayland/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
|
index 1c23728b..f2181fd6 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,15 +598,17 @@ 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));
|
|
|
|
window.setMaximumSize(QSize(500, 400));
|
|
+ window.update();
|
|
QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(500, 400));
|
|
|
|
window.setMinimumSize(QSize(50, 40));
|
|
+ window.update();
|
|
QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(50, 40));
|
|
}
|
|
|
|
Submodule qtwebchannel b292c653...00000000 (submodule deleted)
|
|
Submodule qtwebengine f328054d...00000000 (submodule deleted)
|
|
Submodule qtwebsockets e1f9a1a1..a0c1c335:
|
|
diff --git a/qtwebsockets/src/websockets/qwebsocket_p.cpp b/qtwebsockets/src/websockets/qwebsocket_p.cpp
|
|
index cf3087f..0dd0fa6 100644
|
|
--- a/qtwebsockets/src/websockets/qwebsocket_p.cpp
|
|
+++ b/qtwebsockets/src/websockets/qwebsocket_p.cpp
|
|
@@ -1100,6 +1100,8 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
|
|
m_handshakeState = AllDoneState;
|
|
setErrorString(errorDescription);
|
|
Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
|
|
+ if (m_pSocket->state() != QAbstractSocket::UnconnectedState)
|
|
+ m_pSocket->disconnectFromHost();
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
/*!
|