diff options
author | Liang Qi <liang.qi@qt.io> | 2016-11-15 09:51:41 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-11-15 09:58:16 +0100 |
commit | 9808b53fde1dfc65ad3757cc6720e430c3cc89a2 (patch) | |
tree | a0517ae1e290e7bbdb118c9f01f4e6e5d744998c /src | |
parent | c214379156e4c75dcfe59cf73d69b912f4293303 (diff) | |
parent | 246fe271878dbe586b5f3222a78d67dfecd1ca83 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
configure
src/plugins/platforms/eglfs/qeglfsintegration.cpp
src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
Change-Id: Id2da7c775439adb62646d5b741ee7c638042b34b
Diffstat (limited to 'src')
42 files changed, 339 insertions, 150 deletions
diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp index 4b98ef076c..5286c4cc8e 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 8eeff01b59..b1b03601b2 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -310,12 +310,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(); @@ -384,11 +391,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(); @@ -590,7 +602,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; }; @@ -600,7 +612,7 @@ public: inline Value at(int i) const; inline Value &operator [](int i); - bool isValid() const; + bool isValid(int maxSize) const; }; @@ -655,12 +667,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); } @@ -686,6 +698,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; @@ -698,8 +719,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 2ffcf03eb2..607c523435 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> @@ -106,6 +107,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; @@ -122,6 +124,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; @@ -130,6 +133,7 @@ private: bool removeTimer(int id) { + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) return false; @@ -253,14 +257,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(); @@ -428,6 +436,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) @@ -459,6 +468,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 @@ -507,6 +517,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); @@ -515,17 +528,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 83b26d50ab..3c5bdfbfc0 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 0233ccbf87..3556f987b9 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -380,8 +380,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 fccd81f8e8..7ac876838d 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -342,8 +342,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 2fe8446c65..736f816bfe 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -264,7 +264,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 a20f4329b1..2dd5e884a4 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2502,6 +2502,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 5f9d78b780..bed5d0b371 100644 --- a/src/gui/opengl/qopengl.h +++ b/src/gui/opengl/qopengl.h @@ -95,6 +95,13 @@ 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) # include <GLES3/gl31.h> # elif defined(QT_OPENGL_ES_3) @@ -106,6 +113,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 @@ -126,7 +138,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 d9d4288ec8..9b07129303 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -955,6 +955,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 bb44c19557..3a751e64cc 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 3b1ee8ec03..b603ec7fc6 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1902,11 +1902,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 ce030086c3..c67bbef9dc 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -587,6 +587,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const if (d->socketType != QAbstractSocket::TcpSocket) return -1; + QMutexLocker locker(&d->readMutex); return d->readBytes.size() - d->readBytes.pos(); } @@ -599,12 +600,12 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) // 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; } - QMutexLocker mutexLocker(&d->readMutex); return d->readBytes.read(data, maxlen); } @@ -635,6 +636,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea PacketHeaderOptions) { Q_D(QNativeSocketEngine); + QMutexLocker locker(&d->readMutex); if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { if (header) header->clear(); @@ -654,6 +656,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea } else { readOrigin = datagram.data; } + locker.unlock(); memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length()))); return readOrigin.length(); } @@ -691,12 +694,14 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI bool QNativeSocketEngine::hasPendingDatagrams() const { Q_D(const QNativeSocketEngine); + QMutexLocker locker(&d->readMutex); return d->pendingDatagrams.length() > 0; } qint64 QNativeSocketEngine::pendingDatagramSize() const { Q_D(const QNativeSocketEngine); + QMutexLocker locker(&d->readMutex); if (d->pendingDatagrams.isEmpty()) return -1; @@ -1346,7 +1351,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async hr = byteArrayAccess->Buffer(&data); Q_ASSERT_SUCCEEDED(hr); - readMutex.lock(); + QMutexLocker locker(&readMutex); if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset readBytes.close(); if (!readBytes.isOpen()) @@ -1356,7 +1361,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async Q_ASSERT(readBytes.atEnd()); readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength)); readBytes.seek(readPos); - readMutex.unlock(); + locker.unlock(); if (notifyOnRead) emit q->readReady(); @@ -1420,7 +1425,9 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I datagram.data.resize(length); hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data())); RETURN_OK_IF_FAILED("Could not read datagram"); + QMutexLocker locker(&readMutex); pendingDatagrams.append(datagram); + locker.unlock(); if (notifyOnRead) emit q->readReady(); diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 5b76c2d223..822d1fd513 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -206,10 +206,18 @@ private: Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32>> readOp; + + // Protected by readMutex. Written in handleReadyRead (native callback) QBuffer readBytes; - QMutex readMutex; + // In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is + // pendingDatagrams. They are written inside native callbacks (handleReadyRead and + // handleNewDatagrams/putIntoPendingDatagramsList) + mutable QMutex readMutex; + + // Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList QList<WinRtDatagram> pendingDatagrams; + QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections; QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections; QEventLoop eventLoop; 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/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 591259ad70..d5cb02e291 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 cc18c372a7..f89c06fc58 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 0433084436..4870c521c7 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -61,7 +61,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); @@ -83,9 +83,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 5c27cf8059..d9c835d797 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -966,6 +966,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 4eb35f5495..c7191e4841 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> @@ -243,6 +244,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 2f4f80ad18..32c4077961 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 7065a364bf..b06fff1375 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 8562246817..a327750ffd 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 cc87e17d01..849ed858d1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -242,6 +242,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 524276e3a2..b3cbf9f599 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1663,31 +1663,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 && m_qtView) { - [m_nsWindow invalidateCursorRectsForView : m_qtView]; + if (m_windowCursor) + return m_windowCursor; + if (!parent()) + return nil; + return static_cast<QCocoaWindow *>(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 (!m_qtView) + 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 00d65ea7f8..c30ace35b4 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -131,7 +131,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 0e46c3150b..ba86b39e5b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -125,7 +125,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)cursorUpdate:(NSEvent *)theEvent { - [view cursorUpdateImpl:theEvent]; + [self cursorUpdate:theEvent]; } @end @@ -1071,21 +1071,10 @@ QT_WARNING_POP [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 @@ -1915,9 +1904,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/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 6f38a96f45..a4263c490e 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -418,15 +418,17 @@ void QEglFSIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID) - m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + bool useTslib = false; #ifndef QT_NO_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 // QT_NO_TSLIB +#endif + +#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID) + 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 e31584d581..009f3f8a20 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -625,7 +625,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 685f231756..2037f29a5a 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -147,15 +147,17 @@ void QLinuxFbIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID) - new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + bool useTslib = false; #ifndef QT_NO_TSLIB - const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); + useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); if (useTslib) new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); - else -#endif // QT_NO_TSLIB +#endif + +#if !defined(QT_NO_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/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 5580f81a7a..4c4176a063 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 e1ba3759e0..55c5203bb5 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 a2920a6a8b..09a89e4591 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -9631,11 +9631,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 f073f1cccb..754062ac26 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 5db1013fd2..20a4917567 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -585,6 +585,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)); |