From 7c5475f1c03a4b9d6c023bc7ff937e1fc2f62271 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 19 Oct 2017 10:07:50 +0200 Subject: Doc: add hint about QMimeDatabase to QImageReader::canRead() Task-number: QTBUG-63568 Change-Id: I5b700138487dbebfc8cbe70eb3a076efceafb361 Reviewed-by: Venugopal Shivashankar --- src/gui/image/qimagereader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 381ddb5b45..f49e90ba0a 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1211,10 +1211,13 @@ float QImageReader::gamma() const see if the image data is valid. read() may still return false after canRead() returns \c true, if the image data is corrupt. + \note A QMimeDatabase lookup is normally a better approach than this + function for identifying potentially non-image files or data. + For images that support animation, canRead() returns \c false when all frames have been read. - \sa read(), supportedImageFormats() + \sa read(), supportedImageFormats(), QMimeDatabase */ bool QImageReader::canRead() const { -- cgit v1.2.3 From 7944423bfaec48e5c7642a042bede1557b1beff2 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 19 Oct 2017 09:36:15 +0200 Subject: Add clarifying documentation for QLayout::removeWidget() Change-Id: I6c256c6c5cdfed6ceb45758d708fdc8f74d2939f Reviewed-by: Leena Miettinen --- src/widgets/kernel/qlayout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index 1e455b0d64..f3db4f4e2d 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -1350,7 +1350,8 @@ QRect QLayout::alignmentRect(const QRect &r) const /*! Removes the widget \a widget from the layout. After this call, it is the caller's responsibility to give the widget a reasonable - geometry or to put the widget back into a layout. + geometry or to put the widget back into a layout or to explicitly + hide it if necessary. \b{Note:} The ownership of \a widget remains the same as when it was added. -- cgit v1.2.3 From 7e7683cabb8df58097c5bc4638a2e08cf6e6ff71 Mon Sep 17 00:00:00 2001 From: Yulong Bai Date: Tue, 17 Oct 2017 14:41:42 +0200 Subject: QAction: fix ::setData() always emits changed() QAction::setData() always emits changed() even without actual data change. Original code lacks a guard to check if the data changes. According to http://doc.qt.io/qt-4.8/signalsandslots.html, adding guard also benefits to prevent infinite looping in case of cyclic connections. Task-number: QTBUG-62006 Change-Id: I776369b668082f9f02e4502a36b1ae234ee7e079 Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qaction.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index f1788bb3f4..7754defaac 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -1118,6 +1118,8 @@ void QAction::setData(const QVariant &data) { Q_D(QAction); + if (d->userData == data) + return; d->userData = data; d->sendDataChanged(); } -- cgit v1.2.3 From 18f0a45964e62bf3db7b657847902a356fd31f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 19 Oct 2017 12:22:16 +0200 Subject: Fix redirecting all the other methods for HTTP 307 and 308 c4cf90b1f739c47383672de3d66b1d9d5427f5db made POST requests be redirected properly, but this wasn't enough and should have included every method/verb. Change-Id: I37b12dc9fdffcbf2aadbd2360d4fc2584c024939 Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkreplyhttpimpl.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index fa49c8e05b..c1a9f628a0 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1110,16 +1110,14 @@ QNetworkAccessManager::Operation QNetworkReplyHttpImplPrivate::getRedirectOperat // HTTP status code can be used to decide if we can redirect with a GET // operation or not. See http://www.ietf.org/rfc/rfc2616.txt [Sec 10.3] for // more details - Q_UNUSED(httpStatus); + + // We MUST keep using the verb that was used originally when being redirected with 307 or 308. + if (httpStatus == 307 || httpStatus == 308) + return currentOp; switch (currentOp) { case QNetworkAccessManager::HeadOperation: return QNetworkAccessManager::HeadOperation; - case QNetworkAccessManager::PostOperation: - // We MUST keep using POST when being redirected with 307 or 308. - if (statusCode == 307 || statusCode == 308) - return QNetworkAccessManager::PostOperation; - break; default: break; } -- cgit v1.2.3 From 4f9b2cb026e334eb24dd35b05422b9dad6d8a2f3 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 21 Sep 2017 13:14:40 +0200 Subject: Remove duplicate qnx from the platform file selector names Update the QFileSelector tests for QNX. Co-authored-by: James McDonnell Change-Id: I68a8fde86725596323b539433287ac1a18fac1eb Reviewed-by: Thiago Macieira --- src/corelib/io/qfileselector.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 9db67f2f9b..0ba8b124f7 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -146,7 +146,7 @@ QFileSelectorPrivate::QFileSelectorPrivate() Selectors normally available are \list \li platform, any of the following strings which match the platform the application is running - on (list not exhaustive): android, ios, osx, darwin, mac, linux, wince, unix, windows. + on (list not exhaustive): android, ios, osx, darwin, mac, macos, linux, qnx, unix, windows. On Linux, if it can be determined, the name of the distribution too, like debian, fedora or opensuse. \li locale, same as QLocale().name(). @@ -373,8 +373,8 @@ QStringList QFileSelectorPrivate::platformSelectors() # endif #elif defined(Q_OS_UNIX) ret << QStringLiteral("unix"); -# if !defined(Q_OS_ANDROID) - // we don't want "linux" for Android +# if !defined(Q_OS_ANDROID) && !defined(Q_OS_QNX) + // we don't want "linux" for Android or two instances of "qnx" for QNX ret << QSysInfo::kernelType(); # ifdef Q_OS_MAC ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin" -- cgit v1.2.3 From 37a1478787d64b34a0716421c8a47f3246e41bfd Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 20 Oct 2017 11:07:59 +0700 Subject: Cocoa QPA: Code clean up, make some bits more readable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7f37c1b0f7f72a79bb2ac5828ba54111a90a0a00 Reviewed-by: Jake Petroules Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/messages.cpp | 2 +- src/plugins/platforms/cocoa/messages.h | 11 +++++++++++ src/plugins/platforms/cocoa/qcocoamenuitem.mm | 10 +++------- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 20 +++++++------------- 4 files changed, 22 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/messages.cpp b/src/plugins/platforms/cocoa/messages.cpp index 85b814ce1c..8eea1e654e 100644 --- a/src/plugins/platforms/cocoa/messages.cpp +++ b/src/plugins/platforms/cocoa/messages.cpp @@ -75,7 +75,7 @@ QString qt_mac_applicationmenu_string(int type) QPlatformMenuItem::MenuRole detectMenuRole(const QString &caption) { QString captionNoAmpersand(caption); - captionNoAmpersand.remove(QChar('&')); + captionNoAmpersand.remove(QLatin1Char('&')); const QString aboutString = QCoreApplication::translate("QCocoaMenuItem", "About"); if (captionNoAmpersand.startsWith(aboutString, Qt::CaseInsensitive) || caption.endsWith(aboutString, Qt::CaseInsensitive)) return QPlatformMenuItem::AboutRole; diff --git a/src/plugins/platforms/cocoa/messages.h b/src/plugins/platforms/cocoa/messages.h index a9c9cc42e5..e41898fe59 100644 --- a/src/plugins/platforms/cocoa/messages.h +++ b/src/plugins/platforms/cocoa/messages.h @@ -45,6 +45,17 @@ QT_BEGIN_NAMESPACE +enum { + ServicesAppMenuItem = 0, + HideAppMenuItem, + HideOthersAppMenuItem, + ShowAllAppMenuItem, + PreferencesAppMenuItem, + QuitAppMenuItem, + AboutAppMenuItem +}; + + QString msgAboutQt(); QString qt_mac_applicationmenu_string(int type); diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 21f2b4de85..ecbab38a83 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -370,24 +370,20 @@ NSMenuItem *QCocoaMenuItem::sync() return m_native; } -QT_BEGIN_NAMESPACE -extern QString qt_mac_applicationmenu_string(int type); -QT_END_NAMESPACE - QString QCocoaMenuItem::mergeText() { QCocoaMenuLoader *loader = [QCocoaMenuLoader sharedMenuLoader]; if (m_native == [loader aboutMenuItem]) { - return qt_mac_applicationmenu_string(6).arg(qt_mac_applicationName()); + return qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()); } else if (m_native== [loader aboutQtMenuItem]) { if (m_text == QString("About Qt")) return msgAboutQt(); else return m_text; } else if (m_native == [loader preferencesMenuItem]) { - return qt_mac_applicationmenu_string(4); + return qt_mac_applicationmenu_string(PreferencesAppMenuItem); } else if (m_native == [loader quitMenuItem]) { - return qt_mac_applicationmenu_string(5).arg(qt_mac_applicationName()); + return qt_mac_applicationmenu_string(QuitAppMenuItem).arg(qt_mac_applicationName()); } else if (m_text.contains('\t')) { return m_text.left(m_text.indexOf('\t')); } diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 01a3c04afb..0d9bb5009d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -47,14 +47,8 @@ #include #include #include -#include -#include -#include #include -QT_FORWARD_DECLARE_CLASS(QCFString) -QT_FORWARD_DECLARE_CLASS(QString) - @implementation QCocoaMenuLoader + (instancetype)sharedMenuLoader @@ -314,13 +308,13 @@ QT_FORWARD_DECLARE_CLASS(QString) { #ifndef QT_NO_TRANSLATION - [servicesItem setTitle:qt_mac_applicationmenu_string(0).toNSString()]; - [hideItem setTitle:qt_mac_applicationmenu_string(1).arg(qt_mac_applicationName()).toNSString()]; - [hideAllOthersItem setTitle:qt_mac_applicationmenu_string(2).toNSString()]; - [showAllItem setTitle:qt_mac_applicationmenu_string(3).toNSString()]; - [preferencesItem setTitle:qt_mac_applicationmenu_string(4).toNSString()]; - [quitItem setTitle:qt_mac_applicationmenu_string(5).arg(qt_mac_applicationName()).toNSString()]; - [aboutItem setTitle:qt_mac_applicationmenu_string(6).arg(qt_mac_applicationName()).toNSString()]; + [servicesItem setTitle:qt_mac_applicationmenu_string(ServicesAppMenuItem).toNSString()]; + [hideItem setTitle:qt_mac_applicationmenu_string(HideAppMenuItem).arg(qt_mac_applicationName()).toNSString()]; + [hideAllOthersItem setTitle:qt_mac_applicationmenu_string(HideOthersAppMenuItem).toNSString()]; + [showAllItem setTitle:qt_mac_applicationmenu_string(ShowAllAppMenuItem).toNSString()]; + [preferencesItem setTitle:qt_mac_applicationmenu_string(PreferencesAppMenuItem).toNSString()]; + [quitItem setTitle:qt_mac_applicationmenu_string(QuitAppMenuItem).arg(qt_mac_applicationName()).toNSString()]; + [aboutItem setTitle:qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()).toNSString()]; #endif } -- cgit v1.2.3 From abcf558e49d5e8c20eda14badc30e93e2e9cba32 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 16 Oct 2017 11:53:53 +0200 Subject: moc: Restore compatibility with Qt 5.7's -b option In Qt 5.7, it was possible to call moc "-bfoo.h" or "-b foo.h" and it had the same effect. With the port to QCommandLineOption, we broke the -b option as it was not annotated as a short option. (Regression in a7e3c17e755881aa3169a2bb662338bbd2c67512) Task-number: QTBUG-63706 Change-Id: I161d0f1a4e65d129063b5e8431802257677da19d Reviewed-by: Jake Petroules Reviewed-by: Thiago Macieira --- src/tools/moc/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index b30de66258..98cc9652ab 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -267,6 +267,7 @@ int runMoc(int argc, char **argv) QCommandLineOption prependIncludeOption(QStringLiteral("b")); prependIncludeOption.setDescription(QStringLiteral("Prepend #include (preserve default include).")); prependIncludeOption.setValueName(QStringLiteral("file")); + prependIncludeOption.setFlags(QCommandLineOption::ShortOptionStyle); parser.addOption(prependIncludeOption); QCommandLineOption includeOption(QStringLiteral("include")); -- cgit v1.2.3 From 3b8f828174f08d9037a0947b8709648ac37cdc36 Mon Sep 17 00:00:00 2001 From: Maciej Czarnecki Date: Mon, 21 Aug 2017 13:28:51 +0200 Subject: QWizard: Do not remove the Next button's shortcut Currently on Windows, the Next button's shortcut doesn't work, because QWizard overrides it with an empty key sequence. The key sequence should be changed only if isVistaThemeEnabled() returns true. Task-number: QTBUG-46894 Change-Id: I54f26388b167973cc8065a867d9e771c1e6a2a72 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qwizard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 1984cb0a89..a4ea7ae8de 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1468,8 +1468,8 @@ void QWizardPrivate::updateButtonTexts() // even in RTL mode, so do the same, even if it might be counter-intuitive. // The shortcut for 'back' is set in class QVistaBackButton. #if QT_CONFIG(shortcut) - if (btns[QWizard::NextButton]) - btns[QWizard::NextButton]->setShortcut(isVistaThemeEnabled() ? QKeySequence(Qt::ALT | Qt::Key_Right) : QKeySequence()); + if (btns[QWizard::NextButton] && isVistaThemeEnabled()) + btns[QWizard::NextButton]->setShortcut(QKeySequence(Qt::ALT | Qt::Key_Right)); #endif } -- cgit v1.2.3 From 5ec02f7792e97208c0f621c9e8a16854168022e3 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 24 Oct 2017 14:33:24 +0200 Subject: winrt: Fix compilation with -no-pch Task-number: QTBUG-63210 Change-Id: Icdd4fcee67e3b386b86a131c302424b53b18e565 Reviewed-by: Maurice Kalinowski Reviewed-by: Jake Petroules --- src/corelib/kernel/qfunctions_winrt.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h index 9b33f8b120..d0c44be683 100644 --- a/src/corelib/kernel/qfunctions_winrt.h +++ b/src/corelib/kernel/qfunctions_winrt.h @@ -44,6 +44,7 @@ #ifdef Q_OS_WIN +#include #include #include #include -- cgit v1.2.3 From ecd183455b8039ee15b9d51fd1111992af19ed1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Wed, 11 Oct 2017 11:35:42 +0200 Subject: Refactor childIdListForAccessibleObject It has several problems: 1. It could potentially create an intArray with uninitialized elements. This could happen because the index for getting interfaces were the same as the storage index. This was not correct, because they could diverge if iface->child() returned an invalid interface. 2. The count of accessible child elements could change while iterating. This could cause out-of-bounds condition when calling SetIntArrayRegion as described in QTBUG-45855. Instead now, we call SetIntArrayRegion only once, after we have gathered all the child interface ids. Task-number: QTBUG-45855 Change-Id: I77e813158df5f563d04931ac4e296e3fc2a16e67 Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/android/androidjniaccessibility.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index e4d670239f..a3bc58bb89 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -105,15 +105,15 @@ namespace QtAndroidAccessibility { QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { - jintArray jArray = env->NewIntArray(jsize(iface->childCount())); - for (int i = 0; i < iface->childCount(); ++i) { + const int childCount = iface->childCount(); + QVarLengthArray ifaceIdArray(childCount); + for (int i = 0; i < childCount; ++i) { QAccessibleInterface *child = iface->child(i); - if (child && child->isValid()) { - QAccessible::Id ifaceId = QAccessible::uniqueId(child); - jint jid = ifaceId; - env->SetIntArrayRegion(jArray, i, 1, &jid); - } + if (child && child->isValid()) + ifaceIdArray.append(QAccessible::uniqueId(child)); } + jintArray jArray = env->NewIntArray(jsize(ifaceIdArray.count())); + env->SetIntArrayRegion(jArray, 0, ifaceIdArray.count(), ifaceIdArray.data()); return jArray; } -- cgit v1.2.3 From 5eb508a31717c75d804cfb55e46e867c19ae58d2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 18 Oct 2017 15:34:52 +0200 Subject: Fix clazy-strict-iterators Change-Id: I9276a85f0a8061b2636687cf694b8ed1abaa18b8 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/statemachine/qstatemachine.cpp | 2 +- src/dbus/qdbusinternalfilters.cpp | 2 +- src/gui/text/qtexttable.cpp | 4 ++-- .../platforminputcontexts/compose/qcomposeplatforminputcontext.cpp | 2 +- src/tools/moc/preprocessor.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 1d80da55c9..2808ba2ced 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -411,7 +411,7 @@ QStateMachinePrivate::~QStateMachinePrivate() qDeleteAll(internalEventQueue); qDeleteAll(externalEventQueue); - for (QHash::const_iterator it = delayedEvents.begin(), eit = delayedEvents.end(); it != eit; ++it) { + for (QHash::const_iterator it = delayedEvents.cbegin(), eit = delayedEvents.cend(); it != eit; ++it) { delete it.value().event; } } diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 0927f326f2..0ef5061b5f 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -407,7 +407,7 @@ QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = std::lower_bound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), interface_name); - if (it != connector->adaptors.end() && interface_name == QLatin1String(it->interface)) { + if (it != connector->adaptors.cend() && interface_name == QLatin1String(it->interface)) { return propertyWriteReply(msg, interface_name, property_name, writeProperty(it->adaptor, property_name, value)); } diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index e4a3c2b915..9639c18d2b 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -1048,7 +1048,7 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols) QFragmentFindHelper helper(origCellPosition, p->fragmentMap()); const auto begin = d->cells.cbegin(); const auto it = std::lower_bound(begin, d->cells.cend(), helper); - Q_ASSERT(it != d->cells.end()); + Q_ASSERT(it != d->cells.cend()); Q_ASSERT(!(helper < *it)); Q_ASSERT(*it == cellFragment); const int insertCellIndex = it - begin; @@ -1082,7 +1082,7 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols) QFragmentFindHelper helper(pos, p->fragmentMap()); const auto begin = d->cells.cbegin(); const auto it = std::lower_bound(begin, d->cells.cend(), helper); - Q_ASSERT(it != d->cells.end()); + Q_ASSERT(it != d->cells.cend()); Q_ASSERT(!(helper < *it)); Q_ASSERT(*it == fragment); firstCellIndex = cellIndex = it - begin; diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp index 6016d460fc..48693ccdb0 100644 --- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp @@ -222,7 +222,7 @@ bool QComposeInputContext::checkComposeTable() int next = 1; do { // if we are at the end of the table, then we have nothing to do here - if (it + next != m_composeTable.end()) { + if (it + next != m_composeTable.constEnd()) { QComposeTableElement nextElem = *(it + next); if (isDuplicate(elem, nextElem)) { elem = nextElem; diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 9a06fb38d0..a6725af924 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -992,7 +992,7 @@ static void mergeStringLiterals(Symbols *_symbols) mergeSymbolLexem.reserve(literalsLength); mergeSymbolLexem.append('"'); mergeSymbolLexem.append(mergeSymbolOriginalLexem); - for (Symbols::const_iterator j = mergeSymbol + 1; j != i; ++j) + for (Symbols::iterator j = mergeSymbol + 1; j != i; ++j) mergeSymbolLexem.append(j->lex.constData() + j->from + 1, j->len - 2); // append j->unquotedLexem() mergeSymbolLexem.append('"'); mergeSymbol->len = mergeSymbol->lex.length(); -- cgit v1.2.3 From 7a26582807b06d16d8d1b909a0c5ea34bcecfa42 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 9 Oct 2017 11:47:43 +0200 Subject: Make sure that QAccessibleWindowContainer::childCount is valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When embedding foreign windows, we won't be able to return a valid child accessible interface, so do not report it at all. Supporting foreign windows properly is platform specific and something to consider, but at least we shouldn't crash. Task-number: QTBUG-63451 Change-Id: I19350cf97dc8d0c3f3052411eba0eee5f750dbab Reviewed-by: Jan Arve Sæther --- src/widgets/accessible/simplewidgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index 73de51ff45..bacb00fe2e 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -953,7 +953,7 @@ QAccessibleWindowContainer::QAccessibleWindowContainer(QWidget *w) int QAccessibleWindowContainer::childCount() const { - if (container()->containedWindow()) + if (container()->containedWindow() && QAccessible::queryAccessibleInterface(container()->containedWindow())) return 1; return 0; } -- cgit v1.2.3 From 4e339a5ac1c3ef721d040dd88d84adc9930626c7 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 16 Jun 2017 14:27:19 +0200 Subject: Doc: QImageReader assumes exclusive control over its device Make an explicit mention of the fact that modifying a device while it is being held by a QImageReader is undefined. Task-number: QTBUG-61121 Change-Id: Ie0a016255c2614c5b8b415c8cd9602169153c8f8 Reviewed-by: Paul Olav Tvete --- src/gui/image/qimagereader.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index f49e90ba0a..e1089936c2 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -72,6 +72,11 @@ that occurred, or errorString() to get a human readable description of what went wrong. + \note QImageReader assumes exclusive control over the file or + device that is assigned. Any attempts to modify the assigned file + or device during the lifetime of the QImageReader object will + yield undefined results. + \section1 Formats Call supportedImageFormats() for a list of formats that -- cgit v1.2.3 From 9574436666c1806a69fdd5f7a83f41ad0f6152ac Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 21 Sep 2017 13:59:05 -0700 Subject: QUrl: make sure setPort(nonnegative) is taken as part of authority There were a couple of corner cases where doing setPort() would result in QUrl thinking that an authority was not present. Since the full URL parsing implies that a host is always present if the authority is present, then we also imply that setting the port number makes the host be present too. Change-Id: I69f37f9304f24709a823fffd14e67c12da18d69f Reviewed-by: David Faure --- src/corelib/io/qurl.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index a499dc2d30..cf7ed130ba 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -1037,6 +1037,7 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU { sectionIsPresent &= ~Authority; sectionIsPresent |= Host; + port = -1; // we never actually _loop_ while (from != end) { @@ -1061,10 +1062,8 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU } } - if (colonIndex == end - 1) { - // found a colon but no digits after it - port = -1; - } else if (uint(colonIndex) < uint(end)) { + if (uint(colonIndex) < uint(end) - 1) { + // found a colon with digits after it unsigned long x = 0; for (int i = colonIndex + 1; i < end; ++i) { ushort c = auth.at(i).unicode(); @@ -1083,8 +1082,6 @@ inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QU if (mode == QUrl::StrictMode) break; } - } else { - port = -1; } setHost(auth, from, qMin(end, colonIndex), mode); @@ -1644,8 +1641,7 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p if (path.isEmpty()) return NoError; if (path.at(0) == QLatin1Char('/')) { - if (sectionIsPresent & QUrlPrivate::Authority || port != -1 || - path.length() == 1 || path.at(1) != QLatin1Char('/')) + if (hasAuthority() || path.length() == 1 || path.at(1) != QLatin1Char('/')) return NoError; if (source) { *source = path; @@ -2474,6 +2470,8 @@ void QUrl::setPort(int port) } d->port = port; + if (port != -1) + d->sectionIsPresent |= QUrlPrivate::Host; } /*! -- cgit v1.2.3 From a1d62e61cbdf93dde52bfe34caf6e7c0073be679 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 26 Sep 2017 15:38:07 +0200 Subject: Synthesize LICENSE.txt for FreeType documentation The LICENSE.txt we showed so far only mentioned the two mutual licenses (FTL and GPLv2), whithout actually spelling them out. This is required though. [ChangeLog][Third-Party Code] Improve documentation about Freetype 2 licenses. Change-Id: I3af84b732aff58b12218cb7e8bb8e8de00c86307 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/3rdparty/freetype/LICENSE.txt | 551 ++++++++++++++++++++++++++++++ src/3rdparty/freetype/qt_attribution.json | 4 +- 2 files changed, 553 insertions(+), 2 deletions(-) create mode 100644 src/3rdparty/freetype/LICENSE.txt (limited to 'src') diff --git a/src/3rdparty/freetype/LICENSE.txt b/src/3rdparty/freetype/LICENSE.txt new file mode 100644 index 0000000000..382225f105 --- /dev/null +++ b/src/3rdparty/freetype/LICENSE.txt @@ -0,0 +1,551 @@ +The FreeType 2 font engine is copyrighted work and cannot be used +legally without a software license. In order to make this project +usable to a vast majority of developers, we distribute it under two +mutually exclusive open-source licenses. + +This means that *you* must choose *one* of the two licenses described +below, then obey all its terms and conditions when using FreeType 2 in +any of your projects or products. + + - The FreeType License, found in the file `FTL.TXT', which is similar + to the original BSD license *with* an advertising clause that forces + you to explicitly cite the FreeType project in your product's + documentation. All details are in the license file. This license + is suited to products which don't use the GNU General Public + License. + + Note that this license is compatible to the GNU General Public + License version 3, but not version 2. + + - The GNU General Public License version 2, found in `GPLv2.TXT' (any + later version can be used also), for programs which already use the + GPL. Note that the FTL is incompatible with GPLv2 due to its + advertisement clause. + +The contributed BDF and PCF drivers come with a license similar to that +of the X Window System. It is compatible to the above two licenses (see +file src/bdf/README and src/pcf/README). + +The gzip module uses the zlib license (see src/gzip/zlib.h) which too is +compatible to the above two licenses. + +The MD5 checksum support (only used for debugging in development builds) +is in the public domain. + + +--- FDL.TXT --- + + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + +--- end of FDL.TXT --- + +--- GPLv2.TXT --- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +--- end of GPLv2.TXT --- + diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index 6c11f1b617..0a8e47a2e0 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -7,7 +7,7 @@ "Description": "FreeType is a freely available software library to render fonts.", "Homepage": "http://www.freetype.org", "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL or GPL-2.0", - "LicenseFile": "docs/LICENSE.TXT", + "LicenseId": "FTL OR GPL-2.0", + "LicenseFile": "LICENSE.TXT", "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." } -- cgit v1.2.3 From 870423f98ba4a3a53e4a32a96c80535580eeb04e Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 26 Sep 2017 16:58:42 +0200 Subject: Freetype: Also list BDF, PCF, ZLIB licenses These are third party licenses that are part of freetype. Change-Id: I8c54feb6b5537ccfb0d0a4ffc24bc830c3c530e4 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/3rdparty/freetype/BDF-LICENSE.txt | 43 +++++++++++++++++++ src/3rdparty/freetype/PCF-LICENSE.txt | 20 +++++++++ src/3rdparty/freetype/ZLIB-LICENSE.txt | 20 +++++++++ src/3rdparty/freetype/qt_attribution.json | 69 +++++++++++++++++++++++++------ 4 files changed, 139 insertions(+), 13 deletions(-) create mode 100644 src/3rdparty/freetype/BDF-LICENSE.txt create mode 100644 src/3rdparty/freetype/PCF-LICENSE.txt create mode 100644 src/3rdparty/freetype/ZLIB-LICENSE.txt (limited to 'src') diff --git a/src/3rdparty/freetype/BDF-LICENSE.txt b/src/3rdparty/freetype/BDF-LICENSE.txt new file mode 100644 index 0000000000..6fb375cf8b --- /dev/null +++ b/src/3rdparty/freetype/BDF-LICENSE.txt @@ -0,0 +1,43 @@ +Copyright (C) 2001-2002 by Francesco Zappa Nardelli + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*** Portions of the driver (that is, bdflib.c and bdf.h): + +Copyright 2000 Computing Research Labs, New Mexico State University +Copyright 2001-2002, 2011 Francesco Zappa Nardelli + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/3rdparty/freetype/PCF-LICENSE.txt b/src/3rdparty/freetype/PCF-LICENSE.txt new file mode 100644 index 0000000000..3f3a3b3f0c --- /dev/null +++ b/src/3rdparty/freetype/PCF-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (C) 2000 by Francesco Zappa Nardelli + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/3rdparty/freetype/ZLIB-LICENSE.txt b/src/3rdparty/freetype/ZLIB-LICENSE.txt new file mode 100644 index 0000000000..abbdfcc017 --- /dev/null +++ b/src/3rdparty/freetype/ZLIB-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index 0a8e47a2e0..e00f2062b0 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -1,13 +1,56 @@ -{ - "Id": "freetype", - "Name": "Freetype 2", - "QDocModule": "qtgui", - "QtUsage": "Optionally used in Qt GUI and platform plugins. Configure with -no-freetype, or -system-freetype to avoid.", - - "Description": "FreeType is a freely available software library to render fonts.", - "Homepage": "http://www.freetype.org", - "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL OR GPL-2.0", - "LicenseFile": "LICENSE.TXT", - "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." -} +[ + { + "Id": "freetype", + "Name": "Freetype 2", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in Qt GUI and platform plugins. Configure with -no-freetype, or -system-freetype to avoid.", + + "Description": "FreeType is a freely available software library to render fonts.", + "Homepage": "http://www.freetype.org", + "License": "Freetype Project License or GNU General Public License v2.0 only", + "LicenseId": "FTL OR GPL-2.0", + "LicenseFile": "LICENSE.TXT", + "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." + }, + { + "Id": "freetype-zlib", + "Name": "Freetype 2 - zlib", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in Qt GUI and platform plugins. Configure with -no-freetype, or -system-freetype to avoid.", + + "Description": "FreeType is a freely available software library to render fonts.", + "Homepage": "http://www.freetype.org", + "License": "zlib License", + "LicenseId": "Zlib", + "LicenseFile": "ZLIB-LICENSE.TXT", + "Copyright": "Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler" + }, + { + "Id": "freetype-bdf", + "Name": "Freetype 2 - Bitmap Distribution Format (BDF) support", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in Qt GUI and platform plugins. Configure with -no-freetype, or -system-freetype to avoid.", + + "Description": "FreeType is a freely available software library to render fonts.", + "Homepage": "http://www.freetype.org", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "BDF-LICENSE.TXT", + "Copyright": "Copyright (C) 2001-2002 by Francesco Zappa Nardelli +Copyright 2000 Computing Research Labs, New Mexico State University +Copyright 2001-2002, 2011 Francesco Zappa Nardelli" + }, + { + "Id": "freetype-pcf", + "Name": "Freetype 2 - Portable Compiled Format (PCF) support", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in Qt GUI and platform plugins. Configure with -no-freetype, or -system-freetype to avoid.", + + "Description": "FreeType is a freely available software library to render fonts.", + "Homepage": "http://www.freetype.org", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "PCF-LICENSE.TXT", + "Copyright": "Copyright (C) 2000 by Francesco Zappa Nardelli" + } +] -- cgit v1.2.3 From 0bd4b194d13b76456fa74330f40cc76a0a2d2b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 23 Oct 2017 12:50:52 +0200 Subject: Replace unneeded nullptr-checks with ASSERTS The manager and managerPrivate member variables are set in the constructor and never changed after that. Change-Id: I7cc2fd2eb3f50bdc529ed29485e74bf9c016b0c0 Coverity-Id: 185272 Reviewed-by: Timur Pocheptsov Reviewed-by: Edward Welbourne --- src/network/access/qnetworkreplyhttpimpl.cpp | 72 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index c1a9f628a0..73f88025ac 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -182,6 +182,7 @@ QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manage : QNetworkReply(*new QNetworkReplyHttpImplPrivate, manager) { Q_D(QNetworkReplyHttpImpl); + Q_ASSERT(manager); d->manager = manager; d->managerPrivate = manager->d_func(); d->request = request; @@ -394,9 +395,9 @@ bool QNetworkReplyHttpImpl::canReadLine () const void QNetworkReplyHttpImpl::ignoreSslErrors() { Q_D(QNetworkReplyHttpImpl); + Q_ASSERT(d->managerPrivate); - if (d->managerPrivate && d->managerPrivate->stsEnabled - && d->managerPrivate->stsCache.isKnownHost(url())) { + if (d->managerPrivate->stsEnabled && d->managerPrivate->stsCache.isKnownHost(url())) { // We cannot ignore any Security Transport-related errors for this host. return; } @@ -407,9 +408,9 @@ void QNetworkReplyHttpImpl::ignoreSslErrors() void QNetworkReplyHttpImpl::ignoreSslErrorsImplementation(const QList &errors) { Q_D(QNetworkReplyHttpImpl); + Q_ASSERT(d->managerPrivate); - if (d->managerPrivate && d->managerPrivate->stsEnabled - && d->managerPrivate->stsCache.isKnownHost(url())) { + if (d->managerPrivate->stsEnabled && d->managerPrivate->stsCache.isKnownHost(url())) { // We cannot ignore any Security Transport-related errors for this host. return; } @@ -1144,6 +1145,8 @@ QNetworkRequest QNetworkReplyHttpImplPrivate::createRedirectRequest(const QNetwo void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int httpStatus, int maxRedirectsRemaining) { Q_Q(QNetworkReplyHttpImpl); + Q_ASSERT(manager); + Q_ASSERT(managerPrivate); if (isFinished) return; @@ -1178,7 +1181,7 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt redirectRequest = createRedirectRequest(originalRequest, url, maxRedirectsRemaining); operation = getRedirectOperation(operation, httpStatus); - if (const QNetworkCookieJar *const cookieJar = (manager ? manager->cookieJar() : nullptr)) { + if (const QNetworkCookieJar *const cookieJar = manager->cookieJar()) { auto cookies = cookieJar->cookiesForUrl(url); if (!cookies.empty()) { redirectRequest.setHeader(QNetworkRequest::KnownHeaders::CookieHeader, @@ -1195,6 +1198,7 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt void QNetworkReplyHttpImplPrivate::followRedirect() { Q_Q(QNetworkReplyHttpImpl); + Q_ASSERT(managerPrivate); rawHeaders.clear(); cookedHeaders.clear(); @@ -1206,7 +1210,7 @@ void QNetworkReplyHttpImplPrivate::followRedirect() // If the original request didn't need a session (i.e. it was to localhost) // then we might not have a session open, to which to redirect, if the // new URL is remote. When this happens, we need to open the session now: - if (managerPrivate && isSessionNeeded(url)) { + if (isSessionNeeded(url)) { if (auto session = managerPrivate->getNetworkSession()) { if (session->state() != QNetworkSession::State::Connected || !session->isOpen()) { startWaitForSession(session); @@ -2039,9 +2043,7 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData() void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() { Q_Q(QNetworkReplyHttpImpl); - - if (!manager) - return; + Q_ASSERT(managerPrivate); QSharedPointer session = managerPrivate->getNetworkSession(); if (!session) @@ -2171,28 +2173,27 @@ void QNetworkReplyHttpImplPrivate::finished() if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; - if (manager) { #ifndef QT_NO_BEARERMANAGEMENT - QSharedPointer session = managerPrivate->getNetworkSession(); - if (session && session->state() == QNetworkSession::Roaming && - state == Working && errorCode != QNetworkReply::OperationCanceledError) { - // only content with a known size will fail with a temporary network failure error - if (!totalSize.isNull()) { - if (bytesDownloaded != totalSize) { - if (migrateBackend()) { - // either we are migrating or the request is finished/aborted - if (state == Reconnecting || state == WaitingForSession) { - return; // exit early if we are migrating. - } - } else { - error(QNetworkReply::TemporaryNetworkFailureError, - QNetworkReply::tr("Temporary network failure.")); + Q_ASSERT(managerPrivate); + QSharedPointer session = managerPrivate->getNetworkSession(); + if (session && session->state() == QNetworkSession::Roaming && + state == Working && errorCode != QNetworkReply::OperationCanceledError) { + // only content with a known size will fail with a temporary network failure error + if (!totalSize.isNull()) { + if (bytesDownloaded != totalSize) { + if (migrateBackend()) { + // either we are migrating or the request is finished/aborted + if (state == Reconnecting || state == WaitingForSession) { + return; // exit early if we are migrating. } + } else { + error(QNetworkReply::TemporaryNetworkFailureError, + QNetworkReply::tr("Temporary network failure.")); } } } -#endif } +#endif // if we don't know the total size of or we received everything save the cache if (totalSize.isNull() || totalSize == -1 || bytesDownloaded == totalSize) @@ -2250,17 +2251,16 @@ void QNetworkReplyHttpImplPrivate::_q_metaDataChanged() Q_Q(QNetworkReplyHttpImpl); // 1. do we have cookies? // 2. are we allowed to set them? - if (manager) { - const auto it = cookedHeaders.constFind(QNetworkRequest::SetCookieHeader); - if (it != cookedHeaders.cend() - && request.attribute(QNetworkRequest::CookieSaveControlAttribute, - QNetworkRequest::Automatic).toInt() == QNetworkRequest::Automatic) { - QNetworkCookieJar *jar = manager->cookieJar(); - if (jar) { - QList cookies = - qvariant_cast >(it.value()); - jar->setCookiesFromUrl(cookies, url); - } + Q_ASSERT(manager); + const auto it = cookedHeaders.constFind(QNetworkRequest::SetCookieHeader); + if (it != cookedHeaders.cend() + && request.attribute(QNetworkRequest::CookieSaveControlAttribute, + QNetworkRequest::Automatic).toInt() == QNetworkRequest::Automatic) { + QNetworkCookieJar *jar = manager->cookieJar(); + if (jar) { + QList cookies = + qvariant_cast >(it.value()); + jar->setCookiesFromUrl(cookies, url); } } emit q->metaDataChanged(); -- cgit v1.2.3 From 70b0c127f020205c3b0a892544d12dfd637b0919 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 25 Oct 2017 15:48:52 +0200 Subject: Fix private includes in qhttp2protocolhandler_p.h This file could not be included by user code in an installed Qt. Change-Id: Id222d56dda9ef47d010ab947efa01bf63ecac050 Reviewed-by: Timur Pocheptsov --- src/network/access/qhttp2protocolhandler_p.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h index df0cf6a288..5e04c79376 100644 --- a/src/network/access/qhttp2protocolhandler_p.h +++ b/src/network/access/qhttp2protocolhandler_p.h @@ -57,11 +57,11 @@ #if !defined(QT_NO_HTTP) -#include "http2/http2protocol_p.h" -#include "http2/http2streams_p.h" -#include "http2/http2frames_p.h" -#include "http2/hpacktable_p.h" -#include "http2/hpack_p.h" +#include +#include +#include +#include +#include #include #include -- cgit v1.2.3 From e8d2e831a4054a7519c60b11d1ba9e6bec85c3bd Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 11 Oct 2017 15:19:17 +0300 Subject: QSslSocket::waitForDisconnected(): flush write buffer before waiting Otherwise, the plain socket might be blocked indefinitely on waiting for socket activity. This issue is tested by tst_QSslSocket::disconnectFromHostWhenConnected() which was unstable in CI. Task-number: QTBUG-64016 Change-Id: I6a1a111dea4d1d1adaf55e6a90c0c5f995a270af Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslsocket.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 9d11506fcb..8eba5db9fe 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1686,7 +1686,8 @@ bool QSslSocket::waitForDisconnected(int msecs) if (!d->plainSocket) return false; - if (d->mode == UnencryptedMode) + // Forward to the plain socket unless the connection is secure. + if (d->mode == UnencryptedMode && !d->autoStartHandshake) return d->plainSocket->waitForDisconnected(msecs); QElapsedTimer stopWatch; @@ -1697,6 +1698,17 @@ bool QSslSocket::waitForDisconnected(int msecs) if (!waitForEncrypted(msecs)) return false; } + // We are delaying the disconnect, if the write buffer is not empty. + // So, start the transmission. + if (!d->writeBuffer.isEmpty()) + d->transmit(); + + // At this point, the socket might be disconnected, if disconnectFromHost() + // was called just after the connectToHostEncrypted() call. Also, we can + // lose the connection as a result of the transmit() call. + if (state() == UnconnectedState) + return true; + bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); if (!retVal) { setSocketState(d->plainSocket->state()); -- cgit v1.2.3 From 9f0dda29d5d070f63b7f098139f01f07ec91ffdf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Oct 2017 10:24:19 +0200 Subject: Windows QPA: Restrict warning about geometry failure Print warning only for visible windows or in debug mode. Task-number: QTBUG-63661 Change-Id: I742c86afcb40455074a6de753b0b1ce6a11d55af Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowswindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 16c2e16d64..402009c70d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -66,6 +66,7 @@ #include #include +#include #include @@ -1473,7 +1474,7 @@ void QWindowsWindow::setGeometry(const QRect &rectIn) // achieve that size (for example, window title minimal constraint), // notify and warn. setGeometry_sys(rect); - if (m_data.geometry != rect) { + if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) { qWarning("%s: Unable to set geometry %dx%d+%d+%d on %s/'%s'." " Resulting geometry: %dx%d+%d+%d " "(frame: %d, %d, %d, %d, custom margin: %d, %d, %d, %d" -- cgit v1.2.3 From acdb3340321d1b8823b54f2ea492f975c6f942d8 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 27 Oct 2017 08:36:25 +0200 Subject: Fix dragging inside a modal window when a QShapedPixmapWindow is used A regression was introduced with a3d59c7c7f675b0a4e128efeb781aa1c2f7db4c0 which caused dragging to fail within a modal dialog on the XCB platform. By adding an exception for the QShapedPixmapWindow, which is the window used for the drag, we can allow that to continue to work whilst blocking to the other newly created windows. Task-number: QTBUG-63846 Change-Id: I7c7f365f30fcf5f04f50dc1a7fff7a09e6e5ed6c Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 43b201e9b0..9e5b687851 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -54,6 +54,7 @@ # include "qaccessible.h" #endif #include "qhighdpiscaling_p.h" +#include "qshapedpixmapdndwindow_p.h" #include @@ -576,7 +577,9 @@ void QWindow::setVisible(bool visible) QGuiApplicationPrivate::showModalWindow(this); else QGuiApplicationPrivate::hideModalWindow(this); - } else if (visible && QGuiApplication::modalWindow()) { + // QShapedPixmapWindow is used on some platforms for showing a drag pixmap, so don't block + // input to this window as it is performing a drag - QTBUG-63846 + } else if (visible && QGuiApplication::modalWindow() && !qobject_cast(this)) { QGuiApplicationPrivate::updateBlockedStatus(this); } -- cgit v1.2.3 From 3a92f7cf4f1abd7ad91bdfc7251b1f3e82bdf89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 25 Oct 2017 15:43:30 +0200 Subject: macOS: Retain NSWindow during event delivery We have logic to deal with self.platformWindow and frame strut mouse events which happens after delivering the event to the NSWindow, but delivering it might dealloc the window, e.g. when closing it, so we need to explicitly retain it for the duration of [QNSWindow sendEvent:] Task-number: QTBUG-64023 Change-Id: I223fe3e3ac36a309da375522ba11f20f1ad6fc4f Reviewed-by: Timur Pocheptsov Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qnswindow.mm | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 799704a407..5213008bd4 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -185,6 +185,10 @@ static bool isMouseEvent(NSEvent *ev) if (!self.platformWindow) return; + // Prevent deallocation of this NSWindow during event delivery, as we + // have logic further below that depends on the window being alive. + [[self retain] autorelease]; + const char *eventType = object_getClassName(theEvent); if (QWindowSystemInterface::handleNativeEvent(self.platformWindow->window(), QByteArray::fromRawData(eventType, qstrlen(eventType)), theEvent, nullptr)) { @@ -221,6 +225,7 @@ static bool isMouseEvent(NSEvent *ev) #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" - (void)dealloc { + qCDebug(lcQpaCocoaWindow) << "dealloc" << self; qt_objcDynamicSuper(); } #pragma clang diagnostic pop -- cgit v1.2.3 From f4090b23b98c132c47237e4695bc4dc93170cbe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 25 Oct 2017 13:05:49 +0200 Subject: macOS: Add categorized logging of event and notification forwarding Useful for debugging issues in this area. Change-Id: Ic343ef790e20b66371028265efe2ec1816c954bd Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 17 ++++++++++++++++- src/plugins/platforms/cocoa/qnswindow.mm | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index ed942af1b1..af44564968 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -79,6 +79,8 @@ static void qt_closePopups() } } +Q_LOGGING_CATEGORY(lcCocoaNotifications, "qt.qpa.cocoa.notifications"); + static void qRegisterNotificationCallbacks() { static const QLatin1String notificationHandlerPrefix(Q_NOTIFICATION_PREFIX); @@ -110,11 +112,24 @@ static void qRegisterNotificationCallbacks() if (QNSView *qnsView = qnsview_cast(notification.object)) cocoaWindows += qnsView.platformWindow; } else { - qCWarning(lcQpaCocoaWindow) << "Unhandled notifcation" + qCWarning(lcCocoaNotifications) << "Unhandled notifcation" << notification.name << "for" << notification.object; return; } + if (lcCocoaNotifications().isDebugEnabled()) { + if (cocoaWindows.isEmpty()) { + qCDebug(lcCocoaNotifications) << "Could not find forwarding target for" << + qPrintable(notificationName) << "from" << notification.object; + } else { + QVector debugWindows; + for (QCocoaWindow *cocoaWindow : cocoaWindows) + debugWindows += cocoaWindow; + qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) << + "to" << debugWindows; + } + } + // FIXME: Could be a foreign window, look up by iterating top level QWindows for (QCocoaWindow *cocoaWindow : cocoaWindows) { diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 5213008bd4..e846fa043c 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -46,6 +46,8 @@ #include #include +Q_LOGGING_CATEGORY(lcCocoaEvents, "qt.qpa.cocoa.events"); + static bool isMouseEvent(NSEvent *ev) { switch ([ev type]) { @@ -116,6 +118,22 @@ static bool isMouseEvent(NSEvent *ev) return qnsview_cast(self.contentView).platformWindow; } +- (NSString *)description +{ + NSMutableString *description = [NSMutableString stringWithString:qt_objcDynamicSuper()]; + +#ifndef QT_NO_DEBUG_STREAM + QString contentViewDescription; + QDebug debug(&contentViewDescription); + debug.nospace() << "; contentView=" << qnsview_cast(self.contentView) << ">"; + + NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1]; + [description replaceCharactersInRange:lastCharacter withString:contentViewDescription.toNSString()]; +#endif + + return description; +} + - (BOOL)canBecomeKeyWindow { QCocoaWindow *pw = self.platformWindow; @@ -177,6 +195,8 @@ static bool isMouseEvent(NSEvent *ev) - (void)sendEvent:(NSEvent*)theEvent { + qCDebug(lcCocoaEvents) << "Sending" << theEvent << "to" << self; + // We might get events for a NSWindow after the corresponding platform // window has been deleted, as the NSWindow can outlive the QCocoaWindow // e.g. if being retained by other parts of AppKit, or in an auto-release -- cgit v1.2.3 From e6fb36389e7f69e852c10c79d0af72f85ade300b Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 24 Oct 2017 18:59:55 +0200 Subject: QDateTimeParser: Remove unused variable Change-Id: Iaa6460d4eb96632f3cb03bc29b57934c53cbf88e Reviewed-by: Jesus Fernandez Reviewed-by: Edward Welbourne --- src/corelib/tools/qdatetimeparser.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 978b663444..dd277f7753 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -1090,7 +1090,6 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, int dayofweek = defaultDate.dayOfWeek(); Qt::TimeSpec tspec = defaultValue.timeSpec(); int zoneOffset = 0; // In seconds; local - UTC - QString zoneName; QTimeZone timeZone; switch (tspec) { case Qt::OffsetFromUTC: // timeZone is ignored -- cgit v1.2.3 From 6ca6efb22aae2c80868c5d0d8f50b55505cfc0d6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 21 Aug 2017 16:16:20 -0700 Subject: Fix unused variable warning when compiling in release mode with GCC 7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit error: unused variable ‘ret’ [-Werror=unused-variable] Change-Id: I6e9274c1e7444ad48c81fffd14dcff9278d4376b Reviewed-by: Lars Knoll --- src/corelib/global/qrandom.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 0bbe79aeb4..9abb9ece7f 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -138,11 +138,13 @@ public: // getentropy can't fail under normal circumstances int ret = getentropy(reinterpret_cast(buffer) + read, 256); Q_ASSERT(ret == 0); + Q_UNUSED(ret); read += 256; } int ret = getentropy(reinterpret_cast(buffer) + read, count - read); Q_ASSERT(ret == 0); + Q_UNUSED(ret); return count; } }; -- cgit v1.2.3 From 38bc9956079e2291d19b15d68cc2e6dd4a20f202 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 31 Oct 2017 09:21:44 +0100 Subject: Fix redundant Vulkan logging category definition Task-number: QTBUG-64124 Change-Id: Ic8f9a7f62e3c00dba5f345037c45fb45908be848 Reviewed-by: Andy Nichols --- src/gui/vulkan/qvulkanwindow.cpp | 44 +++++++++++----------- .../vkconvenience/qbasicvulkanplatforminstance.cpp | 12 +++--- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index bc82f5df08..7dea743ea8 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcVk, "qt.vulkan") +Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan") /*! \class QVulkanWindow @@ -357,7 +357,7 @@ QVector QVulkanWindow::availablePhysicalDevices() return d->physDevProps; } - qCDebug(lcVk, "%d physical devices", count); + qCDebug(lcGuiVk, "%d physical devices", count); if (!count) return d->physDevProps; @@ -373,7 +373,7 @@ QVector QVulkanWindow::availablePhysicalDevices() for (uint32_t i = 0; i < count; ++i) { VkPhysicalDeviceProperties *p = &d->physDevProps[i]; f->vkGetPhysicalDeviceProperties(d->physDevs.at(i), p); - qCDebug(lcVk, "Physical device [%d]: name '%s' version %d.%d.%d", i, p->deviceName, + qCDebug(lcGuiVk, "Physical device [%d]: name '%s' version %d.%d.%d", i, p->deviceName, VK_VERSION_MAJOR(p->driverVersion), VK_VERSION_MINOR(p->driverVersion), VK_VERSION_PATCH(p->driverVersion)); } @@ -442,7 +442,7 @@ QVulkanInfoVector QVulkanWindow::supportedDeviceExtensions() exts.append(ext); } d->supportedDevExtensions.insert(physDev, exts); - qDebug(lcVk) << "Supported device extensions:" << exts; + qDebug(lcGuiVk) << "Supported device extensions:" << exts; return exts; } } @@ -615,7 +615,7 @@ void QVulkanWindowPrivate::init() Q_Q(QVulkanWindow); Q_ASSERT(status == StatusUninitialized); - qCDebug(lcVk, "QVulkanWindow init"); + qCDebug(lcGuiVk, "QVulkanWindow init"); inst = q->vulkanInstance(); if (!inst) { @@ -648,7 +648,7 @@ void QVulkanWindowPrivate::init() qWarning("QVulkanWindow: Invalid physical device index; defaulting to 0"); physDevIndex = 0; } - qCDebug(lcVk, "Using physical device [%d]", physDevIndex); + qCDebug(lcGuiVk, "Using physical device [%d]", physDevIndex); // Give a last chance to do decisions based on the physical device and the surface. if (renderer) @@ -665,7 +665,7 @@ void QVulkanWindowPrivate::init() presQueueFamilyIdx = uint32_t(-1); for (int i = 0; i < queueFamilyProps.count(); ++i) { const bool supportsPresent = inst->supportsPresent(physDev, i, q); - qCDebug(lcVk, "queue family %d: flags=0x%x count=%d supportsPresent=%d", i, + qCDebug(lcGuiVk, "queue family %d: flags=0x%x count=%d supportsPresent=%d", i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount, supportsPresent); if (gfxQueueFamilyIdx == uint32_t(-1) && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) @@ -675,7 +675,7 @@ void QVulkanWindowPrivate::init() if (gfxQueueFamilyIdx != uint32_t(-1)) { presQueueFamilyIdx = gfxQueueFamilyIdx; } else { - qCDebug(lcVk, "No queue with graphics+present; trying separate queues"); + qCDebug(lcGuiVk, "No queue with graphics+present; trying separate queues"); for (int i = 0; i < queueFamilyProps.count(); ++i) { if (gfxQueueFamilyIdx == uint32_t(-1) && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) gfxQueueFamilyIdx = i; @@ -698,7 +698,7 @@ void QVulkanWindowPrivate::init() if (qEnvironmentVariableIsSet("QT_VK_PRESENT_QUEUE_INDEX")) presQueueFamilyIdx = qEnvironmentVariableIntValue("QT_VK_PRESENT_QUEUE_INDEX"); #endif - qCDebug(lcVk, "Using queue families: graphics = %u present = %u", gfxQueueFamilyIdx, presQueueFamilyIdx); + qCDebug(lcGuiVk, "Using queue families: graphics = %u present = %u", gfxQueueFamilyIdx, presQueueFamilyIdx); VkDeviceQueueCreateInfo queueInfo[2]; const float prio[] = { 0 }; @@ -724,7 +724,7 @@ void QVulkanWindowPrivate::init() if (supportedExtensions.contains(ext)) devExts.append(ext.constData()); } - qCDebug(lcVk) << "Enabling device extensions:" << devExts; + qCDebug(lcGuiVk) << "Enabling device extensions:" << devExts; VkDeviceCreateInfo devInfo; memset(&devInfo, 0, sizeof(devInfo)); @@ -774,7 +774,7 @@ void QVulkanWindowPrivate::init() physDevs.clear(); physDevProps.clear(); status = StatusUninitialized; - qCDebug(lcVk, "Attempting to restart in 2 seconds"); + qCDebug(lcGuiVk, "Attempting to restart in 2 seconds"); QTimer::singleShot(2000, q, [this]() { ensureStarted(); }); return; } @@ -819,7 +819,7 @@ void QVulkanWindowPrivate::init() f->vkGetPhysicalDeviceMemoryProperties(physDev, &physDevMemProps); for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) { const VkMemoryType *memType = physDevMemProps.memoryTypes; - qCDebug(lcVk, "memtype %d: flags=0x%x", i, memType[i].propertyFlags); + qCDebug(lcGuiVk, "memtype %d: flags=0x%x", i, memType[i].propertyFlags); // Find a host visible, host coherent memtype. If there is one that is // cached as well (in addition to being coherent), prefer that. const int hostVisibleAndCoherent = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; @@ -831,7 +831,7 @@ void QVulkanWindowPrivate::init() } } } - qCDebug(lcVk, "Picked memtype %d for host visible memory", hostVisibleMemIndex); + qCDebug(lcGuiVk, "Picked memtype %d for host visible memory", hostVisibleMemIndex); deviceLocalMemIndex = 0; for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) { const VkMemoryType *memType = physDevMemProps.memoryTypes; @@ -841,7 +841,7 @@ void QVulkanWindowPrivate::init() break; } } - qCDebug(lcVk, "Picked memtype %d for device local memory", deviceLocalMemIndex); + qCDebug(lcGuiVk, "Picked memtype %d for device local memory", deviceLocalMemIndex); if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR || !vkGetPhysicalDeviceSurfaceFormatsKHR) { vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast( @@ -906,7 +906,7 @@ void QVulkanWindowPrivate::init() if (dsFormatIdx == dsFormatCandidateCount) qWarning("QVulkanWindow: Failed to find an optimal depth-stencil format"); - qCDebug(lcVk, "Color format: %d Depth-stencil format: %d", colorFormat, dsFormat); + qCDebug(lcGuiVk, "Color format: %d Depth-stencil format: %d", colorFormat, dsFormat); if (!createDefaultRenderPass()) return; @@ -922,7 +922,7 @@ void QVulkanWindowPrivate::reset() if (!dev) // do not rely on 'status', a half done init must be cleaned properly too return; - qCDebug(lcVk, "QVulkanWindow reset"); + qCDebug(lcGuiVk, "QVulkanWindow reset"); devFuncs->vkDeviceWaitIdle(dev); @@ -1118,7 +1118,7 @@ void QVulkanWindowPrivate::recreateSwapChain() swapChainInfo.clipped = true; swapChainInfo.oldSwapchain = oldSwapChain; - qCDebug(lcVk, "Creating new swap chain of %d buffers, size %dx%d", reqBufferCount, bufferSize.width, bufferSize.height); + qCDebug(lcGuiVk, "Creating new swap chain of %d buffers, size %dx%d", reqBufferCount, bufferSize.width, bufferSize.height); VkSwapchainKHR newSwapChain; VkResult err = vkCreateSwapchainKHR(dev, &swapChainInfo, nullptr, &newSwapChain); @@ -1139,7 +1139,7 @@ void QVulkanWindowPrivate::recreateSwapChain() return; } - qCDebug(lcVk, "Actual swap chain buffer count: %d (supportsReadback=%d)", + qCDebug(lcGuiVk, "Actual swap chain buffer count: %d (supportsReadback=%d)", actualSwapChainBufferCount, swapChainSupportsReadBack); if (actualSwapChainBufferCount > MAX_SWAPCHAIN_BUFFER_COUNT) { qWarning("QVulkanWindow: Too many swapchain buffers (%d)", actualSwapChainBufferCount); @@ -1389,7 +1389,7 @@ bool QVulkanWindowPrivate::createTransientImage(VkFormat format, return false; } startIndex = memInfo.memoryTypeIndex + 1; - qCDebug(lcVk, "Allocating %u bytes for transient image (memtype %u)", + qCDebug(lcGuiVk, "Allocating %u bytes for transient image (memtype %u)", uint32_t(memInfo.allocationSize), memInfo.memoryTypeIndex); err = devFuncs->vkAllocateMemory(dev, &memInfo, nullptr, mem); if (err != VK_SUCCESS && err != VK_ERROR_OUT_OF_DEVICE_MEMORY) { @@ -1435,7 +1435,7 @@ void QVulkanWindowPrivate::releaseSwapChain() if (!dev || !swapChain) // do not rely on 'status', a half done init must be cleaned properly too return; - qCDebug(lcVk, "Releasing swapchain"); + qCDebug(lcGuiVk, "Releasing swapchain"); devFuncs->vkDeviceWaitIdle(dev); @@ -2059,10 +2059,10 @@ bool QVulkanWindowPrivate::checkDeviceLost(VkResult err) qWarning("QVulkanWindow: Device lost"); if (renderer) renderer->logicalDeviceLost(); - qCDebug(lcVk, "Releasing all resources due to device lost"); + qCDebug(lcGuiVk, "Releasing all resources due to device lost"); releaseSwapChain(); reset(); - qCDebug(lcVk, "Restarting"); + qCDebug(lcGuiVk, "Restarting"); ensureStarted(); return true; } diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp index 1a2a07260a..382d142334 100644 --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcVk, "qt.vulkan") +Q_LOGGING_CATEGORY(lcPlatVk, "qt.vulkan") /*! \class QBasicPlatformVulkanInstance @@ -87,7 +87,7 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib) if (m_vkGetInstanceProcAddr) return; - qCDebug(lcVk, "Vulkan init (%s)", qPrintable(lib->fileName())); + qCDebug(lcPlatVk, "Vulkan init (%s)", qPrintable(lib->fileName())); // While not strictly required with every implementation, try to follow the spec // and do not rely on core functions being exported. @@ -137,7 +137,7 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib) m_supportedLayers.append(layer); } } - qCDebug(lcVk) << "Supported Vulkan instance layers:" << m_supportedLayers; + qCDebug(lcPlatVk) << "Supported Vulkan instance layers:" << m_supportedLayers; uint32_t extCount = 0; m_vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr); @@ -152,7 +152,7 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib) m_supportedExtensions.append(ext); } } - qDebug(lcVk) << "Supported Vulkan instance extensions:" << m_supportedExtensions; + qDebug(lcPlatVk) << "Supported Vulkan instance extensions:" << m_supportedExtensions; } QVulkanInfoVector QBasicPlatformVulkanInstance::supportedLayers() const @@ -206,13 +206,13 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const if (!m_supportedLayers.contains(layerName)) m_enabledLayers.removeAt(i--); } - qDebug(lcVk) << "Enabling Vulkan instance layers:" << m_enabledLayers; + qDebug(lcPlatVk) << "Enabling Vulkan instance layers:" << m_enabledLayers; for (int i = 0; i < m_enabledExtensions.count(); ++i) { const QByteArray &extName(m_enabledExtensions[i]); if (!m_supportedExtensions.contains(extName)) m_enabledExtensions.removeAt(i--); } - qDebug(lcVk) << "Enabling Vulkan instance extensions:" << m_enabledExtensions; + qDebug(lcPlatVk) << "Enabling Vulkan instance extensions:" << m_enabledExtensions; VkInstanceCreateInfo instInfo; memset(&instInfo, 0, sizeof(instInfo)); -- cgit v1.2.3 From 89951262bf8bbc764ee15be53e63e0294dae15db Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 31 Oct 2017 11:58:26 +0100 Subject: Drop qvulkan headers from QtGui master header ...in order to allow applications built against Vulkan-enabled pre-built packages to include on systems without Vulkan headers. This has the downside of not being able to pull in qvulkan* headers via the master header. This is an acceptable compromise for now. Task-number: QTBUG-64073 Change-Id: I63c5834dcec60e66aba34c003d4bfe8e7d31607f Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Oswald Buddenhagen --- src/gui/vulkan/qvulkaninstance.h | 4 ++++ src/gui/vulkan/qvulkanwindow.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index ada297be43..57459e458c 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -42,6 +42,10 @@ #include +#if 0 +#pragma qt_no_master_include +#endif + #if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC) #ifndef VK_NO_PROTOTYPES diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h index 65249ecbfc..927c81042f 100644 --- a/src/gui/vulkan/qvulkanwindow.h +++ b/src/gui/vulkan/qvulkanwindow.h @@ -42,6 +42,10 @@ #include +#if 0 +#pragma qt_no_master_include +#endif + #if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC) #include -- cgit v1.2.3 From 58f46077015fc5dd71543ca25f762ff34fc12621 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 3 Nov 2017 11:02:51 +0100 Subject: QWindowPrivate::globalPosition(): Take embedded windows into account MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QPlatformWindow::mapToGlobal() should also be used in case a window is embedded. Task-number: QTBUG-64116 Change-Id: I1fbdf3d185659d0faea13a593db901e36ab27d8d Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 9969124339..369f3ea3ab 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2575,7 +2575,7 @@ QPoint QWindowPrivate::globalPosition() const QPoint offset = q->position(); for (const QWindow *p = q->parent(); p; p = p->parent()) { QPlatformWindow *pw = p->handle(); - if (pw && pw->isForeignWindow()) { + if (pw && (pw->isForeignWindow() || pw->isEmbedded())) { // Use mapToGlobal() for foreign windows offset += p->mapToGlobal(QPoint(0, 0)); break; -- cgit v1.2.3 From c988a8a28214914d20f4b8858e7f314a51b27507 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 3 Oct 2017 10:10:46 +0200 Subject: Make QCOMPARE print QColor alpha values on failure Currently, when two colors are equal except for their alpha values, QCOMPARE produces the following failure message: FAIL! : tst_Test::test() Compared values are not the same Actual (colorA): #ff0000 Expected (colorB): #ff0000 By using the HexArgb format instead of the default HexRgb, we can see the full hex string, with alpha values included: FAIL! : tst_Test::test() Compared values are not the same Actual (colorA): #88ff0000 Expected (colorB): #ffff0000 Task-number: QTBUG-55574 Change-Id: Id82c60a1b473ac6025a6f6ac560fce95a910d782 Reviewed-by: Friedemann Kleint Reviewed-by: Edward Welbourne --- src/testlib/qtest_gui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index d848f08d55..2b486aae5d 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -83,7 +83,7 @@ namespace QTest */ template<> inline char *toString(const QColor &color) { - return qstrdup(color.name().toLocal8Bit().constData()); + return qstrdup(color.name(QColor::HexArgb).toLocal8Bit().constData()); } template<> inline char *toString(const QRegion ®ion) -- cgit v1.2.3 From 2b7cf045bfbfa5d379698fdc18a3d200487a9457 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 30 Oct 2017 15:27:57 +0100 Subject: Replace includes with qglobal.h Nothing (except the *global*.h headers themselves) is supposed to include the generated *config*.h files directly. The QtConfig forwarding header should not exist in the first place. Change-Id: I5e9edd25d905582381cdc6386804c1f3ef8716ae Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/windows/accessible/iaccessible2.cpp | 2 +- src/plugins/platforms/windows/accessible/iaccessible2.h | 2 +- src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp | 2 +- src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp | 2 +- src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h | 3 +-- 5 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 9239facb0c..75af65b5ab 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -36,7 +36,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include +#include #ifndef QT_NO_ACCESSIBILITY #include "iaccessible2.h" diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index e56106f247..d987016e15 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -39,7 +39,7 @@ #ifndef IACCESSIBLE2_H #define IACCESSIBLE2_H -#include +#include #ifndef QT_NO_ACCESSIBILITY #include "qwindowscombase.h" diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index e214d47137..d48cb9674f 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include +#include #ifndef QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 47b179250a..fe2b9335cb 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include +#include #ifndef QT_NO_ACCESSIBILITY #include "qwindowsmsaaaccessible.h" diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index e654f262da..5380fc2411 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -39,9 +39,8 @@ #ifndef QWINDOWSMSAAACCESSIBLE_H #define QWINDOWSMSAAACCESSIBLE_H -#include -#ifndef QT_NO_ACCESSIBILITY #include +#ifndef QT_NO_ACCESSIBILITY #include #include -- cgit v1.2.3 From 8f1277da8c137270ff857128d8fea1423d8a7700 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 22 Oct 2017 21:39:31 +0200 Subject: QStorageInfo: Properly decode labels from /dev/disk/by-label udev encodes the labels for /dev/disk/by-label/ with ID_LABEL_FS_ENC which is done with blkid_encode_string(). This function encodes some unsafe 1-byte utf-8 characters as hex (e.g. '\' or ' ') Task-number: QTBUG-61420 Change-Id: If82f4381d348acf9008b79ec5ac7c55e6d3819de Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 9072b34f54..1fc32e0f2d 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -544,6 +544,38 @@ void QStorageInfoPrivate::initRootPath() } } +#ifdef Q_OS_LINUX +// udev encodes the labels with ID_LABEL_FS_ENC which is done with +// blkid_encode_string(). Within this function some 1-byte utf-8 +// characters not considered safe (e.g. '\' or ' ') are encoded as hex +static QString decodeFsEncString(const QString &str) +{ + QString decoded; + decoded.reserve(str.size()); + + int i = 0; + while (i < str.size()) { + if (i <= str.size() - 4) { // we need at least four characters \xAB + if (str.at(i) == QLatin1Char('\\') && + str.at(i+1) == QLatin1Char('x')) { + bool bOk; + const int code = str.midRef(i+2, 2).toInt(&bOk, 16); + // only decode characters between 0x20 and 0x7f but not + // the backslash to prevent collisions + if (bOk && code >= 0x20 && code < 0x80 && code != '\\') { + decoded += QChar(code); + i += 4; + continue; + } + } + } + decoded += str.at(i); + ++i; + } + return decoded; +} +#endif + static inline QString retrieveLabel(const QByteArray &device) { #ifdef Q_OS_LINUX @@ -557,7 +589,7 @@ static inline QString retrieveLabel(const QByteArray &device) it.next(); QFileInfo fileInfo(it.fileInfo()); if (fileInfo.isSymLink() && fileInfo.symLinkTarget() == devicePath) - return fileInfo.fileName(); + return decodeFsEncString(fileInfo.fileName()); } #elif defined Q_OS_HAIKU fs_info fsInfo; -- cgit v1.2.3 From a4f9cf23444dd76a11d4eb67c4ea65d5c3948894 Mon Sep 17 00:00:00 2001 From: Elvis Angelaccio Date: Sat, 29 Jul 2017 11:28:13 +0200 Subject: Disable window shortcuts if there is a window modal dialog If a window is blocked by a WindowModal dialog, it should not be possible to trigger window shortcuts on that window if it receives a WindowActivate event. This currently happens if the blocked window gets clicked, because the window becomes the active_window and then QApplication sends it a WindowActivate event (this doesn't happen with application modal dialogs). The correctWidgetContext() function calls QApplicationPrivate::tryModalHelper() only if the shortcut context is ApplicationShortcut. This patch makes it call even if the shortcut context is WindowShortcut. Change-Id: Iff87d85bcae603a6a24128e0cedfa9d33b6485fd Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qshortcut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index f944a7097b..32600d4152 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -205,7 +205,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge #if defined(DEBUG_QSHORTCUTMAP) qDebug().nospace() << "..true [Pass-through]"; #endif - return true; + return QApplicationPrivate::tryModalHelper(w, nullptr); } #if QT_CONFIG(graphicsview) -- cgit v1.2.3 From 937ded010b09250c6ab9a57917f2e430fb5875f5 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sat, 28 Oct 2017 19:13:58 +0200 Subject: QListView: make sure to respect grid size during dataChanged() handling When the dataChanged() signal is handled by QIconModeViewBase, the size of the items are recalculated. During this operation the optional grid size is not taken into account which leads to a screwed up layout. This patch adds the missing check similar it is done in doStaticLayout()/doDynamicLayout(). Task-number: QTBUG-45427 Change-Id: Iba7adb44b1510c511a69c289ccb4f168992a6871 Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qlistview.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 9e959c8e1e..9217fec10e 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -2874,10 +2874,19 @@ void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { if (column() >= topLeft.column() && column() <= bottomRight.column()) { - QStyleOptionViewItem option = viewOptions(); - int bottom = qMin(items.count(), bottomRight.row() + 1); + const QStyleOptionViewItem option = viewOptions(); + const int bottom = qMin(items.count(), bottomRight.row() + 1); + const bool useItemSize = !dd->grid.isValid(); for (int row = topLeft.row(); row < bottom; ++row) - items[row].resize(itemSize(option, modelIndex(row))); + { + QSize s = itemSize(option, modelIndex(row)); + if (!useItemSize) + { + s.setWidth(qMin(dd->grid.width(), s.width())); + s.setHeight(qMin(dd->grid.height(), s.height())); + } + items[row].resize(s); + } } } -- cgit v1.2.3 From 851c226247d692a608d78a1d7f9e621f4a82f40d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 2 Nov 2017 08:56:09 +0100 Subject: QFilesystemWatcher/Windows: Use event dispatcher of thread Previously, the native event filter listening on removable drivers was installed on QCoreApplication::eventDispatcher() which led to a mismatch when launched from a non-GUI thread since ~QAbstractNativeEventFilter() removes itself from QAbstractEventDispatcher::instance(). Amends 45580aa92557caa4f3f5be783573ddb80602e494, e612fe8d47bc0fe762668617a5189117ad1aee15. Task-number: QTBUG-64171 Change-Id: Icbe289bd585f124d66989d0cd574040b986e680c Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index cdb79e7c97..9e43d11e71 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -308,7 +308,7 @@ void QWindowsRemovableDriveListener::addPath(const QString &p) notify.dbch_size = sizeof(notify); notify.dbch_devicetype = DBT_DEVTYP_HANDLE; notify.dbch_handle = volumeHandle; - QEventDispatcherWin32 *winEventDispatcher = static_cast(QCoreApplication::eventDispatcher()); + QEventDispatcherWin32 *winEventDispatcher = static_cast(QAbstractEventDispatcher::instance()); re.devNotify = RegisterDeviceNotification(winEventDispatcher->internalHwnd(), ¬ify, DEVICE_NOTIFY_WINDOW_HANDLE); // Empirically found: The notifications also work when the handle is immediately @@ -336,7 +336,7 @@ QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine(QObject *parent : QFileSystemWatcherEngine(parent) { #ifndef Q_OS_WINRT - if (QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher()) { + if (QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance()) { m_driveListener = new QWindowsRemovableDriveListener(this); eventDispatcher->installNativeEventFilter(m_driveListener); parent->setProperty("_q_driveListener", -- cgit v1.2.3 From d366d6dfd30de6e6f83afc807a4648f008b396e5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Oct 2017 13:21:22 +0200 Subject: Windows QPA: Restrict file dialog to file system items in Directory mode Qt cannot handle places like 'Network', etc. Task-number: QTBUG-63645 Change-Id: I53d0eedc2996af6a1ec3230e3d65a3e272aa3710 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index f4527bcc60..75ca090cef 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1010,7 +1010,9 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, break; case QFileDialogOptions::Directory: case QFileDialogOptions::DirectoryOnly: - flags |= FOS_PICKFOLDERS | FOS_FILEMUSTEXIST; + // QTBUG-63645: Restrict to file system items, as Qt cannot deal with + // places like 'Network', etc. + flags |= FOS_PICKFOLDERS | FOS_FILEMUSTEXIST | FOS_FORCEFILESYSTEM; break; case QFileDialogOptions::ExistingFiles: flags |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT; @@ -1219,6 +1221,8 @@ void QWindowsNativeFileDialogBase::onSelectionChange() { const QList current = selectedFiles(); m_data.setSelectedFiles(current); + qDebug() << __FUNCTION__ << current << current.size(); + if (current.size() == 1) emit currentChanged(current.front()); } -- cgit v1.2.3 From b4ac5525612812dd411c93e671813d079a152e57 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Oct 2017 13:28:44 +0200 Subject: Windows QPA: Pass on Url of non-filesystem directory items Do not attempt to copy directory items, which will fail and result in empty result lists. Amends 5865e582fd537fff530c13301e5229a7b4ed21c7. Task-number: QTBUG-57070 Task-number: QTBUG-63645 Change-Id: I59efce196b28099ec8aff5a802ef0a4d9a098453 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 75ca090cef..4b08528d17 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1419,7 +1419,7 @@ QList QWindowsNativeOpenFileDialog::dialogResult() const for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) { QWindowsShellItem qItem(item); const QString path = qItem.path(); - if (path.isEmpty()) { + if (path.isEmpty() && !qItem.isDir()) { const QString temporaryCopy = createTemporaryItemCopy(qItem); if (temporaryCopy.isEmpty()) qWarning() << "Unable to create a local copy of" << qItem; -- cgit v1.2.3 From 92c61b11c1704450adfa3a8ac839478c0f3dd19d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Oct 2017 15:23:39 +0200 Subject: Windows: Use SM_CXSMICON instead of SM_CXICON for the tray icon size Partially reverts b465fe759695bb7e1de693c3d4d20acfd2c49779. Task-number: QTBUG-63447 Change-Id: Iaf8a54b59a054e33811f65f64322af3aa746885e Reviewed-by: Oliver Wolff --- src/widgets/util/qsystemtrayicon_win.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp index 3f007f24c1..57d46912e0 100644 --- a/src/widgets/util/qsystemtrayicon_win.cpp +++ b/src/widgets/util/qsystemtrayicon_win.cpp @@ -313,9 +313,8 @@ HICON QSystemTrayIconSys::createIcon() const QIcon icon = q->icon(); if (icon.isNull()) return oldIcon; - const QSize requestedSize = QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA - ? QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)) - : QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + // When merging this to 5.10, change at src/plugins/platforms/windows/qwindowssystemtrayicon.cpp:351. + const QSize requestedSize = QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); const QSize size = icon.actualSize(requestedSize); const QPixmap pm = icon.pixmap(size); if (pm.isNull()) -- cgit v1.2.3 From d674d227f7ab22aed206d3a7f5c96e5e8dfa48f2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 6 Apr 2017 13:20:18 -0700 Subject: qGlobalQHashSeed: initialize the seed before returning it If you had never used QHash before, this function returned -1. That's not useful if you're trying to implement your own QHash that uses Qt's global seed. Change-Id: Ib0e40a7a3ebc44329f23fffd14b2e875b970a55c Reviewed-by: Lars Knoll --- src/corelib/tools/qhash.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 4cc9ec8ec8..1662e944cf 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -361,6 +361,7 @@ static void qt_initialize_qhash_seed() */ int qGlobalQHashSeed() { + qt_initialize_qhash_seed(); return qt_qhash_seed.load(); } -- cgit v1.2.3 From 484a186f50de59279cf3c02088273ff114f4cfcf Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 4 Oct 2017 12:00:57 -0700 Subject: QNativeSocketEngine/Win: fix getting the datagram destination Looks like I never even tested this. There were two problems: 1) when we asked for the recvmsg and sendmsg functions, we used the wrong variable (socketDescriptor was still -1) 2) we extracted the destination addresses, but never set them in the QIpPacketHeader object The added tests confirm that this works on Windows, Linux, Darwin, FreeBSD. There also seems to be a problem, obtaining the destination address on an IPv4 socket with a dual-stack sender (I can reproduce that on FreeBSD, macOS and Windows, plus an old version of Linux). Task-number: QTBUG-63605 Change-Id: I638cf58bfa7b4e5fb386fffd14ea732bddbc0c42 Reviewed-by: Timur Pocheptsov --- src/network/socket/qnativesocketengine_win.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index eb633eb1d2..3ecfb06411 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -408,13 +408,13 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc // get the pointer to sendmsg and recvmsg DWORD bytesReturned; GUID recvmsgguid = WSAID_WSARECVMSG; - if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER, + if (WSAIoctl(socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &recvmsgguid, sizeof(recvmsgguid), &recvmsg, sizeof(recvmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) recvmsg = 0; GUID sendmsgguid = WSAID_WSASENDMSG; - if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER, + if (WSAIoctl(socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &sendmsgguid, sizeof(sendmsgguid), &sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) sendmsg = 0; @@ -1257,26 +1257,28 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress); } - if (ret != -1 && recvmsg) { + if (ret != -1 && recvmsg && options != QAbstractSocketEngine::WantNone) { // get the ancillary data + header->destinationPort = localPort; WSACMSGHDR *cmsgptr; for (cmsgptr = WSA_CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = WSA_CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in6_pktinfo))) { in6_pktinfo *info = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); - QHostAddress target(reinterpret_cast(&info->ipi6_addr)); - if (info->ipi6_ifindex) - target.setScopeId(QString::number(info->ipi6_ifindex)); + + header->destinationAddress.setAddress(reinterpret_cast(&info->ipi6_addr)); + header->ifindex = info->ipi6_ifindex; + if (header->ifindex) + header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex)); } if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in_pktinfo))) { in_pktinfo *info = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); u_long addr; WSANtohl(socketDescriptor, info->ipi_addr.s_addr, &addr); - QHostAddress target(addr); - if (info->ipi_ifindex) - target.setScopeId(QString::number(info->ipi_ifindex)); + header->destinationAddress.setAddress(addr); + header->ifindex = info->ipi_ifindex; } if (cmsgptr->cmsg_len == WSA_CMSG_LEN(sizeof(int)) -- cgit v1.2.3 From 8ba1f91d4eed03be09046bf4ef81944787316ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 26 Oct 2017 10:06:10 +0200 Subject: macOS: Add logging of screen add/remove/changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic9c9ac307441dde98bb43d656466a03805746917 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoascreen.h | 4 ++++ src/plugins/platforms/cocoa/qcocoascreen.mm | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index dd17848109..d185905782 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -222,6 +222,8 @@ QCocoaIntegration::Options QCocoaIntegration::options() const return mOptions; } +Q_LOGGING_CATEGORY(lcCocoaScreen, "qt.qpa.cocoa.screens"); + /*! \brief Synchronizes the screen list, adds new screens, removes deleted ones */ @@ -261,9 +263,11 @@ void QCocoaIntegration::updateScreens() if (screen) { remainingScreens.remove(screen); screen->updateGeometry(); + qCDebug(lcCocoaScreen) << "Updated properties of" << screen; } else { screen = new QCocoaScreen(i); mScreens.append(screen); + qCDebug(lcCocoaScreen) << "Adding" << screen; screenAdded(screen); } siblings << screen; @@ -280,6 +284,7 @@ void QCocoaIntegration::updateScreens() mScreens.removeOne(screen); // Prevent stale references to NSScreen during destroy screen->m_screenIndex = -1; + qCDebug(lcCocoaScreen) << "Removing" << screen; destroyScreen(screen); } } diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h index eb17efa937..937002f493 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.h +++ b/src/plugins/platforms/cocoa/qcocoascreen.h @@ -102,6 +102,10 @@ public: QList m_siblings; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QCocoaScreen *screen); +#endif + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index 13e5220b6a..f523873bde 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -275,4 +275,22 @@ QCocoaScreen *QCocoaScreen::primaryScreen() return static_cast(QGuiApplication::primaryScreen()->handle()); } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QCocoaScreen *screen) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QCocoaScreen(" << (const void *)screen; + if (screen) { + debug << ", index=" << screen->m_screenIndex; + debug << ", native=" << screen->nativeScreen(); + debug << ", geometry=" << screen->geometry(); + debug << ", dpr=" << screen->devicePixelRatio(); + debug << ", name=" << screen->name(); + } + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE -- cgit v1.2.3 From ad36da8ff416501e249beb098e5b84eaa2fba43d Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 30 Oct 2017 13:45:18 +0100 Subject: testlib: start sharing common helper functions ... by moving them in QTestPrivate namespace (qtesthelpers_p.h). This header file is a convenient staging area for helper APIs, eventually some could be moved to public QTest API. This header file utilizes the same pattern as other qtestlib header files - wrapping functions with QT_${LIBNAME}_LIB to automatically enable certain APIs based on what is in the projects dependencies, e.g. QT += widgets. Change-Id: Ic0266429939c1f3788912ad8b84fc6e0d5edd68b Reviewed-by: Edward Welbourne --- src/testlib/qtesthelpers_p.h | 112 +++++++++++++++++++++++++++++++++++++++++++ src/testlib/testlib.pro | 3 +- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/testlib/qtesthelpers_p.h (limited to 'src') diff --git a/src/testlib/qtesthelpers_p.h b/src/testlib/qtesthelpers_p.h new file mode 100644 index 0000000000..0e39f7aea2 --- /dev/null +++ b/src/testlib/qtesthelpers_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTHELPERS_P_H +#define QTESTHELPERS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +#ifdef QT_GUI_LIB +#include +#include +#endif + +#ifdef QT_WIDGETS_LIB +#include +#endif + +QT_BEGIN_NAMESPACE + +namespace QTestPrivate { + +static inline bool canHandleUnicodeFileNames() +{ +#if defined(Q_OS_WIN) + return true; +#else + // Check for UTF-8 by converting the Euro symbol (see tst_utf8) + return QFile::encodeName(QString(QChar(0x20AC))) == QByteArrayLiteral("\342\202\254"); +#endif +} + +#ifdef QT_WIDGETS_LIB +static inline void centerOnScreen(QWidget *w, const QSize &size) +{ + const QPoint offset = QPoint(size.width() / 2, size.height() / 2); + w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset); +} + +static inline void centerOnScreen(QWidget *w) +{ + centerOnScreen(w, w->geometry().size()); +} + +/*! \internal + + Make a widget frameless to prevent size constraints of title bars from interfering (Windows). +*/ +static inline void setFrameless(QWidget *w) +{ + Qt::WindowFlags flags = w->windowFlags(); + flags |= Qt::FramelessWindowHint; + flags &= ~(Qt::WindowTitleHint | Qt::WindowSystemMenuHint + | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + w->setWindowFlags(flags); +} +#endif // QT_WIDGETS_LIB + +} // namespace QTestPrivate + +QT_END_NAMESPACE + +#endif // QTESTHELPERS_P_H diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index e11e25e1da..f99f28ca84 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -37,7 +37,8 @@ HEADERS = qbenchmark.h \ qtestspontaneevent.h \ qtestsystem.h \ qtesttouch.h \ - qtestblacklist_p.h + qtestblacklist_p.h \ + qtesthelpers_p.h SOURCES = qtestcase.cpp \ qtestlog.cpp \ -- cgit v1.2.3 From 435c4b2ccbbb7284918dd2d4a14f8e44c3977d98 Mon Sep 17 00:00:00 2001 From: Robert Szefner Date: Fri, 20 Oct 2017 22:51:07 +0200 Subject: QPSQL: Fix detection of PostreSQL version 9.x and later Fixed parsing version string for PostgreSQL. PostgreSQL versioning changed since version 10, see link: https://www.postgresql.org/support/versioning Extended QPSQLDriver::Protocol enum for PostreSQL 9.x and later, added underscore to item names to separate major and minor version. Changed long switch-case statements to if-else. Change-Id: Ib19ae7ba426f262e80c52670e7ecb3532ff460a0 Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 182 +++++++++++++++--------------- src/plugins/sqldrivers/psql/qsql_psql_p.h | 24 ++-- 2 files changed, 108 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index acadc830b2..f650e4cca8 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -187,7 +187,7 @@ public: void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type) { QString query; - if (pro >= QPSQLDriver::Version73) { + if (pro >= QPSQLDriver::Version7_3) { query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class " "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) " "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') " @@ -525,7 +525,7 @@ int QPSQLResult::numRowsAffected() QVariant QPSQLResult::lastInsertId() const { Q_D(const QPSQLResult); - if (d->drv_d_func()->pro >= QPSQLDriver::Version81) { + if (d->drv_d_func()->pro >= QPSQLDriver::Version8_1) { QSqlQuery qry(driver()->createResult()); // Most recent sequence value obtained from nextval if (qry.exec(QLatin1String("SELECT lastval();")) && qry.next()) @@ -697,7 +697,7 @@ void QPSQLDriverPrivate::detectBackslashEscape() { // standard_conforming_strings option introduced in 8.2 // http://www.postgresql.org/docs/8.2/static/runtime-config-compatible.html - if (pro < QPSQLDriver::Version82) { + if (pro < QPSQLDriver::Version8_2) { hasBackslashEscape = true; } else { hasBackslashEscape = false; @@ -719,11 +719,11 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin) { switch (vMin) { case 1: - return QPSQLDriver::Version71; + return QPSQLDriver::Version7_1; case 3: - return QPSQLDriver::Version73; + return QPSQLDriver::Version7_3; case 4: - return QPSQLDriver::Version74; + return QPSQLDriver::Version7_4; default: return QPSQLDriver::Version7; } @@ -733,76 +733,109 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin) { switch (vMin) { case 1: - return QPSQLDriver::Version81; + return QPSQLDriver::Version8_1; case 2: - return QPSQLDriver::Version82; + return QPSQLDriver::Version8_2; case 3: - return QPSQLDriver::Version83; + return QPSQLDriver::Version8_3; case 4: - return QPSQLDriver::Version84; + return QPSQLDriver::Version8_4; default: return QPSQLDriver::Version8; } break; } case 9: - return QPSQLDriver::Version9; + { + switch (vMin) { + case 1: + return QPSQLDriver::Version9_1; + case 2: + return QPSQLDriver::Version9_2; + case 3: + return QPSQLDriver::Version9_3; + case 4: + return QPSQLDriver::Version9_4; + case 5: + return QPSQLDriver::Version9_5; + case 6: + return QPSQLDriver::Version9_6; + default: + return QPSQLDriver::Version9; + } break; + } + case 10: + return QPSQLDriver::Version10; default: + if (vMaj > 10) + return QPSQLDriver::UnknownLaterVersion; break; } return QPSQLDriver::VersionUnknown; } +static QPSQLDriver::Protocol qFindPSQLVersion(const QString &versionString) +{ + const QRegExp rx(QStringLiteral("(\\d+)(?:\\.(\\d+))?")); + if (rx.indexIn(versionString) != -1) { + // Beginning with PostgreSQL version 10, a major release is indicated by + // increasing the first part of the version, e.g. 10 to 11. + // Before version 10, a major release was indicated by increasing either + // the first or second part of the version number, e.g. 9.5 to 9.6. + int vMaj = rx.cap(1).toInt(); + int vMin; + if (vMaj >= 10) { + vMin = 0; + } else { + if (rx.cap(2).isEmpty()) + return QPSQLDriver::VersionUnknown; + vMin = rx.cap(2).toInt(); + } + return qMakePSQLVersion(vMaj, vMin); + } + + return QPSQLDriver::VersionUnknown; +} + QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion() { QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6; PGresult* result = exec("select version()"); int status = PQresultStatus(result); if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) { - QString val = QString::fromLatin1(PQgetvalue(result, 0, 0)); - - QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)")); - rx.setMinimal(true); // enforce non-greedy RegExp + serverVersion = qFindPSQLVersion( + QString::fromLatin1(PQgetvalue(result, 0, 0))); + } + PQclear(result); - if (rx.indexIn(val) != -1) { - int vMaj = rx.cap(1).toInt(); - int vMin = rx.cap(2).toInt(); - serverVersion = qMakePSQLVersion(vMaj, vMin); + QPSQLDriver::Protocol clientVersion = #if defined(PG_MAJORVERSION) - if (rx.indexIn(QLatin1String(PG_MAJORVERSION)) != -1) + qFindPSQLVersion(QLatin1String(PG_MAJORVERSION)); #elif defined(PG_VERSION) - if (rx.indexIn(QLatin1String(PG_VERSION)) != -1) + qFindPSQLVersion(QLatin1String(PG_VERSION)); #else - if (0) + QPSQLDriver::VersionUnknown; #endif - { - vMaj = rx.cap(1).toInt(); - vMin = rx.cap(2).toInt(); - QPSQLDriver::Protocol clientVersion = qMakePSQLVersion(vMaj, vMin); - - if (serverVersion >= QPSQLDriver::Version9 && clientVersion < QPSQLDriver::Version9) { - //Client version before QPSQLDriver::Version9 only supports escape mode for bytea type, - //but bytea format is set to hex by default in PSQL 9 and above. So need to force the - //server use the old escape mode when connects to the new server with old client library. - PQclear(result); - result = exec("SET bytea_output=escape; "); - status = PQresultStatus(result); - } else if (serverVersion == QPSQLDriver::VersionUnknown) { - serverVersion = clientVersion; - if (serverVersion != QPSQLDriver::VersionUnknown) - qWarning("The server version of this PostgreSQL is unknown, falling back to the client version."); - } - } - } + + if (serverVersion >= QPSQLDriver::Version9 && clientVersion < QPSQLDriver::Version9) { + // Client version before QPSQLDriver::Version9 only supports escape mode for bytea type, + // but bytea format is set to hex by default in PSQL 9 and above. So need to force the + // server use the old escape mode when connects to the new server with old client library. + result = exec("SET bytea_output=escape; "); + status = PQresultStatus(result); + PQclear(result); + } else if (serverVersion == QPSQLDriver::VersionUnknown) { + serverVersion = clientVersion; + if (serverVersion != QPSQLDriver::VersionUnknown) + qWarning("The server version of this PostgreSQL is unknown, falling back to the client version."); } - PQclear(result); - //keep the old behavior unchanged + // Keep the old behavior unchanged if (serverVersion == QPSQLDriver::VersionUnknown) serverVersion = QPSQLDriver::Version6; - if (serverVersion < QPSQLDriver::Version71) { + if (serverVersion < QPSQLDriver::Version7_1) { qWarning("This version of PostgreSQL is not supported and may not work."); } @@ -852,7 +885,7 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const return true; case PreparedQueries: case PositionalPlaceholders: - return d->pro >= QPSQLDriver::Version82; + return d->pro >= QPSQLDriver::Version8_2; case BatchOperations: case NamedPlaceholders: case SimpleLocking: @@ -861,7 +894,7 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const case CancelQuery: return false; case BLOB: - return d->pro >= QPSQLDriver::Version71; + return d->pro >= QPSQLDriver::Version7_1; case Unicode: return d->isUtf8; } @@ -988,12 +1021,7 @@ bool QPSQLDriver::commitTransaction() // This hack is used to tell if the transaction has succeeded for the protocol versions of // PostgreSQL below. For 7.x and other protocol versions we are left in the dark. // This hack can dissapear once there is an API to query this sort of information. - if (d->pro == QPSQLDriver::Version8 || - d->pro == QPSQLDriver::Version81 || - d->pro == QPSQLDriver::Version82 || - d->pro == QPSQLDriver::Version83 || - d->pro == QPSQLDriver::Version84 || - d->pro == QPSQLDriver::Version9) { + if (d->pro >= QPSQLDriver::Version8) { transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0; } @@ -1080,8 +1108,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const else schema = std::move(schema).toLower(); - switch(d->pro) { - case QPSQLDriver::Version6: + if (d->pro == QPSQLDriver::Version6) { stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname " "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind " "where pg_cl.relname = '%1_pkey' " @@ -1090,9 +1117,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const "and pg_att1.attrelid = pg_ind.indrelid " "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] " "order by pg_att2.attnum"); - break; - case QPSQLDriver::Version7: - case QPSQLDriver::Version71: + } else if (d->pro == QPSQLDriver::Version7 || d->pro == QPSQLDriver::Version7_1) { stmt = QLatin1String("select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname " "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind " "where pg_cl.relname = '%1_pkey' " @@ -1101,15 +1126,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const "and pg_att1.attrelid = pg_ind.indrelid " "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] " "order by pg_att2.attnum"); - break; - case QPSQLDriver::Version73: - case QPSQLDriver::Version74: - case QPSQLDriver::Version8: - case QPSQLDriver::Version81: - case QPSQLDriver::Version82: - case QPSQLDriver::Version83: - case QPSQLDriver::Version84: - case QPSQLDriver::Version9: + } else if (d->pro >= QPSQLDriver::Version7_3) { stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, " "pg_class.relname " "FROM pg_attribute, pg_class " @@ -1124,10 +1141,8 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const else stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema)); - break; - case QPSQLDriver::VersionUnknown: - qFatal("PSQL version is unknown"); - break; + } else { + qFatal("QPSQLDriver::primaryIndex(tablename): unknown PSQL version, query statement not set"); } i.exec(stmt.arg(tbl)); @@ -1161,8 +1176,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const schema = std::move(schema).toLower(); QString stmt; - switch(d->pro) { - case QPSQLDriver::Version6: + if (d->pro == QPSQLDriver::Version6) { stmt = QLatin1String("select pg_attribute.attname, int(pg_attribute.atttypid), " "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, " "int(pg_attribute.attrelid), pg_attribute.attnum " @@ -1170,8 +1184,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const "where pg_class.relname = '%1' " "and pg_attribute.attnum > 0 " "and pg_attribute.attrelid = pg_class.oid "); - break; - case QPSQLDriver::Version7: + } else if (d->pro == QPSQLDriver::Version7) { stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, " "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, " "pg_attribute.attrelid::int, pg_attribute.attnum " @@ -1179,8 +1192,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const "where pg_class.relname = '%1' " "and pg_attribute.attnum > 0 " "and pg_attribute.attrelid = pg_class.oid "); - break; - case QPSQLDriver::Version71: + } else if (d->pro == QPSQLDriver::Version7_1) { stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, " "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, " "pg_attrdef.adsrc " @@ -1191,15 +1203,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const "and pg_attribute.attnum > 0 " "and pg_attribute.attrelid = pg_class.oid " "order by pg_attribute.attnum "); - break; - case QPSQLDriver::Version73: - case QPSQLDriver::Version74: - case QPSQLDriver::Version8: - case QPSQLDriver::Version81: - case QPSQLDriver::Version82: - case QPSQLDriver::Version83: - case QPSQLDriver::Version84: - case QPSQLDriver::Version9: + } else if (d->pro >= QPSQLDriver::Version7_3) { stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, " "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, " "pg_attrdef.adsrc " @@ -1217,15 +1221,13 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const else stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " "pg_namespace where pg_namespace.nspname = '%1')").arg(schema)); - break; - case QPSQLDriver::VersionUnknown: - qFatal("PSQL version is unknown"); - break; + } else { + qFatal("QPSQLDriver::record(tablename): unknown PSQL version, query statement not set"); } QSqlQuery query(createResult()); query.exec(stmt.arg(tbl)); - if (d->pro >= QPSQLDriver::Version71) { + if (d->pro >= QPSQLDriver::Version7_1) { while (query.next()) { int len = query.value(3).toInt(); int precision = query.value(4).toInt(); diff --git a/src/plugins/sqldrivers/psql/qsql_psql_p.h b/src/plugins/sqldrivers/psql/qsql_psql_p.h index 8468b9af93..f5cb2e9bd0 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql_p.h +++ b/src/plugins/sqldrivers/psql/qsql_psql_p.h @@ -76,15 +76,23 @@ public: VersionUnknown = -1, Version6 = 6, Version7 = 7, - Version71 = 8, - Version73 = 9, - Version74 = 10, + Version7_1 = 8, + Version7_3 = 9, + Version7_4 = 10, Version8 = 11, - Version81 = 12, - Version82 = 13, - Version83 = 14, - Version84 = 15, - Version9 = 16 + Version8_1 = 12, + Version8_2 = 13, + Version8_3 = 14, + Version8_4 = 15, + Version9 = 16, + Version9_1 = 17, + Version9_2 = 18, + Version9_3 = 19, + Version9_4 = 20, + Version9_5 = 21, + Version9_6 = 22, + Version10 = 23, + UnknownLaterVersion = 100000 }; explicit QPSQLDriver(QObject *parent=0); -- cgit v1.2.3 From ff914ea59c3788b2359ddb8d607299576b7a1296 Mon Sep 17 00:00:00 2001 From: Robert Szefner Date: Fri, 20 Oct 2017 23:31:12 +0200 Subject: QPSQL: Fix handling binary data for PostgreSQL 9.x and later Set byte_output to 'escape' mode for server version 9 and later, no matter what version of client library we use. Since setting byte_output doesn't depend on client version anymore, we can move it to separate function. This fixes qtbase\tests\auto\sql\kernel\qsqldatabase tst_QSqlDatabase::psql_escapeBytea() test (before this change test did not pass on PostgreSQL 9.6) Change-Id: I37aaa18267d7e6459c00010ed899536c01e8124e Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index f650e4cca8..aac9a1fa13 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -181,6 +181,7 @@ public: QPSQLDriver::Protocol getPSQLVersion(); bool setEncodingUtf8(); void setDatestyle(); + void setByteaOutput(); void detectBackslashEscape(); }; @@ -693,6 +694,20 @@ void QPSQLDriverPrivate::setDatestyle() PQclear(result); } +void QPSQLDriverPrivate::setByteaOutput() +{ + if (pro >= QPSQLDriver::Version9) { + // Server version before QPSQLDriver::Version9 only supports escape mode for bytea type, + // but bytea format is set to hex by default in PSQL 9 and above. So need to force the + // server to use the old escape mode when connects to the new server. + PGresult *result = exec("SET bytea_output TO escape"); + int status = PQresultStatus(result); + if (status != PGRES_COMMAND_OK) + qWarning("%s", PQerrorMessage(connection)); + PQclear(result); + } +} + void QPSQLDriverPrivate::detectBackslashEscape() { // standard_conforming_strings option introduced in 8.2 @@ -818,14 +833,7 @@ QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion() QPSQLDriver::VersionUnknown; #endif - if (serverVersion >= QPSQLDriver::Version9 && clientVersion < QPSQLDriver::Version9) { - // Client version before QPSQLDriver::Version9 only supports escape mode for bytea type, - // but bytea format is set to hex by default in PSQL 9 and above. So need to force the - // server use the old escape mode when connects to the new server with old client library. - result = exec("SET bytea_output=escape; "); - status = PQresultStatus(result); - PQclear(result); - } else if (serverVersion == QPSQLDriver::VersionUnknown) { + if (serverVersion == QPSQLDriver::VersionUnknown) { serverVersion = clientVersion; if (serverVersion != QPSQLDriver::VersionUnknown) qWarning("The server version of this PostgreSQL is unknown, falling back to the client version."); @@ -957,6 +965,7 @@ bool QPSQLDriver::open(const QString & db, d->detectBackslashEscape(); d->isUtf8 = d->setEncodingUtf8(); d->setDatestyle(); + d->setByteaOutput(); setOpen(true); setOpenError(false); -- cgit v1.2.3 From b35a27676bec7f79761be83b2a7764ac0470e789 Mon Sep 17 00:00:00 2001 From: Robert Szefner Date: Fri, 20 Oct 2017 23:55:16 +0200 Subject: QPSQL: Fix check for minimum supported PostgreSQL version According to Qt documentation http://doc.qt.io/qt-5/sql-driver.html#qpsql minimum supported version of PostgreSQL is 7.3 Change-Id: I30cffaddc29fd56b534bfd259cc235ea1204a21f Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index aac9a1fa13..8f7d261bdc 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -843,7 +843,7 @@ QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion() if (serverVersion == QPSQLDriver::VersionUnknown) serverVersion = QPSQLDriver::Version6; - if (serverVersion < QPSQLDriver::Version7_1) { + if (serverVersion < QPSQLDriver::Version7_3) { qWarning("This version of PostgreSQL is not supported and may not work."); } -- cgit v1.2.3 From 385589ef458715fcaa533bbd01ca421dc1040eba Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 20 Oct 2017 17:39:08 +0700 Subject: QCocoaMenu: Attach menu items when updating the menubar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of waiting for the menu delegate to update each item, we can attach an NSMenu to its NSMenuItem as soon as we update the current window's menubar. This is safe to do because we know that this is going to be the main menubar right after, so we're not orphaning any NSMenuItem from its NSMenu at the wrong moment. By doing this, we also ensure that all menus from the active menubar are reachable by the key-equivalent dispatching logic, even before we display the actual menu. This was shown in BigMenuCreator where, under the menubar's ASP and SAP menus, all A*S submenus would be disabled. Furthermore, on the same menus, SAP would show the same issue. Added test in Menurama as well. Change-Id: If6e7311072e6b53ad1cbced73623d1832aa0df8e Task-number: QTBUG-57076 Task-number: QTBUG-63712 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenu.h | 2 ++ src/plugins/platforms/cocoa/qcocoamenu.mm | 16 +++++++++++++++- src/plugins/platforms/cocoa/qcocoamenubar.h | 2 ++ src/plugins/platforms/cocoa/qcocoamenubar.mm | 11 ++++++++--- 4 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 06688dbf3d..7baaf971f4 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -98,6 +98,8 @@ public: void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; + void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate); + private: QCocoaMenuItem *itemOrNull(int index) const; void insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 3a11023a4d..8bdd0512de 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -434,6 +434,11 @@ void QCocoaMenu::timerEvent(QTimerEvent *e) } void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) +{ + syncMenuItem_helper(menuItem, false /*menubarUpdate*/); +} + +void QCocoaMenu::syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate) { QMacAutoReleasePool pool; QCocoaMenuItem *cocoaItem = static_cast(menuItem); @@ -444,8 +449,9 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) const bool wasMerged = cocoaItem->isMerged(); NSMenuItem *oldItem = cocoaItem->nsItem(); + NSMenuItem *syncedItem = cocoaItem->sync(); - if (cocoaItem->sync() != oldItem) { + if (syncedItem != oldItem) { // native item was changed for some reason if (oldItem) { if (wasMerged) { @@ -463,6 +469,14 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) // when an item's enabled state changes after menuWillOpen: scheduleUpdate(); } + + // This may be a good moment to attach this item's eventual submenu to the + // synced item, but only on the condition we're all currently hooked to the + // menunbar. A good indicator of this being the right moment is knowing that + // we got called from QCocoaMenuBar::updateMenuBarImmediately(). + if (menubarUpdate) + if (QCocoaMenu *submenu = cocoaItem->menu()) + submenu->setAttachedItem(syncedItem); } void QCocoaMenu::syncSeparatorsCollapsible(bool enable) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index 0725e9db68..a4ee531e91 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -72,6 +72,8 @@ public: QList merged() const; NSMenuItem *itemForRole(QPlatformMenuItem::MenuRole r); + void syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate); + private: static QCocoaWindow *findWindowForMenubar(); static QCocoaMenuBar *findGlobalMenubar(); diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 3e466c9587..a4cd465dae 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -155,7 +155,7 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor } } - syncMenu(menu); + syncMenu_helper(menu, false /*internaCall*/); if (needsImmediateUpdate()) updateMenuBarImmediately(); @@ -182,12 +182,17 @@ void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) } void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) +{ + syncMenu_helper(menu, false /*internaCall*/); +} + +void QCocoaMenuBar::syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate) { QMacAutoReleasePool pool; QCocoaMenu *cocoaMenu = static_cast(menu); Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items()) - cocoaMenu->syncMenuItem(item); + cocoaMenu->syncMenuItem_helper(item, menubarUpdate); BOOL shouldHide = YES; if (cocoaMenu->isVisible()) { @@ -357,7 +362,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() menu->setAttachedItem(item); menu->setMenuParent(mb); // force a sync? - mb->syncMenu(menu); + mb->syncMenu_helper(menu, true /*menubarUpdate*/); menu->propagateEnabledState(!disableForModal); } -- cgit v1.2.3 From d2b8a01ab0670337bd29f6f9b76069cc2599cc75 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Wed, 1 Nov 2017 22:21:35 +0100 Subject: Fix indentation Tabs and white spaces were mixed. Change-Id: I498944334b68b5c23a61e6f4ba6a0e8df77799c6 Reviewed-by: Timur Pocheptsov --- src/network/kernel/kernel.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 00c115da84..1b62892c9f 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -6,7 +6,7 @@ INCLUDEPATH += $$PWD HEADERS += kernel/qtnetworkglobal.h \ kernel/qtnetworkglobal_p.h \ kernel/qauthenticator.h \ - kernel/qauthenticator_p.h \ + kernel/qauthenticator_p.h \ kernel/qdnslookup.h \ kernel/qdnslookup_p.h \ kernel/qhostaddress.h \ -- cgit v1.2.3 From e45ffd7bf6b05062590da039e0de64707d2fb536 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 26 Oct 2017 13:26:56 +0200 Subject: Xinput: Avoid misdetecting certain trackballs as tablets The algorithm triggers on the word "cursor" in the device name, which would also happen for devices from the manufacturer Cursor Controls. Task-number: QTBUG-48034 Change-Id: I9645c0d0bc1fa951d0ea00480572fd0df0220eb5 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 6f20ec25e3..26a9ba8d26 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -220,7 +220,7 @@ void QXcbConnection::xi2SetupDevices() isTablet = true; tabletData.pointerType = QTabletEvent::Eraser; dbgType = QLatin1String("eraser"); - } else if (name.contains("cursor")) { + } else if (name.contains("cursor") && !(name.contains("cursor controls") && name.contains("trackball"))) { isTablet = true; tabletData.pointerType = QTabletEvent::Cursor; dbgType = QLatin1String("cursor"); -- cgit v1.2.3 From 3e5dde4766780665c1030003e3af3aefb75c5dbf Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Fri, 3 Nov 2017 18:20:45 +0100 Subject: Testlib: Fix developer-build with clang 4 "implicit conversion increases floating-point precision: 'float' to 'double'" Change-Id: Id6f4315316e63c849f1a5ddb6c77abc2bab0b2a9 Reviewed-by: Friedemann Kleint --- src/testlib/qtest_gui.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index 2b486aae5d..d4b2de2214 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -122,25 +122,25 @@ template<> inline char *toString(const QRegion ®ion) #ifndef QT_NO_VECTOR2D template<> inline char *toString(const QVector2D &v) { - QByteArray result = "QVector2D(" + QByteArray::number(v.x()) + ", " - + QByteArray::number(v.y()) + ')'; + QByteArray result = "QVector2D(" + QByteArray::number(double(v.x())) + ", " + + QByteArray::number(double(v.y())) + ')'; return qstrdup(result.constData()); } #endif // !QT_NO_VECTOR2D #ifndef QT_NO_VECTOR3D template<> inline char *toString(const QVector3D &v) { - QByteArray result = "QVector3D(" + QByteArray::number(v.x()) + ", " - + QByteArray::number(v.y()) + ", " + QByteArray::number(v.z()) + ')'; + QByteArray result = "QVector3D(" + QByteArray::number(double(v.x())) + ", " + + QByteArray::number(double(v.y())) + ", " + QByteArray::number(double(v.z())) + ')'; return qstrdup(result.constData()); } #endif // !QT_NO_VECTOR3D #ifndef QT_NO_VECTOR4D template<> inline char *toString(const QVector4D &v) { - QByteArray result = "QVector4D(" + QByteArray::number(v.x()) + ", " - + QByteArray::number(v.y()) + ", " + QByteArray::number(v.z()) - + ", " + QByteArray::number(v.w()) + ')'; + QByteArray result = "QVector4D(" + QByteArray::number(double(v.x())) + ", " + + QByteArray::number(double(v.y())) + ", " + QByteArray::number(double(v.z())) + + ", " + QByteArray::number(double(v.w())) + ')'; return qstrdup(result.constData()); } #endif // !QT_NO_VECTOR4D -- cgit v1.2.3 From 7df4dcff2cafcd9b57eb7a4812be871d956f0ec8 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 3 Nov 2017 14:40:46 +0100 Subject: Fix memory corruption on scaled emojis Bitmap glyphs are returned prescaled, which means we should include the transform in their bounding box. Additionally painting them should stick the smallest rect to avoid writing outside the allocated area, and assert in debug builds. Task-number: QTBUG-64239 Change-Id: I5f877d36566891323f528018f910798344ba4ce2 Reviewed-by: Konstantin Ritt Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qtextureglyphcache.cpp | 3 ++- .../fontdatabases/freetype/qfontengine_ft.cpp | 30 ++++++++++++++-------- .../fontdatabases/freetype/qfontengine_ft_p.h | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 86a53c21a3..2a7e0eaa0c 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -318,11 +318,12 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP return; } #endif + Q_ASSERT(mask.width() <= c.w && mask.height() <= c.h); if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) { QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()), - qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(), + qMin(mask.width(), c.w), qMin(mask.height(), c.h), m_image.bytesPerLine(), m_image.format()); QPainter p(&ref); p.setCompositionMode(QPainter::CompositionMode_Source); diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index 64a0ef6fe8..85bedff5e6 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -1776,15 +1776,25 @@ QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const return m * scalableBitmapScaleFactor; } -glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const +glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &t) const { + QTransform trans(t); + const qreal scaleFactor = scalableBitmapScaleFactor.toReal(); + trans.scale(scaleFactor, scaleFactor); + + QRectF rect(m.x.toReal(), m.y.toReal(), m.width.toReal(), m.height.toReal()); + QPointF offset(m.xoff.toReal(), m.yoff.toReal()); + + rect = trans.mapRect(rect); + offset = trans.map(offset); + glyph_metrics_t metrics; - metrics.x = scaledBitmapMetrics(m.x); - metrics.y = scaledBitmapMetrics(m.y); - metrics.width = scaledBitmapMetrics(m.width); - metrics.height = scaledBitmapMetrics(m.height); - metrics.xoff = scaledBitmapMetrics(m.xoff); - metrics.yoff = scaledBitmapMetrics(m.yoff); + metrics.x = QFixed::fromReal(rect.x()); + metrics.y = QFixed::fromReal(rect.y()); + metrics.width = QFixed::fromReal(rect.width()); + metrics.height = QFixed::fromReal(rect.height()); + metrics.xoff = QFixed::fromReal(offset.x()); + metrics.yoff = QFixed::fromReal(offset.y()); return metrics; } @@ -1878,7 +1888,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) unlockFace(); if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); + overall = scaledBitmapMetrics(overall, QTransform()); return overall; } @@ -1917,7 +1927,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) unlockFace(); if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); + overall = scaledBitmapMetrics(overall, QTransform()); return overall; } @@ -1955,7 +1965,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe } if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); + overall = scaledBitmapMetrics(overall, matrix); return overall; } diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index 2993e3b616..c063f5df30 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -321,7 +321,7 @@ private: int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; bool shouldUseDesignMetrics(ShaperFlags flags) const; QFixed scaledBitmapMetrics(QFixed m) const; - glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m) const; + glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m, const QTransform &matrix) const; GlyphFormat defaultFormat; FT_Matrix matrix; -- cgit v1.2.3 From 5194817941985c766bbc7f80039a58e0cf504b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 6 Nov 2017 15:08:37 +0100 Subject: Cocoa: optimize backingstore flush on 10-bit displays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt draws the backing store to the window using CoreGrahics, which will trigger a slow RGB32 -> RGB64 conversion when the output display is a deep color display. Disable NSWindow dynamicDepthLimit and force the depthLimit to WindowDepthTwentyforBitRGB for the common case of 8-bit-per-component raster surfaces. This was benchmarked by resizing a simple QRasterWindow test case which fills the window area using QPainter::fillRect(). Before: 67.1% rgba64_image_mark_rgb32 10.8% __vImageCopyBuffer_block_invoke 6.0% madvise 5.0% _kernelrpc_mach_vm_deallocate_trap 4.1% qt_memfill32(unsigned int*, unsigned int, int) After: 30.7% __vImageCopyBuffer_block_invoke 20.3% madvise 12.3% __vOverwriteChannelsWithScalar_ARGB8888_block_invoke 12.2% qt_memfill32(unsigned int*, unsigned int, int) 4.6% _kernelrpc_mach_vm_deallocate_trap The test program now spends significantly more of its time allocating/deallocating the backing store (madvise), and running the Qt paint event (qt_memfill32). Task-number: QTBUG-47660 Change-Id: I878be7a0e6eee4ad798f7a53f7f9f79b7950af26 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindow.mm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index c6fa6795c1..5cd4beb4f0 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1887,6 +1887,21 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh applyContentBorderThickness(window); + // Prevent CoreGraphics RGB32 -> RGB64 backing store conversions on deep color + // displays by forcing 8-bit components, unless a deep color format has been + // requested. This conversion uses significant CPU time. + QSurface::SurfaceType surfaceType = QPlatformWindow::window()->surfaceType(); + bool usesCoreGraphics = surfaceType == QSurface::RasterSurface || surfaceType == QSurface::RasterGLSurface; + QSurfaceFormat surfaceFormat = QPlatformWindow::window()->format(); + bool usesDeepColor = surfaceFormat.redBufferSize() > 8 || + surfaceFormat.greenBufferSize() > 8 || + surfaceFormat.blueBufferSize() > 8; + bool usesLayer = view().layer; + if (usesCoreGraphics && !usesDeepColor && !usesLayer) { + [window setDynamicDepthLimit:NO]; + [window setDepthLimit:NSWindowDepthTwentyfourBitRGB]; + } + return window; } -- cgit v1.2.3 From b4f4c384d9ee7cf93cc3db289a7d4275ac10a618 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sat, 28 Oct 2017 13:20:53 +0200 Subject: QHeaderView: Honor maximumSectionSize property during resizeSections() Resizing a QTreeeView section with double click or resizeColumnToContents() does not respect the maximumSectionSize when the resize mode is Interactive or Fixed. Since the documentation of maximumSectionSize states that it should honor this property for those cases either the documentation or implementation is incorrect. This patch fixes the latter. Task-number: QTBUG-64036 Change-Id: Ic14c8e444d50b9c50a117efed19d0bca7ec1cf82 Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qheaderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 213cc96b03..3af191b06c 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3364,7 +3364,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool // because it isn't stretch, determine its width and remove that from lengthToStretch int sectionSize = 0; if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) { - sectionSize = headerSectionSize(i); + sectionSize = qBound(q->minimumSectionSize(), headerSectionSize(i), q->maximumSectionSize()); } else { // resizeMode == QHeaderView::ResizeToContents int logicalIndex = q->logicalIndex(i); sectionSize = qMax(viewSectionSizeHint(logicalIndex), -- cgit v1.2.3 From 2937ab9e320ea04fdfda8e3a252559d4762e811e Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 31 Oct 2017 19:47:12 +0100 Subject: QHeaderView: Skip hidden sections on cascading resize When a section is hidden, QHeaderViewPrivate::cascadingResize() does resize a section even it is hidden. This leads to space between the neighbor sections and also some unneeded calculations. Task-number: QTBUG-54601 Change-Id: Ie139417ae2c77ef25e66cf628bfe400185f88ee8 Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qheaderview.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 3af191b06c..298270a785 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3539,6 +3539,8 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize) // cascade the section size change for (int i = visual + 1; i < sectionCount(); ++i) { + if (isVisualIndexHidden(i)) + continue; if (!sectionIsCascadable(i)) continue; int currentSectionSize = headerSectionSize(i); @@ -3581,6 +3583,8 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize) // cascade the section size change if (delta < 0 && newSize < minimumSize) { for (int i = visual - 1; i >= 0; --i) { + if (isVisualIndexHidden(i)) + continue; if (!sectionIsCascadable(i)) continue; int sectionSize = headerSectionSize(i); @@ -3595,6 +3599,8 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize) // let the next section get the space from the resized section if (!sectionResized) { for (int i = visual + 1; i < sectionCount(); ++i) { + if (isVisualIndexHidden(i)) + continue; if (!sectionIsCascadable(i)) continue; int currentSectionSize = headerSectionSize(i); -- cgit v1.2.3 From 28c1e17aef520abfa051c7d9a9fe0f45ec6a5db8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 6 Nov 2017 14:31:29 +0100 Subject: QWinEventNotifier: Fix exit crash Make sure the wait handle is unregistered even though there is no event dispatcher in QWinEventNotifier::setEnabled(). Task-number: QTBUG-64152 Task-number: QTCREATORBUG-19175 Change-Id: I608b95adc7cb874bc52dc5bf0e9f51b443b54ebc Reviewed-by: Orgad Shaneh Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qwineventnotifier.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 362111a2c8..24de491326 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -199,8 +199,11 @@ void QWinEventNotifier::setEnabled(bool enable) d->enabled = enable; QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load(); - if (!eventDispatcher) // perhaps application is shutting down + if (!eventDispatcher) { // perhaps application is shutting down + if (!enable && d->waitHandle != nullptr) + d->unregisterWaitObject(); return; + } if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread"); return; -- cgit v1.2.3 From b084837ffc34439710552cb6ed31054c60f6b2d4 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 1 Nov 2017 15:19:45 +0100 Subject: Update bundled libpng to version 1.6.34 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes an upstream bug in the existing version 1.6.32 which would cause certain valid png files to be rejected. The remaining diff to clean 1.6.34 is archived in the qtpatches.diff file. [ChangeLog][Third-Party Code] libpng was updated to version 1.6.34 Task-number: QTBUG-63950 Change-Id: Ie6f2a09c78a93b6e5623848776b75650bb5bca66 Reviewed-by: André Klitzing Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/3rdparty/libpng/ANNOUNCE | 77 +++++---------------------------- src/3rdparty/libpng/CHANGES | 51 +++++++++++++++++++++- src/3rdparty/libpng/LICENSE | 4 +- src/3rdparty/libpng/README | 2 +- src/3rdparty/libpng/libpng-manual.txt | 21 ++++++--- src/3rdparty/libpng/png.c | 32 +++++++------- src/3rdparty/libpng/png.h | 28 ++++++------ src/3rdparty/libpng/pngconf.h | 2 +- src/3rdparty/libpng/pnglibconf.h | 4 +- src/3rdparty/libpng/pngread.c | 14 +++++- src/3rdparty/libpng/pngrtran.c | 22 +++++----- src/3rdparty/libpng/pngrutil.c | 47 +++++++++----------- src/3rdparty/libpng/pngtrans.c | 6 +-- src/3rdparty/libpng/pngwrite.c | 2 +- src/3rdparty/libpng/qt_attribution.json | 2 +- 15 files changed, 161 insertions(+), 153 deletions(-) (limited to 'src') diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 3cbe5a926e..0f66c0d1da 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,4 +1,4 @@ -Libpng 1.6.32 - August 24, 2017 +Libpng 1.6.34 - September 29, 2017 This is a public release of libpng, intended for use in production codes. @@ -7,79 +7,24 @@ Files available for download: Source files with LF line endings (for Unix/Linux) and with a "configure" script - libpng-1.6.32.tar.xz (LZMA-compressed, recommended) - libpng-1.6.32.tar.gz + libpng-1.6.34.tar.xz (LZMA-compressed, recommended) + libpng-1.6.34.tar.gz Source files with CRLF line endings (for Windows), without the "configure" script - lpng1632.7z (LZMA-compressed, recommended) - lpng1632.zip + lpng1634.7z (LZMA-compressed, recommended) + lpng1634.zip Other information: - libpng-1.6.32-README.txt - libpng-1.6.32-LICENSE.txt - libpng-1.6.32-*.asc (armored detached GPG signatures) + libpng-1.6.34-README.txt + libpng-1.6.34-LICENSE.txt + libpng-1.6.34-*.asc (armored detached GPG signatures) -Changes since the last public release (1.6.31): - Avoid possible NULL dereference in png_handle_eXIf when benign_errors - are allowed. Avoid leaking the input buffer "eXIf_buf". - Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif - to arguments for png_get_eXIf() and png_set_eXIf(). - Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in - pngwrite.c, and made various other fixes to png_write_eXIf(). - Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and - png_set_eXIf_1(), respectively, to avoid breaking API compatibility - with libpng-1.6.31. - Updated contrib/libtests/pngunknown.c with eXIf chunk. - Initialized btoa[] in pngstest.c - Stop memory leak when returning from png_handle_eXIf() with an error - (Bug report from the OSS-fuzz project). - Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). - Update libpng.3 and libpng-manual.txt about eXIf functions. - Restored png_get_eXIf() and png_set_eXIf() to maintain API compatability. - Removed png_get_eXIf_1() and png_set_eXIf_1(). - Check length of all chunks except IDAT against user limit to fix an - OSS-fuzz issue. - Check length of IDAT against maximum possible IDAT size, accounting - for height, rowbytes, interlacing and zlib/deflate overhead. - Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) - does not work (the eXIf chunk data can contain zeroes). - Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, - no longer using deprecated cmake LOCATION feature (Clifford Yapp). - Fixed five-byte error in the calculation of IDAT maximum possible size. - Moved chunk-length check into a png_check_chunk_length() private - function (Suggested by Max Stepin). - Moved bad pngs from tests to contrib/libtests/crashers - Moved testing of bad pngs into a separate tests/pngtest-badpngs script - Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL - in the output but PASS for the libpng test. - Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). - Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the - num_exif argument to png_get_eXIf_1() (Github Issue 171). - Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). - Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. - Make pngtest --strict, --relax, --xfail options imply -m (multiple). - Removed unused chunk_name parameter from png_check_chunk_length(). - Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. - Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. - Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. - Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. - Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account - for the minimum 'deflate' stream, and relocate the test to a point - after the keyword has been read. - Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". - Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, - one for each known chunk type, with length = 2GB-1. - Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts - in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, - and 162707). - Renamed chunks in contrib/testpngs/crashers to avoid having files whose - names differ only in case; this causes problems with some platforms - (github issue #172). - Added contrib/oss-fuzz directory which contains files used by the oss-fuzz - project (https://github.com/google/oss-fuzz/tree/master/projects/libpng). +Changes since the last public release (1.6.33): + Removed contrib/pngsuite/i*.png; some of these were incorrect and caused + test failures. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index 14e60dd269..4b82118910 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -833,7 +833,7 @@ Version 1.0.7beta11 [May 7, 2000] Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. @@ -5939,7 +5939,7 @@ Version 1.6.32beta06 [August 2, 2017] Version 1.6.32beta07 [August 3, 2017] Check length of all chunks except IDAT against user limit to fix an - OSS-fuzz issue. + OSS-fuzz issue (Fixes CVE-2017-12652). Version 1.6.32beta08 [August 3, 2017] Check length of IDAT against maximum possible IDAT size, accounting @@ -5994,6 +5994,53 @@ Version 1.6.32rc02 [August 22, 2017] Version 1.6.32 [August 24, 2017] No changes. +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of these were incorrect and caused + test failures. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE index e803911d37..4cda4fa0ad 100644 --- a/src/3rdparty/libpng/LICENSE +++ b/src/3rdparty/libpng/LICENSE @@ -10,7 +10,7 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000 through 1.6.32, August 24, 2017 are +libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals @@ -130,4 +130,4 @@ any encryption software. See the EAR, paragraphs 734.3(b)(3) and Glenn Randers-Pehrson glennrp at users.sourceforge.net -April 1, 2017 +September 29, 2017 diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index 71292715eb..0da5a5ef83 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.32 - August 24, 2017 (shared library 16.0) +README for libpng version 1.6.34 - September 29, 2017 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index e34b1436f5..d4407ef2ea 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.6.32 - August 24, 2017 + libpng version 1.6.34 - September 29, 2017 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2017 Glenn Randers-Pehrson @@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.6.32 - August 24, 2017 + libpng versions 0.97, January 1998, through 1.6.34 - September 29, 2017 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2017 Glenn Randers-Pehrson @@ -986,8 +986,17 @@ premultiplication. png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); -This is the default libpng handling of the alpha channel - it is not -pre-multiplied into the color components. In addition the call states +Choices for the alpha_mode are + + PNG_ALPHA_PNG 0 /* according to the PNG standard */ + PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ + PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ + PNG_ALPHA_PREMULTIPLIED 1 /* as above */ + PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ + PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_ALPHA_PNG is the default libpng handling of the alpha channel. It is not +pre-multiplied into the color components. In addition the call states that the output is for a sRGB system and causes all PNG files without gAMA chunks to be assumed to be encoded using sRGB. @@ -1002,7 +1011,7 @@ early Mac systems behaved. This is the classic Jim Blinn approach and will work in academic environments where everything is done by the book. It has the shortcoming of assuming that input PNG data with no gamma information is linear - this -is unlikely to be correct unless the PNG files where generated locally. +is unlikely to be correct unless the PNG files were generated locally. Most of the time the output precision will be so low as to show significant banding in dark areas of the image. @@ -5405,7 +5414,7 @@ Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.6.32 are Y2K compliant. It is my belief that earlier +upward through 1.6.34 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has two year fields. One is a 2-byte unsigned integer diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 2352df13cb..ff02c56518 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.32 [August 24, 2017] + * Last changed in libpng 1.6.33 [September 28, 2017] * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_32 Your_png_h_is_not_version_1_6_32; +typedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34; #ifdef __GNUC__ /* The version tests may need to be added to, but the problem warning has @@ -816,14 +816,14 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.32 - August 24, 2017" PNG_STRING_NEWLINE \ + "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.32 - August 24, 2017\ + return "libpng version 1.6.34 - September 29, 2017\ Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -1913,12 +1913,12 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); + (png_alloc_size_t)intent, "invalid sRGB rendering intent"); if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && colorspace->rendering_intent != intent) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); + (png_alloc_size_t)intent, "inconsistent rendering intents"); if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) { @@ -1979,7 +1979,6 @@ icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, if (profile_length < 132) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, "too short"); - return 1; } @@ -2224,22 +2223,23 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, * being in range. All defined tag types have an 8 byte header - a 4 byte * type signature then 0. */ + + /* This is a hard error; potentially it can cause read outside the + * profile. + */ + if (tag_start > profile_length || tag_length > profile_length - tag_start) + return png_icc_profile_error(png_ptr, colorspace, name, tag_id, + "ICC profile tag outside profile"); + if ((tag_start & 3) != 0) { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is * only a warning here because libpng does not care about the * alignment. */ (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, "ICC profile tag start not a multiple of 4"); } - - /* This is a hard error; potentially it can cause read outside the - * profile. - */ - if (tag_start > profile_length || tag_length > profile_length - tag_start) - return png_icc_profile_error(png_ptr, colorspace, name, tag_id, - "ICC profile tag outside profile"); } return 1; /* success, maybe with warnings */ @@ -3761,7 +3761,7 @@ png_log16bit(png_uint_32 x) * of getting this accuracy in practice. * * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the + * fractional part of the logarithm by using an accurate 32-bit value from the * top four fractional bits then multiplying in the remaining bits. */ static const png_uint_32 diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index 51ac8abe74..4c873f5c22 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.32, August 24, 2017 + * libpng version 1.6.34, September 29, 2017 * * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -12,7 +12,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.32, August 24, 2017: + * libpng versions 0.97, January 1998, through 1.6.34, September 29, 2017: * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -25,7 +25,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.32, August 24, 2017 are + * libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are * Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals @@ -209,11 +209,11 @@ * ... * 1.0.19 10 10019 10.so.0.19[.0] * ... - * 1.2.57 13 10257 12.so.0.57[.0] + * 1.2.59 13 10257 12.so.0.59[.0] * ... - * 1.5.28 15 10527 15.so.15.28[.0] + * 1.5.30 15 10527 15.so.15.30[.0] * ... - * 1.6.32 16 10632 16.so.16.32[.0] + * 1.6.34 16 10633 16.so.16.34[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -241,13 +241,13 @@ * Y2K compliance in libpng: * ========================= * - * August 24, 2017 + * September 29, 2017 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.32 are Y2K compliant. It is my belief that + * upward through 1.6.34 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -309,8 +309,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.32" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.32 - August 24, 2017\n" +#define PNG_LIBPNG_VER_STRING "1.6.34" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.34 - September 29, 2017\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -318,7 +318,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 32 +#define PNG_LIBPNG_VER_RELEASE 34 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: @@ -349,7 +349,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10632 /* 1.6.32 */ +#define PNG_LIBPNG_VER 10634 /* 1.6.34 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -459,7 +459,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_32; +typedef char* png_libpng_version_1_6_34; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -2819,6 +2819,8 @@ typedef struct # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ #endif +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + /* Commonly used formats have predefined macros. * * First the single byte (sRGB) formats: diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h index c0f15547be..d13b13e57a 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.32, August 24, 2017 + * libpng version 1.6.34, September 29, 2017 * * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index 9e45f73129..53b5e442c4 100644 --- a/src/3rdparty/libpng/pnglibconf.h +++ b/src/3rdparty/libpng/pnglibconf.h @@ -1,8 +1,8 @@ -/* libpng 1.6.32 STANDARD API DEFINITION */ +/* libpng 1.6.34 STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.32 - August 24, 2017 */ +/* Libpng version 1.6.34 - September 29, 2017 */ /* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c index e34ddd99a0..da32e9ad9c 100644 --- a/src/3rdparty/libpng/pngread.c +++ b/src/3rdparty/libpng/pngread.c @@ -1,7 +1,7 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] + * Last changed in libpng 1.6.33 [September 28, 2017] * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -3759,7 +3759,13 @@ png_image_read_direct(png_voidp argument) mode = PNG_ALPHA_PNG; output_gamma = PNG_DEFAULT_sRGB; } - + + if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) + { + mode = PNG_ALPHA_OPTIMIZED; + change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + /* If 'do_local_background' is set check for the presence of gamma * correction; this is part of the work-round for the libpng bug * described above. @@ -3985,6 +3991,10 @@ png_image_read_direct(png_voidp argument) else if (do_local_compose != 0) /* internal error */ png_error(png_ptr, "png_image_read: alpha channel lost"); + if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) { + info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + if (info_ptr->bit_depth == 16) info_format |= PNG_FORMAT_FLAG_LINEAR; diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c index 9a30ddf22b..c189650313 100644 --- a/src/3rdparty/libpng/pngrtran.c +++ b/src/3rdparty/libpng/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.31 [July 27, 2017] + * Last changed in libpng 1.6.33 [September 28, 2017] * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -430,7 +430,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int i; png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); for (i = 0; i < num_palette; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -447,7 +447,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize an array to sort colors */ png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); /* Initialize the quantize_sort array */ for (i = 0; i < num_palette; i++) @@ -581,9 +581,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize palette index arrays */ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -592,7 +594,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_ptr->palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 * (sizeof (png_dsortp)))); num_new_palette = num_palette; @@ -623,7 +625,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, { t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); + (png_alloc_size_t)(sizeof (png_dsort))); if (t == NULL) break; @@ -748,9 +750,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_size_t num_entries = ((png_size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_uint_32)(num_entries * (sizeof (png_byte)))); + (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); memset(distance, 0xff, num_entries * (sizeof (png_byte))); @@ -3322,7 +3324,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= + tmp |= (unsigned int)(png_ptr->background.gray << shift); *sp = (png_byte)(tmp & 0xff); } diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c index a4fa71457b..8692933bd8 100644 --- a/src/3rdparty/libpng/pngrutil.c +++ b/src/3rdparty/libpng/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] + * Last changed in libpng 1.6.33 [September 28, 2017] * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -314,6 +314,7 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) if (buffer != NULL) { + memset(buffer, 0, new_size); /* just in case */ png_ptr->read_buffer = buffer; png_ptr->read_buffer_size = new_size; } @@ -673,6 +674,8 @@ png_decompress_chunk(png_structrp png_ptr, if (text != NULL) { + memset(text, 0, buffer_size); + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, png_ptr->read_buffer + prefix_size, &lzsize, text + prefix_size, newlength); @@ -736,9 +739,7 @@ png_decompress_chunk(png_structrp png_ptr, { /* inflateReset failed, store the error message */ png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; + ret = PNG_UNEXPECTED_ZLIB_RETURN; } } @@ -1476,7 +1477,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole * profile. The header check has already validated - * that none of these stuff will overflow. + * that none of this stuff will overflow. */ const png_uint_32 tag_count = png_get_uint_32( profile_header+128); @@ -1583,19 +1584,11 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } } - - else if (size > 0) - errmsg = "truncated"; - -#ifndef __COVERITY__ - else + if (errmsg == NULL) errmsg = png_ptr->zstream.msg; -#endif } - /* else png_icc_check_tag_table output an error */ } - else /* profile truncated */ errmsg = png_ptr->zstream.msg; } @@ -3144,28 +3137,28 @@ png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) { png_alloc_size_t limit = PNG_UINT_31_MAX; - if (png_ptr->chunk_name != png_IDAT) - { # ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; # elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; # endif - } - else + if (png_ptr->chunk_name == png_IDAT) { + png_alloc_size_t idat_limit = PNG_UINT_31_MAX; size_t row_factor = (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1) + 1 + (png_ptr->interlaced? 6: 0)); if (png_ptr->height > PNG_UINT_32_MAX/row_factor) - limit=PNG_UINT_31_MAX; + idat_limit=PNG_UINT_31_MAX; else - limit = png_ptr->height * row_factor; - limit += 6 + 5*(limit/32566+1); /* zlib+deflate overhead */ - limit=limit < PNG_UINT_31_MAX? limit : PNG_UINT_31_MAX; + idat_limit = png_ptr->height * row_factor; + row_factor = row_factor > 32566? 32566 : row_factor; + idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */ + idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX; + limit = limit < idat_limit? idat_limit : limit; } if (length > limit) diff --git a/src/3rdparty/libpng/pngtrans.c b/src/3rdparty/libpng/pngtrans.c index 326ac33f0e..6882f0fd7b 100644 --- a/src/3rdparty/libpng/pngtrans.c +++ b/src/3rdparty/libpng/pngtrans.c @@ -1,7 +1,7 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.30 [June 28, 2017] + * Last changed in libpng 1.6.33 [September 28, 2017] * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -609,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = (unsigned int)(dp-row); + row_info->rowbytes = (png_size_t)(dp-row); } #endif @@ -708,7 +708,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) * forms produced on either GCC or MSVC. */ int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width); - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1; switch (row_info->bit_depth) { diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c index a7662acb71..a16d77ce00 100644 --- a/src/3rdparty/libpng/pngwrite.c +++ b/src/3rdparty/libpng/pngwrite.c @@ -1940,7 +1940,7 @@ png_image_write_main(png_voidp argument) int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); - int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); + int write_16bit = linear && (display->convert_to_8bit == 0); # ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Make sure we error out on any bad situation */ diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json index 7b2d776978..23fb903bdd 100644 --- a/src/3rdparty/libpng/qt_attribution.json +++ b/src/3rdparty/libpng/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "libpng is the official PNG reference library.", "Homepage": "http://www.libpng.org/pub/png/libpng.html", - "Version": "1.6.32", + "Version": "1.6.34", "License": "libpng License", "LicenseId": "Libpng", "LicenseFile": "LICENSE", -- cgit v1.2.3 From 421df7570b80ad7073d1af9b636ad42b8eb79ee8 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 7 Nov 2017 10:15:57 +0100 Subject: Enable glyph cache workaround for GC2000 as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The glyph cache resize is clearly doing something that is not actually legal with OpenGL ES. Until this gets investigated properly, add the Vivante GC2000 (found in the commonly used i.MX6 quad) to the list since reports show that the issue occurs there as well. Task-number: QTBUG-49490 Change-Id: Ia890346d8dbb1691bc113e2ef522713ba6709393 Reviewed-by: Louis Kröger Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/kernel/qopenglcontext.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 3dc06ae60e..cd6f011fcb 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -1008,6 +1008,7 @@ bool QOpenGLContext::makeCurrent(QSurface *surface) || qstrncmp(rendererString, "Adreno 4xx", 8) == 0 // Same as above but without the '(TM)' || qstrcmp(rendererString, "GC800 core") == 0 || qstrcmp(rendererString, "GC1000 core") == 0 + || strstr(rendererString, "GC2000") != 0 || qstrcmp(rendererString, "Immersion.16") == 0; } needsWorkaroundSet = true; -- cgit v1.2.3 From 59c5f7bd9da63621887260fc45e6669282d71ecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 6 Nov 2017 14:52:13 +0100 Subject: macOS: Fall back to QWindow::icon for application icon if not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are three ways to set the application (Dock/task switcher) icon: 1. By setting an ICON in the project file 2. By calling QGuiApplication::setWindowIcon 3. By calling QWindow::setIcon The third one was not working on macOS, despite being documented as such: "The window icon might be used by the windowing system for example to decorate the window, and/or in the task switcher." We now update the application icon based on the active window, unless a global application icon has been set using ICON, or via QGuiApplication::setWindowIcon. The reason for not allowing the window's icon to override a global application icon is that the developer may have intended to set the document icon for a window (to represent QWindow::filePath), and we don't want that to affect the Dock icon of the application. The role of QGuiApplication::setWindowIcon is a bit dubious in this, as it's documented as "This property holds the default window icon", which would indicate it should follow the same logic as above by not letting it override the global ICON set in the project file, but this would not allow runtime switching of the application icon, so the QGuiApplication property is left as is. The property should probably have been named QGuiApplication::applicationIcon initially. Task-number: QTBUG-63340 Change-Id: I94d3710a8586bb729af42f59a915b8f49dded101 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.h | 6 ++++- src/plugins/platforms/cocoa/qcocoaintegration.mm | 32 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index dc7c5916a3..2fc5156d24 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -60,8 +60,9 @@ QT_BEGIN_NAMESPACE class QCocoaScreen; -class QCocoaIntegration : public QPlatformIntegration +class QCocoaIntegration : public QObject, public QPlatformIntegration { + Q_OBJECT public: enum Option { UseFreeTypeFontEngine = 0x1 @@ -120,6 +121,9 @@ public: void beep() const Q_DECL_OVERRIDE; +private Q_SLOTS: + void focusWindowChanged(QWindow *); + private: static QCocoaIntegration *mInstance; Options mOptions; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index d185905782..55b3805df3 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -179,6 +179,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) QMacInternalPasteboardMime::initializeMimeTypes(); QCocoaMimeTypes::initializeMimeTypes(); QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); + + connect(qGuiApp, &QGuiApplication::focusWindowChanged, + this, &QCocoaIntegration::focusWindowChanged); } QCocoaIntegration::~QCocoaIntegration() @@ -510,4 +513,33 @@ void QCocoaIntegration::beep() const NSBeep(); } +void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow) +{ + // Don't revert icon just because we lost focus + if (!focusWindow) + return; + + static bool hasDefaultApplicationIcon = [](){ + NSImage *genericApplicationIcon = [[NSWorkspace sharedWorkspace] + iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; + NSImage *applicationIcon = [NSImage imageNamed:NSImageNameApplicationIcon]; + + NSRect rect = NSMakeRect(0, 0, 32, 32); + return [applicationIcon CGImageForProposedRect:&rect context:nil hints:nil] + == [genericApplicationIcon CGImageForProposedRect:&rect context:nil hints:nil]; + }(); + + // Don't let the window icon override an explicit application icon set in the Info.plist + if (!hasDefaultApplicationIcon) + return; + + // Or an explicit application icon set on QGuiApplication + if (!qGuiApp->windowIcon().isNull()) + return; + + setApplicationIcon(focusWindow->icon()); +} + +#include "moc_qcocoaintegration.cpp" + QT_END_NAMESPACE -- cgit v1.2.3 From c3aa422df6e3eb4af7bd75c7255586e9e5f79197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 6 Nov 2017 15:18:14 +0100 Subject: QWidget: Propagate window file path after create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-63340 Change-Id: Ic21964a33ee2910200627fe8a8c8ec2454e2e20c Reviewed-by: Morten Johan Sørvig --- src/widgets/kernel/qwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 9b6c3df828..de734b6f51 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1372,6 +1372,8 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) d->setWindowIconText_helper(d->topData()->iconText); if (isWindow() && !d->topData()->caption.isEmpty()) d->setWindowTitle_helper(d->topData()->caption); + if (isWindow() && !d->topData()->filePath.isEmpty()) + d->setWindowFilePath_helper(d->topData()->filePath); if (windowType() != Qt::Desktop) { d->updateSystemBackground(); -- cgit v1.2.3 From b02bd4bbad9f80154307d06ad95a6f96c30858f0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 15 Aug 2017 11:19:32 +0700 Subject: QMenuPrivate: Rearrange member variables This saves 32 bytes per instance on 64-bit macOS, from 888 down to 856 bytes. Change-Id: I2592631aa3566d2eab72bad338aacfe76bee8ef3 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qmenu_p.h | 129 +++++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 4b7ce05169..8adfc82ef5 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -92,18 +92,18 @@ class QMenuSloppyState public: QMenuSloppyState() : m_menu(Q_NULLPTR) + , m_reset_action(Q_NULLPTR) + , m_origin_action(Q_NULLPTR) + , m_parent(Q_NULLPTR) + , m_uni_dir_discarded_count(0) + , m_uni_dir_fail_at_count(0) + , m_timeout(0) + , m_init_guard(false) + , m_first_mouse(true) , m_enabled(false) , m_uni_directional(false) , m_select_other_actions(false) - , m_first_mouse(true) - , m_init_guard(false) , m_use_reset_action(true) - , m_uni_dir_discarded_count(0) - , m_uni_dir_fail_at_count(0) - , m_timeout(0) - , m_reset_action(Q_NULLPTR) - , m_origin_action(Q_NULLPTR) - , m_parent(Q_NULLPTR) { } ~QMenuSloppyState() { reset(); } @@ -253,43 +253,59 @@ public: private: QMenu *m_menu; - bool m_enabled; - bool m_uni_directional; - bool m_select_other_actions; - bool m_first_mouse; - bool m_init_guard; - bool m_discard_state_when_entering_parent; - bool m_dont_start_time_on_leave; - bool m_use_reset_action; - short m_uni_dir_discarded_count; - short m_uni_dir_fail_at_count; - short m_timeout; - QBasicTimer m_time; QAction *m_reset_action; QAction *m_origin_action; QRectF m_action_rect; QPointF m_previous_point; QPointer m_sub_menu; QMenuSloppyState *m_parent; + QBasicTimer m_time; + short m_uni_dir_discarded_count; + short m_uni_dir_fail_at_count; + short m_timeout; + bool m_init_guard; + bool m_first_mouse; + + bool m_enabled : 1; + bool m_uni_directional : 1; + bool m_select_other_actions : 1; + bool m_discard_state_when_entering_parent : 1; + bool m_dont_start_time_on_leave : 1; + bool m_use_reset_action : 1; }; class QMenuPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QMenu) public: - QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0), - collapsibleSeparators(true), toolTipsVisible(false), - activationRecursionGuard(false), delayedPopupGuard(false), - hasReceievedEnter(false), - hasHadMouse(0), aboutToHide(0), motions(0), - currentAction(0), + QMenuPrivate() : + currentAction(nullptr), #ifdef QT_KEYPAD_NAVIGATION - selectAction(0), - cancelAction(0), + selectAction(nullptr), + cancelAction(nullptr), #endif - scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0), - hasCheckableItems(0), doChildEffects(false), platformMenu(0), - scrollUpTearOffItem(nullptr), scrollDownItem(nullptr) + scroll(nullptr), + eventLoop(nullptr), + platformMenu(nullptr), + scrollUpTearOffItem(nullptr), + scrollDownItem(nullptr), + maxIconWidth(0), + tabWidth(0), + motions(0), + activationRecursionGuard(false), + ncols(0), + itemsDirty(false), + hasCheckableItems(false), + collapsibleSeparators(true), + toolTipsVisible(false), + delayedPopupGuard(false), + hasReceievedEnter(false), + hasHadMouse(false), + aboutToHide(false), + tearoff(false), + tornoff(false), + tearoffHighlighted(false), + doChildEffects(false) { } ~QMenuPrivate() @@ -310,8 +326,6 @@ public: int scrollerHeight() const; //item calculations - mutable uint itemsDirty : 1; - mutable uint maxIconWidth, tabWidth; QRect actionRect(QAction *) const; mutable QVector actionRects; @@ -320,22 +334,12 @@ public: void updateActionRects(const QRect &screen) const; QRect popupGeometry() const; QRect popupGeometry(int screen) const; - mutable uint ncols : 4; //4 bits is probably plenty - uint collapsibleSeparators : 1; - uint toolTipsVisible : 1; int getLastVisibleAction() const; - bool activationRecursionGuard; - bool delayedPopupGuard; - bool hasReceievedEnter; - //selection static QMenu *mouseDown; QPoint mousePopupPos; - uint hasHadMouse : 1; - uint aboutToHide : 1; - int motions; - int mousePopupDelay; + QAction *currentAction; #ifdef QT_KEYPAD_NAVIGATION QAction *selectAction; @@ -365,8 +369,8 @@ public: } QMenu *parent; - QBasicTimer timer; QAction *action; + QBasicTimer timer; } delayState; enum SelectionReason { SelectedFromKeyboard, @@ -383,11 +387,12 @@ public: struct QMenuScroller { enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter }; enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 }; - uint scrollFlags : 2, scrollDirection : 2; int scrollOffset; QBasicTimer scrollTimer; + quint8 scrollFlags; + quint8 scrollDirection; - QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { } + QMenuScroller() : scrollOffset(0), scrollFlags(ScrollNone), scrollDirection(ScrollNone) { } ~QMenuScroller() { } } *scroll; void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false); @@ -421,11 +426,8 @@ public: inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); } //tear off support - uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1; QPointer tornPopup; - mutable bool hasCheckableItems; - QMenuSloppyState sloppyState; //default action @@ -450,9 +452,6 @@ public: void adjustMenuScreen(const QPoint &p); void updateLayoutDirection(); - //menu fading/scrolling effects - bool doChildEffects; - QPointer platformMenu; QPointer actionAboutToTrigger; @@ -477,6 +476,30 @@ public: void drawScroller(QPainter *painter, ScrollerTearOffItem::Type type, const QRect &rect); void drawTearOff(QPainter *painter, const QRect &rect); QRect rect() const; + + mutable uint maxIconWidth, tabWidth; + int motions; + int mousePopupDelay; + + bool activationRecursionGuard; + + mutable quint8 ncols; // "255cols ought to be enough for anybody." + + mutable bool itemsDirty : 1; + mutable bool hasCheckableItems : 1; + bool collapsibleSeparators : 1; + bool toolTipsVisible : 1; + bool delayedPopupGuard : 1; + bool hasReceievedEnter : 1; + // Selection + bool hasHadMouse : 1; + bool aboutToHide : 1; + // Tear-off menus + bool tearoff : 1; + bool tornoff : 1; + bool tearoffHighlighted : 1; + //menu fading/scrolling effects + bool doChildEffects : 1; }; QT_END_NAMESPACE -- cgit v1.2.3 From 237b1c1d689fabf1680a8cf3d9226da5f712302d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Sat, 26 Aug 2017 11:26:45 +0700 Subject: QMenuPrivate: Use in-class initializers where possible Change-Id: I5347cb41443baf96e28bd399c84983a801b10fcd Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qmenu_p.h | 87 +++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 8adfc82ef5..64d22087e3 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -91,16 +91,7 @@ class QMenuSloppyState Q_DISABLE_COPY(QMenuSloppyState) public: QMenuSloppyState() - : m_menu(Q_NULLPTR) - , m_reset_action(Q_NULLPTR) - , m_origin_action(Q_NULLPTR) - , m_parent(Q_NULLPTR) - , m_uni_dir_discarded_count(0) - , m_uni_dir_fail_at_count(0) - , m_timeout(0) - , m_init_guard(false) - , m_first_mouse(true) - , m_enabled(false) + : m_enabled(false) , m_uni_directional(false) , m_select_other_actions(false) , m_use_reset_action(true) @@ -252,19 +243,19 @@ public: QMenu *subMenu() const { return m_sub_menu; } private: - QMenu *m_menu; - QAction *m_reset_action; - QAction *m_origin_action; + QMenu *m_menu = nullptr; + QAction *m_reset_action = nullptr; + QAction *m_origin_action = nullptr; QRectF m_action_rect; QPointF m_previous_point; QPointer m_sub_menu; - QMenuSloppyState *m_parent; + QMenuSloppyState *m_parent = nullptr; QBasicTimer m_time; - short m_uni_dir_discarded_count; - short m_uni_dir_fail_at_count; - short m_timeout; - bool m_init_guard; - bool m_first_mouse; + short m_uni_dir_discarded_count = 0; + short m_uni_dir_fail_at_count = 0; + short m_timeout = 0; + bool m_init_guard = false; + bool m_first_mouse = true; bool m_enabled : 1; bool m_uni_directional : 1; @@ -279,21 +270,6 @@ class QMenuPrivate : public QWidgetPrivate Q_DECLARE_PUBLIC(QMenu) public: QMenuPrivate() : - currentAction(nullptr), -#ifdef QT_KEYPAD_NAVIGATION - selectAction(nullptr), - cancelAction(nullptr), -#endif - scroll(nullptr), - eventLoop(nullptr), - platformMenu(nullptr), - scrollUpTearOffItem(nullptr), - scrollDownItem(nullptr), - maxIconWidth(0), - tabWidth(0), - motions(0), - activationRecursionGuard(false), - ncols(0), itemsDirty(false), hasCheckableItems(false), collapsibleSeparators(true), @@ -340,15 +316,13 @@ public: static QMenu *mouseDown; QPoint mousePopupPos; - QAction *currentAction; + QAction *currentAction = nullptr; #ifdef QT_KEYPAD_NAVIGATION - QAction *selectAction; - QAction *cancelAction; + QAction *selectAction = nullptr; + QAction *cancelAction = nullptr; #endif struct DelayState { DelayState() - : parent(0) - , action(0) { } void initialize(QMenu *parent) { @@ -368,8 +342,8 @@ public: timer.stop(); } - QMenu *parent; - QAction *action; + QMenu *parent = nullptr; + QAction *action = nullptr; QBasicTimer timer; } delayState; enum SelectionReason { @@ -387,20 +361,20 @@ public: struct QMenuScroller { enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter }; enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 }; - int scrollOffset; + int scrollOffset = 0; QBasicTimer scrollTimer; - quint8 scrollFlags; - quint8 scrollDirection; + quint8 scrollFlags = ScrollNone; + quint8 scrollDirection = ScrollNone; - QMenuScroller() : scrollOffset(0), scrollFlags(ScrollNone), scrollDirection(ScrollNone) { } + QMenuScroller() { } ~QMenuScroller() { } - } *scroll; + } *scroll = nullptr; void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false); void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false); void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false); //synchronous operation (ie exec()) - QEventLoop *eventLoop; + QEventLoop *eventLoop = nullptr; QPointer syncAction; //search buffer @@ -433,8 +407,8 @@ public: //default action QPointer defaultAction; - QAction *menuAction; - QAction *defaultMenuAction; + QAction *menuAction = nullptr; + QAction *defaultMenuAction = nullptr; void setOverrideMenuAction(QAction *); void _q_overrideMenuActionDestroyed(); @@ -470,20 +444,21 @@ public: QMenuPrivate *menuPrivate; Type scrollType; }; - ScrollerTearOffItem *scrollUpTearOffItem; - ScrollerTearOffItem *scrollDownItem; + ScrollerTearOffItem *scrollUpTearOffItem = nullptr; + ScrollerTearOffItem *scrollDownItem = nullptr; void drawScroller(QPainter *painter, ScrollerTearOffItem::Type type, const QRect &rect); void drawTearOff(QPainter *painter, const QRect &rect); QRect rect() const; - mutable uint maxIconWidth, tabWidth; - int motions; - int mousePopupDelay; + mutable uint maxIconWidth = 0; + mutable uint tabWidth = 0; + int motions = 0; + int mousePopupDelay = 0; - bool activationRecursionGuard; + bool activationRecursionGuard = false; - mutable quint8 ncols; // "255cols ought to be enough for anybody." + mutable quint8 ncols = 0; // "255cols ought to be enough for anybody." mutable bool itemsDirty : 1; mutable bool hasCheckableItems : 1; -- cgit v1.2.3 From 7986e1e2f0c88ea305dd8a842884908ed4724fd7 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 20 Oct 2017 18:12:17 +0700 Subject: QMenuBar: Update title on change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When one of the menubar actions changed, we would omit to update several properties on the platform menu, most notably its title. Manual tested with BigMenuCreator, where the sequence menu->addAction(action); // A-operation action->setMenu(submenu); // S-operation would result in an "Untitled" menubar item on macOS, and this regardless of when the submenu is populated. Change-Id: I43989f36f6bf3f0b7056310ac986c06f8e02f128 Reviewed-by: Dmitry Shachnev Reviewed-by: Erik Verbruggen Reviewed-by: Morten Johan Sørvig --- src/widgets/widgets/qmenubar.cpp | 54 +++++++++++++++++++++++----------------- src/widgets/widgets/qmenubar_p.h | 4 ++- 2 files changed, 34 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 41b6bf49f8..6dfbb7c8a1 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1187,7 +1187,7 @@ void QMenuBar::leaveEvent(QEvent *) d->setCurrentAction(0); } -QPlatformMenu *QMenuBarPrivate::getPlatformMenu(QAction *action) +QPlatformMenu *QMenuBarPrivate::getPlatformMenu(const QAction *action) { if (!action || !action->menu()) return 0; @@ -1202,6 +1202,29 @@ QPlatformMenu *QMenuBarPrivate::getPlatformMenu(QAction *action) return platformMenu; } +QPlatformMenu *QMenuBarPrivate::findInsertionPlatformMenu(const QAction *action) +{ + Q_Q(QMenuBar); + QPlatformMenu *beforeMenu = nullptr; + for (int beforeIndex = indexOf(const_cast(action)) + 1; + !beforeMenu && (beforeIndex < q->actions().size()); + ++beforeIndex) { + beforeMenu = getPlatformMenu(q->actions().at(beforeIndex)); + } + + return beforeMenu; +} + +void QMenuBarPrivate::copyActionToPlatformMenu(const QAction *action, QPlatformMenu *menu) +{ + const auto tag = reinterpret_cast(action); + if (menu->tag() != tag) + menu->setTag(tag); + menu->setText(action->text()); + menu->setVisible(action->isVisible()); + menu->setEnabled(action->isEnabled()); +} + /*! \reimp */ @@ -1218,16 +1241,9 @@ void QMenuBar::actionEvent(QActionEvent *e) if (e->type() == QEvent::ActionAdded) { QPlatformMenu *menu = d->getPlatformMenu(e->action()); if (menu) { - QPlatformMenu* beforeMenu = NULL; - for (int beforeIndex = d->indexOf(e->action()) + 1; - !beforeMenu && (beforeIndex < actions().size()); - ++beforeIndex) - { - beforeMenu = d->getPlatformMenu(actions().at(beforeIndex)); - } + d->copyActionToPlatformMenu(e->action(), menu); - menu->setTag(reinterpret_cast(e->action())); - menu->setText(e->action()->text()); + QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(e->action()); d->platformMenuBar->insertMenu(menu, beforeMenu); } } else if (e->type() == QEvent::ActionRemoved) { @@ -1235,7 +1251,7 @@ void QMenuBar::actionEvent(QActionEvent *e) if (menu) d->platformMenuBar->removeMenu(menu); } else if (e->type() == QEvent::ActionChanged) { - QPlatformMenu* cur = d->platformMenuBar->menuForTag(reinterpret_cast(e->action())); + QPlatformMenu *cur = d->platformMenuBar->menuForTag(reinterpret_cast(e->action())); QPlatformMenu *menu = d->getPlatformMenu(e->action()); // the menu associated with the action can change, need to @@ -1244,21 +1260,13 @@ void QMenuBar::actionEvent(QActionEvent *e) if (cur) d->platformMenuBar->removeMenu(cur); if (menu) { - menu->setTag(reinterpret_cast(e->action())); - - QPlatformMenu* beforeMenu = NULL; - for (int beforeIndex = d->indexOf(e->action()) + 1; - !beforeMenu && (beforeIndex < actions().size()); - ++beforeIndex) - { - beforeMenu = d->getPlatformMenu(actions().at(beforeIndex)); - } + d->copyActionToPlatformMenu(e->action(), menu); + + QPlatformMenu *beforeMenu = d->findInsertionPlatformMenu(e->action()); d->platformMenuBar->insertMenu(menu, beforeMenu); } } else if (menu) { - menu->setText(e->action()->text()); - menu->setVisible(e->action()->isVisible()); - menu->setEnabled(e->action()->isEnabled()); + d->copyActionToPlatformMenu(e->action(), menu); d->platformMenuBar->syncMenu(menu); } } diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h index 01d8793a3a..c276a4512d 100644 --- a/src/widgets/widgets/qmenubar_p.h +++ b/src/widgets/widgets/qmenubar_p.h @@ -132,7 +132,9 @@ public: QBasicTimer autoReleaseTimer; QPlatformMenuBar *platformMenuBar; - QPlatformMenu *getPlatformMenu(QAction *action); + QPlatformMenu *getPlatformMenu(const QAction *action); + QPlatformMenu *findInsertionPlatformMenu(const QAction *action); + void copyActionToPlatformMenu(const QAction *e, QPlatformMenu *menu); inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); } }; -- cgit v1.2.3 From 5d6878f234d1d8697bba43cb5140094dee722a86 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 24 Oct 2017 14:53:31 +0700 Subject: QMainWindow: Clear menubar parent when new one is set In QMainWindow::setMenuBar(), we hide and schedule the current menubar, if any, to be deleted later. However, it remains installed as its whole ancestry's event filter, which could conflict with the newly assigned menubar until the old menubar is destroyed. In our case, we have noticed issues with the Cocoa QPA plugin. We force uninstalling the old menubar as event filter by setting its parent to null, pending its deletion shortly after. This fixes BigMenuCreator's empty menubar when calling it with only the "--new-menubar" option. It also fixes QTBUG-34160 example which was not behaving as well as it should. Task-number: QTBUG-34160 Change-Id: Ifefb72affad01e7b7371005442074afd6a39a5b8 Reviewed-by: Dmitry Shachnev Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qmainwindow.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 5c6f983149..ced7ec38ea 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -574,6 +574,7 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) menuBar->setCornerWidget(cornerWidget, Qt::TopRightCorner); } oldMenuBar->hide(); + oldMenuBar->setParent(nullptr); oldMenuBar->deleteLater(); } topLayout->setMenuBar(menuBar); -- cgit v1.2.3 From 3f519ffa150ce5a2d9e3ad3f147745b312d29afb Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 25 Oct 2017 09:32:48 +0700 Subject: QCocoaMenuItem: Don't clear NSMenuItem.action when setting submenu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contrarily to what the comment stated, we actually rely on automatic menu validation, even for submenu items. This is visible in the menu delegate's validateMenuItem: and itemFired: methods. This solves the last visible issue in BigMenuCreator where, under ASP/ASP, ASP/SAP, SAP/ASP and SAP/SAP, all A*S submenus would be disabled. The cause was an incorrect target/action setup. Menurama still behaves as expected. Change-Id: I2599d6fb0d51f56f5d36f03b69647e35ff6c550a Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenuitem.mm | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index ecbab38a83..394e0fb8e4 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -150,10 +150,6 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) QMacAutoReleasePool pool; m_menu = static_cast(menu); if (m_menu) { - if (m_native) { - // Skip automatic menu item validation - m_native.action = nil; - } m_menu->setMenuParent(this); m_menu->propagateEnabledState(isEnabled()); } else { -- cgit v1.2.3 From 159b3306d66d91274feb9fd28fdc176cecf47755 Mon Sep 17 00:00:00 2001 From: Helio Chissini de Castro Date: Wed, 27 Sep 2017 10:11:50 +0200 Subject: Change fallthrough detection order to fix clang detection Clang compiler defines fallthrough, but wrongly detects QT_HAS_CPP_ATTRIBUTE(fallthrough). This makes compiler breaks compilation due clang be expecting clang::fallthrough. Change the order makes the exceptions. clang/gnu, been tested before the generic, setting then proper defines at end. LLVM-bug: https://bugs.llvm.org/show_bug.cgi?id=33518 Change-Id: Ic287e9028936af3bdade5c1ee319ca8914b36ea7 Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 2c58ff87e9..231ac2c9b0 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1347,12 +1347,12 @@ } while (false) #if defined(__cplusplus) -#if QT_HAS_CPP_ATTRIBUTE(fallthrough) -# define Q_FALLTHROUGH() [[fallthrough]] -#elif QT_HAS_CPP_ATTRIBUTE(clang::fallthrough) +#if QT_HAS_CPP_ATTRIBUTE(clang::fallthrough) # define Q_FALLTHROUGH() [[clang::fallthrough]] #elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough) # define Q_FALLTHROUGH() [[gnu::fallthrough]] +#elif QT_HAS_CPP_ATTRIBUTE(fallthrough) +# define Q_FALLTHROUGH() [[fallthrough]] #endif #endif #ifndef Q_FALLTHROUGH -- cgit v1.2.3 From 19b0ce5daa31e2ffebfcf2701143742302f1deb4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 13 Apr 2017 21:13:52 -0700 Subject: Change almost all other uses of qrand() to QRandomGenerator The vast majority is actually switched to QRandomGenerator::bounded(), which gives a mostly uniform distribution over the [0, bound) range. There are very few floating point cases left, as many of those that did use floating point did not need to, after all. (I did leave some that were too ugly for me to understand) This commit also found a couple of calls to rand() instead of qrand(). This commit does not include changes to SSL code that continues to use qrand() (job for someone else): src/network/ssl/qsslkey_qt.cpp src/network/ssl/qsslsocket_mac.cpp tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp Change-Id: Icd0e0d4b27cb4e5eb892fffd14b5285d43f4afbf Reviewed-by: Lars Knoll --- src/corelib/io/qprocess_win.cpp | 7 +++---- src/corelib/io/qtemporaryfile.cpp | 2 +- src/gui/image/qpixmap_blitter.cpp | 3 ++- src/gui/opengl/qopenglgradientcache.cpp | 3 ++- src/gui/painting/qpaintengine_raster.cpp | 3 ++- src/network/kernel/qdnslookup.cpp | 11 +++-------- src/opengl/gl2paintengineex/qglgradientcache.cpp | 3 ++- 7 files changed, 15 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 2bbc4eddd0..8da6d6b16e 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -99,10 +100,8 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe) wchar_t pipeName[256]; unsigned int attempts = 1000; forever { - // ### The user must make sure to call qsrand() to make the pipe names less predictable. - // ### Replace the call to qrand() with a secure version, once we have it in Qt. _snwprintf(pipeName, sizeof(pipeName) / sizeof(pipeName[0]), - L"\\\\.\\pipe\\qt-%X", qrand()); + L"\\\\.\\pipe\\qt-%X", QRandomGenerator::global()->generate()); DWORD dwOpenMode = FILE_FLAG_OVERLAPPED; DWORD dwOutputBufferSize = 0; diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 5865d9e19a..b8d3e859cf 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -165,7 +165,7 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext() Char *rIter = placeholderEnd; while (rIter != placeholderStart) { - quint32 rnd = QRandomGenerator::generate(); + quint32 rnd = QRandomGenerator::global()->generate(); auto applyOne = [&]() { quint32 v = rnd & ((1 << BitsPerCharacter) - 1); rnd >>= BitsPerCharacter; diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index de32327071..d694352fc1 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -252,7 +253,7 @@ QImage *QBlittablePlatformPixmap::overlay() m_rasterOverlay->size() != QSize(w,h)){ m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied); m_rasterOverlay->fill(0x00000000); - uint color = (qrand() % 11)+7; + uint color = QRandomGenerator::global()->bounded(11)+7; m_overlayColor = QColor(Qt::GlobalColor(color)); m_overlayColor.setAlpha(0x88); diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index 58dcbed50a..3aa4c0d2e6 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include "qopenglfunctions.h" #include "qopenglextensions_p.h" @@ -137,7 +138,7 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient { QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); if (cache.size() == maxCacheSize()) { - int elem_to_remove = qrand() % maxCacheSize(); + int elem_to_remove = QRandomGenerator::global()->bounded(maxCacheSize()); quint64 key = cache.keys()[elem_to_remove]; // need to call glDeleteTextures on each removed cache entry: diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 68554c6579..d0d948bbb7 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -50,6 +50,7 @@ #include #include #include +#include // #include // #include @@ -4229,7 +4230,7 @@ protected: QSharedPointer addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK - cache.erase(cache.begin() + (qrand() % maxCacheSize())); + cache.erase(cache.begin() + QRandomGenerator::global()->bounded(maxCacheSize())); } auto cache_entry = QSharedPointer::create(gradient.stops(), opacity, gradient.interpolationMode()); generateGradientColorTable(gradient, cache_entry->buffer64, paletteSize(), opacity); diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 6203ba37b3..10ff35b72c 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -42,7 +42,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,6 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QDnsLookupThreadPool, theDnsLookupThreadPool); -Q_GLOBAL_STATIC(QThreadStorage, theDnsLookupSeedStorage); static bool qt_qdnsmailexchangerecord_less_than(const QDnsMailExchangeRecord &r1, const QDnsMailExchangeRecord &r2) { @@ -85,7 +84,7 @@ static void qt_qdnsmailexchangerecord_sort(QList &record // Randomize the slice of records. while (!slice.isEmpty()) { - const unsigned int pos = qrand() % slice.size(); + const unsigned int pos = QRandomGenerator::global()->bounded(slice.size()); records[i++] = slice.takeAt(pos); } } @@ -134,7 +133,7 @@ static void qt_qdnsservicerecord_sort(QList &records) // Order the slice of records. while (!slice.isEmpty()) { - const unsigned int weightThreshold = qrand() % (sliceWeight + 1); + const unsigned int weightThreshold = QRandomGenerator::global()->bounded(sliceWeight + 1); unsigned int summedWeight = 0; for (int j = 0; j < slice.size(); ++j) { summedWeight += slice.at(j).weight(); @@ -1011,10 +1010,6 @@ void QDnsLookupRunnable::run() query(requestType, requestName, nameserver, &reply); // Sort results. - if (!theDnsLookupSeedStorage()->hasLocalData()) { - qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast(this)); - theDnsLookupSeedStorage()->setLocalData(new bool(true)); - } qt_qdnsmailexchangerecord_sort(reply.mailExchangeRecords); qt_qdnsservicerecord_sort(reply.serviceRecords); diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index b4ca49514f..fc5e236ca6 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -41,6 +41,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -130,7 +131,7 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra { QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); if (cache.size() == maxCacheSize()) { - int elem_to_remove = qrand() % maxCacheSize(); + int elem_to_remove = QRandomGenerator::global()->bounded(maxCacheSize()); quint64 key = cache.keys()[elem_to_remove]; // need to call glDeleteTextures on each removed cache entry: -- cgit v1.2.3 From dfdd99fc123ee80e162f0c14b4687fa00a328215 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 25 Sep 2017 12:09:08 +0200 Subject: Doc: Be more specific on full stop in QVersionNumber So far we just write ... '.'. , which looks weird. Change-Id: Iac6fc781c80976994ea0a182b55958baa39a7e52 Reviewed-by: Leena Miettinen --- src/corelib/tools/qversionnumber.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 97e5da8b3c..d2667ddea9 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -388,7 +388,7 @@ QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, /*! \fn QString QVersionNumber::toString() const - Returns a string with all of the segments delimited by a '.'. + Returns a string with all of the segments delimited by a period (\c{.}). \sa majorVersion(), minorVersion(), microVersion(), segments() */ @@ -411,7 +411,7 @@ QString QVersionNumber::toString() const int *suffixIndex) Constructs a QVersionNumber from a specially formatted \a string of - non-negative decimal numbers delimited by '.'. + non-negative decimal numbers delimited by a period (\c{.}). Once the numerical segments have been parsed, the remainder of the string is considered to be the suffix string. The start index of that string will be -- cgit v1.2.3 From 7d10936443750b8b0c90bf1c979ad6ab51eb92a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sun, 5 Nov 2017 16:18:54 +0100 Subject: Fix QHighDpi::fromNativeLocalExposedRegion rounding errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ceiling width/height fails to take into account rects that do no have their top left position on an exact point boundary. Example: QRect(0,0 20x20) and QRect(1,1 20x20) with scale 2.0 would give the same result of QRect(0,0 10x10). The correct rects are QRect(0,0 10x10) and QRect(0,0 11x11), so that we are sure to repaint all pixels within the exposed region. Before 5138fada0b9c, rects were also rounded incorrectly. The old method would give the result of QRect(0,0 11x11) in both cases, causing the exposed region to be larger than a window. Amends 5138fada0b9ce3968b23ec11df5f0d4e67544c43 Task-number: QTBUG-63943 Change-Id: I9f3dddf649bdc506c23bce1b6704860d61481459 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qhighdpiscaling_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index 0a060a2d2c..83fc9452c5 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -402,7 +402,8 @@ inline QRegion fromNativeLocalExposedRegion(const QRegion &pixelRegion, const QW const QPointF topLeftP = rect.topLeft() / scaleFactor; const QSizeF sizeP = rect.size() / scaleFactor; pointRegion += QRect(QPoint(qFloor(topLeftP.x()), qFloor(topLeftP.y())), - QSize(qCeil(sizeP.width()), qCeil(sizeP.height()))); + QPoint(qCeil(topLeftP.x() + sizeP.width() - 1.0), + qCeil(topLeftP.y() + sizeP.height() - 1.0))); } return pointRegion; } -- cgit v1.2.3 From d0736e9d17d0b3ec2f7aa3f323a1edf70aa83e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 7 Nov 2017 15:03:32 +0100 Subject: Cocoa: Make High DPI drag cursor work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ide4bc50ab7173529a00fe60a04204bad0b3f275e Task-id: QTBUG-60769 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index ec9d25fff9..2e64204fb7 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -2068,6 +2068,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin } else { NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor); + nsimage.size = NSSizeFromCGSize((pixmapCursor.size() / pixmapCursor.devicePixelRatioF()).toCGSize()); nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint]; [nsimage release]; } -- cgit v1.2.3 From 4502999ff054f16aab1fdd99fbd9256b22ecadf9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 12 Oct 2017 21:58:51 -0700 Subject: QRandomGenerator: remove the per-thread buffer Since we're adding a deterministic generator that inherently does not use syscalls, and people should really use that one by default, there is no point in optimizing the secure generator wrt syscalls. Besides, keeping the random data in memory for longer than needed is likely inadviseable. Change-Id: Ib17dde1a1dbb49a7bba8fffd14ed0871117fe930 Reviewed-by: Lars Knoll --- src/corelib/global/qrandom.cpp | 72 +++++------------------------------------- src/corelib/global/qrandom_p.h | 1 - 2 files changed, 8 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 9abb9ece7f..17f25ead86 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -129,7 +129,6 @@ namespace { class SystemRandom { public: - enum { EfficientBufferFill = true }; static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { // getentropy can read at most 256 bytes, so break the reading @@ -217,7 +216,6 @@ qssize_t SystemRandom::fillBuffer(void *buffer, qssize_t count) class SystemRandom { public: - enum { EfficientBufferFill = true }; static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { auto RtlGenRandom = SystemFunction036; @@ -228,7 +226,6 @@ public: class SystemRandom { public: - enum { EfficientBufferFill = false }; static qssize_t fillBuffer(void *, qssize_t) Q_DECL_NOTHROW { // always use the fallback @@ -362,9 +359,15 @@ static qssize_t fill_cpu(quint32 *buffer, qssize_t count) Q_DECL_NOTHROW return 0; } -static void fill_internal(quint32 *buffer, qssize_t count) - Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(buffer, count))) +static Q_NEVER_INLINE void fill(void *begin, void *end) + Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(nullptr, 1))) { + // Verify that the pointers are properly aligned for 32-bit + Q_ASSERT(quintptr(begin) % sizeof(quint32) == 0); + Q_ASSERT(quintptr(end) % sizeof(quint32) == 0); + quint32 *buffer = reinterpret_cast(begin); + qssize_t count = reinterpret_cast(end) - buffer; + if (Q_UNLIKELY(uint(qt_randomdevice_control) & SetRandomData)) { uint value = uint(qt_randomdevice_control) & RandomDataMask; std::fill_n(buffer, count, value); @@ -386,65 +389,6 @@ static void fill_internal(quint32 *buffer, qssize_t count) } } -static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) - Q_DECL_NOEXCEPT_EXPR(noexcept(fill_internal(static_cast(buffer), 1))) -{ - struct ThreadState { - enum { - DesiredBufferByteSize = 32, - BufferCount = DesiredBufferByteSize / sizeof(quint32) - }; - quint32 buffer[BufferCount]; - int idx = BufferCount; - }; - - // Verify that the pointers are properly aligned for 32-bit - Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0); - Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0); - - quint32 *ptr = reinterpret_cast(buffer); - quint32 * const end = reinterpret_cast(bufferEnd); - -#if defined(Q_COMPILER_THREAD_LOCAL) && !defined(QT_BOOTSTRAPPED) - if (SystemRandom::EfficientBufferFill && (end - ptr) < ThreadState::BufferCount - && uint(qt_randomdevice_control) == 0) { - thread_local ThreadState state; - qssize_t itemsAvailable = ThreadState::BufferCount - state.idx; - - // copy as much as we already have - qssize_t itemsToCopy = qMin(qssize_t(end - ptr), itemsAvailable); - memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); - ptr += itemsToCopy; - - if (ptr != end) { - // refill the buffer and try again - fill_internal(state.buffer, ThreadState::BufferCount); - state.idx = 0; - - itemsToCopy = end - ptr; - memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); - ptr = end; - } - - // erase what we copied and advance -# ifdef Q_OS_WIN - // Microsoft recommends this - SecureZeroMemory(state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); -# else - // We're quite confident the compiler will not optimize this out because - // we're writing to a thread-local buffer - memset(state.buffer + state.idx, 0, size_t(itemsToCopy) * sizeof(*ptr)); -# endif - state.idx += itemsToCopy; - } -#endif // Q_COMPILER_THREAD_LOCAL && !QT_BOOTSTRAPPED - - if (ptr != end) { - // fill directly in the user buffer - fill_internal(ptr, end - ptr); - } -} - /*! \class QRandomGenerator \inmodule QtCore diff --git a/src/corelib/global/qrandom_p.h b/src/corelib/global/qrandom_p.h index 6ac2904e1b..525a73cce4 100644 --- a/src/corelib/global/qrandom_p.h +++ b/src/corelib/global/qrandom_p.h @@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE enum QRandomGeneratorControl { - SkipMemfill = 1, SkipSystemRNG = 2, SkipHWRNG = 4, SetRandomData = 8, -- cgit v1.2.3 From af456842e13ab83cfeb44f3638b62652b201281c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Oct 2017 15:28:40 +0200 Subject: Change QRandomGenerator to have a deterministic mode Now only QRandomGenerator::system() will access the system-wide RNG, which we document to be cryptographically-safe and possibly backed by a true HWRNG. Everything else just wraps a Mersenne Twister. Change-Id: I0a103569c81b4711a649fffd14ec8cd3469425df Reviewed-by: Lars Knoll --- src/corelib/global/qrandom.cpp | 707 ++++++++++++++++++++++++++--------------- src/corelib/global/qrandom.h | 160 +++++++--- src/corelib/global/qrandom_p.h | 17 + 3 files changed, 581 insertions(+), 303 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 17f25ead86..44b807d745 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -43,10 +43,8 @@ #include "qrandom.h" #include "qrandom_p.h" #include +#include #include -#include - -#include #include @@ -86,6 +84,7 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando #undef Q_ASSERT_X #undef Q_ASSERT #define Q_ASSERT(cond) assert(cond) +#define Q_ASSERT_X(cond, x, msg) assert(cond && msg) #if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) # define NDEBUG 1 #endif @@ -122,13 +121,41 @@ static QT_FUNCTION_TARGET(RDRND) qssize_t qt_random_cpu(void *buffer, qssize_t c out: return ptr - reinterpret_cast(buffer); } +#else +static qssize_t qt_random_cpu(void *, qssize_t) +{ + return 0; +} #endif namespace { -#if QT_CONFIG(getentropy) -class SystemRandom +static QBasicMutex globalPRNGMutex; + +struct PRNGLocker +{ + const bool locked; + PRNGLocker(const QRandomGenerator *that) + : locked(that == nullptr || that == QRandomGenerator::global()) + { + if (locked) + globalPRNGMutex.lock(); + } + ~PRNGLocker() + { + if (locked) + globalPRNGMutex.unlock(); + } +}; +} + +enum { + // may be "overridden" by a member enum + FillBufferNoexcept = true +}; + +struct QRandomGenerator::SystemGenerator : public QRandomGenerator::SystemGeneratorBase { -public: +#if QT_CONFIG(getentropy) static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { // getentropy can read at most 256 bytes, so break the reading @@ -146,94 +173,94 @@ public: Q_UNUSED(ret); return count; } -}; #elif defined(Q_OS_UNIX) -class SystemRandom -{ - static QBasicAtomicInt s_fdp1; // "file descriptor plus 1" - static int openDevice(); -#ifdef Q_CC_GNU - // If it's not GCC or GCC-like, then we'll leak the file descriptor - __attribute__((destructor)) -#endif - static void closeDevice(); - SystemRandom() {} -public: - enum { EfficientBufferFill = true }; - static qssize_t fillBuffer(void *buffer, qssize_t count); -}; -QBasicAtomicInt SystemRandom::s_fdp1 = Q_BASIC_ATOMIC_INITIALIZER(0); + QBasicAtomicInt fdp1; // "file descriptor plus 1" + int openDevice() + { + int fd = fdp1.loadAcquire() - 1; + if (fd != -1) + return fd; + + fd = qt_safe_open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK); + if (fd == -1) { + // failed on both, set to -2 so we won't try again + fd = -2; + } -void SystemRandom::closeDevice() -{ - int fd = s_fdp1.loadAcquire() - 1; - if (fd >= 0) - qt_safe_close(fd); -} + int opened_fdp1; + if (fdp1.testAndSetOrdered(0, fd + 1, opened_fdp1)) + return fd; -int SystemRandom::openDevice() -{ - int fd = s_fdp1.loadAcquire() - 1; - if (fd != -1) - return fd; - - fd = qt_safe_open("/dev/urandom", O_RDONLY); - if (fd == -1) - fd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK); - if (fd == -1) { - // failed on both, set to -2 so we won't try again - fd = -2; + // failed, another thread has opened the file descriptor + if (fd >= 0) + qt_safe_close(fd); + return opened_fdp1 - 1; } - int opened_fdp1; - if (s_fdp1.testAndSetOrdered(0, fd + 1, opened_fdp1)) { - if (fd >= 0) { - static const SystemRandom closer; - Q_UNUSED(closer); - } - return fd; +#ifdef Q_CC_GNU + // If it's not GCC or GCC-like, then we'll leak the file descriptor + __attribute__((destructor)) +#endif + static void closeDevice() + { + int fd = static_cast(system()->storage.sys).fdp1.load() - 1; + if (fd >= 0) + qt_safe_close(fd); } - // failed, another thread has opened the file descriptor - if (fd >= 0) - qt_safe_close(fd); - return opened_fdp1 - 1; -} + SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {} -qssize_t SystemRandom::fillBuffer(void *buffer, qssize_t count) -{ - int fd = openDevice(); - if (Q_UNLIKELY(fd < 0)) - return 0; + qssize_t fillBuffer(void *buffer, qssize_t count) + { + int fd = openDevice(); + if (Q_UNLIKELY(fd < 0)) + return 0; - qint64 n = qt_safe_read(fd, buffer, count); - return qMax(n, 0); // ignore any errors -} -#endif // Q_OS_UNIX + qint64 n = qt_safe_read(fd, buffer, count); + return qMax(n, 0); // ignore any errors + } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) -class SystemRandom -{ -public: - static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { auto RtlGenRandom = SystemFunction036; return RtlGenRandom(buffer, ULONG(count)) ? count: 0; } -}; #elif defined(Q_OS_WINRT) -class SystemRandom -{ -public: - static qssize_t fillBuffer(void *, qssize_t) Q_DECL_NOTHROW + qssize_t fillBuffer(void *, qssize_t) Q_DECL_NOTHROW { // always use the fallback return 0; } -}; #endif // Q_OS_WINRT -} // unnamed namespace + + static SystemGenerator &self() + { + return static_cast(QRandomGenerator::system()->storage.sys); + } + void generate(quint32 *begin, quint32 *end) Q_DECL_NOEXCEPT_EXPR(FillBufferNoexcept); + + // For std::mersenne_twister_engine implementations that use something + // other than quint32 (unsigned int) to fill their buffers. + template void generate(T *begin, T *end) + { + Q_STATIC_ASSERT(sizeof(T) >= sizeof(quint32)); + if (sizeof(T) == sizeof(quint32)) { + // Microsoft Visual Studio uses unsigned long, but that's still 32-bit + generate(reinterpret_cast(begin), reinterpret_cast(end)); + } else { + // Slow path. Fix your C++ library. + std::generate(begin, end, [this]() { + quint32 datum; + generate(&datum, &datum + 1); + return datum; + }); + } + } +}; #if defined(Q_OS_WIN) static void fallback_update_seed(unsigned) {} @@ -252,6 +279,7 @@ static void fallback_update_seed(unsigned) {} static void fallback_fill(quint32 *, qssize_t) Q_DECL_NOTHROW { // no fallback necessary, getentropy cannot fail under normal circumstances + Q_UNREACHABLE(); } #elif defined(Q_OS_BSD4) static void fallback_update_seed(unsigned) {} @@ -347,26 +375,11 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW } #endif -static qssize_t fill_cpu(quint32 *buffer, qssize_t count) Q_DECL_NOTHROW -{ -#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) - if (qCpuHasFeature(RDRND) && (uint(qt_randomdevice_control) & SkipHWRNG) == 0) - return qt_random_cpu(buffer, count); -#else - Q_UNUSED(buffer); - Q_UNUSED(count); -#endif - return 0; -} - -static Q_NEVER_INLINE void fill(void *begin, void *end) - Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(nullptr, 1))) +Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, quint32 *end) + Q_DECL_NOEXCEPT_EXPR(FillBufferNoexcept) { - // Verify that the pointers are properly aligned for 32-bit - Q_ASSERT(quintptr(begin) % sizeof(quint32) == 0); - Q_ASSERT(quintptr(end) % sizeof(quint32) == 0); - quint32 *buffer = reinterpret_cast(begin); - qssize_t count = reinterpret_cast(end) - buffer; + quint32 *buffer = begin; + qssize_t count = end - begin; if (Q_UNLIKELY(uint(qt_randomdevice_control) & SetRandomData)) { uint value = uint(qt_randomdevice_control) & RandomDataMask; @@ -374,10 +387,13 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) return; } - qssize_t filled = fill_cpu(buffer, count); + qssize_t filled = 0; + if (qt_has_hwrng() && (uint(qt_randomdevice_control) & SkipHWRNG) == 0) + filled += qt_random_cpu(buffer, count); + if (filled != count && (uint(qt_randomdevice_control) & SkipSystemRNG) == 0) { qssize_t bytesFilled = - SystemRandom::fillBuffer(buffer + filled, (count - filled) * qssize_t(sizeof(*buffer))); + fillBuffer(buffer + filled, (count - filled) * qssize_t(sizeof(*buffer))); filled += bytesFilled / qssize_t(sizeof(*buffer)); } if (filled) @@ -392,85 +408,153 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) /*! \class QRandomGenerator \inmodule QtCore + \reentrant \since 5.10 \brief The QRandomGenerator class allows one to obtain random values from a - high-quality, seed-less Random Number Generator. + high-quality Random Number Generator. QRandomGenerator may be used to generate random values from a high-quality - random number generator. Unlike qrand(), QRandomGenerator does not need to be - seeded. That also means it is not possible to force it to produce a - reliable sequence, which may be needed for debugging. + random number generator. Like the C++ random engines, QRandomGenerator can + be seeded with user-provided values through the constructor. + When seeded, the sequence of numbers generated by this + class is deterministic. That is to say, given the same seed data, + QRandomGenerator will generate the same sequence of numbers. But given + different seeds, the results should be considerably different. + + QRandomGenerator::global() returns a global instance of QRandomGenerator + that Qt will ensure to be securely seeded. This object is thread-safe, may + be shared for most uses, and is always seeded from + QRandomGenerator::system() + + QRandomGenerator::system() may be used to access the system's + cryptographically-safe random generator. On Unix systems, it's equivalent + to reading from \c {/dev/urandom} or the \c {getrandom()} or \c + {getentropy()} system calls. The class can generate 32-bit or 64-bit quantities, or fill an array of those. The most common way of generating new values is to call the generate(), generate64() or fillRange() functions. One would use it as: \code - quint32 value = QRandomGenerator::generate(); + quint32 value = QRandomGenerator::global()->generate(); + \endcode + + Additionally, it provides a floating-point function generateDouble() that + returns a number in the range [0, 1) (that is, inclusive of zero and + exclusive of 1). There's also a set of convenience functions that + facilitate obtaining a random number in a bounded, integral range. + + \section1 Seeding and determinism + + QRandomGenerator may be seeded with specific seed data. When that is done, + the numbers generated by the object will always be the same, as in the + following example: + + \code + QRandomGenerator prng1(1234), prng2(1234); + Q_ASSERT(prng1.generate32() == prng2.generate32()); + Q_ASSERT(prng1.generate64() == prng2.generate64()); \endcode - Additionally, it provides a floating-point function generateDouble() that returns - a number in the range [0, 1) (that is, inclusive of zero and exclusive of - 1). There's also a set of convenience functions that facilitate obtaining a - random number in a bounded, integral range. + The seed data takes the form of one or more 32-bit words. The ideal seed + size is approximately equal to the size of the QRandomGenerator class + itself. Due to mixing of the seed data, QRandomGenerator cannot guarantee + that distinct seeds will produce different sequences. + + QRandomGenerator::global() is always seeded from + QRandomGenerator::system(), so it's not possible to make it produce + identical sequences. - \warning This class is not suitable for bulk data creation. See below for the - technical reasons. + \section1 Bulk data - \section1 Frequency and entropy exhaustion + When operating in deterministic mode, QRandomGenerator may be used for bulk + data generation. In fact, applications that do not need + cryptographically-secure or true random data are advised to use a regular + QRandomGenerator instead of QRandomGenerator::system() for their random + data needs. - QRandomGenerator does not need to be seeded and instead uses operating system - or hardware facilities to generate random numbers. On some systems and with - certain hardware, those facilities are true Random Number Generators. - However, if they are true RNGs, those facilities have finite entropy source - and thus may fail to produce any results if the entropy pool is exhausted. + For ease of use, QRandomGenerator provides a global object that can + be easily used, as in the following example: + + \code + int x = QRandomGenerator::global()->generate32(); + int y = QRandomGenerator::global()->generate32(); + int w = QRandomGenerator::global()->bounded(16384); + int h = QRandomGenerator::global()->bounded(16384); + \endcode + + \section1 System-wide random number generator + + QRandomGenerator::system() may be used to access the system-wide random + number generator, which is cryptographically-safe on all systems that Qt + runs on. This function will use hardware facilities to generate random + numbers where available. On such systems, those facilities are true Random + Number Generators. However, if they are true RNGs, those facilities have + finite entropy sources and thus may fail to produce any results if their + entropy pool is exhausted. If that happens, first the operating system then QRandomGenerator will fall back to Pseudo Random Number Generators of decreasing qualities (Qt's - fallback generator being the simplest). Therefore, QRandomGenerator should - not be used for high-frequency random number generation, lest the entropy - pool become empty. As a rule of thumb, this class should not be called upon - to generate more than a kilobyte per second of random data (note: this may - vary from system to system). + fallback generator being the simplest). Whether those generators are still + of cryptographic quality is implementation-defined. Therefore, + QRandomGenerator::system() should not be used for high-frequency random + number generation, lest the entropy pool become empty. As a rule of thumb, + this class should not be called upon to generate more than a kilobyte per + second of random data (note: this may vary from system to system). If an application needs true RNG data in bulk, it should use the operating - system facilities (such as \c{/dev/random} on Unix systems) directly and - wait for entropy to become available. If true RNG is not required, - applications should instead use a PRNG engines and can use QRandomGenerator to - seed those. + system facilities (such as \c{/dev/random} on Linux) directly and wait for + entropy to become available. If the application requires PRNG engines of + cryptographic quality but not of true randomness, + QRandomGenerator::system() may still be used (see section below). + + If neither a true RNG nor a cryptographically secure PRNG are required, + applications should instead use PRNG engines like QRandomGenerator's + deterministic mode and those from the C++ Standard Library. + QRandomGenerator::system() can be used to seed those. + + \section2 Fallback quality + + QRandomGenerator::system() uses the operating system facilities to obtain + random numbers, which attempt to collect real entropy from the surrounding + environment to produce true random numbers. However, it's possible that the + entropy pool becomes exhausted, in which case the operating system will + fall back to a pseudo-random engine for a time. Under no circumstances will + QRandomGenerator::system() block, waiting for more entropy to be collected. + + The following operating systems guarantee that the results from their + random-generation API will be of at least cryptographically-safe quality, + even if the entropy pool is exhausted: Apple OSes (Darwin), BSDs, Linux, + Windows. Barring a system installation problem (such as \c{/dev/urandom} + not being readable by the current process), QRandomGenerator::system() will + therefore have the same guarantees. + + On other operating systems, QRandomGenerator will fall back to a PRNG of + good numeric distribution, but it cannot guarantee proper seeding in all + cases. Please consult the OS documentation for more information. + + Applications that require QRandomGenerator not to fall back to + non-cryptographic quality generators are advised to check their operating + system documentation or restrict their deployment to one of the above. + + \section1 Reentrancy and thread-safety + + QRandomGenerator is reentrant, meaning that multiple threads can operate on + this class at the same time, so long as they operate on different objects. + If multiple threads need to share one PRNG sequence, external locking by a + mutex is required. + + The exceptions are the objects returned by QRandomGenerator::global() and + QRandomGenerator::system(): those objects are thread-safe and may be used + by any thread without external locking. Note that thread-safety does not + extend to copying those objects: they should always be used by reference. \section1 Standard C++ Library compatibility - QRandomGenerator is modeled after - \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}} - and may be used in almost all contexts that the Standard Library can. - QRandomGenerator attempts to use either the same engine that backs - \c{std::random_device} or a better one. Note that \c{std::random_device} is - also allowed to fail if the source entropy pool becomes exhausted, in which - case it will throw an exception. QRandomGenerator never throws, but may abort - program execution instead. - - Like the Standard Library class, QRandomGenerator can be used to seed Standard - Library deterministic random engines from \c{}, such as the - Mersenne Twister. Unlike \c{std::random_device}, QRandomGenerator also - implements the API of - \c{\l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq}{std::seed_seq}}, - allowing it to seed the deterministic engines directly. - - The following code can be used to create and seed the - implementation-defined default deterministic PRNG, then use it to fill a - block range: - - \code - QRandomGenerator rd; - std::default_random_engine rng(rd); - std::generate(block.begin(), block.end(), rng); - - // equivalent to: - for (auto &v : block) - v = rng(); - \endcode + QRandomGenerator is modeled after the requirements for random number + engines in the C++ Standard Library and may be used in almost all contexts + that the Standard Library engines can. QRandomGenerator is also compatible with the uniform distribution classes \c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as @@ -479,57 +563,101 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) [1, 2.5): \code - QRandomGenerator64 rd; std::uniform_real_distribution dist(1, 2.5); - return dist(rd); + return dist(*QRandomGenerator::global()); \endcode - Note the use of the QRandomGenerator64 class instead of QRandomGenerator to - obtain 64 bits of random data in a single call, though it is not required - to make the algorithm work (the Standard Library functions will make as - many calls as required to obtain enough bits of random data for the desired - range). - \sa QRandomGenerator64, qrand() */ /*! - \fn QRandomGenerator::QRandomGenerator() - \internal - Defaulted constructor, does nothing. + \fn QRandomGenerator::QRandomGenerator(quint32 seed) + + Initializes this QRandomGenerator object with the value \a seed as + the seed. Two objects constructed with the same seed value will + produce the same number sequence. */ /*! - \typedef QRandomGenerator::result_type + \fn QRandomGenerator::QRandomGenerator(const quint32 (&seedBuffer)[N]) + \overload - A typedef to the type that operator()() returns. That is, quint32. + Initializes this QRandomGenerator object with the values found in the + array \a seedBuffer as the seed. Two objects constructed or reseeded with + the same seed value will produce the same number sequence. + */ - \sa operator()() +/*! + \fn QRandomGenerator::QRandomGenerator(const quint32 *seedBuffer, qssize_t len) + \overload + + Initializes this QRandomGenerator object with \a len values found in + the array \a seedBuffer as the seed. Two objects constructed or reseeded + with the same seed value will produce the same number sequence. + + This constructor is equivalent to: + \code + std::seed_seq sseq(seedBuffer, seedBuffer + len); + QRandomGenerator generator(sseq); + \endcode */ /*! - \fn result_type QRandomGenerator::operator()() + \fn QRandomGenerator::QRandomGenerator(const quint32 *begin, const quin32 *end) + \overload - Generates a 32-bit random quantity and returns it. + Initializes this QRandomGenerator object with the values found in the range + from \a begin to \a end as the seed. Two objects constructed or reseeded + with the same seed value will produce the same number sequence. - \sa QRandomGenerator::generate(), QRandomGenerator::generate64() + This constructor is equivalent to: + \code + std::seed_seq sseq(begin, end); + QRandomGenerator generator(sseq); + \endcode + */ + +/*! + \fn QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) + \overload + + Initializes this QRandomGenerator object with the seed sequence \a + sseq as the seed. Two objects constructed or reseeded with the same seed + value will produce the same number sequence. */ /*! - \fn double QRandomGenerator::entropy() const + \fn QRandomGenerator::QRandomGenerator(const QRandomGenerator &other) - Returns the estimate of the entropy in the random generator source. + Creates a copy of the generator state in the \a other object. If \a other is + QRandomGenerator::system() or a copy of that, this object will also read + from the operating system random-generating facilities. In that case, the + sequences generated by the two objects will be different. - This function exists to comply with the Standard Library requirements for - \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}} - but it does not and cannot ever work. It is not possible to obtain a - reliable entropy value in a shared entropy pool in a multi-tasking system, - as other processes or threads may use that entropy. Any value non-zero - value that this function could return would be obsolete by the time the - user code reached it. + In all other cases, the new QRandomGenerator object will start at the same + position in the deterministic sequence as the \a other object was. Both + objects will generate the same sequence from this point on. - Since QRandomGenerator attempts to use a hardware Random Number Generator, - this function always returns 0.0. + For that reason, it is not adviseable to create a copy of + QRandomGenerator::global(). If one needs an exclusive deterministic + generator, consider instead creating a new object and seeding it from + QRandomGenerator::system(). + */ + +/*! + \typedef QRandomGenerator::result_type + + A typedef to the type that operator()() returns. That is, quint32. + + \sa operator()() + */ + +/*! + \fn result_type QRandomGenerator::operator()() + + Generates a 32-bit random quantity and returns it. + + \sa generate(), generate64() */ /*! @@ -537,7 +665,7 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) Returns the minimum value that QRandomGenerator may ever generate. That is, 0. - \sa max(), QRandomGenerator64::max() + \sa max(), QRandomGenerator64::min() */ /*! @@ -556,7 +684,7 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) and \a end. This function is equivalent to (and is implemented as): \code - std::generate(begin, end, []() { return generate(); }); + std::generate(begin, end, [this]() { return generate(); }); \endcode This function complies with the requirements for the function @@ -569,7 +697,7 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) quantities, one can write: \code - std::generate(begin, end, []() { return QRandomGenerator::generate64(); }); + std::generate(begin, end, []() { return QRandomGenerator::global()->generate64(); }); \endcode If the range refers to contiguous memory (such as an array or the data from @@ -647,26 +775,26 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) */ /*! - \fn qreal QRandomGenerator::bounded(qreal sup) + \fn qreal QRandomGenerator::bounded(qreal highest) Generates one random qreal in the range between 0 (inclusive) and \a - sup (exclusive). This function is equivalent to and is implemented as: + highest (exclusive). This function is equivalent to and is implemented as: \code - return generateDouble() * sup; + return generateDouble() * highest; \endcode \sa generateDouble(), bounded() */ /*! - \fn quint32 QRandomGenerator::bounded(quint32 sup) + \fn quint32 QRandomGenerator::bounded(quint32 highest) \overload Generates one random 32-bit quantity in the range between 0 (inclusive) and - \a sup (exclusive). The same result may also be obtained by using + \a highest (exclusive). The same result may also be obtained by using \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{std::uniform_int_distribution}} - with parameters 0 and \c{sup - 1}. That class can also be used to obtain + with parameters 0 and \c{highest - 1}. That class can also be used to obtain quantities larger than 32 bits. For example, to obtain a value between 0 and 255 (inclusive), one would write: @@ -685,11 +813,11 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) */ /*! - \fn quint32 QRandomGenerator::bounded(int sup) + \fn quint32 QRandomGenerator::bounded(int highest) \overload Generates one random 32-bit quantity in the range between 0 (inclusive) and - \a sup (exclusive). \a sup must not be negative. + \a highest (exclusive). \a highest must not be negative. Note that this function cannot be used to obtain values in the full 32-bit range of int. Instead, use generate() and cast to int. @@ -698,13 +826,13 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) */ /*! - \fn quint32 QRandomGenerator::bounded(quint32 min, quint32 sup) + \fn quint32 QRandomGenerator::bounded(quint32 lowest, quint32 highest) \overload - Generates one random 32-bit quantity in the range between \a min (inclusive) - and \a sup (exclusive). The same result may also be obtained by using + Generates one random 32-bit quantity in the range between \a lowest (inclusive) + and \a highest (exclusive). The same result may also be obtained by using \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{std::uniform_int_distribution}} - with parameters \a min and \c{\a sup - 1}. That class can also be used to + with parameters \a lowest and \c{\a highest - 1}. That class can also be used to obtain quantities larger than 32 bits. For example, to obtain a value between 1000 (incl.) and 2000 (excl.), one @@ -722,11 +850,11 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) */ /*! - \fn quint32 QRandomGenerator::bounded(int min, int sup) + \fn quint32 QRandomGenerator::bounded(int lowest, int highest) \overload - Generates one random 32-bit quantity in the range between \a min - (inclusive) and \a sup (exclusive), both of which may be negative. + Generates one random 32-bit quantity in the range between \a lowest + (inclusive) and \a highest (exclusive), both of which may be negative. Note that this function cannot be used to obtain values in the full 32-bit range of int. Instead, use generate() and cast to int. @@ -734,6 +862,54 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) \sa generate(), generate64(), generateDouble() */ +/*! + \fn QRandomGenerator *QRandomGenerator::system() + \threadsafe + + Returns a pointer to a shared QRandomGenerator that always uses the + facilities provided by the operating system to generate random numbers. The + system facilities are considered to be cryptographically safe on at least + the following operating systems: Apple OSes (Darwin), BSDs, Linux, Windows. + That may also be the case on other operating systems. + + They are also possibly backed by a true hardware random number generator. + For that reason, the QRandomGenerator returned by this function should not + be used for bulk data generation. Instead, use it to seed QRandomGenerator + or a random engine from the header. + + The object returned by this function is thread-safe and may be used in any + thread without locks. It may also be copied and the resulting + QRandomGenerator will also access the operating system facilities, but they + will not generate the same sequence. + + \sa global() +*/ + +/*! + \fn QRandomGenerator *QRandomGenerator::global() + \threadsafe + + Returns a pointer to a shared QRandomGenerator that was seeded using + QRandomGenerator::system(). This function should be used to create random data + without the expensive creation of a securely-seeded QRandomGenerator for a + specific use or storing the rather large QRandomGenerator object. + large QRandomGenerator object. + + For example, the following creates a random RGB color: + + \code + return QColor::fromRgb(QRandomGenerator::global()->generate()); + \endcode + + Accesses to this object are thread-safe and it may therefore be used in any + thread without locks. The object may also be copied and the sequence + produced by the copy will be the same as the shared object will produce. + Note, however, that if there are other threads accessing the global object, + those threads may obtain samples at unpredictable intervals. + + \sa system() +*/ + /*! \class QRandomGenerator64 \inmodule QtCore @@ -755,10 +931,11 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) */ /*! - \fn QRandomGenerator64::QRandomGenerator64() - \internal - Defaulted constructor, does nothing. - */ + \fn QRandomGenerator64::QRandomGenerator64(const QRandomGenerator &other) + \internal + + Creates a copy. +*/ /*! \typedef QRandomGenerator64::result_type @@ -793,80 +970,78 @@ static Q_NEVER_INLINE void fill(void *begin, void *end) \sa QRandomGenerator::generate(), QRandomGenerator::generate64() */ -/*! - \fn double QRandomGenerator64::entropy() const - - Returns the estimate of the entropy in the random generator source. - - This function exists to comply with the Standard Library requirements for - \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}} - but it does not and cannot ever work. It is not possible to obtain a - reliable entropy value in a shared entropy pool in a multi-tasking system, - as other processes or threads may use that entropy. Any value non-zero - value that this function could return would be obsolete by the time the - user code reached it. - - Since QRandomGenerator64 attempts to use a hardware Random Number Generator, - this function always returns 0.0. - */ - -/*! - \fn result_type QRandomGenerator64::min() - - Returns the minimum value that QRandomGenerator64 may ever generate. That is, 0. - - \sa max(), QRandomGenerator::max() - */ +inline QRandomGenerator::Storage::Storage() +{ + // nothing +} -/*! - \fn result_type QRandomGenerator64::max() +inline QRandomGenerator64::QRandomGenerator64(System s) + : QRandomGenerator(s) +{ +} - Returns the maximum value that QRandomGenerator64 may ever generate. That is, - \c {std::numeric_limits::max()}. +QRandomGenerator64 *QRandomGenerator64::system() +{ + static QRandomGenerator64 system(System{}); + return &system; +} - \sa min(), QRandomGenerator::max() - */ +QRandomGenerator64 *QRandomGenerator64::global() +{ + PRNGLocker lock(nullptr); + static QRandomGenerator64 global(System{}); + if (global.type == SystemRNG) { + // seed with the system CSPRNG and change the type + new (&global.storage.engine()) RandomEngine(static_cast(system()->storage.sys)); + global.type = MersenneTwister; + } -/*! - Generates one 32-bit random value and returns it. + return &global; +} - Note about casting to a signed integer: all bits returned by this function - are random, so there's a 50% chance that the most significant bit will be - set. If you wish to cast the returned value to int and keep it positive, - you should mask the sign bit off: +/// \internal +inline QRandomGenerator::QRandomGenerator(System) + : type(SystemRNG) +{ + Q_STATIC_ASSERT(sizeof(storage) >= sizeof(SystemGenerator)); + new (&storage) SystemGenerator(); +} - \code - int value = QRandomGenerator::generate() & std::numeric_limits::max(); - \endcode - \sa generate64(), generateDouble() - */ -quint32 QRandomGenerator::generate() +QRandomGenerator::QRandomGenerator(const QRandomGenerator &other) + : type(other.type) { - quint32 ret; - fill(&ret, &ret + 1); - return ret; + if (type != SystemRNG) { + PRNGLocker lock(&other); + storage.engine() = other.storage.engine(); + } } -/*! - Generates one 64-bit random value and returns it. +QRandomGenerator &QRandomGenerator::operator=(const QRandomGenerator &other) +{ + if (this != &other) { + if (Q_UNLIKELY(this == system()) || Q_UNLIKELY(this == global())) + qFatal("Attempted to overwrite a QRandomGenerator to system() or global()."); - Note about casting to a signed integer: all bits returned by this function - are random, so there's a 50% chance that the most significant bit will be - set. If you wish to cast the returned value to qint64 and keep it positive, - you should mask the sign bit off: + if ((type = other.type) != SystemRNG) { + PRNGLocker lock(&other); + storage.engine() = other.storage.engine(); + } + } + return *this; +} - \code - qint64 value = QRandomGenerator::generate64() & std::numeric_limits::max(); - \endcode +QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) Q_DECL_NOTHROW + : type(MersenneTwister) +{ + new (&storage.engine()) RandomEngine(sseq); +} - \sa generate(), generateDouble(), QRandomGenerator64 - */ -quint64 QRandomGenerator::generate64() +QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end) + : type(MersenneTwister) { - quint64 ret; - fill(&ret, &ret + 1); - return ret; + std::seed_seq s(begin, end); + new (&storage.engine()) RandomEngine(s); } /*! @@ -875,9 +1050,19 @@ quint64 QRandomGenerator::generate64() Fills the range pointed by \a buffer and \a bufferEnd with 32-bit random values. The buffer must be correctly aligned. */ -void QRandomGenerator::fillRange_helper(void *buffer, void *bufferEnd) +void QRandomGenerator::_fillRange(void *buffer, void *bufferEnd) { - fill(buffer, bufferEnd); + // Verify that the pointers are properly aligned for 32-bit + Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0); + Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0); + quint32 *begin = static_cast(buffer); + quint32 *end = static_cast(bufferEnd); + + if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control) & (UseSystemRNG|SetRandomData))) + return SystemGenerator::self().generate(begin, end); + + PRNGLocker lock(this); + std::generate(begin, end, [this]() { return storage.engine()(); }); } #if defined(Q_OS_ANDROID) && (__ANDROID_API__ < 21) diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h index 049495d4e8..e6fd4f02de 100644 --- a/src/corelib/global/qrandom.h +++ b/src/corelib/global/qrandom.h @@ -42,6 +42,7 @@ #include #include // for std::generate +#include // for std::mt19937 QT_BEGIN_NAMESPACE @@ -51,19 +52,37 @@ class QRandomGenerator template using IfValidUInt = typename std::enable_if::value && sizeof(UInt) >= sizeof(uint), bool>::type; public: - static QRandomGenerator system() { return {}; } - static QRandomGenerator global() { return {}; } - QRandomGenerator() = default; - - // ### REMOVE BEFORE 5.10 - QRandomGenerator *operator->() { return this; } - static quint32 get32() { return generate(); } - static quint64 get64() { return generate64(); } - static qreal getReal() { return generateDouble(); } - - static Q_CORE_EXPORT quint32 generate(); - static Q_CORE_EXPORT quint64 generate64(); - static double generateDouble() + QRandomGenerator(quint32 seed = 1) + : QRandomGenerator(&seed, 1) + {} + template QRandomGenerator(const quint32 (&seedBuffer)[N]) + : QRandomGenerator(seedBuffer, seedBuffer + N) + {} + QRandomGenerator(const quint32 *seedBuffer, qssize_t len) + : QRandomGenerator(seedBuffer, seedBuffer + len) + {} + Q_CORE_EXPORT QRandomGenerator(std::seed_seq &sseq) Q_DECL_NOTHROW; + Q_CORE_EXPORT QRandomGenerator(const quint32 *begin, const quint32 *end); + + // copy constructor & assignment operator (move unnecessary) + Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other); + Q_CORE_EXPORT QRandomGenerator &operator=(const QRandomGenerator &other); + + quint32 generate() + { + quint32 ret; + fillRange(&ret, 1); + return ret; + } + + quint64 generate64() + { + quint32 buf[2]; + fillRange(buf); + return buf[0] | (quint64(buf[1]) << 32); + } + + double generateDouble() { // IEEE 754 double precision has: // 1 bit sign @@ -77,87 +96,144 @@ public: return double(x) / double(limit); } - static qreal bounded(qreal sup) + double bounded(double highest) { - return generateDouble() * sup; + return generateDouble() * highest; } - static quint32 bounded(quint32 sup) + quint32 bounded(quint32 highest) { quint64 value = generate(); - value *= sup; + value *= highest; value /= (max)() + quint64(1); return quint32(value); } - static int bounded(int sup) + int bounded(int highest) { - return int(bounded(quint32(sup))); + return int(bounded(quint32(highest))); } - static quint32 bounded(quint32 min, quint32 sup) + quint32 bounded(quint32 lowest, quint32 highest) { - return bounded(sup - min) + min; + return bounded(highest - lowest) + lowest; } - static int bounded(int min, int sup) + int bounded(int lowest, int highest) { - return bounded(sup - min) + min; + return bounded(highest - lowest) + lowest; } template = true> - static void fillRange(UInt *buffer, qssize_t count) + void fillRange(UInt *buffer, qssize_t count) { - fillRange_helper(buffer, buffer + count); + _fillRange(buffer, buffer + count); } template = true> - static void fillRange(UInt (&buffer)[N]) + void fillRange(UInt (&buffer)[N]) { - fillRange_helper(buffer, buffer + N); + _fillRange(buffer, buffer + N); } // API like std::seed_seq template void generate(ForwardIterator begin, ForwardIterator end) { - auto generator = static_cast(&QRandomGenerator::generate); - std::generate(begin, end, generator); + std::generate(begin, end, [this]() { return generate(); }); } void generate(quint32 *begin, quint32 *end) { - fillRange_helper(begin, end); + _fillRange(begin, end); } - // API like std::random_device + // API like std:: random engines typedef quint32 result_type; result_type operator()() { return generate(); } - double entropy() const Q_DECL_NOTHROW { return 0.0; } static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } + static inline QRandomGenerator *system(); + static inline QRandomGenerator *global(); + +protected: + enum System {}; + QRandomGenerator(System); + private: - static Q_CORE_EXPORT void fillRange_helper(void *buffer, void *bufferEnd); + Q_CORE_EXPORT void _fillRange(void *buffer, void *bufferEnd); + + friend class QRandomGenerator64; + struct SystemGeneratorBase {}; + struct SystemGenerator; + typedef std::mt19937 RandomEngine; + + union Storage { + SystemGeneratorBase sys; +#ifdef Q_COMPILER_UNRESTRICTED_UNIONS + RandomEngine twister; + RandomEngine &engine() { return twister; } + const RandomEngine &engine() const { return twister; } +#else + std::aligned_storage::type buffer; + RandomEngine &engine() { return reinterpret_cast(buffer); } + const RandomEngine &engine() const { return reinterpret_cast(buffer); } +#endif + + Q_STATIC_ASSERT_X(std::is_trivially_destructible::value, + "std::mersenne_twister not trivially destructible as expected"); + Storage(); + }; + uint type; + Storage storage; }; -class QRandomGenerator64 +class QRandomGenerator64 : public QRandomGenerator { + QRandomGenerator64(System); public: - static QRandomGenerator64 system() { return {}; } - static QRandomGenerator64 global() { return {}; } - QRandomGenerator64() = default; - - static quint64 generate() { return QRandomGenerator::generate64(); } + // unshadow generate() overloads, since we'll override. + using QRandomGenerator::generate; + quint64 generate() { return generate64(); } - // API like std::random_device typedef quint64 result_type; - result_type operator()() { return QRandomGenerator::generate64(); } - double entropy() const Q_DECL_NOTHROW { return 0.0; } + result_type operator()() { return generate64(); } + +#ifndef Q_QDOC + QRandomGenerator64(quint32 seed = 1) + : QRandomGenerator(seed) + {} + template QRandomGenerator64(const quint32 (&seedBuffer)[N]) + : QRandomGenerator(seedBuffer) + {} + QRandomGenerator64(const quint32 *seedBuffer, qssize_t len) + : QRandomGenerator(seedBuffer, len) + {} + QRandomGenerator64(std::seed_seq &sseq) Q_DECL_NOTHROW + : QRandomGenerator(sseq) + {} + QRandomGenerator64(const quint32 *begin, const quint32 *end) + : QRandomGenerator(begin, end) + {} + QRandomGenerator64(const QRandomGenerator &other) : QRandomGenerator(other) {} + static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } + static Q_CORE_EXPORT QRandomGenerator64 *system(); + static Q_CORE_EXPORT QRandomGenerator64 *global(); +#endif // Q_QDOC }; +inline QRandomGenerator *QRandomGenerator::system() +{ + return QRandomGenerator64::system(); +} + +inline QRandomGenerator *QRandomGenerator::global() +{ + return QRandomGenerator64::global(); +} QT_END_NAMESPACE diff --git a/src/corelib/global/qrandom_p.h b/src/corelib/global/qrandom_p.h index 525a73cce4..917a91098e 100644 --- a/src/corelib/global/qrandom_p.h +++ b/src/corelib/global/qrandom_p.h @@ -52,10 +52,12 @@ // #include "qglobal_p.h" +#include QT_BEGIN_NAMESPACE enum QRandomGeneratorControl { + UseSystemRNG = 1, SkipSystemRNG = 2, SkipHWRNG = 4, SetRandomData = 8, @@ -64,6 +66,11 @@ enum QRandomGeneratorControl { RandomDataMask = 0xfffffff0 }; +enum RNGType { + SystemRNG = 0, + MersenneTwister = 1 +}; + #if defined(QT_BUILD_INTERNAL) && defined(QT_BUILD_CORE_LIB) Q_CORE_EXPORT QBasicAtomicInteger qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U); #elif defined(QT_BUILD_INTERNAL) @@ -72,6 +79,16 @@ extern Q_CORE_EXPORT QBasicAtomicInteger qt_randomdevice_control; enum { qt_randomdevice_control = 0 }; #endif +inline bool qt_has_hwrng() +{ +#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) + return qCpuHasFeature(RDRND); +#else + return false; +#endif +} + + QT_END_NAMESPACE #endif // QRANDOM_P_H -- cgit v1.2.3 From cfad4e298f4d65fe26c3a4109d19839bdfcd30c2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 23 Oct 2017 19:39:45 -0700 Subject: QRandomGenerator: add securelySeeded(), to ensure appropriate seeding Since we don't document how many bytes one needs (it's 2496), it's difficult for the caller to provide just enough data in the seed sequence. Moreover, since std::mt19937 doesn't make it easy to provide the ideal size either, we can't actually write code that operates optimally given a quint32 range either -- we only provide it via std::seed_seq, which is inefficient. However, we can do it internally by passing QRandomGenerator to the std::mersenne_twister_engine constructor, as it's designed to work. Change-Id: Icaa86fc7b54d4b368c0efffd14f0613c10998321 Reviewed-by: Lars Knoll --- src/corelib/global/qrandom.cpp | 60 +++++++++++++++++++++++++++++++++++------- src/corelib/global/qrandom.h | 7 +++++ 2 files changed, 58 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 44b807d745..2241dc7095 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -422,6 +422,9 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, QRandomGenerator will generate the same sequence of numbers. But given different seeds, the results should be considerably different. + QRandomGenerator::securelySeeded() can be used to create a QRandomGenerator + that is securely seeded with QRandomGenerator::system(), meaning that the + sequence of numbers it generates cannot be easily predicted. Additionally, QRandomGenerator::global() returns a global instance of QRandomGenerator that Qt will ensure to be securely seeded. This object is thread-safe, may be shared for most uses, and is always seeded from @@ -462,7 +465,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, itself. Due to mixing of the seed data, QRandomGenerator cannot guarantee that distinct seeds will produce different sequences. - QRandomGenerator::global() is always seeded from + QRandomGenerator::global(), like all generators created by + QRandomGenerator::securelySeeded(), is always seeded from QRandomGenerator::system(), so it's not possible to make it produce identical sequences. @@ -576,6 +580,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, Initializes this QRandomGenerator object with the value \a seed as the seed. Two objects constructed with the same seed value will produce the same number sequence. + + \sa securelySeeded() */ /*! @@ -585,6 +591,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, Initializes this QRandomGenerator object with the values found in the array \a seedBuffer as the seed. Two objects constructed or reseeded with the same seed value will produce the same number sequence. + + \sa securelySeeded() */ /*! @@ -600,6 +608,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, std::seed_seq sseq(seedBuffer, seedBuffer + len); QRandomGenerator generator(sseq); \endcode + + \sa securelySeeded() */ /*! @@ -615,6 +625,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, std::seed_seq sseq(begin, end); QRandomGenerator generator(sseq); \endcode + + \sa securelySeeded() */ /*! @@ -624,6 +636,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, Initializes this QRandomGenerator object with the seed sequence \a sseq as the seed. Two objects constructed or reseeded with the same seed value will produce the same number sequence. + + \sa securelySeeded() */ /*! @@ -640,8 +654,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, For that reason, it is not adviseable to create a copy of QRandomGenerator::global(). If one needs an exclusive deterministic - generator, consider instead creating a new object and seeding it from - QRandomGenerator::system(). + generator, consider instead using securelySeeded() to obtain a new object + that shares no relationship with the QRandomGenerator::global(). */ /*! @@ -882,7 +896,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, QRandomGenerator will also access the operating system facilities, but they will not generate the same sequence. - \sa global() + \sa securelySeeded(), global() */ /*! @@ -890,10 +904,9 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, \threadsafe Returns a pointer to a shared QRandomGenerator that was seeded using - QRandomGenerator::system(). This function should be used to create random data - without the expensive creation of a securely-seeded QRandomGenerator for a - specific use or storing the rather large QRandomGenerator object. - large QRandomGenerator object. + securelySeeded(). This function should be used to create random data + without the expensive creation of a securely-seeded QRandomGenerator + for a specific use or storing the rather large QRandomGenerator object. For example, the following creates a random RGB color: @@ -907,9 +920,28 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, Note, however, that if there are other threads accessing the global object, those threads may obtain samples at unpredictable intervals. - \sa system() + \sa securelySeeded(), system() */ +/*! + \fn QRandomGenerator QRandomGenerator::securelySeeded() + + Returns a new QRandomGenerator object that was securely seeded with + QRandomGenerator::system(). This function will obtain the ideal seed size + for the algorithm that QRandomGenerator uses and is therefore the + recommended way for creating a new QRandomGenerator object that will be + kept for some time. + + Given the amount of data required to securely seed the deterministic + engine, this function is somewhat expensive and should not be used for + short-term uses of QRandomGenerator (using it to generate fewer than 2600 + bytes of random data is effectively a waste of resources). If the use + doesn't require that much data, consider using QRandomGenerator::global() + and not storing a QRandomGenerator object instead. + + \sa global(), system() + */ + /*! \class QRandomGenerator64 \inmodule QtCore @@ -999,6 +1031,16 @@ QRandomGenerator64 *QRandomGenerator64::global() return &global; } +QRandomGenerator64 QRandomGenerator64::securelySeeded() +{ + QRandomGenerator64 result(System{}); + result.type = MersenneTwister; + + // seed with the system CSPRNG + new (&result.storage.engine()) RandomEngine(static_cast(system()->storage.sys)); + return result; +} + /// \internal inline QRandomGenerator::QRandomGenerator(System) : type(SystemRNG) diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h index e6fd4f02de..c25a0ad643 100644 --- a/src/corelib/global/qrandom.h +++ b/src/corelib/global/qrandom.h @@ -156,6 +156,7 @@ public: static inline QRandomGenerator *system(); static inline QRandomGenerator *global(); + static inline QRandomGenerator securelySeeded(); protected: enum System {}; @@ -222,6 +223,7 @@ public: static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } static Q_CORE_EXPORT QRandomGenerator64 *system(); static Q_CORE_EXPORT QRandomGenerator64 *global(); + static Q_CORE_EXPORT QRandomGenerator64 securelySeeded(); #endif // Q_QDOC }; @@ -235,6 +237,11 @@ inline QRandomGenerator *QRandomGenerator::global() return QRandomGenerator64::global(); } +QRandomGenerator QRandomGenerator::securelySeeded() +{ + return QRandomGenerator64::securelySeeded(); +} + QT_END_NAMESPACE #endif // QRANDOM_H -- cgit v1.2.3 From 08bf28de03f16e5b014b23e228dfc3cfc2ac7feb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 23 Oct 2017 19:16:34 -0700 Subject: QRandomGenerator: add more of the std Random Engine API This brings us to almost parity with the C++11 Random Engine API requirements (see chapter 26.5.1.4 [rand.req.eng]). We don't implement the templated Sseq requirements because it would require moving the implementation details to the public API. And we don't implement the code because we don't want to. Change-Id: Icaa86fc7b54d4b368c0efffd14f05ff813ebd759 Reviewed-by: Lars Knoll --- src/corelib/global/qrandom.cpp | 90 +++++++++++++++++++++++++++++++++++++----- src/corelib/global/qrandom.h | 24 +++++++++-- 2 files changed, 101 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 2241dc7095..a9596df432 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -558,7 +558,15 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, QRandomGenerator is modeled after the requirements for random number engines in the C++ Standard Library and may be used in almost all contexts - that the Standard Library engines can. + that the Standard Library engines can. Exceptions to the requirements are + the following: + + \list + \li QRandomGenerator does not support seeding from another seed + sequence-like class besides std::seed_seq itself; + \li QRandomGenerator is not comparable (but is copyable) or + streamable to \c{std::ostream} or from \c{std::istream}. + \endlist QRandomGenerator is also compatible with the uniform distribution classes \c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as @@ -575,13 +583,13 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, */ /*! - \fn QRandomGenerator::QRandomGenerator(quint32 seed) + \fn QRandomGenerator::QRandomGenerator(quint32 seedValue) - Initializes this QRandomGenerator object with the value \a seed as - the seed. Two objects constructed with the same seed value will + Initializes this QRandomGenerator object with the value \a seedValue as + the seed. Two objects constructed or reseeded with the same seed value will produce the same number sequence. - \sa securelySeeded() + \sa seed(), securelySeeded() */ /*! @@ -592,7 +600,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, array \a seedBuffer as the seed. Two objects constructed or reseeded with the same seed value will produce the same number sequence. - \sa securelySeeded() + \sa seed(), securelySeeded() */ /*! @@ -609,7 +617,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, QRandomGenerator generator(sseq); \endcode - \sa securelySeeded() + \sa seed(), securelySeeded() */ /*! @@ -626,7 +634,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, QRandomGenerator generator(sseq); \endcode - \sa securelySeeded() + \sa seed(), securelySeeded() */ /*! @@ -637,7 +645,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, sseq as the seed. Two objects constructed or reseeded with the same seed value will produce the same number sequence. - \sa securelySeeded() + \sa seed(), securelySeeded() */ /*! @@ -658,6 +666,24 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, that shares no relationship with the QRandomGenerator::global(). */ +/*! + \fn bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2) + \relates QRandomGenerator + + Returns true if the two the two engines \a rng1 and \a rng2 are at the same + state or if they are both reading from the operating system facilities, + false otherwise. +*/ + +/*! + \fn bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2) + \relates QRandomGenerator + + Returns true if the two the two engines \a rng1 and \a rng2 are at + different states or if one of them is reading from the operating system + facilities and the other is not, false otherwise. +*/ + /*! \typedef QRandomGenerator::result_type @@ -691,6 +717,31 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, \sa min(), QRandomGenerator64::max() */ +/*! + \fn void QRandomGenerator::seed(quint32 seed) + + Reseeds this object using the value \a seed as the seed. + */ + +/*! + \fn void QRandomGenerator::seed(std::seed_seq &seed) + \overload + + Reseeds this object using the seed sequence \a sseq as the seed. + */ + +/*! + \fn void QRandomGenerator::discard(unsigned long long z) + + Discards the next \a z entries from the sequence. This method is equivalent + to calling generate() \a z times and discarding the result, as in: + + \code + while (z--) + generator.generate(); + \endcode +*/ + /*! \fn void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end) @@ -1086,6 +1137,27 @@ QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end) new (&storage.engine()) RandomEngine(s); } +void QRandomGenerator::discard(unsigned long long z) +{ + if (Q_UNLIKELY(type == SystemRNG)) + return; + + PRNGLocker lock(this); + storage.engine().discard(z); +} + +bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2) +{ + if (rng1.type != rng2.type) + return false; + if (rng1.type == SystemRNG) + return true; + + // Lock global() if either is it (otherwise this locking is a no-op) + PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2); + return rng1.storage.engine() == rng2.storage.engine(); +} + /*! \internal diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h index c25a0ad643..c31c9afddb 100644 --- a/src/corelib/global/qrandom.h +++ b/src/corelib/global/qrandom.h @@ -52,8 +52,8 @@ class QRandomGenerator template using IfValidUInt = typename std::enable_if::value && sizeof(UInt) >= sizeof(uint), bool>::type; public: - QRandomGenerator(quint32 seed = 1) - : QRandomGenerator(&seed, 1) + QRandomGenerator(quint32 seedValue = 1) + : QRandomGenerator(&seedValue, 1) {} template QRandomGenerator(const quint32 (&seedBuffer)[N]) : QRandomGenerator(seedBuffer, seedBuffer + N) @@ -68,6 +68,12 @@ public: Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other); Q_CORE_EXPORT QRandomGenerator &operator=(const QRandomGenerator &other); + friend Q_CORE_EXPORT bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2); + friend bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2) + { + return !(rng1 == rng2); + } + quint32 generate() { quint32 ret; @@ -151,6 +157,9 @@ public: // API like std:: random engines typedef quint32 result_type; result_type operator()() { return generate(); } + void seed(quint32 s = 1) { *this = { s }; } + void seed(std::seed_seq &sseq) Q_DECL_NOTHROW { *this = { sseq }; } + Q_CORE_EXPORT void discard(unsigned long long z); static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } @@ -202,8 +211,8 @@ public: result_type operator()() { return generate64(); } #ifndef Q_QDOC - QRandomGenerator64(quint32 seed = 1) - : QRandomGenerator(seed) + QRandomGenerator64(quint32 seedValue = 1) + : QRandomGenerator(seedValue) {} template QRandomGenerator64(const quint32 (&seedBuffer)[N]) : QRandomGenerator(seedBuffer) @@ -219,6 +228,13 @@ public: {} QRandomGenerator64(const QRandomGenerator &other) : QRandomGenerator(other) {} + void discard(unsigned long long z) + { + Q_ASSERT_X(z * 2 > z, "QRandomGenerator64::discard", + "Overflow. Are you sure you want to skip over 9 quintillion samples?"); + QRandomGenerator::discard(z * 2); + } + static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } static Q_CORE_EXPORT QRandomGenerator64 *system(); -- cgit v1.2.3 From 86d91d2bf8e7ac7a75f88f0e4886140abc06fd4c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Oct 2017 15:58:59 -0700 Subject: QRandomGenerator: optimize the global() and system() storage We store both in a single memory structure, instead of two local statics. By construction, we also ensure that the global PRNG mutex is in a different cacheline from the global PRNG state itself. Finally, we don't store the full system QRandomGenerator, since we only need the type member from it. Change-Id: Icaa86fc7b54d4b368c0efffd14eecc48ff05ec27 Reviewed-by: Edward Welbourne --- src/corelib/global/qrandom.cpp | 192 +++++++++++++++++++++++++++++------------ src/corelib/global/qrandom.h | 14 +-- 2 files changed, 144 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index a9596df432..58458d6984 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -128,32 +128,12 @@ static qssize_t qt_random_cpu(void *, qssize_t) } #endif -namespace { -static QBasicMutex globalPRNGMutex; - -struct PRNGLocker -{ - const bool locked; - PRNGLocker(const QRandomGenerator *that) - : locked(that == nullptr || that == QRandomGenerator::global()) - { - if (locked) - globalPRNGMutex.lock(); - } - ~PRNGLocker() - { - if (locked) - globalPRNGMutex.unlock(); - } -}; -} - enum { // may be "overridden" by a member enum FillBufferNoexcept = true }; -struct QRandomGenerator::SystemGenerator : public QRandomGenerator::SystemGeneratorBase +struct QRandomGenerator::SystemGenerator { #if QT_CONFIG(getentropy) static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW @@ -175,6 +155,8 @@ struct QRandomGenerator::SystemGenerator : public QRandomGenerator::SystemGenera } #elif defined(Q_OS_UNIX) + enum { FillBufferNoexcept = false }; + QBasicAtomicInt fdp1; // "file descriptor plus 1" int openDevice() { @@ -206,12 +188,12 @@ struct QRandomGenerator::SystemGenerator : public QRandomGenerator::SystemGenera #endif static void closeDevice() { - int fd = static_cast(system()->storage.sys).fdp1.load() - 1; + int fd = self().fdp1.load() - 1; if (fd >= 0) qt_safe_close(fd); } - SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {} + Q_DECL_CONSTEXPR SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {} qssize_t fillBuffer(void *buffer, qssize_t count) { @@ -237,10 +219,7 @@ struct QRandomGenerator::SystemGenerator : public QRandomGenerator::SystemGenera } #endif // Q_OS_WINRT - static SystemGenerator &self() - { - return static_cast(QRandomGenerator::system()->storage.sys); - } + static SystemGenerator &self(); void generate(quint32 *begin, quint32 *end) Q_DECL_NOEXCEPT_EXPR(FillBufferNoexcept); // For std::mersenne_twister_engine implementations that use something @@ -405,6 +384,99 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, } } +struct QRandomGenerator::SystemAndGlobalGenerators +{ + // Construction notes: + // 1) The global PRNG state is in a different cacheline compared to the + // mutex that protects it. This avoids any false cacheline sharing of + // the state in case another thread tries to lock the mutex. It's not + // a common scenario, but since sizeof(QRandomGenerator) >= 2560, the + // overhead is actually acceptable. + // 2) We use both Q_DECL_ALIGN and std::aligned_storage<..., 64> because + // some implementations of std::aligned_storage can't align to more + // than a primitive type's alignment. + // 3) We don't store the entire system QRandomGenerator, only the space + // used by the QRandomGenerator::type member. This is fine because we + // (ab)use the common initial sequence exclusion to aliasing rules. + QBasicMutex globalPRNGMutex; + struct ShortenedSystem { uint type; } system_; + SystemGenerator sys; + Q_DECL_ALIGN(64) std::aligned_storage::type global_; + +#ifdef Q_COMPILER_CONSTEXPR + constexpr SystemAndGlobalGenerators() + : globalPRNGMutex{}, system_{0}, sys{}, global_{} + {} +#endif + + void confirmLiteral() + { +#if defined(Q_COMPILER_CONSTEXPR) && !defined(Q_CC_MSVC) + // Currently fails to compile with MSVC 2017, saying QBasicMutex is not + // a literal type. Disassembly with MSVC 2013 and 2015 shows it is + // actually a literal; MSVC 2017 has a bug relating to this, so we're + // withhold judgement for now. + + constexpr SystemAndGlobalGenerators g = {}; + Q_UNUSED(g); + Q_STATIC_ASSERT(std::is_literal_type::value); +#endif + } + + static SystemAndGlobalGenerators *self() + { + static SystemAndGlobalGenerators g; + Q_STATIC_ASSERT(sizeof(g) > sizeof(QRandomGenerator64)); + return &g; + } + + static QRandomGenerator64 *system() + { + // Though we never call the constructor, the system QRandomGenerator is + // properly initialized by the zero initialization performed in self(). + // Though QRandomGenerator is has non-vacuous initialization, we + // consider it initialized because of the common initial sequence. + return reinterpret_cast(&self()->system_); + } + + static QRandomGenerator64 *globalNoInit() + { + // This function returns the pointer to the global QRandomGenerator, + // but does not initialize it. Only call it directly if you meant to do + // a pointer comparison. + return reinterpret_cast(&self()->global_); + } + + static void securelySeed(QRandomGenerator *rng) + { + // force reconstruction, just to be pedantic + new (rng) QRandomGenerator{System{}}; + + rng->type = MersenneTwister; + new (&rng->storage.engine()) RandomEngine(self()->sys); + } + + struct PRNGLocker { + const bool locked; + PRNGLocker(const QRandomGenerator *that) + : locked(that == globalNoInit()) + { + if (locked) + self()->globalPRNGMutex.lock(); + } + ~PRNGLocker() + { + if (locked) + self()->globalPRNGMutex.unlock(); + } + }; +}; + +inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::self() +{ + return SystemAndGlobalGenerators::self()->sys; +} + /*! \class QRandomGenerator \inmodule QtCore @@ -1053,7 +1125,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, \sa QRandomGenerator::generate(), QRandomGenerator::generate64() */ -inline QRandomGenerator::Storage::Storage() +Q_DECL_CONSTEXPR QRandomGenerator::Storage::Storage() + : dummy(0) { // nothing } @@ -1065,30 +1138,33 @@ inline QRandomGenerator64::QRandomGenerator64(System s) QRandomGenerator64 *QRandomGenerator64::system() { - static QRandomGenerator64 system(System{}); - return &system; + auto self = SystemAndGlobalGenerators::system(); + Q_ASSERT(self->type == SystemRNG); + return self; } QRandomGenerator64 *QRandomGenerator64::global() { - PRNGLocker lock(nullptr); - static QRandomGenerator64 global(System{}); - if (global.type == SystemRNG) { - // seed with the system CSPRNG and change the type - new (&global.storage.engine()) RandomEngine(static_cast(system()->storage.sys)); - global.type = MersenneTwister; - } + auto self = SystemAndGlobalGenerators::globalNoInit(); - return &global; + // Yes, this is a double-checked lock. + // We can return even if the type is not completely initialized yet: + // any thread trying to actually use the contents of the random engine + // will necessarily wait on the lock. + if (Q_LIKELY(self->type != SystemRNG)) + return self; + + SystemAndGlobalGenerators::PRNGLocker locker(self); + if (self->type == SystemRNG) + SystemAndGlobalGenerators::securelySeed(self); + + return self; } QRandomGenerator64 QRandomGenerator64::securelySeeded() { QRandomGenerator64 result(System{}); - result.type = MersenneTwister; - - // seed with the system CSPRNG - new (&result.storage.engine()) RandomEngine(static_cast(system()->storage.sys)); + SystemAndGlobalGenerators::securelySeed(&result); return result; } @@ -1096,30 +1172,29 @@ QRandomGenerator64 QRandomGenerator64::securelySeeded() inline QRandomGenerator::QRandomGenerator(System) : type(SystemRNG) { - Q_STATIC_ASSERT(sizeof(storage) >= sizeof(SystemGenerator)); - new (&storage) SystemGenerator(); + // don't touch storage } - QRandomGenerator::QRandomGenerator(const QRandomGenerator &other) : type(other.type) { + Q_ASSERT(this != system()); + Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit()); + if (type != SystemRNG) { - PRNGLocker lock(&other); + SystemAndGlobalGenerators::PRNGLocker lock(&other); storage.engine() = other.storage.engine(); } } QRandomGenerator &QRandomGenerator::operator=(const QRandomGenerator &other) { - if (this != &other) { - if (Q_UNLIKELY(this == system()) || Q_UNLIKELY(this == global())) - qFatal("Attempted to overwrite a QRandomGenerator to system() or global()."); + if (Q_UNLIKELY(this == system()) || Q_UNLIKELY(this == SystemAndGlobalGenerators::globalNoInit())) + qFatal("Attempted to overwrite a QRandomGenerator to system() or global()."); - if ((type = other.type) != SystemRNG) { - PRNGLocker lock(&other); - storage.engine() = other.storage.engine(); - } + if ((type = other.type) != SystemRNG) { + SystemAndGlobalGenerators::PRNGLocker lock(&other); + storage.engine() = other.storage.engine(); } return *this; } @@ -1127,12 +1202,18 @@ QRandomGenerator &QRandomGenerator::operator=(const QRandomGenerator &other) QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) Q_DECL_NOTHROW : type(MersenneTwister) { + Q_ASSERT(this != system()); + Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit()); + new (&storage.engine()) RandomEngine(sseq); } QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end) : type(MersenneTwister) { + Q_ASSERT(this != system()); + Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit()); + std::seed_seq s(begin, end); new (&storage.engine()) RandomEngine(s); } @@ -1142,7 +1223,7 @@ void QRandomGenerator::discard(unsigned long long z) if (Q_UNLIKELY(type == SystemRNG)) return; - PRNGLocker lock(this); + SystemAndGlobalGenerators::PRNGLocker lock(this); storage.engine().discard(z); } @@ -1154,6 +1235,7 @@ bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2) return true; // Lock global() if either is it (otherwise this locking is a no-op) + using PRNGLocker = QRandomGenerator::SystemAndGlobalGenerators::PRNGLocker; PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2); return rng1.storage.engine() == rng2.storage.engine(); } @@ -1175,7 +1257,7 @@ void QRandomGenerator::_fillRange(void *buffer, void *bufferEnd) if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control) & (UseSystemRNG|SetRandomData))) return SystemGenerator::self().generate(begin, end); - PRNGLocker lock(this); + SystemAndGlobalGenerators::PRNGLocker lock(this); std::generate(begin, end, [this]() { return storage.engine()(); }); } diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h index c31c9afddb..bde64646a4 100644 --- a/src/corelib/global/qrandom.h +++ b/src/corelib/global/qrandom.h @@ -163,8 +163,8 @@ public: static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } - static inline QRandomGenerator *system(); - static inline QRandomGenerator *global(); + static inline Q_DECL_CONST_FUNCTION QRandomGenerator *system(); + static inline Q_DECL_CONST_FUNCTION QRandomGenerator *global(); static inline QRandomGenerator securelySeeded(); protected: @@ -175,12 +175,12 @@ private: Q_CORE_EXPORT void _fillRange(void *buffer, void *bufferEnd); friend class QRandomGenerator64; - struct SystemGeneratorBase {}; struct SystemGenerator; + struct SystemAndGlobalGenerators; typedef std::mt19937 RandomEngine; union Storage { - SystemGeneratorBase sys; + uint dummy; #ifdef Q_COMPILER_UNRESTRICTED_UNIONS RandomEngine twister; RandomEngine &engine() { return twister; } @@ -193,7 +193,7 @@ private: Q_STATIC_ASSERT_X(std::is_trivially_destructible::value, "std::mersenne_twister not trivially destructible as expected"); - Storage(); + Q_DECL_CONSTEXPR Storage(); }; uint type; Storage storage; @@ -237,8 +237,8 @@ public: static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits::min)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits::max)(); } - static Q_CORE_EXPORT QRandomGenerator64 *system(); - static Q_CORE_EXPORT QRandomGenerator64 *global(); + static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system(); + static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global(); static Q_CORE_EXPORT QRandomGenerator64 securelySeeded(); #endif // Q_QDOC }; -- cgit v1.2.3 From 25b18fb241315ed314b6b67f4b97028e2a1e484a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 2 Nov 2017 17:46:35 +0100 Subject: Document interaction of style name and other style properties Setting style name to "Regular" and then setting bold to true, results in platform depending behavior, and should be avoided. Also removes comment about style name not working on Windows, it has been working since 5.8.0. Task-number: QTBUG-63792 Change-Id: Ie5be7215a673f5751dbeb6512df8ec7bfaef4d0a Reviewed-by: Leena Miettinen Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfont.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 7f3ed3adaa..806ede88e2 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -727,11 +727,9 @@ void QFont::setFamily(const QString &family) /*! \since 4.8 - Returns the requested font style name, it will be used to match the + Returns the requested font style name. This can be used to match the font with irregular styles (that can't be normalized in other style - properties). It depends on system font support, thus only works for - \macos and X11 so far. On Windows irregular styles will be added - as separate font families so there is no need for this. + properties). \sa setFamily(), setStyle() */ @@ -744,7 +742,12 @@ QString QFont::styleName() const \since 4.8 Sets the style name of the font to \a styleName. When set, other style properties - like \l style() and \l weight() will be ignored for font matching. + like \l style() and \l weight() will be ignored for font matching, though they may be + simulated afterwards if supported by the platform's font engine. + + Due to the lower quality of artificially simulated styles, and the lack of full cross + platform support, it is not recommended to use matching by style name together with + matching by style properties \sa styleName() */ @@ -985,6 +988,10 @@ int QFont::pixelSize() const Sets the style() of the font to QFont::StyleItalic if \a enable is true; otherwise the style is set to QFont::StyleNormal. + \note If styleName() is set, this value may be ignored, or if supported + on the platform, the font may be rendered tilted instead of picking a + designed italic font-variant. + \sa italic(), QFontInfo */ @@ -1050,6 +1057,8 @@ int QFont::weight() const Sets the weight of the font to \a weight, using the scale defined by \l QFont::Weight enumeration. + \note If styleName() is set, this value may be ignored for font selection. + \sa weight(), QFontInfo */ void QFont::setWeight(int weight) @@ -1083,6 +1092,9 @@ void QFont::setWeight(int weight) For finer boldness control use setWeight(). + \note If styleName() is set, this value may be ignored, or if supported + on the platform, the font artificially embolded. + \sa bold(), setWeight() */ -- cgit v1.2.3 From 1a05a7149358a5b5fb11b1f87a85760cc182a726 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 12 Nov 2017 14:15:28 -0800 Subject: Fix QBasicMutex default constructor not constexpr Commit 02dc39fa8ee6fd9945728e12208a9e313ac4dd4b added the constructor for the bootstrapped mode. For the regular mode, we hadn't needed, since the {} syntax guaranteed initialization for us. Turns out there's at least one compiler that doesn't think it was enough (GCC for QNX 7). Task-number: QTBUG-64451 Change-Id: Ic632b4163d784b83951cfffd14f6766b4cb4eb64 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Liang Qi --- src/corelib/thread/qmutex.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 607cc13a2f..3d24379fa9 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -67,6 +67,12 @@ class QMutexData; class Q_CORE_EXPORT QBasicMutex { public: +#ifdef Q_COMPILER_CONSTEXPR + constexpr QBasicMutex() + : d_ptr(nullptr) + {} +#endif + // BasicLockable concept inline void lock() QT_MUTEX_LOCK_NOEXCEPT { if (!fastTryLock()) -- cgit v1.2.3 From c84f7554894cef0cbeeba8a61f441286e190a797 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 13 Nov 2017 11:28:41 +0100 Subject: Offscreen QPA: Use fusion style always MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent it from crashing when naively using it for example on Windows, which defaults to the Windows Vista style operating on native window handles. Change-Id: I7b1dfb00a6b6860d0f0a134653ce1142b45959ec Reviewed-by: Sami Nurmenniemi Reviewed-by: Gatis Paeglis Reviewed-by: Morten Johan Sørvig --- .../platforms/offscreen/qoffscreenintegration.cpp | 32 ++++++++++++++++++++++ .../platforms/offscreen/qoffscreenintegration.h | 3 ++ 2 files changed, 35 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 3eb8675d77..75bb786b28 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include @@ -167,6 +168,37 @@ QAbstractEventDispatcher *QOffscreenIntegration::createEventDispatcher() const #endif } +static QString themeName() { return QStringLiteral("offscreen"); } + +QStringList QOffscreenIntegration::themeNames() const +{ + return QStringList(themeName()); +} + +// Restrict the styles to "fusion" to prevent native styles requiring native +// window handles (eg Windows Vista style) from being used. +class OffscreenTheme : public QPlatformTheme +{ +public: + OffscreenTheme() {} + + QVariant themeHint(ThemeHint h) const override + { + switch (h) { + case StyleNames: + return QVariant(QStringList(QStringLiteral("fusion"))); + default: + break; + } + return QPlatformTheme::themeHint(h); + } +}; + +QPlatformTheme *QOffscreenIntegration::createPlatformTheme(const QString &name) const +{ + return name == themeName() ? new OffscreenTheme() : nullptr; +} + QPlatformFontDatabase *QOffscreenIntegration::fontDatabase() const { return m_fontDatabase.data(); diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h index 569ec8fc28..f72587d11a 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h @@ -69,6 +69,9 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; + QStringList themeNames() const; + QPlatformTheme *createPlatformTheme(const QString &name) const; + static QOffscreenIntegration *createOffscreenIntegration(); private: -- cgit v1.2.3 From a95936f37695706144ba6ca050c3493af88d7d34 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 12 Nov 2017 15:49:44 -0800 Subject: QSemaphoreReleaser: Move private members to the usual position Change-Id: Ic632b4163d784b83951cfffd14f67b902d096d8b Reviewed-by: Edward Welbourne Reviewed-by: hjk --- src/corelib/thread/qsemaphore.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h index a92740c8ce..9de23173e8 100644 --- a/src/corelib/thread/qsemaphore.h +++ b/src/corelib/thread/qsemaphore.h @@ -71,8 +71,6 @@ private: class QSemaphoreReleaser { - QSemaphore *m_sem = nullptr; - int m_n; public: QSemaphoreReleaser() = default; explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW @@ -106,6 +104,10 @@ public: m_sem = nullptr; return old; } + +private: + QSemaphore *m_sem = nullptr; + int m_n; }; #endif // QT_NO_THREAD -- cgit v1.2.3 From 2884c652b5b2d186eb1c43fd8ecb82df83a581c9 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 14 Nov 2017 11:17:40 +0100 Subject: A brute-force solution to get QRandomGenerator build on Integrity Task-number: QTBUG-64451 Change-Id: Ife11c3448f54609ba6e85a269a3b5376c43a075f Reviewed-by: Thiago Macieira --- src/corelib/global/qrandom.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 58458d6984..72ac8d332b 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -411,11 +411,12 @@ struct QRandomGenerator::SystemAndGlobalGenerators void confirmLiteral() { -#if defined(Q_COMPILER_CONSTEXPR) && !defined(Q_CC_MSVC) +#if defined(Q_COMPILER_CONSTEXPR) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY) // Currently fails to compile with MSVC 2017, saying QBasicMutex is not // a literal type. Disassembly with MSVC 2013 and 2015 shows it is // actually a literal; MSVC 2017 has a bug relating to this, so we're - // withhold judgement for now. + // withhold judgement for now. Integrity's compiler is unable to + // guarantee g's alignment for some reason. constexpr SystemAndGlobalGenerators g = {}; Q_UNUSED(g); -- cgit v1.2.3 From 3dab19ffed61a69166045d6e90e1e114d81f85a8 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 13 Nov 2017 13:03:36 +0100 Subject: OCI: Match the constraints on the index_name column When looking for the primary index, it is possible that the constraint_name in the all_ind_columns table does not match that of the index_name. Whereas the index_name will match in this case, so the query should set the where clause on the index_name in both tables. Task-number: QTBUG-64427 Change-Id: I1bf1fb580e620b9f75f2fde1ecf408842e377365 Reviewed-by: Jesus Fernandez --- src/plugins/sqldrivers/oci/qsql_oci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp index a4793351de..9ce2fc1b55 100644 --- a/src/plugins/sqldrivers/oci/qsql_oci.cpp +++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp @@ -2603,7 +2603,7 @@ QSqlIndex QOCIDriver::primaryIndex(const QString& tablename) const QString stmt(QLatin1String("select b.column_name, b.index_name, a.table_name, a.owner " "from all_constraints a, all_ind_columns b " "where a.constraint_type='P' " - "and b.index_name = a.constraint_name " + "and b.index_name = a.index_name " "and b.index_owner = a.owner")); bool buildIndex = false; -- cgit v1.2.3 From 7465329fe18315d50c4e6325cfd7c9fc1e203812 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 25 Oct 2017 13:24:49 +0200 Subject: QAbstractButton: don't clear 'pressed' flag unless left button is released As it stood, we would set 'pressed' to false regardless of which button that was released. This would end up wrong if pressing the left button, and at the same time, did a click with the right button. This would clear the flag prematurely, and cause a release signal not to be emitted when later releasing the left button. tst_QAbstractButton: adding autotest Adding tests to simulate the bug report's cases: 1) left press button 2) click right/middle key 3) move mouse out of button's boundary 4) test if the released() signal triggered properly Taks-number: QTBUG-53244 Change-Id: Ifc0d5f52a917ac9cd2df5e86c0475abcda47e425 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qabstractbutton.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index dbd94e890d..5854472ff0 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -991,13 +991,14 @@ void QAbstractButton::mousePressEvent(QMouseEvent *e) void QAbstractButton::mouseReleaseEvent(QMouseEvent *e) { Q_D(QAbstractButton); - d->pressed = false; if (e->button() != Qt::LeftButton) { e->ignore(); return; } + d->pressed = false; + if (!d->down) { // refresh is required by QMacStyle to resume the default button animation d->refresh(); -- cgit v1.2.3 From 7416fc5e80446ab25b44803f9f1858d9822e6be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 8 Nov 2017 01:02:28 +0100 Subject: Cocoa: Set NSImage (point) size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when converting from QPixmap. This will make the image display correctly when used by native API. Task-number: QTBUG-60769 Change-Id: Iec3160affbe2902d34a219b6816f503dc2f56f74 Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qcoregraphics.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index a234a12bf0..e1601d87dc 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -110,6 +110,7 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm) QImage image = pm.toImage(); CGImageRef cgImage = qt_mac_toCGImage(image); NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); + nsImage.size = (pm.size() / pm.devicePixelRatioF()).toCGSize(); CGImageRelease(cgImage); return nsImage; } -- cgit v1.2.3 From c8a5f331c8fdbf243ccb467f7bc3c9f62bd47c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sun, 12 Nov 2017 18:54:04 +0100 Subject: QMenu: Update menu action sizes if popup is (not)caused from menu bar Menu width differs if it contains key shortcuts or not. Amends 6634c424f8ca0e3aed2898507d5f9f4b774c4602 Task-number: QTBUG-49435 Task-number: QTBUG-61181 Task-number: QTBUG-64449 Change-Id: I8c479af550128069ca91dd089dfc7bd8c24c66ba Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qmenu.cpp | 6 ++++++ src/widgets/widgets/qmenu_p.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index ded218de73..463254efa9 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2339,6 +2339,12 @@ void QMenu::popup(const QPoint &p, QAction *atAction) d->updateLayoutDirection(); d->adjustMenuScreen(p); + const bool contextMenu = d->isContextMenu(); + if (d->lastContextMenu != contextMenu) { + d->itemsDirty = true; + d->lastContextMenu = contextMenu; + } + #if QT_CONFIG(menubar) // if this menu is part of a chain attached to a QMenuBar, set the // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index bdf576b980..a81d8ffafb 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -272,6 +272,7 @@ public: QMenuPrivate() : itemsDirty(false), hasCheckableItems(false), + lastContextMenu(false), collapsibleSeparators(true), toolTipsVisible(false), delayedPopupGuard(false), @@ -464,6 +465,7 @@ public: mutable bool itemsDirty : 1; mutable bool hasCheckableItems : 1; + bool lastContextMenu : 1; bool collapsibleSeparators : 1; bool toolTipsVisible : 1; bool delayedPopupGuard : 1; -- cgit v1.2.3 From 26986276531b7f0a3f950d4b3960d5302010d204 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 19 Oct 2017 15:35:25 +0700 Subject: QMenu: Refactor insertion of action in QPA menu First, remove a bit of code duplication around the creation of the platform menu item. Then, we move copyActionToPlatformItem() inside QMenuPrivate to get rid of one parameter. Change-Id: I5a33103566367f2313930479844365e79773d82f Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qmenu.cpp | 108 +++++++++++++++++++++--------------------- src/widgets/widgets/qmenu_p.h | 3 ++ 2 files changed, 57 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 463254efa9..c5b912e35b 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -234,9 +234,6 @@ void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu) } } -// forward declare function -static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu); - void QMenuPrivate::syncPlatformMenu() { Q_Q(QMenu); @@ -246,19 +243,64 @@ void QMenuPrivate::syncPlatformMenu() QPlatformMenuItem *beforeItem = Q_NULLPTR; const QList actions = q->actions(); for (QList::const_reverse_iterator it = actions.rbegin(), end = actions.rend(); it != end; ++it) { - QPlatformMenuItem *menuItem = platformMenu->createMenuItem(); - QAction *action = *it; - menuItem->setTag(reinterpret_cast(action)); - QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection); - QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection); - copyActionToPlatformItem(action, menuItem, platformMenu.data()); - platformMenu->insertMenuItem(menuItem, beforeItem); + QPlatformMenuItem *menuItem = insertActionInPlatformMenu(*it, beforeItem); beforeItem = menuItem; } platformMenu->syncSeparatorsCollapsible(collapsibleSeparators); platformMenu->setEnabled(q->isEnabled()); } +void QMenuPrivate::copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item) +{ + item->setText(action->text()); + item->setIsSeparator(action->isSeparator()); + if (action->isIconVisibleInMenu()) { + item->setIcon(action->icon()); + if (QWidget *w = action->parentWidget()) { + QStyleOption opt; + opt.init(w); + item->setIconSize(w->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, w)); + } else { + QStyleOption opt; + item->setIconSize(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, 0)); + } + } else { + item->setIcon(QIcon()); + } + item->setVisible(action->isVisible()); +#if QT_CONFIG(shortcut) + item->setShortcut(action->shortcut()); +#endif + item->setCheckable(action->isCheckable()); + item->setChecked(action->isChecked()); + item->setHasExclusiveGroup(action->actionGroup() && action->actionGroup()->isExclusive()); + item->setFont(action->font()); + item->setRole((QPlatformMenuItem::MenuRole) action->menuRole()); + item->setEnabled(action->isEnabled()); + + if (action->menu()) { + if (!action->menu()->platformMenu()) + action->menu()->setPlatformMenu(platformMenu->createSubMenu()); + item->setMenu(action->menu()->platformMenu()); + } else { + item->setMenu(0); + } +} + +QPlatformMenuItem * QMenuPrivate::insertActionInPlatformMenu(const QAction *action, QPlatformMenuItem *beforeItem) +{ + QPlatformMenuItem *menuItem = platformMenu->createMenuItem(); + Q_ASSERT(menuItem); + + menuItem->setTag(reinterpret_cast(action)); + QObject::connect(menuItem, &QPlatformMenuItem::activated, action, &QAction::trigger, Qt::QueuedConnection); + QObject::connect(menuItem, &QPlatformMenuItem::hovered, action, &QAction::hovered, Qt::QueuedConnection); + copyActionToPlatformItem(action, menuItem); + platformMenu->insertMenuItem(menuItem, beforeItem); + + return menuItem; +} + int QMenuPrivate::scrollerHeight() const { Q_Q(const QMenu); @@ -3483,43 +3525,6 @@ QMenu::timerEvent(QTimerEvent *e) } } -static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu) -{ - item->setText(action->text()); - item->setIsSeparator(action->isSeparator()); - if (action->isIconVisibleInMenu()) { - item->setIcon(action->icon()); - if (QWidget *w = action->parentWidget()) { - QStyleOption opt; - opt.init(w); - item->setIconSize(w->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, w)); - } else { - QStyleOption opt; - item->setIconSize(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, 0)); - } - } else { - item->setIcon(QIcon()); - } - item->setVisible(action->isVisible()); -#ifndef QT_NO_SHORTCUT - item->setShortcut(action->shortcut()); -#endif - item->setCheckable(action->isCheckable()); - item->setChecked(action->isChecked()); - item->setHasExclusiveGroup(action->actionGroup() && action->actionGroup()->isExclusive()); - item->setFont(action->font()); - item->setRole((QPlatformMenuItem::MenuRole) action->menuRole()); - item->setEnabled(action->isEnabled()); - - if (action->menu()) { - if (!action->menu()->platformMenu()) - action->menu()->setPlatformMenu(itemsMenu->createSubMenu()); - item->setMenu(action->menu()->platformMenu()); - } else { - item->setMenu(0); - } -} - /*! \reimp */ @@ -3573,15 +3578,10 @@ void QMenu::actionEvent(QActionEvent *e) if (!d->platformMenu.isNull()) { if (e->type() == QEvent::ActionAdded) { - QPlatformMenuItem *menuItem = d->platformMenu->createMenuItem(); - menuItem->setTag(reinterpret_cast(e->action())); - QObject::connect(menuItem, SIGNAL(activated()), e->action(), SLOT(trigger())); - QObject::connect(menuItem, SIGNAL(hovered()), e->action(), SIGNAL(hovered())); - copyActionToPlatformItem(e->action(), menuItem, d->platformMenu); QPlatformMenuItem *beforeItem = e->before() ? d->platformMenu->menuItemForTag(reinterpret_cast(e->before())) : nullptr; - d->platformMenu->insertMenuItem(menuItem, beforeItem); + d->insertActionInPlatformMenu(e->action(), beforeItem); } else if (e->type() == QEvent::ActionRemoved) { QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast(e->action())); d->platformMenu->removeMenuItem(menuItem); @@ -3589,7 +3589,7 @@ void QMenu::actionEvent(QActionEvent *e) } else if (e->type() == QEvent::ActionChanged) { QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast(e->action())); if (menuItem) { - copyActionToPlatformItem(e->action(), menuItem, d->platformMenu); + d->copyActionToPlatformItem(e->action(), menuItem); d->platformMenu->syncMenuItem(menuItem); } } diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index a81d8ffafb..ce5134958e 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -295,6 +295,9 @@ public: QPlatformMenu *createPlatformMenu(); void setPlatformMenu(QPlatformMenu *menu); void syncPlatformMenu(); + void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item); + QPlatformMenuItem *insertActionInPlatformMenu(const QAction *action, QPlatformMenuItem *beforeItem); + #ifdef Q_OS_OSX void moveWidgetToPlatformItem(QWidget *w, QPlatformMenuItem* item); #endif -- cgit v1.2.3 From d7dce54ba0c018c4db92a291d322167dcf308d75 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 7 Nov 2017 11:35:46 +0700 Subject: QMacStyle: Rename Cocoa controls enum names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For easier sorting and grouping by actual Cocoa NSControl class. We also shorten the names and move the types inside QMacStylePrivate. Change-Id: Iac093fd359da66abd263aca841b870ea84337f50 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 131 +++++++++++++++-------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 56 ++++++------ 2 files changed, 99 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index b24ecee102..9c5ede6d47 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1849,36 +1849,36 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) return tds; } -static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind) + QMacStylePrivate::CocoaControl QMacStylePrivate::cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind) { - QCocoaWidget w; + CocoaControl w; switch (kind) { case kThemePopupButton: case kThemePopupButtonSmall: case kThemePopupButtonMini: - w.first = QCocoaPopupButton; + w.first = Button_PopupButton; break; case kThemeComboBox: - w.first = QCocoaComboBox; + w.first = ComboBox; break; case kThemeArrowButton: - w.first = QCocoaDisclosureButton; + w.first = Button_Disclosure; break; case kThemeCheckBox: case kThemeCheckBoxSmall: case kThemeCheckBoxMini: - w.first = QCocoaCheckBox; + w.first = Button_CheckBox; break; case kThemeRadioButton: case kThemeRadioButtonSmall: case kThemeRadioButtonMini: - w.first = QCocoaRadioButton; + w.first = Button_RadioButton; break; case kThemePushButton: case kThemePushButtonSmall: case kThemePushButtonMini: - w.first = QCocoaPushButton; + w.first = Button_PushButton; break; default: break; @@ -1914,13 +1914,13 @@ static NSButton *makeButton(NSButtonType type, NSBezelStyle style) return b; } -NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const +NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const { NSView *bv = cocoaControls.value(widget, nil); if (!bv) { switch (widget.first) { - case QCocoaBox: { + case Box: { NSBox *bc = [[NSBox alloc] init]; bc.title = @""; bc.titlePosition = NSNoTitle; @@ -1929,48 +1929,48 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const bv = bc; break; } - case QCocoaCheckBox: + case Button_CheckBox: bv = makeButton(NSSwitchButton, NSRegularSquareBezelStyle); break; - case QCocoaDisclosureButton: + case Button_Disclosure: bv = makeButton(NSOnOffButton, NSDisclosureBezelStyle); break; - case QCocoaPopupButton: - case QCocoaPullDownButton: { + case Button_PopupButton: + case Button_PullDown: { NSPopUpButton *bc = [[NSPopUpButton alloc] init]; bc.title = @""; - if (widget.first == QCocoaPullDownButton) + if (widget.first == Button_PullDown) bc.pullsDown = YES; bv = bc; break; } - case QCocoaPushButton: + case Button_PushButton: bv = makeButton(NSMomentaryLightButton, NSRoundedBezelStyle); break; - case QCocoaRadioButton: + case Button_RadioButton: bv = makeButton(NSRadioButton, NSRegularSquareBezelStyle); break; - case QCocoaComboBox: + case ComboBox: bv = [[NSComboBox alloc] init]; break; - case QCocoaProgressIndicator: + case ProgressIndicator_Determinate: bv = [[NSProgressIndicator alloc] init]; break; - case QCocoaIndeterminateProgressIndicator: + case ProgressIndicator_Indeterminate: bv = [[QIndeterminateProgressIndicator alloc] init]; break; - case QCocoaHorizontalScroller: + case Scroller_Horizontal: bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; break; - case QCocoaVerticalScroller: + case Scroller_Vertical: // Cocoa sets the orientation from the view's frame // at construction time, and it cannot be changed later. bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; break; - case QCocoaHorizontalSlider: + case Slider_Horizontal: bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; break; - case QCocoaVerticalSlider: + case Slider_Vertical: // Cocoa sets the orientation from the view's frame // at construction time, and it cannot be changed later. bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; @@ -1991,10 +1991,10 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const default: break; } - } else if (widget.first == QCocoaProgressIndicator || - widget.first == QCocoaIndeterminateProgressIndicator) { + } else if (widget.first == ProgressIndicator_Determinate || + widget.first == ProgressIndicator_Indeterminate) { auto *pi = static_cast(bv); - pi.indeterminate = (widget.first == QCocoaIndeterminateProgressIndicator); + pi.indeterminate = (widget.first == ProgressIndicator_Indeterminate); switch (widget.second) { case QStyleHelper::SizeSmall: pi.controlSize = NSSmallControlSize; @@ -2013,15 +2013,15 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const return bv; } -NSCell *QMacStylePrivate::cocoaCell(QCocoaWidget widget) const +NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const { NSCell *cell = cocoaCells[widget]; if (!cell) { switch (widget.first) { - case QCocoaStepper: + case Stepper: cell = [[NSStepperCell alloc] init]; break; - case QCocoaDisclosureButton: { + case Button_Disclosure: { NSButtonCell *bc = [[NSButtonCell alloc] init]; bc.buttonType = NSOnOffButton; bc.bezelStyle = NSDisclosureBezelStyle; @@ -2049,31 +2049,31 @@ NSCell *QMacStylePrivate::cocoaCell(QCocoaWidget widget) const return cell; } -void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, QCocoaDrawRectBlock drawRectBlock) const +void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, DrawRectBlock drawRectBlock) const { QPoint offset; - if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeLarge)) + if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeLarge)) offset.setY(2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeSmall)) + else if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeSmall)) offset = QPoint(-1, 2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeMini)) + else if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeMini)) offset.setY(2); - else if (widget == QCocoaWidget(QCocoaPopupButton, QStyleHelper::SizeSmall) - || widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeLarge)) + else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall) + || widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeLarge)) offset.setY(1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeSmall)) + else if (widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeSmall)) offset.setX(-1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeMini)) + else if (widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeMini)) offset = QPoint(7, 5); - else if (widget == QCocoaWidget(QCocoaPopupButton, QStyleHelper::SizeMini)) + else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeMini)) offset = QPoint(2, -1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeLarge)) + else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeLarge)) offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeSmall)) + else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeSmall)) offset = QPoint(2, 1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeMini)) + else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeMini)) offset = QPoint(5, 0); - else if (widget == QCocoaWidget(QCocoaComboBox, QStyleHelper::SizeLarge)) + else if (widget == CocoaControl(ComboBox, QStyleHelper::SizeLarge)) offset = QPoint(3, 0); QMacCGContext ctx(p); @@ -2162,7 +2162,7 @@ void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonD if (!combo && !button && bdi->value == kThemeButtonOff) { pm = activePixmap; } else if ((combo && !editableCombo) || button) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi->kind); + CocoaControl cw = cocoaControlFromHIThemeButtonKind(bdi->kind); NSButton *bc = (NSButton *)cocoaControl(cw); [bc highlight:pressed]; bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; @@ -3211,7 +3211,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai if (groupBox->features & QStyleOptionFrame::Flat) { QCommonStyle::drawPrimitive(pe, groupBox, p, w); } else { - const auto cw = QCocoaWidget(QCocoaBox, QStyleHelper::SizeDefault); + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeDefault); auto *box = static_cast(d->cocoaControl(cw)); d->drawNSViewInRect(cw, box, groupBox->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); @@ -3397,7 +3397,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai case PE_IndicatorBranch: { if (!(opt->state & State_Children)) break; - NSButtonCell *triangleCell = static_cast(d->cocoaCell(QCocoaWidget(QCocoaDisclosureButton, QStyleHelper::SizeLarge))); + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge); + NSButtonCell *triangleCell = static_cast(d->cocoaCell(cw)); [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; @@ -3884,8 +3885,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } if (hasMenu && bdi.kind != kThemeBevelButton) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); - cw.first = QCocoaPullDownButton; + auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); + cw.first = QMacStylePrivate::Button_PullDown; NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); [pdb highlight:(bdi.state == kThemeStatePressed)]; pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; @@ -4451,7 +4452,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject)); QIndeterminateProgressIndicator *ipi = nil; if (isIndeterminate || animation) - ipi = static_cast(d->cocoaControl({ QCocoaIndeterminateProgressIndicator, aquaSize })); + ipi = static_cast(d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize })); if (isIndeterminate) { // QIndeterminateProgressIndicator derives from NSProgressIndicator. We use a single // instance that we start animating as soon as one of the progress bars is indeterminate. @@ -4478,7 +4479,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter [ipi stopAnimation]; } - const QCocoaWidget cw = { QCocoaProgressIndicator, aquaSize }; + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize); auto *pi = static_cast(d->cocoaControl(cw)); d->drawNSViewInRect(cw, pi, rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { d->setupVerticalInvertedXform(ctx, reverse, vertical, rect); @@ -5265,7 +5266,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex d->setupNSGraphicsContext(cg, NO /* flipped */); - const QCocoaWidget cw(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, cocoaSize); + const auto controlType = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; + const auto cw = QMacStylePrivate::CocoaControl(controlType, cocoaSize); NSScroller *scroller = static_cast(d->cocoaControl(cw)); if (isTransient) { @@ -5347,8 +5349,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex case CC_Slider: if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *slider = static_cast(d->cocoaControl(cw)); if (!setupSlider(slider, sl)) break; @@ -5483,7 +5486,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex d->setupNSGraphicsContext(cg, NO); const auto aquaSize = d->effectiveAquaSizeConstrain(opt, widget); - NSStepperCell *cell = static_cast(d->cocoaCell(QCocoaWidget(QCocoaStepper, aquaSize))); + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize); + NSStepperCell *cell = static_cast(d->cocoaCell(cw)); cell.enabled = (sb->state & State_Enabled); const CGRect newRect = [cell drawingRectForBounds:updown.toCGRect()]; @@ -5518,7 +5522,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex if (tds != kThemeStateInactive) QMacStylePrivate::drawCombobox(rect, bdi, p); else if (!widget && combo->editable) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); + const auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); NSView *cb = d->cocoaControl(cw); QRect r = combo->rect.adjusted(3, 0, 0, 0); d->drawNSViewInRect(cw, cb, r, p, widget != 0); @@ -5822,8 +5826,9 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, const bool hasTicks = sl->tickPosition != QSlider::NoTicks; const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *slider = static_cast(d->cocoaControl(cw)); if (!setupSlider(slider, sl)) break; @@ -5848,9 +5853,10 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, break; } - const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget); const bool isHorizontal = sb->orientation == Qt::Horizontal; - const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, controlSize); + const auto ct = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *scroller = static_cast(d->cocoaControl(cw)); if (!setupScroller(scroller, sb)) { sc = SC_None; @@ -5956,8 +5962,9 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op // And nothing else since 10.7 if (part != NSScrollerNoPart) { - const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, controlSize); + const auto ct = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *scroller = static_cast(d->cocoaControl(cw)); if (setupScroller(scroller, sb)) ret = QRectF::fromCGRect([scroller rectForPart:part]).toRect(); @@ -5968,8 +5975,9 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { const bool hasTicks = sl->tickPosition != QSlider::NoTicks; const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *slider = static_cast(d->cocoaControl(cw)); if (!setupSlider(slider, sl)) break; @@ -6230,7 +6238,8 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op Q_UNREACHABLE(); } - NSStepperCell *cell = static_cast(d->cocoaCell(QCocoaWidget(QCocoaStepper, aquaSize))); + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize); + NSStepperCell *cell = static_cast(d->cocoaCell(cw)); const CGRect outRect = [cell drawingRectForBounds:ret.toCGRect()]; ret = QRectF::fromCGRect(outRect).toRect(); diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 528edfcda1..9c38831c0a 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -167,28 +167,6 @@ QT_BEGIN_NAMESPACE #define CT1(c) CT2(c, c) #define CT2(c1, c2) ((uint(c1) << 16) | uint(c2)) -enum QCocoaWidgetKind { - QCocoaBox, // QGroupBox - QCocoaCheckBox, - QCocoaComboBox, // Editable QComboBox - QCocoaDisclosureButton, // Disclosure triangle, like in QTreeView - QCocoaPopupButton, // Non-editable QComboBox - QCocoaProgressIndicator, - QCocoaIndeterminateProgressIndicator, - QCocoaPullDownButton, // QPushButton with menu - QCocoaPushButton, - QCocoaRadioButton, - QCocoaHorizontalScroller, - QCocoaVerticalScroller, - QCocoaHorizontalSlider, - QCocoaVerticalSlider, - QCocoaStepper // QSpinBox buttons -}; - -typedef QPair QCocoaWidget; - -typedef void (^QCocoaDrawRectBlock)(CGContextRef, const CGRect &); - #define SIZE(large, small, mini) \ (controlSize == QStyleHelper::SizeLarge ? (large) : controlSize == QStyleHelper::SizeSmall ? (small) : (mini)) @@ -207,6 +185,28 @@ class QMacStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QMacStyle) public: + enum CocoaControlType { + Box, // QGroupBox + Button_CheckBox, + Button_Disclosure, // Disclosure triangle, like in QTreeView + Button_PopupButton, // Non-editable QComboBox + Button_PullDown, // QPushButton with menu + Button_PushButton, + Button_RadioButton, + ComboBox, // Editable QComboBox + ProgressIndicator_Determinate, + ProgressIndicator_Indeterminate, + Scroller_Horizontal, + Scroller_Vertical, + Slider_Horizontal, + Slider_Vertical, + Stepper // QSpinBox buttons + }; + + typedef QPair CocoaControl; + + typedef void (^DrawRectBlock)(CGContextRef, const CGRect &); + QMacStylePrivate(); ~QMacStylePrivate(); @@ -260,15 +260,17 @@ public: void setAutoDefaultButton(QObject *button) const; - NSView *cocoaControl(QCocoaWidget widget) const; - NSCell *cocoaCell(QCocoaWidget widget) const; + NSView *cocoaControl(CocoaControl widget) const; + NSCell *cocoaCell(CocoaControl widget) const; + + static CocoaControl cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind); void setupNSGraphicsContext(CGContextRef cg, bool flipped) const; void restoreNSGraphicsContext(CGContextRef cg) const; void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const; - void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const; + void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, DrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window); void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; @@ -284,8 +286,8 @@ public: mutable QPointer focusWidget; QT_MANGLE_NAMESPACE(NotificationReceiver) *receiver; NSView *backingStoreNSView; - mutable QHash cocoaControls; - mutable QHash cocoaCells; + mutable QHash cocoaControls; + mutable QHash cocoaCells; QFont smallSystemFont; QFont miniSystemFont; -- cgit v1.2.3 From dbc1c790431aab1d45ca8c77886dbd6438c139de Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 7 Nov 2017 14:05:21 +0700 Subject: QMacStyle: Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I6e71871b19ce12daddd4cfbbe7c1d9beede13a9b Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 66 ------------------------------ src/plugins/styles/mac/qmacstyle_mac_p.h | 4 -- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 4 -- 3 files changed, 74 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 9c5ede6d47..3ae13c3282 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -569,7 +569,6 @@ static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) case QTabBar::TriangularSouth: ttd = kThemeTabSouth; break; - default: // Added to remove the warning, since all values are taken care of, really! case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: ttd = kThemeTabNorth; @@ -622,47 +621,6 @@ static QString qt_mac_removeMnemonics(const QString &original) return returnText; } -OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon) -{ - QRegion *region = static_cast(inRefcon); - if (!region) - return paramErr; - - switch (inMessage) { - case kHIShapeEnumerateRect: - *region += QRect(inRect->origin.x, inRect->origin.y, - inRect->size.width, inRect->size.height); - break; - case kHIShapeEnumerateInit: - // Assume the region is already setup correctly - case kHIShapeEnumerateTerminate: - default: - break; - } - return noErr; -} - -/*! - \internal - Create's a mutable shape, it's the caller's responsibility to release. - WARNING: this function clamps the coordinates to SHRT_MIN/MAX on 10.4 and below. -*/ -HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) -{ - HIMutableShapeRef shape = HIShapeCreateMutable(); - if (region.rectCount() < 2 ) { - QRect qtRect = region.boundingRect(); - CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } else { - for (const QRect &qtRect : region) { - CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } - } - return shape; -} - bool qt_macWindowIsTextured(const QWidget *window) { if (QWindow *w = window->windowHandle()) @@ -1518,18 +1476,6 @@ void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, } } -#if QT_CONFIG(pushbutton) -bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option) -{ - QMacStyle *macStyle = qobject_cast(pushButton->style()); - if (!macStyle) - return false; - HIThemeButtonDrawInfo bdi; - macStyle->d_func()->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); - return bdi.kind == kThemeBevelButton; -} -#endif - /** Creates a HIThemeButtonDrawInfo structure that specifies the correct button kind and other details to use for drawing the given combobox. Which button @@ -6817,16 +6763,4 @@ int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, return_SIZE(10, 8, 6); // guess } -/* -FontHash::FontHash() -{ - QHash::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts()); -} - -Q_GLOBAL_STATIC(FontHash, app_fonts) -FontHash *qt_app_fonts_hash() -{ - return app_fonts(); -} -*/ QT_END_NAMESPACE diff --git a/src/plugins/styles/mac/qmacstyle_mac_p.h b/src/plugins/styles/mac/qmacstyle_mac_p.h index 6011baeea2..d6874001d3 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p.h @@ -117,10 +117,6 @@ public: private: Q_DISABLE_COPY(QMacStyle) Q_DECLARE_PRIVATE(QMacStyle) - -#if QT_CONFIG(pushbutton) - friend bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); -#endif }; QT_END_NAMESPACE diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 9c38831c0a..b893e851fd 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -177,10 +177,6 @@ QT_BEGIN_NAMESPACE return sizes[controlSize]; \ } while (false) -#if QT_CONFIG(pushbutton) -bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); -#endif - class QMacStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QMacStyle) -- cgit v1.2.3 From 9af0601fd91d9a0fa6266e978c8b742a38140b7f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 7 Nov 2017 14:15:39 +0700 Subject: QMacStyle: Replace HITheme info structs with QMSP::CocoaControl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not yet a full replacement, but a scaffolding stage until we can remove all traces of HITheme info structs. Change-Id: I10eb6a60662c6b102bc687e335d0d1bedd6a4a12 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 164 ++++++++++++++++------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 6 +- 2 files changed, 92 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 3ae13c3282..a8cb361969 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1483,6 +1483,7 @@ void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, explicit user style settings, etc. */ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, + CocoaControl *cw, const QWidget *widget, const ThemeDrawState &tds) const { bdi->version = qt_mac_hitheme_version; @@ -1496,6 +1497,8 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem bdi->state = tds; QStyleHelper::WidgetSizePolicy aSize = aquaSizeConstrain(combo, widget); + cw->first = combo->editable ? ComboBox : Button_PopupButton; + cw->second = aSize; switch (aSize) { case QStyleHelper::SizeMini: bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) @@ -1525,21 +1528,29 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem // them forever). So anyway, the height threshold should be smaller // in this case, or the style gets confused when it needs to render // or return any subcontrol size of the poor thing. - if (h < 9) + if (h < 9) { bdi->kind = kThemeComboBoxMini; - else if (h < 22) + cw->second = QStyleHelper::SizeMini; + } else if (h < 22) { bdi->kind = kThemeComboBoxSmall; - else + cw->second = QStyleHelper::SizeSmall; + } else { bdi->kind = kThemeComboBox; + cw->second = QStyleHelper::SizeLarge; + } } else #endif { - if (h < 21) + if (h < 21) { bdi->kind = kThemeComboBoxMini; - else if (h < 26) + cw->second = QStyleHelper::SizeMini; + } else if (h < 26) { bdi->kind = kThemeComboBoxSmall; - else + cw->second = QStyleHelper::SizeSmall; + } else { bdi->kind = kThemeComboBox; + cw->second = QStyleHelper::SizeLarge; + } } } else { // Even if we specify that we want the kThemePopupButton, Carbon @@ -1547,12 +1558,16 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem // do the same size check explicit to have the size of the inner // text field be correct. Therefore, do this even if the user specifies // the use of LargeButtons explicit. - if (h < 21) + if (h < 21) { bdi->kind = kThemePopupButtonMini; - else if (h < 26) + cw->second = QStyleHelper::SizeMini; + } else if (h < 26) { bdi->kind = kThemePopupButtonSmall; - else + cw->second = QStyleHelper::SizeSmall; + } else { bdi->kind = kThemePopupButton; + cw->second = QStyleHelper::SizeLarge; + } } break; } @@ -1562,51 +1577,54 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. */ -CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, int buttonKind) +CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget) { CGRect innerBounds = outerBounds; // Carbon draw parts of the view outside the rect. // So make the rect a bit smaller to compensate // (I wish HIThemeGetButtonBackgroundBounds worked) - switch (buttonKind){ - case kThemePopupButton: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - break; - case kThemePopupButtonSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 6; - innerBounds.size.height -= 7; - break; - case kThemePopupButtonMini: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - break; - case kThemeComboBox: - innerBounds.origin.x += 3; - innerBounds.origin.y += 2; - innerBounds.size.width -= 6; - innerBounds.size.height -= 8; - break; - case kThemeComboBoxSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 7; - innerBounds.size.height -= 8; - break; - case kThemeComboBoxMini: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 4; - innerBounds.size.height -= 8; - break; - default: - break; + if (cocoaWidget.first == Button_PopupButton) { + switch (cocoaWidget.second) { + case QStyleHelper::SizeSmall: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 6; + innerBounds.size.height -= 7; + break; + case QStyleHelper::SizeMini: + innerBounds.origin.x += 2; + innerBounds.origin.y += 2; + innerBounds.size.width -= 5; + innerBounds.size.height -= 6; + break; + case QStyleHelper::SizeLarge: + case QStyleHelper::SizeDefault: + innerBounds.origin.x += 2; + innerBounds.origin.y += 2; + innerBounds.size.width -= 5; + innerBounds.size.height -= 6; + } + } else if (cocoaWidget.first == ComboBox) { + switch (cocoaWidget.second) { + case QStyleHelper::SizeSmall: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 7; + innerBounds.size.height -= 8; + break; + case QStyleHelper::SizeMini: + innerBounds.origin.x += 3; + innerBounds.origin.y += 3; + innerBounds.size.width -= 4; + innerBounds.size.height -= 8; + break; + case QStyleHelper::SizeLarge: + case QStyleHelper::SizeDefault: + innerBounds.origin.x += 3; + innerBounds.origin.y += 2; + innerBounds.size.width -= 6; + innerBounds.size.height -= 8; + } } return innerBounds; @@ -1650,11 +1668,11 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. */ -void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) +void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p) { if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ // We have an unscaled combobox, or popup-button; use Carbon directly. - const CGRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind); + const CGRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, cw); HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0); } else { QPixmap buffer; @@ -2045,7 +2063,7 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window) backingStoreNSView = window ? (NSView *)window->winId() : nil; } -void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, +void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, const CocoaControl &cw, QPainter *p, const QStyleOption *opt) const { int xoff = 0, @@ -2093,7 +2111,7 @@ void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonD // Carbon combos don't scale. Therefore we draw it // ourselves, if a scaled version is needed. QPainter tmpPainter(&activePixmap); - QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter); + QMacStylePrivate::drawCombobox(macRect, *bdi, cw, &tmpPainter); } else { QMacCGContext cg(&activePixmap); CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); @@ -3332,10 +3350,11 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai else bdi.value = kThemeButtonOff; CGRect macRect = opt->rect.toCGRect(); + const QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); if (!drawColorless) HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); else - d->drawColorlessButton(macRect, &bdi, p, opt); + d->drawColorlessButton(macRect, &bdi, cw, p, opt); break; } case PE_FrameFocusRect: // Use the our own focus widget stuff. @@ -3830,9 +3849,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; } - if (hasMenu && bdi.kind != kThemeBevelButton) { - auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); + QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); + if (hasMenu) cw.first = QMacStylePrivate::Button_PullDown; + if (hasMenu && bdi.kind != kThemeBevelButton) { NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); [pdb highlight:(bdi.state == kThemeStatePressed)]; pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; @@ -3840,7 +3860,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter rect.adjust(0, 0, cw.second == QStyleHelper::SizeSmall ? -4 : cw.second == QStyleHelper::SizeMini ? -9 : -6, 0); d->drawNSViewInRect(cw, pdb, rect, p, w != 0); } else if (hasMenu && bdi.state == kThemeStatePressed) - d->drawColorlessButton(newRect, &bdi, p, opt); + d->drawColorlessButton(newRect, &bdi, cw, p, opt); else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); @@ -5461,19 +5481,20 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex case CC_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ HIThemeButtonDrawInfo bdi; - d->initComboboxBdi(combo, &bdi, widget, tds); + QMacStylePrivate::CocoaControl cw; + d->initComboboxBdi(combo, &bdi, &cw, widget, tds); CGRect rect = combo->rect.toCGRect(); if (combo->editable) rect.origin.y += tds == kThemeStateInactive ? 1 : 2; if (tds != kThemeStateInactive) - QMacStylePrivate::drawCombobox(rect, bdi, p); + QMacStylePrivate::drawCombobox(rect, bdi, cw, p); else if (!widget && combo->editable) { const auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); NSView *cb = d->cocoaControl(cw); QRect r = combo->rect.adjusted(3, 0, 0, 0); d->drawNSViewInRect(cw, cb, r, p, widget != 0); } else - d->drawColorlessButton(rect, &bdi, p, opt); + d->drawColorlessButton(rect, &bdi, cw, p, opt); } break; case CC_TitleBar: @@ -6017,7 +6038,8 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op case CC_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { HIThemeButtonDrawInfo bdi; - d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); + QMacStylePrivate::CocoaControl cw; + d->initComboboxBdi(combo, &bdi, &cw, widget, d->getDrawState(opt->state)); switch (sc) { case SC_ComboBoxEditField:{ @@ -6032,7 +6054,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op break; } case SC_ComboBoxListBoxPopup:{ if (combo->editable) { - const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), bdi.kind); + const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), cw); QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); const int comboTop = combo->rect.top(); ret = QRect(qRound(inner.origin.x), @@ -6509,20 +6531,10 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, // We compensate for this by adding some extra space here to make room for the frame when drawing: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ const auto widgetSize = d->aquaSizeConstrain(opt, widget); - int bkind = 0; - switch (widgetSize) { - default: - case QStyleHelper::SizeLarge: - bkind = combo->editable ? kThemeComboBox : kThemePopupButton; - break; - case QStyleHelper::SizeSmall: - bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall); - break; - case QStyleHelper::SizeMini: - bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini; - break; - } - const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, bkind); + QMacStylePrivate::CocoaControl cw; + cw.first = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; + cw.second = widgetSize; + const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); sz.rwidth() -= qRound(diffRect.size.width); sz.rheight() -= qRound(diffRect.size.height); } else if (ct == CT_PushButton || ct == CT_ToolButton){ diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index b893e851fd..01b0a15427 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -231,6 +231,7 @@ public: // Utility functions void drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, + const CocoaControl &cw, QPainter *p, const QStyleOption *opt) const; QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const; @@ -239,13 +240,14 @@ public: const HIThemeButtonDrawInfo *bdi) const; void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, + CocoaControl *cw, const QWidget *widget, const ThemeDrawState &tds) const; - static CGRect comboboxInnerBounds(const CGRect &outerBounds, int buttonKind); + static CGRect comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget); static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); - static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p); + static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p); static void drawTableHeader(const CGRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p); bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, -- cgit v1.2.3 From 1939cb02104d8e5ca0e4169e18b8e1f400090921 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 7 Nov 2017 16:37:12 +0700 Subject: QMacStyle: Make backingStoreNSView mutable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even thought the resolve function is effectively not const, it's more straightforward to call. Change-Id: I7c881183862c3c0b326daf001b2f9e569153ee76 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 8 ++++---- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index a8cb361969..c7f573cc08 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -2058,7 +2058,7 @@ void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const restoreNSGraphicsContext(ctx); } -void QMacStylePrivate::resolveCurrentNSView(QWindow *window) +void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const { backingStoreNSView = window ? (NSView *)window->winId() : nil; } @@ -3095,7 +3095,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai QMacCGContext cg(p); QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); + d->resolveCurrentNSView(window); switch (pe) { case PE_IndicatorArrowUp: case PE_IndicatorArrowDown: @@ -3593,7 +3593,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QMacCGContext cg(p); QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); + d->resolveCurrentNSView(window); switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { @@ -5126,7 +5126,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex QMacCGContext cg(p); QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); + d->resolveCurrentNSView(window); switch (cc) { case CC_ScrollBar: if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 01b0a15427..045753989f 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -269,7 +269,7 @@ public: void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const; void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, DrawRectBlock drawRectBlock = nil) const; - void resolveCurrentNSView(QWindow *window); + void resolveCurrentNSView(QWindow *window) const; void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; @@ -283,7 +283,7 @@ public: mutable QPointer focusWidget; QT_MANGLE_NAMESPACE(NotificationReceiver) *receiver; - NSView *backingStoreNSView; + mutable NSView *backingStoreNSView; mutable QHash cocoaControls; mutable QHash cocoaCells; -- cgit v1.2.3 From 67e3d192398ccf06d4411acc86df7748b0de98a5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 9 Nov 2017 13:21:23 +0700 Subject: QMacStyle: Render tool button even when a11y is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tool buttons were being skipped a couple cases (CE_ToolButtonLabel and CC_ToolButton) when accessibility was disabled. Although unlikely anyone would disable accessibility on macOS, we fall back to the non- toolbar rendering if that were to be the case. Change-Id: Ie8ee11475efbe4b418c34842317bafeba80c3c57 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index c7f573cc08..1246f64a7d 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3786,12 +3786,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } else { QCommonStyle::drawControl(ce, &myTb, p, w); } - } else { + } else +#endif // QT_NO_ACCESSIBILITY + { QCommonStyle::drawControl(ce, &myTb, p, w); } -#else - Q_UNUSED(tb) -#endif } break; case CE_ToolBoxTabShape: @@ -5674,7 +5673,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex p->fillPath(path, brush); } proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); - } else { + } else +#endif // QT_NO_ACCESSIBILITY + { ThemeButtonKind bkind = kThemeBevelButton; switch (d->aquaSizeConstrain(opt, widget)) { case QStyleHelper::SizeDefault: @@ -5757,7 +5758,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); } -#endif } break; #if QT_CONFIG(dial) -- cgit v1.2.3 From c1780b932268ff070387de80a617c9763263a9f0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 9 Nov 2017 21:41:24 +0800 Subject: QMacStyle: De-HITheme item views headers and a couple arrows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This one is all manual. The arrows were manual before and the header sections are now plain rectangles. Removes one usage of HIThemeDrawButton and related logic together with a cached pixmap and its rendering. Still broken in some places, but not worse than before. In particular, sunken or selected header sections will not render the left hand side section separator properly. Look can be improved in the header label with different shades for the selected or current rows/columns. Change-Id: I6b1c1f529909341bbf72e82e5a3fc61905c75fa8 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 190 +++++++++-------------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 2 - 2 files changed, 57 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 1246f64a7d..c6ae7c1b79 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -311,6 +311,9 @@ static const QColor tabBarCloseButtonCrossSelected(115, 115, 115); static const int closeButtonSize = 14; static const qreal closeButtonCornerRadius = 2.0; +static const int headerSectionArrowHeight = 6; +static const int headerSectionSeparatorInset = 2; + #if QT_CONFIG(tabbar) static bool isVerticalTabs(const QTabBar::Shape shape) { return (shape == QTabBar::RoundedEast @@ -1715,69 +1718,6 @@ void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButt } } -/** - Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header - onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. -*/ -void QMacStylePrivate::drawTableHeader(const CGRect &outerBounds, - bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p) -{ - static int headerHeight = qt_mac_aqua_get_metric(ListHeaderHeight); - - QPixmap buffer; - QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value)); - if (!QPixmapCache::find(key, buffer)) { - CGRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}}; - buffer = QPixmap(headerNormalRect.size.width, headerNormalRect.size.height); - buffer.fill(Qt::transparent); - QPainter buffPainter(&buffer); - HIThemeDrawButton(&headerNormalRect, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); - buffPainter.end(); - QPixmapCache::insert(key, buffer); - } - const int buttonw = qRound(outerBounds.size.width); - const int buttonh = qRound(outerBounds.size.height); - const int framew = 1; - const int frameh_n = 4; - const int frameh_s = 3; - const int transh = buffer.height() - frameh_n - frameh_s; - int center = buttonh - frameh_s - int(transh / 2.0f) + 1; // Align bottom; - - int skipTopBorder = 0; - if (!drawTopBorder) - skipTopBorder = 1; - - p->translate(outerBounds.origin.x, outerBounds.origin.y); - - p->drawPixmap(QRect(QRect(0, -skipTopBorder, buttonw - framew , frameh_n)), buffer, QRect(framew, 0, 1, frameh_n)); - p->drawPixmap(QRect(0, buttonh - frameh_s, buttonw - framew, frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, frameh_s)); - // Draw upper and lower center blocks - p->drawPixmap(QRect(0, frameh_n - skipTopBorder, buttonw - framew, center - frameh_n + skipTopBorder), buffer, QRect(framew, frameh_n, 1, 1)); - p->drawPixmap(QRect(0, center, buttonw - framew, buttonh - center - frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, 1)); - // Draw right center block borders - p->drawPixmap(QRect(buttonw - framew, frameh_n - skipTopBorder, framew, center - frameh_n), buffer, QRect(buffer.width() - framew, frameh_n, framew, 1)); - p->drawPixmap(QRect(buttonw - framew, center, framew, buttonh - center - 1), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, 1)); - // Draw right corners - p->drawPixmap(QRect(buttonw - framew, -skipTopBorder, framew, frameh_n), buffer, QRect(buffer.width() - framew, 0, framew, frameh_n)); - p->drawPixmap(QRect(buttonw - framew, buttonh - frameh_s, framew, frameh_s), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, frameh_s)); - // Draw center transition block - p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), buttonw - framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(framew, frameh_n + 1, 1, transh)); - // Draw right center transition block border - p->drawPixmap(QRect(buttonw - framew, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(buffer.width() - framew, frameh_n + 1, framew, transh)); - if (drawLeftBorder){ - // Draw left center block borders - p->drawPixmap(QRect(0, frameh_n - skipTopBorder, framew, center - frameh_n + skipTopBorder), buffer, QRect(0, frameh_n, framew, 1)); - p->drawPixmap(QRect(0, center, framew, buttonh - center - 1), buffer, QRect(0, buffer.height() - frameh_s, framew, 1)); - // Draw left corners - p->drawPixmap(QRect(0, -skipTopBorder, framew, frameh_n), buffer, QRect(0, 0, framew, frameh_n)); - p->drawPixmap(QRect(0, buttonh - frameh_s, framew, frameh_s), buffer, QRect(0, buffer.height() - frameh_s, framew, frameh_s)); - // Draw left center transition block border - p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(0, frameh_n + 1, framew, transh)); - } - - p->translate(-outerBounds.origin.x, -outerBounds.origin.y); -} - QMacStylePrivate::QMacStylePrivate() : backingStoreNSView(nil) { @@ -3103,7 +3043,17 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai case PE_IndicatorArrowLeft: { p->save(); p->setRenderHint(QPainter::Antialiasing); - int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1; + const int xOffset = 1; // FIXME: opt->direction == Qt::LeftToRight ? 2 : -1; + qreal halfSize = 0.5 * qMin(opt->rect.width(), opt->rect.height()); + const qreal penWidth = qMax(halfSize / 3.0, 1.25); +#if QT_CONFIG(toolbutton) + if (const QToolButton *tb = qobject_cast(w)) { + // When stroking the arrow, make sure it fits in the tool button + if (tb->arrowType() != Qt::NoArrow) + halfSize -= penWidth; + } +#endif + QMatrix matrix; matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); QPainterPath path; @@ -3121,13 +3071,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai matrix.rotate(-90); break; } - path.moveTo(0, 5); - path.lineTo(-4, -3); - path.lineTo(4, -3); p->setMatrix(matrix); - p->setPen(Qt::NoPen); - p->setBrush(QColor(0, 0, 0, 135)); - p->drawPath(path); + + path.moveTo(-halfSize, -halfSize * 0.5); + path.lineTo(0.0, halfSize * 0.5); + path.lineTo(halfSize, -halfSize * 0.5); + + const QPen arrowPen(opt->palette.text(), penWidth, + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + p->strokePath(path, arrowPen); p->restore(); break; } #if QT_CONFIG(tabbar) @@ -3597,66 +3549,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; State flags = header->state; QRect ir = header->rect; - bdi.kind = kThemeListHeaderButton; - bdi.adornment = kThemeAdornmentNone; - bdi.state = kThemeStateActive; - if (flags & State_On) - bdi.value = kThemeButtonOn; - else - bdi.value = kThemeButtonOff; - - if (header->orientation == Qt::Horizontal){ - switch (header->position) { - case QStyleOptionHeader::Beginning: - ir.adjust(-1, -1, 0, 0); - break; - case QStyleOptionHeader::Middle: - ir.adjust(-1, -1, 0, 0); - break; - case QStyleOptionHeader::OnlyOneSection: - case QStyleOptionHeader::End: - ir.adjust(-1, -1, 1, 0); - break; - default: - break; - } - - if (header->position != QStyleOptionHeader::Beginning - && header->position != QStyleOptionHeader::OnlyOneSection) { - bdi.adornment = header->direction == Qt::LeftToRight - ? kThemeAdornmentHeaderButtonLeftNeighborSelected - : kThemeAdornmentHeaderButtonRightNeighborSelected; - } - } - - if (flags & State_Active) { - if (!(flags & State_Enabled)) - bdi.state = kThemeStateUnavailable; - else if (flags & State_Sunken) - bdi.state = kThemeStatePressed; - } else { - if (flags & State_Enabled) - bdi.state = kThemeStateInactive; - else - bdi.state = kThemeStateUnavailableInactive; - } - - if (header->sortIndicator != QStyleOptionHeader::None) { - bdi.value = kThemeButtonOn; - if (header->sortIndicator == QStyleOptionHeader::SortDown) - bdi.adornment = kThemeAdornmentHeaderButtonSortUp; - } - if (flags & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - - ir = visualRect(header->direction, header->rect, ir); - CGRect bounds = ir.toCGRect(); +#if 0 // FIXME: What's this solving exactly? bool noVerticalHeader = true; #if QT_CONFIG(tableview) if (w) @@ -3664,12 +3561,22 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter noVerticalHeader = !table->verticalHeader()->isVisible(); #endif - bool drawTopBorder = header->orientation == Qt::Horizontal; - bool drawLeftBorder = header->orientation == Qt::Vertical - || header->position == QStyleOptionHeader::OnlyOneSection - || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); - d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p); + const bool drawLeftBorder = header->orientation == Qt::Vertical + || header->position == QStyleOptionHeader::OnlyOneSection + || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); +#endif + + const bool pressed = (flags & State_Sunken) && !(flags & State_On); + p->fillRect(ir, pressed ? header->palette.dark() : header->palette.button()); + p->setPen(QPen(header->palette.dark(), 1.0)); + if (header->orientation == Qt::Horizontal) + p->drawLine(QLineF(ir.right() + 0.5, ir.top() + headerSectionSeparatorInset, + ir.right() + 0.5, ir.bottom() - headerSectionSeparatorInset)); + else + p->drawLine(QLineF(ir.left() + headerSectionSeparatorInset, ir.bottom(), + ir.right() - headerSectionSeparatorInset, ir.bottom())); } + break; case CE_HeaderLabel: if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { @@ -4657,14 +4564,31 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, // Subtract width needed for arrow, if there is one if (header->sortIndicator != QStyleOptionHeader::None) { if (opt->state & State_Horizontal) - rect.setWidth(rect.width() - (opt->rect.height() / 2) - (margin * 2)); + rect.setWidth(rect.width() - (headerSectionArrowHeight) - (margin * 2)); else - rect.setHeight(rect.height() - (opt->rect.width() / 2) - (margin * 2)); + rect.setHeight(rect.height() - (headerSectionArrowHeight) - (margin * 2)); } } rect = visualRect(opt->direction, opt->rect, rect); break; } + case SE_HeaderArrow: { + int h = opt->rect.height(); + int w = opt->rect.width(); + int x = opt->rect.x(); + int y = opt->rect.y(); + int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); + + if (opt->state & State_Horizontal) { + rect.setRect(x + w - margin * 2 - headerSectionArrowHeight, y + 5, + headerSectionArrowHeight, h - margin * 2 - 5); + } else { + rect.setRect(x + 5, y + h - margin * 2 - headerSectionArrowHeight, + w - margin * 2 - 5, headerSectionArrowHeight); + } + rect = visualRect(opt->direction, opt->rect, rect); + break; + } case SE_ProgressBarGroove: // Wrong in the secondary dimension, but accurate enough in the main dimension. rect = opt->rect; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 045753989f..078509d551 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -248,8 +248,6 @@ public: static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p); - static void drawTableHeader(const CGRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, - const HIThemeButtonDrawInfo &bdi, QPainter *p); bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, ThemeButtonKind buttonKindToCheck) const; void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget, -- cgit v1.2.3 From 7c334301bd32376538390027f7481c4b5f3eab49 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 10 Nov 2017 16:25:49 +0100 Subject: HTTP/2 - fix header processing httpReply->setHeaderField does not simply append (name|value) pairs, it first erases all entries with the same name. This is quite wrong when we have _several_ 'Set-Cookie' headers, for example. Found while trying to login into a facebook account :) Task-number: QTBUG-64359 Change-Id: I51416ca3ba3d92b9414e4649e493d9cd88f6d9a0 Reviewed-by: Edward Welbourne --- src/network/access/qhttp2protocolhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 114feb91b7..9dfcec8311 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -1069,7 +1069,7 @@ void QHttp2ProtocolHandler::updateStream(Stream &stream, const HPack::HttpHeader QByteArray binder(", "); if (name == "set-cookie") binder = "\n"; - httpReply->setHeaderField(name, value.replace('\0', binder)); + httpReplyPrivate->fields.append(qMakePair(name, value.replace('\0', binder))); } } -- cgit v1.2.3 From 55f8d7dfe5589f85b0fa8a0705b1821f69b2cb34 Mon Sep 17 00:00:00 2001 From: Mikkel Krautz Date: Mon, 13 Feb 2017 21:35:02 +0100 Subject: qsslsocket_mac: handle 'OrLater' SslProtocols in verifySessionProtocol() The verifySessionProtocol() method in the SecureTransport backend did not properly handle TlsV1_0OrLater, TlsV1_1OrLater and TlsV1_2OrLater. This commit teaches verifySessionProtocol() about them. It also adds TlsV1_0OrLater, TlsV1_1OrLater and TlsV1_2OrLater to the protocolServerSide() test in tst_qsslsocket. Backport from 5.10 to 5.9 (LTS). Reviewed-by: Timur Pocheptsov (cherry picked from commit 9c765522d1c4f8090b5f5d391b1740fc4bd67664) Change-Id: I58c53bdf43e0f19b4506f3696d793f657eb4dc6f Reviewed-by: Edward Welbourne --- src/network/ssl/qsslsocket_mac.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 0aef6a2a99..2ba988fb70 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -1108,6 +1108,12 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const protocolOk = (sessionProtocol() >= QSsl::SslV3); else if (configuration.protocol == QSsl::SecureProtocols) protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); + else if (configuration.protocol == QSsl::TlsV1_0OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); + else if (configuration.protocol == QSsl::TlsV1_1OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_1); + else if (configuration.protocol == QSsl::TlsV1_2OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_2); else protocolOk = (sessionProtocol() == configuration.protocol); -- cgit v1.2.3 From 2caebf42a70cceb21b46b08e341c3cbf928b1fc8 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Tue, 14 Nov 2017 19:26:56 +0200 Subject: QIODevice: do not clear error string on close Keeping a description of the last device error is a more informative to the user than forcing the string to 'Unknown error'. Change-Id: Ie98fe1c94f24279fb633ce950bbe16450b0efdbd Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- src/corelib/io/qiodevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 82fc34c537..0a3e83206b 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -775,6 +775,7 @@ bool QIODevice::open(OpenMode mode) d->writeBuffers.clear(); d->setReadChannelCount(isReadable() ? 1 : 0); d->setWriteChannelCount(isWritable() ? 1 : 0); + d->errorString.clear(); #if defined QIODEVICE_DEBUG printf("%p QIODevice::open(0x%x)\n", this, quint32(mode)); #endif @@ -801,7 +802,6 @@ void QIODevice::close() emit aboutToClose(); #endif d->openMode = NotOpen; - d->errorString.clear(); d->pos = 0; d->transactionStarted = false; d->transactionPos = 0; -- cgit v1.2.3 From a4113d0c644edba1c39d9d268a259e95ae51c61e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 17 Nov 2017 10:35:58 +0100 Subject: qfloat16(float) constructor: explicit cast on aarch64 to avoid warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The warning was global/qfloat16.h: In constructor ‘qfloat16::qfloat16(float)’: global/qfloat16.h:124:18: error: conversion to ‘__fp16’ from ‘float’ may alter its value [-Werror=float-conversion] __fp16 f16 = f; ^ cc1plus: all warnings being treated as errors The warning was added by fb5976038162d93d60c7f76376bbb4df38e83ba9. Change-Id: I489348c4d5d672bfa5d4db99c837696a2a69a27e Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 10598adb1d..a36852fc22 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -121,7 +121,7 @@ inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW __m128i packhalf = _mm_cvtps_ph(packsingle, 0); b16 = _mm_extract_epi16(packhalf, 0); #elif defined (__ARM_FP16_FORMAT_IEEE) - __fp16 f16 = f; + __fp16 f16 = __fp16(f); memcpy(&b16, &f16, sizeof(quint16)); #else quint32 u; -- cgit v1.2.3