From c0c75b3c2093976bab90dbf1566a02a1d10f2d33 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 28 Oct 2016 15:12:51 +0200 Subject: vcxproj generator: Support the /DEBUG:FASTLINK option of VS 2015 Make qmake understand the /DEBUG:FASTLINK option in QMAKE_LFLAGS, and write the corresponding value correctly to VS 2015 project files. Task-number: QTBUG-55591 Change-Id: I670375ed1523a5ab96bb3cce28635785564edba8 Reviewed-by: Oswald Buddenhagen Reviewed-by: Friedemann Kleint Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msbuild_objectmodel.cpp | 17 ++++++++++++++++- qmake/generators/win32/msvc_objectmodel.cpp | 4 +++- qmake/generators/win32/msvc_objectmodel.h | 5 +++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 9dbb33ba14..fec181e61f 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -1163,6 +1163,21 @@ static inline QString toString(subSystemOption option) return QString(); } +static inline QString toString(triState genDebugInfo, linkerDebugOption option) +{ + switch (genDebugInfo) { + case unset: + break; + case _False: + return "false"; + case _True: + if (option == linkerDebugOptionFastLink) + return "DebugFastLink"; + return "true"; + } + return QString(); +} + static inline QString toString(machineTypeOption option) { switch (option) { @@ -1541,7 +1556,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool) << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol) << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") << attrTagS(_FunctionOrder, tool.FunctionOrder) - << attrTagT(_GenerateDebugInformation, tool.GenerateDebugInformation) + << attrTagS(_GenerateDebugInformation, toString(tool.GenerateDebugInformation, tool.DebugInfoOption)) << attrTagT(_GenerateManifest, tool.GenerateManifest) << attrTagT(_GenerateWindowsMetadata, tool.GenerateWindowsMetadata) << attrTagS(_WindowsMetadataFile, tool.GenerateWindowsMetadata == _True ? tool.WindowsMetadataFile : QString()) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 7fd748e39c..82adc6814c 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -1430,8 +1430,10 @@ bool VCLinkerTool::parseOption(const char* option) }else EnableUAC = _True; break; - case 0x3389797: // /DEBUG + case 0x3389797: // /DEBUG[:FASTLINK] GenerateDebugInformation = _True; + if (config->CompilerVersion >= NET2015 && strcmp(option + 7, "FASTLINK") == 0) + DebugInfoOption = linkerDebugOptionFastLink; break; case 0x0033896: // /DEF:filename ModuleDefinitionFile = option+5; diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 7092da3e59..96923ba23d 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -282,6 +282,10 @@ enum inlineExpansionOption { expandAnySuitable, expandDefault // Not useful number, but stops the output }; +enum linkerDebugOption { + linkerDebugOptionNone, + linkerDebugOptionFastLink +}; enum linkIncrementalType { linkIncrementalDefault, linkIncrementalNo, @@ -595,6 +599,7 @@ public: QStringList ForceSymbolReferences; QString FunctionOrder; triState GenerateDebugInformation; + linkerDebugOption DebugInfoOption; triState GenerateMapFile; qlonglong HeapCommitSize; qlonglong HeapReserveSize; -- cgit v1.2.3 From 2f5b7157f5a601d9c439f97e56b238758f9672f2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 3 Nov 2016 18:11:01 +0100 Subject: remove dependencies from sync.profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the CI obtains them from the qt5 super repo nowadays. Change-Id: I146e6a74763f32bee6651f427dd3664a1236ea0e Reviewed-by: Jędrzej Nowacki --- sync.profile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sync.profile b/sync.profile index bba0ff2b2f..8f57593b00 100644 --- a/sync.profile +++ b/sync.profile @@ -58,11 +58,3 @@ my @zlib_headers = ( "zconf.h", "zlib.h" ); @ignore_for_include_check = ( "qsystemdetection.h", "qcompilerdetection.h", "qprocessordetection.h", @zlib_headers, @angle_headers); @ignore_for_qt_begin_namespace_check = ( "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qatomic_arch.h", "qatomic_windowsce.h", "qt_windows.h", "qatomic_macosx.h", @zlib_headers, @angle_headers); %inject_headers = ( "$basedir/src/corelib/global" => [ "qconfig.h", "qfeatures.h" ] ); -# Module dependencies. -# Every module that is required to build this module should have one entry. -# Each of the module version specifiers can take one of the following values: -# - A specific Git revision. -# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch) -# -%dependencies = ( -); -- cgit v1.2.3 From a07e77a99a916f5ee65511ffade0f087d72bf8bb Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 4 Nov 2016 11:07:54 +0100 Subject: iOS: fix 'incompatible pointer type' compiler warning Change-Id: I01bb7516a3600dd1dbd71dd6989f541494840abc Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiostextresponder.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 6224a6603c..3a888e2bd0 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -619,7 +619,7 @@ - (id)tokenizer { - return [[[UITextInputStringTokenizer alloc] initWithTextInput:id(self)] autorelease]; + return [[[UITextInputStringTokenizer alloc] initWithTextInput:self] autorelease]; } - (UITextPosition *)beginningOfDocument -- cgit v1.2.3 From c972c452e2ae2f38ce957eaac1761d8dff265f9b Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 2 Nov 2016 13:12:12 +0100 Subject: winrt: Proper guarding by readMutex Commented its purpose and the guarded members for readMutex. Fixed places where guarded members were accessed without using the mutex. Use QMutexLocker instead of manually (un-)locking the mutex. Task-number: QTBUG-44357 Change-Id: I3049bb0df30f00659dc284c8e30ad7503c11e7c6 Reviewed-by: David Faure --- src/network/socket/qnativesocketengine_winrt.cpp | 13 ++++++++++--- src/network/socket/qnativesocketengine_winrt_p.h | 10 +++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 920b8e2cb1..32fafc2cb0 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -580,6 +580,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const if (d->socketType != QAbstractSocket::TcpSocket) return -1; + QMutexLocker locker(&d->readMutex); return d->readBytes.size() - d->readBytes.pos(); } @@ -592,12 +593,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); } @@ -628,6 +629,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(); @@ -647,6 +649,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(); } @@ -684,12 +687,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; @@ -1336,7 +1341,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()) @@ -1346,7 +1351,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async Q_ASSERT(readBytes.atEnd()); readBytes.write(reinterpret_cast(data), qint64(bufferLength)); readBytes.seek(readPos); - readMutex.unlock(); + locker.unlock(); if (notifyOnRead) emit q->readReady(); @@ -1410,7 +1415,9 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I datagram.data.resize(length); hr = reader->ReadBytes(length, reinterpret_cast(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 c1fbcf70fa..654bb99d35 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -200,10 +200,18 @@ private: Microsoft::WRL::ComPtr tcpListener; Microsoft::WRL::ComPtr connectOp; Microsoft::WRL::ComPtr> 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 pendingDatagrams; + QList pendingConnections; QList currentConnections; QEventLoop eventLoop; -- cgit v1.2.3 From fe51dbac3d20ef9275dd1a9070f8185dc7705ad9 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 31 Oct 2016 12:57:38 +0100 Subject: winrt: Fix potential memory corruption The timerInfo list might get accessed concurrently and cause references to become dangling. Hence, we need to protect usages with a mutex. According to tests/benchmark there is no impact on performance. Task-number: QTBUG-56756 Change-Id: I4bdffccff70d2dca99f4a39defad438afe571ada Reviewed-by: Oliver Wolff --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 29 +++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index d115a3db2a..4a2e2d887f 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,7 @@ public: private: QHash timerIdToObject; QVector timerInfos; + mutable QMutex timerInfoLock; QHash timerHandleToId; QHash timerIdToHandle; QHash timerIdToCancelHandle; @@ -116,6 +118,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; @@ -124,6 +127,7 @@ private: bool removeTimer(int id) { + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) return false; @@ -247,14 +251,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(); @@ -421,6 +429,7 @@ QList QEventDispatcherWinRT::registeredTime } Q_D(const QEventDispatcherWinRT); + QMutexLocker locker(&d->timerInfoLock); QList timerInfos; foreach (const WinRTTimerInfo &info, d->timerInfos) { if (info.object == object && info.timerId != INVALID_TIMER_ID) @@ -452,6 +461,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 @@ -500,6 +510,9 @@ bool QEventDispatcherWinRT::event(QEvent *e) case QEvent::Timer: { QTimerEvent *timerEvent = static_cast(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); @@ -508,9 +521,13 @@ 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; -- cgit v1.2.3 From ffe72840a34ed7c99294f29f85828c5d5fad728f Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 1 Nov 2016 13:10:35 +0100 Subject: Only turn off font hinting when scale is != 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KDE will set the screen scale factors to 1 by default. Make sure we don't turn off font hinting in that case. Task-number: QTBUG-56797 Change-Id: Ieab18a7cfe4c1cb7087caab4d881932a4a991bc8 Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qhighdpiscaling.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index 6846196719..a94ad1e00a 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -332,8 +332,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 -- cgit v1.2.3 From ae8d3d69d68e7f3da1b0f524e12496387aff26ec Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 1 Nov 2016 15:28:17 -0700 Subject: macOS: Clear event dispatcher interrupt state A pending interrupt of a QEventLoop may interfere with native runModal calls, resulting in Cocoa's main event loop to be stopped unexpectedly. After commit 9ab60b9c processEvents() no longer resets the event dispatcher interrupt flag. Add QCocoaEventDispatcher::clearCurrentThreadCocoa EventDispatcherInterruptFlag(). Use it to clear the interrupt state before calling runModal and variants. Work around the inability to use platform API in the print support code. Change-Id: I52f26f99a63cbb46969db42f65b09a3c3119ad15 Task-number: QTBUG-56746 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 2 ++ src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 13 +++++++++++++ src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoanativeinterface.h | 2 ++ src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 6 ++++++ src/printsupport/dialogs/qpagesetupdialog_mac.mm | 5 +++++ src/printsupport/dialogs/qprintdialog_mac.mm | 5 +++++ 9 files changed, 48 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 3c924bec94..474e2cdb19 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -39,6 +39,7 @@ #include #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import @@ -318,6 +319,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/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 8a2a478a72..569dd3b028 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -125,6 +125,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 1cfb3ecff9..09a0e14950 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -960,6 +960,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(QThread::currentThread()->eventDispatcher()); + if (!cocoaEventDispatcher) + return; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = + static_cast(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 4c1b190b9c..71748ae77f 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -45,6 +45,7 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoamenubar.h" +#include "qcocoaeventdispatcher.h" #include #include #include @@ -235,6 +236,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 5b27dc1da9..eb800afd47 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -43,6 +43,7 @@ #include #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import @@ -313,6 +314,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 d018c05635..d6786b9274 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -96,6 +96,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 baee451903..8534c1c6fb 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -38,6 +38,7 @@ #include "qcocoahelpers.h" #include "qcocoaapplication.h" #include "qcocoaintegration.h" +#include "qcocoaeventdispatcher.h" #include #include @@ -193,6 +194,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() return QPixmap(); } +void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); +} + void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) { Q_UNUSED(window); diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm index b86de31883..9c86c5a90e 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm +++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm @@ -127,6 +127,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 030526954d..964b20dac5 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -239,6 +239,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 { -- cgit v1.2.3 From 8f2eb9b43c23b03918c50fa721a47f3ab99e4ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 27 Oct 2016 09:57:54 +0200 Subject: Prevent stale QOpenGLContext fbo pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is logic for clearing the qgl_curent_fbo pointer in release(), but it is not always called, causing the pointer to become stale on QOpenGLFramebufferObject deletion. As a last resort, clear the qgl_curent_fbo pointer on the current context if it’s pointing to the object that is being deleted. Change-Id: I36cca511da295412332193524219e32607ef8261 Task-number: QTBUG-56639 Reviewed-by: Laszlo Agocs Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qopenglcontext_p.h | 2 +- src/gui/opengl/qopenglframebufferobject.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 7c8c698a7d..113b789512 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -258,7 +258,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/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index b1b580f85b..b5fa6b9785 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -949,6 +949,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; + } } /*! -- cgit v1.2.3 From 356f5bbac3a66701e958896f8075bbacc90439df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 25 Oct 2016 08:14:21 +0200 Subject: Cocoa: Make child window cursors work correctly The existing cursor logic had a couple of issues: - It made the faulty assumption that we could not use the NSWindow invalidateCursorRectsForView API for child NSViews. - It used NSWindow invalidateCursorRectsForView and NSView resetCursorRects. This API has been replaced by the more general NSTrackingArea API. - It did not implement falling back to the parent window cursor if the current window has no cursor set. Document that QWindow cursors work the same way as QWidget cursors in that a QWindow with no set cursor will fall back to the parent window cursor. Change the cocoa platform code to use NSTrackingArea exclusively and implement NSView cursorUpdate which sets the cursor. Handle immediate change on QWindow:: setCursor() manually. Add QWindow::effectiveWindowCursor() and applyEffectiveWindowCursor() which finds the correct window cursor. Add a manual test for the child window, child widget, and QWidget::createWindowChild cases. Task-number: QTBUG-33479 Task-number: QTBUG-52023 Change-Id: I0370e11bbadb2da95e8632e61be6228ec2cd5e9d Reviewed-by: Timur Pocheptsov --- src/gui/kernel/qwindow.cpp | 3 + src/plugins/platforms/cocoa/qcocoacursor.mm | 9 +- src/plugins/platforms/cocoa/qcocoawindow.h | 2 + src/plugins/platforms/cocoa/qcocoawindow.mm | 60 ++++++--- src/plugins/platforms/cocoa/qnsview.h | 1 - src/plugins/platforms/cocoa/qnsview.mm | 19 +-- tests/manual/qcursor/childwidget/childwidget.pro | 6 + tests/manual/qcursor/childwidget/main.cpp | 92 ++++++++++++++ tests/manual/qcursor/childwindow/childwindow.pro | 5 + tests/manual/qcursor/childwindow/main.cpp | 91 ++++++++++++++ .../childwindowcontainer/childwindowcontainer.pro | 6 + tests/manual/qcursor/childwindowcontainer/main.cpp | 138 +++++++++++++++++++++ tests/manual/qcursor/qcursor.pro | 2 +- 13 files changed, 395 insertions(+), 39 deletions(-) create mode 100644 tests/manual/qcursor/childwidget/childwidget.pro create mode 100644 tests/manual/qcursor/childwidget/main.cpp create mode 100644 tests/manual/qcursor/childwindow/childwindow.pro create mode 100644 tests/manual/qcursor/childwindow/main.cpp create mode 100644 tests/manual/qcursor/childwindowcontainer/childwindowcontainer.pro create mode 100644 tests/manual/qcursor/childwindowcontainer/main.cpp diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 2ff19f5175..c7ad10a46f 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2462,6 +2462,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/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 8e38181c29..a4c291c14a 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -55,7 +55,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(platformWindow)->setWindowCursor(cocoaCursor); @@ -77,9 +77,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/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 9cf6328281..bf28f83540 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -236,6 +236,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 977a5ae657..a18d93b89e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1645,31 +1645,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(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 2d4ad7aad3..9d2b54a321 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -118,7 +118,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 c67bcfd23b..1ad9b5f327 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -120,7 +120,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)cursorUpdate:(NSEvent *)theEvent { - [view cursorUpdateImpl:theEvent]; + [self cursorUpdate:theEvent]; } @end @@ -924,21 +924,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 diff --git a/tests/manual/qcursor/childwidget/childwidget.pro b/tests/manual/qcursor/childwidget/childwidget.pro new file mode 100644 index 0000000000..9ca41c5b4f --- /dev/null +++ b/tests/manual/qcursor/childwidget/childwidget.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = childwidget +INCLUDEPATH += . +QT += widgets + +SOURCES += main.cpp diff --git a/tests/manual/qcursor/childwidget/main.cpp b/tests/manual/qcursor/childwidget/main.cpp new file mode 100644 index 0000000000..4447c87210 --- /dev/null +++ b/tests/manual/qcursor/childwidget/main.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +class CursorWidget : public QWidget +{ +public: + CursorWidget(QCursor cursor, QColor color) + :m_cursor(cursor) + ,m_color(color) + { + if (cursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(cursor); + } + + void paintEvent(QPaintEvent *e) + { + QPainter p(this); + p.fillRect(e->rect(), m_color); + } + + void mousePressEvent(QMouseEvent *) + { + // Toggle cursor + QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor; + if (newCursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(newCursor); + } + +private: + QCursor m_cursor; + QColor m_color; +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + // Test child widgets (one of which is native) with set cursors. + // Click window to toggle cursor. + + CursorWidget w1((QCursor(Qt::SizeVerCursor)), QColor(Qt::blue).darker()); + w1.resize(200, 200); + w1.show(); + + CursorWidget w2((QCursor(Qt::OpenHandCursor)), QColor(Qt::red).darker()); + w2.setParent(&w1); + w2.setGeometry(0, 0, 100, 100); + w2.show(); + + CursorWidget w3((QCursor(Qt::IBeamCursor)), QColor(Qt::green).darker()); + w3.winId(); + w3.setParent(&w1); + w3.setGeometry(100, 100, 100, 100); + w3.show(); + + return app.exec(); +} diff --git a/tests/manual/qcursor/childwindow/childwindow.pro b/tests/manual/qcursor/childwindow/childwindow.pro new file mode 100644 index 0000000000..194536a91a --- /dev/null +++ b/tests/manual/qcursor/childwindow/childwindow.pro @@ -0,0 +1,5 @@ +TEMPLATE = app +TARGET = childwindow +INCLUDEPATH += . + +SOURCES += main.cpp diff --git a/tests/manual/qcursor/childwindow/main.cpp b/tests/manual/qcursor/childwindow/main.cpp new file mode 100644 index 0000000000..5fc293dfcf --- /dev/null +++ b/tests/manual/qcursor/childwindow/main.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +class CursorWindow : public QRasterWindow +{ +public: + CursorWindow(QCursor cursor, QColor color) + :m_cursor(cursor) + ,m_color(color) + { + if (cursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(cursor); + } + + void paintEvent(QPaintEvent *e) + { + QPainter p(this); + p.fillRect(e->rect(), m_color); + } + + void mousePressEvent(QMouseEvent *) + { + // Toggle cursor + QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor; + if (newCursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(newCursor); + } + +private: + QCursor m_cursor; + QColor m_color; +}; + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + // Test child windows with set cursors. Create parent window and + // two child windows. Click window to toggle cursor. + + CursorWindow w1((QCursor(Qt::SizeVerCursor)), QColor(Qt::blue).darker()); + w1.resize(200, 200); + w1.show(); + + CursorWindow w2((QCursor(Qt::OpenHandCursor)), QColor(Qt::red).darker()); + w2.setParent(&w1); + w2.setGeometry(0, 0, 100, 100); + w2.show(); + + CursorWindow w3((QCursor(Qt::IBeamCursor)), QColor(Qt::green).darker()); + w3.setParent(&w1); + w3.setGeometry(100, 100, 100, 100); + w3.show(); + + return app.exec(); +} diff --git a/tests/manual/qcursor/childwindowcontainer/childwindowcontainer.pro b/tests/manual/qcursor/childwindowcontainer/childwindowcontainer.pro new file mode 100644 index 0000000000..2233ce4a63 --- /dev/null +++ b/tests/manual/qcursor/childwindowcontainer/childwindowcontainer.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = childwindowcontainer +INCLUDEPATH += . +QT += widgets + +SOURCES += main.cpp diff --git a/tests/manual/qcursor/childwindowcontainer/main.cpp b/tests/manual/qcursor/childwindowcontainer/main.cpp new file mode 100644 index 0000000000..d440133a42 --- /dev/null +++ b/tests/manual/qcursor/childwindowcontainer/main.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +class CursorWindow : public QRasterWindow +{ +public: + CursorWindow(QCursor cursor, QColor color) + :m_cursor(cursor) + ,m_color(color) + { + if (cursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(cursor); + } + + void paintEvent(QPaintEvent *e) + { + QPainter p(this); + p.fillRect(e->rect(), m_color); + } + + void mousePressEvent(QMouseEvent *) + { + // Toggle cursor + QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor; + if (newCursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(newCursor); + } + +private: + QCursor m_cursor; + QColor m_color; +}; + +class CursorWidget : public QWidget +{ +public: + CursorWidget(QCursor cursor, QColor color) + :m_cursor(cursor) + ,m_color(color) + { + if (cursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(cursor); + } + + void paintEvent(QPaintEvent *e) + { + QPainter p(this); + p.fillRect(e->rect(), m_color); + } + + void mousePressEvent(QMouseEvent *) + { + // Toggle cursor + QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor; + if (newCursor.shape() == Qt::ArrowCursor) + unsetCursor(); + else + setCursor(newCursor); + } + +private: + QCursor m_cursor; + QColor m_color; +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + { + // Create top-level windowContainer with window. Setting the cursor + // for the container should set the cursor for the window as well. + // Setting the cursor for the window overrides the cursor for the + // container. The example starts out with a window cursor; click + // to fall back to the container cursor. + CursorWindow *w1 = new CursorWindow(QCursor(Qt::OpenHandCursor), QColor(Qt::red).darker()); + QWidget* container = QWidget::createWindowContainer(w1); + container->resize(200, 200); + container->setCursor(Qt::PointingHandCursor); + container->show(); + } + + { + // Similar to above, but with a top-level QWiget + CursorWidget *w1 = new CursorWidget(QCursor(Qt::IBeamCursor), QColor(Qt::green).darker()); + w1->resize(200, 200); + + CursorWindow *w2 = new CursorWindow(QCursor(Qt::OpenHandCursor), QColor(Qt::red).darker()); + QWidget* container = QWidget::createWindowContainer(w2); + container->winId(); // must make the container native, otherwise setCursor + // sets the cursor on a QWindowContainerClassWindow which + // is outside the QWindow hierarchy (macOS). + container->setParent(w1); + container->setCursor(Qt::PointingHandCursor); + container->setGeometry(0, 0, 100, 100); + + w1->show(); + } + + return app.exec(); +} diff --git a/tests/manual/qcursor/qcursor.pro b/tests/manual/qcursor/qcursor.pro index 0b5c2b1945..c6617b8e89 100644 --- a/tests/manual/qcursor/qcursor.pro +++ b/tests/manual/qcursor/qcursor.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = allcursors grab_override qcursorhighdpi +SUBDIRS = allcursors childwidget childwindow childwindowcontainer grab_override qcursorhighdpi -- cgit v1.2.3 From d7bcdc3a442b99c2caebd4cfd38de67e14090e05 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 2 Nov 2016 16:45:41 +0100 Subject: QStyleHelper::uniqueName(): Improve palette pixmap cache key Use QDataStream to obtain cache key for a palettes that are different from the default QPalette. This results in unique keys for palettes created from QStyleSheetStyle's render rules. Task-number: QTBUG-56743 Change-Id: Icbfe165f705ef3e1c9e88cfc9dca88ff1d1e81e6 Reviewed-by: Andy Shaw --- src/widgets/styles/qstylehelper.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 6602b58a9d..960695e9df 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -43,6 +43,8 @@ #include "qstylehelper_p.h" #include +#include +#include QT_BEGIN_NAMESPACE @@ -56,7 +58,6 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize & QString tmp = key % HexString(option->state) % HexString(option->direction) % HexString(complexOption ? uint(complexOption->activeSubControls) : 0u) - % HexString(option->palette.cacheKey()) % HexString(size.width()) % HexString(size.height()); @@ -67,6 +68,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; } -- cgit v1.2.3 From 92805a0e9c488e47280e93f65e5378818e340ad1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 7 Nov 2016 11:23:21 +0100 Subject: Fix EGL break on Debian X32 Change to QT_POINTER_SIZE instead of Q_PROCESSOR_WORDSIZE. The latter is 8 due to targeting 64-bit, but pointers are 32-bit still in such builds. For the condition in question it is the pointer size that matters. Task-number: QTBUG-56686 Change-Id: I96c203cae91ceb8404606de605c4fdb1a02a9d5f Reviewed-by: Dmitry Shachnev Reviewed-by: Thiago Macieira --- src/platformsupport/eglconvenience/qt_egl_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { return v; } }; -#if Q_PROCESSOR_WORDSIZE > 4 +#if QT_POINTER_SIZE > 4 template <> struct QtEglConverter { -- cgit v1.2.3 From e25f2392eb4a208449c3aa53196c81583dba08dc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 11 Oct 2016 00:43:29 +0200 Subject: QGraphicsWidget: add missing break statement to switch in event() If the QEvent::GraphicsSceneMousePress case falls through, it does so because d->hasDecoration() == false or the virtual call to windowFrameEvent() returned false. It falls through to the case for QEvent::GraphicsSceneMouseMove, etc, which ensures d->windowData and then checks hasDecoration() again, with some other conditions on top, and calls the same virtual function, windowFrameEvent(), with the same arguments again. Now, it could, theoretically, be possible that that second call would, due to the presence of a windowData that wasn't there before, return true when before it did return false. But the only modification to *this between the calls to windowFrameEvent() is the potential allocation of d->windowData, which, if actually effected, will have d->windowData->grabbedSection == Qt::NoSection, hence windowFrameEvent() won't even be called a second time It is therefore safe to assume that a break was intended here, so add it. Discovered independently be GCC 7 and Coverity. Coverity-Id: 11149 Change-Id: Id708a1689ed0f0c914622e388c456ea4576fda02 Reviewed-by: Edward Welbourne --- src/widgets/graphicsview/qgraphicswidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index 125174627d..5a4f96a2aa 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -1449,6 +1449,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: -- cgit v1.2.3 From ef36fd02178482cd312ea551303856ef563421af Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 8 Oct 2016 16:41:46 +0200 Subject: QGraphicsSceneBspTreeIndex: fix misleading code in event() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code employed a switch statement to filter timer events, but fell unconditionally through to the default case of calling QObject::event(). The final return statement following the switch is thus dead code. Fix by turning the switch into an if and returning QObject::event() unconditionally afterwards, which much better describes the intent of the code, and also fixes the GCC 7 warning about implicit fall- through in the switch (which wasn't implicit to a human, but GCC's comment-reading-capabilities are somewhat limited at this point). Change-Id: I6756a65b3679a446d09fd721dfd0adc24fdf7772 Reviewed-by: Sérgio Martins Reviewed-by: Edward Welbourne --- src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp index ce43b1332d..9916591ffa 100644 --- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -691,8 +691,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(event)->timerId() == d->indexTimerId) { if (d->restartIndexTimer) { d->restartIndexTimer = false; @@ -701,11 +700,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 -- cgit v1.2.3 From b559b5646359e6fd9c208c29b7524352784e6177 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 10 Oct 2016 20:27:36 +0200 Subject: QFontconfigDatabase: remove 200 unneeded relocations Same change as in QColor (d38f86e50b01c6dd60f5a97355031e08d6a47d18). No text and data reduction numbers (ubsan build). Change-Id: I7280a511e785c9442a3a6a1ed55e10011ce0a84e Reviewed-by: Edward Welbourne --- .../fontconfig/qfontconfigdatabase.cpp | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 1c2c3288a0..71236227de 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -110,7 +110,7 @@ static inline int stretchFromFcWidth(int fcwidth) return qtstretch; } -static const char *specialLanguages[] = { +static const char specialLanguages[][6] = { "", // Unknown "", // Inherited "", // Common @@ -244,12 +244,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 @@ -279,25 +279,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 @@ -310,20 +310,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); @@ -425,7 +425,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(cap), capabilityForWritingSystem[j]) == 0) -- cgit v1.2.3 From 0383d0be33c7ede2104b7225c9af13104cbef85d Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Nov 2016 07:50:14 +0100 Subject: winrt: Do not copy into a reference The intention has probably been to reset a reference, which is not required. Task-number: QTBUG-56756 Change-Id: I1ef44b6c9b8365ac5c8d48234137e518558e9398 Reviewed-by: Oliver Wolff --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index 4a2e2d887f..8d4fbfd8e4 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -532,7 +532,6 @@ bool QEventDispatcherWinRT::event(QEvent *e) if (id >= d->timerInfos.size()) break; - info = d->timerInfos[id]; if (info.timerId == INVALID_TIMER_ID) break; -- cgit v1.2.3 From c83ba01f7bc542368973f3f24dfb59c6052dd78a Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Nov 2016 07:51:25 +0100 Subject: winrt: remove superfluous code We do not need to check for an invalid timer id, as this can only happen if the above check is already true. Hence, this was doing the same check twice. Task-number: QTBUG-56756 Change-Id: Icca9b26c32ce88eab76dd02c6c10b24af07bfad7 Reviewed-by: Oliver Wolff --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index 8d4fbfd8e4..6126ff0e5d 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -532,9 +532,6 @@ bool QEventDispatcherWinRT::event(QEvent *e) if (id >= d->timerInfos.size()) break; - 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)); -- cgit v1.2.3 From 9de3b15d07dcf1be5ff7b26e2e7987ed8e91a0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= Date: Mon, 7 Nov 2016 09:40:34 +0100 Subject: QLabel: take DPR of QMovie in account when calculating sizeHint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QLabel already does that for QPixmap, so just do the same for QMovie's current pixmap. Task-number: QTBUG-48157 Change-Id: I7b26460f778e56ff017a5efd433f8929f30e4b41 Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig --- src/widgets/widgets/qlabel.cpp | 1 + tests/auto/widgets/widgets/qlabel/red@2x.png | Bin 0 -> 105 bytes tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp | 24 +++++++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/auto/widgets/widgets/qlabel/red@2x.png diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index a07a964595..34b75cb550 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -579,6 +579,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)); diff --git a/tests/auto/widgets/widgets/qlabel/red@2x.png b/tests/auto/widgets/widgets/qlabel/red@2x.png new file mode 100644 index 0000000000..4a843e744f Binary files /dev/null and b/tests/auto/widgets/widgets/qlabel/red@2x.png differ diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp index d76dbf6b46..2b2756fef3 100644 --- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp +++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp @@ -101,6 +101,9 @@ private Q_SLOTS: void taskQTBUG_7902_contextMenuCrash(); #endif + void taskQTBUG_48157_dprPixmap(); + void taskQTBUG_48157_dprMovie(); + private: QLabel *testWidget; QPointer test_box; @@ -546,5 +549,26 @@ void tst_QLabel::taskQTBUG_7902_contextMenuCrash() } #endif +void tst_QLabel::taskQTBUG_48157_dprPixmap() +{ + QLabel label; + QPixmap pixmap; + pixmap.load(QFINDTESTDATA(QStringLiteral("red@2x.png"))); + QCOMPARE(pixmap.devicePixelRatio(), 2.0); + label.setPixmap(pixmap); + QCOMPARE(label.sizeHint(), pixmap.rect().size() / pixmap.devicePixelRatio()); +} + +void tst_QLabel::taskQTBUG_48157_dprMovie() +{ + QLabel label; + QMovie movie; + movie.setFileName(QFINDTESTDATA(QStringLiteral("red@2x.png"))); + movie.start(); + QCOMPARE(movie.currentPixmap().devicePixelRatio(), 2.0); + label.setMovie(&movie); + QCOMPARE(label.sizeHint(), movie.currentPixmap().size() / movie.currentPixmap().devicePixelRatio()); +} + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" -- cgit v1.2.3 From a160fd52a1e121dfb237bfcddc305caa896df7dc Mon Sep 17 00:00:00 2001 From: Steve Schilz Date: Fri, 6 May 2016 09:31:03 -0700 Subject: Documentation: Specify units for QTextDocument::pageSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parameter in setPageSize is QSizeF. Without a specified unit it is hard to know what to use as input. Units depend upon the underlying paint device Change-Id: If001b3e9587d6085cc18017680fa20396e936adb Reviewed-by: Edward Welbourne Reviewed-by: Topi Reiniö Reviewed-by: Nico Vertriest Reviewed-by: Steve Schilz --- src/gui/text/qtextdocument.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 6cccf417c7..baadc068d5 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1760,6 +1760,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. -- cgit v1.2.3 From 8ee65cd1f25d8a78b6cdba3e6ab6fa031468693c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 7 Nov 2016 12:29:12 +0100 Subject: Correct a Q_CHECK_PTR()'s parameter Someone cut-and-pasted but forgot one of the changes. Change-Id: I647dc8117ebfe8ce3d4b26d468b80c15d4e533e8 Reviewed-by: Thiago Macieira --- src/corelib/xml/qxmlstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index ef7d454dca..6ad06eaed6 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -880,7 +880,7 @@ inline void QXmlStreamReaderPrivate::reallocateStack() sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); Q_CHECK_PTR(sym_stack); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); - Q_CHECK_PTR(sym_stack); + Q_CHECK_PTR(state_stack); } -- cgit v1.2.3 From 15414257b3719f2c302cca26efe40f2b3caa115b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 4 Nov 2016 15:52:32 +0100 Subject: Don't count no-break spaces as trailing spaces No-break-spaces should not be counted in the space data, but rather be treated as any other non-breakable character. We were already taking care of this in the loop we reach if the item starts with a character which isn't whitespace, but there is a second loop for items that begin with whitespace characters. The result of this was that in certain circumstances where you gave the nbsp its own format and made the line wrap, the previous line would count an extra trailing space and it would swallow the first character in its following line. [ChangeLog][QtGui][Text] Fixed a bug where a no-break space would sometimes cause the first character of the containing line to not be displayed. Task-number: QTBUG-56714 Change-Id: Idd760a389052e6de70f6cc397122b217987fa5f2 Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 8 +++-- .../auto/gui/text/qtextlayout/tst_qtextlayout.cpp | 37 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index aca475a581..ac2895aeb3 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1896,11 +1896,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/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 84d58191c0..22a4276b8e 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -142,6 +142,7 @@ private slots: void xToCursorForLigatures(); void cursorInNonStopChars(); void nbsp(); + void nbspWithFormat(); void noModificationOfInputString(); void superscriptCrash_qtbug53911(); @@ -2266,5 +2267,41 @@ void tst_QTextLayout::superscriptCrash_qtbug53911() qDeleteAll(textLayouts); } +void tst_QTextLayout::nbspWithFormat() +{ + QString s1 = QLatin1String("ABCDEF "); + QString s2 = QLatin1String("GHI"); + QChar nbsp(QChar::Nbsp); + QString s3 = QLatin1String("JKLMNOPQRSTUVWXYZ"); + + QTextLayout layout; + layout.setText(s1 + s2 + nbsp + s3); + + QTextLayout::FormatRange formatRange; + formatRange.start = s1.length() + s2.length(); + formatRange.length = 1; + formatRange.format.setFontUnderline(true); + + QList overrides; + overrides.append(formatRange); + + layout.setAdditionalFormats(overrides); + + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(1); + } + layout.endLayout(); + + QCOMPARE(layout.lineCount(), 2); + QCOMPARE(layout.lineAt(0).textStart(), 0); + QCOMPARE(layout.lineAt(0).textLength(), s1.length()); + QCOMPARE(layout.lineAt(1).textStart(), s1.length()); + QCOMPARE(layout.lineAt(1).textLength(), s2.length() + 1 + s3.length()); +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" -- cgit v1.2.3 From 5fcda458721c85f7b4209f418b416ffa5c93936e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 8 Nov 2016 21:45:07 +0100 Subject: Do not guard tslib with evdev That relation is incorrect. We can have tslib support without evdev. Task-number: QTBUG-54998 Change-Id: I2c09bad73210fa4a13000077480c70365d482e2e Reviewed-by: Eirik Aavitsland --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 14 ++++++++------ src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index c226c0134a..bb62506f33 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -406,15 +406,17 @@ void QEglFSIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) - 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) || defined(Q_OS_ANDROID_NO_SDK)) + 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/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 8c8c8a15ea..3cc0e735ad 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -141,15 +141,17 @@ void QLinuxFbIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) - 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) || defined(Q_OS_ANDROID_NO_SDK)) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + if (!useTslib) new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); #endif } -- cgit v1.2.3 From e8364f9a4b481207ba6822827e143fb31eccfe51 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 27 Oct 2016 11:38:57 +0200 Subject: Enable GL prototypes with recent Khronos headers Recent Khronos headers decided to break the world by guarding all function prototypes with GL_GLEXT_PROTOTYPES which has traditionally been used for extension headers only. Until this gets corrected - see https://lists.freedesktop.org/archives/mesa-dev/2016-September/128654.html - add the define to the config tests and qopengl.h. While 5.7 already has some of the qopengl.h fixes due to an upgraded ANGLE shipping with newer headers, this is a cross-platform issue that will surface everywhere eventually. Therefore we target the full set of fixes to 5.6. This time we also make sure the forced define of GL_GLEXT_PROTOTYPES is removed before including the ext header, thus apps get the ext protos only if they actually requested them. Task-number: QTBUG-56764 Change-Id: Ib2c6d2e7b71b8fb8683424f43e6289e64e4ee46c Reviewed-by: Oliver Wolff Reviewed-by: Andy Nichols --- config.tests/unix/opengldesktop/opengldesktop.cpp | 1 + config.tests/unix/opengles2/opengles2.cpp | 1 + config.tests/unix/opengles3/opengles3.cpp | 1 + src/gui/opengl/qopengl.h | 22 +++++++++++++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/config.tests/unix/opengldesktop/opengldesktop.cpp b/config.tests/unix/opengldesktop/opengldesktop.cpp index 13e3059364..7ca8764a09 100644 --- a/config.tests/unix/opengldesktop/opengldesktop.cpp +++ b/config.tests/unix/opengldesktop/opengldesktop.cpp @@ -34,6 +34,7 @@ #ifdef __APPLE__ #include #else +#define GL_GLEXT_PROTOTYPES #include #endif diff --git a/config.tests/unix/opengles2/opengles2.cpp b/config.tests/unix/opengles2/opengles2.cpp index b3b9be6d49..81926f3ee4 100644 --- a/config.tests/unix/opengles2/opengles2.cpp +++ b/config.tests/unix/opengles2/opengles2.cpp @@ -34,6 +34,7 @@ #ifdef BUILD_ON_MAC #include #else + #define GL_GLEXT_PROTOTYPES #include #endif diff --git a/config.tests/unix/opengles3/opengles3.cpp b/config.tests/unix/opengles3/opengles3.cpp index 506ac8b19c..80b2323465 100644 --- a/config.tests/unix/opengles3/opengles3.cpp +++ b/config.tests/unix/opengles3/opengles3.cpp @@ -34,6 +34,7 @@ #ifdef BUILD_ON_MAC #include #else + #define GL_GLEXT_PROTOTYPES #include #endif diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h index a060949c17..aa0e6394d3 100644 --- a/src/gui/opengl/qopengl.h +++ b/src/gui/opengl/qopengl.h @@ -89,6 +89,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 # elif defined(QT_OPENGL_ES_3) @@ -97,6 +104,11 @@ typedef void* GLeglImageOES; # include #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 @@ -117,7 +129,15 @@ typedef char GLchar; # include # else # define GL_GLEXT_LEGACY // Prevents GL/gl.h from #including system glext.h -# include +// 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 +# undef GL_GLEXT_PROTOTYPES +# else +# include +# endif # include # endif // Q_OS_MAC #endif // QT_OPENGL_ES_2 -- cgit v1.2.3 From 3c2cb87de2554b9c4f6e2080768fe9ede00aeab3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 7 Nov 2016 09:54:55 +0100 Subject: xcb: Warn and bail out when even the basic, dummy context fails Do not move on to glGet since the behavior is undefined. Task-number: QTBUG-48986 Change-Id: Ifd279635ed1b8441f92697965d15ae3ecb59a7e3 Reviewed-by: Andy Nichols --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 9bdedcc830..c2b7a562a9 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -672,8 +672,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; -- cgit v1.2.3 From bfaa8925d5cc0a59cec3f747a8d982ca819f026b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 2 Nov 2016 14:10:47 +0100 Subject: Improve the validation algorithm for binary JSON Add better boundary checks and catch (hopefully all) cases where invalid binary JSON could cause crashes. Change-Id: I206510b7c5e3ba953802a5f46645878e65704ecc Reviewed-by: Edward Welbourne --- src/corelib/json/qjson.cpp | 25 ++++++++------- src/corelib/json/qjson_p.h | 35 ++++++++++++++++----- tests/auto/corelib/json/invalidBinaryData/10.bjson | Bin 0 -> 544 bytes tests/auto/corelib/json/invalidBinaryData/11.bjson | Bin 0 -> 542 bytes tests/auto/corelib/json/invalidBinaryData/12.bjson | Bin 0 -> 506 bytes tests/auto/corelib/json/invalidBinaryData/13.bjson | Bin 0 -> 544 bytes tests/auto/corelib/json/invalidBinaryData/14.bjson | Bin 0 -> 521 bytes tests/auto/corelib/json/invalidBinaryData/15.bjson | Bin 0 -> 536 bytes tests/auto/corelib/json/invalidBinaryData/16.bjson | Bin 0 -> 874 bytes tests/auto/corelib/json/invalidBinaryData/17.bjson | Bin 0 -> 49 bytes tests/auto/corelib/json/invalidBinaryData/18.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/19.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/20.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/21.bjson | Bin 0 -> 552 bytes tests/auto/corelib/json/invalidBinaryData/22.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/23.bjson | Bin 0 -> 533 bytes tests/auto/corelib/json/invalidBinaryData/24.bjson | Bin 0 -> 506 bytes tests/auto/corelib/json/invalidBinaryData/25.bjson | Bin 0 -> 542 bytes tests/auto/corelib/json/invalidBinaryData/26.bjson | Bin 0 -> 628 bytes tests/auto/corelib/json/invalidBinaryData/27.bjson | Bin 0 -> 51 bytes tests/auto/corelib/json/invalidBinaryData/28.bjson | Bin 0 -> 542 bytes tests/auto/corelib/json/invalidBinaryData/29.bjson | Bin 0 -> 544 bytes tests/auto/corelib/json/invalidBinaryData/30.bjson | Bin 0 -> 542 bytes tests/auto/corelib/json/invalidBinaryData/31.bjson | Bin 0 -> 553 bytes tests/auto/corelib/json/invalidBinaryData/32.bjson | Bin 0 -> 536 bytes tests/auto/corelib/json/invalidBinaryData/33.bjson | Bin 0 -> 544 bytes tests/auto/corelib/json/invalidBinaryData/34.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/35.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/36.bjson | Bin 0 -> 524 bytes tests/auto/corelib/json/invalidBinaryData/37.bjson | Bin 0 -> 536 bytes tests/auto/corelib/json/tst_qtjson.cpp | 16 ++++++++++ 31 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 tests/auto/corelib/json/invalidBinaryData/10.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/11.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/12.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/13.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/14.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/15.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/16.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/17.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/18.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/19.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/20.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/21.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/22.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/23.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/24.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/25.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/26.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/27.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/28.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/29.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/30.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/31.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/32.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/33.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/34.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/35.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/36.bjson create mode 100644 tests/auto/corelib/json/invalidBinaryData/37.bjson diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp index c3b58e59a5..c6fff068ce 100644 --- a/src/corelib/json/qjson.cpp +++ b/src/corelib/json/qjson.cpp @@ -129,10 +129,12 @@ bool Data::valid() const return false; bool res = false; - if (header->root()->is_object) - res = static_cast(header->root())->isValid(); + Base *root = header->root(); + int maxSize = alloc - sizeof(Header); + if (root->is_object) + res = static_cast(root)->isValid(maxSize); else - res = static_cast(header->root())->isValid(); + res = static_cast(root)->isValid(maxSize); return res; } @@ -195,9 +197,9 @@ int Object::indexOf(const QString &key, bool *exists) 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; @@ -206,8 +208,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) @@ -221,9 +222,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) { @@ -323,12 +324,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(base(b))->isValid(); + return static_cast(base(b))->isValid(s); if (type == QJsonValue::Object) - return static_cast(base(b))->isValid(); + return static_cast(base(b))->isValid(s); return true; } diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index b7de24d165..c5fd38e640 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -302,12 +302,19 @@ public: 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(); @@ -376,11 +383,16 @@ public: 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(); @@ -567,7 +579,7 @@ public: } int indexOf(const QString &key, bool *exists); - bool isValid() const; + bool isValid(int maxSize) const; }; @@ -577,7 +589,7 @@ public: inline Value at(int i) const; inline Value &operator [](int i); - bool isValid() const; + bool isValid(int maxSize) const; }; @@ -631,12 +643,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); } @@ -662,6 +674,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; diff --git a/tests/auto/corelib/json/invalidBinaryData/10.bjson b/tests/auto/corelib/json/invalidBinaryData/10.bjson new file mode 100644 index 0000000000..12b29b7aa5 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/10.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/11.bjson b/tests/auto/corelib/json/invalidBinaryData/11.bjson new file mode 100644 index 0000000000..cf2b612111 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/11.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/12.bjson b/tests/auto/corelib/json/invalidBinaryData/12.bjson new file mode 100644 index 0000000000..9c2403350e Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/12.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/13.bjson b/tests/auto/corelib/json/invalidBinaryData/13.bjson new file mode 100644 index 0000000000..db6308b1fd Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/13.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/14.bjson b/tests/auto/corelib/json/invalidBinaryData/14.bjson new file mode 100644 index 0000000000..347da4572c Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/14.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/15.bjson b/tests/auto/corelib/json/invalidBinaryData/15.bjson new file mode 100644 index 0000000000..c6c5558934 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/15.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/16.bjson b/tests/auto/corelib/json/invalidBinaryData/16.bjson new file mode 100644 index 0000000000..ae8b57446d Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/16.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/17.bjson b/tests/auto/corelib/json/invalidBinaryData/17.bjson new file mode 100644 index 0000000000..32f0cc0e23 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/17.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/18.bjson b/tests/auto/corelib/json/invalidBinaryData/18.bjson new file mode 100644 index 0000000000..50c89169eb Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/18.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/19.bjson b/tests/auto/corelib/json/invalidBinaryData/19.bjson new file mode 100644 index 0000000000..b922212f45 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/19.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/20.bjson b/tests/auto/corelib/json/invalidBinaryData/20.bjson new file mode 100644 index 0000000000..c965a0d294 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/20.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/21.bjson b/tests/auto/corelib/json/invalidBinaryData/21.bjson new file mode 100644 index 0000000000..98165ee40c Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/21.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/22.bjson b/tests/auto/corelib/json/invalidBinaryData/22.bjson new file mode 100644 index 0000000000..151f773a81 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/22.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/23.bjson b/tests/auto/corelib/json/invalidBinaryData/23.bjson new file mode 100644 index 0000000000..6eb5269470 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/23.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/24.bjson b/tests/auto/corelib/json/invalidBinaryData/24.bjson new file mode 100644 index 0000000000..c55a2a3e3b Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/24.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/25.bjson b/tests/auto/corelib/json/invalidBinaryData/25.bjson new file mode 100644 index 0000000000..6c619f2ae1 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/25.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/26.bjson b/tests/auto/corelib/json/invalidBinaryData/26.bjson new file mode 100644 index 0000000000..3bf303215a Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/26.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/27.bjson b/tests/auto/corelib/json/invalidBinaryData/27.bjson new file mode 100644 index 0000000000..d2656c2287 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/27.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/28.bjson b/tests/auto/corelib/json/invalidBinaryData/28.bjson new file mode 100644 index 0000000000..6797cf8c40 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/28.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/29.bjson b/tests/auto/corelib/json/invalidBinaryData/29.bjson new file mode 100644 index 0000000000..0645dfc3b2 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/29.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/30.bjson b/tests/auto/corelib/json/invalidBinaryData/30.bjson new file mode 100644 index 0000000000..f77fe1efd0 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/30.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/31.bjson b/tests/auto/corelib/json/invalidBinaryData/31.bjson new file mode 100644 index 0000000000..d9840b6582 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/31.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/32.bjson b/tests/auto/corelib/json/invalidBinaryData/32.bjson new file mode 100644 index 0000000000..1de4cb829f Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/32.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/33.bjson b/tests/auto/corelib/json/invalidBinaryData/33.bjson new file mode 100644 index 0000000000..532a31dc08 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/33.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/34.bjson b/tests/auto/corelib/json/invalidBinaryData/34.bjson new file mode 100644 index 0000000000..f498558eff Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/34.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/35.bjson b/tests/auto/corelib/json/invalidBinaryData/35.bjson new file mode 100644 index 0000000000..8701210755 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/35.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/36.bjson b/tests/auto/corelib/json/invalidBinaryData/36.bjson new file mode 100644 index 0000000000..ef5864e911 Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/36.bjson differ diff --git a/tests/auto/corelib/json/invalidBinaryData/37.bjson b/tests/auto/corelib/json/invalidBinaryData/37.bjson new file mode 100644 index 0000000000..f4dd4ae12f Binary files /dev/null and b/tests/auto/corelib/json/invalidBinaryData/37.bjson differ diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index 1665ff696d..f2f9166711 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -103,6 +103,7 @@ private Q_SLOTS: void fromBinary(); void toAndFromBinary_data(); void toAndFromBinary(); + void invalidBinaryData(); void parseNumbers(); void parseStrings(); void parseDuplicateKeys(); @@ -1779,6 +1780,21 @@ void tst_QtJson::toAndFromBinary() QVERIFY(doc == outdoc); } +void tst_QtJson::invalidBinaryData() +{ + QDir dir(testDataDir + "/invalidBinaryData"); + QFileInfoList files = dir.entryInfoList(); + for (int i = 0; i < files.size(); ++i) { + if (!files.at(i).isFile()) + continue; + QFile file(files.at(i).filePath()); + file.open(QIODevice::ReadOnly); + QByteArray bytes = file.readAll(); + QJsonDocument document = QJsonDocument::fromRawData(bytes.constData(), bytes.size()); + QVERIFY(document.isNull()); + } +} + void tst_QtJson::parseNumbers() { { -- cgit v1.2.3 From dffde23a0ae28f05ef2aa9af138f0a82bbfce942 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Nov 2016 10:32:54 +0100 Subject: Fix writing into application directory Tests are not supposed to write into the build/application directory, but rather should output to the temp directory. Change-Id: Idcdf51226a2d547514aea2fbb2054998d8a3437e Reviewed-by: Friedemann Kleint --- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 286f00c111..73da5804eb 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -171,6 +171,7 @@ private: const QString m_prefix; const QString m_convertFromImage; const QString m_loadFromData; + const QTemporaryDir m_tempDir; }; static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) @@ -230,11 +231,11 @@ void tst_QPixmap::initTestCase() QVERIFY(!m_prefix.isEmpty()); QVERIFY(!m_convertFromImage.isEmpty()); QVERIFY(!m_loadFromData.isEmpty()); + QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString())); } void tst_QPixmap::cleanupTestCase() { - QFile::remove(QLatin1String("temp_image.png")); } void tst_QPixmap::swap() @@ -1471,18 +1472,18 @@ void tst_QPixmap::preserveDepth() void tst_QPixmap::loadAsBitmapOrPixmap() { QImage tmp(10, 10, QImage::Format_RGB32); - tmp.save("temp_image.png"); + tmp.save(m_tempDir.path() + "/temp_image.png"); bool ok; // Check that we can load the pixmap as a pixmap and that it then turns into a pixmap - QPixmap pixmap("temp_image.png"); + QPixmap pixmap(m_tempDir.path() + "/temp_image.png"); QVERIFY(!pixmap.isNull()); QVERIFY(pixmap.depth() > 1); QVERIFY(!pixmap.isQBitmap()); pixmap = QPixmap(); - ok = pixmap.load("temp_image.png"); + ok = pixmap.load(m_tempDir.path() + "/temp_image.png"); QVERIFY(ok); QVERIFY(!pixmap.isNull()); QVERIFY(pixmap.depth() > 1); @@ -1490,20 +1491,20 @@ void tst_QPixmap::loadAsBitmapOrPixmap() //now we can try to load it without an extension pixmap = QPixmap(); - ok = pixmap.load("temp_image"); + ok = pixmap.load(m_tempDir.path() + "/temp_image"); QVERIFY(ok); QVERIFY(!pixmap.isNull()); QVERIFY(pixmap.depth() > 1); QVERIFY(!pixmap.isQBitmap()); // The do the same check for bitmaps.. - QBitmap bitmap("temp_image.png"); + QBitmap bitmap(m_tempDir.path() + "/temp_image.png"); QVERIFY(!bitmap.isNull()); QCOMPARE(bitmap.depth(), 1); QVERIFY(bitmap.isQBitmap()); bitmap = QBitmap(); - ok = bitmap.load("temp_image.png"); + ok = bitmap.load(m_tempDir.path() + "/temp_image.png"); QVERIFY(ok); QVERIFY(!bitmap.isNull()); QCOMPARE(bitmap.depth(), 1); -- cgit v1.2.3 From 2265fbe7c12cbb1f98fad8b4bb878d571427000c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 12 Oct 2016 17:33:30 +0300 Subject: Remove unused variable in QIconLoader::findIconHelper() Change-Id: Idac0b24631187063445ea5acfd078b2479359d52 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/image/qiconloader.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index c7f1f2beb4..8f9f22eb95 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -242,8 +242,6 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, QThemeIconInfo info; Q_ASSERT(!themeName.isEmpty()); - QPixmap pixmap; - // Used to protect against potential recursions visited << themeName; -- cgit v1.2.3 From 1c080465659af269775908bb249159152d563b89 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 8 Nov 2016 15:54:43 +0300 Subject: doc: Remove obsolete note for QWidget::paintEvent() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qt_x11_set_global_double_buffer() is dead code since Qt 5. Change-Id: Ie9a33b6f03dc2e39f12bc790292bb0d227f05c44 Reviewed-by: Tor Arne Vestbø --- src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp | 8 -------- src/widgets/kernel/qwidget.cpp | 5 ----- 2 files changed, 13 deletions(-) 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 53cd907c74..b26f791d37 100644 --- a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp +++ b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp @@ -127,11 +127,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/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index b2db4e1529..53b39e0394 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -9597,11 +9597,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 -- cgit v1.2.3 From 839cae0422be3302ca4a9cbbd7e8482152a7d8c3 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 19 Oct 2016 17:37:00 +0300 Subject: doc: Add missing documentation for QXcbWindowFunctions::setWmWindowRole() Change-Id: I5a457eb19fee011868cdf6d0534713c760fd57d2 Reviewed-by: Friedemann Kleint Reviewed-by: David Faure --- .../xcbfunctions/qxcbwindowfunctions.qdoc | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc index b26255553f..8d9c85a5c3 100644 --- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc +++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc @@ -85,6 +85,35 @@ relayed to the function retrieved by QGuiApplication. */ +/*! + \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 -- cgit v1.2.3 From 468eeca88ea1a398bc15ea156a4b1609dc23a018 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Nov 2016 16:44:50 +0100 Subject: fix showing lgpl in the license prompt the response is lowercased, so an uppercase L would never match. amends c7c7cf636. Change-Id: Idc796ec9a43bfd23452cd758100cbf1fb6fb252b Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann --- tools/configure/configureapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 263cd6e78c..4639709602 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -4514,7 +4514,7 @@ bool Configure::showLicense(QString orgLicenseFile) return false; } else { if (dictionary["EDITION"] == "OpenSource") { - if (accept == 'L') + if (accept == 'l') licenseFile = orgLicenseFile + "/LICENSE.LGPL3"; else licenseFile = orgLicenseFile + "/LICENSE.GPL2"; -- cgit v1.2.3 From c214379156e4c75dcfe59cf73d69b912f4293303 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 14 Nov 2016 10:49:35 +0100 Subject: winrt: Fix definition of GL_GLEXT_PROTOTYPES in qwinrtbackingstore We have to make sure that GL_GLEXT_RPOTOTYPES is defined when qplatformbackingstore.h is included. Without the definition glBlitFramebufferANGLE will not be set and compilation might fail. Task-number: QTBUG-57083 Change-Id: I4cacaf4c2851913b3437ebd1f0f2956d0f400553 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/winrt/qwinrtbackingstore.h | 1 + 1 file changed, 1 insertion(+) 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 #include #include -- cgit v1.2.3 From 8db556d29919fd0c0ddb23b743cb5e6c218b1ae2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 9 Nov 2016 13:11:31 +0100 Subject: fix $$section()'s bad argument count error message the autotest was also broken, because it was created by pasting the bogus message into the result ... Change-Id: I02b8663b96c7d96cdb3c19639e2213e49fd2bcec Reviewed-by: Joerg Bornemann --- qmake/library/qmakebuiltins.cpp | 3 +-- tests/auto/tools/qmakelib/evaltest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 8f3849e6d8..c8208909b6 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -478,8 +478,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( int end = -1; if (func_t == E_SECTION) { if (args.count() != 3 && args.count() != 4) { - evalError(fL1S("%1(var) section(var, sep, begin, end) requires" - " three or four arguments.").arg(func.toQString(m_tmp1))); + evalError(fL1S("section(var, sep, begin, end) requires three or four arguments.")); } else { var = args[0]; sep = args.at(1).toQString(); diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 09482d86d9..3c96c6fb7a 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -1125,8 +1125,8 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) QTest::newRow("$$section(): bad number of arguments") << "VAR = $$section(1, 2) \\\n$$section(1, 2, 3, 4, 5)" << "VAR =" - << "##:1: section(var) section(var, sep, begin, end) requires three or four arguments.\n" - "##:2: section(var) section(var, sep, begin, end) requires three or four arguments." + << "##:1: section(var, sep, begin, end) requires three or four arguments.\n" + "##:2: section(var, sep, begin, end) requires three or four arguments." << true; QTest::newRow("$$find()") -- cgit v1.2.3 From 9308b7d618db7f08768b11c17b661853c66005e4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 8 Nov 2016 13:41:27 +0100 Subject: don't create bogus property variants sysroot, spec, and xspec have no /src and /get variants. Change-Id: I8548791f8ea6ba9fd9f10c35f914ed6badbea9d4 Reviewed-by: Joerg Bornemann --- qmake/property.cpp | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/qmake/property.cpp b/qmake/property.cpp index 817ae953d5..b9139d5be1 100644 --- a/qmake/property.cpp +++ b/qmake/property.cpp @@ -46,38 +46,41 @@ static const struct { const char *name; QLibraryInfo::LibraryLocation loc; bool raw; + bool singular; } propList[] = { - { "QT_SYSROOT", QLibraryInfo::SysrootPath, true }, - { "QT_INSTALL_PREFIX", QLibraryInfo::PrefixPath, false }, - { "QT_INSTALL_ARCHDATA", QLibraryInfo::ArchDataPath, false }, - { "QT_INSTALL_DATA", QLibraryInfo::DataPath, false }, - { "QT_INSTALL_DOCS", QLibraryInfo::DocumentationPath, false }, - { "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath, false }, - { "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath, false }, - { "QT_INSTALL_LIBEXECS", QLibraryInfo::LibraryExecutablesPath, false }, - { "QT_INSTALL_BINS", QLibraryInfo::BinariesPath, false }, - { "QT_INSTALL_TESTS", QLibraryInfo::TestsPath, false }, - { "QT_INSTALL_PLUGINS", QLibraryInfo::PluginsPath, false }, - { "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath, false }, - { "QT_INSTALL_QML", QLibraryInfo::Qml2ImportsPath, false }, - { "QT_INSTALL_TRANSLATIONS", QLibraryInfo::TranslationsPath, false }, - { "QT_INSTALL_CONFIGURATION", QLibraryInfo::SettingsPath, false }, - { "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath, false }, - { "QT_INSTALL_DEMOS", QLibraryInfo::ExamplesPath, false }, // Just backwards compat - { "QT_HOST_PREFIX", QLibraryInfo::HostPrefixPath, true }, - { "QT_HOST_DATA", QLibraryInfo::HostDataPath, true }, - { "QT_HOST_BINS", QLibraryInfo::HostBinariesPath, true }, - { "QT_HOST_LIBS", QLibraryInfo::HostLibrariesPath, true }, - { "QMAKE_SPEC", QLibraryInfo::HostSpecPath, true }, - { "QMAKE_XSPEC", QLibraryInfo::TargetSpecPath, true }, + { "QT_SYSROOT", QLibraryInfo::SysrootPath, true, true }, + { "QT_INSTALL_PREFIX", QLibraryInfo::PrefixPath, false, false }, + { "QT_INSTALL_ARCHDATA", QLibraryInfo::ArchDataPath, false, false }, + { "QT_INSTALL_DATA", QLibraryInfo::DataPath, false, false }, + { "QT_INSTALL_DOCS", QLibraryInfo::DocumentationPath, false, false }, + { "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath, false, false }, + { "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath, false, false }, + { "QT_INSTALL_LIBEXECS", QLibraryInfo::LibraryExecutablesPath, false, false }, + { "QT_INSTALL_BINS", QLibraryInfo::BinariesPath, false, false }, + { "QT_INSTALL_TESTS", QLibraryInfo::TestsPath, false, false }, + { "QT_INSTALL_PLUGINS", QLibraryInfo::PluginsPath, false, false }, + { "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath, false, false }, + { "QT_INSTALL_QML", QLibraryInfo::Qml2ImportsPath, false, false }, + { "QT_INSTALL_TRANSLATIONS", QLibraryInfo::TranslationsPath, false, false }, + { "QT_INSTALL_CONFIGURATION", QLibraryInfo::SettingsPath, false, false }, + { "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath, false, false }, + { "QT_INSTALL_DEMOS", QLibraryInfo::ExamplesPath, false, false }, // Just backwards compat + { "QT_HOST_PREFIX", QLibraryInfo::HostPrefixPath, true, false }, + { "QT_HOST_DATA", QLibraryInfo::HostDataPath, true, false }, + { "QT_HOST_BINS", QLibraryInfo::HostBinariesPath, true, false }, + { "QT_HOST_LIBS", QLibraryInfo::HostLibrariesPath, true, false }, + { "QMAKE_SPEC", QLibraryInfo::HostSpecPath, true, true }, + { "QMAKE_XSPEC", QLibraryInfo::TargetSpecPath, true, true }, }; QMakeProperty::QMakeProperty() : settings(0) { for (unsigned i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) { QString name = QString::fromLatin1(propList[i].name); - m_values[ProKey(name + "/src")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectiveSourcePaths); - m_values[ProKey(name + "/get")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectivePaths); + if (!propList[i].singular) { + m_values[ProKey(name + "/src")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectiveSourcePaths); + m_values[ProKey(name + "/get")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectivePaths); + } QString val = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::FinalPaths); if (!propList[i].raw) { m_values[ProKey(name + "/dev")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::DevicePaths); -- cgit v1.2.3 From 4e1d65071b0984fc9570b7328be3142b11b740d2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Nov 2016 16:51:24 +0100 Subject: fix wording issues in license prompt Task-number: QTBUG-42136 Change-Id: Ie4ff1b38af6e7a74490558e80a0e559fee8a5486 Reviewed-by: Kai Koehne --- configure | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 0b8b417bbc..6ebeab30fe 100755 --- a/configure +++ b/configure @@ -3108,14 +3108,14 @@ if [ "$Edition" = "OpenSource" ]; then while true; do if [ "$CFG_ANDROID_STYLE_ASSETS" = "no" ] || [ "$XPLATFORM_ANDROID" = "no" ]; then echo "You are licensed to use this software under the terms of" - echo "the Lesser GNU General Public License (LGPL) versions 2.1." + echo "the GNU Lesser General Public License (LGPL) version 2.1." echo "You are also licensed to use this software under the terms of" - echo "the GNU Lesser General Public License (LGPL) versions 3." + echo "the GNU Lesser General Public License (LGPL) version 3." affix="either" showLGPL2="yes" else echo "You are licensed to use this software under the terms of" - echo "the GNU Lesser General Public License (LGPL) versions 3." + echo "the GNU Lesser General Public License (LGPL) version 3." showLGPL2="no" affix="the" fi @@ -3129,7 +3129,7 @@ if [ "$Edition" = "OpenSource" ]; then echo "Type '3' to view the GNU Lesser General Public License version 3." fi if [ "$showLGPL2" = "yes" ]; then - echo "Type 'L' to view the Lesser GNU General Public License version 2.1." + echo "Type 'L' to view the GNU Lesser General Public License version 2.1." fi echo "Type 'yes' to accept this license offer." echo "Type 'no' to decline this license offer." -- cgit v1.2.3 From 6bfe30a0bf33f300f80f87026177f4da8f54df13 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Nov 2016 17:08:07 +0100 Subject: drop obsolete file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amends 97fcf3bc9 (introduction of official android port). Change-Id: Iaab596559c5d4c825269cbdda77d956c3650fb09 Reviewed-by: Joerg Bornemann Reviewed-by: Jake Petroules Reviewed-by: BogDan Vatra Reviewed-by: Otto Ryynänen --- mkspecs/common/linux-android.conf | 114 -------------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 mkspecs/common/linux-android.conf diff --git a/mkspecs/common/linux-android.conf b/mkspecs/common/linux-android.conf deleted file mode 100644 index fec008cb45..0000000000 --- a/mkspecs/common/linux-android.conf +++ /dev/null @@ -1,114 +0,0 @@ -MAKEFILE_GENERATOR = UNIX -QMAKE_INCREMENTAL_STYLE = sublib - -QMAKE_PLATFORM += android - -include(linux.conf) -include(gcc-base-unix.conf) - -DEFINES += QT_NO_PRINTER QT_NO_PRINTDIALOG -QT_QPA_DEFAULT_PLATFORM = minimal - -NDK_ROOT = $$(ANDROID_NDK_ROOT) -isEmpty(NDK_ROOT): error("$ANDROID_NDK_ROOT is empty, please set it to something like ~/android/ndk-r7c") - -NDK_HOST = $$(ANDROID_NDK_HOST) -isEmpty(NDK_HOST): error("$ANDROID_NDK_HOST is empty, please set it to something like linux-x86 or darwin-x86") - -ANDROID_PLATFORM = $$(ANDROID_NDK_PLATFORM) -isEmpty(ANDROID_PLATFORM): ANDROID_PLATFORM = android-5 - -NDK_TOOLCHAIN_VERSION = $$(ANDROID_NDK_TOOLCHAIN_VERSION) -isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = 4.4.3 - -!contains(NDK_TOOLCHAIN_VERSION, 4.4.3): ANDROID_CXXSTL_SUFFIX = -$$NDK_TOOLCHAIN_VERSION - -NDK_TOOLCHAIN = $$ANDROID_NDK_TOOLCHAIN_PREFIX-$$NDK_TOOLCHAIN_VERSION -NDK_TOOLCHAIN_PATH = $$NDK_ROOT/toolchains/$$NDK_TOOLCHAIN/prebuilt/$$NDK_HOST - -CONFIG += $$ANDROID_PLATFORM $$ANDROID_TARGET_ARCH -ANDROID_PLATFORM_ROOT_PATH = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/ -ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr - -# used to compile platform plugins for android-4 and android-5 -QMAKE_ANDROID_PLATFORM_INCDIR = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/usr/include -QMAKE_ANDROID_PLATFORM_LIBDIR = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/usr/lib - -ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl$$ANDROID_CXXSTL_SUFFIX/gnu-libstdc++/libs/$$ANDROID_TARGET_ARCH -ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl$$ANDROID_CXXSTL_SUFFIX/gnu-libstdc++/include $$ANDROID_SOURCES_CXX_STL_LIBDIR/include - -# modifications to g++.conf -QMAKE_CC = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-gcc - -QMAKE_CFLAGS_WARN_ON = -Wall -Wextra -QMAKE_CFLAGS_WARN_OFF = -Wno-psabi - -QMAKE_CFLAGS_SHLIB = -fPIC -QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden - -QMAKE_CXX = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-g++ -QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF -QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE -QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG -QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB -QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD -QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden - -QMAKE_LINK = $$QMAKE_CXX -QMAKE_LINK_SHLIB = $$QMAKE_LINK - -# modifications to linux.conf -QMAKE_AR = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-ar cqs -QMAKE_OBJCOPY = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-objcopy -QMAKE_NM = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-nm -P -QMAKE_STRIP = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-strip -QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-ranlib - -QMAKE_INCDIR = $$ANDROID_PLATFORM_PATH/include $$ANDROID_SOURCES_CXX_STL_INCDIR -QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$ANDROID_PLATFORM_PATH/lib -QMAKE_INCDIR_X11 = -QMAKE_LIBDIR_X11 = -QMAKE_INCDIR_OPENGL = -QMAKE_INCDIR_OPENGL_ES2 = -QMAKE_LIBDIR_OPENGL_ES2 = - -contains(ANDROID_TARGET_ARCH, x86): LIBGCC_PATH_FULL = $$system($$QMAKE_CC -print-libgcc-file-name) - else: LIBGCC_PATH_FULL = $$system($$QMAKE_CC -mthumb-interwork -print-libgcc-file-name) - -QMAKE_LINK = $$QMAKE_CXX -QMAKE_LINK_SHLIB = $$QMAKE_CXX -QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH -L$$dirname(LIBGCC_PATH_FULL) -Wl,-rpath-link=$$ANDROID_PLATFORM_PATH/lib -QMAKE_LFLAGS_APP = -QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared - -contains(NDK_ROOT, ".*r[56].*") { - !contains(ANDROID_PLATFORM, ".*android-[458].*") { - message("Your NDK-version is out-dated. A work-around is enabled. Consider updating your NDK (workarounds are required until r6(a))") - QMAKE_LFLAGS_SHLIB += $$ANDROID_PLATFORM_PATH/lib/crtbegin_so.o $$ANDROID_PLATFORM_PATH/lib/crtend_so.o - } -} - -QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_SONAME = -QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined -QMAKE_LFLAGS_RPATH = -Wl,-rpath= - -# TODO: -lgnustl_static was -lstdc++, but that leads to undefined reference to -# std::__throw_bad_alloc during configure. -QMAKE_LIBS = -lsupc++ -llog -lz -lm -ldl -lc -lgcc -lgnustl_static -QMAKE_LIBS_X11 = -QMAKE_LIBS_X11SM = -QMAKE_LIBS_QT_THREAD = -QMAKE_LIBS_QT_OPENGL = -QMAKE_LIBS_QTOPIA = -QMAKE_LIBS_THREAD = -QMAKE_LIBS_OPENGL = -QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 $$QMAKE_LIBS - -load(qt_config) - -- cgit v1.2.3 From d91bf00c43736940e4139357e288df6432775a3d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 Jun 2016 12:06:29 +0200 Subject: tst_QFileSystemModel::specialFiles(): Remove Windows parts The test created a Windows shortcut (.lnk) and checked on its existence. It was not found in the first test since QFileSystemModel returned the resolved file name (linktarget.txt). When fixing this by querying QFileSystemModel::fileInfo()::fileName(), the 2nd test failed since shortcut files are not considered system files. Amends change 3b093034b638a69b4dc91212d1743638864a1337. Task-number: QTBUG-53890 Task-number: QTBUG-20968 Task-number: QTBUG-29403 Change-Id: Iec58b52532b44d12759eaa6c8d63a8a4dc8d1bc3 Reviewed-by: Joerg Bornemann --- .../dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index af92f0735d..cb0f0b040a 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -1097,6 +1097,10 @@ static QSet fileListUnderIndex(const QFileSystemModel *model, const QMo void tst_QFileSystemModel::specialFiles() { +#ifndef Q_OS_UNIX + QSKIP("Not implemented"); +#endif + QFileSystemModel model; model.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); @@ -1105,23 +1109,8 @@ void tst_QFileSystemModel::specialFiles() // as it will always return a valid index for existing files, // even if the file is not visible with the given filter. -#if defined(Q_OS_UNIX) const QModelIndex rootIndex = model.setRootPath(QStringLiteral("/dev/")); const QString testFileName = QStringLiteral("null"); -#elif defined(Q_OS_WIN) - const QModelIndex rootIndex = model.setRootPath(flatDirTestPath); - - const QString testFileName = QStringLiteral("linkSource.lnk"); - - QFile file(flatDirTestPath + QLatin1String("/linkTarget.txt")); - QVERIFY(file.open(QIODevice::WriteOnly)); - file.close(); - QVERIFY(file.link(flatDirTestPath + '/' + testFileName)); -#else - QSKIP("Not implemented"); - QModelIndex rootIndex; - QString testFileName; -#endif QTRY_VERIFY(fileListUnderIndex(&model, rootIndex).contains(testFileName)); -- cgit v1.2.3 From addf1f45f3e2c37a09ef7f7bab909467c2bf79f7 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 11 Nov 2016 12:34:54 -0800 Subject: qmake: fix installation of asset catalog files This strips leading whitespace from asset catalog filenames, which was causing installation to fail due to incorrectly calculated paths. Task-number: QTBUG-57090 Change-Id: I80db627262f9d58f4403e2d8ab205bef2113992b Reviewed-by: Oswald Buddenhagen --- mkspecs/features/mac/asset_catalogs.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/mac/asset_catalogs.prf b/mkspecs/features/mac/asset_catalogs.prf index 57d93d56d5..87875136c2 100644 --- a/mkspecs/features/mac/asset_catalogs.prf +++ b/mkspecs/features/mac/asset_catalogs.prf @@ -65,7 +65,7 @@ actool_output_files = $$system(\ mkdir -p $$system_quote($$QMAKE_ASSET_CATALOGS_BUILD_PATH) && \ /usr/libexec/PlistBuddy -c \'Print :com.apple.actool.compilation-results:output-files\' \ - /dev/stdin <<< $($${asset_catalog_compiler.commands} 2>/dev/null) | grep \'^ .*$\', lines) + /dev/stdin <<< $($${asset_catalog_compiler.commands} 2>/dev/null) | sed -Ene \'s/^ +//p\', lines) for (output_file, actool_output_files) { !equals(output_file, $$asset_catalog_compiler.target): \ -- cgit v1.2.3 From 80842959c4f63be930c77da39df7ac386dcaa1d7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 12 Nov 2016 21:01:20 +0100 Subject: Revert "Optimize QJsonObject::operator==" This reverts commit 862fa24179505ef725ff78bb64bdabd54bd00c95, which attempted to optimize QJsonObject::operator== under the assumption that the entries it holds are lexicographically sorted. They should be, because Object::indexOf() finds them by binary search, but apparently both fromJson(), as well as construction through op[] leave (some) entries unsorted. This behavior should be fixed, because other code relies on sorted entries, too, but until the problem is more fully under- stood, revert the patch to unbreak equality comparisons. Task-number: QTBUG-56843 Change-Id: I5b608c16d1bbcb4f01b75ce93bd58b49ff050be2 Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 2 -- src/corelib/json/qjsonobject.cpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index c5fd38e640..5be31ca03f 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -691,8 +691,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 f5fd76eac0..b83c8dd19a 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -545,8 +545,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; } -- cgit v1.2.3 From 291eba6f8099a0fec8fbd9cf8a1fb67e5c9f4f8d Mon Sep 17 00:00:00 2001 From: Palo Kisa Date: Mon, 7 Nov 2016 18:27:17 +0100 Subject: QClipboard: Fix emitting changed() in XCB In XCB environment the QClipboard::changed() was not delivered if the QClipboard::clear() was issued by other Qt app/process. If the QClipboard::clear() is used, then the owner in xcb_xfixes_selection_notify_event_t is XCB_NONE, so we need make the decission to handle this event by the selection_timestamp and our m_timestamp[mode]. Task-number: QTBUG-56972 Change-Id: If4c486ac02223eac506465cac7ff1a07bd02a187 Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index d44ebae8f7..40abef4e50 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -723,8 +723,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 { -- cgit v1.2.3 From 246fe271878dbe586b5f3222a78d67dfecd1ca83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Nov 2016 08:01:29 +0100 Subject: Cocoa: Make dictation via speech recognition work Returning NSNotFound from the NSTextInputClient selectedRange implementation when there is no selection prevents dictation from activating (for unknown reasons). Return an empty {0, 0} range instead. Text input methods such as Pinyin still work after this change. [ChangeLog][macOS] Speech to text dictation now works for Qt text input. Change-Id: Ibf1729bdd271e8ed5ce3c9d2a0373c8ab3613d8e Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1ad9b5f327..50dda52a7b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1783,9 +1783,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) -- cgit v1.2.3