From 1534297323284c8e5daec36246bc30d968899f2f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 24 Mar 2016 11:03:08 +0100 Subject: [PATCH 01/31] Update comment in tst_QLocalSocket::readBufferOverflow QWindowsPipeWriter doesn't write in a separate thread anymore. Change-Id: Id978bfdfa2531be91cce94476ab9b0dff237bd61 Reviewed-by: Kai Koehne --- tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index bfe43673d21..a96c88874ec 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -611,7 +611,7 @@ void tst_QLocalSocket::readBufferOverflow() serverSocket->write(buffer, dataBufferSize); #ifndef Q_OS_WIN // The data is not immediately sent, but buffered. - // On Windows, the flushing is done asynchronously by a separate thread. + // On Windows, the flushing is done by an asynchronous write operation. // However, this operation will never complete as long as the data is not // read by the other end, so the call below always times out. // On Unix, the flushing is synchronous and thus needs to be done before From 2e385b3d74ffbcad820b36b717f9215cc7b86720 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 23 Mar 2016 13:05:54 +0100 Subject: [PATCH 02/31] Windows QPA: Fix regular expression to match CLSIDs in file dialog. Match correct number of digits and entire string, amending change 4347e811611ab15e544765a3a34761d2f5c68cb3. Task-number: QTBUG-33962 Task-number: QTBUG-51373 Change-Id: I56de00bd5ffb3a3a700efbb20970154faf86f923 Reviewed-by: Giuseppe D'Angelo --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index ca5b90b4290..993dff51290 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1325,7 +1325,7 @@ void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel static inline bool isClsid(const QString &s) { // detect "374DE290-123F-4565-9164-39C4925E467B". - static const QRegularExpression pattern(QLatin1String("[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{8}")); + static const QRegularExpression pattern(QLatin1String("\\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\\z")); Q_ASSERT(pattern.isValid()); return pattern.match(s).hasMatch(); } From 705d29585b9a006b2fc8dd77ebf7a67b3670011b Mon Sep 17 00:00:00 2001 From: "M. Moellney" Date: Sat, 19 Mar 2016 22:00:32 +0100 Subject: [PATCH 03/31] Fix qSetMessagePattern to have many time/backtrace parts The previous implementation overwrote multiple 'time' parts in the qSetMessagePattern with the last setting in the pattern line. %{time}%{time process}%{time boot} ended up to be output as if %{time boot}%{time boot}%{time boot} was set. This fix keeps the arguments of each individual 'time' part. The same holds for multiple 'backtrace' parts. The previouse implementation overwrote multiple 'backtrace' arguments with the arguments of the last occurrence. This fix keeps the individual arguments for the 'process' parts. The individual arguments are applied in qFormatLogMessage. A new test to verify the individual 'time' arguments application is added, too. Task-number: QTBUG-51944 Change-Id: Ib757614a482c5f31ed0a61b550daa2eea4b907b4 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qlogging.cpp | 69 +++++++++++++------ .../corelib/global/qlogging/tst_qlogging.cpp | 11 +++ 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index dcac9a16a40..86b95976091 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -980,13 +980,16 @@ struct QMessagePattern { // 0 terminated arrays of literal tokens / literal or placeholder tokens const char **literals; const char **tokens; - QString timeFormat; + QList timeArgs; // timeFormats in sequence of %{time #ifndef QT_BOOTSTRAPPED QElapsedTimer timer; #endif #ifdef QLOGGING_HAVE_BACKTRACE - QString backtraceSeparator; - int backtraceDepth; + struct BacktraceParams { + QString backtraceSeparator; + int backtraceDepth; + }; + QList backtraceArgs; // backtrace argumens in sequence of %{backtrace #endif bool fromEnvironment; @@ -998,10 +1001,6 @@ QBasicMutex QMessagePattern::mutex; QMessagePattern::QMessagePattern() : literals(0) , tokens(0) -#ifdef QLOGGING_HAVE_BACKTRACE - , backtraceSeparator(QLatin1Char('|')) - , backtraceDepth(5) -#endif , fromEnvironment(false) { #ifndef QT_BOOTSTRAPPED @@ -1104,10 +1103,14 @@ void QMessagePattern::setPattern(const QString &pattern) tokens[i] = timeTokenC; int spaceIdx = lexeme.indexOf(QChar::fromLatin1(' ')); if (spaceIdx > 0) - timeFormat = lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2); + timeArgs.append(lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2)); + else + timeArgs.append(QString()); } else if (lexeme.startsWith(QLatin1String(backtraceTokenC))) { #ifdef QLOGGING_HAVE_BACKTRACE tokens[i] = backtraceTokenC; + QString backtraceSeparator = QStringLiteral("|"); + int backtraceDepth = 5; QRegularExpression depthRx(QStringLiteral(" depth=(?|\"([^\"]*)\"|([^ }]*))")); QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))")); QRegularExpressionMatch m = depthRx.match(lexeme); @@ -1121,6 +1124,10 @@ void QMessagePattern::setPattern(const QString &pattern) m = separatorRx.match(lexeme); if (m.hasMatch()) backtraceSeparator = m.captured(1); + BacktraceParams backtraceParams; + backtraceParams.backtraceDepth = backtraceDepth; + backtraceParams.backtraceSeparator = backtraceSeparator; + backtraceArgs.append(backtraceParams); #else error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n"); #endif @@ -1263,13 +1270,29 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con bool skip = false; +#ifndef QT_BOOTSTRAPPED + int timeArgsIdx = 0; +#ifdef QLOGGING_HAVE_BACKTRACE + int backtraceArgsIdx = 0; +#endif +#endif + // we do not convert file, function, line literals to local encoding due to overhead for (int i = 0; pattern->tokens[i] != 0; ++i) { const char *token = pattern->tokens[i]; if (token == endifTokenC) { skip = false; } else if (skip) { - // do nothing + // we skip adding messages, but we have to iterate over + // timeArgsIdx and backtraceArgsIdx anyway +#ifndef QT_BOOTSTRAPPED + if (token == timeTokenC) + timeArgsIdx++; +#ifdef QLOGGING_HAVE_BACKTRACE + else if (token == backtraceTokenC) + backtraceArgsIdx++; +#endif +#endif } else if (token == messageTokenC) { message.append(str); } else if (token == categoryTokenC) { @@ -1307,11 +1330,15 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16)); #ifdef QLOGGING_HAVE_BACKTRACE } else if (token == backtraceTokenC) { - QVarLengthArray buffer(7 + pattern->backtraceDepth); + QMessagePattern::BacktraceParams backtraceParams = pattern->backtraceArgs.at(backtraceArgsIdx); + QString backtraceSeparator = backtraceParams.backtraceSeparator; + int backtraceDepth = backtraceParams.backtraceDepth; + backtraceArgsIdx++; + QVarLengthArray buffer(7 + backtraceDepth); int n = backtrace(buffer.data(), buffer.size()); if (n > 0) { int numberPrinted = 0; - for (int i = 0; i < n && numberPrinted < pattern->backtraceDepth; ++i) { + for (int i = 0; i < n && numberPrinted < backtraceDepth; ++i) { QScopedPointer strings(backtrace_symbols(buffer.data() + i, 1)); QString trace = QString::fromLatin1(strings.data()[0]); // The results of backtrace_symbols looks like this: @@ -1341,7 +1368,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con } if (numberPrinted > 0) - message.append(pattern->backtraceSeparator); + message.append(backtraceSeparator); if (function.isEmpty()) { if (numberPrinted == 0 && context.function) @@ -1355,27 +1382,29 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con } else { if (numberPrinted == 0) continue; - message += pattern->backtraceSeparator + QLatin1String("???"); + message += backtraceSeparator + QLatin1String("???"); } numberPrinted++; } } #endif } else if (token == timeTokenC) { - if (pattern->timeFormat == QLatin1String("process")) { - quint64 ms = pattern->timer.elapsed(); - message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000))); - } else if (pattern->timeFormat == QLatin1String("boot")) { + QString timeFormat = pattern->timeArgs.at(timeArgsIdx); + timeArgsIdx++; + if (timeFormat == QLatin1String("process")) { + quint64 ms = pattern->timer.elapsed(); + message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000))); + } else if (timeFormat == QLatin1String("boot")) { // just print the milliseconds since the elapsed timer reference // like the Linux kernel does QElapsedTimer now; now.start(); uint ms = now.msecsSinceReference(); message.append(QString::asprintf("%6d.%03d", uint(ms / 1000), uint(ms % 1000))); - } else if (pattern->timeFormat.isEmpty()) { - message.append(QDateTime::currentDateTime().toString(Qt::ISODate)); + } else if (timeFormat.isEmpty()) { + message.append(QDateTime::currentDateTime().toString(Qt::ISODate)); } else { - message.append(QDateTime::currentDateTime().toString(pattern->timeFormat)); + message.append(QDateTime::currentDateTime().toString(timeFormat)); } #endif } else if (token == ifCategoryTokenC) { diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index a65a72313f0..618806f3cd6 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -779,6 +779,17 @@ void tst_qmessagehandler::qMessagePattern_data() << true << (QList() << ('/' + QDateTime::currentDateTime().toString("yyyy - MM - d").toUtf8() + "/qDebug")); + QTest::newRow("time-time") << "/%{time yyyy - MM - d}/%{time dd-MM-yy}/%{message}" + << true << (QList() + << ('/' + QDateTime::currentDateTime().toString("yyyy - MM - d").toUtf8() + + '/' + QDateTime::currentDateTime().toString("dd-MM-yy").toUtf8() + + "/qDebug")); + + QTest::newRow("skipped-time-shown-time") + << "/%{if-warning}%{time yyyy - MM - d}%{endif}%{if-debug}%{time dd-MM-yy}%{endif}/%{message}" + << true << (QList() + << ('/' + QDateTime::currentDateTime().toString("dd-MM-yy").toUtf8() + "/qDebug")); + // %{time} should have a padding of 6 so if it takes less than 10 seconds to show // the first message, there should be 5 spaces QTest::newRow("time-process") << "<%{time process}>%{message}" << true << (QList() From f64640f44163d868e3d101c3b0ba41d33147a5be Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Tue, 1 Mar 2016 09:07:11 +0100 Subject: [PATCH 04/31] Allow to style arrows drawn with drawPrimitive in QCommonStyle. Its currently not possible to style the arrows with QCommonStyle because drawPrimitive from QCommonStyle is called instead from the proxy. Change-Id: I910b13df110601cb18578bc16edfa5ddaa17bbd2 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/styles/qcommonstyle.cpp | 6 +-- .../auto/widgets/styles/qstyle/tst_qstyle.cpp | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 748cef20c1e..4b6e3ac5c45 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -1597,7 +1597,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (!hasArrow) { proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm); } else { - drawArrow(this, toolbutton, pr, p, widget); + drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignCenter; } else { @@ -1607,7 +1607,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (!hasArrow) { proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm); } else { - drawArrow(this, toolbutton, pr, p, widget); + drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignLeft | Qt::AlignVCenter; } @@ -1618,7 +1618,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, } else { rect.translate(shiftX, shiftY); if (hasArrow) { - drawArrow(this, toolbutton, rect, p, widget); + drawArrow(proxy(), toolbutton, rect, p, widget); } else { proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm); } diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index 21369d45208..dafa95fb25a 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -131,6 +131,8 @@ private slots: void defaultFont(); void testDrawingShortcuts(); void testFrameOnlyAroundContents(); + + void testProxyCalled(); private: void lineUpLayoutTest(QStyle *); QWidget *testWidget; @@ -808,5 +810,51 @@ void tst_QStyle::testFrameOnlyAroundContents() } +class ProxyTest: public QProxyStyle +{ + Q_OBJECT +public: + ProxyTest(QStyle *style = 0) + :QProxyStyle(style) + , called(false) + {} + + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const Q_DECL_OVERRIDE { + called = true; + return QProxyStyle::drawPrimitive(pe, opt, p, w); + } + mutable bool called; +}; + + +void tst_QStyle::testProxyCalled() +{ + QToolButton b; + b.setArrowType(Qt::DownArrow); + QStyleOptionToolButton opt; + opt.init(&b); + opt.features |= QStyleOptionToolButton::Arrow; + QPixmap surface(QSize(200, 200)); + QPainter painter(&surface); + + QStringList keys = QStyleFactory::keys(); + QVector styles; + styles.reserve(keys.size() + 1); + + styles << new QCommonStyle(); + + Q_FOREACH (const QString &key, keys) { + styles << QStyleFactory::create(key); + } + + Q_FOREACH (QStyle *style, styles) { + ProxyTest testStyle; + testStyle.setBaseStyle(style); + style->drawControl(QStyle::CE_ToolButtonLabel, &opt, &painter, &b); + QVERIFY(testStyle.called); + delete style; + } +} + QTEST_MAIN(tst_QStyle) #include "tst_qstyle.moc" From 95c9a0376e6e27e46ea5ad67349af0089bd2f981 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 21 Mar 2016 19:40:46 +0100 Subject: [PATCH 05/31] QTabBar: enable high dpi moving of a tab Moving tabs of a QTabBar goes through a temporary QWidget that captures a "screenshot" of the tab, and then gets moved around. Unfortunately, that screenshot was not using the devicePixelRatio, resulting in blurry text and icons. For some reason, setting the DPR on the pixmap isn't enough -- that causes it to be drawn twice as big (bug somewhere in Qt styles?). Work around that by not using the palette, but a simple widget which draws the pixmap (which also leads to somehow clean code). Change-Id: Id12f9251625693d108031488ddfab86277128705 Task-number: QTBUG-50898 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qtabbar.cpp | 27 +++++++++++++++++++++------ src/widgets/widgets/qtabbar_p.h | 15 ++++++++++++++- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 41019a1de60..2ac08ffdcdd 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -64,6 +64,23 @@ QT_BEGIN_NAMESPACE +QMovableTabWidget::QMovableTabWidget(QWidget *parent) + : QWidget(parent) +{ +} + +void QMovableTabWidget::setPixmap(const QPixmap &pixmap) +{ + m_pixmap = pixmap; + update(); +} + +void QMovableTabWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + QPainter p(this); + p.drawPixmap(0, 0, m_pixmap); +} inline static bool verticalTabs(QTabBar::Shape shape) { @@ -1906,13 +1923,14 @@ void QTabBarPrivate::setupMovableTab() { Q_Q(QTabBar); if (!movingTab) - movingTab = new QWidget(q); + movingTab = new QMovableTabWidget(q); int taboverlap = q->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0 ,q); QRect grabRect = q->tabRect(pressedIndex); grabRect.adjust(-taboverlap, 0, taboverlap, 0); - QPixmap grabImage(grabRect.size()); + QPixmap grabImage(grabRect.size() * q->devicePixelRatioF()); + grabImage.setDevicePixelRatio(q->devicePixelRatioF()); grabImage.fill(Qt::transparent); QStylePainter p(&grabImage, q); p.initFrom(q); @@ -1923,11 +1941,8 @@ void QTabBarPrivate::setupMovableTab() p.drawControl(QStyle::CE_TabBarTab, tab); p.end(); - QPalette pal; - pal.setBrush(QPalette::All, QPalette::Window, grabImage); - movingTab->setPalette(pal); + movingTab->setPixmap(grabImage); movingTab->setGeometry(grabRect); - movingTab->setAutoFillBackground(true); movingTab->raise(); // Re-arrange widget order to avoid overlaps diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index 38a3c138cc9..e58fde160c2 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -61,6 +61,19 @@ QT_BEGIN_NAMESPACE +class QMovableTabWidget : public QWidget +{ +public: + explicit QMovableTabWidget(QWidget *parent = Q_NULLPTR); + void setPixmap(const QPixmap &pixmap); + +protected: + void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE; + +private: + QPixmap m_pixmap; +}; + class QTabBarPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QTabBar) @@ -201,7 +214,7 @@ public: int switchTabCurrentIndex; int switchTabTimerId; - QWidget *movingTab; + QMovableTabWidget *movingTab; #ifdef Q_DEAD_CODE_FROM_QT4_MAC int previousPressedIndex; #endif From 215a04d51ac7e609588fc7b7f0d21aedf6140a87 Mon Sep 17 00:00:00 2001 From: Lorenz Haas Date: Fri, 25 Mar 2016 12:19:03 +0100 Subject: [PATCH 06/31] Fix debug message to match the method's name Change-Id: Ieaf7366663beeecec3240353d045fb19e2ae99ee Reviewed-by: Louai Al-Khanji --- src/corelib/io/qprocess_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 18d203404dc..df13a2533e1 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -640,7 +640,7 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) void QProcessPrivate::terminateProcess() { #if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::killProcess()"); + qDebug("QProcessPrivate::terminateProcess()"); #endif if (pid) ::kill(pid_t(pid), SIGTERM); From 717724b17ac8e12ab06fe3820c0ac6349e971814 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 29 Feb 2016 14:32:11 +0100 Subject: [PATCH 07/31] Purge sRGB chunks from PNGs in tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subjects each *.png file that matched grep -law "sRGB" to: pngcrush -ow -brute -rem allb -reduce (Two needed -force but did get smaller.) Change-Id: Ia030f0bc1d3617ba716bcc26677ff919ef58423c Reviewed-by: Topi Reiniö --- .../convertFromToHICON/icon_8bpp_16x16.png | Bin 1454 -> 1335 bytes .../convertFromToHICON/icon_8bpp_32x32.png | Bin 1721 -> 1577 bytes .../convertFromToHICON/icon_8bpp_48x48.png | Bin 1967 -> 1778 bytes .../qpixmap/loadFromData/designer_argb32.png | Bin 4189 -> 2874 bytes .../designer_indexed8_no_alpha.png | Bin 2431 -> 2365 bytes .../designer_indexed8_with_alpha.png | Bin 1405 -> 1339 bytes tests/auto/other/lancelot/images/alpha2x2.png | Bin 169 -> 78 bytes tests/auto/other/lancelot/images/solid2x2.png | Bin 169 -> 75 bytes .../widgets/effects/qpixmapfilter/noise.png | Bin 7517 -> 6305 bytes .../widgets/qcombobox/qtlogoinverted.png | Bin 2827 -> 2297 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_16x16.png index e9a995e19ebf47682c9c2899783920ba04e0cce4..03b1a65f7084c79cb0e6d2692787381e89d93566 100644 GIT binary patch delta 261 zcmV+g0s8)~3%3f8Bn<>-K}|sb0I`n?{9y&LY8wQ9)=5M`R2b7^`2U|-P+wP9_dgUc z{AXgZ)Ya8e)By_Ws)Ga=ISmb@G+Y&x3=~v=3V|xvO+~y5OVeD0gWZ%N0_OaAIgXjh zJegtgU;$1A+lqL$$by85d=EvifLK69EVo~US4Fh38dyLyydp-(r^3EGL>8h&!nY!h z%fG^Gt~?ZKhNewLB5PEMbwwaV1-k`bR*_Ri5^r(3yCTFLk`B2Qsb=CqvCgVs0Yd{B ztFjamZ3Ssnh!!JVeSwH004R> z004l5008;`004mK004C`008P>0026e000+ooVrmwu`wG2e+h6%S#tmY4#NNd4#NS* zZ>VGd000}3hJu=|IhHBk<-vXO2buA$v{B`s1T@v-BiT8ur$p@ zIM_`YB4Ey+f0yH!naq@i@M8hj$ zgnTOO%R^)#S|ofc;<)@P?8-x-W@y?}B(g@8SXTr>RIpp{WfeJPB=HufyMqm7HFNtaWP2)tE4>I2(AAffQ`H0enBo6_4pW5Z b|NjR7jX+^hd0ltL00000NkvXXu0mjfBAu3E diff --git a/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png b/tests/auto/gui/image/qpixmap/convertFromToHICON/icon_8bpp_32x32.png index 41ef57f94d8154609be3d9a0f4f7b90e03e8e6d1..0ef47c556d772cc167d75c87333999302cbf6505 100644 GIT binary patch delta 506 zcmV-K}|sb0I`n?{9y&LY8nK80mw;2K~y-6ZIfwR(?Ar3QLq`H z6%nfCiheFoOkZr9Q-Xn>!) z@v-%PXS=rGNLe1cre#pM!4`tpU3C02(^wpd0fK!3wjWNl(4M)<-r>0u1ypv3PCv2J z)4)qBvyLT;M*u%P2mG#xd_S;yuK5p}Ul!a*2KF9kNKxo*pfSE*%#srZMCvQBIV#HR zJ8+ALcE{rXf+g!p9GYDgvV+GoQ2kfYiu0=^<ND_53eJ8|kqLleZ-LhJ@}<5ecJt?Tz#o{R*5`RX18ik)0?#Zrdd0=eUuu3h zeIHl}#=bf`&!gMyeM6gk`k;+=#p-WTx@9{8cvhx%xNeo5{I>R?8qFY;dEqr3Tn`Lk z<2x?5OL5D2>huIqALjd>(=A7Y*|$T}dR#p6>{!gzYJhsc3+GV39Jjsna004R> z004l5008;`004mK004C`008P>0026e000+ooVrmwu`wD1e*g(^NLh0L01m?d01m?e z$8V@)0000ObVXQnQ*UN;cVTj608n9RZgehAMN}YmGcGeWspsM)0005zNklsp#|1>zkIkCfoZ{KFRkz z^SoVul^x4ie}XJL8`c%QOR0d!bV32W$F0P>ff3N#lWMu^C-PQ6clzl1qF45~hG>8+ zS=HG)V`GZo;}Mtyg8Y?_jb8_A3q>I+6PM$H|EG}o;Rci)E*66m(^x!jMBwZbaPV-d zf#%F5_72Y}P%?$gog(iiPG%Z-X=it^WP2JAWF7!Nf2+JO0IZ&_|H0mu1y_r}-UBtk zOMNxeu7|}eQIb{{JhcJrjq?io3S1*%`O#g<(E{A`F0f5wV(Y-|Ve&U>D5bv4hv`6 zBLqWJf7JTCSI7eUxvRi4o92{g(?6H}P0f#F?g1-m?5lJ0+8l)JdqY3@^nMe~sy$Gr zaLbOS2j9-p1fuVjxtp8YA7=FkLRx2EljDvOOi*+^r)(%n_;T-K}|sb0I`n?{9y&LY8nK80+C5XK~zY`rI!6$(m))*t<(|< ze8Ef&^93O^2V*kYwVhq0W?5FKL7VnTds`8v1wkPqSp(2NTE>Q46lFqa z!RcHkC0hY#VyKE6vKLbT^etn&8?gYixt>q#dc<+V{fJR2o=)unm)3?5m zwU&h8p1d`nF7~d|^R*?JpeN)hD@+a6FfPr1FT{8NoV{_#Y!?6wUOymDdC%9%1;*ct zg>8ugpoxJa!*rm{GjA%Mdd!LfPs82uOS<`ym~2>gGInSOXamb^^Fx$udROS<`!TAh zoGWBv93bI&!GLX&6>#u5v#xgyTRL4265gVK@4f-N!j@qrz(x}=&i=^10)-Ahn@P5R z8i4FsYj@fXP@BSPhB#{rn0Dg~-S@6C))qki;ooLzm;pFT*=v|`RVYwu04MLTlHM2V6=w#nQay}u zn}BSl-$A{m(F0$Ny(x=a0EXC?P1z@Z{V(BLIVMI{vl72Ap+NsmqsxFeaZ3%pPN!4x zsAcDy^RMR5$?>CY(P&>#iAE*Gy0>a@<{FLYuce6Wtb40*_OtMAGO0Lg_sD;bWeDDl zIs>%Dn?@mhi*QCHZvw&a(A(q7HVuj;0AM`yW;4Cn;)AZ+%s5RE#hA<+*$##*qRySu re8A==&ZZkRsbSH8JeWeJ4*wU-k00000NkvXXu0mjfH3C@m delta 899 zcmV-}1AP4Q4X+Q7Bt`*qQb$4nuFf3k00004XF*Lt006O%3;baP0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmwu`wD1e*g(^NLh0L01m?d01m?e z$8V@)0000ObVXQnQ*UN;cVTj608n9RZgehAMN}YmGcGeWspsM)0008qNkl_Z{mj_?3= zI`Fo3^y}n%Wi3Xvs91<4O^0Lg0SEjwjmhbD3J4`Me^o4GbpzWqsN+KoeLW17goLo~ ziKdlfOhp@@M0-Ba&39I|$XFB}h`p~J0CmKFOcrj=O5#zJ%HM2kQaJa$ol4D z3eZECZ3vTtO-%I&q_pQL z1#)mJ@Ze)=UGFpawQ<@AlD0+w-)#oGfM1)i0sw~u!hkU{-TYUe)B&L9W;V%D14?;_ zhZd(Dd_b}(ta^wyoJ=wt)e7V`dza~vI09;5fA}YjrGWH^9cP_2OuFg>*!gppz9B~d z^5-J~8lt4%)~ev4P75+k>$Z%O`{`vm$;Kaz_>W+=9`injp?)uTp9|oL8x2BK<3`5m zfvY$6c$W{sNwDj;YvinSr4+!HWU~Rh{-Wq4!7l7?jlhZIIK!>I5 Z?{j^n2!nfu`da`1002ovPDHLkV1j;{i_!o9 diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_argb32.png index 55d8247cfcfc3470a7e8a85e08ce92288022d755..a35316b9c9e95d99f32b5e428f77bcb6fb66f9ea 100644 GIT binary patch delta 2868 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 HaE<#nwN5gC literal 4189 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 nA^-v+00JTa0wMr{9K`%O;k diff --git a/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png b/tests/auto/gui/image/qpixmap/loadFromData/designer_indexed8_no_alpha.png index 28cd2f06d18121a1246babe36eda8a74e531d755..3dd2115df1b79ca0df355171005745a5a29c9fe4 100644 GIT binary patch delta 15 Xcmew_v{z_?@ delta 76 zcmdnZ^_Odc3KwH>kh>GZx^prwCo0w%GcYE3ySp%Su*!NcFfecyctjR6Fz{Xn;!egi ef!B+Gg6t)pzOL-I*hCnuj1GTu_1`#m9t!|P4HfSI diff --git a/tests/auto/other/lancelot/images/alpha2x2.png b/tests/auto/other/lancelot/images/alpha2x2.png index 67ecc04286257d1968beffea1f6da60590efd156..8e99feb4cc6450bd140e55d2173b84b5226fd131 100644 GIT binary patch delta 48 zcmZ3<=r=({OVrcFF@z&JIpN3o5C83%C!{c3=HX$mzr^~xr1irW1|aZs^>bP0l+XkK Dvb7QG delta 140 zcmeZU$v8o!p0PN{-HBn{IhmIX3=EtF9+AZi4BWyX%*Zfnjs#GUy~NYkmHh@cH;0NW z-_$r$ppayVYeb22er|4RUI~M9QEFmIYKlU6W=V#EyQgnJcq5-UP?4CYi(?4Kb=HH7 lj6hz4z<+=7B^<2G_Lo?H`^|j)04T=b>B{Ekvd$@?2>`}^C2#-$ diff --git a/tests/auto/other/lancelot/images/solid2x2.png b/tests/auto/other/lancelot/images/solid2x2.png index ad67cd3e12096637d9839a872c370f26691f7c6c..f34562f964e55ff585d64d0845890c7b4db2d1ec 100644 GIT binary patch delta 45 zcmZ3<=siJ2UC7hLF@z&JIpGI?i^7NdCr)rMNGmW;dAq^Tivb8cUHx3vIVCg!09{ZI A82|tP delta 140 zcmeZX$v8o!p0PN{-HBn{IhmIX3=EtF9+AZi4BWyX%*Zfnjs#GUy~NYkmHh@cH;1y; z&&=GvKq1Kz*N775{M_8syb=cIqSVBa)D(sC%#sWRcTeAd@J2pypdv9(7sn8e>&Xc} l&VQKS2m}xJPn;;oAg#bWB|()(2dIL<)0NH7Wt~$(69C8!DOvyk diff --git a/tests/auto/widgets/effects/qpixmapfilter/noise.png b/tests/auto/widgets/effects/qpixmapfilter/noise.png index 1bebaf528e39eb43f1e2b445378fc7c796454ac8..c8433602b2fbb6092ec0830bb47cbafec243816f 100644 GIT binary patch literal 6305 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 delta 2820 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 W)OHBV63gNM0000 Date: Wed, 23 Mar 2016 14:44:31 +0100 Subject: [PATCH 08/31] QPlainTextEdit: Take vertical offset into account when answering input method queries. Determine offset point to similar to QTextEdit::inputMethodQuery() and add an autotest. Task-number: QTBUG-51923 Change-Id: I8232eb348063e2cd95d0632fe74a6eb30c897eda Reviewed-by: Marc Mutz --- src/widgets/widgets/qplaintextedit.cpp | 10 +++++----- .../widgets/qplaintextedit/tst_qplaintextedit.cpp | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 91788a33834..bb933362dab 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2198,15 +2198,15 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVarian break; default: v = d->control->inputMethodQuery(property, argument); - const QPoint offset(-d->horizontalOffset(), -0); + const QPointF offset = contentOffset(); if (v.type() == QVariant::RectF) - v = v.toRectF().toRect().translated(offset); + v = v.toRectF().translated(offset); else if (v.type() == QVariant::PointF) - v = v.toPointF().toPoint() + offset; + v = v.toPointF() + offset; else if (v.type() == QVariant::Rect) - v = v.toRect().translated(offset); + v = v.toRect().translated(offset.toPoint()); else if (v.type() == QVariant::Point) - v = v.toPoint() + offset; + v = v.toPoint() + offset.toPoint(); } return v; diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index 21452600130..d466489acb0 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -154,6 +154,7 @@ private slots: #ifndef QT_NO_CONTEXTMENU void contextMenu(); #endif + void inputMethodCursorRect(); private: void createSelection(); @@ -1727,5 +1728,17 @@ void tst_QPlainTextEdit::contextMenu() } #endif // QT_NO_CONTEXTMENU +// QTBUG-51923: Verify that the cursor rectangle returned by the input +// method query correctly reflects the viewport offset. +void tst_QPlainTextEdit::inputMethodCursorRect() +{ + ed->setPlainText("Line1\nLine2Line3\nLine3"); + ed->moveCursor(QTextCursor::End); + const QRectF cursorRect = ed->cursorRect(); + const QVariant cursorRectV = ed->inputMethodQuery(Qt::ImCursorRectangle); + QCOMPARE(cursorRectV.type(), QVariant::RectF); + QCOMPARE(cursorRectV.toRect(), cursorRect.toRect()); +} + QTEST_MAIN(tst_QPlainTextEdit) #include "tst_qplaintextedit.moc" From a58cf4004404845553a732338539ab3dfdbb8143 Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Tue, 29 Mar 2016 11:03:46 +0200 Subject: [PATCH 09/31] wince: Disable Native Filedialogs for WEC2013 Qt crashes when opening a native file dialog. Disable this feature to fix this issue. Change-Id: I1ee17d858238c2531964a63ddbe3e11c5a85483c Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 993dff51290..6e8df340df2 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -2173,6 +2173,7 @@ namespace QWindowsDialogs { // QWindowsDialogHelperBase creation functions bool useHelper(QPlatformTheme::DialogType type) { +#if !defined(_WIN32_WCE) || _WIN32_WCE < 0x800 if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs) return false; switch (type) { @@ -2191,10 +2192,14 @@ bool useHelper(QPlatformTheme::DialogType type) break; } return false; +#else + return false; +#endif // !defined(_WIN32_WCE) || _WIN32_WCE < 0x800 } QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) { +#if !defined(_WIN32_WCE) || _WIN32_WCE < 0x800 if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs) return 0; switch (type) { @@ -2222,6 +2227,9 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) break; } return 0; +#else + return 0; +#endif // !defined(_WIN32_WCE) || _WIN32_WCE < 0x800 } } // namespace QWindowsDialogs From 88fae806a85ea1bcff2cecbd86f63f396631c120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Fri, 25 Mar 2016 02:48:14 +0100 Subject: [PATCH 10/31] QtWidgets: Add autotests for Qt::WA_OutsideWSRange flag Task-number: QTBUG-48321 Task-number: QTBUG-49445 Task-number: QTBUG-51788 Change-Id: I6c04919ff788cad684df69d0aee73d86fd985bb9 Reviewed-by: Dmitry Shachnev Reviewed-by: Ulf Hermann --- .../widgets/kernel/qwidget/tst_qwidget.cpp | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index fb3e644a5c6..1c2a74109f5 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -461,6 +461,8 @@ private slots: void qmlSetParentHelper(); + void testForOutsideWSRangeFlag(); + private: bool ensureScreenSize(int width, int height); QWidget *testWidget; @@ -10549,5 +10551,69 @@ void tst_QWidget::qmlSetParentHelper() #endif } +void tst_QWidget::testForOutsideWSRangeFlag() +{ + // QTBUG-49445 + { + QWidget widget; + widget.resize(0, 0); + widget.show(); + QTest::qWait(100); // Wait for a while... + QVERIFY(!widget.windowHandle()->isExposed()); // The window should not be visible + QVERIFY(widget.isVisible()); // The widget should be in visible state + } + { + QWidget widget; + + QWidget native(&widget); + native.setAttribute(Qt::WA_NativeWindow); + native.resize(0, 0); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + QVERIFY(!native.windowHandle()->isExposed()); + } + { + QWidget widget; + QWidget native(&widget); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + QVERIFY(native.isVisible()); + + native.resize(0, 0); + native.setAttribute(Qt::WA_NativeWindow); + QTest::qWait(100); // Wait for a while... + QVERIFY(!native.windowHandle()->isExposed()); + } + + // QTBUG-48321 + { + QWidget widget; + + QWidget native(&widget); + native.setAttribute(Qt::WA_NativeWindow); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + QVERIFY(native.windowHandle()->isExposed()); + + native.resize(0, 0); + QTest::qWait(100); // Wait for a while... + QVERIFY(!native.windowHandle()->isExposed()); + } + + // QTBUG-51788 + { + QWidget widget; + widget.setLayout(new QGridLayout); + widget.layout()->addWidget(new QLineEdit); + widget.resize(0, 0); + widget.show(); + // The layout should change the size, so the widget must be visible! + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + } +} + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" From 72ff2a2f0db1e728d2a53f546021018e076bbfb5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 21 Mar 2016 14:16:09 -0700 Subject: [PATCH 11/31] QMacStyle: Return a guess for SE_ProgressBarGroove's rect QMacStyle doesn't know how to accurately compute SE_ProgressBarGroove But, since we only need the progress bar's main dimension, its rect is good enough for QProgressBarPrivate::repaintRequired(). Change-Id: I81e936003b847cc9cc0ddf4fbfc05ddc1c9f6625 Task-number: QTBUG-51120 Reviewed-by: Timur Pocheptsov --- src/widgets/styles/qmacstyle_mac.mm | 3 +++ src/widgets/widgets/qprogressbar.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 092cf4d5438..9f241b6e67a 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -4978,6 +4978,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, break; } case SE_ProgressBarGroove: + // Wrong in the secondary dimension, but accurate enough in the main dimension. + rect = opt->rect; + break; case SE_ProgressBarLabel: break; case SE_ProgressBarContents: diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index adb4d0369b3..c1c08d9ec76 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -155,7 +155,7 @@ bool QProgressBarPrivate::repaintRequired() const QStyleOptionProgressBar opt; q->initStyleOption(&opt); int cw = q->style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &opt, q); - QRect groove = q->style()->subElementRect(QStyle::SE_ProgressBarGroove, &opt, q); + QRect groove = q->style()->subElementRect(QStyle::SE_ProgressBarGroove, &opt, q); // This expression is basically // (valueDifference / (maximum - minimum) > cw / groove.width()) // transformed to avoid integer division. From c35795b413c6aedd6b02f03fdcaa5fb4888084d5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 22 Mar 2016 14:16:23 -0700 Subject: [PATCH 12/31] QFontEngine: Add handle() function Both QFont::handle() and QFont::freetypeFace() used to be available in Qt 4 but were removed in Qt 5. There's currently no API to get access to the native font handle, which the font engine holds in a way or another. Similar to the way it was in Qt 4, the actual handle type depends on the font engine currently in use. The types map as follows: Font Engine Native Handle ------------------------------------ DirectWrite IDWriteFontFace * Freetype FT_Face Mac CTFontRef Win HFONT All other font engines return a null handle. Change-Id: I3bea8259ac1378fd24079723aa6603bf9e74834c Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine.cpp | 5 +++++ src/gui/text/qfontengine_ft.cpp | 5 +++++ src/gui/text/qfontengine_ft_p.h | 1 + src/gui/text/qfontengine_p.h | 2 ++ .../fontdatabases/mac/qfontengine_coretext.mm | 5 +++++ .../fontdatabases/mac/qfontengine_coretext_p.h | 1 + src/plugins/platforms/windows/qwindowsfontengine.cpp | 5 +++++ src/plugins/platforms/windows/qwindowsfontengine.h | 1 + .../platforms/windows/qwindowsfontenginedirectwrite.cpp | 5 +++++ .../platforms/windows/qwindowsfontenginedirectwrite.h | 1 + 10 files changed, 31 insertions(+) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 03ad6a24e97..39348a52b0c 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1229,6 +1229,11 @@ int QFontEngine::glyphCount() const return count; } +Qt::HANDLE QFontEngine::handle() const +{ + return Q_NULLPTR; +} + const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize) { const uchar *header = table; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 8fbeff35963..ebfd2a81826 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -2005,6 +2005,11 @@ QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const } } +Qt::HANDLE QFontEngineFT::handle() const +{ + return non_locked_face(); +} + QT_END_NAMESPACE #endif // QT_NO_FREETYPE diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 6f05645a3fa..a1bd21dab97 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -283,6 +283,7 @@ private: void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; + Qt::HANDLE handle() const Q_DECL_OVERRIDE; bool initFromFontEngine(const QFontEngineFT *fontEngine); HintStyle defaultHintStyle() const { return default_hint_style; } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index be9eaa50206..7ddc5c0c328 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -229,6 +229,8 @@ public: virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return 0; } + virtual Qt::HANDLE handle() const; + void *harfbuzzFont() const; void *harfbuzzFace() const; bool supportsScript(QChar::Script script) const; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 732aead62a4..bcb57368f5c 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -738,6 +738,11 @@ QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const return new QCoreTextFontEngine(cgFont, newFontDef); } +Qt::HANDLE QCoreTextFontEngine::handle() const +{ + return (Qt::HANDLE)ctfont; +} + bool QCoreTextFontEngine::supportsTransformation(const QTransform &transform) const { if (transform.type() < QTransform::TxScale) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 1c33ae7d84b..746c9051a02 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -101,6 +101,7 @@ public: bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; + Qt::HANDLE handle() const Q_DECL_OVERRIDE; int glyphMargin(QFontEngine::GlyphFormat format) Q_DECL_OVERRIDE { Q_UNUSED(format); return 0; } QFontEngine::Properties properties() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index a97062273f4..660c1380972 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1256,6 +1256,11 @@ QFontEngine *QWindowsFontEngine::cloneWithSize(qreal pixelSize) const return fontEngine; } +Qt::HANDLE QWindowsFontEngine::handle() const +{ + return hfont; +} + void QWindowsFontEngine::initFontInfo(const QFontDef &request, int dpi) { diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 47891a2830e..6eaa9024198 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -108,6 +108,7 @@ public: glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; + Qt::HANDLE handle() const Q_DECL_OVERRIDE; bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; #ifndef Q_CC_MINGW diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 5b2e220fd63..c5831dd2e1d 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -639,6 +639,11 @@ QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const return fontEngine; } +Qt::HANDLE QWindowsFontEngineDirectWrite::handle() const +{ + return m_directWriteFontFace; +} + void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, int dpi) { diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index 91de871311b..4d9664b3918 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -92,6 +92,7 @@ public: QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; + Qt::HANDLE handle() const Q_DECL_OVERRIDE; const QSharedPointer &fontEngineData() const { return m_fontEngineData; } From 086317d72a6b6964bf26df4ebedcb6d321b2d56b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 23 Mar 2016 14:48:09 +0100 Subject: [PATCH 13/31] QTextEdit::inputMethodQuery(): Preserve types when applying offset. The old code converted QRectF into QRect when applying the offset. Change the offset point to QPointF and change the conversions accordingly. Add an autotest similar to that of QPlainTextEdit. This minimizes rounding errors and prevents conversions since the input method logic mostly uses qreal. Task-number: QTBUG-51923 Change-Id: I0c2f80ccae028d8bbbb97ec603f8782f69959c76 Reviewed-by: Marc Mutz --- src/widgets/widgets/qtextedit.cpp | 10 +++++----- .../widgets/widgets/qtextedit/tst_qtextedit.cpp | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 7439005b929..95f0bc7c59c 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1726,15 +1726,15 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume break; default: v = d->control->inputMethodQuery(query, argument); - const QPoint offset(-d->horizontalOffset(), -d->verticalOffset()); + const QPointF offset(-d->horizontalOffset(), -d->verticalOffset()); if (v.type() == QVariant::RectF) - v = v.toRectF().toRect().translated(offset); + v = v.toRectF().translated(offset); else if (v.type() == QVariant::PointF) - v = v.toPointF().toPoint() + offset; + v = v.toPointF() + offset; else if (v.type() == QVariant::Rect) - v = v.toRect().translated(offset); + v = v.toRect().translated(offset.toPoint()); else if (v.type() == QVariant::Point) - v = v.toPoint() + offset; + v = v.toPoint() + offset.toPoint(); } return v; diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index 0cc812cbca4..b81e4df1230 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -191,6 +191,7 @@ private slots: void inputMethodQuery(); void inputMethodQueryImHints_data(); void inputMethodQueryImHints(); + void inputMethodCursorRect(); void highlightLongLine(); @@ -2473,6 +2474,18 @@ void tst_QTextEdit::inputMethodQueryImHints() QCOMPARE(static_cast(value.toInt()), hints); } +// QTBUG-51923: Verify that the cursor rectangle returned by the input +// method query correctly reflects the viewport offset. +void tst_QTextEdit::inputMethodCursorRect() +{ + ed->setPlainText("Line1\nLine2Line3\nLine3"); + ed->moveCursor(QTextCursor::End); + const QRectF cursorRect = ed->cursorRect(); + const QVariant cursorRectV = ed->inputMethodQuery(Qt::ImCursorRectangle); + QCOMPARE(cursorRectV.type(), QVariant::RectF); + QCOMPARE(cursorRectV.toRect(), cursorRect.toRect()); +} + void tst_QTextEdit::highlightLongLine() { QTextEdit edit; From 8875e9fe825f3f4d39a25fe29006245f4801e595 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 24 Mar 2016 14:47:53 +0100 Subject: [PATCH 14/31] Refactor methods QTextEdit/QPlainTextEdit::inputMethodQuery(). Replace if / else if chain by switch() and return the value instead of reassigning it. Change-Id: Ib87c54bbf9911a58d3ae764b71f19f33d59590ce Reviewed-by: Marc Mutz --- src/widgets/widgets/qplaintextedit.cpp | 32 ++++++++++++-------------- src/widgets/widgets/qtextedit.cpp | 30 +++++++++++------------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index bb933362dab..8a64e3a3970 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2188,27 +2188,25 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const /*!\internal */ -QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const +QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const { Q_D(const QPlainTextEdit); - QVariant v; - switch (property) { - case Qt::ImHints: - v = QWidget::inputMethodQuery(property); - break; + if (query == Qt::ImHints) + return QWidget::inputMethodQuery(query); + const QVariant v = d->control->inputMethodQuery(query, argument); + const QPointF offset = contentOffset(); + switch (v.type()) { + case QVariant::RectF: + return v.toRectF().translated(offset); + case QVariant::PointF: + return v.toPointF() + offset; + case QVariant::Rect: + return v.toRect().translated(offset.toPoint()); + case QVariant::Point: + return v.toPoint() + offset.toPoint(); default: - v = d->control->inputMethodQuery(property, argument); - const QPointF offset = contentOffset(); - if (v.type() == QVariant::RectF) - v = v.toRectF().translated(offset); - else if (v.type() == QVariant::PointF) - v = v.toPointF() + offset; - else if (v.type() == QVariant::Rect) - v = v.toRect().translated(offset.toPoint()); - else if (v.type() == QVariant::Point) - v = v.toPoint() + offset.toPoint(); + break; } - return v; } diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 95f0bc7c59c..c4503538c63 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1719,24 +1719,22 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const { Q_D(const QTextEdit); - QVariant v; - switch (query) { - case Qt::ImHints: - v = QWidget::inputMethodQuery(query); - break; + if (query == Qt::ImHints) + return QWidget::inputMethodQuery(query); + const QVariant v = d->control->inputMethodQuery(query, argument); + const QPointF offset(-d->horizontalOffset(), -d->verticalOffset()); + switch (v.type()) { + case QVariant::RectF: + return v.toRectF().translated(offset); + case QVariant::PointF: + return v.toPointF() + offset; + case QVariant::Rect: + return v.toRect().translated(offset.toPoint()); + case QVariant::Point: + return v.toPoint() + offset.toPoint(); default: - v = d->control->inputMethodQuery(query, argument); - const QPointF offset(-d->horizontalOffset(), -d->verticalOffset()); - if (v.type() == QVariant::RectF) - v = v.toRectF().translated(offset); - else if (v.type() == QVariant::PointF) - v = v.toPointF() + offset; - else if (v.type() == QVariant::Rect) - v = v.toRect().translated(offset.toPoint()); - else if (v.type() == QVariant::Point) - v = v.toPoint() + offset.toPoint(); + break; } - return v; } From 9bc352e38d6b03fbb12a359a7bdfc8d22aa7e192 Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Wed, 23 Mar 2016 19:26:02 +0100 Subject: [PATCH 15/31] Enable cmake auto tests for -no-gui This change disables tests which require QtGui. Change-Id: Ib647afd086f54536054cb4c0cde5696d762ee8c4 Reviewed-by: Stephen Kelly Reviewed-by: Kevin Funk --- src/corelib/Qt5CTestMacros.cmake | 3 +++ tests/auto/auto.pro | 2 +- tests/auto/cmake/CMakeLists.txt | 7 ++++++- tests/auto/cmake/test_testlib_definitions/CMakeLists.txt | 4 +++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/corelib/Qt5CTestMacros.cmake b/src/corelib/Qt5CTestMacros.cmake index 6451f65b55b..a1044fa89ad 100644 --- a/src/corelib/Qt5CTestMacros.cmake +++ b/src/corelib/Qt5CTestMacros.cmake @@ -39,6 +39,9 @@ if (CMAKE_VERBOSE_MAKEFILE) list(APPEND BUILD_OPTIONS_LIST "-DCMAKE_VERBOSE_MAKEFILE=1") endif() +if (NO_GUI) + list(APPEND BUILD_OPTIONS_LIST "-DNO_GUI=True") +endif() if (NO_WIDGETS) list(APPEND BUILD_OPTIONS_LIST "-DNO_WIDGETS=True") endif() diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index cc916edbad9..f7c38e4422b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -24,7 +24,7 @@ ios: SUBDIRS = corelib gui wince: SUBDIRS -= printsupport cross_compile: SUBDIRS -= tools !qtHaveModule(opengl): SUBDIRS -= opengl -!qtHaveModule(gui): SUBDIRS -= gui cmake installed_cmake +!qtHaveModule(gui): SUBDIRS -= gui !qtHaveModule(widgets): SUBDIRS -= widgets !qtHaveModule(printsupport): SUBDIRS -= printsupport !qtHaveModule(concurrent): SUBDIRS -= concurrent diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 1abbef0d68d..c780096854b 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -116,13 +116,18 @@ endif() set(qt_module_includes Core QObject - Gui QImage Network QHostInfo Sql QSqlError Test QTestEventList Xml QDomDocument ) +if (NOT NO_GUI) + list(APPEND qt_module_includes + Gui QImage + ) +endif() + if (NOT NO_WIDGETS) list(APPEND qt_module_includes Widgets QWidget diff --git a/tests/auto/cmake/test_testlib_definitions/CMakeLists.txt b/tests/auto/cmake/test_testlib_definitions/CMakeLists.txt index cc54bf5bc39..6fe7e56d240 100644 --- a/tests/auto/cmake/test_testlib_definitions/CMakeLists.txt +++ b/tests/auto/cmake/test_testlib_definitions/CMakeLists.txt @@ -34,7 +34,9 @@ macro(test_testlib_project _module) endmacro() add_subdirectory(core_only) -add_subdirectory(gui) +if(NOT NO_GUI) + add_subdirectory(gui) +endif() if(NOT NO_WIDGETS) add_subdirectory(widgets) endif() From adc4e000fc1ffe1acba47ff932c092678a54b9f2 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Fri, 22 Jan 2016 14:56:18 +0300 Subject: [PATCH 16/31] QFontEngineFT: Apply hinting for non-scaled rotated glyphs Scaled hinted glyphs looks ugly, see QTBUG-24846. It was fixed in 6da6845f078e419ccb555fe1dd152e0ba82a7e88 by disabling hinting for them. But at the same time that commit also disabled hinting for glyphs with the most common transformation - rotating without scaling. Detect this type of transformation and don't disable hinting for it. Change-Id: I0e69a2b60e7e4bc24e9efc4fdedb984df07ad15c Task-number: QTBUG-50574 Reviewed-by: Friedemann Kleint Reviewed-by: Konstantin Ritt Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine_ft.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index ebfd2a81826..361702681f9 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1780,6 +1780,12 @@ void QFontEngineFT::unlockAlphaMapForGlyph() QFontEngine::unlockAlphaMapForGlyph(); } +static inline bool is2dRotation(const QTransform &t) +{ + return qFuzzyCompare(t.m11(), t.m22()) && qFuzzyCompare(t.m12(), -t.m21()) + && qFuzzyCompare(t.m11()*t.m22() - t.m12()*t.m21(), 1.0); +} + QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, @@ -1793,7 +1799,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) { QScopedValueRollback saved_default_hint_style(default_hint_style); - if (t.type() >= QTransform::TxScale) + if (t.type() >= QTransform::TxScale && !is2dRotation(t)) default_hint_style = HintNone; // disable hinting if the glyphs are transformed lockFace(); From 87715cc4917e0edcc1090658ea09be508f47f3b7 Mon Sep 17 00:00:00 2001 From: Timo Jyrinki Date: Wed, 23 Mar 2016 09:41:50 +0000 Subject: [PATCH 17/31] Blacklist Mali-T760/Mali-T720 from supporting BGRA. Extend the blacklist with Mali-T760 and Mali-T720 as found on Meizu Pro 5 and Bq Aquaris M10 Ubuntu Editions. Reading from FBO like taking screenshots does not produce correct result otherwise. Initially reported at: https://launchpad.net/bugs/1557915 and https://launchpad.net/bugs/1559906 Change-Id: Ic875bd083277bf933863a3a50f8e874dd6e04365 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglframebufferobject.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 5184283a317..0e1074f8d4a 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -1281,9 +1281,13 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ const char *renderer = reinterpret_cast(funcs->glGetString(GL_RENDERER)); const char *ver = reinterpret_cast(funcs->glGetString(GL_VERSION)); - // Blacklist PowerVR Rogue G6200 as it has problems with its BGRA support. + // Blacklist GPU chipsets that have problems with their BGRA support. const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0 - && ::strstr(ver, "1.3") != 0); + && ::strstr(ver, "1.3") != 0) || + (qstrcmp(renderer, "Mali-T760") == 0 + && ::strstr(ver, "3.1") != 0) || + (qstrcmp(renderer, "Mali-T720") == 0 + && ::strstr(ver, "3.1") != 0); const bool supports_bgra = has_bgra_ext && !blackListed; From f5b5e1f76dc1d317ac235007eb81d0cc01fa66d1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Mar 2016 16:53:18 +0100 Subject: [PATCH 18/31] Windows QPA: Scale the cursor rectangle of the input method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the position of the input method window when High DPI scaling is active. Task-number: QTBUG-51923 Change-Id: I35ee4bcf320f8c2b7d5cc7fb8484348b18e1d833 Reviewed-by: Morten Johan Sørvig --- .../platforms/windows/qwindowsinputcontext.cpp | 17 ++++++++++++----- .../platforms/windows/qwindowsinputcontext.h | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index d3299db460d..1faa00d0955 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -48,6 +48,8 @@ #include #include +#include + #include QT_BEGIN_NAMESPACE @@ -159,7 +161,8 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp HIMC QWindowsInputContext::m_defaultContext = 0; QWindowsInputContext::CompositionContext::CompositionContext() : - hwnd(0), haveCaret(false), position(0), isComposing(false) + hwnd(0), haveCaret(false), position(0), isComposing(false), + factor(1) { } @@ -270,9 +273,12 @@ void QWindowsInputContext::cursorRectChanged() if (!m_compositionContext.hwnd) return; const QInputMethod *inputMethod = QGuiApplication::inputMethod(); - const QRect cursorRectangle = inputMethod->cursorRectangle().toRect(); - if (!cursorRectangle.isValid()) + const QRectF cursorRectangleF = inputMethod->cursorRectangle(); + if (!cursorRectangleF.isValid()) return; + const QRect cursorRectangle = + QRectF(cursorRectangleF.topLeft() * m_compositionContext.factor, + cursorRectangleF.size() * m_compositionContext.factor).toRect(); qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle; @@ -390,7 +396,7 @@ bool QWindowsInputContext::startComposition(HWND hwnd) qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window << "language=" << m_languageId; if (!fo || QWindowsWindow::handleOf(window) != hwnd) return false; - initContext(hwnd, fo); + initContext(hwnd, QHighDpiScaling::factor(window), fo); startContextComposition(); return true; } @@ -522,12 +528,13 @@ bool QWindowsInputContext::endComposition(HWND hwnd) return true; } -void QWindowsInputContext::initContext(HWND hwnd, QObject *focusObject) +void QWindowsInputContext::initContext(HWND hwnd, qreal factor, QObject *focusObject) { if (m_compositionContext.hwnd) doneContext(); m_compositionContext.hwnd = hwnd; m_compositionContext.focusObject = focusObject; + m_compositionContext.factor = factor; // Create a hidden caret which is kept at the microfocus // position in update(). This is important for some // Chinese input methods. diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 636d481e704..071e2c7d822 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -59,6 +59,7 @@ class QWindowsInputContext : public QPlatformInputContext int position; bool isComposing; QPointer focusObject; + qreal factor; }; public: explicit QWindowsInputContext(); @@ -88,7 +89,7 @@ private slots: void cursorRectChanged(); private: - void initContext(HWND hwnd, QObject *focusObject); + void initContext(HWND hwnd, qreal factor, QObject *focusObject); void doneContext(); void startContextComposition(); void endContextComposition(); From a4e2f2e687ca7aec88ecf82f72d42ac61e17a5b9 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 4 Mar 2016 13:50:18 +0100 Subject: [PATCH 19/31] Fix possible crash in QImage::pixel() QImage::pixel() assumed that the color table was valid for the values in the bitmap. This was always wrong for indexed images with explicit no color table set and was wrong for mono images that were constructed from preexisting data. For mono images, we default to a black/white color table, like we do when constructing with uninitialized data. For indexed image, we always default to no color table, but instead of crashing in pixel(), we warn and return an undefined value. [ChangeLog][QtGui][Image] Fixed possible crash in QImage::pixel() for mono or indexed images. Change-Id: Ieaf19c03984badddfd06e1855a7e287b862adc70 Task-number: QTBUG-50745 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 57 +++++++++++++--------- src/gui/image/qimage_p.h | 2 +- tests/auto/gui/image/qimage/tst_qimage.cpp | 29 +++++++++++ 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 6f649efcf47..29a688099b9 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -98,35 +98,22 @@ QImageData::QImageData() { } -/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors) +/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format) \internal Creates a new image data. Returns 0 if invalid parameters are give or anything else failed. */ -QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors) +QImageData * QImageData::create(const QSize &size, QImage::Format format) { - if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid) + if (!size.isValid() || format == QImage::Format_Invalid) return 0; // invalid parameter(s) uint width = size.width(); uint height = size.height(); uint depth = qt_depthForFormat(format); - switch (format) { - case QImage::Format_Mono: - case QImage::Format_MonoLSB: - numColors = 2; - break; - case QImage::Format_Indexed8: - numColors = qBound(0, numColors, 256); - break; - default: - numColors = 0; - break; - } - const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4) // sanity check for potential overflows @@ -138,13 +125,16 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu return 0; QScopedPointer d(new QImageData); - d->colortable.resize(numColors); - if (depth == 1) { + + switch (format) { + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + d->colortable.resize(2); d->colortable[0] = QColor(Qt::black).rgba(); d->colortable[1] = QColor(Qt::white).rgba(); - } else { - for (int i = 0; i < numColors; ++i) - d->colortable[i] = 0; + break; + default: + break; } d->width = width; @@ -773,7 +763,7 @@ QImage::QImage() Q_DECL_NOEXCEPT QImage::QImage(int width, int height, Format format) : QPaintDevice() { - d = QImageData::create(QSize(width, height), format, 0); + d = QImageData::create(QSize(width, height), format); } /*! @@ -788,7 +778,7 @@ QImage::QImage(int width, int height, Format format) QImage::QImage(const QSize &size, Format format) : QPaintDevice() { - d = QImageData::create(size, format, 0); + d = QImageData::create(size, format); } @@ -832,6 +822,17 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm d->cleanupFunction = cleanupFunction; d->cleanupInfo = cleanupInfo; + switch (format) { + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + d->colortable.resize(2); + d->colortable[0] = QColor(Qt::black).rgba(); + d->colortable[1] = QColor(Qt::white).rgba(); + break; + default: + break; + } + return d; } @@ -2236,7 +2237,15 @@ QRgb QImage::pixel(int x, int y) const case Format_MonoLSB: return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1); case Format_Indexed8: - return d->colortable.at((int)s[x]); + { + int index = (int)s[x]; + if (index < d->colortable.size()) { + return d->colortable.at(index); + } else { + qWarning("QImage::pixel: color table index %d out of range.", index); + return 0; + } + } case Format_RGB32: return 0xff000000 | reinterpret_cast(s)[x]; case Format_ARGB32: // Keep old behaviour. diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 0c0653e8abc..4979eab2072 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -57,7 +57,7 @@ class QImageWriter; struct Q_GUI_EXPORT QImageData { // internal image data QImageData(); ~QImageData(); - static QImageData *create(const QSize &size, QImage::Format format, int numColors = 0); + static QImageData *create(const QSize &size, QImage::Format format); static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); QAtomicInt ref; diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 23ddfbdd583..e8e1cd18968 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -197,6 +197,7 @@ private slots: void metadataPassthrough(); void pixelColor(); + void pixel(); private: const QString m_prefix; @@ -3038,5 +3039,33 @@ void tst_QImage::pixelColor() QCOMPARE(t.pixel(0,0), argb32pm.pixel(0,0)); } +void tst_QImage::pixel() +{ + { + QImage mono(1, 1, QImage::Format_Mono); + QImage monolsb(1, 1, QImage::Format_MonoLSB); + QImage indexed(1, 1, QImage::Format_Indexed8); + + mono.fill(0); + monolsb.fill(0); + indexed.fill(0); + + QCOMPARE(QColor(mono.pixel(0, 0)), QColor(Qt::black)); + QCOMPARE(QColor(monolsb.pixel(0, 0)), QColor(Qt::black)); + indexed.pixel(0, 0); // Don't crash + } + + { + uchar a = 0; + QImage mono(&a, 1, 1, QImage::Format_Mono); + QImage monolsb(&a, 1, 1, QImage::Format_MonoLSB); + QImage indexed(&a, 1, 1, QImage::Format_Indexed8); + + QCOMPARE(QColor(mono.pixel(0, 0)), QColor(Qt::black)); + QCOMPARE(QColor(monolsb.pixel(0, 0)), QColor(Qt::black)); + indexed.pixel(0, 0); // Don't crash + } +} + QTEST_GUILESS_MAIN(tst_QImage) #include "tst_qimage.moc" From 479ee4fa461e3c9bd71480d8e7a0bcabced52919 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 30 Mar 2016 18:20:40 +0200 Subject: [PATCH 20/31] moc: bail out early on missing or invalid options file If moc is invoked with the @ argument and no options file is specified or the options file cannot be read, do not try to parse the empty arguments list. Otherwise QCommandLineParser will print an additional error message that is of no value for the user. Task-number: QTBUG-51847 Change-Id: I9aa1eb20a44097b553123be8bc6fded87473a03a Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/tools/moc/main.cpp | 2 ++ tests/auto/tools/moc/tst_moc.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index a5cbad76681..18fbc977abf 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -282,6 +282,8 @@ int runMoc(int argc, char **argv) QStringLiteral("Read additional options from option-file.")); const QStringList arguments = argumentsFromCommandLineAndFile(app.arguments()); + if (arguments.isEmpty()) + return 1; parser.process(arguments); diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 5c16c7a48fd..b3f9a9f85f8 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -627,6 +627,8 @@ private slots: void unnamedNamespaceObjectsAndGadgets(); void veryLongStringData(); void gadgetHierarchy(); + void optionsFileError_data(); + void optionsFileError(); signals: void sigWithUnsignedArg(unsigned foo); @@ -3501,6 +3503,31 @@ void tst_Moc::gadgetHierarchy() QCOMPARE(GrandParentGadget::DerivedGadget::staticMetaObject.superClass(), &GrandParentGadget::BaseGadget::staticMetaObject); } +void tst_Moc::optionsFileError_data() +{ + QTest::addColumn("optionsArgument"); + QTest::newRow("no filename") << QStringLiteral("@"); + QTest::newRow("nonexistent file") << QStringLiteral("@letshuntasnark"); +} + +void tst_Moc::optionsFileError() +{ +#ifdef MOC_CROSS_COMPILED + QSKIP("Not tested when cross-compiled"); +#endif +#if !defined(QT_NO_PROCESS) + QFETCH(QString, optionsArgument); + QProcess p; + p.start(m_moc, QStringList(optionsArgument)); + QVERIFY(p.waitForFinished()); + QCOMPARE(p.exitCode(), 1); + QVERIFY(p.readAllStandardOutput().isEmpty()); + const QByteArray err = p.readAllStandardError(); + QVERIFY(err.contains("moc: ")); + QVERIFY(!err.contains("QCommandLineParser")); +#endif +} + QTEST_MAIN(tst_Moc) // the generated code must compile with QT_NO_KEYWORDS From ea122fa9e30b78af6b7738284f33451741638444 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 31 Mar 2016 11:23:24 +0200 Subject: [PATCH 21/31] Fixup for text labels in lancelot graphics test Some strings were drawn with a different size or scaling than what the string itself said, causing confusion. Change-Id: I4b187cba6d467cfa0900576bdf451052baa806e6 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../other/lancelot/scripts/statictext.qps | 20 +++++++++---------- tests/auto/other/lancelot/scripts/text.qps | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/auto/other/lancelot/scripts/statictext.qps b/tests/auto/other/lancelot/scripts/statictext.qps index c5ddda197ff..6b7b97d8faa 100644 --- a/tests/auto/other/lancelot/scripts/statictext.qps +++ b/tests/auto/other/lancelot/scripts/statictext.qps @@ -9,7 +9,7 @@ save setFont "sansserif" 12 normal drawStaticText 0 40 "sansserif 12pt, normal" - setFont "sansserif" 10 bold + setFont "sansserif" 12 bold drawStaticText 0 60 "sansserif 12pt, bold" setFont "sansserif" 10 bold italic @@ -25,7 +25,7 @@ save setFont "sansserif" 12 normal drawStaticText 0 40 "alpha sansserif 12pt, normal" - setFont "sansserif" 10 bold + setFont "sansserif" 12 bold drawStaticText 0 60 "alpha sansserif 12pt, bold" setFont "sansserif" 10 bold italic @@ -43,7 +43,7 @@ save setFont "sansserif" 12 normal drawStaticText 0 40 "scaled sansserif 12pt, normal" - setFont "sansserif" 10 bold + setFont "sansserif" 12 bold drawStaticText 0 60 "scaled sansserif 12pt, bold" setFont "sansserif" 10 bold italic @@ -61,7 +61,7 @@ save setFont "sansserif" 12 normal drawStaticText 0 40 "flipped sansserif 12pt, normal" - setFont "sansserif" 10 bold + setFont "sansserif" 12 bold drawStaticText 0 60 "flipped sansserif 12pt, bold" setFont "sansserif" 10 bold italic @@ -75,16 +75,16 @@ save rotate 185 setFont "sansserif" 10 normal - drawStaticText 0 20 "scaled sansserif 10pt, normal" + drawStaticText 0 20 "rotated sansserif 10pt, normal" setFont "sansserif" 12 normal - drawStaticText 0 40 "scaled sansserif 12pt, normal" + drawStaticText 0 40 "rotated sansserif 12pt, normal" - setFont "sansserif" 10 bold - drawStaticText 0 60 "scaled sansserif 12pt, bold" + setFont "sansserif" 12 bold + drawStaticText 0 60 "rotated sansserif 12pt, bold" setFont "sansserif" 10 bold italic - drawStaticText 0 80 "scaled sansserif 10pt, bold italic" + drawStaticText 0 80 "rotated sansserif 10pt, bold italic" restore translate 0 100 @@ -100,7 +100,7 @@ save setFont "sansserif" 12 normal drawStaticText 0 20 "gradient sansserif 12pt, normal" - setFont "sansserif" 10 bold + setFont "sansserif" 12 bold drawStaticText 0 40 "gradient sansserif 12pt, bold" setFont "sansserif" 10 bold italic diff --git a/tests/auto/other/lancelot/scripts/text.qps b/tests/auto/other/lancelot/scripts/text.qps index 169549a5bde..1b4fe4f0644 100644 --- a/tests/auto/other/lancelot/scripts/text.qps +++ b/tests/auto/other/lancelot/scripts/text.qps @@ -77,16 +77,16 @@ save rotate 185 setFont "sansserif" 10 normal - drawText 0 20 "scaled sansserif 10pt, normal" + drawText 0 20 "rotated sansserif 10pt, normal" setFont "sansserif" 12 normal - drawText 0 40 "scaled sansserif 12pt, normal" + drawText 0 40 "rotated sansserif 12pt, normal" setFont "sansserif" 12 bold - drawText 0 60 "scaled sansserif 12pt, bold" + drawText 0 60 "rotated sansserif 12pt, bold" setFont "sansserif" 10 bold italic - drawText 0 80 "scaled sansserif 10pt, bold italic" + drawText 0 80 "rotated sansserif 10pt, bold italic" restore translate 0 100 From 05ed49519120fa2cc4e00417efa0524ba00228a4 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 4 Mar 2016 13:15:03 +0100 Subject: [PATCH 22/31] Fix possible out-of-bounds access when making distance fields While extremely unlikely, there is a theoretical possibility that the '0' glyph of a given font will have a width or height of 1 pixel, in which case the (x + 1) / 2 way of getting the center would give us an out of bounds pixel. We just default to true in this case, since we cannot make any assumption based on the 0 glyph if it doesn't make any sense. If the image is invalid, we default to false. Change-Id: I36cea0b80c9d55aa10eb65db44d1b7ec8a40fc8c Reviewed-by: Yoann Lopes --- src/gui/text/qdistancefield.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 4d189786a18..6a7019bc3cb 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -687,8 +687,10 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path static bool imageHasNarrowOutlines(const QImage &im) { - if (im.isNull()) + if (im.isNull() || im.width() < 1 || im.height() < 1) return false; + else if (im.width() == 1 || im.height() == 1) + return true; int minHThick = 999; int minVThick = 999; From f44d826751a46427ffc35560f990f6aa66855f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simo=20F=C3=A4lt?= Date: Wed, 24 Feb 2016 09:20:56 +0200 Subject: [PATCH 23/31] Autotest: Remove blacklistings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing blacklistings from tests that are now passing. Change-Id: I00aa1ce286d3e7715fb4bee4a36d0d77049a29ae Reviewed-by: Simon Hausmann Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tony Sarajärvi --- tests/auto/corelib/io/qstandardpaths/BLACKLIST | 2 -- tests/auto/gui/kernel/qwindow/BLACKLIST | 2 -- tests/auto/opengl/qgl/BLACKLIST | 2 -- tests/auto/widgets/dialogs/qfontdialog/BLACKLIST | 4 ---- tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST | 6 ------ tests/auto/widgets/kernel/qwidget/BLACKLIST | 3 --- tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST | 2 -- tests/auto/widgets/widgets/qmenu/BLACKLIST | 3 --- 8 files changed, 24 deletions(-) delete mode 100644 tests/auto/corelib/io/qstandardpaths/BLACKLIST delete mode 100644 tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST diff --git a/tests/auto/corelib/io/qstandardpaths/BLACKLIST b/tests/auto/corelib/io/qstandardpaths/BLACKLIST deleted file mode 100644 index 8496a620b3f..00000000000 --- a/tests/auto/corelib/io/qstandardpaths/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[testRuntimeDirectory] -rhel-7.1 diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index cfbd47745f6..a34066dd7ce 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -1,5 +1,3 @@ -[testInputEvents] -rhel-7.1 [positioning:default] ubuntu-14.04 [modalWindowPosition] diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index 547a9a2a730..fa7c829b30e 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -1,5 +1,3 @@ -[] -rhel-7.1 [glWidgetRendering] windows [glFBORendering] diff --git a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST index 5fd026537eb..669ec50978a 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfontdialog/BLACKLIST @@ -1,7 +1,3 @@ [task256466_wrongStyle] opensuse-13.1 rhel-7.1 -[setFont] -ubuntu-14.04 -redhatenterpriselinuxworkstation-6.6 -rhel-7.1 diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST index 14c41711aca..7f55c2dae02 100644 --- a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST +++ b/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST @@ -1,8 +1,2 @@ [panGesture:Two finger] xcb -[swipeGesture:SmallDirectionChange] -rhel-7.1 -[swipeGesture:Line] -rhel-7.1 -[pinchGesture:Standard] -rhel-7.1 diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 8d18d40e058..4563da8d482 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -32,7 +32,6 @@ osx osx [widgetAt] osx -rhel-7.1 [sheetOpacity] osx [resizeEvent] @@ -65,10 +64,8 @@ osx osx [taskQTBUG_4055_sendSyntheticEnterLeave] osx -rhel-7.1 [syntheticEnterLeave] osx -rhel-7.1 [maskedUpdate] osx [hideWhenFocusWidgetIsChild] diff --git a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST deleted file mode 100644 index a10cf663d05..00000000000 --- a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[setSystemMenu] -rhel-7.1 diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST index dbc3e268371..de49d5ff459 100644 --- a/tests/auto/widgets/widgets/qmenu/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST @@ -1,5 +1,2 @@ [task258920_mouseBorder] osx -rhel-7.1 -[pushButtonPopulateOnAboutToShow] -rhel-7.1 From a5456b23f4aee5693c4a24e2cce49ed40c43d71e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 1 Apr 2016 18:44:18 +0200 Subject: [PATCH 24/31] eglfs QPA: Hide the cursor when QT_QPA_EGLFS_HIDECURSOR is set Change-Id: Ib5491c26db2a29e8905573198741df75d8511ace Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp index fe47c947b4e..dda61e3901d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -64,6 +64,12 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) , m_cursorImage(0, 0, 0, 0, 0, 0) , m_visible(true) { + QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); + if (!hideCursorVal.isEmpty()) + m_visible = hideCursorVal.toInt() == 0; + if (!m_visible) + return; + uint64_t width, height; if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0) && (drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &height) == 0)) { From b7c7beacda529edd642d979064748bdad27b989b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 1 Apr 2016 09:24:51 +0200 Subject: [PATCH 25/31] QPointer: add a test for const QPointer People use this, so make sure there's a test for it. I don't expect this test to fail, but static and dynamic checkers should be presented with this use-case, so they have a chance of warning, because certain implementation strategies of QPointer may make this code undefined. Change-Id: I334bd73204ba4e186c4098fc6b7188917407e020 Reviewed-by: Olivier Goffart (Woboq GmbH) --- .../corelib/kernel/qpointer/tst_qpointer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp index d7cce4ada44..f3f485297ac 100644 --- a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp +++ b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp @@ -59,6 +59,7 @@ private slots: void qvariantCast(); void constPointer(); + void constQPointer(); }; void tst_QPointer::constructors() @@ -402,6 +403,21 @@ void tst_QPointer::constPointer() delete fp.data(); } +void tst_QPointer::constQPointer() +{ + // Check that const QPointers work. It's a bit weird to mark a pointer + // const if its value can change, but the shallow-const principle in C/C++ + // allows this, and people use it, so document it with a test. + // + // It's unlikely that this test will fail in and out of itself, but it + // presents the use-case to static and dynamic checkers that can raise + // a warning (hopefully) should this become an issue. + QObject *o = new QObject(this); + const QPointer p = o; + delete o; + QVERIFY(!p); +} + QTEST_MAIN(tst_QPointer) #include "tst_qpointer.moc" From fc65b9a7cbed3fe66e3037501b56949bc1d3ae30 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 31 Mar 2016 21:15:30 +0200 Subject: [PATCH 26/31] QGraphics*Layout: fix memory leaks Change-Id: I5f9d2ccc8912e3fa08e376b5f6b6450d22913406 Task-number: QTBUG-10768 Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/graphicsview/qgraphicsgridlayout.cpp | 9 +++++---- src/widgets/graphicsview/qgraphicslinearlayout.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsgridlayout.cpp b/src/widgets/graphicsview/qgraphicsgridlayout.cpp index 6f65558a1a3..2dc84a53995 100644 --- a/src/widgets/graphicsview/qgraphicsgridlayout.cpp +++ b/src/widgets/graphicsview/qgraphicsgridlayout.cpp @@ -83,6 +83,7 @@ #include "qgraphicswidget.h" #include "qgraphicsgridlayoutengine_p.h" #include "qgraphicslayoutstyleinfo_p.h" +#include "qscopedpointer.h" #ifdef QT_DEBUG # include #endif @@ -92,10 +93,10 @@ QT_BEGIN_NAMESPACE class QGraphicsGridLayoutPrivate : public QGraphicsLayoutPrivate { public: - QGraphicsGridLayoutPrivate(): m_styleInfo(0) { } + QGraphicsGridLayoutPrivate() { } QGraphicsLayoutStyleInfo *styleInfo() const; - mutable QGraphicsLayoutStyleInfo *m_styleInfo; + mutable QScopedPointer m_styleInfo; QGraphicsGridLayoutEngine engine; #ifdef QGRIDLAYOUTENGINE_DEBUG @@ -107,8 +108,8 @@ public: QGraphicsLayoutStyleInfo *QGraphicsGridLayoutPrivate::styleInfo() const { if (!m_styleInfo) - m_styleInfo = new QGraphicsLayoutStyleInfo(this); - return m_styleInfo; + m_styleInfo.reset(new QGraphicsLayoutStyleInfo(this)); + return m_styleInfo.data(); } /*! diff --git a/src/widgets/graphicsview/qgraphicslinearlayout.cpp b/src/widgets/graphicsview/qgraphicslinearlayout.cpp index 0384364ad4b..91e0fff60f9 100644 --- a/src/widgets/graphicsview/qgraphicslinearlayout.cpp +++ b/src/widgets/graphicsview/qgraphicslinearlayout.cpp @@ -116,6 +116,7 @@ #include "qgraphicswidget.h" #include "qgraphicsgridlayoutengine_p.h" #include "qgraphicslayoutstyleinfo_p.h" +#include "qscopedpointer.h" #ifdef QT_DEBUG #include #endif @@ -126,8 +127,7 @@ class QGraphicsLinearLayoutPrivate : public QGraphicsLayoutPrivate { public: QGraphicsLinearLayoutPrivate(Qt::Orientation orientation) - : orientation(orientation), - m_styleInfo(0) + : orientation(orientation) { } void removeGridItem(QGridLayoutItem *gridItem); @@ -137,7 +137,7 @@ public: int gridColumn(int index) const; Qt::Orientation orientation; - mutable QGraphicsLayoutStyleInfo *m_styleInfo; + mutable QScopedPointer m_styleInfo; QGraphicsGridLayoutEngine engine; }; @@ -172,8 +172,8 @@ int QGraphicsLinearLayoutPrivate::gridColumn(int index) const QGraphicsLayoutStyleInfo *QGraphicsLinearLayoutPrivate::styleInfo() const { if (!m_styleInfo) - m_styleInfo = new QGraphicsLayoutStyleInfo(this); - return m_styleInfo; + m_styleInfo.reset(new QGraphicsLayoutStyleInfo(this)); + return m_styleInfo.data(); } /*! From f805d7075a86775eccb3a153ffe7e874b103ee4d Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Fri, 25 Mar 2016 22:26:36 +0100 Subject: [PATCH 27/31] Fix QtGui dependencies in tests/benchmarks Before this change, -no-gui builds failed already while running qmake. Change-Id: I3e300a16669371098589822806c5cf8aa9b801c7 Reviewed-by: Oswald Buddenhagen --- .../corelib/kernel/qcoreapplication/qcoreapplication.pro | 2 +- tests/benchmarks/corelib/kernel/qvariant/qvariant.pro | 1 + tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp | 8 +++++++- .../access/qnetworkdiskcache/qnetworkdiskcache.pro | 3 +-- .../qnetworkreply_from_cache/qnetworkreply_from_cache.pro | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro b/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro index df5450f88d4..9efce766413 100644 --- a/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro +++ b/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro @@ -1,4 +1,4 @@ -QT += testlib +QT = core testlib TEMPLATE = app TARGET = tst_bench_qcoreapplication diff --git a/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro b/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro index afacbd2c2b2..f05fa94b355 100644 --- a/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro +++ b/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro @@ -1,5 +1,6 @@ TARGET = tst_bench_qvariant QT += testlib +!qtHaveModule(gui): QT -= gui CONFIG += release #CONFIG += debug diff --git a/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp index 1268ede7461..5ab209561c8 100644 --- a/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/benchmarks/corelib/kernel/qvariant/tst_qvariant.cpp @@ -32,7 +32,9 @@ ****************************************************************************/ #include -#include +#ifdef QT_GUI_LIB +# include +#endif #include #define ITERATION_COUNT 1e5 @@ -47,7 +49,9 @@ private slots: void floatVariantCreation(); void rectVariantCreation(); void stringVariantCreation(); +#ifdef QT_GUI_LIB void pixmapVariantCreation(); +#endif void stringListVariantCreation(); void bigClassVariantCreation(); void smallClassVariantCreation(); @@ -158,10 +162,12 @@ void tst_qvariant::stringVariantCreation() variantCreation(QString()); } +#ifdef QT_GUI_LIB void tst_qvariant::pixmapVariantCreation() { variantCreation(QPixmap()); } +#endif void tst_qvariant::stringListVariantCreation() { diff --git a/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro index 226c123a72e..8c443dadea6 100644 --- a/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro +++ b/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro @@ -1,8 +1,7 @@ TEMPLATE = app TARGET = tst_bench_qnetworkdiskcache -QT += gui # for QDesktopServices -QT += network testlib +QT = core network testlib CONFIG += release diff --git a/tests/benchmarks/network/access/qnetworkreply_from_cache/qnetworkreply_from_cache.pro b/tests/benchmarks/network/access/qnetworkreply_from_cache/qnetworkreply_from_cache.pro index bd3b34473f4..e1fabffe4d5 100644 --- a/tests/benchmarks/network/access/qnetworkreply_from_cache/qnetworkreply_from_cache.pro +++ b/tests/benchmarks/network/access/qnetworkreply_from_cache/qnetworkreply_from_cache.pro @@ -1,3 +1,3 @@ TARGET = tst_bench_qnetworkreply_from_cache -QT += network testlib +QT = core network testlib SOURCES += tst_qnetworkreply_from_cache.cpp From f84c50243365f1a0d3cb3b70c2a5b4dbc4e31257 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 31 Mar 2016 22:12:00 +0200 Subject: [PATCH 28/31] QScrollerTimer: fix a memory leak The QScrollerTimer instance allocated by QScrollerPrivate was never freed. I've absolutely no idea why QScroller has such a messy d-pointer handling, so go for the easiest approach: exploit the fact that QScrollerPrivate is a QObject and parent the QScrollerTimer to it. Change-Id: I500edc9d0d14b2fb9eec02712229970eb2b9fe81 Task-number: QTBUG-52280 Reviewed-by: Friedemann Kleint --- src/widgets/util/qscroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 92a9dd72020..270f1c5890d 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -187,7 +187,7 @@ class QScrollTimer : public QAbstractAnimation { public: QScrollTimer(QScrollerPrivate *_d) - : d(_d), ignoreUpdate(false), skip(0) + : QAbstractAnimation(_d), d(_d), ignoreUpdate(false), skip(0) { } int duration() const Q_DECL_OVERRIDE From ad864ef194ddceed01c6fe16627f7ba761a972d0 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 2 Apr 2016 21:29:47 +0200 Subject: [PATCH 29/31] QGraphicsView: clarify documentation for viewportTransform d->matrix holds the scene->viewport transform, not vice versa. Change-Id: I997cbdfbf519f39f242cd0dbbd00621e59ec9307 Task-number: QTBUG-48705 Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 1c5c5416280..79f1394c9e8 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -3828,7 +3828,7 @@ QTransform QGraphicsView::transform() const } /*! - Returns a matrix that maps viewport coordinates to scene coordinates. + Returns a matrix that maps scene coordinates to viewport coordinates. \sa mapToScene(), mapFromScene() */ From bedf0367ac580a2e73712be2f4207bb6af9f0226 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 1 Apr 2016 08:32:37 +0200 Subject: [PATCH 30/31] QVariant: Fix flags for type-erased associative iterator key The flags here are passed to a private QVariant constructor, and they really represent a boolean - IsPointer or not. Because the flag for the key_type was incorrectly populated with the flag for the value_type, memory would be corrupted when using a mapping type whose value_type is a pointer, but whose key type was not, such as QMap This typo has been there since the concept was introduced in commit v5.2.0-alpha1~807 (Add container access functionality for associative containers in QVariant., 2013-04-05). Task-number: QTBUG-52246 Change-Id: I9ecb13c603015eed2dc2ca43947fa0ecd6be8b5a Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetatype.h | 2 +- .../corelib/kernel/qvariant/tst_qvariant.cpp | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 3b8f8e71664..899a51173e3 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1226,7 +1226,7 @@ public: inline void destroyIter() { _destroyIter(&_iterator); } - inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_value); } + inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); } inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); } inline void find(const VariantData &key) diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index c91bb213992..f2f3baae6b8 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -280,6 +280,8 @@ private slots: void compareSanity_data(); void compareSanity(); + void accessSequentialContainerKey(); + private: void dataStream_data(QDataStream::Version version); void loadQVariantFromDataStream(QDataStream::Version version); @@ -4733,5 +4735,30 @@ void tst_QVariant::compareSanity() } } +void tst_QVariant::accessSequentialContainerKey() +{ + QString nameResult; + + { + QMap mapping; + QString name = QString::fromLatin1("Seven"); + mapping.insert(name, Q_NULLPTR); + + QVariant variant = QVariant::fromValue(mapping); + + QAssociativeIterable iterable = variant.value(); + QAssociativeIterable::const_iterator iit = iterable.begin(); + const QAssociativeIterable::const_iterator end = iterable.end(); + for ( ; iit != end; ++iit) { + nameResult += iit.key().toString(); + } + } // Destroy mapping + // Regression test for QTBUG-52246 - no memory corruption/double deletion + // of the string key. + + QCOMPARE(nameResult, QStringLiteral("Seven")); +} + + QTEST_MAIN(tst_QVariant) #include "tst_qvariant.moc" From 8ce657d0279566ef327af1b88339534041ddc012 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 3 Apr 2016 12:45:40 +0200 Subject: [PATCH 31/31] QAbstractItemView: don't call restart() on invalid QElapsedTimer In keyboardSearch(), QAbstractItemView unconditionally called QElapsedTimer::restart(). Calling restart() on an invalid QElapsedTimer is undefined behavior: qelapsedtimer_unix.cpp:192:9: runtime error: signed integer overflow: 3313808 - -9223372036854775808 cannot be represented in type 'long int' qelapsedtimer_unix.cpp:193:10: runtime error: signed integer overflow: 534150461 - -9223372036854775808 cannot be represented in type 'long int' qelapsedtimer_unix.cpp:194:17: runtime error: signed integer overflow: -9223372036851462000 * 1000000000 cannot be represented in type 'long long int' The code already checked the timer for validity, and did not use the return value of restart() in case of an invalid timer, but the check came too late. Fix by checking the return value of QElapsedTimer::isValid() earlier, and calling start() instead of restart() instead. Fix the same error in QTreeView, which has a c'n'p copy of the buggy code. Change-Id: I9751465394707d9348d5c05a0b1b2be147eceb2e Reviewed-by: Giuseppe D'Angelo --- src/widgets/itemviews/qabstractitemview.cpp | 6 +++++- src/widgets/itemviews/qtreeview.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 251b09ce7db..9dbe5c6c543 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -2932,7 +2932,11 @@ void QAbstractItemView::keyboardSearch(const QString &search) : d->model->index(0, 0, d->root); bool skipRow = false; bool keyboardTimeWasValid = d->keyboardInputTime.isValid(); - qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart(); + qint64 keyboardInputTimeElapsed; + if (keyboardTimeWasValid) + keyboardInputTimeElapsed = d->keyboardInputTime.restart(); + else + d->keyboardInputTime.start(); if (search.isEmpty() || !keyboardTimeWasValid || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) { d->keyboardInput = search; diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 0ccb9891988..e6a6b2a447d 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -1017,7 +1017,11 @@ void QTreeView::keyboardSearch(const QString &search) bool skipRow = false; bool keyboardTimeWasValid = d->keyboardInputTime.isValid(); - qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart(); + qint64 keyboardInputTimeElapsed; + if (keyboardTimeWasValid) + keyboardInputTimeElapsed = d->keyboardInputTime.restart(); + else + d->keyboardInputTime.start(); if (search.isEmpty() || !keyboardTimeWasValid || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) { d->keyboardInput = search;