diff options
author | Liang Qi <liang.qi@qt.io> | 2016-11-16 07:37:38 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-11-16 12:35:36 +0100 |
commit | 90c425642dfeae4564b43dacf15f80479962e910 (patch) | |
tree | 7e51683195210b3c70c04a8a0753ee272af1cd4c /src | |
parent | 1a43199fcea1bcec1ebf1a1a12cd3dcb942d67b4 (diff) | |
parent | 9808b53fde1dfc65ad3757cc6720e430c3cc89a2 (diff) |
Merge remote-tracking branch 'origin/5.7' into 5.8
Conflicts:
mkspecs/common/linux-android.conf
src/gui/opengl/qopengl.h
src/network/socket/qnativesocketengine_winrt.cpp
src/network/socket/qnativesocketengine_winrt_p.h
src/plugins/platforms/cocoa/qcocoawindow.mm
src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
sync.profile
Change-Id: If70aaf2c49df91157b864cf0d7d9513546c9bec4
Diffstat (limited to 'src')
43 files changed, 317 insertions, 146 deletions
diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp index e9a1366af0..d509349a51 100644 --- a/src/corelib/json/qjson.cpp +++ b/src/corelib/json/qjson.cpp @@ -135,10 +135,12 @@ bool Data::valid() const return false; bool res = false; - if (header->root()->is_object) - res = static_cast<Object *>(header->root())->isValid(); + Base *root = header->root(); + int maxSize = alloc - sizeof(Header); + if (root->is_object) + res = static_cast<Object *>(root)->isValid(maxSize); else - res = static_cast<Array *>(header->root())->isValid(); + res = static_cast<Array *>(root)->isValid(maxSize); return res; } @@ -223,9 +225,9 @@ int Object::indexOf(QLatin1String key, bool *exists) const return min; } -bool Object::isValid() const +bool Object::isValid(int maxSize) const { - if (tableOffset + length*sizeof(offset) > size) + if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size) return false; QString lastKey; @@ -234,8 +236,7 @@ bool Object::isValid() const if (entryOffset + sizeof(Entry) >= tableOffset) return false; Entry *e = entryAt(i); - int s = e->size(); - if (table()[i] + s > tableOffset) + if (!e->isValid(tableOffset - table()[i])) return false; QString key = e->key(); if (key < lastKey) @@ -249,9 +250,9 @@ bool Object::isValid() const -bool Array::isValid() const +bool Array::isValid(int maxSize) const { - if (tableOffset + length*sizeof(offset) > size) + if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size) return false; for (uint i = 0; i < length; ++i) { @@ -359,12 +360,12 @@ bool Value::isValid(const Base *b) const int s = usedStorage(b); if (!s) return true; - if (s < 0 || offset + s > (int)b->tableOffset) + if (s < 0 || s > (int)b->tableOffset - offset) return false; if (type == QJsonValue::Array) - return static_cast<Array *>(base(b))->isValid(); + return static_cast<Array *>(base(b))->isValid(s); if (type == QJsonValue::Object) - return static_cast<Object *>(base(b))->isValid(); + return static_cast<Object *>(base(b))->isValid(s); return true; } diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 4be62172a2..0c78fadfc7 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -326,12 +326,19 @@ public: explicit String(const char *data) { d = (Data *)data; } struct Data { - qle_int length; + qle_uint length; qle_ushort utf16[1]; }; Data *d; + int byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; } + bool isValid(int maxSize) const { + // Check byteSize() <= maxSize, avoiding integer overflow + maxSize -= sizeof(uint); + return maxSize >= 0 && uint(d->length) <= maxSize / sizeof(ushort); + } + inline String &operator=(const QString &str) { d->length = str.length(); @@ -400,11 +407,16 @@ public: explicit Latin1String(const char *data) { d = (Data *)data; } struct Data { - qle_short length; + qle_ushort length; char latin1[1]; }; Data *d; + int byteSize() const { return sizeof(ushort) + sizeof(char)*(d->length); } + bool isValid(int maxSize) const { + return byteSize() <= maxSize; + } + inline Latin1String &operator=(const QString &str) { int len = d->length = str.length(); @@ -606,7 +618,7 @@ public: int indexOf(const QString &key, bool *exists) const; int indexOf(QLatin1String key, bool *exists) const; - bool isValid() const; + bool isValid(int maxSize) const; }; @@ -616,7 +628,7 @@ public: inline Value at(int i) const; inline Value &operator [](int i); - bool isValid() const; + bool isValid(int maxSize) const; }; @@ -671,12 +683,12 @@ public: // key // value data follows key - int size() const { + uint size() const { int s = sizeof(Entry); if (value.latinKey) - s += sizeof(ushort) + qFromLittleEndian(*(ushort *) ((const char *)this + sizeof(Entry))); + s += shallowLatin1Key().byteSize(); else - s += sizeof(uint) + sizeof(ushort)*qFromLittleEndian(*(int *) ((const char *)this + sizeof(Entry))); + s += shallowKey().byteSize(); return alignedSize(s); } @@ -702,6 +714,15 @@ public: return shallowKey().toString(); } + bool isValid(int maxSize) const { + if (maxSize < (int)sizeof(Entry)) + return false; + maxSize -= sizeof(Entry); + if (value.latinKey) + return shallowLatin1Key().isValid(maxSize); + return shallowKey().isValid(maxSize); + } + bool operator ==(const QString &key) const; inline bool operator !=(const QString &key) const { return !operator ==(key); } inline bool operator >=(const QString &key) const; @@ -714,8 +735,6 @@ public: bool operator >=(const Entry &other) const; }; -inline bool operator!=(const Entry &lhs, const Entry &rhs) { return !(lhs == rhs); } - inline bool Entry::operator >=(const QString &key) const { if (value.latinKey) diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index fb651f0f24..b5b6f36bc6 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -599,8 +599,8 @@ bool QJsonObject::operator==(const QJsonObject &other) const for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); - QJsonPrivate::Entry *oe = other.o->entryAt(i); - if (*e != *oe || QJsonValue(d, o, e->value) != QJsonValue(other.d, other.o, oe->value)) + QJsonValue v(d, o, e->value); + if (other.value(e->key()) != v) return false; } diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index 3b2321aa49..ff397fc750 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -42,6 +42,7 @@ #include <QtCore/QCoreApplication> #include <QtCore/QThread> #include <QtCore/QHash> +#include <QtCore/QMutex> #include <QtCore/qfunctions_winrt.h> #include <private/qabstracteventdispatcher_p.h> #include <private/qcoreapplication_p.h> @@ -151,6 +152,7 @@ public: private: QHash<int, QObject *> timerIdToObject; QVector<WinRTTimerInfo> timerInfos; + mutable QMutex timerInfoLock; QHash<HANDLE, int> timerHandleToId; QHash<int, HANDLE> timerIdToHandle; QHash<int, HANDLE> timerIdToCancelHandle; @@ -167,6 +169,7 @@ private: timerIdToObject.insert(id, obj); const quint64 targetTime = qt_msectime() + interval; const WinRTTimerInfo info(id, interval, type, obj, targetTime); + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) timerInfos.resize(id + 1); timerInfos[id] = info; @@ -175,6 +178,7 @@ private: bool removeTimer(int id) { + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) return false; @@ -312,14 +316,18 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) if (timerId == INTERRUPT_HANDLE) break; - WinRTTimerInfo &info = d->timerInfos[timerId]; - Q_ASSERT(info.timerId != INVALID_TIMER_ID); + { + QMutexLocker locker(&d->timerInfoLock); - QCoreApplication::postEvent(this, new QTimerEvent(timerId)); + WinRTTimerInfo &info = d->timerInfos[timerId]; + Q_ASSERT(info.timerId != INVALID_TIMER_ID); - // Update timer's targetTime - const quint64 targetTime = qt_msectime() + info.interval; - info.targetTime = targetTime; + QCoreApplication::postEvent(this, new QTimerEvent(timerId)); + + // Update timer's targetTime + const quint64 targetTime = qt_msectime() + info.interval; + info.targetTime = targetTime; + } waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE); } emit awake(); @@ -487,6 +495,7 @@ QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTime } Q_D(const QEventDispatcherWinRT); + QMutexLocker locker(&d->timerInfoLock); QList<TimerInfo> timerInfos; for (const WinRTTimerInfo &info : d->timerInfos) { if (info.object == object && info.timerId != INVALID_TIMER_ID) @@ -518,6 +527,7 @@ int QEventDispatcherWinRT::remainingTime(int timerId) } Q_D(QEventDispatcherWinRT); + QMutexLocker locker(&d->timerInfoLock); const WinRTTimerInfo timerInfo = d->timerInfos.at(timerId); if (timerInfo.timerId == INVALID_TIMER_ID) { #ifndef QT_NO_DEBUG @@ -566,6 +576,9 @@ bool QEventDispatcherWinRT::event(QEvent *e) case QEvent::Timer: { QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e); const int id = timerEvent->timerId(); + + QMutexLocker locker(&d->timerInfoLock); + Q_ASSERT(id < d->timerInfos.size()); WinRTTimerInfo &info = d->timerInfos[id]; Q_ASSERT(info.timerId != INVALID_TIMER_ID); @@ -574,17 +587,17 @@ bool QEventDispatcherWinRT::event(QEvent *e) break; info.inEvent = true; + locker.unlock(); + QTimerEvent te(id); QCoreApplication::sendEvent(d->timerIdToObject.value(id), &te); + locker.relock(); + // The timer might have been removed in the meanwhile if (id >= d->timerInfos.size()) break; - info = d->timerInfos[id]; - if (info.timerId == INVALID_TIMER_ID) - break; - if (info.interval == 0 && info.inEvent) { // post the next zero timer event as long as the timer was not restarted QCoreApplication::postEvent(this, new QTimerEvent(id)); diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 1ffaeca852..af35193b13 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -886,7 +886,7 @@ inline void QXmlStreamReaderPrivate::reallocateStack() sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value))); Q_CHECK_PTR(sym_stack); state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int))); - Q_CHECK_PTR(sym_stack); + Q_CHECK_PTR(state_stack); } diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 17d77a07b5..324f13a17b 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -378,8 +378,6 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, QThemeIconInfo info; Q_ASSERT(!themeName.isEmpty()); - QPixmap pixmap; - // Used to protect against potential recursions visited << themeName; diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index 1085b546a7..085652879c 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -343,8 +343,10 @@ static const char scaleFactorProperty[] = "_q_scaleFactor"; */ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor) { - m_screenFactorSet = true; - m_active = true; + if (!qFuzzyCompare(factor, qreal(1))) { + m_screenFactorSet = true; + m_active = true; + } screen->setProperty(scaleFactorProperty, QVariant(factor)); // hack to force re-evaluation of screen geometry diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 57f70356b8..64bf55beee 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -266,7 +266,7 @@ public: static QOpenGLContextPrivate *get(QOpenGLContext *context) { - return context->d_func(); + return context ? context->d_func() : Q_NULLPTR; } #if !defined(QT_NO_DEBUG) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index edb65a2d4c..94a34b5c27 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2505,6 +2505,9 @@ void QWindowPrivate::_q_clearAlert() See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes. + If no cursor has been set, or after a call to unsetCursor(), the + parent window's cursor is used. + By default, the cursor has the Qt::ArrowCursor shape. Some underlying window implementations will reset the cursor if it diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h index c7a3e79666..cd44ddfe4d 100644 --- a/src/gui/opengl/qopengl.h +++ b/src/gui/opengl/qopengl.h @@ -95,8 +95,11 @@ typedef void* GLeglImageOES; // applications cannot target ES 3. Therefore QOpenGLFunctions and // friends do everything dynamically and never rely on these macros. +// Some Khronos headers use the ext proto guard in the standard headers as well, +// which is bad. Work it around, but avoid spilling over to the ext header. # ifndef GL_GLEXT_PROTOTYPES # define GL_GLEXT_PROTOTYPES +# define QGL_TEMP_GLEXT_PROTO # endif # if defined(QT_OPENGL_ES_3_1) @@ -107,6 +110,11 @@ typedef void* GLeglImageOES; # include <GLES2/gl2.h> #endif +# ifdef QGL_TEMP_GLEXT_PROTO +# undef GL_GLEXT_PROTOTYPES +# undef QGL_TEMP_GLEXT_PROTO +# endif + /* Some GLES2 implementations (like the one on Harmattan) are missing the typedef for GLchar. Work around it here by adding it. The Kkronos headers @@ -125,7 +133,15 @@ typedef char GLchar; # include <OpenGL/glext.h> # else # define GL_GLEXT_LEGACY // Prevents GL/gl.h from #including system glext.h -# include <GL/gl.h> +// Some Khronos headers use the ext proto guard in the standard headers as well, +// which is bad. Work it around, but avoid spilling over to the ext header. +# ifndef GL_GLEXT_PROTOTYPES +# define GL_GLEXT_PROTOTYPES +# include <GL/gl.h> +# undef GL_GLEXT_PROTOTYPES +# else +# include <GL/gl.h> +# endif # include <QtGui/qopenglext.h> # endif // Q_OS_MAC #endif // QT_OPENGL_ES_2 diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 4833617377..cedbe19191 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -950,6 +950,12 @@ QOpenGLFramebufferObject::~QOpenGLFramebufferObject() d->stencil_buffer_guard->free(); if (d->fbo_guard) d->fbo_guard->free(); + + QOpenGLContextPrivate *contextPrv = QOpenGLContextPrivate::get(QOpenGLContext::currentContext()); + if (contextPrv && contextPrv->qgl_current_fbo == this) { + contextPrv->qgl_current_fbo_invalid = true; + contextPrv->qgl_current_fbo = Q_NULLPTR; + } } /*! diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 07aec6f019..0d05fee6ef 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1766,6 +1766,10 @@ QTextBlock QTextDocument::lastBlock() const \property QTextDocument::pageSize \brief the page size that should be used for laying out the document + The units are determined by the underlying paint device. The size is + measured in logical pixels when painting to the screen, and in points + (1/72 inch) when painting to a printer. + By default, for a newly-created, empty document, this property contains an undefined size. diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 28a5eb6a89..540bbf5d54 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1905,11 +1905,15 @@ void QTextLine::layout_helper(int maxGlyphs) ++lbh.glyphCount; if (lbh.checkFullOtherwiseExtend(line)) goto found; - } else if (attributes[lbh.currentPosition].whiteSpace) { + } else if (attributes[lbh.currentPosition].whiteSpace + && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) { lbh.whiteSpaceOrObject = true; - while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace) + while (lbh.currentPosition < end + && attributes[lbh.currentPosition].whiteSpace + && eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) { addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount, current, lbh.logClusters, lbh.glyphs); + } if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) { lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line. diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index d547f829f8..3daca38959 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -662,10 +662,10 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) if (d->socketType != QAbstractSocket::TcpSocket) return -1; - QMutexLocker mutexLocker(&d->readMutex); // There will be a read notification when the socket was closed by the remote host. If that // happens and there isn't anything left in the buffer, we have to return -1 in order to signal // the closing of the socket. + QMutexLocker mutexLocker(&d->readMutex); if (d->readBytes.pos() == d->readBytes.size() && d->socketState != QAbstractSocket::ConnectedState) { close(); return -1; diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc index 241dff05da..f0ef5ee2a7 100644 --- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc +++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc @@ -86,6 +86,35 @@ */ /*! + \typedef QXcbWindowFunctions::SetWmWindowRole + \since 5.6.2 + + This is the typedef for the function returned by + QGuiApplication::platformFunction when passed the + value returned by setWmWindowRoleIdentifier(). +*/ + +/*! + \fn QByteArray QXcbWindowFunctions::setWmWindowRoleIdentifier() + \since 5.6.2 + + This function returns the byte array that can be used to query + QGuiApplication::platformFunction to retrieve the SetWmWindowRole function. +*/ + +/*! + \fn void QXcbWindowFunctions::setWmWindowRole(QWindow *window, const QByteArray &role) + \since 5.6.2 + + Sets the WM_WINDOW_ROLE property from \role on the corresponding + X11 window. + + This is a convenience function that can be used directly instead + of resolving the function pointer. \a window and \a role will be + relayed to the function retrieved by QGuiApplication. +*/ + +/*! \typedef QXcbWindowFunctions::SetWmWindowIconText This is the typedef for the function returned by diff --git a/src/platformsupport/eglconvenience/qt_egl_p.h b/src/platformsupport/eglconvenience/qt_egl_p.h index 615ee4b80a..b1495c9f9d 100644 --- a/src/platformsupport/eglconvenience/qt_egl_p.h +++ b/src/platformsupport/eglconvenience/qt_egl_p.h @@ -83,7 +83,7 @@ struct QtEglConverter<uint32_t, uintptr_t> { return v; } }; -#if Q_PROCESSOR_WORDSIZE > 4 +#if QT_POINTER_SIZE > 4 template <> struct QtEglConverter<uintptr_t, uint32_t> { diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index d92b87c6da..65bc494e91 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -117,7 +117,7 @@ static inline int stretchFromFcWidth(int fcwidth) return qtstretch; } -static const char *specialLanguages[] = { +static const char specialLanguages[][6] = { "", // Unknown "", // Inherited "", // Common @@ -251,12 +251,12 @@ static const char *specialLanguages[] = { "", // OldHungarian "" // SignWriting }; -Q_STATIC_ASSERT(sizeof(specialLanguages) / sizeof(const char *) == QChar::ScriptCount); +Q_STATIC_ASSERT(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount); // this could become a list of all languages used for each writing // system, instead of using the single most common language. -static const char *languageForWritingSystem[] = { - 0, // Any +static const char languageForWritingSystem[][6] = { + "", // Any "en", // Latin "el", // Greek "ru", // Cyrillic @@ -286,25 +286,25 @@ static const char *languageForWritingSystem[] = { "ja", // Japanese "ko", // Korean "vi", // Vietnamese - 0, // Symbol + "", // Symbol "sga", // Ogham "non", // Runic "man" // N'Ko }; -Q_STATIC_ASSERT(sizeof(languageForWritingSystem) / sizeof(const char *) == QFontDatabase::WritingSystemsCount); +Q_STATIC_ASSERT(sizeof languageForWritingSystem / sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount); #if FC_VERSION >= 20297 // Newer FontConfig let's us sort out fonts that report certain scripts support, // but no open type tables for handling them correctly. // Check the reported script presence in the FC_CAPABILITY's "otlayout:" section. -static const char *capabilityForWritingSystem[] = { - 0, // Any - 0, // Latin - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic +static const char capabilityForWritingSystem[][5] = { + "", // Any + "", // Latin + "", // Greek + "", // Cyrillic + "", // Armenian + "", // Hebrew + "", // Arabic "syrc", // Syriac "thaa", // Thaana "deva", // Devanagari @@ -317,20 +317,20 @@ static const char *capabilityForWritingSystem[] = { "knda", // Kannada "mlym", // Malayalam "sinh", // Sinhala - 0, // Thai - 0, // Lao + "", // Thai + "", // Lao "tibt", // Tibetan "mymr", // Myanmar - 0, // Georgian + "", // Georgian "khmr", // Khmer - 0, // SimplifiedChinese - 0, // TraditionalChinese - 0, // Japanese - 0, // Korean - 0, // Vietnamese - 0, // Symbol - 0, // Ogham - 0, // Runic + "", // SimplifiedChinese + "", // TraditionalChinese + "", // Japanese + "", // Korean + "", // Vietnamese + "", // Symbol + "", // Ogham + "", // Runic "nko " // N'Ko }; Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount); @@ -436,7 +436,7 @@ static void populateFromPattern(FcPattern *pattern) FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) { #if FC_VERSION >= 20297 - if (capabilityForWritingSystem[j] != Q_NULLPTR && requiresOpenType(j)) { + if (*capabilityForWritingSystem[j] && requiresOpenType(j)) { if (cap == Q_NULLPTR) capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0) diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 3a5a0c8e78..7f81e313cb 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -45,6 +45,7 @@ #include "qcocoacolordialoghelper.h" #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import <AppKit/AppKit.h> @@ -322,6 +323,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mColorPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 8e523dfbbf..3df2a7c962 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -62,7 +62,7 @@ QCocoaCursor::~QCocoaCursor() void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) { - NSCursor * cocoaCursor = convertCursor(cursor); + NSCursor *cocoaCursor = convertCursor(cursor); if (QPlatformWindow * platformWindow = window->handle()) static_cast<QCocoaWindow *>(platformWindow)->setWindowCursor(cocoaCursor); @@ -84,9 +84,12 @@ void QCocoaCursor::setPos(const QPoint &position) CFRelease(e); } -NSCursor *QCocoaCursor::convertCursor(QCursor * cursor) +NSCursor *QCocoaCursor::convertCursor(QCursor *cursor) { - const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (cursor == Q_NULLPTR) + return 0; + + const Qt::CursorShape newShape = cursor->shape(); NSCursor *cocoaCursor; // Check for a suitable built-in NSCursor first: diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 84880d51c5..70887c41c9 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -131,6 +131,8 @@ public: void interrupt(); void flush(); + static void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b2b9fe2c1e..72c7856c2d 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -965,6 +965,19 @@ void QCocoaEventDispatcher::interrupt() void QCocoaEventDispatcher::flush() { } +// QTBUG-56746: The behavior of processEvents() has been changed to not clear +// the interrupt flag. Use this function to clear it. + void QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher *cocoaEventDispatcher = + qobject_cast<QCocoaEventDispatcher *>(QThread::currentThread()->eventDispatcher()); + if (!cocoaEventDispatcher) + return; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = + static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher)); + cocoaEventDispatcherPrivate->interrupt = false; +} + QCocoaEventDispatcher::~QCocoaEventDispatcher() { Q_D(QCocoaEventDispatcher); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index ef102990b4..234da57f59 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -53,6 +53,7 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoamenubar.h" +#include "qcocoaeventdispatcher.h" #include <qregexp.h> #include <qbuffer.h> #include <qdebug.h> @@ -250,6 +251,10 @@ static QString strippedText(QString s) // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModal call below. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); mReturnCode = [mSavePanel runModal]; QCocoaMenuBar::resetKnownMenuItemsToQt(); diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 0be931b54f..791839d6ea 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -49,6 +49,7 @@ #include "qcocoafontdialoghelper.h" #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import <AppKit/AppKit.h> @@ -319,6 +320,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mFontPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 477165607c..26fbe3e4bc 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -100,6 +100,8 @@ private: */ Q_INVOKABLE QPixmap defaultBackgroundPixmapForQWizard(); + Q_INVOKABLE void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + // QMacPastebardMime support. The mac pasteboard void pointers are // QMacPastebardMime instances from the cocoa plugin or qtmacextras // These two classes are kept in sync and can be casted between. diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 10435d0b1d..972230349b 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -44,6 +44,7 @@ #include "qcocoahelpers.h" #include "qcocoaapplication.h" #include "qcocoaintegration.h" +#include "qcocoaeventdispatcher.h" #include <qbytearray.h> #include <qwindow.h> @@ -194,6 +195,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() return QPixmap(); } +void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); +} + void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) { Q_UNUSED(window); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 2e9de03dfc..16639fd8b1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -216,6 +216,8 @@ public: void setMenubar(QCocoaMenuBar *mb); QCocoaMenuBar *menubar() const; + NSCursor *effectiveWindowCursor() const; + void applyEffectiveWindowCursor(); void setWindowCursor(NSCursor *cursor); void registerTouch(bool enable); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index e377d8f83d..602da0a175 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1638,31 +1638,53 @@ QCocoaMenuBar *QCocoaWindow::menubar() const return m_menubar; } -void QCocoaWindow::setWindowCursor(NSCursor *cursor) +// Finds the effective cursor for this window by walking up the +// ancestor chain (including this window) until a set cursor is +// found. Returns nil if there is not set cursor. +NSCursor *QCocoaWindow::effectiveWindowCursor() const { - // This function is called (via QCocoaCursor) by Qt to set - // the cursor for this window. It can be called for a window - // that is not currenly under the mouse pointer (for example - // for a popup window.) Qt expects the set cursor to "stick": - // it should be accociated with the window until a different - // cursor is set. - if (m_windowCursor != cursor) { - [m_windowCursor release]; - m_windowCursor = [cursor retain]; - } - // Use the built in cursor rect API if the QCocoaWindow has a NSWindow. - // Othervise, set the cursor if this window is under the mouse. In - // this case QNSView::cursorUpdate will set the cursor as the pointer - // moves. - if (m_nsWindow && window()->type() != Qt::ForeignWindow) { - [m_nsWindow invalidateCursorRectsForView:m_view]; + if (m_windowCursor) + return m_windowCursor; + if (!QPlatformWindow::parent()) + return nil; + return static_cast<QCocoaWindow *>(QPlatformWindow::parent())->effectiveWindowCursor(); +} + +// Applies the cursor as returned by effectiveWindowCursor(), handles +// the special no-cursor-set case by setting the arrow cursor. +void QCocoaWindow::applyEffectiveWindowCursor() +{ + NSCursor *effectiveCursor = effectiveWindowCursor(); + if (effectiveCursor) { + [effectiveCursor set]; } else { - if (m_windowUnderMouse) - [cursor set]; + // We wold like to _unset_ the cursor here; but there is no such + // API. Fall back to setting the default arrow cursor. + [[NSCursor arrowCursor] set]; } } +void QCocoaWindow::setWindowCursor(NSCursor *cursor) +{ + if (m_windowCursor == cursor) + return; + + // Setting a cursor in a foregin view is not supported. + if (window()->type() == Qt::ForeignWindow) + return; + + [m_windowCursor release]; + m_windowCursor = cursor; + [m_windowCursor retain]; + + // The installed view tracking area (see QNSView updateTrackingAreas) will + // handle cursor updates on mouse enter/leave. Handle the case where the + // mouse is on the this window by changing the cursor immediately. + if (m_windowUnderMouse) + applyEffectiveWindowCursor(); +} + void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index abaff39e81..f226547b90 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -129,7 +129,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)mouseMovedImpl:(NSEvent *)theEvent; - (void)mouseEnteredImpl:(NSEvent *)theEvent; - (void)mouseExitedImpl:(NSEvent *)theEvent; -- (void)cursorUpdateImpl:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 6181997923..a63bc4d570 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -121,7 +121,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)cursorUpdate:(NSEvent *)theEvent { - [view cursorUpdateImpl:theEvent]; + [self cursorUpdate:theEvent]; } @end @@ -1053,21 +1053,10 @@ static bool _q_dontOverrideCtrlLMB = false; [self addTrackingArea:m_trackingArea]; } --(void)cursorUpdateImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - // Set the cursor manually if there is no NSWindow. - if (!m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [m_platformWindow->m_windowCursor set]; - else - [super cursorUpdate:theEvent]; -} - --(void)resetCursorRects +- (void)cursorUpdate:(NSEvent *)theEvent { - // Use the cursor rect API if there is a NSWindow - if (m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; + Q_UNUSED(theEvent); + m_platformWindow->applyEffectiveWindowCursor(); } - (void)mouseMovedImpl:(NSEvent *)theEvent @@ -1891,9 +1880,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) - (NSRange) selectedRange { - NSRange selectedRange = {NSNotFound, 0}; - selectedRange.location = NSNotFound; - selectedRange.length = 0; + NSRange selectedRange = {0, 0}; QObject *fo = QGuiApplication::focusObject(); if (!fo) diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 733f0bd139..7c88c73cc2 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -418,15 +418,17 @@ void QEglFSIntegration::createInputHandlers() } #endif -#if QT_CONFIG(evdev) - m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + bool useTslib = false; #if QT_CONFIG(tslib) - const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB"); + useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB"); if (useTslib) new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */); - else #endif + +#if QT_CONFIG(evdev) + m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + if (!useTslib) new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); #endif } diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index e8d216fbc2..eab6792266 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -628,7 +628,7 @@ - (id<UITextInputTokenizer>)tokenizer { - return [[[UITextInputStringTokenizer alloc] initWithTextInput:id<UITextInput>(self)] autorelease]; + return [[[UITextInputStringTokenizer alloc] initWithTextInput:self] autorelease]; } - (UITextPosition *)beginningOfDocument diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 893205177d..c1c235588e 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -147,15 +147,17 @@ void QLinuxFbIntegration::createInputHandlers() } #endif -#if QT_CONFIG(evdev) && !defined(Q_OS_ANDROID) - new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + bool useTslib = false; #if QT_CONFIG(tslib) - const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); + useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); if (useTslib) new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); - else #endif + +#if QT_CONFIG(evdev) && !defined(Q_OS_ANDROID) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + if (!useTslib) new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); #endif } diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index ce99718548..41b27debcc 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -40,6 +40,7 @@ #ifndef QWINRTBACKINGSTORE_H #define QWINRTBACKINGSTORE_H +#define GL_GLEXT_PROTOTYPES #include <qpa/qplatformbackingstore.h> #include <QtCore/QScopedPointer> #include <QtCore/QLoggingCategory> diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index dc720c090f..1f36a1ad2a 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -678,8 +678,11 @@ void QGLXContext::queryDummyContext() } QOpenGLContext context; - context.create(); - context.makeCurrent(surface.data()); + if (!context.create() || !context.makeCurrent(surface.data())) { + qWarning("QGLXContext: Failed to create dummy context"); + m_supportsThreading = false; + return; + } m_supportsThreading = true; diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index f9c32cd0a4..38e91cc9f6 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -729,8 +729,10 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve if (mode > QClipboard::Selection) return; - // here we care only about the xfixes events that come from non Qt processes - if (event->owner != XCB_NONE && event->owner != owner()) { + // Note1: Here we care only about the xfixes events that come from other processes. + // Note2: If the QClipboard::clear() is issued, event->owner is XCB_NONE, + // so we check selection_timestamp to not handle our own QClipboard::clear(). + if (event->owner != owner() && event->selection_timestamp > m_timestamp[mode]) { if (!m_xClipboard[mode]) { m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this)); } else { diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm index e3e7523a16..c29b911e35 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm +++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm @@ -133,6 +133,11 @@ void QMacPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) alloc] initWithNSPrintInfo:printInfo]; if (modality == Qt::ApplicationModal) { + + // Make sure we don't interrupt the runModalWithPrintInfo call. + (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(), + "clearCurrentThreadCocoaEventDispatcherInterruptFlag"); + int rval = [pageLayout runModalWithPrintInfo:printInfo]; [delegate pageLayoutDidEnd:pageLayout returnCode:rval contextInfo:q]; } else { diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index c16bb93013..c630ab634a 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -245,6 +245,11 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality) if (modality == Qt::ApplicationModal || !q->parentWidget()) { if (modality == Qt::NonModal) qWarning("QPrintDialog is required to be modal on OS X"); + + // Make sure we don't interrupt the runModalWithPrintInfo call. + (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(), + "clearCurrentThreadCocoaEventDispatcherInterruptFlag"); + int rval = [printPanel runModalWithPrintInfo:printInfo]; [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q]; } else { diff --git a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp index 18f8f2df8c..f2db73226b 100644 --- a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp +++ b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp @@ -137,11 +137,3 @@ setUpdatesEnabled(false); bigVisualChanges(); setUpdatesEnabled(true); //! [13] - - -//! [14] -... -extern void qt_x11_set_global_double_buffer(bool); -qt_x11_set_global_double_buffer(false); -... -//! [14] diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp index b884e93290..203cc8007c 100644 --- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -694,8 +694,7 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { Q_D(QGraphicsSceneBspTreeIndex); - switch (event->type()) { - case QEvent::Timer: + if (event->type() == QEvent::Timer) { if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) { if (d->restartIndexTimer) { d->restartIndexTimer = false; @@ -704,11 +703,8 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) d->_q_updateIndex(); } } - // Fallthrough intended - support timers in subclasses. - default: - return QObject::event(event); } - return true; + return QObject::event(event); } QT_END_NAMESPACE diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index d153915ae6..2adc58e4a4 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -1456,6 +1456,7 @@ bool QGraphicsWidget::event(QEvent *event) case QEvent::GraphicsSceneMousePress: if (d->hasDecoration() && windowFrameEvent(event)) return true; + break; case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: case QEvent::GraphicsSceneMouseDoubleClick: diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 8ca79bbb3c..ace50f13ee 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -9625,11 +9625,6 @@ void QWidget::leaveEvent(QEvent *) Since Qt 4.0, QWidget automatically double-buffers its painting, so there is no need to write double-buffering code in paintEvent() to avoid flicker. - \b{Note for the X11 platform}: It is possible to toggle global double - buffering by calling \c qt_x11_set_global_double_buffer(). For example, - - \snippet code/src_gui_kernel_qwidget.cpp 14 - \note Generally, you should refrain from calling update() or repaint() \b{inside} a paintEvent(). For example, calling update() or repaint() on children inside a paintevent() results in undefined behavior; the child may diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 583385ee8a..602421725f 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -49,6 +49,8 @@ #include "qstylehelper_p.h" #include <qstringbuilder.h> +#include <qdatastream.h> +#include <qcryptographichash.h> QT_BEGIN_NAMESPACE @@ -62,7 +64,6 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize & QString tmp = key % HexString<uint>(option->state) % HexString<uint>(option->direction) % HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u) - % HexString<quint64>(option->palette.cacheKey()) % HexString<uint>(size.width()) % HexString<uint>(size.height()); @@ -73,6 +74,25 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize & % QLatin1Char(spinBox->frame ? '1' : '0'); ; } #endif // QT_NO_SPINBOX + + // QTBUG-56743, try to create a palette cache key reflecting the value, + // as leaks may occur in conjunction with QStyleSheetStyle/QRenderRule modifying + // palettes when using QPalette::cacheKey() + if (option->palette != QGuiApplication::palette()) { + tmp.append(QLatin1Char('P')); +#ifndef QT_NO_DATASTREAM + QByteArray key; + key.reserve(5120); // Observed 5040B for a serialized palette on 64bit + { + QDataStream str(&key, QIODevice::WriteOnly); + str << option->palette; + } + const QByteArray sha1 = QCryptographicHash::hash(key, QCryptographicHash::Sha1).toHex(); + tmp.append(QString::fromLatin1(sha1)); +#else // QT_NO_DATASTREAM + tmp.append(QString::number(option->palette.cacheKey(), 16)); +#endif // !QT_NO_DATASTREAM + } return tmp; } diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index 76713d9880..fa0cff45c9 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -583,6 +583,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const #ifndef QT_NO_MOVIE } else if (movie && !movie->currentPixmap().isNull()) { br = movie->currentPixmap().rect(); + br.setSize(br.size() / movie->currentPixmap().devicePixelRatio()); #endif } else if (isTextLabel) { int align = QStyle::visualAlignment(textDirection(), QFlag(this->align)); |