Merge remote-tracking branch 'origin/5.9' into dev

Change-Id: I7d84cfed0b2a122d334b8a920e6e4f18472d2f11
This commit is contained in:
Liang Qi 2017-02-28 13:03:36 +01:00
commit 1a4f0deeb4
67 changed files with 678 additions and 238 deletions

View File

@ -56,7 +56,6 @@
"android-sdk": "string", "android-sdk": "string",
"android-toolchain-version": "string", "android-toolchain-version": "string",
"accessibility": "boolean",
"android-style-assets": "boolean", "android-style-assets": "boolean",
"appstore-compliant": "boolean", "appstore-compliant": "boolean",
"avx": "boolean", "avx": "boolean",
@ -941,10 +940,6 @@
"condition": "config.qnx && tests.stack_protector", "condition": "config.qnx && tests.stack_protector",
"output": [ "publicQtConfig" ] "output": [ "publicQtConfig" ]
}, },
"accessibility": {
"label": "Accessibility",
"output": [ "publicFeature", "feature" ]
},
"system-zlib": { "system-zlib": {
"label": "Using system zlib", "label": "Using system zlib",
"condition": "libs.zlib", "condition": "libs.zlib",
@ -1106,11 +1101,6 @@ or compile needed modules into the library."
"message": "Qt is using double for qreal on this system. This is binary-incompatible against Qt 5.1. "message": "Qt is using double for qreal on this system. This is binary-incompatible against Qt 5.1.
Configure with '-qreal float' to create a build that is binary-compatible with 5.1." Configure with '-qreal float' to create a build that is binary-compatible with 5.1."
}, },
{
"type": "warning",
"condition": "!features.accessibility",
"message": "Accessibility disabled. This configuration of Qt is unsupported."
},
{ {
"type": "error", "type": "error",
"condition": "!features.stl", "condition": "!features.stl",
@ -1217,7 +1207,6 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
}, { }, {
"section": "Support enabled for", "section": "Support enabled for",
"entries": [ "entries": [
"accessibility",
"pkg-config", "pkg-config",
"qml-debug", "qml-debug",
"libudev", "libudev",

View File

@ -1,5 +1,5 @@
CONFIG(release, debug|release):DEFINES *= NDEBUG CONFIG(release, debug|release):DEFINES *= NDEBUG
DEFINES += SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_RTREE DEFINES += SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE
!contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS !contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS
qtConfig(posix_fallocate): DEFINES += HAVE_POSIX_FALLOCATE=1 qtConfig(posix_fallocate): DEFINES += HAVE_POSIX_FALLOCATE=1
winrt: DEFINES += SQLITE_OS_WINRT winrt: DEFINES += SQLITE_OS_WINRT

View File

@ -58,9 +58,10 @@ class QTypeInfo
{ {
public: public:
enum { enum {
isSpecialized = std::is_enum<T>::value, // don't require every enum to be marked manually
isPointer = false, isPointer = false,
isIntegral = std::is_integral<T>::value, isIntegral = std::is_integral<T>::value,
isComplex = true, isComplex = !isIntegral && !std::is_enum<T>::value,
isStatic = true, isStatic = true,
isRelocatable = std::is_enum<T>::value, isRelocatable = std::is_enum<T>::value,
isLarge = (sizeof(T)>sizeof(void*)), isLarge = (sizeof(T)>sizeof(void*)),
@ -74,6 +75,7 @@ class QTypeInfo<void>
{ {
public: public:
enum { enum {
isSpecialized = true,
isPointer = false, isPointer = false,
isIntegral = false, isIntegral = false,
isComplex = false, isComplex = false,
@ -90,6 +92,7 @@ class QTypeInfo<T*>
{ {
public: public:
enum { enum {
isSpecialized = true,
isPointer = true, isPointer = true,
isIntegral = false, isIntegral = false,
isComplex = false, isComplex = false,
@ -152,6 +155,7 @@ class QTypeInfoMerger
{ {
public: public:
enum { enum {
isSpecialized = true,
isComplex = QTypeInfoQuery<T1>::isComplex || QTypeInfoQuery<T2>::isComplex isComplex = QTypeInfoQuery<T1>::isComplex || QTypeInfoQuery<T2>::isComplex
|| QTypeInfoQuery<T3>::isComplex || QTypeInfoQuery<T4>::isComplex, || QTypeInfoQuery<T3>::isComplex || QTypeInfoQuery<T4>::isComplex,
isStatic = QTypeInfoQuery<T1>::isStatic || QTypeInfoQuery<T2>::isStatic isStatic = QTypeInfoQuery<T1>::isStatic || QTypeInfoQuery<T2>::isStatic
@ -173,6 +177,7 @@ class QTypeInfo< CONTAINER<T> > \
{ \ { \
public: \ public: \
enum { \ enum { \
isSpecialized = true, \
isPointer = false, \ isPointer = false, \
isIntegral = false, \ isIntegral = false, \
isComplex = true, \ isComplex = true, \
@ -201,6 +206,7 @@ class QTypeInfo< CONTAINER<K, V> > \
{ \ { \
public: \ public: \
enum { \ enum { \
isSpecialized = true, \
isPointer = false, \ isPointer = false, \
isIntegral = false, \ isIntegral = false, \
isComplex = true, \ isComplex = true, \
@ -241,6 +247,7 @@ class QTypeInfo<TYPE > \
{ \ { \
public: \ public: \
enum { \ enum { \
isSpecialized = true, \
isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \
isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \ isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \
isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE), \ isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE), \

View File

@ -143,21 +143,17 @@ public:
} }
bool operator==(const QArgumentType &other) const bool operator==(const QArgumentType &other) const
{ {
if (_type) if (_type && other._type)
return _type == other._type; return _type == other._type;
else if (other._type)
return false;
else else
return _name == other._name; return name() == other.name();
} }
bool operator!=(const QArgumentType &other) const bool operator!=(const QArgumentType &other) const
{ {
if (_type) if (_type && other._type)
return _type != other._type; return _type != other._type;
else if (other._type)
return true;
else else
return _name != other._name; return name() != other.name();
} }
private: private:

View File

@ -316,22 +316,39 @@ void QThreadPoolPrivate::clear()
} }
/*! /*!
\internal \since 5.9
Searches for \a runnable in the queue, removes it from the queue and
returns \c true if it was found in the queue Attempts to remove the specified \a runnable from the queue if it is not yet started.
If the runnable had not been started, returns \c true, and ownership of \a runnable
is transferred to the caller (even when \c{runnable->autoDelete() == true}).
Otherwise returns \c false.
\note If \c{runnable->autoDelete() == true}, this function may remove the wrong
runnable. This is known as the \l{https://en.wikipedia.org/wiki/ABA_problem}{ABA problem}:
the original \a runnable may already have executed and has since been deleted.
The memory is re-used for another runnable, which then gets removed instead of
the intended one. For this reason, we recommend calling this function only for
runnables that are not auto-deleting.
\sa start(), QRunnable::autoDelete()
*/ */
bool QThreadPoolPrivate::stealRunnable(QRunnable *runnable) bool QThreadPool::tryTake(QRunnable *runnable)
{ {
Q_D(QThreadPool);
if (runnable == 0) if (runnable == 0)
return false; return false;
{ {
QMutexLocker locker(&mutex); QMutexLocker locker(&d->mutex);
QVector<QPair<QRunnable *, int> >::iterator it = queue.begin();
QVector<QPair<QRunnable *, int> >::iterator end = queue.end(); auto it = d->queue.begin();
auto end = d->queue.end();
while (it != end) { while (it != end) {
if (it->first == runnable) { if (it->first == runnable) {
queue.erase(it); d->queue.erase(it);
if (runnable->autoDelete())
--runnable->ref; // undo ++ref in start()
return true; return true;
} }
++it; ++it;
@ -349,10 +366,10 @@ bool QThreadPoolPrivate::stealRunnable(QRunnable *runnable)
*/ */
void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable) void QThreadPoolPrivate::stealAndRunRunnable(QRunnable *runnable)
{ {
if (!stealRunnable(runnable)) Q_Q(QThreadPool);
if (!q->tryTake(runnable))
return; return;
const bool autoDelete = runnable->autoDelete(); const bool del = runnable->autoDelete() && !runnable->ref; // tryTake already deref'ed
bool del = autoDelete && !--runnable->ref;
runnable->run(); runnable->run();
@ -642,24 +659,23 @@ void QThreadPool::clear()
d->clear(); d->clear();
} }
#if QT_DEPRECATED_SINCE(5, 9)
/*! /*!
\since 5.5 \since 5.5
\obsolete use tryTake() instead, but note the different deletion rules.
Removes the specified \a runnable from the queue if it is not yet started. Removes the specified \a runnable from the queue if it is not yet started.
The runnables for which \l{QRunnable::autoDelete()}{runnable->autoDelete()} The runnables for which \l{QRunnable::autoDelete()}{runnable->autoDelete()}
returns \c true are deleted. returns \c true are deleted.
\sa start() \sa start(), tryTake()
*/ */
void QThreadPool::cancel(QRunnable *runnable) void QThreadPool::cancel(QRunnable *runnable)
{ {
Q_D(QThreadPool); if (tryTake(runnable) && runnable->autoDelete() && !runnable->ref) // tryTake already deref'ed
if (!d->stealRunnable(runnable))
return;
if (runnable->autoDelete() && !--runnable->ref) {
delete runnable; delete runnable;
} }
} #endif
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -83,7 +83,12 @@ public:
bool waitForDone(int msecs = -1); bool waitForDone(int msecs = -1);
void clear(); void clear();
#if QT_DEPRECATED_SINCE(5, 9)
QT_DEPRECATED_X("use tryTake(), but note the different deletion rules")
void cancel(QRunnable *runnable); void cancel(QRunnable *runnable);
#endif
bool tryTake(QRunnable *runnable) Q_REQUIRED_RESULT;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -82,7 +82,6 @@ public:
void reset(); void reset();
bool waitForDone(int msecs); bool waitForDone(int msecs);
void clear(); void clear();
bool stealRunnable(QRunnable *runnable);
void stealAndRunRunnable(QRunnable *runnable); void stealAndRunRunnable(QRunnable *runnable);
mutable QMutex mutex; mutable QMutex mutex;

View File

@ -145,7 +145,7 @@ struct QGenericArrayOps
T *const begin = this->begin(); T *const begin = this->begin();
do { do {
new (begin + this->size) T(); new (begin + this->size) T;
} while (uint(++this->size) != newSize); } while (uint(++this->size) != newSize);
} }
@ -412,7 +412,7 @@ struct QArrayOpsSelector
template <class T> template <class T>
struct QArrayOpsSelector<T, struct QArrayOpsSelector<T,
typename std::enable_if< typename std::enable_if<
!QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic !QTypeInfoQuery<T>::isComplex && QTypeInfoQuery<T>::isRelocatable
>::type> >::type>
{ {
typedef QPodArrayOps<T> Type; typedef QPodArrayOps<T> Type;
@ -421,7 +421,7 @@ struct QArrayOpsSelector<T,
template <class T> template <class T>
struct QArrayOpsSelector<T, struct QArrayOpsSelector<T,
typename std::enable_if< typename std::enable_if<
QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic QTypeInfoQuery<T>::isComplex && QTypeInfoQuery<T>::isRelocatable
>::type> >::type>
{ {
typedef QMovableArrayOps<T> Type; typedef QMovableArrayOps<T> Type;

View File

@ -132,6 +132,9 @@ private:
} }
}; };
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4351) // MSVC 2013: "new behavior: elements of array ... will be default initialized"
// remove once we drop MSVC 2013 support
template <uint N> template <uint N>
class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
{ {
@ -153,6 +156,8 @@ public:
QByteArray pattern() const { return QByteArray(m_pattern, int(N - 1)); } QByteArray pattern() const { return QByteArray(m_pattern, int(N - 1)); }
}; };
QT_WARNING_POP
template <uint N> template <uint N>
Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) Q_DECL_NOTHROW Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) Q_DECL_NOTHROW
{ return QStaticByteArrayMatcher<N>(pattern); } { return QStaticByteArrayMatcher<N>(pattern); }

View File

@ -126,6 +126,7 @@ class QList
public: public:
struct MemoryLayout struct MemoryLayout
: std::conditional< : std::conditional<
// must stay isStatic until ### Qt 6 for BC reasons (don't use !isRelocatable)!
QTypeInfo<T>::isStatic || QTypeInfo<T>::isLarge, QTypeInfo<T>::isStatic || QTypeInfo<T>::isLarge,
QListData::IndirectLayout, QListData::IndirectLayout,
typename std::conditional< typename std::conditional<

View File

@ -136,7 +136,7 @@ QTimeZonePrivate::~QTimeZonePrivate()
{ {
} }
QTimeZonePrivate *QTimeZonePrivate::clone() QTimeZonePrivate *QTimeZonePrivate::clone() const
{ {
return new QTimeZonePrivate(*this); return new QTimeZonePrivate(*this);
} }
@ -784,7 +784,7 @@ QUtcTimeZonePrivate::~QUtcTimeZonePrivate()
{ {
} }
QTimeZonePrivate *QUtcTimeZonePrivate::clone() QUtcTimeZonePrivate *QUtcTimeZonePrivate::clone() const
{ {
return new QUtcTimeZonePrivate(*this); return new QUtcTimeZonePrivate(*this);
} }

View File

@ -88,7 +88,7 @@ void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
m_id = ianaId; m_id = ianaId;
} }
QTimeZonePrivate *QAndroidTimeZonePrivate::clone() QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
{ {
return new QAndroidTimeZonePrivate(*this); return new QAndroidTimeZonePrivate(*this);
} }

View File

@ -305,7 +305,7 @@ QIcuTimeZonePrivate::~QIcuTimeZonePrivate()
ucal_close(m_ucal); ucal_close(m_ucal);
} }
QTimeZonePrivate *QIcuTimeZonePrivate::clone() QIcuTimeZonePrivate *QIcuTimeZonePrivate::clone() const
{ {
return new QIcuTimeZonePrivate(*this); return new QIcuTimeZonePrivate(*this);
} }

View File

@ -82,7 +82,7 @@ QMacTimeZonePrivate::~QMacTimeZonePrivate()
[m_nstz release]; [m_nstz release];
} }
QTimeZonePrivate *QMacTimeZonePrivate::clone() QMacTimeZonePrivate *QMacTimeZonePrivate::clone() const
{ {
return new QMacTimeZonePrivate(*this); return new QMacTimeZonePrivate(*this);
} }

View File

@ -92,7 +92,7 @@ public:
QTimeZonePrivate(const QTimeZonePrivate &other); QTimeZonePrivate(const QTimeZonePrivate &other);
virtual ~QTimeZonePrivate(); virtual ~QTimeZonePrivate();
virtual QTimeZonePrivate *clone(); virtual QTimeZonePrivate *clone() const;
bool operator==(const QTimeZonePrivate &other) const; bool operator==(const QTimeZonePrivate &other) const;
bool operator!=(const QTimeZonePrivate &other) const; bool operator!=(const QTimeZonePrivate &other) const;
@ -187,7 +187,7 @@ public:
QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other); QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
virtual ~QUtcTimeZonePrivate(); virtual ~QUtcTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QUtcTimeZonePrivate *clone() const override;
Data data(qint64 forMSecsSinceEpoch) const Q_DECL_OVERRIDE; Data data(qint64 forMSecsSinceEpoch) const Q_DECL_OVERRIDE;
@ -234,7 +234,7 @@ public:
QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other); QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
~QIcuTimeZonePrivate(); ~QIcuTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QIcuTimeZonePrivate *clone() const override;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const Q_DECL_OVERRIDE; const QLocale &locale) const Q_DECL_OVERRIDE;
@ -287,15 +287,15 @@ Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzT
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate Q_DECL_FINAL : public QTimeZonePrivate class Q_AUTOTEST_EXPORT QTzTimeZonePrivate Q_DECL_FINAL : public QTimeZonePrivate
{ {
QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
public: public:
// Create default time zone // Create default time zone
QTzTimeZonePrivate(); QTzTimeZonePrivate();
// Create named time zone // Create named time zone
QTzTimeZonePrivate(const QByteArray &ianaId); QTzTimeZonePrivate(const QByteArray &ianaId);
QTzTimeZonePrivate(const QTzTimeZonePrivate &other);
~QTzTimeZonePrivate(); ~QTzTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QTzTimeZonePrivate *clone() const override;
QLocale::Country country() const Q_DECL_OVERRIDE; QLocale::Country country() const Q_DECL_OVERRIDE;
QString comment() const Q_DECL_OVERRIDE; QString comment() const Q_DECL_OVERRIDE;
@ -351,7 +351,7 @@ public:
QMacTimeZonePrivate(const QMacTimeZonePrivate &other); QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
~QMacTimeZonePrivate(); ~QMacTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QMacTimeZonePrivate *clone() const override;
QString comment() const Q_DECL_OVERRIDE; QString comment() const Q_DECL_OVERRIDE;
@ -404,7 +404,7 @@ public:
QWinTimeZonePrivate(const QWinTimeZonePrivate &other); QWinTimeZonePrivate(const QWinTimeZonePrivate &other);
~QWinTimeZonePrivate(); ~QWinTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QWinTimeZonePrivate *clone() const override;
QString comment() const Q_DECL_OVERRIDE; QString comment() const Q_DECL_OVERRIDE;
@ -454,7 +454,7 @@ public:
QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other); QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other);
~QAndroidTimeZonePrivate(); ~QAndroidTimeZonePrivate();
QTimeZonePrivate *clone() Q_DECL_OVERRIDE; QAndroidTimeZonePrivate *clone() const override;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const Q_DECL_OVERRIDE; const QLocale &locale) const Q_DECL_OVERRIDE;

View File

@ -452,13 +452,31 @@ static inline bool asciiIsLetter(char ch)
return ch >= 'a' && ch <= 'z'; return ch >= 'a' && ch <= 'z';
} }
namespace {
struct PosixZone
{
enum {
InvalidOffset = INT_MIN,
};
QString name;
int offset;
static PosixZone invalid() { return {QString(), InvalidOffset}; }
static PosixZone parse(const char *&pos, const char *end);
bool hasValidOffset() const Q_DECL_NOTHROW { return offset != InvalidOffset; }
};
} // unnamed namespace
// Returns the zone name, the offset (in seconds) and advances \a begin to // Returns the zone name, the offset (in seconds) and advances \a begin to
// where the parsing ended. Returns a zone of INT_MIN in case an offset // where the parsing ended. Returns a zone of INT_MIN in case an offset
// couldn't be read. // couldn't be read.
static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end) PosixZone PosixZone::parse(const char *&pos, const char *end)
{ {
static const char offsetChars[] = "0123456789:"; static const char offsetChars[] = "0123456789:";
QPair<QString, int> result = qMakePair(QString(), INT_MIN);
const char *nameBegin = pos; const char *nameBegin = pos;
const char *nameEnd; const char *nameEnd;
@ -480,7 +498,7 @@ static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const c
pos = nameEnd; pos = nameEnd;
} }
if (nameEnd - nameBegin < 3) if (nameEnd - nameBegin < 3)
return result; // name must be at least 3 characters long return invalid(); // name must be at least 3 characters long
// zone offset, form [+-]hh:mm:ss // zone offset, form [+-]hh:mm:ss
const char *zoneBegin = pos; const char *zoneBegin = pos;
@ -493,11 +511,10 @@ static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const c
++zoneEnd; ++zoneEnd;
} }
result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin); QString name = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
if (zoneEnd > zoneBegin) const int offset = zoneEnd > zoneBegin ? parsePosixOffset(zoneBegin, zoneEnd) : InvalidOffset;
result.second = parsePosixOffset(zoneBegin, zoneEnd);
pos = zoneEnd; pos = zoneEnd;
return result; return {std::move(name), offset};
} }
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
@ -517,19 +534,19 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
QList<QByteArray> parts = posixRule.split(','); QList<QByteArray> parts = posixRule.split(',');
QPair<QString, int> stdZone, dstZone; PosixZone stdZone, dstZone;
{ {
const QByteArray &zoneinfo = parts.at(0); const QByteArray &zoneinfo = parts.at(0);
const char *begin = zoneinfo.constBegin(); const char *begin = zoneinfo.constBegin();
stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); stdZone = PosixZone::parse(begin, zoneinfo.constEnd());
if (stdZone.second == INT_MIN) { if (!stdZone.hasValidOffset()) {
stdZone.second = 0; // reset to UTC if we failed to parse stdZone.offset = 0; // reset to UTC if we failed to parse
} else if (begin < zoneinfo.constEnd()) { } else if (begin < zoneinfo.constEnd()) {
dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); dstZone = PosixZone::parse(begin, zoneinfo.constEnd());
if (dstZone.second == INT_MIN) { if (!dstZone.hasValidOffset()) {
// if the dst offset isn't provided, it is 1 hour ahead of the standard offset // if the dst offset isn't provided, it is 1 hour ahead of the standard offset
dstZone.second = stdZone.second + (60 * 60); dstZone.offset = stdZone.offset + (60 * 60);
} }
} }
} }
@ -538,10 +555,10 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
if (parts.count() == 1) { if (parts.count() == 1) {
QTimeZonePrivate::Data data; QTimeZonePrivate::Data data;
data.atMSecsSinceEpoch = lastTranMSecs; data.atMSecsSinceEpoch = lastTranMSecs;
data.offsetFromUtc = stdZone.second; data.offsetFromUtc = stdZone.offset;
data.standardTimeOffset = stdZone.second; data.standardTimeOffset = stdZone.offset;
data.daylightTimeOffset = 0; data.daylightTimeOffset = 0;
data.abbreviation = stdZone.first; data.abbreviation = stdZone.name;
result << data; result << data;
return result; return result;
} }
@ -568,18 +585,18 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
for (int year = startYear; year <= endYear; ++year) { for (int year = startYear; year <= endYear; ++year) {
QTimeZonePrivate::Data dstData; QTimeZonePrivate::Data dstData;
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC); QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000); dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.offset * 1000);
dstData.offsetFromUtc = dstZone.second; dstData.offsetFromUtc = dstZone.offset;
dstData.standardTimeOffset = stdZone.second; dstData.standardTimeOffset = stdZone.offset;
dstData.daylightTimeOffset = dstZone.second - stdZone.second; dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
dstData.abbreviation = dstZone.first; dstData.abbreviation = dstZone.name;
QTimeZonePrivate::Data stdData; QTimeZonePrivate::Data stdData;
QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC); QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000); stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.offset * 1000);
stdData.offsetFromUtc = stdZone.second; stdData.offsetFromUtc = stdZone.offset;
stdData.standardTimeOffset = stdZone.second; stdData.standardTimeOffset = stdZone.offset;
stdData.daylightTimeOffset = 0; stdData.daylightTimeOffset = 0;
stdData.abbreviation = stdZone.first; stdData.abbreviation = stdZone.name;
// Part of the high year will overflow // Part of the high year will overflow
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) { if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
if (dstData.atMSecsSinceEpoch > 0) { if (dstData.atMSecsSinceEpoch > 0) {
@ -598,37 +615,21 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
// Create the system default time zone // Create the system default time zone
QTzTimeZonePrivate::QTzTimeZonePrivate() QTzTimeZonePrivate::QTzTimeZonePrivate()
#if QT_CONFIG(icu)
: m_icu(0)
#endif
{ {
init(systemTimeZoneId()); init(systemTimeZoneId());
} }
// Create a named time zone // Create a named time zone
QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId) QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
#if QT_CONFIG(icu)
: m_icu(0)
#endif
{ {
init(ianaId); init(ianaId);
} }
QTzTimeZonePrivate::QTzTimeZonePrivate(const QTzTimeZonePrivate &other)
: QTimeZonePrivate(other), m_tranTimes(other.m_tranTimes),
m_tranRules(other.m_tranRules), m_abbreviations(other.m_abbreviations),
#if QT_CONFIG(icu)
m_icu(other.m_icu),
#endif
m_posixRule(other.m_posixRule)
{
}
QTzTimeZonePrivate::~QTzTimeZonePrivate() QTzTimeZonePrivate::~QTzTimeZonePrivate()
{ {
} }
QTimeZonePrivate *QTzTimeZonePrivate::clone() QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
{ {
return new QTzTimeZonePrivate(*this); return new QTzTimeZonePrivate(*this);
} }

View File

@ -415,7 +415,7 @@ QWinTimeZonePrivate::~QWinTimeZonePrivate()
{ {
} }
QTimeZonePrivate *QWinTimeZonePrivate::clone() QWinTimeZonePrivate *QWinTimeZonePrivate::clone() const
{ {
return new QWinTimeZonePrivate(*this); return new QWinTimeZonePrivate(*this);
} }

View File

@ -352,7 +352,7 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
a = Prealloc; a = Prealloc;
} }
s = 0; s = 0;
if (QTypeInfo<T>::isStatic) { if (!QTypeInfoQuery<T>::isRelocatable) {
QT_TRY { QT_TRY {
// copy all the old elements // copy all the old elements
while (s < copySize) { while (s < copySize) {
@ -445,7 +445,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
if (n != 0) { if (n != 0) {
resize(s + n); resize(s + n);
const T copy(t); const T copy(t);
if (QTypeInfo<T>::isStatic) { if (!QTypeInfoQuery<T>::isRelocatable) {
T *b = ptr + offset; T *b = ptr + offset;
T *j = ptr + s; T *j = ptr + s;
T *i = j - n; T *i = j - n;

View File

@ -553,7 +553,7 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo
T *srcEnd = asize > d->size ? d->end() : d->begin() + asize; T *srcEnd = asize > d->size ? d->end() : d->begin() + asize;
T *dst = x->begin(); T *dst = x->begin();
if (QTypeInfo<T>::isStatic || (isShared && QTypeInfo<T>::isComplex)) { if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) {
// we can not move the data, we need to copy construct it // we can not move the data, we need to copy construct it
while (srcBegin != srcEnd) { while (srcBegin != srcEnd) {
new (dst++) T(*srcBegin++); new (dst++) T(*srcBegin++);
@ -598,7 +598,7 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo
} }
if (d != x) { if (d != x) {
if (!d->ref.deref()) { if (!d->ref.deref()) {
if (QTypeInfo<T>::isStatic || !aalloc || (isShared && QTypeInfo<T>::isComplex)) { if (!QTypeInfoQuery<T>::isRelocatable || !aalloc || (isShared && QTypeInfo<T>::isComplex)) {
// data was copy constructed, we need to call destructors // data was copy constructed, we need to call destructors
// or if !alloc we did nothing to the old 'd'. // or if !alloc we did nothing to the old 'd'.
freeData(d); freeData(d);
@ -697,7 +697,7 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
const T copy(t); const T copy(t);
if (!isDetached() || d->size + n > int(d->alloc)) if (!isDetached() || d->size + n > int(d->alloc))
reallocData(d->size, d->size + n, QArrayData::Grow); reallocData(d->size, d->size + n, QArrayData::Grow);
if (QTypeInfo<T>::isStatic) { if (!QTypeInfoQuery<T>::isRelocatable) {
T *b = d->end(); T *b = d->end();
T *i = d->end() + n; T *i = d->end() + n;
while (i != b) while (i != b)
@ -746,7 +746,7 @@ typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
detach(); detach();
abegin = d->begin() + itemsUntouched; abegin = d->begin() + itemsUntouched;
aend = abegin + itemsToErase; aend = abegin + itemsToErase;
if (QTypeInfo<T>::isStatic) { if (!QTypeInfoQuery<T>::isRelocatable) {
iterator moveBegin = abegin + itemsToErase; iterator moveBegin = abegin + itemsToErase;
iterator moveEnd = d->end(); iterator moveEnd = d->end();
while (moveBegin != moveEnd) { while (moveBegin != moveEnd) {

View File

@ -7,6 +7,7 @@
"commandline": { "commandline": {
"options": { "options": {
"accessibility": "boolean",
"angle": "boolean", "angle": "boolean",
"direct2d": "boolean", "direct2d": "boolean",
"directfb": "boolean", "directfb": "boolean",
@ -1042,6 +1043,11 @@ Specify -opengl desktop to use regular OpenGL."
"message": "The OpenGL functionality tests failed! "message": "The OpenGL functionality tests failed!
You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2], You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2],
QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform." QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform."
},
{
"type": "warning",
"condition": "!features.accessibility",
"message": "Accessibility disabled. This configuration of Qt is unsupported."
} }
], ],
@ -1049,6 +1055,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
{ {
"section": "Qt Gui", "section": "Qt Gui",
"entries": [ "entries": [
"accessibility",
"freetype", "freetype",
"system-freetype", "system-freetype",
"harfbuzz", "harfbuzz",

View File

@ -3,7 +3,7 @@ QT = core-private
qtConfig(opengl.*): MODULE_CONFIG = opengl qtConfig(opengl.*): MODULE_CONFIG = opengl
DEFINES += QT_NO_USING_NAMESPACE DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
QMAKE_DOCS = $$PWD/doc/qtgui.qdocconf QMAKE_DOCS = $$PWD/doc/qtgui.qdocconf

View File

@ -745,7 +745,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
#ifdef PNG_iTXt_SUPPORTED #ifdef PNG_iTXt_SUPPORTED
bool needsItxt = false; bool needsItxt = false;
foreach(const QChar c, it.value()) { for (const QChar c : it.value()) {
uchar ch = c.cell(); uchar ch = c.cell();
if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) { if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) {
needsItxt = true; needsItxt = true;

View File

@ -1124,7 +1124,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform
= QStringLiteral("This application failed to start because it could not find or load the Qt platform plugin \"%1\"\nin \"%2\".\n\n").arg(name, QDir::toNativeSeparators(platformPluginPath)); = QStringLiteral("This application failed to start because it could not find or load the Qt platform plugin \"%1\"\nin \"%2\".\n\n").arg(name, QDir::toNativeSeparators(platformPluginPath));
if (!keys.isEmpty()) { if (!keys.isEmpty()) {
fatalMessage += QStringLiteral("Available platform plugins are: %1.\n\n").arg( fatalMessage += QStringLiteral("Available platform plugins are: %1.\n\n").arg(
keys.join(QStringLiteral(", "))); keys.join(QLatin1String(", ")));
} }
fatalMessage += QStringLiteral("Reinstalling the application may fix this problem."); fatalMessage += QStringLiteral("Reinstalling the application may fix this problem.");
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)

View File

@ -109,6 +109,7 @@ public:
virtual QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; virtual QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const;
virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0; virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0;
virtual QPlatformWindow *createForeignWindow(QWindow *, WId) const { return 0; }
virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0; virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0;
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;

View File

@ -424,7 +424,7 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
} }
} }
void QWindowPrivate::create(bool recursive) void QWindowPrivate::create(bool recursive, WId nativeHandle)
{ {
Q_Q(QWindow); Q_Q(QWindow);
if (platformWindow) if (platformWindow)
@ -433,8 +433,10 @@ void QWindowPrivate::create(bool recursive)
if (q->parent()) if (q->parent())
q->parent()->create(); q->parent()->create();
platformWindow = QGuiApplicationPrivate::platformIntegration()->createPlatformWindow(q); QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
Q_ASSERT(platformWindow || q->type() == Qt::ForeignWindow); platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
: platformIntegration->createPlatformWindow(q);
Q_ASSERT(platformWindow);
if (!platformWindow) { if (!platformWindow) {
qWarning() << "Failed to create platform window for" << q << "with flags" << q->flags(); qWarning() << "Failed to create platform window for" << q << "with flags" << q->flags();
@ -629,9 +631,6 @@ WId QWindow::winId() const
{ {
Q_D(const QWindow); Q_D(const QWindow);
if (type() == Qt::ForeignWindow)
return WId(property("_q_foreignWinId").value<WId>());
if(!d->platformWindow) if(!d->platformWindow)
const_cast<QWindow *>(this)->create(); const_cast<QWindow *>(this)->create();
@ -865,7 +864,12 @@ void QWindow::setFlags(Qt::WindowFlags flags)
Qt::WindowFlags QWindow::flags() const Qt::WindowFlags QWindow::flags() const
{ {
Q_D(const QWindow); Q_D(const QWindow);
return d->windowFlags; Qt::WindowFlags flags = d->windowFlags;
if (d->platformWindow && d->platformWindow->isForeignWindow())
flags |= Qt::ForeignWindow;
return flags;
} }
/*! /*!
@ -2584,13 +2588,13 @@ QWindow *QWindow::fromWinId(WId id)
} }
QWindow *window = new QWindow; QWindow *window = new QWindow;
window->setFlags(Qt::ForeignWindow); qt_window_private(window)->create(false, id);
window->setProperty("_q_foreignWinId", QVariant::fromValue(id));
window->create();
if (!window->handle()) { if (!window->handle()) {
delete window; delete window;
return nullptr; return nullptr;
} }
return window; return window;
} }

View File

@ -136,7 +136,7 @@ public:
void updateSiblingPosition(SiblingPosition); void updateSiblingPosition(SiblingPosition);
bool windowRecreationRequired(QScreen *newScreen) const; bool windowRecreationRequired(QScreen *newScreen) const;
void create(bool recursive); void create(bool recursive, WId nativeHandle = 0);
void destroy(); void destroy();
void setTopLevelScreen(QScreen *newScreen, bool recreate); void setTopLevelScreen(QScreen *newScreen, bool recreate);
void connectToScreen(QScreen *topLevelScreen); void connectToScreen(QScreen *topLevelScreen);

View File

@ -133,7 +133,7 @@ NSImage *qt_mac_create_nsimage(const QIcon &icon, int defaultSize)
QList<QSize> availableSizes = icon.availableSizes(); QList<QSize> availableSizes = icon.availableSizes();
if (availableSizes.isEmpty() && defaultSize > 0) if (availableSizes.isEmpty() && defaultSize > 0)
availableSizes << QSize(defaultSize, defaultSize); availableSizes << QSize(defaultSize, defaultSize);
foreach (QSize size, availableSizes) { for (QSize size : qAsConst(availableSizes)) {
QPixmap pm = icon.pixmap(size); QPixmap pm = icon.pixmap(size);
if (pm.isNull()) if (pm.isNull())
continue; continue;

View File

@ -6549,8 +6549,8 @@ static void qInitDrawhelperFunctions()
destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon; qMemRotateFunctions[QPixelLayout::BPP16][0] = qt_memrotate90_16_neon;
qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon; qMemRotateFunctions[QPixelLayout::BPP16][2] = qt_memrotate270_16_neon;
#endif #endif
#endif // defined(__ARM_NEON__) #endif // defined(__ARM_NEON__)

View File

@ -45,12 +45,11 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window) QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle)
: QAndroidPlatformWindow(window), : QAndroidPlatformWindow(window),
m_surfaceId(-1) m_surfaceId(-1)
{ {
const WId wId = window->property("_q_foreignWinId").value<WId>(); m_view = reinterpret_cast<jobject>(nativeHandle);
m_view = reinterpret_cast<jobject>(wId);
if (m_view.isValid()) if (m_view.isValid())
QtAndroid::setViewVisibility(m_view.object(), false); QtAndroid::setViewVisibility(m_view.object(), false);
} }

View File

@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
{ {
public: public:
explicit QAndroidPlatformForeignWindow(QWindow *window); explicit QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle);
~QAndroidPlatformForeignWindow(); ~QAndroidPlatformForeignWindow();
void lower() override; void lower() override;
void raise() override; void raise() override;
@ -57,6 +57,7 @@ public:
void setVisible(bool visible) override; void setVisible(bool visible) override;
void applicationStateChanged(Qt::ApplicationState state) override; void applicationStateChanged(Qt::ApplicationState state) override;
void setParent(const QPlatformWindow *window) override; void setParent(const QPlatformWindow *window) override;
bool isForeignWindow() const override { return true; }
private: private:
int m_surfaceId; int m_surfaceId;

View File

@ -285,12 +285,15 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind
{ {
if (!QtAndroid::activity()) if (!QtAndroid::activity())
return nullptr; return nullptr;
if (window->type() == Qt::ForeignWindow)
return new QAndroidPlatformForeignWindow(window);
else
return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay); return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay);
} }
QPlatformWindow *QAndroidPlatformIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
{
return new QAndroidPlatformForeignWindow(window, nativeHandle);
}
QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const
{ {
return new QAndroidEventDispatcher; return new QAndroidEventDispatcher;

View File

@ -78,6 +78,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override; bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
QAbstractEventDispatcher *createEventDispatcher() const override; QAbstractEventDispatcher *createEventDispatcher() const override;

View File

@ -126,6 +126,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const Q_DECL_OVERRIDE;
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
#endif #endif

View File

@ -524,6 +524,11 @@ QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const
return new QCocoaWindow(window); return new QCocoaWindow(window);
} }
QPlatformWindow *QCocoaIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
{
return new QCocoaWindow(window, nativeHandle);
}
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{ {

View File

@ -156,7 +156,7 @@ class QCocoaWindow : public QObject, public QPlatformWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
QCocoaWindow(QWindow *tlw); QCocoaWindow(QWindow *tlw, WId nativeHandle = 0);
~QCocoaWindow(); ~QCocoaWindow();
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
@ -186,6 +186,8 @@ public:
QMargins frameMargins() const Q_DECL_OVERRIDE; QMargins frameMargins() const Q_DECL_OVERRIDE;
QSurfaceFormat format() const Q_DECL_OVERRIDE; QSurfaceFormat format() const Q_DECL_OVERRIDE;
bool isForeignWindow() const Q_DECL_OVERRIDE;
void requestActivateWindow() Q_DECL_OVERRIDE; void requestActivateWindow() Q_DECL_OVERRIDE;
WId winId() const Q_DECL_OVERRIDE; WId winId() const Q_DECL_OVERRIDE;
@ -206,7 +208,9 @@ public:
Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey(); Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey();
Q_NOTIFICATION_HANDLER(NSWindowDidMiniaturizeNotification) void windowDidMiniaturize(); Q_NOTIFICATION_HANDLER(NSWindowDidMiniaturizeNotification) void windowDidMiniaturize();
Q_NOTIFICATION_HANDLER(NSWindowDidDeminiaturizeNotification) void windowDidDeminiaturize(); Q_NOTIFICATION_HANDLER(NSWindowDidDeminiaturizeNotification) void windowDidDeminiaturize();
Q_NOTIFICATION_HANDLER(NSWindowWillEnterFullScreenNotification) void windowWillEnterFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowWillExitFullScreenNotification) void windowWillExitFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen();

View File

@ -433,7 +433,7 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterNotificationCallbacks)
const int QCocoaWindow::NoAlertRequest = -1; const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *tlw) QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
: QPlatformWindow(tlw) : QPlatformWindow(tlw)
, m_view(nil) , m_view(nil)
, m_nsWindow(0) , m_nsWindow(0)
@ -470,8 +470,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
QMacAutoReleasePool pool; QMacAutoReleasePool pool;
if (tlw->type() == Qt::ForeignWindow) { if (nativeHandle) {
m_view = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>()); m_view = reinterpret_cast<NSView *>(nativeHandle);
[m_view retain];
} else { } else {
m_view = [[QNSView alloc] initWithCocoaWindow:this]; m_view = [[QNSView alloc] initWithCocoaWindow:this];
// Enable high-dpi OpenGL for retina displays. Enabling has the side // Enable high-dpi OpenGL for retina displays. Enabling has the side
@ -562,6 +563,11 @@ void QCocoaWindow::setGeometry(const QRect &rectIn)
setCocoaGeometry(rect); setCocoaGeometry(rect);
} }
bool QCocoaWindow::isForeignWindow() const
{
return ![m_view isKindOfClass:[QNSView class]];
}
QRect QCocoaWindow::geometry() const QRect QCocoaWindow::geometry() const
{ {
// QWindows that are embedded in a NSView hiearchy may be considered // QWindows that are embedded in a NSView hiearchy may be considered
@ -941,6 +947,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
if (m_drawContentBorderGradient) if (m_drawContentBorderGradient)
styleMask |= NSTexturedBackgroundWindowMask; styleMask |= NSTexturedBackgroundWindowMask;
// Don't wipe fullscreen state
if (m_nsWindow.styleMask & NSFullScreenWindowMask)
styleMask |= NSFullScreenWindowMask;
return styleMask; return styleMask;
} }
@ -1363,19 +1373,40 @@ void QCocoaWindow::windowDidDeminiaturize()
reportCurrentWindowState(); reportCurrentWindowState();
} }
void QCocoaWindow::windowWillEnterFullScreen()
{
// The NSWindow needs to be resizable, otherwise we'll end up with
// the normal window geometry, centered in the middle of the screen
// on a black background. The styleMask will be reset below.
m_nsWindow.styleMask |= NSResizableWindowMask;
}
void QCocoaWindow::windowDidEnterFullScreen() void QCocoaWindow::windowDidEnterFullScreen()
{ {
Q_ASSERT_X(m_nsWindow.qt_fullScreen, "QCocoaWindow", Q_ASSERT_X(m_nsWindow.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first"); "FullScreen category processes window notifications first");
// Reset to original styleMask
setWindowFlags(m_windowFlags);
reportCurrentWindowState(); reportCurrentWindowState();
} }
void QCocoaWindow::windowWillExitFullScreen()
{
// The NSWindow needs to be resizable, otherwise we'll end up with
// a weird zoom animation. The styleMask will be reset below.
m_nsWindow.styleMask |= NSResizableWindowMask;
}
void QCocoaWindow::windowDidExitFullScreen() void QCocoaWindow::windowDidExitFullScreen()
{ {
Q_ASSERT_X(!m_nsWindow.qt_fullScreen, "QCocoaWindow", Q_ASSERT_X(!m_nsWindow.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first"); "FullScreen category processes window notifications first");
// Reset to original styleMask
setWindowFlags(m_windowFlags);
Qt::WindowState requestedState = window()->windowState(); Qt::WindowState requestedState = window()->windowState();
// Deliver update of QWindow state // Deliver update of QWindow state
@ -1869,24 +1900,13 @@ void QCocoaWindow::toggleMaximized()
void QCocoaWindow::toggleFullScreen() void QCocoaWindow::toggleFullScreen()
{ {
// The NSWindow needs to be resizable, otherwise we'll end up with // The window needs to have the correct collection behavior for the
// the normal window geometry, centered in the middle of the screen // toggleFullScreen call to have an effect. The collection behavior
// on a black background. // will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
const bool wasResizable = m_nsWindow.styleMask & NSResizableWindowMask;
m_nsWindow.styleMask |= NSResizableWindowMask;
// It also needs to have the correct collection behavior for the
// toggleFullScreen call to have an effect.
const bool wasFullScreenEnabled = m_nsWindow.collectionBehavior & NSWindowCollectionBehaviorFullScreenPrimary;
m_nsWindow.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary; m_nsWindow.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
const id sender = m_nsWindow; const id sender = m_nsWindow;
[m_nsWindow toggleFullScreen:sender]; [m_nsWindow toggleFullScreen:sender];
if (!wasResizable)
m_nsWindow.styleMask &= ~NSResizableWindowMask;
if (!wasFullScreenEnabled)
m_nsWindow.collectionBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
} }
bool QCocoaWindow::isTransitioningToFullScreen() const bool QCocoaWindow::isTransitioningToFullScreen() const

View File

@ -41,6 +41,7 @@
#include "qeglfskmsegldevice.h" #include "qeglfskmsegldevice.h"
#include <QGuiApplication> #include <QGuiApplication>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <errno.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -81,7 +81,7 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
d << "QMimeData("; d << "QMimeData(";
if (mimeData) { if (mimeData) {
const QStringList formats = mimeData->formats(); const QStringList formats = mimeData->formats();
d << "formats=" << formats.join(QStringLiteral(", ")); d << "formats=" << formats.join(QLatin1String(", "));
if (mimeData->hasText()) if (mimeData->hasText())
d << ", text=" << mimeData->text(); d << ", text=" << mimeData->text();
if (mimeData->hasHtml()) if (mimeData->hasHtml())
@ -321,7 +321,7 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
const HRESULT src = OleSetClipboard(m_data); const HRESULT src = OleSetClipboard(m_data);
if (src != S_OK) { if (src != S_OK) {
QString mimeDataFormats = mimeData ? QString mimeDataFormats = mimeData ?
mimeData->formats().join(QStringLiteral(", ")) : QString(QStringLiteral("NULL")); mimeData->formats().join(QLatin1String(", ")) : QString(QStringLiteral("NULL"));
qErrnoWarning("OleSetClipboard: Failed to set mime data (%s) on clipboard: %s", qErrnoWarning("OleSetClipboard: Failed to set mime data (%s) on clipboard: %s",
qPrintable(mimeDataFormats), qPrintable(mimeDataFormats),
QWindowsContext::comErrorString(src).constData()); QWindowsContext::comErrorString(src).constData());

View File

@ -1167,7 +1167,7 @@ void QWindowsNativeFileDialogBase::selectNameFilter(const QString &filter)
if (index < 0) { if (index < 0) {
qWarning("%s: Invalid parameter '%s' not found in '%s'.", qWarning("%s: Invalid parameter '%s' not found in '%s'.",
__FUNCTION__, qPrintable(filter), __FUNCTION__, qPrintable(filter),
qPrintable(m_nameFilters.join(QStringLiteral(", ")))); qPrintable(m_nameFilters.join(QLatin1String(", "))));
return; return;
} }
m_fileDialog->SetFileTypeIndex(index + 1); // one-based. m_fileDialog->SetFileTypeIndex(index + 1); // one-based.

View File

@ -304,24 +304,6 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
return result; return result;
} }
if (window->type() == Qt::ForeignWindow) {
const HWND hwnd = reinterpret_cast<HWND>(window->winId());
if (!IsWindow(hwnd)) {
qWarning("Windows QPA: Invalid foreign window ID %p.", hwnd);
return nullptr;
}
QWindowsForeignWindow *result = new QWindowsForeignWindow(window, hwnd);
const QRect obtainedGeometry = result->geometry();
QScreen *screen = Q_NULLPTR;
if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
screen = pScreen->screen();
if (screen && screen != window->screen())
window->setScreen(screen);
qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex
<< result->winId() << noshowbase << dec << obtainedGeometry << screen;
return result;
}
QWindowsWindowData requested; QWindowsWindowData requested;
requested.flags = window->flags(); requested.flags = window->flags();
requested.geometry = QHighDpi::toNativePixels(window->geometry(), window); requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
@ -365,6 +347,25 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
return result; return result;
} }
QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
{
const HWND hwnd = reinterpret_cast<HWND>(nativeHandle);
if (!IsWindow(hwnd)) {
qWarning("Windows QPA: Invalid foreign window ID %p.", hwnd);
return nullptr;
}
QWindowsForeignWindow *result = new QWindowsForeignWindow(window, hwnd);
const QRect obtainedGeometry = result->geometry();
QScreen *screen = Q_NULLPTR;
if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
screen = pScreen->screen();
if (screen && screen != window->screen())
window->setScreen(screen);
qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex
<< result->winId() << noshowbase << dec << obtainedGeometry << screen;
return result;
}
// Overridden to return a QWindowsDirect2DWindow in Direct2D plugin. // Overridden to return a QWindowsDirect2DWindow in Direct2D plugin.
QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const
{ {

View File

@ -73,6 +73,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override; bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
QOpenGLContext::OpenGLModuleType openGLModuleType() override; QOpenGLContext::OpenGLModuleType openGLModuleType() override;

View File

@ -171,6 +171,7 @@ public:
void raise() override { raise_sys(); } void raise() override { raise_sys(); }
void lower() override { lower_sys(); } void lower() override { lower_sys(); }
void setWindowTitle(const QString &title) override { setWindowTitle_sys(title); } void setWindowTitle(const QString &title) override { setWindowTitle_sys(title); }
bool isForeignWindow() const override { return true; }
protected: protected:
HWND handle() const override { return m_hwnd; } HWND handle() const override { return m_hwnd; }

View File

@ -214,6 +214,27 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
return xcbWindow; return xcbWindow;
} }
class QXcbForeignWindow : public QXcbWindow
{
public:
QXcbForeignWindow(QWindow *window, WId nativeHandle)
: QXcbWindow(window) { m_window = nativeHandle; }
~QXcbForeignWindow() {}
bool isForeignWindow() const override { return true; }
protected:
// No-ops
void create() override {}
void destroy() override {}
};
QPlatformWindow *QXcbIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
{
QXcbWindow *xcbWindow = new QXcbForeignWindow(window, nativeHandle);
xcbWindow->create();
return xcbWindow;
}
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{ {

View File

@ -61,6 +61,7 @@ public:
~QXcbIntegration(); ~QXcbIntegration();
QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif #endif

View File

@ -341,11 +341,6 @@ enum {
void QXcbWindow::create() void QXcbWindow::create()
{ {
if (window()->type() == Qt::ForeignWindow) {
m_window = window()->winId();
return;
}
destroy(); destroy();
m_windowState = Qt::WindowNoState; m_windowState = Qt::WindowNoState;
@ -590,9 +585,10 @@ QXcbWindow::~QXcbWindow()
if (m_currentBitmapCursor != XCB_CURSOR_NONE) { if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
xcb_free_cursor(xcb_connection(), m_currentBitmapCursor); xcb_free_cursor(xcb_connection(), m_currentBitmapCursor);
} }
if (window()->type() != Qt::ForeignWindow)
destroy(); destroy();
else {
if (isForeignWindow()) {
if (connection()->mouseGrabber() == this) if (connection()->mouseGrabber() == this)
connection()->setMouseGrabber(Q_NULLPTR); connection()->setMouseGrabber(Q_NULLPTR);
if (connection()->mousePressWindow() == this) if (connection()->mousePressWindow() == this)

View File

@ -47,8 +47,6 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#ifndef QT_NO_ACCESSIBILITY
#define QVERIFY_EVENT(event) \ #define QVERIFY_EVENT(event) \
QVERIFY(QTestAccessibility::verifyEvent(event)) QVERIFY(QTestAccessibility::verifyEvent(event))
@ -59,6 +57,8 @@
#include <QtTest/qtest_global.h> #include <QtTest/qtest_global.h>
#include <QtTest/qtestsystem.h> #include <QtTest/qtestsystem.h>
#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -294,5 +294,5 @@ private:
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_NO_ACCESSIBILITY #endif // QT_CONFIG(accessibility)
#endif // QTESTACCESSIBLE_H #endif // QTESTACCESSIBLE_H

View File

@ -305,7 +305,7 @@ int runMoc(int argc, char **argv)
const QStringList files = parser.positionalArguments(); const QStringList files = parser.positionalArguments();
if (files.count() > 1) { if (files.count() > 1) {
error(qPrintable(QStringLiteral("Too many input files specified: '") + files.join(QStringLiteral("' '")) + QLatin1Char('\''))); error(qPrintable(QLatin1String("Too many input files specified: '") + files.join(QLatin1String("' '")) + QLatin1Char('\'')));
parser.showHelp(1); parser.showHelp(1);
} else if (!files.isEmpty()) { } else if (!files.isEmpty()) {
filename = files.first(); filename = files.first();

View File

@ -62,6 +62,13 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace {
struct Message {
QString content;
QString type;
};
}
class QErrorMessagePrivate : public QDialogPrivate class QErrorMessagePrivate : public QDialogPrivate
{ {
Q_DECLARE_PUBLIC(QErrorMessage) Q_DECLARE_PUBLIC(QErrorMessage)
@ -70,7 +77,7 @@ public:
QCheckBox * again; QCheckBox * again;
QTextEdit * errors; QTextEdit * errors;
QLabel * icon; QLabel * icon;
std::queue<QPair<QString, QString> > pending; std::queue<Message> pending;
QSet<QString> doNotShow; QSet<QString> doNotShow;
QSet<QString> doNotShowType; QSet<QString> doNotShowType;
QString currentMessage; QString currentMessage;
@ -163,14 +170,20 @@ static void jump(QtMsgType t, const QMessageLogContext & /*context*/, const QStr
switch (t) { switch (t) {
case QtDebugMsg: case QtDebugMsg:
default:
rich = QErrorMessage::tr("Debug Message:"); rich = QErrorMessage::tr("Debug Message:");
break; break;
case QtWarningMsg: case QtWarningMsg:
rich = QErrorMessage::tr("Warning:"); rich = QErrorMessage::tr("Warning:");
break; break;
case QtCriticalMsg:
rich = QErrorMessage::tr("Critical Error:");
break;
case QtFatalMsg: case QtFatalMsg:
rich = QErrorMessage::tr("Fatal Error:"); rich = QErrorMessage::tr("Fatal Error:");
break;
case QtInfoMsg:
rich = QErrorMessage::tr("Information:");
break;
} }
rich = QString::fromLatin1("<p><b>%1</b></p>").arg(rich); rich = QString::fromLatin1("<p><b>%1</b></p>").arg(rich);
rich += Qt::convertFromPlainText(m, Qt::WhiteSpaceNormal); rich += Qt::convertFromPlainText(m, Qt::WhiteSpaceNormal);
@ -297,9 +310,8 @@ bool QErrorMessagePrivate::isMessageToBeShown(const QString &message, const QStr
bool QErrorMessagePrivate::nextPending() bool QErrorMessagePrivate::nextPending()
{ {
while (!pending.empty()) { while (!pending.empty()) {
QPair<QString,QString> &pendingMessage = pending.front(); QString message = std::move(pending.front().content);
QString message = qMove(pendingMessage.first); QString type = std::move(pending.front().type);
QString type = qMove(pendingMessage.second);
pending.pop(); pending.pop();
if (isMessageToBeShown(message, type)) { if (isMessageToBeShown(message, type)) {
#ifndef QT_NO_TEXTHTMLPARSER #ifndef QT_NO_TEXTHTMLPARSER
@ -349,7 +361,7 @@ void QErrorMessage::showMessage(const QString &message, const QString &type)
Q_D(QErrorMessage); Q_D(QErrorMessage);
if (!d->isMessageToBeShown(message, type)) if (!d->isMessageToBeShown(message, type))
return; return;
d->pending.push(qMakePair(message, type)); d->pending.push({message, type});
if (!isVisible() && d->nextPending()) if (!isVisible() && d->nextPending())
show(); show();
} }

View File

@ -254,6 +254,11 @@ QSizePolicy::ControlType QSizePolicy::controlType() const
\sa QStyle::layoutSpacing() \sa QStyle::layoutSpacing()
*/ */
void QSizePolicy::setControlType(ControlType type) void QSizePolicy::setControlType(ControlType type)
{
bits.ctype = toControlTypeFieldValue(type);
}
quint32 QSizePolicy::toControlTypeFieldValue(ControlType type) Q_DECL_NOTHROW
{ {
/* /*
The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10, The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
@ -271,10 +276,8 @@ void QSizePolicy::setControlType(ControlType type)
int i = 0; int i = 0;
while (true) { while (true) {
if (type & (0x1 << i)) { if (type & (0x1 << i))
bits.ctype = i; return i;
return;
}
++i; ++i;
} }
} }

View File

@ -119,18 +119,25 @@ public:
QT_SIZEPOLICY_CONSTEXPR QSizePolicy() : data(0) { } QT_SIZEPOLICY_CONSTEXPR QSizePolicy() : data(0) { }
#ifdef Q_COMPILER_UNIFORM_INIT
QT_SIZEPOLICY_CONSTEXPR QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType)
: bits{0, 0, quint32(horizontal), quint32(vertical),
type == DefaultType ? 0 : toControlTypeFieldValue(type), 0, 0, 0}
{}
#else
QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType)
: data(0) { : data(0) {
bits.horPolicy = horizontal; bits.horPolicy = horizontal;
bits.verPolicy = vertical; bits.verPolicy = vertical;
setControlType(type); setControlType(type);
} }
#endif // uniform-init
QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); } QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); }
QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); } QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); }
ControlType controlType() const; ControlType controlType() const;
void setHorizontalPolicy(Policy d) { bits.horPolicy = d; } Q_DECL_RELAXED_CONSTEXPR void setHorizontalPolicy(Policy d) { bits.horPolicy = d; }
void setVerticalPolicy(Policy d) { bits.verPolicy = d; } Q_DECL_RELAXED_CONSTEXPR void setVerticalPolicy(Policy d) { bits.verPolicy = d; }
void setControlType(ControlType type); void setControlType(ControlType type);
QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const { QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const {
@ -138,9 +145,9 @@ public:
| ( (horizontalPolicy() & ExpandFlag) ? Qt::Horizontal : Qt::Orientations() ) ; | ( (horizontalPolicy() & ExpandFlag) ? Qt::Horizontal : Qt::Orientations() ) ;
} }
void setHeightForWidth(bool b) { bits.hfw = b; } Q_DECL_RELAXED_CONSTEXPR void setHeightForWidth(bool b) { bits.hfw = b; }
QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const { return bits.hfw; } QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const { return bits.hfw; }
void setWidthForHeight(bool b) { bits.wfh = b; } Q_DECL_RELAXED_CONSTEXPR void setWidthForHeight(bool b) { bits.wfh = b; }
QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const { return bits.wfh; } QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const { return bits.wfh; }
QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const { return data == s.data; } QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const { return data == s.data; }
@ -152,13 +159,13 @@ public:
QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const { return static_cast<int>(bits.horStretch); } QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const { return static_cast<int>(bits.horStretch); }
QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const { return static_cast<int>(bits.verStretch); } QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const { return static_cast<int>(bits.verStretch); }
void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } Q_DECL_RELAXED_CONSTEXPR void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } Q_DECL_RELAXED_CONSTEXPR void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const { return bits.retainSizeWhenHidden; } QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const { return bits.retainSizeWhenHidden; }
void setRetainSizeWhenHidden(bool retainSize) { bits.retainSizeWhenHidden = retainSize; } Q_DECL_RELAXED_CONSTEXPR void setRetainSizeWhenHidden(bool retainSize) { bits.retainSizeWhenHidden = retainSize; }
void transpose() { *this = transposed(); } Q_DECL_RELAXED_CONSTEXPR void transpose() { *this = transposed(); }
#ifndef Q_QDOC #ifndef Q_QDOC
QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT
#endif #endif
@ -176,6 +183,8 @@ private:
struct Bits; struct Bits;
QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) Q_DECL_NOTHROW : bits(b) { } QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) Q_DECL_NOTHROW : bits(b) { }
static quint32 toControlTypeFieldValue(ControlType type) Q_DECL_NOTHROW;
struct Bits { struct Bits {
quint32 horStretch : 8; quint32 horStretch : 8;
quint32 verStretch : 8; quint32 verStretch : 8;

View File

@ -9190,6 +9190,7 @@ bool QWidget::event(QEvent *event)
const QWindow *win = te->window; const QWindow *win = te->window;
d->setWinId((win && win->handle()) ? win->handle()->winId() : 0); d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
} }
d->updateFont(d->data.fnt);
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
d->renderToTextureReallyDirty = 1; d->renderToTextureReallyDirty = 1;
#endif #endif

View File

@ -694,6 +694,10 @@ void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
this, SLOT(_q_editorTextChanged(QString))); this, SLOT(_q_editorTextChanged(QString)));
connect(d->edit, SIGNAL(cursorPositionChanged(int,int)), connect(d->edit, SIGNAL(cursorPositionChanged(int,int)),
this, SLOT(_q_editorCursorPositionChanged(int,int))); this, SLOT(_q_editorCursorPositionChanged(int,int)));
connect(d->edit, SIGNAL(cursorPositionChanged(int,int)),
this, SLOT(updateMicroFocus()));
connect(d->edit->d_func()->control, SIGNAL(updateMicroFocus()),
this, SLOT(updateMicroFocus()));
} }
d->updateEditFieldGeometry(); d->updateEditFieldGeometry();
d->edit->setContextMenuPolicy(Qt::NoContextMenu); d->edit->setContextMenuPolicy(Qt::NoContextMenu);

View File

@ -65,6 +65,7 @@
#include <private/qcombobox_p.h> #include <private/qcombobox_p.h>
#include <private/qabstractitemmodel_p.h> #include <private/qabstractitemmodel_p.h>
#include <private/qabstractscrollarea_p.h> #include <private/qabstractscrollarea_p.h>
#include <private/qlineedit_p.h>
#include <qdebug.h> #include <qdebug.h>
#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && !defined(QT_NO_EFFECTS) && QT_CONFIG(style_mac) #if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && !defined(QT_NO_EFFECTS) && QT_CONFIG(style_mac)
#include <private/qcore_mac_p.h> #include <private/qcore_mac_p.h>
@ -1790,6 +1791,7 @@ void QComboBox::setLineEdit(QLineEdit *edit)
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString))); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString)));
connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus())); connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus()));
connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus())); connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus()));
connect(d->lineEdit->d_func()->control, SIGNAL(updateMicroFocus()), this, SLOT(updateMicroFocus()));
d->lineEdit->setFrame(false); d->lineEdit->setFrame(false);
d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu); d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
d->updateFocusPolicy(); d->updateFocusPolicy();

View File

@ -239,6 +239,7 @@ public:
private: private:
friend class QAbstractSpinBox; friend class QAbstractSpinBox;
friend class QAccessibleLineEdit; friend class QAccessibleLineEdit;
friend class QComboBox;
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
friend class QDateTimeEdit; friend class QDateTimeEdit;
#endif #endif

View File

@ -196,6 +196,9 @@ void QLineEditPrivate::init(const QString& txt)
QObject::connect(control, SIGNAL(textChanged(QString)), QObject::connect(control, SIGNAL(textChanged(QString)),
q, SLOT(updateMicroFocus())); q, SLOT(updateMicroFocus()));
QObject::connect(control, SIGNAL(updateMicroFocus()),
q, SLOT(updateMicroFocus()));
// for now, going completely overboard with updates. // for now, going completely overboard with updates.
QObject::connect(control, SIGNAL(selectionChanged()), QObject::connect(control, SIGNAL(selectionChanged()),
q, SLOT(update())); q, SLOT(update()));

View File

@ -44,6 +44,7 @@
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
#include <private/qwidget_p.h> #include <private/qwidget_p.h>
#include <private/qwindow_p.h>
/*! /*!
\class QMacCocoaViewContainer \class QMacCocoaViewContainer
@ -117,7 +118,9 @@ QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate()
QMacCocoaViewContainer::QMacCocoaViewContainer(NSView *view, QWidget *parent) QMacCocoaViewContainer::QMacCocoaViewContainer(NSView *view, QWidget *parent)
: QWidget(*new QMacCocoaViewContainerPrivate, parent, 0) : QWidget(*new QMacCocoaViewContainerPrivate, parent, 0)
{ {
// Ensures that we have a QWindow, even if we're not a top level widget
setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_NativeWindow);
setCocoaView(view); setCocoaView(view);
} }
@ -149,23 +152,19 @@ void QMacCocoaViewContainer::setCocoaView(NSView *view)
[view retain]; [view retain];
d->nsview = view; d->nsview = view;
// Get rid of QWindow completely, and re-create a new vanilla one, which
// we will then re-configure to be a foreign window.
destroy();
create();
// Can't use QWindow::fromWinId() here due to QWidget controlling its
// QWindow, and can't use QWidget::createWindowContainer() due to the
// QMacCocoaViewContainer class being public API instead of a factory
// function.
QWindow *window = windowHandle(); QWindow *window = windowHandle();
// Note that we only set the flag on the QWindow, and not the QWidget.
// These two are not in sync, so from a QWidget standpoint the widget
// is not a Window, and hence will be shown when the parent widget is
// shown, like all QWidget children.
window->setFlags(Qt::ForeignWindow);
window->setProperty("_q_foreignWinId", view ? WId(view) : QVariant());
// Destroying the platform window implies hiding the window, and we
// also lose the geometry information that the platform window kept,
// and fall back to the stale QWindow geometry, so we update the two
// based on the widget visibility and geometry, which is up to date.
window->destroy(); window->destroy();
window->setVisible(isVisible()); qt_window_private(window)->create(false, WId(view));
window->setGeometry(geometry()); Q_ASSERT(window->handle());
window->create();
[oldView release]; [oldView release];
} }

View File

@ -734,7 +734,7 @@ QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
QTest::newRow("QPair<P,C>") << ::qMetaTypeId<QPair<P,C> >() << false << true << false << false; QTest::newRow("QPair<P,C>") << ::qMetaTypeId<QPair<P,C> >() << false << true << false << false;
QTest::newRow("QPair<P,M>") << ::qMetaTypeId<QPair<P,M> >() << true << true << false << false; QTest::newRow("QPair<P,M>") << ::qMetaTypeId<QPair<P,M> >() << true << true << false << false;
QTest::newRow("QPair<P,P>") << ::qMetaTypeId<QPair<P,P> >() << true << false << false << false; QTest::newRow("QPair<P,P>") << ::qMetaTypeId<QPair<P,P> >() << true << false << false << false;
QTest::newRow("FlagsDataEnum") << ::qMetaTypeId<FlagsDataEnum>() << true << true << false << true; QTest::newRow("FlagsDataEnum") << ::qMetaTypeId<FlagsDataEnum>() << true << false << false << true;
// invalid ids. // invalid ids.
QTest::newRow("-1") << -1 << false << false << false << false; QTest::newRow("-1") << -1 << false << false << false << false;

View File

@ -89,6 +89,7 @@ private slots:
void waitForDone(); void waitForDone();
void clear(); void clear();
void cancel(); void cancel();
void tryTake();
void waitForDoneTimeout(); void waitForDoneTimeout();
void destroyingWaitsForTasksToFinish(); void destroyingWaitsForTasksToFinish();
void stressTest(); void stressTest();
@ -1042,6 +1043,97 @@ void tst_QThreadPool::cancel()
delete runnables[runs-1]; delete runnables[runs-1];
} }
void tst_QThreadPool::tryTake()
{
QSemaphore sem(0);
QSemaphore startedThreads(0);
class SemaphoreReleaser
{
QSemaphore &sem;
int n;
Q_DISABLE_COPY(SemaphoreReleaser)
public:
explicit SemaphoreReleaser(QSemaphore &sem, int n)
: sem(sem), n(n) {}
~SemaphoreReleaser()
{
sem.release(n);
}
};
class BlockingRunnable : public QRunnable
{
public:
QSemaphore &sem;
QSemaphore &startedThreads;
QAtomicInt &dtorCounter;
QAtomicInt &runCounter;
int dummy;
explicit BlockingRunnable(QSemaphore &s, QSemaphore &started, QAtomicInt &c, QAtomicInt &r)
: sem(s), startedThreads(started), dtorCounter(c), runCounter(r) {}
~BlockingRunnable()
{
dtorCounter.fetchAndAddRelaxed(1);
}
void run() override
{
startedThreads.release();
runCounter.fetchAndAddRelaxed(1);
sem.acquire();
count.ref();
}
};
enum {
MaxThreadCount = 3,
OverProvisioning = 2,
Runs = MaxThreadCount * OverProvisioning
};
QThreadPool threadPool;
threadPool.setMaxThreadCount(MaxThreadCount);
BlockingRunnable *runnables[Runs];
// ensure that the QThreadPool doesn't deadlock if any of the checks fail
// and cause an early return:
const SemaphoreReleaser semReleaser(sem, Runs);
count.store(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;
for (int i = 0; i < Runs; i++) {
runnables[i] = new BlockingRunnable(sem, startedThreads, dtorCounter, runCounter);
runnables[i]->setAutoDelete(i != 0 && i != Runs - 1); // one which will run and one which will not
QVERIFY(!threadPool.tryTake(runnables[i])); // verify NOOP for jobs not in the queue
threadPool.start(runnables[i]);
}
// wait for all worker threads to have started up:
QVERIFY(startedThreads.tryAcquire(MaxThreadCount, 60*1000 /* 1min */));
for (int i = 0; i < MaxThreadCount; ++i) {
// check taking runnables doesn't work once they were started:
QVERIFY(!threadPool.tryTake(runnables[i]));
}
for (int i = MaxThreadCount; i < Runs ; ++i) {
QVERIFY(threadPool.tryTake(runnables[i]));
delete runnables[i];
}
runnables[0]->dummy = 0; // valgrind will catch this if tryTake() is crazy enough to delete currently running jobs
QCOMPARE(dtorCounter.load(), int(Runs - MaxThreadCount));
sem.release(MaxThreadCount);
threadPool.waitForDone();
QCOMPARE(runCounter.load(), int(MaxThreadCount));
QCOMPARE(count.load(), int(MaxThreadCount));
QCOMPARE(dtorCounter.load(), int(Runs - 1));
delete runnables[0]; // if the pool deletes them then we'll get double-free crash
}
void tst_QThreadPool::destroyingWaitsForTasksToFinish() void tst_QThreadPool::destroyingWaitsForTasksToFinish()
{ {
QTime total, pass; QTime total, pass;

View File

@ -113,6 +113,8 @@ void tst_QSizePolicy::constExpr()
// check that certain ctors are constexpr (compile-only): // check that certain ctors are constexpr (compile-only):
{ Q_CONSTEXPR QSizePolicy sp; Q_UNUSED(sp); } { Q_CONSTEXPR QSizePolicy sp; Q_UNUSED(sp); }
{ Q_CONSTEXPR QSizePolicy sp = QSizePolicy(); Q_UNUSED(sp); } { Q_CONSTEXPR QSizePolicy sp = QSizePolicy(); Q_UNUSED(sp); }
{ Q_CONSTEXPR QSizePolicy sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); Q_UNUSED(sp); }
{ Q_CONSTEXPR QSizePolicy sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding, QSizePolicy::DefaultType); Q_UNUSED(sp); }
#else #else
QSKIP("QSizePolicy cannot be constexpr with this version of the compiler."); QSKIP("QSizePolicy cannot be constexpr with this version of the compiler.");
#endif #endif

View File

@ -4,7 +4,7 @@
CONFIG += testcase CONFIG += testcase
TARGET = tst_qabstractspinbox TARGET = tst_qabstractspinbox
QT += widgets testlib QT += widgets gui-private core-private testlib
SOURCES += tst_qabstractspinbox.cpp SOURCES += tst_qabstractspinbox.cpp

View File

@ -35,6 +35,20 @@
#include <qlineedit.h> #include <qlineedit.h>
#include <qspinbox.h> #include <qspinbox.h>
#include "../../../shared/platforminputcontext.h"
#include <private/qinputmethod_p.h>
static inline void centerOnScreen(QWidget *w, const QSize &size)
{
const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset);
}
static inline void centerOnScreen(QWidget *w)
{
centerOnScreen(w, w->geometry().size());
}
class tst_QAbstractSpinBox : public QObject class tst_QAbstractSpinBox : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -44,11 +58,19 @@ public:
virtual ~tst_QAbstractSpinBox(); virtual ~tst_QAbstractSpinBox();
private slots: private slots:
void initTestCase();
void cleanupTestCase();
void getSetCheck(); void getSetCheck();
// task-specific tests below me: // task-specific tests below me:
void task183108_clear(); void task183108_clear();
void task228728_cssselector(); void task228728_cssselector();
void inputMethodUpdate();
private:
PlatformInputContext m_platformInputContext;
}; };
tst_QAbstractSpinBox::tst_QAbstractSpinBox() tst_QAbstractSpinBox::tst_QAbstractSpinBox()
@ -67,6 +89,18 @@ public:
void setLineEdit(QLineEdit *le) { QAbstractSpinBox::setLineEdit(le); } void setLineEdit(QLineEdit *le) { QAbstractSpinBox::setLineEdit(le); }
}; };
void tst_QAbstractSpinBox::initTestCase()
{
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &m_platformInputContext;
}
void tst_QAbstractSpinBox::cleanupTestCase()
{
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = 0;
}
// Testing get/set functions // Testing get/set functions
void tst_QAbstractSpinBox::getSetCheck() void tst_QAbstractSpinBox::getSetCheck()
{ {
@ -141,6 +175,60 @@ void tst_QAbstractSpinBox::task228728_cssselector()
QSpinBox box; QSpinBox box;
} }
void tst_QAbstractSpinBox::inputMethodUpdate()
{
QSpinBox box;
QSpinBox *testWidget = &box;
testWidget->setRange(0, 1);
centerOnScreen(testWidget);
testWidget->clear();
testWidget->show();
QVERIFY(QTest::qWaitForWindowExposed(testWidget));
testWidget->activateWindow();
testWidget->setFocus();
QTRY_VERIFY(testWidget->hasFocus());
QTRY_COMPARE(qApp->focusObject(), testWidget);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("1", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant());
QInputMethodEvent event("1", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("", attributes);
event.setCommitString("1");
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
QCOMPARE(testWidget->value(), 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant());
QInputMethodEvent event("", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
}
QTEST_MAIN(tst_QAbstractSpinBox) QTEST_MAIN(tst_QAbstractSpinBox)
#include "tst_qabstractspinbox.moc" #include "tst_qabstractspinbox.moc"

View File

@ -64,6 +64,9 @@
#include <qproxystyle.h> #include <qproxystyle.h>
#include <qfont.h> #include <qfont.h>
#include "../../../shared/platforminputcontext.h"
#include <private/qinputmethod_p.h>
static inline void setFrameless(QWidget *w) static inline void setFrameless(QWidget *w)
{ {
Qt::WindowFlags flags = w->windowFlags(); Qt::WindowFlags flags = w->windowFlags();
@ -80,6 +83,8 @@ public:
tst_QComboBox() {} tst_QComboBox() {}
private slots: private slots:
void initTestCase();
void cleanupTestCase();
void getSetCheck(); void getSetCheck();
void ensureReturnIsIgnored(); void ensureReturnIsIgnored();
void setEditable(); void setEditable();
@ -162,6 +167,10 @@ private slots:
void task_QTBUG_39088_inputMethodHints(); void task_QTBUG_39088_inputMethodHints();
void task_QTBUG_49831_scrollerNotActivated(); void task_QTBUG_49831_scrollerNotActivated();
void task_QTBUG_56693_itemFontFromModel(); void task_QTBUG_56693_itemFontFromModel();
void inputMethodUpdate();
private:
PlatformInputContext m_platformInputContext;
}; };
class MyAbstractItemDelegate : public QAbstractItemDelegate class MyAbstractItemDelegate : public QAbstractItemDelegate
@ -207,6 +216,18 @@ protected:
QRegion visualRegionForSelection(const QItemSelection &) const { return QRegion(); } QRegion visualRegionForSelection(const QItemSelection &) const { return QRegion(); }
}; };
void tst_QComboBox::initTestCase()
{
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &m_platformInputContext;
}
void tst_QComboBox::cleanupTestCase()
{
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = 0;
}
// Testing get/set functions // Testing get/set functions
void tst_QComboBox::getSetCheck() void tst_QComboBox::getSetCheck()
{ {
@ -3324,5 +3345,59 @@ void tst_QComboBox::task_QTBUG_56693_itemFontFromModel()
box.hidePopup(); box.hidePopup();
} }
void tst_QComboBox::inputMethodUpdate()
{
TestWidget topLevel;
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QComboBox *testWidget = topLevel.comboBox();
// make sure we have no lineedit
QVERIFY(!testWidget->lineEdit());
// test setEditable(true)
testWidget->setEditable(true);
QVERIFY(testWidget->lineEdit());
testWidget->activateWindow();
testWidget->setFocus();
QTRY_VERIFY(testWidget->hasFocus());
QTRY_COMPARE(qApp->focusObject(), testWidget);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("preedit text", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant());
QInputMethodEvent event("preedit text", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("", attributes);
event.setCommitString("preedit text");
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
QCOMPARE(testWidget->lineEdit()->text(), QString("preedit text"));
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant());
QInputMethodEvent event("", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
}
QTEST_MAIN(tst_QComboBox) QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc" #include "tst_qcombobox.moc"

View File

@ -294,6 +294,8 @@ private slots:
void inputMethodQueryImHints_data(); void inputMethodQueryImHints_data();
void inputMethodQueryImHints(); void inputMethodQueryImHints();
void inputMethodUpdate();
void undoRedoAndEchoModes_data(); void undoRedoAndEchoModes_data();
void undoRedoAndEchoModes(); void undoRedoAndEchoModes();
@ -4184,6 +4186,57 @@ void tst_QLineEdit::inputMethodQueryImHints()
QCOMPARE(static_cast<Qt::InputMethodHints>(value.toInt()), hints); QCOMPARE(static_cast<Qt::InputMethodHints>(value.toInt()), hints);
} }
void tst_QLineEdit::inputMethodUpdate()
{
QLineEdit *testWidget = ensureTestWidget();
centerOnScreen(testWidget);
testWidget->show();
QVERIFY(QTest::qWaitForWindowExposed(testWidget));
testWidget->setText("");
testWidget->activateWindow();
testWidget->setFocus();
QTRY_VERIFY(testWidget->hasFocus());
QTRY_COMPARE(qApp->focusObject(), testWidget);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("preedit text", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant());
QInputMethodEvent event("preedit text", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
QInputMethodEvent event("", attributes);
event.setCommitString("preedit text");
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
QCOMPARE(testWidget->text(), QString("preedit text"));
m_platformInputContext.m_updateCallCount = 0;
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant());
QInputMethodEvent event("", attributes);
QApplication::sendEvent(testWidget, &event);
}
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
}
void tst_QLineEdit::undoRedoAndEchoModes_data() void tst_QLineEdit::undoRedoAndEchoModes_data()
{ {
QTest::addColumn<int>("echoMode"); QTest::addColumn<int>("echoMode");

View File

@ -49,6 +49,7 @@ SUBDIRS=\
# The following tests depend on private API: # The following tests depend on private API:
!qtConfig(private_tests): SUBDIRS -= \ !qtConfig(private_tests): SUBDIRS -= \
qabstractspinbox \
qcombobox \ qcombobox \
qmainwindow \ qmainwindow \
qtextedit \ qtextedit \

View File

@ -191,12 +191,12 @@ static bool isTopLevel(const QObject *o)
return false; return false;
} }
static Qt::WindowState windowState(const QObject *o) static Qt::WindowStates windowState(const QObject *o)
{ {
if (o->isWidgetType()) { if (o->isWidgetType()) {
Qt::WindowStates states = static_cast<const QWidget *>(o)->windowState(); Qt::WindowStates states = static_cast<const QWidget *>(o)->windowState();
states &= ~Qt::WindowActive; states &= ~Qt::WindowActive;
return static_cast<Qt::WindowState>(int(states)); return states;
} }
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
if (o->isWindowType()) if (o->isWindowType())

View File

@ -202,16 +202,21 @@ PreviewWindow::PreviewWindow(QWidget *parent)
setWindowTitle(tr("Preview <QWidget> Qt %1").arg(QLatin1String(QT_VERSION_STR))); setWindowTitle(tr("Preview <QWidget> Qt %1").arg(QLatin1String(QT_VERSION_STR)));
} }
void PreviewWindow::resizeEvent(QResizeEvent *e) bool PreviewWindow::event(QEvent *event)
{ {
QWidget::resizeEvent(e); const bool ret = QWidget::event(event);
switch (event->type()) {
case QEvent::Move:
case QEvent::Resize:
case QEvent::WindowStateChange:
updateInfo(); updateInfo();
break;
default:
break;
} }
void PreviewWindow::moveEvent(QMoveEvent *e) return ret;
{
QWidget::moveEvent(e);
updateInfo();
} }
void PreviewWindow::setWindowFlags(Qt::WindowFlags flags) void PreviewWindow::setWindowFlags(Qt::WindowFlags flags)
@ -234,16 +239,21 @@ PreviewDialog::PreviewDialog(QWidget *parent)
setWindowTitle(tr("Preview <QDialog> Qt %1").arg(QLatin1String(QT_VERSION_STR))); setWindowTitle(tr("Preview <QDialog> Qt %1").arg(QLatin1String(QT_VERSION_STR)));
} }
void PreviewDialog::resizeEvent(QResizeEvent *e) bool PreviewDialog::event(QEvent *event)
{ {
QDialog::resizeEvent(e); const bool ret = QDialog::event(event);
switch (event->type()) {
case QEvent::Move:
case QEvent::Resize:
case QEvent::WindowStateChange:
updateInfo(); updateInfo();
break;
default:
break;
} }
void PreviewDialog::moveEvent(QMoveEvent *e) return ret;
{
QDialog::moveEvent(e);
updateInfo();
} }
void PreviewDialog::setWindowFlags(Qt::WindowFlags flags) void PreviewDialog::setWindowFlags(Qt::WindowFlags flags)

View File

@ -48,8 +48,7 @@ public slots:
void updateInfo(); void updateInfo();
protected: protected:
void resizeEvent(QResizeEvent *); bool event(QEvent *) override;
void moveEvent(QMoveEvent *);
private: private:
QPlainTextEdit *textEdit; QPlainTextEdit *textEdit;
@ -68,8 +67,7 @@ public slots:
void updateInfo(); void updateInfo();
protected: protected:
void resizeEvent(QResizeEvent *); bool event(QEvent *) override;
void moveEvent(QMoveEvent *);
private: private:
QPlainTextEdit *textEdit; QPlainTextEdit *textEdit;