From 58b70c2f1acedad0df6b4de1acf3dea2011e369c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Nov 2017 16:16:55 +0100 Subject: [PATCH 001/102] tst_QFileSystemModel: Stabilize readOnly(), sortPersistentIndex() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests start to show flakyness on Linux in 5.10 (rowCount() check failing). This seems to point to a race condition between the files showing up and the file system watchers of QFileSystemModel starting. To fix this, close the file and wait until it shows up in the directory before pointing the QFileSystemModel to it. The tests then no longer rely on the file system watchers. Change-Id: I39cffb4cacf6843e8e4180efb405345307c78dd8 Reviewed-by: Jędrzej Nowacki --- .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 31df66e312e..979d5c632e3 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -239,13 +239,18 @@ void tst_QFileSystemModel::readOnly() QCOMPARE(model->isReadOnly(), true); QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); QVERIFY2(file.open(), qPrintable(file.errorString())); + const QString fileName = file.fileName(); + file.close(); + + const QFileInfo fileInfo(fileName); + QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo)); QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); - QVERIFY(!(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable)); + QVERIFY(!(model->flags(model->index(fileName)) & Qt::ItemIsEditable)); model->setReadOnly(false); QCOMPARE(model->isReadOnly(), false); - QVERIFY(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable); + QVERIFY(model->flags(model->index(fileName)) & Qt::ItemIsEditable); } class CustomFileIconProvider : public QFileIconProvider @@ -729,6 +734,9 @@ void tst_QFileSystemModel::sortPersistentIndex() { QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); QVERIFY2(file.open(), qPrintable(file.errorString())); + const QFileInfo fileInfo(file.fileName()); + file.close(); + QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo)); QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); From dc4b4e9949e49da31efa1fe0f2a5cbb15656292d Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Thu, 21 Sep 2017 12:09:05 +0300 Subject: [PATCH 002/102] Build integrityhid support only if it is available Change-Id: I6e0aa2f74516d4c0a1905b188f195834d395584b Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/integrity/integrity.pro | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/integrity/integrity.pro b/src/plugins/platforms/integrity/integrity.pro index 0fb256793d4..54438707eb9 100644 --- a/src/plugins/platforms/integrity/integrity.pro +++ b/src/plugins/platforms/integrity/integrity.pro @@ -8,13 +8,18 @@ QT += \ SOURCES = \ main.cpp \ qintegrityfbintegration.cpp \ - qintegrityfbscreen.cpp \ - qintegrityhidmanager.cpp + qintegrityfbscreen.cpp HEADERS = \ qintegrityfbintegration.h \ - qintegrityfbscreen.h \ - qintegrityhidmanager.h + qintegrityfbscreen.h + +qtConfig(integrityhid) { + SOURCES += \ + qintegrityhidmanager.cpp + HEADERS += \ + qintegrityhidmanager.h +} OTHER_FILES += integrity.json From dae308d8926ae8c6d8f8484cd7108ae395aa5933 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Nov 2017 08:52:42 +0100 Subject: [PATCH 003/102] qprintengine_win.cpp: Fix -Wclazy-range-loop qprintengine_win.cpp:1502: warning: Missing reference in range-for with non trivial type (QPrint::InputSlot) [-Wclazy-range-loop] Change-Id: If6e55c1748e05e32aaa32a16063ba491fe242952 Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprintengine_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index e399118cc95..b479ecacb12 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1499,7 +1499,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const QList out; const auto inputSlots = d->m_printDevice.supportedInputSlots(); out.reserve(inputSlots.size()); - for (const QPrint::InputSlot inputSlot : inputSlots) + for (const QPrint::InputSlot &inputSlot : inputSlots) out << QVariant(inputSlot.id == QPrint::CustomInputSlot ? inputSlot.windowsId : int(inputSlot.id)); value = out; break; From 109290753b59e554a70639a9764259a3c61fd58a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 15 Nov 2017 10:35:50 +0100 Subject: [PATCH 004/102] Android: Fix note for host architecture mismatch The qtConfAddNotice was a typo, so this note was missing from config.log and the build would fail with no explanation. Change-Id: Iae22f92c1ba6bdf96d41a7cc608b9aedd6863b1f Reviewed-by: Oswald Buddenhagen --- configure.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.pri b/configure.pri index 83c0dee141d..dc703ecb148 100644 --- a/configure.pri +++ b/configure.pri @@ -557,7 +557,7 @@ defineTest(qtConfOutput_prepareOptions) { else: \ qtConfFatalError("Cannot detect the Android host." \ "Please use -android-ndk-host option to specify one.") - qtConfAddNotice("Available Android host does not match host architecture.") + qtConfAddNote("Available Android host does not match host architecture.") } } else { !exists($$ndk_tc_pfx/$$ndk_host/*): \ From 1a55c929332cacfc7e3934810fa1a4601f39846b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 24 Nov 2017 17:11:40 +0100 Subject: [PATCH 005/102] iOS: Compute screen available geometry based on safe area insets In addition to the (deprecated) applicationFrame property, we base the available geometry on the root view's safe area, which also takes into account system-reserved areas on iPhone X, and the screen's bezel in the case of tvOS. Change-Id: I252d960a0e486dd0c7e30843f88c0bf5684feb24 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.mm | 29 ++++++++++++++++++++----- src/plugins/platforms/ios/quiview.h | 1 + src/plugins/platforms/ios/quiview.mm | 16 ++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 74e81dedf4d..1a7004c2494 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -175,6 +175,21 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) @end +@interface UIScreen (Compatibility) +@property (nonatomic, readonly) CGRect qt_applicationFrame; +@end + +@implementation UIScreen (Compatibility) +- (CGRect)qt_applicationFrame +{ +#ifdef Q_OS_IOS + return self.applicationFrame; +#else + return self.bounds; +#endif +} +@end + // ------------------------------------------------------------------------- QT_BEGIN_NAMESPACE @@ -271,11 +286,15 @@ void QIOSScreen::updateProperties() QRect previousAvailableGeometry = m_availableGeometry; m_geometry = QRectF::fromCGRect(m_uiScreen.bounds).toRect(); -#ifdef Q_OS_TVOS - m_availableGeometry = m_geometry; -#else - m_availableGeometry = QRectF::fromCGRect(m_uiScreen.applicationFrame).toRect(); -#endif + + // The application frame doesn't take safe area insets into account, and + // the safe area insets are not available before the UIWindow is shown, + // and do not take split-view constraints into account, so we have to + // combine the two to get the correct available geometry. + QRect applicationFrame = QRectF::fromCGRect(m_uiScreen.qt_applicationFrame).toRect(); + UIEdgeInsets safeAreaInsets = m_uiWindow.qt_safeAreaInsets; + m_availableGeometry = m_geometry.adjusted(safeAreaInsets.left, safeAreaInsets.top, + -safeAreaInsets.right, -safeAreaInsets.bottom).intersected(applicationFrame); #ifndef Q_OS_TVOS if (m_uiScreen == [UIScreen mainScreen]) { diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index 1500f0b41c1..1ce9007a358 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -77,5 +77,6 @@ QT_END_NAMESPACE - (QWindow *)qwindow; - (UIViewController *)viewController; - (QIOSViewController*)qtViewController; +@property (nonatomic, readonly) UIEdgeInsets qt_safeAreaInsets; @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index a405fecee28..79f9d6871a6 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -545,6 +545,22 @@ return nil; } +- (UIEdgeInsets)qt_safeAreaInsets +{ +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA) + if (__builtin_available(iOS 11, tvOS 11, *)) + return self.safeAreaInsets; +#endif + + // Fallback for iOS < 11 + UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero; + CGPoint topInset = [self convertPoint:CGPointMake(0, self.viewController.topLayoutGuide.length) fromView:nil]; + CGPoint bottomInset = [self convertPoint:CGPointMake(0, self.viewController.bottomLayoutGuide.length) fromView:nil]; + safeAreaInsets.top = topInset.y; + safeAreaInsets.bottom = bottomInset.y; + return safeAreaInsets; +} + @end #ifndef QT_NO_ACCESSIBILITY From d80fde62ed82493322463d2057a07b6b2ed81a83 Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Wed, 22 Nov 2017 11:56:20 +0100 Subject: [PATCH 006/102] Fix broken QNAM::networkAccessible() When switching on/off multiple time the wifi (mainly, but not only) on ios/macos the QNAM may wrongly stay on a NotAccessible state while the configuration is Active. This change make sure the QNAM::networkAccessible() is correctly reporting the accessibility. Task-number: QTBUG-49751 Task-number: QTBUG-58275 Task-number: QTBUG-60366 Change-Id: I238ab32030fbaa8072cce341db8da6bcfc346035 Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkaccessmanager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index fba5755b77a..0ab3760eeda 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1839,7 +1839,8 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession emit q->networkSessionConnected(); lastSessionState = state; - if (online && state == QNetworkSession::Disconnected) { + if (online && (state == QNetworkSession::Disconnected + || state == QNetworkSession::NotAvailable)) { const auto cfgs = networkConfigurationManager.allConfigurations(); for (const QNetworkConfiguration &cfg : cfgs) { if (cfg.state().testFlag(QNetworkConfiguration::Active)) { @@ -1881,9 +1882,9 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { if (online != isOnline) { + online = isOnline; _q_networkSessionClosed(); createSession(q->configuration()); - online = isOnline; } } if (online) { From 0f1b8fd2dcd2db698095a54ca9beff7e27cf1ceb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 27 Nov 2017 10:40:44 +0100 Subject: [PATCH 007/102] work around flex bug flex emits code using isatty(), but fails to include the required unistd.h. we can work around it by including the header ourselves. Task-number: QTBUG-64771 Change-Id: I05313eeb79f7a0e25365dee5f05a0142f87209ae Reviewed-by: Thiago Macieira --- src/tools/qlalr/examples/qparser/calc.l | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/qlalr/examples/qparser/calc.l b/src/tools/qlalr/examples/qparser/calc.l index e619e34dab0..fe542680a86 100644 --- a/src/tools/qlalr/examples/qparser/calc.l +++ b/src/tools/qlalr/examples/qparser/calc.l @@ -33,6 +33,9 @@ #include "calc_parser.h" #include +// Work around flex bug +#include + #define YY_DECL int CalcParser::nextToken() %} From 6c75857c20972f0d65fc7d556b9dcd81e21060db Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Nov 2017 13:30:54 +0100 Subject: [PATCH 008/102] configure: mention quoting requirements in the help text Change-Id: Id79548b8458dfa25fef17cb25688738bb719e7c5 Reviewed-by: Thiago Macieira --- config_help.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config_help.txt b/config_help.txt index 6b1401c6188..003752dbe7c 100644 --- a/config_help.txt +++ b/config_help.txt @@ -9,6 +9,12 @@ ICU_PREFIX=/opt/icu42 ICU_LIBS="-licui18n -licuuc -licudata". It is also possible to manipulate any QMAKE_* variable, to amend the values from the mkspec for the build of Qt itself, e.g., QMAKE_CXXFLAGS+=-g3. +Note that the *_LIBS* and QMAKE_* assignments manipulate lists, so items +containing meta characters (spaces in particular) need to be quoted according +to qmake rules. On top of that, the assignments as a whole need to be quoted +according to shell rules. It is recommended to use single quotes for the inner +quoting and double quotes for the outer quoting. + Top-level installation directories: -prefix ...... The deployment directory, as seen on the target device. [/usr/local/Qt-$QT_VERSION, $PWD if -developer-build] From 0fbf78250eafc345c2b7925b1dc27056565242b6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Nov 2017 18:07:33 +0100 Subject: [PATCH 009/102] configure: fix processing of *_LIBS_{DEBUG|RELEASE}= args qtConfLibrary_inline() used to set $${1}.builds.$${b}.libs, while everything else assumed no such .libs suffix. fix the former. amends 9172143f52. Task-number: QTBUG-61431 Started-by: Konstantin Ritt Change-Id: I0bd81591c46266d81baa9c12315411183bbc7a63 Reviewed-by: Lars Knoll --- mkspecs/features/qt_configure.prf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 1ba96767beb..a4ed3f0a72e 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -513,8 +513,8 @@ defineTest(qtConfLibrary_inline) { iv = $${input}.libs.$${b} vars += $$eval(config.commandline.rev_assignments.$${iv}) defined(config.input.$${iv}, var) { - $${1}.builds.$${b}.libs = $$eval(config.input.$${iv}) - export($${1}.builds.$${b}.libs) + $${1}.builds.$${b} = $$eval(config.input.$${iv}) + export($${1}.builds.$${b}) any = true } else { all = false From 79a068c3964db79979821bb9e9bad6eb7ab6211c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Nov 2017 18:05:53 +0100 Subject: [PATCH 010/102] configure: fix over-quoting in library exporting unlike for the other fields, we forgot to eval() the values of the build-specific library values, leading to over-quoting of values which require any quoting at all. amends c0cc50520. Task-number: QTBUG-62521 Change-Id: I4dfce31040dd09248d3f9dd4294f7fb147c13bdd Reviewed-by: Lars Knoll --- mkspecs/features/qt_configure.prf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index a4ed3f0a72e..658bd59e5e8 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -670,9 +670,10 @@ defineTest(qtConfExportLibrary) { NAME = $$upper($$name) # LIBS is emitted even if empty, as this allows the library to be "seen". qtConfOutputVar(assign, $$output, QMAKE_LIBS_$$NAME, $$libs) - for (b, $${spfx}.builds._KEYS_): \ - qtConfOutputVar(assign, $$output, QMAKE_LIBS_$${NAME}_$$upper($$b), \ - $$eval($${spfx}.builds.$${b})) + for (b, $${spfx}.builds._KEYS_) { + eval(blibs = $$eval($${spfx}.builds.$${b})) + qtConfOutputVar(assign, $$output, QMAKE_LIBS_$${NAME}_$$upper($$b), $$blibs) + } !isEmpty(defines): qtConfOutputVar(assign, $$output, QMAKE_DEFINES_$$NAME, $$defines) !isEmpty(includes): qtConfOutputVar(assign, $$output, QMAKE_INCDIR_$$NAME, $$includes) !isEmpty($${currentConfig}.module): \ From 26e9a6a5149aca056418ad55402231191a48cdbf Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Nov 2017 19:19:36 +0100 Subject: [PATCH 011/102] configure: make *_LIBS_{DEBUG|RELEASE} always work ... and not only when the source explicitly specifies build variants. Change-Id: Iac6c8fda8f431d5fb50fada8338d1b660ab040d7 Reviewed-by: Lars Knoll --- mkspecs/features/qt_configure.prf | 12 ++++++++---- src/network/configure.json | 8 -------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 658bd59e5e8..ecd9233ddd7 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -509,20 +509,24 @@ defineTest(qtConfLibrary_inline) { vars = any = false all = true - for (b, $${1}.builds._KEYS_) { + for (b, $$list(debug release)) { iv = $${input}.libs.$${b} vars += $$eval(config.commandline.rev_assignments.$${iv}) defined(config.input.$${iv}, var) { $${1}.builds.$${b} = $$eval(config.input.$${iv}) export($${1}.builds.$${b}) + $${1}.builds._KEYS_ *= $${b} any = true } else { all = false } } - $$any:!$$all { - qtConfAddError("Either none or all of $$join(vars, ", ", [, ]) must be specified.") - return(false) + $$any { + !$$all { + qtConfAddError("Either none or all of $$join(vars, ", ", [, ]) must be specified.") + return(false) + } + export($${1}.builds._KEYS_) } # prefix. prepends to (possibly overwritten) inline libs. diff --git a/src/network/configure.json b/src/network/configure.json index 916448a7276..2cf90ed94b7 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -69,18 +69,10 @@ { "comment": "placeholder for OPENSSL_{PATH,LIBS{,_{DEBUG,RELEASE}}}", "libs": "", - "builds": { - "debug": "", - "release": "" - }, "condition": "config.win32 && !features.shared" }, { "libs": "-lssleay32 -llibeay32", - "builds": { - "debug": "", - "release": "" - }, "condition": "config.win32 && features.shared" }, { "libs": "-lssl -lcrypto", "condition": "!config.win32" } From 8dfcc3b0239ffb8af7254280b0fa51770fd4e75b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Nov 2017 19:33:39 +0100 Subject: [PATCH 012/102] configure: reset *_LIBS when *_LIBS_{DEBUG|RELEASE} are specified it could be somewhat surprising that specifying variant-specific libs would not clear the common libs, so do that. of course, the default for the common libs could theoretically contain common deps of the variant-specific libs, in which case clearing them would be surprising in turn - luckily, we have no such case. Change-Id: Ifca08b9e1949c6a0cefed6931ade4021927d7c90 Reviewed-by: Lars Knoll --- mkspecs/features/qt_configure.prf | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index ecd9233ddd7..dcd87a7a1a5 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -499,12 +499,6 @@ defineTest(qtConfLibrary_inline) { # to make them recognize the same input variables. input = $$eval($${2}.alias) - # direct libs. overwrites inline libs. - defined(config.input.$${input}.libs, var) { - $${1}.libs = $$eval(config.input.$${input}.libs) - export($${1}.libs) - } - # build-specific direct libs. overwrites inline libs. vars = any = false @@ -527,6 +521,15 @@ defineTest(qtConfLibrary_inline) { return(false) } export($${1}.builds._KEYS_) + # we also reset the generic libs, to avoid surprises. + $${1}.libs = + export($${1}.libs) + } + + # direct libs. overwrites inline libs. + defined(config.input.$${input}.libs, var) { + $${1}.libs = $$eval(config.input.$${input}.libs) + export($${1}.libs) } # prefix. prepends to (possibly overwritten) inline libs. From 153311706cd21d91ba06a7f86228dd575bd9672e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Nov 2017 15:00:26 +0100 Subject: [PATCH 013/102] macOS/iOS: Fix garbled text under some conditions There seems to be an issue in CoreText which may cause an existing font descriptor to give unreliable results if it refers to one of the system theme fonts. Since we do not know all function calls or events that may trigger this bug, the safe route is to always create fresh font descriptors when creating fonts for these descriptors. The impact on performance should be small, as Qt has its own internal caches. [ChangeLog][macOS/iOS][Text] Fixed an issue where text using one of the system theme fonts would under certain circumstances display random glyphs. Task-number: QTBUG-63476 Change-Id: I9e9b253018c63976345eec1439a6b78de2cab869 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../mac/qcoretextfontdatabase.mm | 24 ++++++++++++------- .../mac/qcoretextfontdatabase_p.h | 4 +++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 6347d4d2319..237e8a89a53 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -416,7 +416,19 @@ extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); template <> QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) { - CTFontDescriptorRef descriptor = static_cast(usrPtr); + QCFType descriptor = QCFType::constructFromGet( + static_cast(usrPtr)); + + // CoreText will sometimes invalidate information in font descriptors that refer + // to system fonts in certain function calls or application states. While the descriptor + // looks the same from the outside, some internal plumbing is different, causing the results + // of creating CTFonts from those descriptors unreliable. The work-around for this + // is to copy the attributes of those descriptors each time we make a new CTFont + // from them instead of referring to the original, as that may trigger the CoreText bug. + if (m_systemFontDescriptors.contains(descriptor)) { + QCFType attributes = CTFontDescriptorCopyAttributes(descriptor); + descriptor = CTFontDescriptorCreateWithAttributes(attributes); + } // Since we do not pass in the destination DPI to CoreText when making // the font, we need to pass in a point size which is scaled to include @@ -427,14 +439,10 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine qreal scaledPointSize = fontDef.pixelSize; CGAffineTransform matrix = qt_transform_from_fontdef(fontDef); - CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); - if (font) { - QFontEngine *engine = new QCoreTextFontEngine(font, fontDef); - CFRelease(font); - return engine; - } + if (QCFType font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix)) + return new QCoreTextFontEngine(font, fontDef); - return NULL; + return nullptr; } #ifndef QT_NO_FREETYPE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 9612b909f19..e14d1d6e6e4 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -91,12 +91,14 @@ public: QFont *themeFont(QPlatformTheme::Font) const; const QHash &themeFonts() const; +protected: + mutable QSet m_systemFontDescriptors; + private: void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString()); mutable QString defaultFontName; - mutable QSet m_systemFontDescriptors; mutable QHash m_themeFonts; bool m_hasPopulatedAliases; }; From 0ebf0cfb6f2e21ceef4f95b54a4a02abd7214dc1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 21 Nov 2017 08:54:03 +0100 Subject: [PATCH 014/102] Blacklist tst_QSplitter::replaceWidget(visible, not collapsed) for Linux The test is flaky on Linux. Task-number: QTBUG-64639 Change-Id: Iec56ebce4f656f52187b34c8f655b137e41c3d17 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Gabriel de Dietrich --- tests/auto/widgets/widgets/qsplitter/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/widgets/widgets/qsplitter/BLACKLIST diff --git a/tests/auto/widgets/widgets/qsplitter/BLACKLIST b/tests/auto/widgets/widgets/qsplitter/BLACKLIST new file mode 100644 index 00000000000..1352805cd7f --- /dev/null +++ b/tests/auto/widgets/widgets/qsplitter/BLACKLIST @@ -0,0 +1,2 @@ +[replaceWidget:visible, not collapsed] +xcb From bfef7d12249717555f6d81b54f748d9df10974e9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 23 Nov 2017 09:48:43 +0100 Subject: [PATCH 015/102] tests/auto/auto.pro: Use correct null device for DBUS check A mysterious file c:\dev\null appeared when running the auto tests on Windows. Fix by using QMAKE_SYSTEM_NULL_DEVICE. Amends 5f3529be32df3cce81e77c3dbb76cfda7feb320c. Change-Id: I0224a9ccd61c4f10b2ddb8f8d690e1849aa88d8a Reviewed-by: Oswald Buddenhagen --- tests/auto/auto.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index a1ffe5b3cee..fbd89e40456 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -35,7 +35,7 @@ else:!qtConfig(process): SUBDIRS -= tools # Disable the QtDBus tests if we can't connect to the session bus !cross_compile:qtHaveModule(dbus) { - !system("dbus-send --session --type=signal / local.AutotestCheck.Hello >/dev/null 2>&1") { + !system("dbus-send --session --type=signal / local.AutotestCheck.Hello >$$QMAKE_SYSTEM_NULL_DEVICE 2>&1") { qtConfig(dbus-linked): \ error("QtDBus is enabled but session bus is not available. Please check the installation.") else: \ From 6d09db53f7b5161d865f0fe8f832aa3757d66f74 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 30 Oct 2017 09:13:32 +0100 Subject: [PATCH 016/102] macOS: Blacklist tst_QPauseAnimation::noTimerUpdates() Task-number: QTBUG-64107 Change-Id: Ie77d2d2525e79fb7e17f1a69d15ef40982f9242d Reviewed-by: Jesus Fernandez --- tests/auto/corelib/animation/qpauseanimation/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST index 8fc1b07502c..a49ed2a617b 100644 --- a/tests/auto/corelib/animation/qpauseanimation/BLACKLIST +++ b/tests/auto/corelib/animation/qpauseanimation/BLACKLIST @@ -4,3 +4,5 @@ osx-10.9 * [multipleSequentialGroups] osx +[noTimerUpdates] +osx From 92cd3bfa2ebe133651b3d9f4e0c3394bbe79ba6a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 30 Oct 2017 09:14:27 +0100 Subject: [PATCH 017/102] macOS: Blacklist: tst_QPropertyAnimation::startWithoutStartValue() Task-number: QTBUG-64108 Change-Id: Id60a9a1bfede9cbe90f378d131a331d726acfdae Reviewed-by: Jesus Fernandez --- tests/auto/corelib/animation/qpropertyanimation/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST b/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST index a7e95b1e974..a8719b241a0 100644 --- a/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST +++ b/tests/auto/corelib/animation/qpropertyanimation/BLACKLIST @@ -2,3 +2,5 @@ windows [startBackwardWithoutEndValue] windows +[startWithoutStartValue] +osx From f4498db196c19208236e97ddae448e0ec1a4be04 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 15 Nov 2017 13:57:22 +0200 Subject: [PATCH 018/102] Add configure test for INTEGRITY EGLFS openWFD integration plugin Change-Id: I846f9e555df4f64097b5634707515d45c13a521c Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- src/gui/configure.json | 18 +++++++++++++++++- .../deviceintegration/deviceintegration.pro | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/gui/configure.json b/src/gui/configure.json index 0664cb92c67..9710ee4e202 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -705,6 +705,17 @@ }, "use": "egl" }, + "egl-openwfd": { + "label": "OpenWFD EGL", + "type": "compile", + "test": { + "include": [ "wfd.h" ], + "main": [ + "wfdEnumerateDevices(nullptr, 0, nullptr);" + ] + }, + "use": "egl" + }, "evdev": { "label": "evdev", "type": "compile", @@ -1088,6 +1099,11 @@ "condition": "features.eglfs_viv && libs.wayland_server", "output": [ "privateFeature" ] }, + "eglfs_openwfd": { + "label": "EGLFS OpenWFD", + "condition": "config.integrity && features.eglfs && tests.egl-openwfd", + "output": [ "privateFeature" ] + }, "gif": { "label": "GIF", "condition": "features.imageformatplugin", @@ -1560,7 +1576,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "section": "EGLFS details", "condition": "features.eglfs", "entries": [ - "eglfs_viv", "eglfs_viv_wl", "eglfs_egldevice", "eglfs_gbm", "eglfs_mali", "eglfs_brcm", "egl_x11" + "eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_egldevice", "eglfs_gbm", "eglfs_mali", "eglfs_brcm", "egl_x11" ] }, "linuxfb", "vnc", "mirclient", diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 6d759938b58..2cddbe9beb7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -8,7 +8,7 @@ qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm qtConfig(eglfs_mali): SUBDIRS += eglfs_mali qtConfig(eglfs_viv): SUBDIRS += eglfs_viv qtConfig(eglfs_viv_wl): SUBDIRS += eglfs_viv_wl - +qtConfig(eglfs_openwfd): SUBDIRS += eglfs_openwfd qtConfig(opengl): SUBDIRS += eglfs_emu eglfs_kms_egldevice.depends = eglfs_kms_support From 7b73d455ee8e6e2bca8bd29ac3cd40e4a89eb511 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 15 Nov 2017 13:23:42 +0200 Subject: [PATCH 019/102] Add mkspec for INTEGRITY Qualcomm s820 MSM8996AU Change-Id: Ia3983594d9295ae858efe2289c296cfcc2fe1b78 Reviewed-by: Rolland Dudemaine Reviewed-by: Andy Nichols --- .../integrity-armv8-msm8996au/qmake.conf | 57 +++++++++++++++++++ .../integrity-armv8-msm8996au/qplatformdefs.h | 45 +++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 mkspecs/devices/integrity-armv8-msm8996au/qmake.conf create mode 100644 mkspecs/devices/integrity-armv8-msm8996au/qplatformdefs.h diff --git a/mkspecs/devices/integrity-armv8-msm8996au/qmake.conf b/mkspecs/devices/integrity-armv8-msm8996au/qmake.conf new file mode 100644 index 00000000000..90299bf3e9a --- /dev/null +++ b/mkspecs/devices/integrity-armv8-msm8996au/qmake.conf @@ -0,0 +1,57 @@ +# +# qmake configuration for INTEGRITY Qualcomm s820 Snapdragon MSM8996AU +# + +load(device_config) + +include(../../common/ghs-integrity-armv8.conf) + +QT_QPA_DEFAULT_PLATFORM = eglfs +EGLFS_DEVICE_INTEGRATION = eglfs_openwfd + +bsp_name = $$(INTEGRITY_BSP) +isEmpty(bsp_name): \ + error("This qmakespec requires $INTEGRITY_BSP to be set") + +os_directory = $$(INTEGRITY_DIR) +isEmpty(os_directory): \ + error("This qmakespec requires $INTEGRITY_DIR to be set") + +qclibs_directory = $$(QCLIBS_DIR) +isEmpty(qclibs_directory): \ + error("This qmakespec requires $QCLIBS_DIR to be set") + +qc_multimedia_inc_directory = $$(QC_MULTIMEDIA_INC_DIR) +isEmpty(qc_multimedia_inc_directory): \ + error("This qmakespec requires $QC_MULTIMEDIA_INC_DIR to be set") + +gl_inc_directory = $$(GL_INC_DIR) +isEmpty(gl_inc_directory): \ + error("This qmakespec requires $GL_INC_DIR to be set") + +gl_lib_directory = $$(GL_LIB_DIR) +isEmpty(gl_lib_directory): \ + error("This qmakespec requires $GL_LIB_DIR to be set") + +QMAKE_LIBDIR += $$(QCLIBS_DIR)/base +QMAKE_LIBDIR += $$(QCLIBS_DIR)/multimedia/display + +QMAKE_INCDIR += $$(QC_MULTIMEDIA_INC_DIR) + +QMAKE_LIBS_EGL += -lESXEGL_Adreno -lESXGLESv2_Adreno -ladreno_utils -lGSLUser -lOSUser -lpanel -livfs -lposix -lpmem -ltzbsp -lpaged_alloc -lglnext-llvm -lopenwfd +QMAKE_LIBS_OPENGL_ES2 += $${QMAKE_LIBS_EGL} + +QMAKE_CFLAGS += -DINTEGRITY +QMAKE_CXXFLAGS += -DINTEGRITY + +QMAKE_CFLAGS += -bigswitch +QMAKE_CXXFLAGS += -bigswitch +QMAKE_LFLAGS += -bigswitch + +# OpenGL libraries have a dependency on libEGL +QMAKE_INCDIR_EGL = $$(GL_INC_DIR) +QMAKE_LIBDIR_EGL = $$(GL_LIB_DIR) +QMAKE_INCDIR_OPENGL_ES2 = $$(GL_INC_DIR) +QMAKE_LIBDIR_OPENGL_ES2 = $$(GL_LIB_DIR) + +load(qt_config) diff --git a/mkspecs/devices/integrity-armv8-msm8996au/qplatformdefs.h b/mkspecs/devices/integrity-armv8-msm8996au/qplatformdefs.h new file mode 100644 index 00000000000..c8361113a09 --- /dev/null +++ b/mkspecs/devices/integrity-armv8-msm8996au/qplatformdefs.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../../common/integrity/qplatformdefs.h" + +#endif // QPLATFORMDEFS_H From de250dd22c698ae1eec4927c87314024c3523c70 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Wed, 15 Nov 2017 13:03:36 +0200 Subject: [PATCH 020/102] Add EGLFS integration plugin for Qualcomm msm8996au board Change-Id: I5bed1fd690daa72492e7ec5f24e80198a2592986 Reviewed-by: Janne Koskinen Reviewed-by: Laszlo Agocs --- .../eglfs_openwfd/eglfs_openwfd.json | 3 + .../eglfs_openwfd/eglfs_openwfd.pro | 17 ++ .../qeglfsopenwfdintegration.cpp | 223 ++++++++++++++++++ .../eglfs_openwfd/qeglfsopenwfdintegration.h | 69 ++++++ .../eglfs_openwfd/qeglfsopenwfdmain.cpp | 58 +++++ 5 files changed, 370 insertions(+) create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json new file mode 100644 index 00000000000..cf7cf6b887a --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_openwfd" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro new file mode 100644 index 00000000000..448b4cbe21c --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/eglfs_openwfd.pro @@ -0,0 +1,17 @@ +TARGET = qeglfs-openwfd-integration + +QT += core-private gui-private eglfsdeviceintegration-private + +INCLUDEPATH += $$PWD/../../api +CONFIG += egl + +SOURCES += $$PWD/qeglfsopenwfdmain.cpp \ + $$PWD/qeglfsopenwfdintegration.cpp + +HEADERS += $$PWD/qeglfsopenwfdintegration.h + +OTHER_FILES += $$PWD/eglfs_openwfd.json + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSOpenWFDIntegrationPlugin +load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp new file mode 100644 index 00000000000..bb176a69d28 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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$ +** +****************************************************************************/ + +#include "qeglfsopenwfdintegration.h" + +#include "wfd.h" +#include "wfdext2.h" + +QT_BEGIN_NAMESPACE + +#define MAX_NUM_OF_WFD_BUFFERS 3 +#define MAX_NUM_OF_WFD_DEVICES 4 +#define MAX_NUM_OF_WFD_PIPELINES 4 +#define MAX_NUM_OF_WFD_PORT_MODES 64 +#define MAX_NUM_OF_WFD_PORTS 4 + +typedef struct wfd_buffer { + WFD_EGLImageType* image; + WFDSource source; +} wfd_buffer_t; + +typedef struct wfd_window { + WFDDevice dev; + WFDPort port; + WFDPipeline pipeline; + int numBuffers; + wfd_buffer_t buffers[MAX_NUM_OF_WFD_BUFFERS]; +} wfd_window_t; + +void QEglFSOpenWFDIntegration::platformInit() +{ + QEglFSDeviceIntegration::platformInit(); + + mNativeDisplay = EGL_DEFAULT_DISPLAY; + + // Get device list + WFDint numDevs = wfdEnumerateDevices(nullptr, 0, nullptr); + WFDint devIds[MAX_NUM_OF_WFD_DEVICES]; + + if (numDevs > 0) + wfdEnumerateDevices(devIds, numDevs, nullptr); + + // Create device + mDevice = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID, nullptr); + + if (WFD_INVALID_HANDLE == mDevice) + qFatal( "Failed to create wfd device"); + + // Get port list + WFDint portIds[MAX_NUM_OF_WFD_PORTS]; + WFDint numPorts = wfdEnumeratePorts(mDevice, nullptr, 0, nullptr); + wfdEnumeratePorts(mDevice, portIds, numPorts, nullptr); + + // Create port + mPort = wfdCreatePort(mDevice, portIds[0], nullptr); + + if (WFD_INVALID_HANDLE == mPort) + qFatal("Failed to create wfd port"); + + // Get port modes + WFDint numPortModes = wfdGetPortModes(mDevice, mPort, nullptr, 0); + WFDPortMode portModes[MAX_NUM_OF_WFD_PORT_MODES]; + wfdGetPortModes(mDevice, mPort, portModes, numPortModes); + + // Get width and height + mScreenSize.setWidth(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_WIDTH)); + mScreenSize.setHeight(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_HEIGHT)); + + // Set port mode + wfdSetPortMode(mDevice, mPort, portModes[0]); + WFDErrorCode eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set wfd port mode"); + + // Power on + wfdSetPortAttribi(mDevice, mPort, WFD_PORT_POWER_MODE, WFD_POWER_MODE_ON); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to power on wfd port"); +} + +QSize QEglFSOpenWFDIntegration::screenSize() const +{ + return mScreenSize; +} + +EGLNativeDisplayType QEglFSOpenWFDIntegration::platformDisplay() const +{ + return mNativeDisplay; +} + +EGLNativeWindowType QEglFSOpenWFDIntegration::createNativeWindow(QPlatformWindow *window, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(window); + Q_UNUSED(format); + + // Get list of pipelines + WFDint numPipelines = wfdEnumeratePipelines(mDevice, nullptr, 0, nullptr); + + WFDint pipelineIds[MAX_NUM_OF_WFD_PIPELINES]; + wfdEnumeratePipelines(mDevice, pipelineIds, numPipelines, nullptr); + + WFDint testId = 0; + testId = pipelineIds[0]; + WFDPipeline pipeline = wfdCreatePipeline(mDevice, testId, nullptr); + if (WFD_INVALID_HANDLE == pipeline) + qFatal("Failed to create wfd pipeline"); + + wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_TRANSPARENCY_ENABLE, + (WFD_TRANSPARENCY_SOURCE_ALPHA|WFD_TRANSPARENCY_GLOBAL_ALPHA)); + + WFDErrorCode eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set WFD_PIPELINE_TRANSPARENCY_ENABLE"); + + wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_GLOBAL_ALPHA, 255); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to set WFD_PIPELINE_GLOBAL_ALPHA"); + + wfdBindPipelineToPort(mDevice, mPort, pipeline); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to bind port to pipeline"); + + // Create buffers + WFDSource source[MAX_NUM_OF_WFD_BUFFERS] = {WFD_INVALID_HANDLE, WFD_INVALID_HANDLE, + WFD_INVALID_HANDLE}; + WFDEGLImage eglImageHandles[MAX_NUM_OF_WFD_BUFFERS]; + WFD_EGLImageType* wfdEglImages[MAX_NUM_OF_WFD_BUFFERS]; + + for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) { + wfdCreateWFDEGLImages(mDevice, mScreenSize.width(), mScreenSize.height(), + WFD_FORMAT_RGBA8888, WFD_USAGE_OPENGL_ES2 | WFD_USAGE_DISPLAY, + 1, &(eglImageHandles[i]), 0); + + wfdEglImages[i] = (WFD_EGLImageType *)(eglImageHandles[i]); + if (WFD_INVALID_HANDLE == wfdEglImages[i]) + qFatal("Failed to create WDFEGLImages"); + + source[i] = wfdCreateSourceFromImage(mDevice, pipeline, eglImageHandles[i], nullptr); + if (WFD_INVALID_HANDLE == source[i]) + qFatal("Failed to create source from EGLImage"); + } + + // Commit port + wfdDeviceCommit(mDevice, WFD_COMMIT_ENTIRE_PORT, mPort); + eError = wfdGetError(mDevice); + if (WFD_ERROR_NONE != eError) + qFatal("Failed to commit port"); + + // Create native window + wfd_window_t* nativeWindow = (wfd_window_t*)malloc(sizeof(wfd_window_t)); + if (nullptr == nativeWindow) + qFatal("Failed to allocate memory for native window"); + + nativeWindow->dev = mDevice; + nativeWindow->port = mPort; + nativeWindow->pipeline = pipeline; + nativeWindow->numBuffers = MAX_NUM_OF_WFD_BUFFERS; + + for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) { + nativeWindow->buffers[i].image = wfdEglImages[i]; + nativeWindow->buffers[i].source = source[i]; + } + + return (EGLNativeWindowType)nativeWindow; +} + +QSurfaceFormat QEglFSOpenWFDIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format; + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + format.setAlphaBufferSize(8); + return format; +} + +void QEglFSOpenWFDIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + free((void*)window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h new file mode 100644 index 00000000000..189ddd4d7a2 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdintegration.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QEGLFSOPENWFDINTEGRATION_H +#define QEGLFSOPENWFDINTEGRATION_H + +#include "private/qeglfsdeviceintegration_p.h" +#define WFD_WFDEXT_PROTOTYPES +#include "wfd.h" +#include "wfdext2.h" + +QT_BEGIN_NAMESPACE + +class QEglFSOpenWFDIntegration : public QEglFSDeviceIntegration +{ +public: + void platformInit() override; + QSize screenSize() const override; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override; + void destroyNativeWindow(EGLNativeWindowType window) override; + EGLNativeDisplayType platformDisplay() const override; + virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; + +private: + QSize mScreenSize; + EGLNativeDisplayType mNativeDisplay; + WFDDevice mDevice; + WFDPort mPort; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp new file mode 100644 index 00000000000..1d6132b55e5 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/qeglfsopenwfdmain.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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$ +** +****************************************************************************/ + +#include "private/qeglfsdeviceintegration_p.h" +#include "qeglfsopenwfdintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSOpenWFDIntegrationPlugin : public QEglFSDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_openwfd.json") + +public: + QEglFSDeviceIntegration *create() override { + return new QEglFSOpenWFDIntegration; + } +}; + +QT_END_NAMESPACE + +#include "qeglfsopenwfdmain.moc" From fbda8acc922217745bb3e7754d1cd450a0e0165a Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 30 Nov 2017 15:08:48 +0300 Subject: [PATCH 021/102] QFutureWatcher: Use nullptr as a default value in constructor ... to make user code buildable with gcc [-Werror=zero-as-null-pointer-constant]. Change-Id: I309953acd7154511660302aa9826410276cfe41b Reviewed-by: Marc Mutz --- src/corelib/thread/qfuturewatcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/thread/qfuturewatcher.h b/src/corelib/thread/qfuturewatcher.h index 3357e270372..8a6716a8f7b 100644 --- a/src/corelib/thread/qfuturewatcher.h +++ b/src/corelib/thread/qfuturewatcher.h @@ -115,7 +115,7 @@ template class QFutureWatcher : public QFutureWatcherBase { public: - explicit QFutureWatcher(QObject *_parent = 0) + explicit QFutureWatcher(QObject *_parent = nullptr) : QFutureWatcherBase(_parent) { } ~QFutureWatcher() From 306c32f50e289c401e4636976c97dc2b40fdd69b Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 28 Nov 2017 11:44:11 +0100 Subject: [PATCH 022/102] Fix out of bounds reads in qdnslookup_unix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the response from res_nquery is too big for the buffer used to receive it (of size PACKETSZ, a mere 512 bytes), the returned responseLength is the size of the data that would have been delivered, had there been enough space. Trying to process all of the data, including what wasn't delivered, leads to reading past the end of the buffer, which either causes a crash or leads to rubbish (from the stack) in the resulting QDnsRecords. Easy to reproduce using many long TXT records. Replace the array with a QVarLengthArray; when the response is big, resize() and retry, so as to actually get all of the data, so that we can process it all. A follow-up patch will fix the case when even the second call/resize buffer is not enough and we have to use TCP. Task-number: QTBUG-64742 Change-Id: I173beb531e11a3828fd9c97f437afc192766035e Reviewed-by: Mårten Nordheim Reviewed-by: Edward Welbourne --- src/network/kernel/qdnslookup_unix.cpp | 27 +++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 1da00813ce2..ce1ec6442a6 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -42,6 +42,7 @@ #if QT_CONFIG(library) #include #endif +#include #include #include #include @@ -58,6 +59,8 @@ # include #endif +#include + QT_BEGIN_NAMESPACE #if QT_CONFIG(library) @@ -137,7 +140,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN // Initialize state. struct __res_state state; - memset(&state, 0, sizeof(state)); + std::memset(&state, 0, sizeof(state)); if (local_res_ninit(&state) < 0) { reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Resolver initialization failed"); @@ -189,11 +192,25 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN QScopedPointer state_ptr(&state); // Perform DNS query. - unsigned char response[PACKETSZ]; - memset(response, 0, sizeof(response)); - const int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, response, sizeof(response)); + QVarLengthArray buffer(PACKETSZ); + std::memset(buffer.data(), 0, buffer.size()); + int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); + if (Q_UNLIKELY(responseLength > PACKETSZ)) { + buffer.resize(responseLength); + std::memset(buffer.data(), 0, buffer.size()); + responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); + if (Q_UNLIKELY(responseLength > buffer.size())) { + // Ok, we give up. + reply->error = QDnsLookup::ResolverError; + reply->errorString.clear(); // We cannot be more specific, alas. + return; + } + } - // Check the response header. + unsigned char *response = buffer.data(); + // Check the response header. Though res_nquery returns -1 as a + // responseLength in case of error, we still can extract the + // exact error code from the response. HEADER *header = (HEADER*)response; const int answerCount = ntohs(header->ancount); switch (header->rcode) { From 0c9e379dd8c57fab9d8e6ba8d35a0dca8ac05a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Fri, 1 Dec 2017 11:19:28 +0100 Subject: [PATCH 023/102] Use a custom QAnimationDriver to take control over time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should reduce flakyness of tests. Change-Id: I26e0a97f7cd3e7cee2ffb44188300c37578cddd7 Reviewed-by: Jędrzej Nowacki --- src/corelib/animation/qabstractanimation.cpp | 4 +- .../qpropertyanimation/qpropertyanimation.pro | 2 +- .../tst_qpropertyanimation.cpp | 227 ++++++++++++------ 3 files changed, 161 insertions(+), 72 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 2041b8816e4..e445037efb2 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -299,13 +299,13 @@ void QUnifiedTimer::stopAnimationDriver() driver->stop(); } -void QUnifiedTimer::updateAnimationTimers(qint64) +void QUnifiedTimer::updateAnimationTimers(qint64 currentTick) { //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations if(insideTick) return; - qint64 totalElapsed = elapsed(); + qint64 totalElapsed = currentTick > 0 ? currentTick : elapsed(); // ignore consistentTiming in case the pause timer is active qint64 delta = (consistentTiming && !pauseTimer.isActive()) ? diff --git a/tests/auto/corelib/animation/qpropertyanimation/qpropertyanimation.pro b/tests/auto/corelib/animation/qpropertyanimation/qpropertyanimation.pro index bfeb183abf5..72a36876b7b 100644 --- a/tests/auto/corelib/animation/qpropertyanimation/qpropertyanimation.pro +++ b/tests/auto/corelib/animation/qpropertyanimation/qpropertyanimation.pro @@ -1,4 +1,4 @@ CONFIG += testcase TARGET = tst_qpropertyanimation -QT = core gui widgets testlib +QT = core gui widgets testlib core-private SOURCES = tst_qpropertyanimation.cpp diff --git a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp index cf4c4e1bdb5..41a051a7193 100644 --- a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,80 @@ public: MyObject o; }; +class TestAnimationDriver : public QAnimationDriver +{ +public: + TestAnimationDriver() + : QAnimationDriver() + , m_elapsed(0) + { + QUnifiedTimer::instance()->installAnimationDriver(this); + } + + ~TestAnimationDriver() + { + // This is to ensure that running animations are removed from the list of actual running + // animations. + QCoreApplication::sendPostedEvents(); + QUnifiedTimer::instance()->uninstallAnimationDriver(this); + } + + void wait(qint64 ms) + { + /* + * When QAbstractAnimation::start() is called it will end up calling + * QAnimationTimer::registerAnimation(). This will do + * + * QMetaObject::invokeMethod(inst, "startAnimations", Qt::QueuedConnection); // typeof(inst) == QAnimationTimer + * + * startAnimations() will again fire a queued connection to actually add the animation + * to the list of running animations: + * + * QMetaObject::invokeMethod(inst, "startTimers", Qt::QueuedConnection); // typeof(inst) == QUnifiedTimer + * + * We therefore have to call QCoreApplication::sendPostedEvents() twice here. + */ + QCoreApplication::sendPostedEvents(); + QCoreApplication::sendPostedEvents(); + + // Simulates the ideal animation update freqency (approx. 60Hz) + static const int interval = 1000/60; + qint64 until = m_elapsed + ms; + while (m_elapsed < until) { + advanceAnimation(m_elapsed); + m_elapsed += interval; + } + advanceAnimation(m_elapsed); + // This is to make sure that animations that were started with DeleteWhenStopped + // will actually delete themselves within the test function. + // Normally, they won't be deleted until the main event loop is processed. + // Therefore, have to explicitly say that we want to process DeferredDelete events. Same + // trick is used by QTest::qWait(). + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + } + + qint64 elapsed() const override + { + return m_elapsed; + } + + void start() override + { + d_func()->running = true; + m_elapsed = 0; + emit started(); + } + + void stop() override + { + d_func()->running = false; + emit stopped(); + } + +private: + qint64 m_elapsed; + Q_DECLARE_PRIVATE(QAnimationDriver) +}; class tst_QPropertyAnimation : public QObject { @@ -261,40 +336,44 @@ void tst_QPropertyAnimation::statesAndSignals() QCOMPARE(currentLoopSpy.count(), 2); runningSpy.clear(); - anim->start(); - QTest::qWait(1000); - QTRY_COMPARE(anim->state(), QAnimationGroup::Stopped); - QCOMPARE(runningSpy.count(), 2); //started and stopped again - runningSpy.clear(); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(anim->currentLoopTime(), 100); - QCOMPARE(anim->currentLoop(), 2); - QCOMPARE(currentLoopSpy.count(), 4); + { + TestAnimationDriver timeDriver; + anim->start(); + timeDriver.wait(1000); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(runningSpy.count(), 2); //started and stopped again + runningSpy.clear(); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(anim->currentLoopTime(), 100); + QCOMPARE(anim->currentLoop(), 2); + QCOMPARE(currentLoopSpy.count(), 4); - anim->start(); // auto-rewinds - QCOMPARE(anim->state(), QAnimationGroup::Running); - QCOMPARE(anim->currentTime(), 0); - QCOMPARE(anim->currentLoop(), 0); - QCOMPARE(currentLoopSpy.count(), 5); - QCOMPARE(runningSpy.count(), 1); // anim has started - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(anim->currentLoop(), 0); - runningSpy.clear(); + anim->start(); // auto-rewinds + QCOMPARE(anim->state(), QAnimationGroup::Running); + QCOMPARE(anim->currentTime(), 0); + QCOMPARE(anim->currentLoop(), 0); + QCOMPARE(currentLoopSpy.count(), 5); + QCOMPARE(runningSpy.count(), 1); // anim has started + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(anim->currentLoop(), 0); + runningSpy.clear(); - QTest::qWait(1000); + timeDriver.wait(1000); - QCOMPARE(currentLoopSpy.count(), 7); - QCOMPARE(anim->state(), QAnimationGroup::Stopped); - QCOMPARE(anim->currentLoop(), 2); - QCOMPARE(runningSpy.count(), 1); // anim has stopped - QCOMPARE(finishedSpy.count(), 2); - QCOMPARE(anim->currentLoopTime(), 100); + QCOMPARE(currentLoopSpy.count(), 7); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(anim->currentLoop(), 2); + QCOMPARE(runningSpy.count(), 1); // anim has stopped + QCOMPARE(finishedSpy.count(), 2); + QCOMPARE(anim->currentLoopTime(), 100); - delete anim; + delete anim; + } } void tst_QPropertyAnimation::deletion1() { + TestAnimationDriver timeDriver; QObject *object = new QWidget; QPointer anim = new QPropertyAnimation(object, "minimumWidth"); @@ -312,23 +391,23 @@ void tst_QPropertyAnimation::deletion1() QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(100); + timeDriver.wait(100); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(150); + timeDriver.wait(150); QVERIFY(anim); //The animation should not have been deleted - QTRY_COMPARE(anim->state(), QAnimationGroup::Stopped); + QCOMPARE(anim->state(), QAnimationGroup::Stopped); QCOMPARE(runningSpy.count(), 2); QCOMPARE(finishedSpy.count(), 1); anim->start(QVariantAnimation::DeleteWhenStopped); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(100); + timeDriver.wait(100); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); - QTest::qWait(150); - QTRY_COMPARE(runningSpy.count(), 4); + timeDriver.wait(150); + QCOMPARE(runningSpy.count(), 4); QCOMPARE(finishedSpy.count(), 2); QVERIFY(!anim); //The animation must have been deleted delete object; @@ -336,6 +415,7 @@ void tst_QPropertyAnimation::deletion1() void tst_QPropertyAnimation::deletion2() { + TestAnimationDriver timeDriver; //test that the animation get deleted if the object is deleted QObject *object = new QWidget; QPointer anim = new QPropertyAnimation(object,"minimumWidth"); @@ -354,7 +434,7 @@ void tst_QPropertyAnimation::deletion2() anim->setDuration(200); anim->start(); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(anim); QCOMPARE(anim->state(), QAnimationGroup::Running); @@ -363,7 +443,7 @@ void tst_QPropertyAnimation::deletion2() //we can't call deletaLater directly because the delete would only happen in the next loop of _this_ event loop QTimer::singleShot(0, object, SLOT(deleteLater())); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(!anim->targetObject()); } @@ -371,6 +451,7 @@ void tst_QPropertyAnimation::deletion2() void tst_QPropertyAnimation::deletion3() { //test that the stopped signal is emit when the animation is destroyed + TestAnimationDriver timeDriver; QObject *object = new QWidget; QPropertyAnimation *anim = new QPropertyAnimation(object,"minimumWidth"); anim->setStartValue(10); @@ -385,7 +466,7 @@ void tst_QPropertyAnimation::deletion3() anim->start(); - QTest::qWait(50); + timeDriver.wait(50); QCOMPARE(anim->state(), QAnimationGroup::Running); QCOMPARE(runningSpy.count(), 1); QCOMPARE(finishedSpy.count(), 0); @@ -432,6 +513,7 @@ public: void tst_QPropertyAnimation::noStartValue() { + TestAnimationDriver timeDriver; StartValueTester o; o.setProperty("ole", 42); o.values.clear(); @@ -441,7 +523,8 @@ void tst_QPropertyAnimation::noStartValue() a.setDuration(250); a.start(); - QTRY_COMPARE(o.values.value(o.values.size() - 1, -1), 420); + timeDriver.wait(a.duration()); + QCOMPARE(o.values.value(o.values.size() - 1, -1), 420); QCOMPARE(o.values.first(), 42); } @@ -471,6 +554,7 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() StartValueTester o; o.setProperty("ole", 42); o.values.clear(); + TestAnimationDriver timeDriver; { //normal case: the animation finishes and is deleted @@ -479,18 +563,17 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() QSignalSpy runningSpy(anim.data(), &QVariantAnimation::stateChanged); QVERIFY(runningSpy.isValid()); anim->start(QVariantAnimation::DeleteWhenStopped); - QTest::qWait(anim->duration() + 100); - QTRY_COMPARE(runningSpy.count(), 2); //started and then stopped + timeDriver.wait(anim->duration()); + QCOMPARE(runningSpy.count(), 2); //started and then stopped QVERIFY(!anim); } - { QPointer anim = new QPropertyAnimation(&o, "ole"); anim->setEndValue(100); QSignalSpy runningSpy(anim.data(), &QVariantAnimation::stateChanged); QVERIFY(runningSpy.isValid()); anim->start(QVariantAnimation::DeleteWhenStopped); - QTest::qWait(anim->duration()/2); + timeDriver.wait(anim->duration()/2); QPointer anim2 = new QPropertyAnimation(&o, "ole"); anim2->setEndValue(100); QCOMPARE(runningSpy.count(), 1); @@ -498,11 +581,11 @@ void tst_QPropertyAnimation::startWhenAnotherIsRunning() //anim2 will interrupt anim1 QMetaObject::invokeMethod(anim2, "start", Qt::QueuedConnection, Q_ARG(QAbstractAnimation::DeletionPolicy, QVariantAnimation::DeleteWhenStopped)); - QTest::qWait(50); + timeDriver.wait(50); QVERIFY(!anim); //anim should have been deleted QVERIFY(anim2); - QTest::qWait(anim2->duration()); - QTRY_VERIFY(!anim2); //anim2 is finished: it should have been deleted by now + timeDriver.wait(anim2->duration()); + QVERIFY(!anim2); //anim2 is finished: it should have been deleted by now QVERIFY(!anim); } @@ -559,6 +642,7 @@ void tst_QPropertyAnimation::easingcurve() void tst_QPropertyAnimation::startWithoutStartValue() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 42); QCOMPARE(o.property("ole").toInt(), 42); @@ -568,14 +652,14 @@ void tst_QPropertyAnimation::startWithoutStartValue() anim.start(); - QTest::qWait(100); + timeDriver.wait(100); int current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current > 42); QVERIFY(current < 100); - QTest::qWait(200); - QTRY_COMPARE(anim.state(), QVariantAnimation::Stopped); + timeDriver.wait(200); + QCOMPARE(anim.state(), QVariantAnimation::Stopped); current = anim.currentValue().toInt(); QCOMPARE(current, 100); QCOMPARE(o.property("ole").toInt(), current); @@ -586,7 +670,7 @@ void tst_QPropertyAnimation::startWithoutStartValue() // the default start value will reevaluate the current property // and set it to the end value of the last iteration QCOMPARE(current, 100); - QTest::qWait(100); + timeDriver.wait(100); current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current >= 100); @@ -595,6 +679,7 @@ void tst_QPropertyAnimation::startWithoutStartValue() void tst_QPropertyAnimation::startBackwardWithoutEndValue() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 42); QCOMPARE(o.property("ole").toInt(), 42); @@ -608,14 +693,14 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() QCOMPARE(anim.state(), QAbstractAnimation::Running); QCOMPARE(o.property("ole").toInt(), 42); //the initial value - QTest::qWait(100); + timeDriver.wait(100); int current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current > 42); QVERIFY(current < 100); - QTest::qWait(200); - QTRY_COMPARE(anim.state(), QVariantAnimation::Stopped); + timeDriver.wait(200); + QCOMPARE(anim.state(), QVariantAnimation::Stopped); current = anim.currentValue().toInt(); QCOMPARE(current, 100); QCOMPARE(o.property("ole").toInt(), current); @@ -626,7 +711,7 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() // the default start value will reevaluate the current property // and set it to the end value of the last iteration QCOMPARE(current, 100); - QTest::qWait(100); + timeDriver.wait(100); current = anim.currentValue().toInt(); //it is somewhere in the animation QVERIFY(current >= 100); @@ -636,6 +721,7 @@ void tst_QPropertyAnimation::startBackwardWithoutEndValue() void tst_QPropertyAnimation::playForwardBackward() { + TestAnimationDriver timeDriver; QObject o; o.setProperty("ole", 0); QCOMPARE(o.property("ole").toInt(), 0); @@ -644,16 +730,16 @@ void tst_QPropertyAnimation::playForwardBackward() anim.setStartValue(0); anim.setEndValue(100); anim.start(); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), anim.duration()); //the animation is at the end anim.setDirection(QVariantAnimation::Backward); anim.start(); QCOMPARE(anim.state(), QAbstractAnimation::Running); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), 0); //the direction is backward @@ -661,8 +747,8 @@ void tst_QPropertyAnimation::playForwardBackward() anim.start(); QCOMPARE(anim.state(), QAbstractAnimation::Running); QCOMPARE(anim.currentTime(), anim.duration()); - QTest::qWait(anim.duration() + 100); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), 0); } @@ -1106,21 +1192,21 @@ void tst_QPropertyAnimation::restart() void tst_QPropertyAnimation::valueChanged() { - + TestAnimationDriver timeDriver; //we check that we receive the valueChanged signal MyErrorObject o; o.setOle(0); QCOMPARE(o.property("ole").toInt(), 0); QPropertyAnimation anim(&o, "ole"); anim.setEndValue(5); - anim.setDuration(1000); + anim.setDuration(200); QSignalSpy spy(&anim, &QPropertyAnimation::valueChanged); QVERIFY(spy.isValid()); anim.start(); + // Drive animation forward to its end + timeDriver.wait(anim.duration()); - QTest::qWait(anim.duration() + 100); - - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); QCOMPARE(anim.currentTime(), anim.duration()); //let's check that the values go forward @@ -1153,6 +1239,7 @@ public: void tst_QPropertyAnimation::twoAnimations() { + TestAnimationDriver timeDriver; MySyncObject o1, o2; o1.setOle(0); o2.setOle(0); @@ -1169,8 +1256,8 @@ void tst_QPropertyAnimation::twoAnimations() o1.anim.start(); o2.anim.start(); - QTest::qWait(o1.anim.duration() + 100); - QTRY_COMPARE(o1.anim.state(), QAbstractAnimation::Stopped); + timeDriver.wait(o1.anim.duration()); + QCOMPARE(o1.anim.state(), QAbstractAnimation::Stopped); QCOMPARE(o2.anim.state(), QAbstractAnimation::Stopped); QCOMPARE(o1.ole(), 1000); @@ -1209,6 +1296,7 @@ public: void tst_QPropertyAnimation::deletedInUpdateCurrentTime() { + TestAnimationDriver timeDriver; // this test case reproduces an animation being deleted in the updateCurrentTime of // another animation(was causing segfault). // the deleted animation must have been started after the animation that is deleting. @@ -1219,9 +1307,9 @@ void tst_QPropertyAnimation::deletedInUpdateCurrentTime() MyComposedAnimation composedAnimation(&o, "value", "realValue"); composedAnimation.start(); QCOMPARE(composedAnimation.state(), QAbstractAnimation::Running); - QTest::qWait(composedAnimation.duration() + 100); + timeDriver.wait(composedAnimation.duration()); - QTRY_COMPARE(composedAnimation.state(), QAbstractAnimation::Stopped); + QCOMPARE(composedAnimation.state(), QAbstractAnimation::Stopped); QCOMPARE(o.value(), 1000); } @@ -1293,6 +1381,7 @@ public: void tst_QPropertyAnimation::recursiveAnimations() { + TestAnimationDriver timeDriver; RecursiveObject o; QPropertyAnimation anim; anim.setTargetObject(&o); @@ -1301,9 +1390,9 @@ void tst_QPropertyAnimation::recursiveAnimations() anim.setEndValue(4000); anim.start(); - QTest::qWait(anim.duration() + o.animation.duration()); - QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); - QTRY_COMPARE(o.animation.state(), QAbstractAnimation::Stopped); + timeDriver.wait(anim.duration() + o.animation.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); + QCOMPARE(o.animation.state(), QAbstractAnimation::Stopped); QCOMPARE(o.y(), qreal(4000)); } From c9f68a5858f053aa5a0b1e8fd4c751ed441e0338 Mon Sep 17 00:00:00 2001 From: Yulong Bai Date: Tue, 21 Nov 2017 14:38:15 +0100 Subject: [PATCH 024/102] QFusionStyle: fix the checkbox rendering in HiDPI situation 1. Make the checkbox's box size hidpi scale-able. Making the size not only anchored to icon size, but also the menuItem's rect height in empty or too small icon cases. 2. Make the checkmark's pen width in propotion to the box's size to keep consistent visual effects among different dpi settings 3. Also make the radio button hidpi scale-able. Task-number: QTBUG-63576 Change-Id: I4369aaa18ee68908a26a118cf04292ee4c3e9847 Reviewed-by: Richard Moe Gustavsen --- src/widgets/styles/qfusionstyle.cpp | 30 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 774eca10189..0b56c1e3a80 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -786,7 +786,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect); QColor checkMarkColor = option->palette.text().color().darker(120); - const int checkMarkPadding = QStyleHelper::dpiScaled(3); + const int checkMarkPadding = 1 + rect.width() * 0.2; // at least one pixel padding if (checkbox->state & State_NoChange) { gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()); @@ -800,18 +800,20 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); } else if (checkbox->state & (State_On)) { - QPen checkPen = QPen(checkMarkColor, QStyleHelper::dpiScaled(1.8)); + qreal penWidth = QStyleHelper::dpiScaled(1.8); + penWidth = qMax(penWidth , 0.18 * rect.height()); + penWidth = qMin(penWidth , 0.30 * rect.height()); + QPen checkPen = QPen(checkMarkColor, penWidth); checkMarkColor.setAlpha(210); - painter->translate(-1, 0.5); + painter->translate(-0.8, 0.5); painter->setPen(checkPen); painter->setBrush(Qt::NoBrush); - painter->translate(0.2, 0.0); // Draw checkmark QPainterPath path; - path.moveTo(2 + checkMarkPadding, rect.height() / 2.0); + path.moveTo(1.33 * checkMarkPadding, rect.height() / 2.0); path.lineTo(rect.width() / 2.0, rect.height() - checkMarkPadding); - path.lineTo(rect.width() - checkMarkPadding - 0.5, checkMarkPadding); + path.lineTo(rect.width() - checkMarkPadding * 0.92, checkMarkPadding); painter->drawPath(path.translated(rect.topLeft())); } } @@ -1580,8 +1582,9 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio bool enabled = menuItem->state & State_Enabled; bool ignoreCheckMark = false; - int checkcol = qMax(menuItem->maxIconWidth, 20); - + const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1; + int checkcol = qMax(menuItem->rect.height() * 0.7, + qMax(menuItem->maxIconWidth * 1.0, dpiScaled(17))); // icon checkbox's highlihgt column width if ( #if QT_CONFIG(combobox) qobject_cast(widget) || @@ -1591,7 +1594,9 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio if (!ignoreCheckMark) { // Check - QRect checkRect(option->rect.left() + 7, option->rect.center().y() - 6, 14, 14); + const int boxMargin = dpiScaled(4); + const int boxWidth = checkcol - 2 * boxMargin; + QRect checkRect(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth); checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); if (checkable) { if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { @@ -1603,7 +1608,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QPalette::ColorRole textRole = !enabled ? QPalette::Text: selected ? QPalette::HighlightedText : QPalette::ButtonText; painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole)); - painter->drawEllipse(checkRect.adjusted(4, 4, -4, -4)); + const int adjustment = checkRect.height() * 0.3; + painter->drawEllipse(checkRect.adjusted(adjustment, adjustment, -adjustment, -adjustment)); } } else { // Check box @@ -1632,7 +1638,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio QPainter *p = painter; QRect vCheckRect = visualRect(opt->direction, menuitem->rect, - QRect(menuitem->rect.x() + 4, menuitem->rect.y(), + QRect(menuitem->rect.x() + checkColHOffset, menuitem->rect.y(), checkcol, menuitem->rect.height())); if (!menuItem->icon.isNull()) { QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; @@ -1683,7 +1689,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio discol = menuitem->palette.text().color(); p->setPen(discol); } - int xm = windowsItemFrame + checkcol + windowsItemHMargin + 2; + int xm = checkColHOffset + checkcol + windowsItemHMargin; int xpos = menuitem->rect.x() + xm; QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); From 29104c85db53e7c0c0aaf3fe78f84b737fce4886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 17 Nov 2017 12:28:55 +0100 Subject: [PATCH 025/102] =?UTF-8?q?Cocoa:=20Disable=20=E2=80=9CHide?= =?UTF-8?q?=E2=80=9D=20menu=20item=20on=20open=20popups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow native behavior and disable ⌘H and the “Hide” menu item if there are any open popup windows. Task-number: QTBUG-58727 Change-Id: Iad38cc5cce29e0081613417c53b154ae0f05857e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 0d9bb5009d9..b986833f6de 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -43,6 +43,7 @@ #include "qcocoahelpers.h" #include "qcocoamenubar.h" #include "qcocoamenuitem.h" +#include "qcocoaintegration.h" #include #include @@ -343,10 +344,13 @@ - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { - if ([menuItem action] == @selector(hide:) - || [menuItem action] == @selector(hideOtherApplications:) + if ([menuItem action] == @selector(hideOtherApplications:) || [menuItem action] == @selector(unhideAllApplications:)) { return [NSApp validateMenuItem:menuItem]; + } else if ([menuItem action] == @selector(hide:)) { + if (QCocoaIntegration::instance()->activePopupWindow()) + return NO; + return [NSApp validateMenuItem:menuItem]; } else if ([menuItem tag]) { QCocoaMenuItem *cocoaItem = reinterpret_cast([menuItem tag]); return cocoaItem->isEnabled(); From b8a6e2b6e8e4b5ea0734285f485c03c22022c30e Mon Sep 17 00:00:00 2001 From: Dongmei Wang Date: Fri, 18 Aug 2017 11:24:13 -0700 Subject: [PATCH 026/102] QColor: write signed 64-bit integer in a platform-independent way MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building Qt 5.6.2 with gcc 4.1.2 on Fedora 8, a compilation error happened when compiling the code below QColor::name() { ... case HexArgb: return QLatin1Char('#') + QString::number(rgba() | 0x100000000, 16).rightRef(8); ... } qtbase/src/gui/painting/qcolor.cpp:527: error: integer constant is too large for ‘long’ type gcc 4.1.2 was unable to handle 0x100000000. The patch is to use Q_INT64_C to append "LL" to 0x100000000 to avoid the compilation error. Change-Id: I000e65a5c897ef2d78fcfe4e212d832eb488a762 Reviewed-by: Gabriel de Dietrich --- src/gui/painting/qcolor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 9e1785c11d1..6e0e348a67f 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -853,7 +853,7 @@ QString QColor::name(NameFormat format) const return QLatin1Char('#') + QString::number(rgba() | 0x1000000, 16).rightRef(6); case HexArgb: // it's called rgba() but it does return AARRGGBB - return QLatin1Char('#') + QString::number(rgba() | 0x100000000, 16).rightRef(8); + return QLatin1Char('#') + QString::number(rgba() | Q_INT64_C(0x100000000), 16).rightRef(8); } return QString(); } From 77687bc64e9ae7172586271de91b266be7ab19ce Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 29 Aug 2017 09:02:31 +0200 Subject: [PATCH 027/102] QFileSystemModel::index(): Add a list size check This prevents an out of range assert when monitoring directory with activity (for example, temp). Task-number: QTBUG-62841 Change-Id: Id3aa4098e9bbd665c7b17a667516885fa7c7f473 Reviewed-by: Jesus Fernandez Reviewed-by: Martin Rotter Reviewed-by: Richard Moe Gustavsen --- src/widgets/dialogs/qfilesystemmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index bf14b5c6fd5..179c5861c9b 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -260,7 +260,10 @@ QModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &pare Q_ASSERT(parentNode); // now get the internal pointer for the index - const QString &childName = parentNode->visibleChildren.at(d->translateVisibleLocation(parentNode, row)); + const int i = d->translateVisibleLocation(parentNode, row); + if (i >= parentNode->visibleChildren.size()) + return QModelIndex(); + const QString &childName = parentNode->visibleChildren.at(i); const QFileSystemModelPrivate::QFileSystemNode *indexNode = parentNode->children.value(childName); Q_ASSERT(indexNode); From ff7dbda3b0eaedf857de3913c2be2f880909ee82 Mon Sep 17 00:00:00 2001 From: Dongmei Wang Date: Fri, 18 Aug 2017 11:32:25 -0700 Subject: [PATCH 028/102] xcb_qpa_lib: Fix "undefined reference to `dlsym'" error Change-Id: I37515542571ef37f4361e72b8db4547ff1e1b86a Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/xcb/xcb_qpa_lib.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 284711075ea..55007b43a73 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -85,4 +85,6 @@ include(gl_integrations/gl_integrations.pri) QMAKE_USE += xkbcommon } +qtConfig(dlopen): QMAKE_USE += libdl + load(qt_module) From 637e8ebcc3c2394d01827043d1a410866234fd0c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 28 Nov 2017 13:35:58 -0800 Subject: [PATCH 029/102] tst_QUdpSocket: Don't test for .bytesAvailable on untrusted platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FreeBSD, for example, does not have SO_NREAD and its FIONREAD returns the full socket buffer size, including IP and UDP headers. Change-Id: Ifb5969bf206e4cd7b14efffd14fb5d8ca778d16a Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim --- .../network/socket/qudpsocket/tst_qudpsocket.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 0f46caa7c29..aa71f7e94d5 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -60,6 +60,13 @@ #include #endif +#ifdef Q_OS_UNIX +# include +#endif +#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(SO_NREAD) +# define RELIABLE_BYTES_AVAILABLE +#endif + Q_DECLARE_METATYPE(QHostAddress) QT_FORWARD_DECLARE_CLASS(QUdpSocket) @@ -1806,7 +1813,9 @@ void tst_QUdpSocket::readyRead() // make sure only one signal was emitted QCOMPARE(spy.count(), 1); QVERIFY(receiver.hasPendingDatagrams()); +#ifdef RELIABLE_BYTES_AVAILABLE QCOMPARE(receiver.bytesAvailable(), qint64(2)); +#endif QCOMPARE(receiver.pendingDatagramSize(), qint64(2)); // write another datagram @@ -1828,7 +1837,9 @@ void tst_QUdpSocket::readyRead() QTest::qWait(100); QCOMPARE(spy.count(), 2); QVERIFY(receiver.hasPendingDatagrams()); +#ifdef RELIABLE_BYTES_AVAILABLE QCOMPARE(receiver.bytesAvailable(), qint64(3)); +#endif QCOMPARE(receiver.pendingDatagramSize(), qint64(3)); } @@ -1860,7 +1871,9 @@ void tst_QUdpSocket::readyReadForEmptyDatagram() char buf[1]; QVERIFY(receiver.hasPendingDatagrams()); QCOMPARE(receiver.pendingDatagramSize(), qint64(0)); +#ifdef RELIABLE_BYTES_AVAILABLE QCOMPARE(receiver.bytesAvailable(), qint64(0)); +#endif QCOMPARE(receiver.readDatagram(buf, sizeof buf), qint64(0)); } @@ -1869,7 +1882,9 @@ void tst_QUdpSocket::async_readDatagramSlot() char buf[1]; QVERIFY(m_asyncReceiver->hasPendingDatagrams()); QCOMPARE(m_asyncReceiver->pendingDatagramSize(), qint64(1)); +#ifdef RELIABLE_BYTES_AVAILABLE QCOMPARE(m_asyncReceiver->bytesAvailable(), qint64(1)); +#endif QCOMPARE(m_asyncReceiver->readDatagram(buf, sizeof(buf)), qint64(1)); if (buf[0] == '2') { From 81a88639acf8e7dfe4312733635c138abe51b828 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 28 Nov 2017 14:59:12 -0800 Subject: [PATCH 030/102] tst_QUdpSocket: fix linkLocalIPv4 test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I broke it in commit 4da2dda2aa1f710177157dc1cf841e0bf0b9d829. It wasn't flaky or anything: it was plain broken and would never pass. That indicates no node in the CI has an IPv4 link-local address (and apparently neither did I at the time). Change-Id: Ifb5969bf206e4cd7b14efffd14fb62176546916e Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim --- tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index aa71f7e94d5..5c5dfc881d3 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -1723,7 +1723,7 @@ void tst_QUdpSocket::linkLocalIPv4() foreach (QNetworkAddressEntry addr, iface.addressEntries()) { if (addr.ip().isInSubnet(localMask, 16)) { addresses << addr.ip(); - qDebug() << addr.ip(); + qDebug() << "Found IPv4 link local address" << addr.ip(); } } } @@ -1748,7 +1748,6 @@ void tst_QUdpSocket::linkLocalIPv4() QVERIFY(s->writeDatagram(testData, s->localAddress(), neutral.localPort())); QVERIFY2(neutral.waitForReadyRead(10000), QtNetworkSettings::msgSocketError(neutral).constData()); - QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData()); QNetworkDatagram dgram = neutral.receiveDatagram(testData.length() * 2); QVERIFY(dgram.isValid()); QCOMPARE(dgram.senderAddress(), s->localAddress()); @@ -1771,7 +1770,7 @@ void tst_QUdpSocket::linkLocalIPv4() } QVERIFY(neutral.writeDatagram(dgram.makeReply(testData))); - + QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData()); dgram = s->receiveDatagram(testData.length() * 2); QVERIFY(dgram.isValid()); QCOMPARE(dgram.data(), testData); From 87efdd8c7f997e16ff5a35a44dce9b967d23f09b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 5 Dec 2017 13:45:13 +0100 Subject: [PATCH 031/102] Android: Reserve space for the QVarLengthArray, so we can use append MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the QVarLengthArray was initialized with a size then append would add to the end of that. Therefore we need to use reserve to get the desired effect. Task-number: QTBUG-64905 Change-Id: Ia1ebeb26cd31bc5e92bd7f81079506a266b845bf Reviewed-by: Jan Arve Sæther --- src/plugins/platforms/android/androidjniaccessibility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index a3bc58bb89c..309e41bfd6f 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -106,7 +106,8 @@ namespace QtAndroidAccessibility QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { const int childCount = iface->childCount(); - QVarLengthArray ifaceIdArray(childCount); + QVarLengthArray ifaceIdArray; + ifaceIdArray.reserve(childCount); for (int i = 0; i < childCount; ++i) { QAccessibleInterface *child = iface->child(i); if (child && child->isValid()) From 58a409c6dce920feb5c746a9319d0e0f1d02a233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 19:30:12 +0100 Subject: [PATCH 032/102] iOS: Implement QPlatformScreen::name for easier debugging Change-Id: I077bec93fe2086c38ebe986b322977a50a1ab27d Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.h | 2 ++ src/plugins/platforms/ios/qiosscreen.mm | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 9fcce428257..7f10b084928 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -56,6 +56,8 @@ public: QIOSScreen(UIScreen *screen); ~QIOSScreen(); + QString name() const override; + QRect geometry() const Q_DECL_OVERRIDE; QRect availableGeometry() const Q_DECL_OVERRIDE; int depth() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 1a7004c2494..67970ba59ed 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -280,6 +280,16 @@ QIOSScreen::~QIOSScreen() [m_uiWindow release]; } +QString QIOSScreen::name() const +{ + if (m_uiScreen == [UIScreen mainScreen]) { + return QString::fromNSString([UIDevice currentDevice].model) + + QLatin1String(" built-in display"); + } else { + return QLatin1String("External display"); + } +} + void QIOSScreen::updateProperties() { QRect previousGeometry = m_geometry; From 77942a1bdf9fe22d8f076e59ce19fe9a9d7870d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 18:09:50 +0100 Subject: [PATCH 033/102] iOS: Try to detect and deal with delayed touch delivery due to gestures A UIGestureRecognizer may have its delaysTouchesBegan or delaysTouchesEnded properties set, which causes iOS to not deliver touch events to the view until the recognizer has failed recognition of its gesture. In that case, the touch event is not delivered via [UIWindow sendEvent:] as usual, but via _UIGestureEnvironmentSortAndSendDelayedTouches. The latter function is apparently not reentrant, as opening a native alert dialog in response to the touch delivery will result in the dialogs's buttons to stop working, probably because they themselves use gestures. Unfortunately iOS maintains two internal gesture recognizers on iPad, of type _UISystemGestureGateGestureRecognizer, probably related to the swipe-from-bottom gesture used for multitasking. Without any workaround, these two recognizers will result in any tap on the bottom part of the screen to be delivered delayed, which may introduce stuck alert dialogs as described above. UITouch has a gestureRecognizers property, but unfortunately this property does not give us any information in the cases where we need it, so we have to use an heuristic involving a UIWindow subclass to detect the case where event delivery is delayed. As there is no way to prevent the user from recursing into an event loop when delivering the event, our only hope is to deliver the event asynchronously. Task-number: QTBUG-64577 Change-Id: I11d9caa8c4542dc80426a9e58ea555914bed433e Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.h | 4 ++++ src/plugins/platforms/ios/qiosscreen.mm | 22 +++++++++++++++++++++- src/plugins/platforms/ios/quiview.mm | 17 ++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 7f10b084928..d63fa29ec31 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -46,6 +46,10 @@ @class QIOSOrientationListener; +@interface QUIWindow : UIWindow +@property (nonatomic, readonly) BOOL sendingEvent; +@end + QT_BEGIN_NAMESPACE class QIOSScreen : public QObject, public QPlatformScreen diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 67970ba59ed..0d3826fc4ce 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -192,6 +192,26 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) // ------------------------------------------------------------------------- +@implementation QUIWindow + +- (id)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) + self->_sendingEvent = NO; + + return self; +} + +- (void)sendEvent:(UIEvent *)event +{ + QScopedValueRollback(self->_sendingEvent, YES); + [super sendEvent:event]; +} + +@end + +// ------------------------------------------------------------------------- + QT_BEGIN_NAMESPACE /*! @@ -261,7 +281,7 @@ QIOSScreen::QIOSScreen(UIScreen *screen) if (!m_uiWindow) { // Create a window and associated view-controller that we can use - m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]]; + m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]]; m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 79f9d6871a6..1dbacad6e73 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -43,6 +43,7 @@ #include "qiosintegration.h" #include "qiosviewcontroller.h" #include "qiostextresponder.h" +#include "qiosscreen.h" #include "qioswindow.h" #ifndef Q_OS_TVOS #include "qiosmenu.h" @@ -359,7 +360,21 @@ - (void)sendTouchEventWithTimestamp:(ulong)timeStamp { QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + if (!static_cast(self.window).sendingEvent) { + // The event is likely delivered as part of delayed touch delivery, via + // _UIGestureEnvironmentSortAndSendDelayedTouches, due to one of the two + // _UISystemGestureGateGestureRecognizer instances on the top level window + // having its delaysTouchesBegan set to YES. During this delivery, it's not + // safe to spin up a recursive event loop, as our calling function is not + // reentrant, so any gestures used by the recursive code, e.g. a native + // alert dialog, will fail to recognize. To be on the safe side, we deliver + // the event asynchronously. + QWindowSystemInterface::handleTouchEvent( + m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + } else { + QWindowSystemInterface::handleTouchEvent( + m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event From e37c9d5d5f4ba9874808a4e565c36b2953eb96da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 4 Dec 2017 14:41:36 +0100 Subject: [PATCH 034/102] iOS: Harden application state change logic Make sure we catch application state changes as early as possible, and deal properly with any changes delivered before we have an app to send them to. Change-Id: I6d0ea0398f9fab88fc182342769b075cb144227f Reviewed-by: Richard Moe Gustavsen --- .../platforms/ios/qiosapplicationstate.h | 18 +-- .../platforms/ios/qiosapplicationstate.mm | 110 +++++++++--------- src/plugins/platforms/ios/qiosintegration.h | 3 +- 3 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/plugins/platforms/ios/qiosapplicationstate.h b/src/plugins/platforms/ios/qiosapplicationstate.h index 1c77b26da12..a68147a72a9 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.h +++ b/src/plugins/platforms/ios/qiosapplicationstate.h @@ -40,20 +40,24 @@ #ifndef QIOSAPPLICATIONSTATE_H #define QIOSAPPLICATIONSTATE_H -#include -#include +#include -Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); +#include QT_BEGIN_NAMESPACE -class QIOSApplicationState +class QIOSApplicationState : public QObject { + Q_OBJECT public: QIOSApplicationState(); - ~QIOSApplicationState(); -private: - QVector m_observers; + + static void handleApplicationStateChanged(UIApplicationState state, const QString &reason); + static Qt::ApplicationState toQtApplicationState(UIApplicationState state); + +Q_SIGNALS: + void applicationStateWillChange(Qt::ApplicationState); + void applicationStateDidChange(Qt::ApplicationState); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index 7c8e1f9927c..fed09999b57 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -40,82 +40,76 @@ #include "qiosapplicationstate.h" #include "qiosglobal.h" +#include "qiosintegration.h" #include #include #include -#import - -static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationState) -{ - switch (uiApplicationState) { - case UIApplicationStateActive: - // The application is visible in front, and receiving events - return Qt::ApplicationActive; - case UIApplicationStateInactive: - // The app is running in the foreground but is not receiving events. This - // typically happens while transitioning to/from active/background, like - // upon app launch or when receiving incoming calls. - return Qt::ApplicationInactive; - case UIApplicationStateBackground: - // Normally the app would enter this state briefly before it gets - // suspeded (you have five seconds, according to Apple). - // You can request more time and start a background task, which would - // normally map closer to Qt::ApplicationHidden. But since we have no - // API for doing that yet, we handle this state as "about to be suspended". - // Note: A screen-shot for the SpringBoard will also be taken after this - // call returns. - return Qt::ApplicationSuspended; - } -} - -static void handleApplicationStateChanged(UIApplicationState uiApplicationState) -{ - Qt::ApplicationState state = qtApplicationState(uiApplicationState); - qCDebug(lcQpaApplication) << "moved to" << state; - QWindowSystemInterface::handleApplicationStateChanged(state); -} - QT_BEGIN_NAMESPACE -QIOSApplicationState::QIOSApplicationState() +static void qRegisterApplicationStateNotifications() { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; - m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidBecomeActiveNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - handleApplicationStateChanged(UIApplicationStateActive); - } - ]); + // Map between notifications and corresponding application state. Note that + // there's no separate notification for moving to UIApplicationStateInactive, + // so we use UIApplicationWillResignActiveNotification as an intermediate. + static QMap notifications { + { UIApplicationDidBecomeActiveNotification, UIApplicationStateActive }, + { UIApplicationWillResignActiveNotification, UIApplicationStateInactive }, + { UIApplicationDidEnterBackgroundNotification, UIApplicationStateBackground }, + }; - m_observers.push_back([notificationCenter addObserverForName:UIApplicationWillResignActiveNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - // Note: UIApplication is still UIApplicationStateActive at this point, - // but since there is no separate notification for the inactive state, - // we report UIApplicationStateInactive now. - handleApplicationStateChanged(UIApplicationStateInactive); - } - ]); - - m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification - object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { - handleApplicationStateChanged(UIApplicationStateBackground); - } - ]); + for (auto i = notifications.constBegin(); i != notifications.constEnd(); ++i) { + [notificationCenter addObserverForName:i.key() object:nil queue:mainQueue + usingBlock:^void(NSNotification *notification) { + NSRange nameRange = NSMakeRange(2, notification.name.length - 14); + QString reason = QString::fromNSString([notification.name substringWithRange:nameRange]); + QIOSApplicationState::handleApplicationStateChanged(i.value(), reason); + }]; + } // Initialize correct startup state, which may not be the Qt default (inactive) UIApplicationState startupState = [UIApplication sharedApplication].applicationState; - QGuiApplicationPrivate::applicationState = qtApplicationState(startupState); + QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application loaded")); +} +Q_CONSTRUCTOR_FUNCTION(qRegisterApplicationStateNotifications) + +QIOSApplicationState::QIOSApplicationState() +{ + UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application launched")); } -QIOSApplicationState::~QIOSApplicationState() +void QIOSApplicationState::handleApplicationStateChanged(UIApplicationState uiState, const QString &reason) { - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - foreach (const NSObject* observer, m_observers) - [notificationCenter removeObserver:observer]; + Qt::ApplicationState state = toQtApplicationState(uiState); + qCDebug(lcQpaApplication) << qPrintable(reason) + << "- moving from" << QGuiApplication::applicationState() << "to" << state; + + if (QIOSIntegration *integration = QIOSIntegration::instance()) { + emit integration->applicationState.applicationStateWillChange(state); + QWindowSystemInterface::handleApplicationStateChanged(state); + emit integration->applicationState.applicationStateDidChange(state); + qCDebug(lcQpaApplication) << "done moving to" << state; + } else { + qCDebug(lcQpaApplication) << "no platform integration yet, setting state directly"; + QGuiApplicationPrivate::applicationState = state; + } } +Qt::ApplicationState QIOSApplicationState::toQtApplicationState(UIApplicationState state) +{ + switch (state) { + case UIApplicationStateActive: return Qt::ApplicationActive; + case UIApplicationStateInactive: return Qt::ApplicationInactive; + case UIApplicationStateBackground: return Qt::ApplicationSuspended; + } +} + +#include "moc_qiosapplicationstate.cpp" + QT_END_NAMESPACE - diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index 54c1a1dcb71..1d537340961 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -109,6 +109,8 @@ public: QFactoryLoader *optionalPlugins() { return m_optionalPlugins; } + QIOSApplicationState applicationState; + private: QPlatformFontDatabase *m_fontDatabase; #ifndef Q_OS_TVOS @@ -116,7 +118,6 @@ private: #endif QPlatformInputContext *m_inputContext; QTouchDevice *m_touchDevice; - QIOSApplicationState m_applicationState; QIOSServices *m_platformServices; mutable QPlatformAccessibility *m_accessibility; QFactoryLoader *m_optionalPlugins; From 933497bace2ddfd9920100ccf155658cd2030c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Nov 2017 16:46:41 +0100 Subject: [PATCH 035/102] iOS: Ignore view layouts while in the background Despite the OpenGL ES Programming Guide telling us to avoid all use of OpenGL while in the background, iOS will perform its view snapshotting for the app switcher after the application has been backgrounded; once for each orientation. Presumably the expectation is that no rendering needs to be done to provide an alternate orientation snapshot, just relayouting of views. But in our case, or any non-stretchable content case such as a OpenGL based game, this is not true. Instead of continuing layout, which will send potentially expensive geometry changes (with isExposed false, since we're in the background), we short-circuit the snapshotting. iOS will still use the latest rendered frame to create the application switcher thumbnail, but it will be based on the last active orientation of the application. To ensure that we pick up the right geometry when rotating the device while the app is in the background, we treat applicationWillEnterForeground as Qt::ApplicationInactive, which matches the recommendations of the OpenGL ES Programming Guide to "re-create any objects and restart your animation timers". Change-Id: Ia9c27f85f996ecf30284c825b43447aa7099224e Reviewed-by: Richard Moe Gustavsen --- .../platforms/ios/qiosapplicationstate.mm | 1 + .../platforms/ios/qiosviewcontroller.mm | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index fed09999b57..3407aebf8f8 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -58,6 +58,7 @@ static void qRegisterApplicationStateNotifications() // there's no separate notification for moving to UIApplicationStateInactive, // so we use UIApplicationWillResignActiveNotification as an intermediate. static QMap notifications { + { UIApplicationWillEnterForegroundNotification, UIApplicationStateInactive }, { UIApplicationDidBecomeActiveNotification, UIApplicationStateActive }, { UIApplicationWillResignActiveNotification, UIApplicationStateInactive }, { UIApplicationDidEnterBackgroundNotification, UIApplicationStateBackground }, diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index c47b6d68b1d..a9fdfaf9f13 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -157,6 +157,26 @@ - (void)layoutSubviews { + if (QGuiApplication::applicationState() == Qt::ApplicationSuspended) { + // Despite the OpenGL ES Programming Guide telling us to avoid all + // use of OpenGL while in the background, iOS will perform its view + // snapshotting for the app switcher after the application has been + // backgrounded; once for each orientation. Presumably the expectation + // is that no rendering needs to be done to provide an alternate + // orientation snapshot, just relayouting of views. But in our case, + // or any non-stretchable content case such as a OpenGL based game, + // this is not true. Instead of continuing layout, which will send + // potentially expensive geometry changes (with isExposed false, + // since we're in the background), we short-circuit the snapshotting + // here. iOS will still use the latest rendered frame to create the + // application switcher thumbnail, but it will be based on the last + // active orientation of the application. + QIOSScreen *screen = self.qtViewController->m_screen; + qCDebug(lcQpaWindow) << "ignoring layout of subviews while suspended," + << "likely system snapshot of" << screen->screen()->primaryOrientation(); + return; + } + for (int i = int(self.subviews.count) - 1; i >= 0; --i) { UIView *view = static_cast([self.subviews objectAtIndex:i]); if (![view isKindOfClass:[QUIView class]]) From a73de7ce2dde1128a14e968bcdd6c17b3d2d17f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 20 Nov 2017 12:04:50 +0100 Subject: [PATCH 036/102] iOS: Harden logic for when it's safe to use the graphics hardware To fix QTBUG-52493 we tied the exposed state of a window to the application being in the foreground. This has the result of a visible flash of black between hiding the launch screen and showing the first frame of the application, as the application is still waiting for UIApplicationStateActive to begin rendering, which happens after iOS hides the launch screen. According to the iOS OpenGL ES Programming Guide, it should be safe to render GL in UIApplicationStateInactive as well, and even in UIApplicationStateBackground, as long as the rendering finishes before the UIApplicationDidEnterBackgroundNotification returns. To ensure that we catch any bugs in this area, checks have been added that verify that no rendering happens while in the background state. Task-number: QTBUG-63229 Task-number: QTBUG-52493 Task-number: QTBUG-55205 Change-Id: Ib42bedbeddd7479ab0fb5e5b7de9f5805658e111 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qopenglcontext.cpp | 4 +- src/plugins/platforms/ios/qioscontext.h | 1 + src/plugins/platforms/ios/qioscontext.mm | 66 ++++++++++++++++++++---- src/plugins/platforms/ios/qioswindow.mm | 2 +- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index cd6f011fcb7..ad5e0b518d9 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -937,7 +937,9 @@ GLuint QOpenGLContext::defaultFramebufferObject() const /*! Makes the context current in the current thread, against the given - \a surface. Returns \c true if successful. + \a surface. Returns \c true if successful; otherwise returns \c false. + The latter may happen if the surface is not exposed, or the graphics + hardware is not available due to e.g. the application being suspended. If \a surface is 0 this is equivalent to calling doneCurrent(). diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index 5b7917f7b45..ce50eff1d95 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -87,6 +87,7 @@ private: bool isComplete; }; + static bool verifyGraphicsHardwareAvailability(); static void deleteBuffers(const FramebufferObject &framebufferObject); FramebufferObject &backingFramebufferObjectFor(QPlatformSurface *) const; diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 6a6cbb43247..03643c19a94 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -38,10 +38,13 @@ ****************************************************************************/ #include "qioscontext.h" + +#include "qiosintegration.h" #include "qioswindow.h" #include +#include #include #import @@ -136,6 +139,9 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return false; + [EAGLContext setCurrentContext:m_eaglContext]; // For offscreen surfaces we don't prepare a default FBO @@ -214,18 +220,12 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface) { Q_ASSERT_IS_GL_SURFACE(surface); + if (!verifyGraphicsHardwareAvailability()) + return; + if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - // When using threaded rendering, the render-thread may not have picked up - // yet on the fact that a window is no longer exposed, and will try to swap - // a non-exposed window. This may in some cases result in crashes, e.g. when - // iOS is suspending an application, so we have an extra guard here. - if (!static_cast(surface)->isExposed()) { - qCDebug(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush"); - return; - } - FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); Q_ASSERT_X(framebufferObject.isComplete, "QIOSContext", "swapBuffers on incomplete FBO"); @@ -287,6 +287,54 @@ bool QIOSContext::needsRenderbufferResize(QPlatformSurface *surface) const return false; } +bool QIOSContext::verifyGraphicsHardwareAvailability() +{ + // Per the iOS OpenGL ES Programming Guide, background apps may not execute commands on the + // graphics hardware. Specifically: "In your app delegate’s applicationDidEnterBackground: + // method, your app may want to delete some of its OpenGL ES objects to make memory and + // resources available to the foreground app. Call the glFinish function to ensure that + // the resources are removed immediately. After your app exits its applicationDidEnterBackground: + // method, it must not make any new OpenGL ES calls. If it makes an OpenGL ES call, it is + // terminated by iOS.". + static bool applicationBackgrounded = QGuiApplication::applicationState() == Qt::ApplicationSuspended; + + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState; + connect(applicationState, &QIOSApplicationState::applicationStateWillChange, [](Qt::ApplicationState state) { + if (applicationBackgrounded && state != Qt::ApplicationSuspended) { + qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled"; + applicationBackgrounded = false; + } + }); + connect(applicationState, &QIOSApplicationState::applicationStateDidChange, [](Qt::ApplicationState state) { + if (state != Qt::ApplicationSuspended) + return; + + qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled"; + applicationBackgrounded = true; + + // By the time we receive this signal the application has moved into + // Qt::ApplactionStateSuspended, and all windows have been obscured, + // which should stop all rendering. If there's still an active GL context, + // we follow Apple's advice and call glFinish before making it inactive. + if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) { + qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext; + glFinish(); + currentContext->doneCurrent(); + } + }); + }); + + if (applicationBackgrounded) { + static const char warning[] = "OpenGL ES calls are not allowed while an application is backgrounded"; + Q_ASSERT_X(!applicationBackgrounded, "QIOSContext", warning); + qCWarning(lcQpaGLContext, warning); + } + + return !applicationBackgrounded; +} + void QIOSContext::windowDestroyed(QObject *object) { QIOSWindow *window = static_cast(object); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index fb161febda2..e934cb90fad 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -225,7 +225,7 @@ void QIOSWindow::applyGeometry(const QRect &rect) bool QIOSWindow::isExposed() const { - return qApp->applicationState() >= Qt::ApplicationActive + return qApp->applicationState() != Qt::ApplicationSuspended && window()->isVisible() && !window()->geometry().isEmpty(); } From dbabe27b5b6402fb7d3c984eed685d5de1ffcc73 Mon Sep 17 00:00:00 2001 From: Michael Dippold Date: Tue, 14 Nov 2017 20:43:29 -0800 Subject: [PATCH 037/102] Android: Support caps lock MetaKeyKeyListener augments the meta state of the keyboard, we need to also check the KeyEvent.getMetaState(). Task-number: QTBUG-61369 Change-Id: I07a5d7b1b741a958bc94e1f1677dc1f2256220b6 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../jar/src/org/qtproject/qt5/android/QtActivityDelegate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 0f02304f9e5..952bf049713 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -1127,7 +1127,7 @@ public class QtActivityDelegate return false; m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); - int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState)); + int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState) | event.getMetaState()); int lc = c; m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState); From f0d226e4c5ddace02640e3b41d392e84dcd2ed02 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 22 Sep 2017 00:35:24 -0700 Subject: [PATCH 038/102] Add a "shim" to allow use of Clang 5's __builtin_available everywhere This is mostly relevant for Apple platforms, where we can use the new unguarded availability warnings to guarantee that proper version checks are present when using APIs that are not necessarily available on the deployment target. Change-Id: Ie408704b2924e1220491a9ea30f0141dfa4867d9 Reviewed-by: Thiago Macieira (cherry-picked from 70422449ef892d7cc3086d88e5e9e43c771e2bc3) --- src/corelib/global/global.pri | 5 +- src/corelib/global/qglobal.cpp | 3 + src/corelib/global/qglobal_p.h | 73 +++++++++++++++++++ .../global/qoperatingsystemversion_p.h | 8 -- .../global/qoperatingsystemversion_win.cpp | 3 + .../global/qoperatingsystemversion_win_p.h | 63 ++++++++++++++++ src/tools/bootstrap/bootstrap.pro | 1 + 7 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 src/corelib/global/qoperatingsystemversion_win_p.h diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index a3c1c4d65ea..eee01341a59 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -38,7 +38,10 @@ SOURCES += \ VERSIONTAGGING_SOURCES = global/qversiontagging.cpp darwin: SOURCES += global/qoperatingsystemversion_darwin.mm -win32: SOURCES += global/qoperatingsystemversion_win.cpp +win32 { + SOURCES += global/qoperatingsystemversion_win.cpp + HEADERS += global/qoperatingsystemversion_win_p.h +} # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 8d614b4f91e..d609f6a30a0 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -47,6 +47,9 @@ #include "qdatetime.h" #include "qoperatingsystemversion.h" #include "qoperatingsystemversion_p.h" +#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINRT) +#include "qoperatingsystemversion_win_p.h" +#endif #include #include diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h index b1d28367837..5f5891bcffd 100644 --- a/src/corelib/global/qglobal_p.h +++ b/src/corelib/global/qglobal_p.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -59,5 +60,77 @@ #include #endif +#if defined(__cplusplus) +#if !QT_HAS_BUILTIN(__builtin_available) +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct qt_clang_builtin_available_os_version_data { + QOperatingSystemVersion::OSType type; + const char *version; +}; + +static inline bool qt_clang_builtin_available( + const std::initializer_list &versions) +{ + for (auto it = versions.begin(); it != versions.end(); ++it) { + if (currentType() == it->type) { + const auto current = QOperatingSystemVersion::current(); + return QVersionNumber( + current.majorVersion(), + current.minorVersion(), + current.microVersion()) >= QVersionNumber::fromString( + QString::fromLatin1(it->version)); + } + } + + // Result is true if the platform is not any of the checked ones; this matches behavior of + // LLVM __builtin_available and @available constructs + return true; +} + +QT_END_NAMESPACE + +#define QT_AVAILABLE_OS_VER(os, ver) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available_os_version_data){\ + QT_PREPEND_NAMESPACE(QOperatingSystemVersion)::os, #ver} +#define QT_AVAILABLE_CAT(L, R) QT_AVAILABLE_CAT_(L, R) +#define QT_AVAILABLE_CAT_(L, R) L ## R +#define QT_AVAILABLE_EXPAND(...) QT_AVAILABLE_OS_VER(__VA_ARGS__) +#define QT_AVAILABLE_SPLIT(os_ver) QT_AVAILABLE_EXPAND(QT_AVAILABLE_CAT(QT_AVAILABLE_SPLIT_, os_ver)) +#define QT_AVAILABLE_SPLIT_macOS MacOS, +#define QT_AVAILABLE_SPLIT_iOS IOS, +#define QT_AVAILABLE_SPLIT_tvOS TvOS, +#define QT_AVAILABLE_SPLIT_watchOS WatchOS, +#define QT_BUILTIN_AVAILABLE0(e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({}) +#define QT_BUILTIN_AVAILABLE1(a, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a)}) +#define QT_BUILTIN_AVAILABLE2(a, b, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b)}) +#define QT_BUILTIN_AVAILABLE3(a, b, c, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b), \ + QT_AVAILABLE_SPLIT(c)}) +#define QT_BUILTIN_AVAILABLE4(a, b, c, d, e) \ + QT_PREPEND_NAMESPACE(qt_clang_builtin_available)({QT_AVAILABLE_SPLIT(a), \ + QT_AVAILABLE_SPLIT(b), \ + QT_AVAILABLE_SPLIT(c), \ + QT_AVAILABLE_SPLIT(d)}) +#define QT_BUILTIN_AVAILABLE_ARG(arg0, arg1, arg2, arg3, arg4, arg5, ...) arg5 +#define QT_BUILTIN_AVAILABLE_CHOOSER(...) QT_BUILTIN_AVAILABLE_ARG(__VA_ARGS__, \ + QT_BUILTIN_AVAILABLE4, \ + QT_BUILTIN_AVAILABLE3, \ + QT_BUILTIN_AVAILABLE2, \ + QT_BUILTIN_AVAILABLE1, \ + QT_BUILTIN_AVAILABLE0, ) +#define __builtin_available(...) QT_BUILTIN_AVAILABLE_CHOOSER(__VA_ARGS__)(__VA_ARGS__) +#endif // !QT_HAS_BUILTIN(__builtin_available) +#endif // defined(__cplusplus) + #endif // QGLOBAL_P_H diff --git a/src/corelib/global/qoperatingsystemversion_p.h b/src/corelib/global/qoperatingsystemversion_p.h index 78d0daf0c61..77f19d27c52 100644 --- a/src/corelib/global/qoperatingsystemversion_p.h +++ b/src/corelib/global/qoperatingsystemversion_p.h @@ -53,16 +53,8 @@ #include "qoperatingsystemversion.h" -#ifdef Q_OS_WIN -#include -#endif - QT_BEGIN_NAMESPACE -#ifdef Q_OS_WIN -OSVERSIONINFOEX qWindowsVersionInfo(); -#endif - static inline QOperatingSystemVersion::OSType currentType() { #if defined(Q_OS_WIN) diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp index 060ca2f7da6..f3662ae1f90 100644 --- a/src/corelib/global/qoperatingsystemversion_win.cpp +++ b/src/corelib/global/qoperatingsystemversion_win.cpp @@ -37,7 +37,10 @@ ** ****************************************************************************/ +#include "qoperatingsystemversion_win_p.h" + #include "qoperatingsystemversion_p.h" + #include #include diff --git a/src/corelib/global/qoperatingsystemversion_win_p.h b/src/corelib/global/qoperatingsystemversion_win_p.h new file mode 100644 index 00000000000..446bd286fcd --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_win_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 QOPERATINGSYSTEMVERSION_WIN_P_H +#define QOPERATINGSYSTEMVERSION_WIN_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 + +QT_BEGIN_NAMESPACE + +OSVERSIONINFOEX qWindowsVersionInfo(); + +QT_END_NAMESPACE + +#endif // QOPERATINGSYSTEMVERSION_WIN_P_H diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 521dd5f0f29..50f669cd236 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -80,6 +80,7 @@ SOURCES += \ ../../corelib/tools/qstringbuilder.cpp \ ../../corelib/tools/qstring_compat.cpp \ ../../corelib/tools/qstringlist.cpp \ + ../../corelib/tools/qversionnumber.cpp \ ../../corelib/tools/qvsnprintf.cpp \ ../../corelib/xml/qxmlutils.cpp \ ../../corelib/xml/qxmlstream.cpp \ From d2d6c6f7813fa38ced6b80ead763ed6e6daaa951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lund=20Martsum?= Date: Thu, 7 Dec 2017 11:19:40 +0100 Subject: [PATCH 039/102] QWidgetResizeHandler - undo (potential) move break When the mode is center we are typically moving the dock widget, but we should however not stop if the mode is Center. Though the regression (in commit e662b4ed721ee36f0a17cc413494b7d09395d52e) is not easy to reproduce it is clear that the code later may call "mouseMoveEvent(e)" and the mode is also checked for being Center and in that case the eventfilter (function) returns true (not false). Change-Id: I3936ec56833d613f78920d9ccf8ddb66e19e9802 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qwidgetresizehandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp index 09c5e522192..8a1f26dbc22 100644 --- a/src/widgets/widgets/qwidgetresizehandler.cpp +++ b/src/widgets/widgets/qwidgetresizehandler.cpp @@ -120,7 +120,7 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee) break; const QRect widgetRect = widget->rect().marginsAdded(QMargins(range, range, range, range)); const QPoint cursorPoint = widget->mapFromGlobal(e->globalPos()); - if (!widgetRect.contains(cursorPoint) || mode == Center || mode == Nowhere) + if (!widgetRect.contains(cursorPoint) || mode == Nowhere) return false; if (e->button() == Qt::LeftButton) { #if 0 // Used to be included in Qt4 for Q_WS_X11 From 3d720f38faec4c1c600e128d5d8da5a4435ec1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Dec 2017 00:22:05 +0100 Subject: [PATCH 040/102] iOS: Implement QIOSScreen::refreshRate to account for 120Hz displays Task-number: QTBUG-64968 Change-Id: If96f6cde8f2fc6d91beb842d82a881fe057260b5 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.h | 1 + src/plugins/platforms/ios/qiosscreen.mm | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index d63fa29ec31..be0f301710a 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -69,6 +69,7 @@ public: QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; qreal devicePixelRatio() const Q_DECL_OVERRIDE; + qreal refreshRate() const override; Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 0d3826fc4ce..521495b42fc 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -459,6 +459,16 @@ qreal QIOSScreen::devicePixelRatio() const return [m_uiScreen scale]; } +qreal QIOSScreen::refreshRate() const +{ +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 100300, 110000, __WATCHOS_NA) + if (__builtin_available(iOS 10.3, tvOS 11, *)) + return m_uiScreen.maximumFramesPerSecond; +#endif + + return 60.0; +} + Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { CGRect nativeBounds = From b0f142e3533599466f15f1303b063ee35b18e4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 8 Dec 2017 02:06:31 +0100 Subject: [PATCH 041/102] iOS: Ensure that the cursor rect doesn't trigger an inverted scroll If the cursor is at the top of the screen, it may end up with a cursor rect that extends beyond the screen after we pad it. We need to make sure it's constrained by the screen geometry before checking if it's within the available geometry. Task-number: QTBUG-65041 Change-Id: I115f49d359b3c2e10219a6b8aa5ad051f44256a7 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosinputcontext.mm | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 237077400b2..050c592aca1 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -500,23 +500,25 @@ void QIOSInputContext::scrollToCursor() QWindow *focusWindow = qApp->focusWindow(); QRect cursorRect = qApp->inputMethod()->cursorRectangle().translated(focusWindow->geometry().topLeft()).toRect(); - if (cursorRect.isNull()) { - scroll(0); - return; - } - - // Add some padding so that the cusor does not end up directly above the keyboard - static const int kCursorRectPadding = 20; - cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding); // We explicitly ask for the geometry of the screen instead of the availableGeometry, - // as we hide the statusbar when scrolling the screen, so the available geometry will + // as we hide the status bar when scrolling the screen, so the available geometry will // include the space taken by the status bar at the moment. QRect screenGeometry = focusWindow->screen()->geometry(); + + if (!cursorRect.isNull()) { + // Add some padding so that the cursor does not end up directly above the keyboard + static const int kCursorRectPadding = 20; + cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding); + + // Make sure the cursor rect is still within the screen geometry after padding + cursorRect &= screenGeometry; + } + QRect keyboardGeometry = QRectF::fromCGRect(m_keyboardState.keyboardEndRect).toRect(); QRect availableGeometry = (QRegion(screenGeometry) - keyboardGeometry).boundingRect(); - if (!availableGeometry.contains(cursorRect, true)) { + if (!cursorRect.isNull() && !availableGeometry.contains(cursorRect)) { qImDebug() << "cursor rect" << cursorRect << "not fully within" << availableGeometry; int scrollToCenter = -(availableGeometry.center() - cursorRect.center()).y(); int scrollToBottom = focusWindow->screen()->geometry().bottom() - availableGeometry.bottom(); @@ -528,6 +530,8 @@ void QIOSInputContext::scrollToCursor() void QIOSInputContext::scroll(int y) { + Q_ASSERT(y >= 0); + UIView *rootView = scrollableRootView(); if (!rootView) return; From e055efb4457cd361c5b3b3caf2b236951ee1706d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 6 Dec 2017 09:06:52 +0100 Subject: [PATCH 042/102] Do not allow drag events when window is blocked by modal window Check for QWindowPrivate::blockedByModalWindow in QGuiApplicationPrivate::processDrag(). Task-number: QTBUG-46287 Change-Id: I8f43de8389f34458f9e10b37b94806b47a50d40a Reviewed-by: Gatis Paeglis Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qguiapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f43329afd06..6d37014b38e 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2868,7 +2868,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM static QPointer currentDragWindow; static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; QPlatformDrag *platformDrag = platformIntegration()->drag(); - if (!platformDrag) { + if (!platformDrag || (w && w->d_func()->blockedByModalWindow)) { lastAcceptedDropAction = Qt::IgnoreAction; return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } From eff7a5f38cd2814c57a8214dbd53bd6fd345023b Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 10 Dec 2017 18:06:05 +0100 Subject: [PATCH 043/102] QFileSystemModel: properly align file size column The file size column was not properly horizontally aligned. The model only returned Qt::AlignRight with no horizontal alignment. This lead to a top alignment within QStyle::alignedRect(). Task-number: QTBUG-64098 Change-Id: Iaef30200a63bd0975c88a67d0af2eb1d5254f588 Reviewed-by: Richard Moe Gustavsen --- src/widgets/dialogs/qfilesystemmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 179c5861c9b..7458cfdd80f 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -747,7 +747,7 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const break; case Qt::TextAlignmentRole: if (index.column() == 1) - return Qt::AlignRight; + return QVariant(Qt::AlignTrailing | Qt::AlignVCenter); break; case FilePermissions: int p = permissions(index); From 26aa20407d2e3feb97d80dabc1d922d4ef21a433 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Thu, 30 Nov 2017 21:45:32 +0100 Subject: [PATCH 044/102] QHeaderView: Fix painting vertical headers in rtl mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In rtl mode, the headers were not painted correctly. The style option selectedPosition was not filled correctly and the paint rect needed to be adjusted by one pixel to fit the table grid. Task-number: QTBUG-56520 Change-Id: Ib92d5ab6ff730bba67eca35c83cd638e613f58b9 Reviewed-by: Friedemann Kleint Reviewed-by: Thorbjørn Lund Martsum Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qheaderview.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 4e4c9572a32..9eb6c3465fb 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2319,18 +2319,20 @@ void QHeaderView::paintEvent(QPaintEvent *e) d->prepareSectionSelected(); // clear and resize the bit array QRect currentSectionRect; - int logical; const int width = d->viewport->width(); const int height = d->viewport->height(); + const int rtlHorizontalOffset = d->reverse() ? 1 : 0; for (int i = start; i <= end; ++i) { if (d->isVisualIndexHidden(i)) continue; painter.save(); - logical = logicalIndex(i); + const int logical = logicalIndex(i); if (d->orientation == Qt::Horizontal) { - currentSectionRect.setRect(sectionViewportPosition(logical), 0, sectionSize(logical), height); + currentSectionRect.setRect(sectionViewportPosition(logical) + rtlHorizontalOffset, + 0, sectionSize(logical), height); } else { - currentSectionRect.setRect(0, sectionViewportPosition(logical), width, sectionSize(logical)); + currentSectionRect.setRect(0, sectionViewportPosition(logical), + width, sectionSize(logical)); } currentSectionRect.translate(offset); @@ -2776,9 +2778,9 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical if (first && last) opt.position = QStyleOptionHeader::OnlyOneSection; else if (first) - opt.position = QStyleOptionHeader::Beginning; + opt.position = d->reverse() ? QStyleOptionHeader::End : QStyleOptionHeader::Beginning; else if (last) - opt.position = QStyleOptionHeader::End; + opt.position = d->reverse() ? QStyleOptionHeader::Beginning : QStyleOptionHeader::End; else opt.position = QStyleOptionHeader::Middle; opt.orientation = d->orientation; From 06e903cf684a829716736702b95b66846c713fd5 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sat, 9 Dec 2017 22:41:41 +0100 Subject: [PATCH 045/102] QHeaderView: Use correct font for drag'n'drop indicator pixmap QHeaderViewPrivate::setupSectionIndicator() did not honor the font set for the QHeaderView which results in a wrong font in the indicator pixmap. Fix it by using the correct font for the dragged section as it is done in paintEvent() Task-number: QTBUG-65017 Change-Id: I5393c6861073de22f30ffa13e12c5e2cf8aa7776 Reviewed-by: Friedemann Kleint Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qheaderview.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 9eb6c3465fb..0905a208124 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3159,6 +3159,15 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position) QRect rect(0, 0, w, h); QPainter painter(&pm); + const QVariant variant = model->headerData(section, orientation, + Qt::FontRole); + if (variant.isValid() && variant.canConvert()) { + const QFont sectionFont = qvariant_cast(variant); + painter.setFont(sectionFont); + } else { + painter.setFont(q->font()); + } + painter.setOpacity(0.75); q->paintSection(&painter, rect, section); painter.end(); From 495833b7965330cc1db5fdce0a3c86f7ec15e836 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Dec 2017 15:50:21 +0100 Subject: [PATCH 046/102] [ChangeLog][QPA][eglfs] Fix crash when using cursors and multiple GL contexts The hash from QOpenGLContext* to cursor texture/shader data can accumulate dangling pointers if the program uses multiple contexts on the same screen. This is fixed by moving the cursor data into the platform context. The code for deleting the texture and shader program is omitted as it is tied to the life time of the context and the GL context deletes its resources automatically upon destruction. Task-number: QTBUG-65119 Change-Id: Ic3b8e5669d14949af811bdf047e7d47000216180 Reviewed-by: Laszlo Agocs --- .../platforms/eglfs/api/qeglfscontext_p.h | 3 +++ .../platforms/eglfs/api/qeglfscursor.cpp | 15 ++++--------- .../platforms/eglfs/api/qeglfscursor_p.h | 22 +++++++++---------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h index 96f7f01381e..af8725b6b38 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h @@ -52,6 +52,7 @@ // #include "qeglfsglobal_p.h" +#include "qeglfscursor_p.h" #include #include @@ -68,6 +69,8 @@ public: void runGLChecks() override; void swapBuffers(QPlatformSurface *surface) override; + QEglFSCursorData cursorData; + private: EGLNativeWindowType m_tempWindow; }; diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp index f46206cab51..22319fcc66c 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp @@ -40,10 +40,10 @@ #include "qeglfscursor_p.h" #include "qeglfsintegration_p.h" #include "qeglfsscreen_p.h" +#include "qeglfscontext_p.h" #include #include -#include #include #include #include @@ -115,13 +115,6 @@ void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::Device void QEglFSCursor::resetResources() { - if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) { - GraphicsContextData &gfx(m_gfx[ctx]); - delete gfx.program; - glDeleteTextures(1, &gfx.customCursorTexture); - glDeleteTextures(1, &gfx.atlasTexture); - gfx = GraphicsContextData(); - } m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull(); } @@ -144,8 +137,8 @@ void QEglFSCursor::createShaderPrograms() " gl_FragColor = texture2D(texture, textureCoord).bgra;\n" "}\n"; - GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); - gfx.program = new QOpenGLShaderProgram; + QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; + gfx.program.reset(new QOpenGLShaderProgram); gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); gfx.program->bindAttributeLocation("vertexCoordEntry", 0); @@ -475,7 +468,7 @@ void QEglFSCursor::draw(const QRectF &r) { StateSaver stateSaver; - GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); + QEglFSCursorData &gfx = static_cast(QOpenGLContext::currentContext()->handle())->cursorData; if (!gfx.program) { // one time initialization initializeOpenGLFunctions(); diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h index aaeb83cb99a..89c2e89f584 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h @@ -56,6 +56,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -81,6 +82,15 @@ private: #if QT_CONFIG(opengl) +struct QEglFSCursorData { + QScopedPointer program; + int textureEntry = 0; + int matEntry = 0; + uint customCursorTexture = 0; + uint atlasTexture = 0; + qint64 customCursorKey = 0; +}; + class Q_EGLFS_EXPORT QEglFSCursor : public QPlatformCursor , protected QOpenGLFunctions { @@ -143,18 +153,6 @@ private: QEglFSCursorDeviceListener *m_deviceListener; bool m_updateRequested; QMatrix4x4 m_rotationMatrix; - - struct GraphicsContextData { - GraphicsContextData() : program(nullptr), textureEntry(0), matEntry(0), - customCursorTexture(0), atlasTexture(0), customCursorKey(0) { } - QOpenGLShaderProgram *program; - int textureEntry; - int matEntry; - uint customCursorTexture; - uint atlasTexture; - qint64 customCursorKey; - }; - QHash m_gfx; }; #endif // QT_CONFIG(opengl) From 280b8b79c0f8a75bf580c76cf61b43061b842aaa Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 28 Nov 2017 14:56:02 +0200 Subject: [PATCH 047/102] Allow the users to disable the text handles The user can set QT_QPA_NO_TEXT_HANDLES to 1 to disable the text handles. Change-Id: I974af4d79c86259288035fe20b6a9d0c6d047af8 Reviewed-by: J-P Nurmi --- src/plugins/platforms/android/qandroidinputcontext.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 7fa809f3f81..ccc7f06b6be 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -526,6 +526,10 @@ void QAndroidInputContext::updateCursorPosition() void QAndroidInputContext::updateSelectionHandles() { + static bool noHandles = qEnvironmentVariableIntValue("QT_QPA_NO_TEXT_HANDLES"); + if (noHandles) + return; + auto im = qGuiApp->inputMethod(); if (!m_focusObject || (m_cursorHandleShown == CursorHandleNotShown)) { // Hide the handles From 4a4efd5693d42a0d5ece0fb166357b0255cb205d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Nov 2017 08:46:18 +0100 Subject: [PATCH 048/102] qwindowsopengltester.cpp: Fix -Wclazy-strict-iterators Change-Id: Id22096197aa5bf406ea1f072e8b5ca2a90578eec Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowsopengltester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 5283d6b2602..a511cc61647 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -214,7 +214,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c #else QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description); SupportedRenderersCache *srCache = supportedRenderersCache(); - SupportedRenderersCache::const_iterator it = srCache->find(qgpu); + SupportedRenderersCache::const_iterator it = srCache->constFind(qgpu); if (it != srCache->cend()) return *it; From 6a5ca7240a03cce4e490b493bb6185df019e7d87 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 12 Dec 2017 13:23:38 +0100 Subject: [PATCH 049/102] Fix QEGLPbuffer::isValid() with surfaceless contexts Task-number: QTBUG-65125 Change-Id: Idcd87804ab63031e48ff2f72eb98c986bfa39f25 Reviewed-by: Andy Nichols --- src/platformsupport/eglconvenience/qeglpbuffer.cpp | 11 ++++++++--- src/platformsupport/eglconvenience/qeglpbuffer_p.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp index 67d72047349..15fc0897786 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer.cpp +++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp @@ -62,7 +62,7 @@ QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffs , m_display(display) , m_pbuffer(EGL_NO_SURFACE) { - bool hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless) + m_hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless) && q_hasEglExtension(display, "EGL_KHR_surfaceless_context"); // Disable surfaceless contexts on Mesa for now. As of 10.6.0 and Intel at least, some @@ -72,9 +72,9 @@ QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffs // read/draw surface in the Intel backend. const char *vendor = eglQueryString(display, EGL_VENDOR); // hard to check for GL_ strings here, so blacklist all Mesa if (vendor && strstr(vendor, "Mesa")) - hasSurfaceless = false; + m_hasSurfaceless = false; - if (hasSurfaceless) + if (m_hasSurfaceless) return; EGLConfig config = q_configFromGLFormat(m_display, m_format, false, EGL_PBUFFER_BIT); @@ -100,4 +100,9 @@ QEGLPbuffer::~QEGLPbuffer() eglDestroySurface(m_display, m_pbuffer); } +bool QEGLPbuffer::isValid() const +{ + return m_pbuffer != EGL_NO_SURFACE || m_hasSurfaceless; +} + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h index 38370c0e620..76233967e7e 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -64,7 +64,7 @@ public: ~QEGLPbuffer(); QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } - bool isValid() const Q_DECL_OVERRIDE { return m_pbuffer != EGL_NO_SURFACE; } + bool isValid() const Q_DECL_OVERRIDE; EGLSurface pbuffer() const { return m_pbuffer; } @@ -72,6 +72,7 @@ private: QSurfaceFormat m_format; EGLDisplay m_display; EGLSurface m_pbuffer; + bool m_hasSurfaceless; }; QT_END_NAMESPACE From 7257862fb2edfab0219d6cd45c83677049404f7d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 11 Dec 2017 16:55:02 +0100 Subject: [PATCH 050/102] Set sharedPainter correctly for QGraphicsEffect Autotest is taken from the previously reverted 8b1377fde16a2049a1c27f6d005bff84a8f85f28. Task-number: QTBUG-60231 Change-Id: I44dd79cba22b6baefdd6d95c176790bef0b7eafe Reviewed-by: Andy Nichols --- src/widgets/kernel/qwidget.cpp | 4 ++-- .../qgraphicseffect/tst_qgraphicseffect.cpp | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index de734b6f511..125f1cf246a 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5528,11 +5528,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP setSystemClip(pdev, rgn.translated(offset)); QPainter p(pdev); p.translate(offset); - context.painter = &p; + context.painter = context.sharedPainter = &p; graphicsEffect->draw(&p); setSystemClip(pdev, QRegion()); } else { - context.painter = sharedPainter; + context.painter = context.sharedPainter = sharedPainter; if (sharedPainter->worldTransform() != sourced->lastEffectTransform) { sourced->invalidateCache(); sourced->lastEffectTransform = sharedPainter->worldTransform(); diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp index a1cb7298496..dfe5baba719 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp @@ -52,6 +52,7 @@ private slots: void boundingRect2(); void draw(); void opacity(); + void nestedOpaqueOpacity(); void grayscale(); void colorize(); void drawPixmapItem(); @@ -407,6 +408,26 @@ void tst_QGraphicsEffect::opacity() QCOMPARE(effect->m_opacity, qreal(0.5)); } +void tst_QGraphicsEffect::nestedOpaqueOpacity() +{ + // QTBUG-60231: Nesting widgets with a QGraphicsEffect on a toplevel with + // QGraphicsOpacityEffect caused crashes due to constructing several + // QPainter instances on a device in the fast path for + // QGraphicsOpacityEffect::opacity=1 + QWidget topLevel; + topLevel.setWindowTitle(QTest::currentTestFunction()); + topLevel.resize(320, 200); + QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect; + opacityEffect->setOpacity(1); + topLevel.setGraphicsEffect(opacityEffect); + QWidget *child = new QWidget(&topLevel); + child->resize(topLevel.size() / 2); + QGraphicsDropShadowEffect *childEffect = new QGraphicsDropShadowEffect; + child->setGraphicsEffect(childEffect); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); +} + void tst_QGraphicsEffect::grayscale() { if (qApp->desktop()->depth() < 24) From 782eb1a114c0aaa729925899b2061d47f494435f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 11 Dec 2017 15:15:56 +0100 Subject: [PATCH 051/102] Report modifiers correctly in mouse events with evdev and libinput Task-number: QTBUG-60694 Change-Id: I7b1625e5f31e49cd2ab18a83bbd0f65f9b58088d Reviewed-by: Andy Nichols --- src/gui/kernel/qinputdevicemanager.cpp | 44 +++++++++++++++++++ src/gui/kernel/qinputdevicemanager_p.h | 3 ++ src/gui/kernel/qinputdevicemanager_p_p.h | 2 + .../evdevkeyboard/qevdevkeyboardhandler.cpp | 7 +++ .../input/libinput/qlibinputkeyboard.cpp | 6 +++ .../input/libinput/qlibinputpointer.cpp | 17 ++++--- 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp index 2d231ae26f6..37b1450d5ae 100644 --- a/src/gui/kernel/qinputdevicemanager.cpp +++ b/src/gui/kernel/qinputdevicemanager.cpp @@ -92,4 +92,48 @@ void QInputDeviceManager::setCursorPos(const QPoint &pos) emit cursorPositionChangeRequested(pos); } +/*! + \return the keyboard modifier state stored in the QInputDeviceManager object. + + Keyboard input handlers are expected to keep this up-to-date via + setKeyboardModifiers(). + + Querying the state via this function (e.g. from a mouse handler that needs + to include the modifier state in mouse events) is the preferred alternative + over QGuiApplication::keyboardModifiers() since the latter may not report + the current state due to asynchronous QPA event processing. + */ +Qt::KeyboardModifiers QInputDeviceManager::keyboardModifiers() const +{ + Q_D(const QInputDeviceManager); + return d->keyboardModifiers; +} + +void QInputDeviceManager::setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key) +{ + Q_D(QInputDeviceManager); + Qt::KeyboardModifiers mods; + switch (key) { + case Qt::Key_Shift: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ShiftModifier); + break; + case Qt::Key_Control: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::ControlModifier); + break; + case Qt::Key_Alt: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::AltModifier); + break; + case Qt::Key_Meta: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::MetaModifier); + break; + case Qt::Key_AltGr: + mods = Qt::KeyboardModifiers(modsBeforeEvent ^ Qt::GroupSwitchModifier); + break; + default: + mods = modsBeforeEvent; + break; + } + d->keyboardModifiers = mods; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h index db9d0596b6c..ddf1e6befab 100644 --- a/src/gui/kernel/qinputdevicemanager_p.h +++ b/src/gui/kernel/qinputdevicemanager_p.h @@ -78,6 +78,9 @@ public: void setCursorPos(const QPoint &pos); + Qt::KeyboardModifiers keyboardModifiers() const; + void setKeyboardModifiers(Qt::KeyboardModifiers modsBeforeEvent, int key); + signals: void deviceListChanged(QInputDeviceManager::DeviceType type); void cursorPositionChangeRequested(const QPoint &pos); diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h index ae91f3a2abf..0a91252fbc3 100644 --- a/src/gui/kernel/qinputdevicemanager_p_p.h +++ b/src/gui/kernel/qinputdevicemanager_p_p.h @@ -69,6 +69,8 @@ public: void setDeviceCount(QInputDeviceManager::DeviceType type, int count); QMap m_deviceCount; + + Qt::KeyboardModifiers keyboardModifiers; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 5c87cb7c9c2..a069a483889 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -49,6 +49,9 @@ #include #include +#include +#include + #ifdef Q_OS_FREEBSD #include #else @@ -222,6 +225,8 @@ void QEvdevKeyboardHandler::readKeycode() void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtcode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat) { + QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(modifiers, qtcode); + QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease), qtcode, modifiers, nativecode + 8, 0, int(modifiers), (unicode != 0xffff ) ? QString(unicode) : QString(), autoRepeat); @@ -403,6 +408,8 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint Qt::KeyboardModifiers qtmods = Qt::KeyboardModifiers(qtcode & modmask); qtcode &= ~modmask; + // qtmods here is the modifier state before the event, i.e. not + // including the current key in case it is a modifier. qCDebug(qLcEvdevKeyMap, "Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode, int(qtmods)); // If NumLockOff and keypad key pressed remap event sent diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index f14a2e8f048..3722c1cecad 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -40,6 +40,8 @@ #include "qlibinputkeyboard_p.h" #include #include +#include +#include #include #include #ifndef QT_NO_XKBCOMMON_EVDEV @@ -196,6 +198,8 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k); + // mods here is the modifier state before the event, i.e. not + // including the current key in case it is a modifier. Qt::KeyboardModifiers mods = Qt::NoModifier; const int qtkey = keysymToQtKey(sym, &mods, text); @@ -211,6 +215,8 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(mods, qtkey); + QWindowSystemInterface::handleExtendedKeyEvent(Q_NULLPTR, pressed ? QEvent::KeyPress : QEvent::KeyRelease, qtkey, mods, k, sym, mods, text); diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp index bdeac8db7e2..734d2fbbc03 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer.cpp +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -78,7 +80,8 @@ void QLibInputPointer::processButton(libinput_event_pointer *e) m_buttons.setFlag(button, pressed); - QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, + QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } void QLibInputPointer::processMotion(libinput_event_pointer *e) @@ -91,7 +94,8 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e) m_pos.setX(qBound(g.left(), qRound(m_pos.x() + dx), g.right())); m_pos.setY(qBound(g.top(), qRound(m_pos.y() + dy), g.bottom())); - QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, + QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } void QLibInputPointer::processAxis(libinput_event_pointer *e) @@ -100,15 +104,18 @@ void QLibInputPointer::processAxis(libinput_event_pointer *e) const double v = libinput_event_pointer_get_axis_value(e) * 120; const Qt::Orientation ori = libinput_event_pointer_get_axis(e) == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL ? Qt::Vertical : Qt::Horizontal; - QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), ori, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), ori, + QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); #else if (libinput_event_pointer_has_axis(e, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { const double v = libinput_event_pointer_get_axis_value(e, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) * 120; - QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), Qt::Vertical, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), Qt::Vertical, + QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } if (libinput_event_pointer_has_axis(e, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { const double v = libinput_event_pointer_get_axis_value(e, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) * 120; - QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), Qt::Horizontal, QGuiApplication::keyboardModifiers()); + QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), Qt::Horizontal, + QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); } #endif } From 98b7ad7682c6bf0e944fb01e17b8ea4ac78a5a7b Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Tue, 12 Dec 2017 11:34:42 +0200 Subject: [PATCH 052/102] QNX: fix slog2 for QNX7 Change the include header to sys/slog2.h, which is available in both QNX 6.6.0 and 7. Task-number: QTBUG-64033 Change-Id: I26d8c5451376bab33e11f4784ca772f84cd6fc28 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/configure.json | 2 +- src/corelib/global/qlogging.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/configure.json b/src/corelib/configure.json index a5b69a2df6f..3db9942123b 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -178,7 +178,7 @@ "slog2": { "label": "slog2", "test": { - "include": "slog2.h", + "include": "sys/slog2.h", "main": "slog2_set_default_buffer((slog2_buffer_t)-1);" }, "export": "", diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index b5ba9351940..1307118bdf3 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -61,7 +61,7 @@ #include #endif #if QT_CONFIG(slog2) -#include +#include #endif #ifdef Q_OS_ANDROID From 91996d4ec4d9f54a4506b92aa06c097a7bb965a5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 13 Dec 2017 09:25:31 +0100 Subject: [PATCH 053/102] Bump version Change-Id: I752089caa4f2a0cb91d1c4bfa2c53fe25b6bb34e Reviewed-by: Oswald Buddenhagen --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index ace04b0970a..135d1f7de14 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.9.3 +MODULE_VERSION = 5.9.4 From 27aacfb61e85a332394c7996f5c6603f07c28cd2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 11 Dec 2017 12:46:11 +0100 Subject: [PATCH 054/102] QString: fix documentation of NUL-termination of unicode(), data(), constData() (or lack thereof). * `QString::utf16()` reallocates if `*this` has been constructed using `fromRawData()`. * `QString::data()` ensures a writable string, so will detach from raw data. * `QString::unicode()`, `constData()`, and `data() const` do not. They just return `QStringData::data()`, which may point to raw, non-NUL-terminated data. These functions can therefore not possibly have the same behavior, but were documented the same. Fix. Also drop the discussion of operator[](size()), as that, too, was not correct, and anyone who indexes with op[] beyond size() - 1 should not rely on proper behavior. [ChangeLog][QtCore][QString] QString::unicode(), constData() and `data() const` do not return a NUL-terminated string. This was true before, but the documentation claimed the opposite. Change-Id: I1437f57cd02bdf80264e8559608b46aa749c23a8 Reviewed-by: Thiago Macieira --- src/corelib/doc/snippets/qstring/main.cpp | 1 - src/corelib/tools/qstring.cpp | 32 ++++++++++++++--------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp index c839c10b84f..2ea75526df2 100644 --- a/src/corelib/doc/snippets/qstring/main.cpp +++ b/src/corelib/doc/snippets/qstring/main.cpp @@ -733,7 +733,6 @@ void Widget::sizeFunction() int n = str.size(); // n == 5 str.data()[0]; // returns 'W' str.data()[4]; // returns 'd' - str.data()[5]; // returns '\0' //! [58] } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index af3d026682b..c0a03e0011e 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5138,14 +5138,9 @@ QString& QString::fill(QChar ch, int size) Returns the number of characters in this string. - The last character in the string is at position size() - 1. In - addition, QString ensures that the character at position size() - is always '\\0', so that you can use the return value of data() - and constData() as arguments to functions that expect - '\\0'-terminated strings. + The last character in the string is at position size() - 1. Example: - \snippet qstring/main.cpp 58 \sa isEmpty(), resize() @@ -5674,10 +5669,13 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, /*! \fn const QChar *QString::unicode() const - Returns a '\\0'-terminated Unicode representation of the string. + Returns a Unicode representation of the string. The result remains valid until the string is modified. - \sa utf16() + \note The returned string may not be '\\0'-terminated. + Use size() to determine the length of the array. + + \sa utf16(), fromRawData() */ /*! @@ -8077,7 +8075,10 @@ bool QString::isRightToLeft() const Returns a pointer to the data stored in the QString. The pointer can be used to access and modify the characters that compose the - string. For convenience, the data is '\\0'-terminated. + string. + + Unlike constData() and unicode(), the returned data is always + '\\0'-terminated. Example: @@ -8093,18 +8094,25 @@ bool QString::isRightToLeft() const /*! \fn const QChar *QString::data() const \overload + + \note The returned string may not be '\\0'-terminated. + Use size() to determine the length of the array. + + \sa fromRawData() */ /*! \fn const QChar *QString::constData() const Returns a pointer to the data stored in the QString. The pointer - can be used to access the characters that compose the string. For - convenience, the data is '\\0'-terminated. + can be used to access the characters that compose the string. Note that the pointer remains valid only as long as the string is not modified. - \sa data(), operator[]() + \note The returned string may not be '\\0'-terminated. + Use size() to determine the length of the array. + + \sa data(), operator[](), fromRawData() */ /*! \fn void QString::push_front(const QString &other) From 27c840f5d45747da7f4d989afba172805ce1fb51 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 13 Dec 2017 10:57:46 +0100 Subject: [PATCH 055/102] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If6111c59b958ba03f6ec5966af5cf443cae5cf9b Reviewed-by: Tor Arne Vestbø --- src/corelib/io/qloggingregistry.cpp | 4 ++-- src/corelib/io/qloggingregistry_p.h | 2 +- .../corelib/io/qloggingregistry/tst_qloggingregistry.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 1bf61017f67..b5f8e30b803 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -255,7 +255,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line) QLoggingRegistry::QLoggingRegistry() : categoryFilter(defaultCategoryFilter) { - initalizeRules(); // Init on first use + initializeRules(); // Init on first use } static bool qtLoggingDebug() @@ -284,7 +284,7 @@ static QVector loadRulesFromFile(const QString &filePath) Initializes the rules database by loading $QT_LOGGING_CONF, $QT_LOGGING_RULES, and .config/QtProject/qtlogging.ini. */ -void QLoggingRegistry::initalizeRules() +void QLoggingRegistry::initializeRules() { QVector er, qr, cr; // get rules from environment diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index a3857d35880..12a1f166b3a 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -113,7 +113,7 @@ class Q_AUTOTEST_EXPORT QLoggingRegistry public: QLoggingRegistry(); - void initalizeRules(); + void initializeRules(); void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel); void unregisterCategory(QLoggingCategory *category); diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp index 15c63d4acd1..a74ea3a89e2 100644 --- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp +++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp @@ -212,7 +212,7 @@ private slots: qunsetenv("QT_LOGGING_RULES"); qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit()); - registry.initalizeRules(); + registry.initializeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0); @@ -220,7 +220,7 @@ private slots: // check that QT_LOGGING_RULES take precedence qputenv("QT_LOGGING_RULES", "Digia.*=true"); - registry.initalizeRules(); + registry.initializeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 2); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].at(1).enabled, true); } @@ -246,7 +246,7 @@ private slots: file.close(); QLoggingRegistry registry; - registry.initalizeRules(); + registry.initializeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 1); // remove file again From 457fe3e8e2f27d773032f4406d5f933ae155e8ff Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 29 Aug 2016 09:48:28 +0200 Subject: [PATCH 056/102] ANGLE: Fix resizing of windows Use the correct height/width values when calculating the vector for resizing the window content and the new size as viewport size. Task-number: QTBUG-62475 Change-Id: I33a8dc1379a908e991b04bc31dfc6254a6d005c9 Reviewed-by: Andre de la Rocha Reviewed-by: Miguel Costa Reviewed-by: Friedemann Kleint --- .../renderer/d3d/d3d11/SwapChain11.cpp | 20 +++---- .../0016-ANGLE-Fix-resizing-of-windows.patch | 57 +++++++++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index 785a83cd770..42c336c8cf3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -707,15 +707,15 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); // Create a quad in homogeneous coordinates - float x1 = (x / float(mWidth)) * 2.0f - 1.0f; - float y1 = (y / float(mHeight)) * 2.0f - 1.0f; - float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; - float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + float x1 = (x / float(width)) * 2.0f - 1.0f; + float y1 = (y / float(height)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(width)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(height)) * 2.0f - 1.0f; - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); + float u1 = x / float(width); + float v1 = y / float(height); + float u2 = (x + width) / float(width); + float v2 = (y + height) / float(height); // Invert the quad vertices depending on the surface orientation. if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) @@ -760,8 +760,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = static_cast(mWidth); - viewport.Height = static_cast(mHeight); + viewport.Width = static_cast(width); + viewport.Height = static_cast(height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); diff --git a/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch b/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch new file mode 100644 index 00000000000..7ba92052f27 --- /dev/null +++ b/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch @@ -0,0 +1,57 @@ +From 55821d34b2208e7858dbba5648760b83c66b58a5 Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Mon, 29 Aug 2016 09:48:28 +0200 +Subject: [PATCH] ANGLE: Fix resizing of windows + +Use the correct height/width values when calculating +the vector for resizing the window content and the +new size as viewport size. + +Task-number: QTBUG-62475 +Change-Id: I33a8dc1379a908e991b04bc31dfc6254a6d005c9 +--- + .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 35 +++++++++++----------- + 1 file changed, 17 insertions(+), 18 deletions(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +index 785a83cd77..fe72bc935d 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +@@ -707,15 +706,15 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates +- float x1 = (x / float(mWidth)) * 2.0f - 1.0f; +- float y1 = (y / float(mHeight)) * 2.0f - 1.0f; +- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; +- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; ++ float x1 = (x / float(width)) * 2.0f - 1.0f; ++ float y1 = (y / float(height)) * 2.0f - 1.0f; ++ float x2 = ((x + width) / float(width)) * 2.0f - 1.0f; ++ float y2 = ((y + height) / float(height)) * 2.0f - 1.0f; + +- float u1 = x / float(mWidth); +- float v1 = y / float(mHeight); +- float u2 = (x + width) / float(mWidth); +- float v2 = (y + height) / float(mHeight); ++ float u1 = x / float(width); ++ float v1 = y / float(height); ++ float u2 = (x + width) / float(width); ++ float v2 = (y + height) / float(height); + + // Invert the quad vertices depending on the surface orientation. + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) +@@ -760,8 +759,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; +- viewport.Width = static_cast(mWidth); +- viewport.Height = static_cast(mHeight); ++ viewport.Width = static_cast(width); ++ viewport.Height = static_cast(height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); +-- +2.15.0.windows.1 + From 59febb49e45b009b740ff8b67bba30c4a285a2f2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 11 Dec 2017 11:28:11 +0100 Subject: [PATCH 057/102] Fix a bug in the generation of the Unicode joining property data The code that was supposed to initialize the joining property of characters to the correct defaults was actually applied after reading in the data from the Unicode file, and was in a couple of cases overwriting explicitly specified data in ArabicShaping.txt Task-number: QTBUG-63191 Change-Id: Ie35261039b2211a827322ca11afacd9555ccefc7 Reviewed-by: Konstantin Ritt --- src/corelib/tools/qunicodetables.cpp | 20 +++++++++---------- src/corelib/tools/qunicodetables_p.h | 4 ++-- util/unicode/main.cpp | 30 +++++++++++++++------------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp index ecab7508335..01fa8b21023 100644 --- a/src/corelib/tools/qunicodetables.cpp +++ b/src/corelib/tools/qunicodetables.cpp @@ -6083,9 +6083,9 @@ static const Properties uc_properties[] = { { 18, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 8, 13, 7 }, { 25, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 8, 12, 7 }, { 25, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 12, 0, 12, 7 }, - { 10, 5, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 3, 4, 4, 12, 8 }, - { 10, 5, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 3, 4, 4, 12, 8 }, - { 10, 5, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 3, 4, 4, 12, 2 }, + { 10, 5, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 3, 4, 4, 12, 8 }, + { 10, 5, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 3, 4, 4, 12, 8 }, + { 10, 5, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 3, 4, 4, 12, 2 }, { 26, 10, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 12, 8 }, { 26, 13, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 12, 8 }, { 25, 4, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 8 }, @@ -6146,7 +6146,7 @@ static const Properties uc_properties[] = { { 18, 13, 0, 3, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 8, 8, 12, 8 }, { 25, 13, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 6, 8 }, { 0, 17, 230, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 4, 4, 21, 8 }, - { 10, 5, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 4, 12, 2 }, + { 10, 5, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 4, 12, 2 }, { 29, 10, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 12, 8 }, { 0, 17, 220, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 4, 4, 21, 8 }, { 17, 13, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 8, 12, 8 }, @@ -6749,7 +6749,7 @@ static const Properties uc_properties[] = { { 25, 10, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 12, 6, 33 }, { 25, 10, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 12, 33 }, { 0, 17, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 4, 4, 21, 33 }, - { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 4, 4, 4, 33 }, + { 10, 18, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 4, 4, 4, 33 }, { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 14, 9, 11, 33 }, { 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 14, 9, 11, 33 }, { 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 14, 9, 11, 33 }, @@ -7058,7 +7058,7 @@ static const Properties uc_properties[] = { { 6, 9, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80, 0, 0, 5, 17, 2 }, { 6, 9, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80, 0, 0, 5, 4, 2 }, { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 4, 20, 2 }, - { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 4, 4, 21, 1 }, + { 10, 18, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 4, 4, 21, 1 }, { 10, 18, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 4, 4, 21, 1 }, { 10, 0, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 4, 21, 2 }, { 10, 1, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 4, 21, 2 }, @@ -7108,10 +7108,10 @@ static const Properties uc_properties[] = { { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 4, 4, 12, 2 }, { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 3, 4, 4, 12, 2 }, { 13, 18, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 12, 0 }, - { 10, 19, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, - { 10, 20, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, - { 10, 21, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, - { 10, 22, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, + { 10, 19, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, + { 10, 20, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, + { 10, 21, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, + { 10, 22, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 3, 4, 4, 21, 2 }, { 10, 18, 0, 5, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 4, 21, 2 }, { 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80, 0, 0, 0, 12, 2 }, { 17, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 80, 0, 8, 6, 12, 3 }, diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h index 5a422ea4eb0..be2f44f0c32 100644 --- a/src/corelib/tools/qunicodetables_p.h +++ b/src/corelib/tools/qunicodetables_p.h @@ -50,11 +50,11 @@ // We mean it. // -#include - #ifndef QUNICODETABLES_P_H #define QUNICODETABLES_P_H +#include + #include QT_BEGIN_NAMESPACE diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp index c995a403433..fe6d4fbca1a 100644 --- a/util/unicode/main.cpp +++ b/util/unicode/main.cpp @@ -1293,6 +1293,18 @@ static void readArabicShaping() { qDebug("Reading ArabicShaping.txt"); + // Initialize defaults: + // Code points that are not explicitly listed in ArabicShaping.txt are either of joining type T or U: + // - Those that not explicitly listed that are of General Category Mn, Me, or Cf have joining type T. + // - All others not explicitly listed have joining type U. + for (int codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) { + UnicodeData &d = UnicodeData::valueRef(codepoint); + if (d.p.joining == QChar::Joining_None) { + if (d.p.category == QChar::Mark_NonSpacing || d.p.category == QChar::Mark_Enclosing || d.p.category == QChar::Other_Format) + d.p.joining = QChar::Joining_Transparent; + } + } + QFile f("data/ArabicShaping.txt"); if (!f.exists()) qFatal("Couldn't find ArabicShaping.txt"); @@ -1338,17 +1350,6 @@ static void readArabicShaping() break; } } - - // Code points that are not explicitly listed in ArabicShaping.txt are either of joining type T or U: - // - Those that not explicitly listed that are of General Category Mn, Me, or Cf have joining type T. - // - All others not explicitly listed have joining type U. - for (int codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) { - UnicodeData &d = UnicodeData::valueRef(codepoint); - if (d.p.joining == QChar::Joining_None) { - if (d.p.category == QChar::Mark_NonSpacing || d.p.category == QChar::Mark_Enclosing || d.p.category == QChar::Other_Format) - d.p.joining = QChar::Joining_Transparent; - } - } } static void readDerivedAge() @@ -2525,7 +2526,7 @@ static QByteArray createSpecialCaseMap() out.chop(1); out += "\n};\n\n"; - qDebug(" memory usage: %d bytes", specialCaseMap.size()*sizeof(unsigned short)); + qDebug(" memory usage: %ld bytes", specialCaseMap.size()*sizeof(unsigned short)); return out; } @@ -3021,7 +3022,7 @@ int main(int, char **) "****************************************************************************/\n\n"; QByteArray note = - "/* This file is autogenerated from the Unicode "DATA_VERSION_S" database. Do not edit */\n\n"; + "/* This file is autogenerated from the Unicode " DATA_VERSION_S " database. Do not edit */\n\n"; QByteArray warning = "//\n" @@ -3062,9 +3063,10 @@ int main(int, char **) f.write(warning); f.write("#ifndef QUNICODETABLES_P_H\n" "#define QUNICODETABLES_P_H\n\n" + "#include \n\n" "#include \n\n" "QT_BEGIN_NAMESPACE\n\n"); - f.write("#define UNICODE_DATA_VERSION "DATA_VERSION_STR"\n\n"); + f.write("#define UNICODE_DATA_VERSION " DATA_VERSION_STR "\n\n"); f.write("namespace QUnicodeTables {\n\n"); f.write(property_string); f.write(grapheme_break_class_string); From ba44cdae38406c429c7fb43863a6883bd0f79cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 1 Dec 2017 19:03:05 +0100 Subject: [PATCH 058/102] Teach QPlatformWindow about safe area margins and implement for iOS The safe area margins of a window represent the area that is safe to place content within, without intersecting areas of the screen where system UI is placed, or where a screen bezel may cover the content. QWidget will incorporate the safe area margins into its contents margins, so that they are are never smaller than the safe area margins. This can be disabled by unsetting the Qt::WA_ContentsMarginsRespectsSafeArea widget attribute, which is set by default. QLayouts will automatically use the contents area of a widget for their layout, unless the Qt::WA_LayoutOnEntireRect attribute has been set. This can be used, along with a contents margin of 0 on the actual layout, to allow e.g. a background image to underlay the status bar and other system areas on an iOS device, while still allowing child widgets of that background to be inset based on the safe area. [ChangeLog][iOS/tvOS] Qt will now take the safe area margins of the device into account when computing layouts for QtWidgets. Change-Id: Ife3827ab663f0625c1451e75b14fb8eeffb00754 Reviewed-by: Richard Moe Gustavsen --- src/corelib/global/qnamespace.h | 2 + src/gui/kernel/qguiapplication.cpp | 14 ++ src/gui/kernel/qguiapplication_p.h | 2 + src/gui/kernel/qplatformwindow.cpp | 10 ++ src/gui/kernel/qplatformwindow.h | 1 + src/gui/kernel/qwindow_p.h | 2 + src/gui/kernel/qwindowsysteminterface.cpp | 7 + src/gui/kernel/qwindowsysteminterface.h | 3 + src/gui/kernel/qwindowsysteminterface_p.h | 12 +- src/plugins/platforms/ios/qioswindow.h | 2 + src/plugins/platforms/ios/qioswindow.mm | 7 + src/plugins/platforms/ios/quiview.mm | 39 ++++++ src/widgets/kernel/qwidget.cpp | 154 +++++++++++++++++----- src/widgets/kernel/qwidget_p.h | 3 + src/widgets/kernel/qwidgetwindow.cpp | 7 + 15 files changed, 234 insertions(+), 31 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index da44c01594b..bd6b667aabb 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -474,6 +474,8 @@ public: WA_TabletTracking = 129, + WA_ContentsMarginsRespectsSafeArea = 130, + // Add new attributes before this line WA_AttributeCount }; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 6d37014b38e..cff11367f7e 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1759,6 +1759,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv case QWindowSystemInterfacePrivate::WindowScreenChanged: QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast(e)); break; + case QWindowSystemInterfacePrivate::SafeAreaMarginsChanged: + QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(static_cast(e)); + break; case QWindowSystemInterfacePrivate::ApplicationStateChanged: { QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast(e); QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); } @@ -2212,6 +2215,17 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf } } +void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *wse) +{ + if (wse->window.isNull()) + return; + + // Handle by forwarding directly to QWindowPrivate, instead of sending spontaneous + // QEvent like most other functions, as there's no QEvent type for the safe area + // change, and we don't want to add one until we know that this is a good API. + qt_window_private(wse->window)->processSafeAreaMarginsChanged(); +} + void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce) { if (self) diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 3804667ef3a..d67ab61ff89 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -133,6 +133,8 @@ public: static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e); static void processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e); + static void processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e); + static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); static void updateFilteredScreenOrientation(QScreen *screen); diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 5062bd1e77e..23e492ee7a4 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -146,6 +146,16 @@ QMargins QPlatformWindow::frameMargins() const return QMargins(); } +/*! + The safe area margins of a window represent the area that is safe to + place content within, without intersecting areas of the screen where + system UI is placed, or where a screen bezel may cover the content. +*/ +QMargins QPlatformWindow::safeAreaMargins() const +{ + return QMargins(); +} + /*! Reimplemented in subclasses to show the surface if \a visible is \c true, and hide it if \a visible is \c false. diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 8af8791bb4a..2bee55c7e02 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -86,6 +86,7 @@ public: virtual QRect normalGeometry() const; virtual QMargins frameMargins() const; + virtual QMargins safeAreaMargins() const; virtual void setVisible(bool visible); virtual void setWindowFlags(Qt::WindowFlags flags); diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index dd282a671da..568aa1e2fce 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -147,6 +147,8 @@ public: virtual void clearFocusObject(); virtual QRectF closestAcceptableGeometry(const QRectF &rect) const; + virtual void processSafeAreaMarginsChanged() {}; + bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; } static QWindowPrivate *get(QWindow *window) { return window->d_func(); } diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3f27094845c..13f45d236ea 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -265,6 +265,13 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } +QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window) +{ + QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e = + new QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent(window); + QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); +} + QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate) { Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)); diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index e91c79749d1..fb428233abe 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -179,6 +179,9 @@ public: static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState, int oldState = -1); static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen); + template + static void handleSafeAreaMarginsChanged(QWindow *window); + template static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 0f350fb2d21..5b41ccc3a50 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -98,7 +98,8 @@ public: #endif ApplicationStateChanged = 0x19, FlushEvents = 0x20, - WindowScreenChanged = 0x21 + WindowScreenChanged = 0x21, + SafeAreaMarginsChanged = 0x22 }; class WindowSystemEvent { @@ -187,6 +188,15 @@ public: QPointer screen; }; + class SafeAreaMarginsChangedEvent : public WindowSystemEvent { + public: + SafeAreaMarginsChangedEvent(QWindow *w) + : WindowSystemEvent(SafeAreaMarginsChanged), window(w) + { } + + QPointer window; + }; + class ApplicationStateChangedEvent : public WindowSystemEvent { public: ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false) diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 81fad420f69..85c60f61df6 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -71,6 +71,8 @@ public: bool isExposed() const Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE {} + QMargins safeAreaMargins() const override; + void raise() Q_DECL_OVERRIDE{ raiseOrLower(true); } void lower() Q_DECL_OVERRIDE { raiseOrLower(false); } diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index e934cb90fad..4ce73d7b5d8 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -223,6 +223,13 @@ void QIOSWindow::applyGeometry(const QRect &rect) [m_view layoutIfNeeded]; } +QMargins QIOSWindow::safeAreaMargins() const +{ + UIEdgeInsets safeAreaInsets = m_view.qt_safeAreaInsets; + return QMargins(safeAreaInsets.left, safeAreaInsets.top, + safeAreaInsets.right, safeAreaInsets.bottom); +} + bool QIOSWindow::isExposed() const { return qApp->applicationState() != Qt::ApplicationSuspended diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 1dbacad6e73..ed8af8e2900 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -56,6 +56,24 @@ @implementation QUIView ++ (void)load +{ + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 11)) { + // iOS 11 handles this though [UIView safeAreaInsetsDidChange], but there's no signal for + // the corresponding top and bottom layout guides that we use on earlier versions. Note + // that we use the _will_ change version of the notification, because we want to react + // to the change as early was possible. But since the top and bottom layout guides have + // not been updated at this point we use asynchronous delivery of the event, so that the + // event is processed by QtGui just after iOS has updated the layout margins. + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillChangeStatusBarFrameNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + for (QWindow *window : QGuiApplication::allWindows()) + QWindowSystemInterface::handleSafeAreaMarginsChanged(window); + } + ]; + } +} + + (Class)layerClass { return [CAEAGLLayer class]; @@ -100,6 +118,22 @@ self.layer.borderColor = colorWithBrightness(1.0); self.layer.borderWidth = 1.0; } + +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA) + if (qEnvironmentVariableIsSet("QT_IOS_DEBUG_WINDOW_SAFE_AREAS")) { + if (__builtin_available(iOS 11, tvOS 11, *)) { + UIView *safeAreaOverlay = [[UIView alloc] initWithFrame:CGRectZero]; + [safeAreaOverlay setBackgroundColor:[UIColor colorWithRed:0.3 green:0.7 blue:0.9 alpha:0.3]]; + [self addSubview:safeAreaOverlay]; + + safeAreaOverlay.translatesAutoresizingMaskIntoConstraints = NO; + [safeAreaOverlay.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES; + [safeAreaOverlay.leftAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leftAnchor].active = YES; + [safeAreaOverlay.rightAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.rightAnchor].active = YES; + [safeAreaOverlay.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES; + } + } +#endif } return self; @@ -203,6 +237,11 @@ QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); } +- (void)safeAreaInsetsDidChange +{ + QWindowSystemInterface::handleSafeAreaMarginsChanged(m_qioswindow->window()); +} + // ------------------------------------------------------------------------- - (BOOL)canBecomeFirstResponder diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 125f1cf246a..f279453ebd4 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1198,6 +1198,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute() adjustQuitOnCloseAttribute(); + q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea); q->setAttribute(Qt::WA_WState_Hidden); //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later @@ -1423,8 +1424,6 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO Q_UNUSED(initializeWindow); Q_UNUSED(destroyOldWindow); - Qt::WindowFlags flags = data.window_flags; - if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) return; // we only care about real toplevels @@ -1442,12 +1441,19 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO win->setProperty(propertyName, q->property(propertyName)); } + Qt::WindowFlags &flags = data.window_flags; + +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) + if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea)) + flags |= Qt::MaximizeUsingFullscreenGeometryHint; +#endif + if (q->testAttribute(Qt::WA_ShowWithoutActivating)) win->setProperty("_q_showWithoutActivating", QVariant(true)); if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true))); setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set - win->setFlags(data.window_flags); + win->setFlags(flags); fixPosIncludesFrame(); if (q->testAttribute(Qt::WA_Moved) || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement)) @@ -7588,21 +7594,7 @@ void QWidget::setContentsMargins(int left, int top, int right, int bottom) d->rightmargin = right; d->bottommargin = bottom; - if (QLayout *l=d->layout) - l->update(); //force activate; will do updateGeometry - else - updateGeometry(); - - if (isVisible()) { - update(); - QResizeEvent e(data->crect.size(), data->crect.size()); - QApplication::sendEvent(this, &e); - } else { - setAttribute(Qt::WA_PendingResizeEvent, true); - } - - QEvent e(QEvent::ContentsRectChange); - QApplication::sendEvent(this, &e); + d->updateContentsRect(); } /*! @@ -7627,6 +7619,27 @@ void QWidget::setContentsMargins(const QMargins &margins) margins.right(), margins.bottom()); } +void QWidgetPrivate::updateContentsRect() +{ + Q_Q(QWidget); + + if (layout) + layout->update(); //force activate; will do updateGeometry + else + q->updateGeometry(); + + if (q->isVisible()) { + q->update(); + QResizeEvent e(q->data->crect.size(), q->data->crect.size()); + QApplication::sendEvent(q, &e); + } else { + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } + + QEvent e(QEvent::ContentsRectChange); + QApplication::sendEvent(q, &e); +} + /*! Returns the widget's contents margins for \a left, \a top, \a right, and \a bottom. @@ -7635,15 +7648,22 @@ void QWidget::setContentsMargins(const QMargins &margins) */ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) const { - Q_D(const QWidget); + QMargins m = contentsMargins(); if (left) - *left = d->leftmargin; + *left = m.left(); if (top) - *top = d->topmargin; + *top = m.top(); if (right) - *right = d->rightmargin; + *right = m.right(); if (bottom) - *bottom = d->bottommargin; + *bottom = m.bottom(); +} + +// FIXME: Move to qmargins.h for next minor Qt release +QMargins operator|(const QMargins &m1, const QMargins &m2) +{ + return QMargins(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()), + qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom())); } /*! @@ -7656,10 +7676,11 @@ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) c QMargins QWidget::contentsMargins() const { Q_D(const QWidget); - return QMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin); + QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin); + return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ? + userMargins | d->safeAreaMargins() : userMargins; } - /*! Returns the area inside the widget's margins. @@ -7667,14 +7688,87 @@ QMargins QWidget::contentsMargins() const */ QRect QWidget::contentsRect() const { - Q_D(const QWidget); - return QRect(QPoint(d->leftmargin, d->topmargin), - QPoint(data->crect.width() - 1 - d->rightmargin, - data->crect.height() - 1 - d->bottommargin)); - + return rect() - contentsMargins(); } +QMargins QWidgetPrivate::safeAreaMargins() const +{ + Q_Q(const QWidget); + QWidget *nativeWidget = q->window(); + if (!nativeWidget->windowHandle()) + return QMargins(); + QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle(); + if (!platformWindow) + return QMargins(); + + QMargins safeAreaMargins = platformWindow->safeAreaMargins(); + + if (!q->isWindow()) { + // In theory the native parent widget already has a contents rect reflecting + // the safe area of that widget, but we can't be sure that the widget or child + // widgets of that widget have respected the contents rect when setting their + // geometry, so we need to manually compute the safe area. + + // Unless the native widget doesn't have any margins, in which case there's + // nothing for us to compute. + if (safeAreaMargins.isNull()) + return QMargins(); + + // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect + // set, then we know that the layout has already taken care of placing us inside the + // safe area, by taking the contents rect of its parent widget into account. + const QWidget *assumedSafeWidget = nullptr; + for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) { + QWidget *parentWidget = w->parentWidget(); + if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect)) + continue; // Layout not going to help us + + QLayout *layout = parentWidget->layout(); + if (!layout) + continue; + + if (layout->geometry().isNull()) + continue; // Layout hasn't been activated yet + + if (layout->indexOf(const_cast(w)) < 0) + continue; // Widget is not in layout + + assumedSafeWidget = w; + break; + } + +#if !defined(QT_DEBUG) + if (assumedSafeWidget) { + // We found a layout that we assume will take care of keeping us within the safe area + // For debug builds we still map the safe area using the fallback logic, so that we + // can detect any misbehaving layouts. + return QMargins(); + } +#endif + + // In all other cases we need to map the safe area of the native parent to the widget. + // This depends on the widget being positioned and sized already, which means the initial + // layout will be wrong, but the layout will then adjust itself. + QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top())); + QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect(); + QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget, + nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom())); + + // Margins should never be negative + safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()), + qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y())); + + if (!safeAreaMargins.isNull() && assumedSafeWidget) { + QLayout *layout = assumedSafeWidget->parentWidget()->layout(); + qWarning() << layout << "is laying out" << assumedSafeWidget + << "outside of the contents rect of" << layout->parentWidget(); + return QMargins(); // Return empty margin to visually highlight the error + } + } + + return safeAreaMargins; +} /*! \fn void QWidget::customContextMenuRequested(const QPoint &pos) diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a24d13e0e12..0c012d19324 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -513,6 +513,9 @@ public: void setLayoutItemMargins(int left, int top, int right, int bottom); void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); + void updateContentsRect(); + QMargins safeAreaMargins() const; + // aboutToDestroy() is called just before the contents of // QWidget::destroy() is executed. It's used to signal QWidget // sub-classes that their internals are about to be released. diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index abaebad821c..165dce04e95 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -87,6 +87,13 @@ public: } QRectF closestAcceptableGeometry(const QRectF &rect) const Q_DECL_OVERRIDE; + + void processSafeAreaMarginsChanged() override + { + Q_Q(QWidgetWindow); + if (QWidget *widget = q->widget()) + QWidgetPrivate::get(widget)->updateContentsRect(); + } }; QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const From 9dc7904556a261e9373bebc9060de62fcdab52a3 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 11 Dec 2017 09:55:53 +0100 Subject: [PATCH 059/102] xcb: update libXi version requirement in the README file ... from 1.7.4 to 1.7.5 (released Sep, 2015). Some more locking issues were fixed after 1.7.4. Testing for a prolonged period of time has showed that 1.7.5 does not cause a system lock-up. [ChangeLog][Platform Specific Changes][X11 / XCB] Minimal libXi version requirement has been updated from 1.7.4 to 1.7.5. This is because XIAllowTouchEvents is known to deadlock with libXi 1.7.4 and earlier. When touch events are never received, this is not an issue. Plain mouse / keyboard systems are not affected. Task-number: QTBUG-62224 Change-Id: Ie70264b9af0390df33c417f660350d4bce48c6d3 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/README | 3 +-- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index 5efc9b7f99a..8308db46dc0 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -25,9 +25,8 @@ This should allow for binaries that are portable across most modern Linux distri PACKAGE VERSION REQUIREMENTS When using touch input via XInput 2.2 or higher, there is a potential issue on systems that ship with -a libXi older than 1.7.4. This is because XIAllowTouchEvents can deadlock with libXi 1.7.3 and earlier. +a libXi older than 1.7.5. This is because XIAllowTouchEvents can deadlock with libXi 1.7.4 and earlier. When touch events are never received, this is not an issue, so plain mouse/keyboard systems are not affected. -See http://lists.x.org/archives/xorg-devel/2014-July/043059.html for details on the libXi patch. Qt versions before 5.8 attempted to recognize this scenario based on the pkg-config package version and skip the call. This has been removed starting from 5.8 since relying on pkg-config package versions is unsafe given that Qt must also support systems with limited or incomplete pkg-config setups. diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 26a9ba8d267..d1d97affe83 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -700,8 +700,9 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence // will get replayed when the grab ends. if (m_xiGrab) { - // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2) - // http://lists.x.org/archives/xorg-devel/2014-July/043059.html + // Note that XIAllowTouchEvents is known to deadlock with older libXi versions, + // for details see qtbase/src/plugins/platforms/xcb/README. This has nothing to + // do with the XInput protocol version, but is a bug in libXi implementation instead. XIAllowTouchEvents(static_cast(m_xlib_display), xiDeviceEvent->deviceid, xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch); } From 2086c183c12afa50ed1e046da9580b0ea0081bf0 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 7 Dec 2017 17:01:38 +0100 Subject: [PATCH 060/102] Fix/workaround a quirk in SecureTransport We set anchors from QSslConfiguration::caCertificates. On macOS these anchors are by default copied from the system store, so I expected setting 'trust those anchors only' should not break anything. Somehow, on 10.11 SecTrustEvaluate fails to evaluate a valid certificate chain (apparently because it has an intermediate certificate, it's just a guess, since their API/docs are too poor to explain well what was the real cause) as I can see connecting, for example, to google.com - we have a chain with a valid root, say it's GetTrust CA and we have it also in our list of anchors we set on trust, but evaluation fails with: kSecTrustResultRecoverableTrustFailure: "This means that you should not trust the chain as-is, but that the chain could be trusted with some minor change to the evaluation context, such as ignoring expired certificates or adding an additional anchor to the set of trusted anchors." Since none of certs is expired, and the required anchor already set, this must be some bug in SecureTransport. For macOS (deployment target) < 10.12 we fallback to the original version of the code (the one that unfortunately does not allow us to limit the set of trusted anchors by what client code wants to trust). Change-Id: Ie42fd77c3eb6ef7469812aa0d7efff88a003c0b8 Reviewed-by: Edward Welbourne --- src/network/ssl/qsslsocket_mac.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 2ba988fb70b..f0742fe6344 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -47,6 +47,7 @@ #include "qsslkey_p.h" #include +#include #include #include #include @@ -1247,13 +1248,17 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() // actual system CA certificate list (which most use-cases need) other than // by letting SecTrustEvaluate fall through to the system list; so, in this case // (even though the client code may have provided its own certs), we retain - // the default behavior. + // the default behavior. Note, with macOS SDK below 10.12 using 'trust my + // anchors only' may result in some valid chains rejected, apparently the + // ones containing intermediated certificates; so we use this functionality + // on more recent versions only. + + bool anchorsFromConfigurationOnly = false; #ifdef Q_OS_MACOS - const bool anchorsFromConfigurationOnly = true; -#else - const bool anchorsFromConfigurationOnly = false; -#endif + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) + anchorsFromConfigurationOnly = true; +#endif // Q_OS_MACOS SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly); From 6a2609f3799c4f52e8ad28495f9846b057743575 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Tue, 12 Dec 2017 20:13:28 -0800 Subject: [PATCH 061/102] Stop blocking the ability to generate dSYM debug symbols with Xcode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Xcode, the default value for GCC_GENERATE_DEBUGGING_SYMBOLS is YES, which causes Xcode to emit debug symbol bundles (.dSYM) on macOS and iOS *if* DEBUG_INFORMATION_FORMAT is also set to dwarf-with-dsym. Since that setting is already set to an appropriate value with debug vs release builds, the default Xcode value for GCC_GENERATE_DEBUGGING_SYMBOLS is already correct and in effect the only thing qmake was doing was always setting GCC_GENERATE_DEBUGGING_SYMBOLS to a wrong value for release builds - it should be YES in all cases, to allow the .dSYM bundles to be generated in release mode, which is in fact the only case where they're really needed in the first place. Task-number: QTBUG-41246 Task-number: QTBUG-50896 Change-Id: I07639a3c4ff9f62d591cde3ad66748767d475e3b Reviewed-by: Tor Arne Vestbø --- qmake/generators/mac/pbuilder_pbx.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 63926e7ef0c..0622ace71b1 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -280,8 +280,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t) QMap settings; settings.insert("COPY_PHASE_STRIP", (as_release ? "YES" : "NO")); - if(as_release) - settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", "NO"); if(project->isActiveConfig("sdk") && !project->isEmpty("QMAKE_MAC_SDK")) settings.insert("SDKROOT", project->first("QMAKE_MAC_SDK").toQString()); { @@ -1499,7 +1497,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) settings.insert("APPLICATION_EXTENSION_API_ONLY", project->isActiveConfig("app_extension_api_only") ? "YES" : "NO"); // required for tvOS (and watchos), optional on iOS (deployment target >= iOS 6.0) settings.insert("ENABLE_BITCODE", project->isActiveConfig("bitcode") ? "YES" : "NO"); - settings.insert("GCC_GENERATE_DEBUGGING_SYMBOLS", as_release ? "NO" : "YES"); if(!as_release) settings.insert("GCC_OPTIMIZATION_LEVEL", "0"); if(project->isActiveConfig("sdk") && !project->isEmpty("QMAKE_MAC_SDK")) From 9832f0ab857904a88c9b5e71a9e447abbebca8fb Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 15 Feb 2017 09:38:28 +0100 Subject: [PATCH 062/102] Copy argv[0] to prevent it pointing to invalid memory later If QCoreApplication is recreated, it is possible the previous argv[0] pointer has become invalid, so we should not rely on it. So to prevent that, we copy the original argv[0] to a static QByteArray. Task-number: QTBUG-58919 Change-Id: Idadd4cb78e4281830165fb681ea7925109f316ff Reviewed-by: Edward Welbourne Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qcoreapplication.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index bf423cef21d..db40b37da92 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2149,11 +2149,11 @@ QString QCoreApplication::applicationFilePath() QCoreApplicationPrivate *d = self->d_func(); if (d->argc) { - static const char *procName = d->argv[0]; - if (qstrcmp(procName, d->argv[0]) != 0) { + static QByteArray procName = QByteArray(d->argv[0]); + if (procName != d->argv[0]) { // clear the cache if the procname changes, so we reprocess it. QCoreApplicationPrivate::clearApplicationFilePath(); - procName = d->argv[0]; + procName = QByteArray(d->argv[0]); } } From 3d65284b60bfc8e01c4ea4b86344a508b6f49358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 14 Dec 2017 11:55:16 +0100 Subject: [PATCH 063/102] QWidget: Remove dead code for handling painting without a backingstore Change-Id: Iacf852c8620ea06d790cddcf6774b772f754e08a Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qwidget.cpp | 67 +++++++++------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index f279453ebd4..a82f97270d1 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -127,15 +127,6 @@ QT_BEGIN_NAMESPACE -static bool qt_enable_backingstore = true; -#if 0 // Used to be included in Qt4 for Q_WS_X11 -// for compatibility with Qt 4.0 -Q_WIDGETS_EXPORT void qt_x11_set_global_double_buffer(bool enable) -{ - qt_enable_backingstore = enable; -} -#endif - #if 0 // Used to be included in Qt4 for Q_WS_MAC bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false; #endif @@ -146,11 +137,6 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2) qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom())); } -static inline bool hasBackingStoreSupport() -{ - return true; -} - #if 0 // Used to be included in Qt4 for Q_WS_MAC # define QT_NO_PAINT_DEBUG #endif @@ -1351,8 +1337,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) // a real toplevel window needs a backing store if (isWindow() && windowType() != Qt::Desktop) { d->topData()->backingStoreTracker.destroy(); - if (hasBackingStoreSupport()) - d->topData()->backingStoreTracker.create(this); + d->topData()->backingStoreTracker.create(this); } d->setModal_sys(); @@ -2339,7 +2324,7 @@ bool QWidgetPrivate::paintOnScreen() const return true; } - return !qt_enable_backingstore; + return false; #endif } @@ -11036,15 +11021,11 @@ void QWidget::repaint(const QRect &rect) if (!isVisible() || !updatesEnabled() || rect.isEmpty()) return; - if (hasBackingStoreSupport()) { - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; - tlwExtra->backingStoreTracker->markDirty(rect, this, QWidgetBackingStore::UpdateNow); - tlwExtra->inRepaint = false; - } - } else { - d->repaint_sys(rect); + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { + tlwExtra->inRepaint = true; + tlwExtra->backingStoreTracker->markDirty(rect, this, QWidgetBackingStore::UpdateNow); + tlwExtra->inRepaint = false; } } @@ -11065,15 +11046,11 @@ void QWidget::repaint(const QRegion &rgn) if (!isVisible() || !updatesEnabled() || rgn.isEmpty()) return; - if (hasBackingStoreSupport()) { - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; - tlwExtra->backingStoreTracker->markDirty(rgn, this, QWidgetBackingStore::UpdateNow); - tlwExtra->inRepaint = false; - } - } else { - d->repaint_sys(rgn); + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { + tlwExtra->inRepaint = true; + tlwExtra->backingStoreTracker->markDirty(rgn, this, QWidgetBackingStore::UpdateNow); + tlwExtra->inRepaint = false; } } @@ -11127,13 +11104,9 @@ void QWidget::update(const QRect &rect) return; } - if (hasBackingStoreSupport()) { - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, this); - } else { - d_func()->repaint_sys(r); - } + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + tlwExtra->backingStoreTracker->markDirty(r, this); } /*! @@ -11156,13 +11129,9 @@ void QWidget::update(const QRegion &rgn) return; } - if (hasBackingStoreSupport()) { - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, this); - } else { - d_func()->repaint_sys(r); - } + QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + tlwExtra->backingStoreTracker->markDirty(r, this); } From d48c502ce535c913424440557cdfe7fa6e383dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 14 Dec 2017 12:14:11 +0100 Subject: [PATCH 064/102] Share QWidget update and repaint code for QRect and QRegion QWidgetBackingStore::markDirty has an optimization for QRect, so we don't want to unify these two functions by calling update/repaint(QRegion(rect)). Change-Id: Id2a42f478f71863da45697041e0ab0130c74b9d2 Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qwidget.cpp | 74 +++++++++++++--------------------- src/widgets/kernel/qwidget_p.h | 7 ++++ 2 files changed, 35 insertions(+), 46 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index a82f97270d1..b57a0d47798 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -11012,21 +11012,7 @@ void QWidget::repaint(int x, int y, int w, int h) void QWidget::repaint(const QRect &rect) { Q_D(QWidget); - - if (testAttribute(Qt::WA_WState_ConfigPending)) { - update(rect); - return; - } - - if (!isVisible() || !updatesEnabled() || rect.isEmpty()) - return; - - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; - tlwExtra->backingStoreTracker->markDirty(rect, this, QWidgetBackingStore::UpdateNow); - tlwExtra->inRepaint = false; - } + d->repaint(rect); } /*! @@ -11037,19 +11023,21 @@ void QWidget::repaint(const QRect &rect) void QWidget::repaint(const QRegion &rgn) { Q_D(QWidget); + d->repaint(rgn); +} - if (testAttribute(Qt::WA_WState_ConfigPending)) { - update(rgn); - return; - } +template +void QWidgetPrivate::repaint(T r) +{ + Q_Q(QWidget); - if (!isVisible() || !updatesEnabled() || rgn.isEmpty()) + if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty()) return; - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { tlwExtra->inRepaint = true; - tlwExtra->backingStoreTracker->markDirty(rgn, this, QWidgetBackingStore::UpdateNow); + tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); tlwExtra->inRepaint = false; } } @@ -11091,22 +11079,8 @@ void QWidget::update() */ void QWidget::update(const QRect &rect) { - if (!isVisible() || !updatesEnabled()) - return; - - QRect r = rect & QWidget::rect(); - - if (r.isEmpty()) - return; - - if (testAttribute(Qt::WA_WState_InPaintEvent)) { - QApplication::postEvent(this, new QUpdateLaterEvent(r)); - return; - } - - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, this); + Q_D(QWidget); + d->update(rect); } /*! @@ -11116,25 +11090,33 @@ void QWidget::update(const QRect &rect) */ void QWidget::update(const QRegion &rgn) { - if (!isVisible() || !updatesEnabled()) + Q_D(QWidget); + d->update(rgn); +} + +template +void QWidgetPrivate::update(T r) +{ + Q_Q(QWidget); + + if (!q->isVisible() || !q->updatesEnabled()) return; - QRegion r = rgn & QWidget::rect(); + T clipped = r & q->rect(); - if (r.isEmpty()) + if (clipped.isEmpty()) return; - if (testAttribute(Qt::WA_WState_InPaintEvent)) { - QApplication::postEvent(this, new QUpdateLaterEvent(r)); + if (q->testAttribute(Qt::WA_WState_InPaintEvent)) { + QApplication::postEvent(q, new QUpdateLaterEvent(clipped)); return; } - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); + QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, this); + tlwExtra->backingStoreTracker->markDirty(clipped, q); } - /*! \internal diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 0c012d19324..15704f32c9d 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -342,6 +342,13 @@ public: QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); QWidgetBackingStore *maybeBackingStore() const; + + template + void repaint(T t); + + template + void update(T t); + void init(QWidget *desktopWidget, Qt::WindowFlags f); void create_sys(WId window, bool initializeWindow, bool destroyOldWindow); void createRecursively(); From 345be581007c05164052e27f90fcfaf27a41c743 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Wed, 6 Dec 2017 19:46:31 +0100 Subject: [PATCH 065/102] Fix assert when emitting a signal from a different thread If a signal is emitted more than once in a multithreaded application the QSignalEventGenerator::execute function asserts in the check for a valid signal index. It happens after abandoning the state and all the connections are disconnected. If we have pending signal to be processed the QObject::sender() won't be able to resolve the sender object. Task-number: QTBUG-61463 Change-Id: I9d4b7266c6dddc9ff2e7453b05a6989876ccb332 Reviewed-by: Edward Welbourne --- src/corelib/statemachine/qstatemachine.cpp | 6 ++-- .../qstatemachine/tst_qstatemachine.cpp | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 2808ba2ced0..c2b5afd241f 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -3096,10 +3096,12 @@ int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a) void QSignalEventGenerator::execute(void **_a) { + auto machinePrivate = QStateMachinePrivate::get(qobject_cast(parent())); + if (machinePrivate->state != QStateMachinePrivate::Running) + return; int signalIndex = senderSignalIndex(); Q_ASSERT(signalIndex != -1); - QStateMachine *machine = qobject_cast(parent()); - QStateMachinePrivate::get(machine)->handleTransitionSignal(sender(), signalIndex, _a); + machinePrivate->handleTransitionSignal(sender(), signalIndex, _a); } QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index 8f0d83ce328..7ea467b6efe 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -101,6 +101,7 @@ Q_OBJECT public: SignalEmitter(QObject *parent = 0) : QObject(parent) {} +public Q_SLOTS: void emitSignalWithNoArg() { emit signalWithNoArg(); } void emitSignalWithIntArg(int arg) @@ -251,6 +252,7 @@ private slots: void qtbug_46059(); void qtbug_46703(); void postEventFromBeginSelectTransitions(); + void dontProcessSlotsWhenMachineIsNotRunning(); }; class TestState : public QState @@ -6658,5 +6660,35 @@ void tst_QStateMachine::postEventFromBeginSelectTransitions() QVERIFY(machine.isRunning()); } +void tst_QStateMachine::dontProcessSlotsWhenMachineIsNotRunning() +{ + QStateMachine machine; + QState initialState; + QFinalState finalState; + + struct Emitter : SignalEmitter + { + QThread thread; + Emitter(QObject *parent = nullptr) : SignalEmitter(parent) + { + moveToThread(&thread); + thread.start(); + } + } emitter; + + initialState.addTransition(&emitter, &Emitter::signalWithNoArg, &finalState); + QTimer::singleShot(0, [&]() { + metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg"); + metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg"); + }); + machine.addState(&initialState); + machine.addState(&finalState); + machine.setInitialState(&initialState); + machine.start(); + connect(&machine, &QStateMachine::finished, &emitter.thread, &QThread::quit); + QSignalSpy signalSpy(&machine, &QStateMachine::finished); + QTRY_COMPARE_WITH_TIMEOUT(signalSpy.count(), 1, 100); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" From af70d4ee85246031ff631488a9191034bf3baa7a Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 14 Dec 2017 15:26:31 +0100 Subject: [PATCH 066/102] Allow empty namespace URI W3C Namespaces Standard states that "The attribute value in a default namespace declaration MAY be empty" (secion 6.2). Analysis and fix thanks to Eugenio Rustico. Task-number: QTBUG-63538 Change-Id: Icd8d4df639b9737d8e0d215bf2bea56fe1e161ac Reviewed-by: Edward Welbourne --- src/corelib/xml/qxmlstream.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index af35193b133..a55d16ed884 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3708,7 +3708,6 @@ void QXmlStreamWriter::writeEntityReference(const QString &name) void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix) { Q_D(QXmlStreamWriter); - Q_ASSERT(!namespaceUri.isEmpty()); Q_ASSERT(prefix != QLatin1String("xmlns")); if (prefix.isEmpty()) { d->findNamespace(namespaceUri, d->inStartElement); From fd3423bfb82f44723fd59991ba56adc3ed112412 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 4 Dec 2017 21:00:38 +0100 Subject: [PATCH 067/102] configure: support discarding selected test results with -recheck especially during debugging, it is often necessary to re-run only one (or a few) tests, where -recheck-all would be wasteful. Task-number: QTBUG-64059 Change-Id: I9410894dec4289ff832d7f75e04f9b60fe76c57c Reviewed-by: Lars Knoll --- config_help.txt | 4 +++- mkspecs/features/data/configure.json | 2 +- mkspecs/features/qt_configure.prf | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/config_help.txt b/config_help.txt index 003752dbe7c..9c424391a91 100644 --- a/config_help.txt +++ b/config_help.txt @@ -66,8 +66,10 @@ Configure meta: -redo ................ Re-configure with previously used options. Additional options may be passed, but will not be saved for later use by -redo. - -recheck ............. Discard cached negative configure test results. + -recheck [test,...] .. Discard cached negative configure test results. Use this after installing missing dependencies. + Alternatively, if tests are specified, only their + results are discarded. -recheck-all ......... Discard all cached configure test results. -feature- ... Enable diff --git a/mkspecs/features/data/configure.json b/mkspecs/features/data/configure.json index 38623d46a4d..167c502e829 100644 --- a/mkspecs/features/data/configure.json +++ b/mkspecs/features/data/configure.json @@ -9,7 +9,7 @@ "continue": "void", - "recheck": { "type": "void", "name": "cache_use", "value": "positive" }, + "recheck": { "type": "optionalString", "name": "cache_recheck" }, "recheck-all": { "type": "void", "name": "cache_use", "value": "none" }, "redo": { "type": "redo" }, diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index dcd87a7a1a5..6ab40e53ecf 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -2041,14 +2041,28 @@ qtConfCheckErrors() QMAKE_CONFIG_CACHE = $$OUT_PWD/config.cache QMAKE_CONFIG_CACHE_USE = $$eval(config.input.cache_use) +cache_recheck = $$eval(config.input.cache_recheck) +equals(cache_recheck, yes) { + QMAKE_CONFIG_CACHE_USE = positive + cache_recheck = +} isEmpty(QMAKE_CONFIG_CACHE_USE): \ QMAKE_CONFIG_CACHE_USE = all !equals(QMAKE_CONFIG_CACHE_USE, none) { include($$QMAKE_CONFIG_CACHE, , true) # this crudely determines when to discard the cache. this also catches the case # of no cache being there in the first place. - !equals(cache.platform, $$[QMAKE_SPEC])|!equals(cache.xplatform, $$[QMAKE_XSPEC]): \ + !equals(cache.platform, $$[QMAKE_SPEC])|!equals(cache.xplatform, $$[QMAKE_XSPEC]) { QMAKE_CONFIG_CACHE_USE = none + } else: !isEmpty(cache_recheck) { + for (cr, $$list($$split(cache_recheck, ","))) { + !isEmpty(cache.$${cr}._KEYS_) { + cache.$${cr}._KEYS_ = + } else { + qtConfAddWarning("Attempting to discard non-cached result '$$cr'.") + } + } + } } equals(QMAKE_CONFIG_CACHE_USE, none) { cont = \ From ff1c8baf4a441e10ddce8469c94b95b6897133d5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Dec 2017 18:37:36 +0100 Subject: [PATCH 068/102] configure: make cached results immediately available otherwise test de-duplication between modules doesn't work. Change-Id: I2c6222d853108df223758aa8907dc8d004efd87f Reviewed-by: Lars Knoll --- mkspecs/features/qt_configure.prf | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 6ab40e53ecf..d5dcda22ac5 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -1052,8 +1052,13 @@ defineTest(qtConfSaveResult) { return() keys = result $$eval($${1}.cache) cont = "cache.$${2}._KEYS_ = $$keys" - for (k, keys): \ + cache.$${2}._KEYS_ = $$keys + export(cache.$${2}._KEYS_) + for (k, keys) { cont += "cache.$${2}.$${k} = $$val_escape($${1}.$${k})" + cache.$${2}.$${k} = $$eval($${1}.$${k}) + export(cache.$${2}.$${k}) + } write_file($$QMAKE_CONFIG_CACHE, cont, append)|error() } From 5dd76ba31c3c7cb9c0d9d97cd62f0d2f535a23f7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 12 Jun 2017 12:30:01 +0200 Subject: [PATCH 069/102] update sqldriver docs - adjusted to new configure system realities - centralized 'make install' instructions - fixed 'make' command for mingw - externalized the license compatibility question - removed dated information about postgresql client libs - removed dated claim that freetds is not stable yet - updated official sybase client link to point to sap support - removed apparently bogus "demo" include path from oci instructions, based on the archive content description - removed troubleshooting item about static builds - one can use static "plugins" with a static build just fine. and building dynamic plugins for a static build is plain impossible to start with. - removed troubleshooting item about build key mismatch, as build keys have been removed in qt5 - removed "general info" sub-section titles, as that's bad style - misc language and minor content fixes Task-number: QTBUG-62479 Change-Id: Ic4efa9e20a5966b6fc646062aec6d1a8d4ff4158 Reviewed-by: Leena Miettinen Reviewed-by: Thiago Macieira --- .../doc/snippets/code/doc_src_sql-driver.cpp | 6 - .../doc/snippets/code/doc_src_sql-driver.qdoc | 158 ++++++++--------- src/sql/doc/src/sql-driver.qdoc | 162 +++++++----------- 3 files changed, 129 insertions(+), 197 deletions(-) diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp index f25ad4f2b05..75ac9fe134e 100644 --- a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp +++ b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp @@ -84,9 +84,3 @@ q.exec("execute procedure my_procedure"); q.next(); qDebug() << q.value(0); // outputs the first RETURN/OUT value //! [26] - - -//! [31] -QSqlDatabase: QMYSQL driver not loaded -QSqlDatabase: available drivers: QMYSQL -//! [31] diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc index 87c1d0c69bd..04ea30915d6 100644 --- a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc +++ b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc @@ -49,14 +49,16 @@ ****************************************************************************/ //! [0] --no-sql- ... Disable SQL entirely. --qt-sql- ... Enable a SQL in the Qt Library, by default - none are turned on. --plugin-sql- Enable SQL as a plugin to be linked to - at run time. +[...] - Possible values for : - [ db2 ibase mysql oci odbc psql sqlite sqlite2 tds ] +Database options: + + -sql- ........ Enable SQL plugin. Supported drivers: + db2 ibase mysql oci odbc psql sqlite2 sqlite tds + [all auto] + -sqlite .............. Select used sqlite3 [system/qt] + +[...] //! [0] @@ -70,9 +72,9 @@ END //! [3] -cd $QTDIR/qtbase/src/plugins/sqldrivers/mysql -qmake "INCLUDEPATH+=/usr/local/include" "LIBS+=-L/usr/local/lib -lmysqlclient_r" mysql.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- MYSQL_PREFIX=/usr/local +make sub-mysql //! [3] @@ -83,32 +85,30 @@ make install //! [5] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\mysql -qmake "INCLUDEPATH+=C:/MySQL/include" "LIBS+=C:/MYSQL/MySQL Server /lib/opt/libmysql.lib" mysql.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- MYSQL_INCDIR=C:/MySQL/include "MYSQL_LIBDIR=C:/MYSQL/MySQL Server /lib/opt" +nmake sub-mysql //! [5] //! [6] -cd $QTDIR/qtbase/src/plugins/sqldrivers/oci -qmake "INCLUDEPATH+=$ORACLE_HOME/rdbms/public $ORACLE_HOME/rdbms/demo" "LIBS+=-L$ORACLE_HOME/lib -lclntsh -lwtc9" oci.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- "OCI_INCDIR=$ORACLE_HOME/rdbms/public" OCI_LIBDIR=$ORACLE_HOME/lib "OCI_LIBS=-lclntsh -lwtc9" +make sub-oci //! [6] //! [7] -cd $QTDIR/qtbase/src/plugins/sqldrivers/oci -qmake "INCLUDEPATH+=/usr/include/oracle/10.1.0.3/client/" "LIBS+=-L/usr/lib/oracle/10.1.0.3/client/lib -lclntsh" oci.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib +make sub-oci //! [7] //! [8] -set INCLUDE=%INCLUDE%;c:\oracle\oci\include -set LIB=%LIB%;c:\oracle\oci\lib\msvc -cd %QTDIR%\qtbase\src\plugins\sqldrivers\oci -qmake oci.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- OCI_INCDIR=c:/oracle/oci/include OCI_LIBDIR=c:/oracle/oci/lib/msvc +nmake sub-oci //! [8] @@ -118,128 +118,110 @@ set PATH=%PATH%;c:\oracle\bin //! [11] -cd $QTDIR/qtbase/src/plugins/sqldrivers/odbc -qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc" -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- ODBC_PREFIX=/usr/local/unixODBC +make sub-odbc //! [11] //! [12] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\odbc -qmake odbc.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake +nmake sub-odbc //! [12] //! [13] -cd $QTDIR/qtbase/src/plugins/sqldrivers/psql -qmake "INCLUDEPATH+=/usr/include/pgsql" "LIBS+=-L/usr/lib -lpq" psql.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- PSQL_INCDIR=/usr/include/pgsql +make sub-psql //! [13] -//! [14] -cd $QTDIR/qtbase/src/plugins/sqldrivers/psql -make install -//! [14] - - //! [15] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\psql -qmake "INCLUDEPATH+=C:/psql/include" "LIBS+=C:/psql/lib/ms/libpq.lib" psql.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- PSQL_INCDIR=C:/psql/include PSQL_LIBDIR=C:/psql/lib/ms +nmake sub-psql //! [15] //! [16] -cd $QTDIR/qtbase/src/plugins/sqldrivers/tds -qmake "INCLUDEPATH=$SYBASE/include" "LIBS=-L$SYBASE/lib -lsybdb" -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- TDS_PREFIX=$SYBASE +make sub-tds //! [16] //! [17] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\tds -qmake "LIBS+=NTWDBLIB.LIB" tds.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake +nmake sub-tds //! [17] //! [18] -cd $QTDIR/qtbase/src/plugins/sqldrivers/db2 -qmake "INCLUDEPATH+=$DB2DIR/include" "LIBS+=-L$DB2DIR/lib -ldb2" -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- DB2_PREFIX=$DB2DIR +make sub-db2 //! [18] -//! [19] -cd $QTDIR/qtbase/src/plugins/sqldrivers/db2 -make install -//! [19] - - //! [20] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\db2 -qmake "INCLUDEPATH+=/sqllib/include" "LIBS+=/sqllib/lib/db2cli.lib" -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- "DB2_PREFIX=/sqllib" +nmake sub-db2 //! [20] //! [21] -cd $QTDIR/qtbase/src/plugins/sqldrivers/sqlite -qmake "INCLUDEPATH+=$SQLITE/include" "LIBS+=-L$SQLITE/lib -lsqlite" -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- -system-sqlite SQLITE3_PREFIX=$SQLITE +make sub-sqlite //! [21] -//! [22] -cd $QTDIR/qtbase/src/plugins/sqldrivers/sqlite -make install -//! [22] - - //! [23] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\sqlite -qmake "INCLUDEPATH+=C:/SQLITE/INCLUDE" "LIBS+=C:/SQLITE/LIB/SQLITE3.LIB" sqlite.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- -system-sqlite SQLITE3_PREFIX=C:/SQLITE +nmake sub-sqlite //! [23] //! [27] -cd $QTDIR/qtbase/src/plugins/sqldrivers/ibase -qmake "INCLUDEPATH+=/opt/interbase/include" "LIBS+=-L/opt/interbase/lib" ibase.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- IBASE_PREFIX=/opt/interbase +make sub-ibase //! [27] //! [28] -cd $QTDIR/qtbase/src/plugins/sqldrivers/ibase -qmake "INCLUDEPATH+=/opt/interbase/include" "LIBS+=-L/opt/interbase/lib -lfbclient" ibase.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- IBASE_PREFIX=/opt/interbase IBASE_LIBS=-lfbclient +make sub-ibase //! [28] //! [29] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\ibase -qmake "INCLUDEPATH+=C:/interbase/include" ibase.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- IBASE_INCDIR=C:/interbase/include +nmake sub-ibase //! [29] //! [30] -cd %QTDIR%\qtbase\src\plugins\sqldrivers\ibase -qmake "INCLUDEPATH+=C:/interbase/include" "LIBS+=-lfbclient" ibase.pro -nmake +cd %QTDIR%\qtbase\src\plugins\sqldrivers +qmake -- IBASE_INCDIR=C:/interbase/include IBASE_LIBS=-lfbclient +nmake sub-ibase //! [30] //! [32] -configure -I /usr/include/oracle/10.1.0.3/client -L /usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10 +configure OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-lclntsh -lnnz10" make //! [32] //! [33] -cd $QTDIR/qtbase/src/plugins/sqldrivers/oci -qmake "INCLUDEPATH+=/usr/include/oracle/10.1.0.3/client" "LIBS+=-L/usr/lib/oracle/10.1.0.3/client/lib -Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10" oci.pro -make +cd $QTDIR/qtbase/src/plugins/sqldrivers +qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10" +make sub-oci //! [33] diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index 4f3f2ce0076..c8de78dd799 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -34,7 +34,7 @@ Plugins}{plugins} to communicate with the different database APIs. Since Qt's SQL Module API is database-independent, all database-specific code is contained within these drivers. Several - drivers are supplied with Qt and other drivers can be added. The + drivers are supplied with Qt, and other drivers can be added. The driver source code is supplied and can be used as a model for \l{#development}{writing your own drivers}. @@ -42,9 +42,7 @@ \section1 Supported Databases - The table below lists the drivers included with Qt. Due to - license incompatibilities with the GPL, not all of the plugins - are provided with Open Source Versions of Qt. + The table below lists the drivers included with Qt: \table \header \li Driver name \li DBMS @@ -74,10 +72,14 @@ libraries", and these are what you need. These libraries are responsible for the low-level communication with the DBMS. - \target building - \section1 Building the Drivers Using Configure + \note When using Qt under Open Source terms but with a proprietary + database, verify the client library's license compatibility with + the LGPL. - On Unix and \macos, the Qt \c configure script tries to + \target building + \section1 Building the Drivers + + The Qt \c configure script tries to automatically detect the available client libraries on your machine. Run \c{configure -help} to see what drivers can be built. You should get an output similar to this: @@ -86,23 +88,28 @@ The \c configure script cannot detect the necessary libraries and include files if they are not in the standard paths, so it - may be necessary to specify these paths using the \c -I and \c -L - command-line options. For example, if your MySQL include files - are installed in \c /usr/local/mysql (or in \c{C:\mysql\include} - on Windows), then pass the following parameter to configure: \c - -I/usr/local/mysql (or \c{-I C:\mysql\include} for Windows). + may be necessary to specify these paths using the \c *_INCDIR=, + \c *_LIBDIR=, or \c *_PREFIX= command-line options. For example, + if your MySQL files are installed in \c /usr/local/mysql (or in + \c{C:\mysql} on Windows), then pass the following parameter to + configure: \c MYSQL_PREFIX=/usr/local/mysql + (or \c{MYSQL_PREFIX=C:\mysql} for Windows). + The particulars for each driver are explained below. - On Windows, the \c -I parameter doesn't accept spaces in - filenames, so use the 8.3 name instead; for example, use - \c{C:\progra~1\mysql} instead of \c{C:\Program Files\mysql}. + Due to the practicalities of dealing with external dependencies, + only the SQLite3 plugin is shipped with binary builds of Qt. + To be able to add additional drivers to the Qt installation + without re-building all of Qt, it is possible to configure + and build the \c qtbase/src/plugins/sqldrivers directory outside + of a full Qt build directory. Note that it is not possible to + \e configure each driver separately, only all of them at once. + Drivers can be \e built separately, though. + If the Qt build is configured with \c{-prefix}, it is necessary to + install the plugins after building them, too. For example: - Use the \c{-qt-sql-} parameter to build the database driver - statically into your Qt library or \c{-plugin-sql-} to build - the driver as a plugin. Look at the sections that follow for - additional information about required libraries. + \snippet code/doc_src_sql-driver.qdoc 4 - \target buildingmanually - \section1 Building the Plugins Manually + \section1 Driver Specifics \target QMYSQL \section2 QMYSQL for MySQL 4 and higher @@ -132,9 +139,8 @@ not required to use MySQL functionality. To use the embedded MySQL server, simply link the Qt plugin to \c - libmysqld instead of libmysqlclient. This can be done by replacing - \c -lmysqlclient_r by \c -lmysqld in the \c qmake command in the - section below. + libmysqld instead of \c libmysqlclient. This can be done by adding + \c MYSQL_LIBS=-lmysqld to the configure command line. Please refer to the MySQL documentation, chapter "libmysqld, the Embedded MySQL Server Library" for more information about the MySQL embedded server. @@ -151,11 +157,6 @@ \snippet code/doc_src_sql-driver.qdoc 3 - After installing Qt, you also need to install the plugin in the standard - location: - - \snippet code/doc_src_sql-driver.qdoc 4 - \section3 How to Build the QMYSQL Plugin on Windows You need to get the MySQL installation files. Run \c SETUP.EXE and @@ -166,18 +167,11 @@ \snippet code/doc_src_sql-driver.qdoc 5 If you are not using a Microsoft compiler, replace \c nmake with \c - make in the line above. - - \note Including \c{"-o Makefile"} as an argument to \l qmake, to - tell it where to build the makefile, can cause the plugin to be - built in release mode only. If you intend to build a debug version - as well, don't use the \c{"-o Makefile"} option. + mingw32-make in the line above. \target QOCI \section2 QOCI for the Oracle Call Interface (OCI) - \section3 General Information about the OCI plugin - The Qt OCI plugin supports Oracle 9i, 10g and higher. After connecting to the Oracle server, the plugin will auto-detect the database version and enable features accordingly. @@ -252,7 +246,7 @@ \snippet code/doc_src_sql-driver.qdoc 8 If you are not using a Microsoft compiler, replace \c nmake with \c - make in the line above. + mingw32-make in the line above. When you run your application, you will also need to add the \c oci.dll path to your \c PATH environment variable: @@ -262,8 +256,6 @@ \target QODBC \section2 QODBC for Open Database Connectivity (ODBC) - \section3 General Information about the ODBC plugin - ODBC is a general interface that allows you to connect to multiple DBMSs using a common interface. The QODBC driver allows you to connect to an ODBC driver manager and access the available data sources. Note @@ -277,7 +269,7 @@ On Windows, an ODBC driver manager should be installed by default. For Unix systems, there are some implementations which must be - installed first. Note that every client that uses your application is + installed first. Note that every end user of your application is required to have an ODBC driver manager installed, otherwise the QODBC plugin will not work. @@ -290,7 +282,7 @@ but do not offer all the necessary functionality. The QODBC plugin therefore checks whether the data source can be used after a connection has been established, and refuses to work if the check - fails. If you don't like this behavior, you can remove the \c{#define + fails. If you do not like this behavior, you can remove the \c{#define ODBC_CHECK_DRIVER} line from the file \c{qsql_odbc.cpp}. Do this at your own risk! @@ -310,7 +302,7 @@ If you experience very slow access of the ODBC datasource, make sure that ODBC call tracing is turned off in the ODBC datasource manager. - Some drivers don't support scrollable cursors. In that case case only + Some drivers do not support scrollable cursors. In that case, only queries in forwardOnly mode can be used successfully. \section3 ODBC Stored Procedure Support @@ -331,7 +323,7 @@ Windows NT based systems, this is the default. Note that the ODBC driver and the DBMS must also support Unicode. - Some driver managers and drivers don't support UNICODE. To use the + Some driver managers and drivers do not support UNICODE. To use the QODBC plugin with such drivers, it has to be compiled with Q_ODBC_VERSION_2 defined. @@ -359,18 +351,12 @@ \snippet code/doc_src_sql-driver.qdoc 12 If you are not using a Microsoft compiler, replace \c nmake with \c - make in the line above. + mingw32-make in the line above. \target QPSQL \section2 QPSQL for PostgreSQL (Version 7.3 and Above) - \section3 General Information about the QPSQL driver - The QPSQL driver supports version 7.3 and higher of the PostgreSQL server. - We recommend that you use a client library from version 7.3.15, 7.4.13, - 8.0.8, 8.1.4, or more recent, as these versions contain security fixes, and - as the QPSQL driver might not build with older versions of the client - library, depending on your platform. For more information about PostgreSQL visit \l http://www.postgresql.org. @@ -404,11 +390,6 @@ \snippet code/doc_src_sql-driver.qdoc 13 - After installing Qt, you also need to install the plugin in the standard - location: - - \snippet code/doc_src_sql-driver.qdoc 14 - \section3 How to Build the QPSQL Plugin on Windows Install the appropriate PostgreSQL developer libraries for your @@ -426,8 +407,6 @@ \note TDS is no longer used by MS Sql Server, and is superceded by \l{QODBC}{ODBC}. QTDS is obsolete from Qt 4.7. - \section3 General Information about QTDS - It is not possible to set the port with QSqlDatabase::setPort() due to limitations in the Sybase client library. Refer to the Sybase documentation for information on how to set up a Sybase client configuration file to enable connections to databases on non-default ports. @@ -438,12 +417,9 @@ \list \li FreeTDS, a free implementation of the TDS protocol - (\l{http://www.freetds.org}). Note that FreeTDS is not yet stable, - so some functionality may not work as expected. + (\l{http://www.freetds.org}). - \li Sybase Open Client, available from \l{http://www.sybase.com}. - Note for Linux users: Get the Open Client RPM from - \l{http://linux.sybase.com}. + \li Sybase Open Client, available from \l{https://support.sap.com}. \endlist Regardless of which library you use, the shared object file @@ -456,22 +432,21 @@ \section3 How to Build the QDTS Plugin on Windows You can either use the DB-Library supplied by Microsoft or the Sybase - Open Client (\l{http://www.sybase.com}). You must include \c + Open Client (\l{https://support.sap.com}). Configure will try to find NTWDBLIB.LIB to build the plugin: \snippet code/doc_src_sql-driver.qdoc 17 - By default the Microsoft library is used on Windows, if you want to + By default, the Microsoft library is used on Windows. If you want to force the use of the Sybase Open Client, you must define \c - Q_USE_SYBASE in \c{%QTDIR%\qtbase\src\sql\drivers\tds\qsql_tds.cpp}. If you - are not using a Microsoft compiler, replace \c nmake with \c make in - the line above. + Q_USE_SYBASE in \c{%QTDIR%\qtbase\src\plugins\sqldrivers\tds\qsql_tds.cpp}. + + If you are not using a Microsoft compiler, replace \c nmake + with \c mingw32-make in the line above. \target QDB2 \section2 QDB2 for IBM DB2 (Version 7.1 and Above) - \section3 General Information about QDB2 - The Qt DB2 plugin makes it possible to access IBM DB2 databases. It has been tested with IBM DB2 v7.1 and 7.2. You must install the IBM DB2 development client library, which contains the header and library @@ -487,11 +462,6 @@ \snippet code/doc_src_sql-driver.qdoc 18 - After installing Qt, you also need to install the plugin in the standard - location: - - \snippet code/doc_src_sql-driver.qdoc 19 - \section3 How to Build the QDB2 Plugin on Windows The DB2 header and include files should already be installed in the @@ -500,7 +470,7 @@ \snippet code/doc_src_sql-driver.qdoc 20 If you are not using a Microsoft compiler, replace \c nmake - with \c make in the line above. + with \c mingw32-make in the line above. \target QSQLITE2 \section2 QSQLITE2 for SQLite Version 2 @@ -512,8 +482,6 @@ \target QSQLITE \section2 QSQLITE for SQLite (Version 3 and Above) - \section3 General Information about QSQLITE - The Qt SQLite plugin makes it possible to access SQLite databases. SQLite is an in-process database, which means that it is not necessary to have a database server. SQLite operates on a @@ -548,22 +516,20 @@ \section3 How to Build the QSQLITE Plugin SQLite version 3 is included as a third-party library within Qt. - It can be built by passing the following parameters to the - configure script: \c{-plugin-sql-sqlite} (build as a plugin) or - \c{-qt-sql-sqlite} (linked directly into the Qt library). + It can be built by passing the \c{-qt-sqlite} parameter to the + configure script. - If you don't want to use the SQLite library included with Qt, you - can pass \c{-system-sqlite} to the configure script to use sqlite - libraries in the operating system. Alternatively, you can build - it manually (replace \c $SQLITE with the directory where + If you do not want to use the SQLite library included with Qt, you + can pass \c{-system-sqlite} to the configure script to use the SQLite + libraries of the operating system. This is recommended whenever possible, + as it reduces the installation size and removes one component for which + you need to track security advisories. + + On Unix and \macos (replace \c $SQLITE with the directory where SQLite resides): \snippet code/doc_src_sql-driver.qdoc 21 - After installing Qt, you also need to install the plugin in the standard location: - - \snippet code/doc_src_sql-driver.qdoc 22 - On Windows: \snippet code/doc_src_sql-driver.qdoc 23 @@ -588,8 +554,6 @@ \target QIBASE \section2 QIBASE for Borland InterBase - \section3 General Information about QIBASE - The Qt InterBase plugin makes it possible to access the InterBase and Firebird databases. InterBase can either be used as a client/server or without a server in which case it operates on local files. The @@ -617,7 +581,7 @@ \snippet code/doc_src_sql-driver.cpp 25 - If Qt doesn't support the given text encoding the driver will issue a + If Qt does not support the given text encoding the driver will issue a warning message and connect to the database using UNICODE_FSS. Note that if the text encoding set when connecting to the database is @@ -658,7 +622,7 @@ \snippet code/doc_src_sql-driver.qdoc 30 If you are not using a Microsoft compiler, replace \c nmake - with \c make in the line above. + with \c mingw32-make in the line above. Note that \c{C:\interbase\bin} must be in the \c PATH. @@ -678,14 +642,12 @@ make sure that the following requirements are met: \list - \li Ensure that you are using a shared Qt library; you cannot use the - plugins with a static build. \li Ensure that the plugin is in the correct directory. You can use QApplication::libraryPaths() to determine where Qt looks for plugins. \li Ensure that the client libraries of the DBMS are available on the system. On Unix, run the command \c{ldd} and pass the name of the plugin as parameter, for example \c{ldd libqsqlmysql.so}. You will - get a warning if any of the client libraries couldn't be found. + get a warning if any of the client libraries could not be found. On Windows, you can use Visual Studio's dependency walker. With Qt Creator, you can update the \c PATH environment variable in the \gui Run section of the \gui Project panel to include the path to @@ -695,12 +657,6 @@ \endlist Make sure you have followed the guide to \l{Deploying Plugins}. - If you experience plugin load problems and see output like this: - - \snippet code/doc_src_sql-driver.cpp 31 - - the problem is usually that the plugin had the wrong build key. - This might require removing an entry from the plugin cache. \target development \section1 How to Write Your Own Database Driver @@ -737,7 +693,7 @@ must use the Q_PLUGIN_METADATA() macro. Read \l{How to Create Qt Plugins} for more information on this. You can also check out how this is done in the SQL plugins that are provided with Qt in - \c{QTDIR/qtbase/src/plugins/sqldrivers} and \c{QTDIR/qtbase/src/sql/drivers}. + \c{QTDIR/qtbase/src/plugins/sqldrivers}. The following code can be used as a skeleton for a SQL driver: From e291f6774339ada7a495b24664c4906d46233272 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 1 Dec 2017 21:22:53 +0100 Subject: [PATCH 070/102] unbreak plugin dependency tracking use the correct operator. amends 623b191c10. Change-Id: Ice8b2a82b1c7828587cccc7d464f9313e176d536 Reviewed-by: Jake Petroules --- mkspecs/features/qt_plugin.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf index 62e1b69fdee..14fc5f9a94d 100644 --- a/mkspecs/features/qt_plugin.prf +++ b/mkspecs/features/qt_plugin.prf @@ -48,7 +48,7 @@ CONFIG(static, static|shared)|prefix_build { !build_pass { qt_plugin_deps = $$QT $$QT_PRIVATE - qt_plugin_deps = s,-private$,_private,g + qt_plugin_deps ~= s,-private$,_private,g MODULE_PRI_CONT = \ "QT_PLUGIN.$${MODULE}.TYPE = $$PLUGIN_TYPE" \ From fb326ae1268aa5e5fd0c9369ccbe30fe5d6d8b62 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 1 Dec 2017 13:04:06 +0100 Subject: [PATCH 071/102] qmake: print compiler output if detection phase fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit helps enormously with debugging. Change-Id: Ic8876e74a4dbb14006d8b48658eb141a3f0e0fbf Reviewed-by: Tor Arne Vestbø --- mkspecs/features/toolchain.prf | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index ba41598be14..eb592badf48 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -19,7 +19,13 @@ defineTest(qtCompilerErrror) { what = " host" else: \ what = " target" - error("Cannot run$$what compiler '$$1'. Maybe you forgot to setup the environment?") + msg = \ + "Cannot run$$what compiler '$$1'. Output:" \ + "===================" \ + $$2 \ + "===================" \ + "Maybe you forgot to setup the environment?" + error($$join(msg, $$escape_expand(\\n))) } cross_compile:host_build: \ @@ -64,7 +70,7 @@ isEmpty($${target_prefix}.INCDIRS) { cxx_flags += -E -v output = $$system("$$cmd_prefix $$QMAKE_CXX $$qtMakeExpand($$cxx_flags) -xc++ - 2>&1 $$cmd_suffix", lines, ec) - !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX) + !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX, $$output) rim_qcc { for (line, output) { @@ -124,7 +130,7 @@ isEmpty($${target_prefix}.INCDIRS) { # What's more, -print-search-dirs can't be used on clang on Apple because it # won't print all the library paths (only the clang-internal ones). output = $$system("$$cmd_prefix $$QMAKE_CXX -print-search-dirs", lines, ec) - !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX) + !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX, $$output) for (line, output) { contains(line, "^libraries: .*") { @@ -166,14 +172,14 @@ isEmpty($${target_prefix}.INCDIRS) { defineReplace(qtVariablesFromMSVC) { ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) NUL", lines, ec) - !equals(ec, 0): qtCompilerErrror($$1) + !equals(ec, 0): qtCompilerErrror($$1, $$ret) return($$ret) } defineReplace(qtVariablesFromGCC) { ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) \ <$$QMAKE_SYSTEM_NULL_DEVICE 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec) - !equals(ec, 0): qtCompilerErrror($$1) + !equals(ec, 0): qtCompilerErrror($$1, $$ret) return($$ret) } From 0a8a7598223993c77985e99d46b20d7ea34fe8c2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 4 Dec 2017 18:32:32 +0100 Subject: [PATCH 072/102] fix namespaced build Change-Id: Ibd16658ef800afe1dec01311cc4ef1a9a6d83929 Reviewed-by: Timur Pocheptsov --- src/network/bearer/qbearerengine.cpp | 4 ++-- src/network/bearer/qnetworkconfigmanager.cpp | 4 ++-- src/network/bearer/qnetworksession.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/bearer/qbearerengine.cpp b/src/network/bearer/qbearerengine.cpp index 215cd3fdddb..677da08cb6c 100644 --- a/src/network/bearer/qbearerengine.cpp +++ b/src/network/bearer/qbearerengine.cpp @@ -93,8 +93,8 @@ bool QBearerEngine::configurationsInUse() const || hasUsedConfiguration(userChoiceConfigurations); } +QT_END_NAMESPACE + #include "moc_qbearerengine_p.cpp" #endif // QT_NO_BEARERMANAGEMENT - -QT_END_NAMESPACE diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index 7d7b7cc5b06..81b5e01d6af 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -378,8 +378,8 @@ void QNetworkConfigurationManager::updateConfigurations() priv->performAsyncConfigurationUpdate(); } -#include "moc_qnetworkconfigmanager.cpp" - QT_END_NAMESPACE +#include "moc_qnetworkconfigmanager.cpp" + #endif // QT_NO_BEARERMANAGEMENT diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index bbcd191041c..e5562e3a0b4 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -749,8 +749,8 @@ void QNetworkSession::disconnectNotify(const QMetaMethod &signal) d->setALREnabled(false); } -#include "moc_qnetworksession.cpp" - QT_END_NAMESPACE +#include "moc_qnetworksession.cpp" + #endif // QT_NO_BEARERMANAGEMENT From 7830cdd8337e3ee9bade2e2c945ce3a2a068e442 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 6 Dec 2017 11:02:07 +0100 Subject: [PATCH 073/102] configure: during early setup, skip all of default_pre.prf ... instead of only toolchain.prf. the license check could go haywire, and everything else that file does is meaningless in configure context anyway. Task-number: QTBUG-63452 Change-Id: I5e31c87fe717fda40978c0317556070637e537e2 Reviewed-by: Jake Petroules --- mkspecs/features/default_pre.prf | 3 +++ mkspecs/features/toolchain.prf | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf index 2d525251906..07a9b1c4014 100644 --- a/mkspecs/features/default_pre.prf +++ b/mkspecs/features/default_pre.prf @@ -2,6 +2,9 @@ # Note that evaluating variable assignments from the command line # still happens in between these two steps. +# In early configure setup; nothing useful to be done here. +isEmpty(QMAKE_CXX): return() + load(exclusive_builds) CONFIG = \ lex yacc debug exceptions depend_includepath \ diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index eb592badf48..fdf3d1cdd35 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -1,7 +1,4 @@ -# In early configure setup; nothing useful to be done here. -isEmpty(QMAKE_CXX): return() - defineReplace(qtMakeExpand) { out = "$$1" for(ever) { From 81b5155e8234747658d0cce210f205fd6c4736ff Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 12 Dec 2017 20:48:17 +0100 Subject: [PATCH 074/102] fix "make clean" of qmake in a builddir with spaces on mingw Change-Id: Ice61a11250694afa66f263fa79a74ff9642ef285 Reviewed-by: Thiago Macieira --- qmake/Makefile.unix.mingw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/Makefile.unix.mingw b/qmake/Makefile.unix.mingw index 2c52c07dca1..6480171c692 100644 --- a/qmake/Makefile.unix.mingw +++ b/qmake/Makefile.unix.mingw @@ -9,7 +9,7 @@ # sh-compatible shell. This is not a problem, because configure.bat # will not do that. ifeq ($(SHELL), sh.exe) - ifeq ($(wildcard $(CURDIR)/sh.exe), ) + ifeq ($(wildcard ./sh.exe), ) SH = 0 else SH = 1 From 9e1b6b6e53d01bed76dc624e4b6c0d5f7748bf85 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 28 Jul 2017 09:00:18 +0200 Subject: [PATCH 075/102] QFileSystemModel: Enable experimental code path for per-file watching QFileSystemModel had a #ifdefed out experimental code path for watching single files to track changes in size, which got outdated over time. Replace the #ifdef 0 by a check for the environment variable QT_FILESYSTEMMODEL_WATCH_FILES, fix it up and apply some fixes to related code to make it work: - Split file names signaled by QFileSystemWatcher on '/' always. - Do not instantiate QDirIterator on "", which means "current directory" and results in mixed-up directories. - Check on lastModified() in QExtendedInformation::operator==() so that changes trigger an update in _q_fileSystemChanged(). - Fix the #ifdefed out part to compile and not to add directories to the watcher. [ChangeLog][QtWidgets][QFileSystemModel] It is now possible to enable per-file watching by setting the environment variable QT_FILESYSTEMMODEL_WATCH_FILES, allowing to track for example changes in file size. Task-number: QTBUG-46684 Change-Id: Ia5da9170866416c9529251f889814b23d7a7d069 Reviewed-by: Edward Welbourne --- src/widgets/dialogs/qfileinfogatherer.cpp | 35 ++++++++++++----------- src/widgets/dialogs/qfileinfogatherer_p.h | 3 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 710ee611b92..aef13a563f7 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -196,7 +196,7 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr */ void QFileInfoGatherer::updateFile(const QString &filePath) { - QString dir = filePath.mid(0, filePath.lastIndexOf(QDir::separator())); + QString dir = filePath.mid(0, filePath.lastIndexOf(QLatin1Char('/'))); QString fileName = filePath.mid(dir.length() + 1); fetchExtendedInformation(dir, QStringList(fileName)); } @@ -267,19 +267,19 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const info.icon = m_iconProvider->icon(fileInfo); info.displayType = m_iconProvider->type(fileInfo); #ifndef QT_NO_FILESYSTEMWATCHER - // ### Not ready to listen all modifications - #if 0 - // Enable the next two commented out lines to get updates when the file sizes change... + // ### Not ready to listen all modifications by default + static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES"); + if (watchFiles) { if (!fileInfo.exists() && !fileInfo.isSymLink()) { - info.size = -1; - //watcher->removePath(fileInfo.absoluteFilePath()); + watcher->removePath(fileInfo.absoluteFilePath()); } else { - if (!fileInfo.absoluteFilePath().isEmpty() && fileInfo.exists() && fileInfo.isReadable() - && !watcher->files().contains(fileInfo.absoluteFilePath())) { - //watcher->addPath(fileInfo.absoluteFilePath()); + const QString path = fileInfo.absoluteFilePath(); + if (!path.isEmpty() && fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() + && !watcher->files().contains(path)) { + watcher->addPath(path); } } - #endif + } #endif #ifdef Q_OS_WIN @@ -329,14 +329,15 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil QVector > updatedFiles; QStringList filesToCheck = files; - QString itPath = QDir::fromNativeSeparators(files.isEmpty() ? path : QLatin1String("")); - QDirIterator dirIt(itPath, QDir::AllEntries | QDir::System | QDir::Hidden); QStringList allFiles; - while (!abort.load() && dirIt.hasNext()) { - dirIt.next(); - fileInfo = dirIt.fileInfo(); - allFiles.append(fileInfo.fileName()); - fetch(fileInfo, base, firstTime, updatedFiles, path); + if (files.isEmpty()) { + QDirIterator dirIt(path, QDir::AllEntries | QDir::System | QDir::Hidden); + while (!abort.load() && dirIt.hasNext()) { + dirIt.next(); + fileInfo = dirIt.fileInfo(); + allFiles.append(fileInfo.fileName()); + fetch(fileInfo, base, firstTime, updatedFiles, path); + } } if (!allFiles.isEmpty()) emit newListOfFiles(path, allFiles); diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 52578126ded..0cf2ed1f581 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -84,7 +84,8 @@ public: bool operator ==(const QExtendedInformation &fileInfo) const { return mFileInfo == fileInfo.mFileInfo && displayType == fileInfo.displayType - && permissions() == fileInfo.permissions(); + && permissions() == fileInfo.permissions() + && lastModified() == fileInfo.lastModified(); } #ifndef QT_NO_FSFILEENGINE From 1adb1ef6bab6247f5914e94380f8b05e11cb8d7e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 30 Oct 2017 15:16:33 +0100 Subject: [PATCH 076/102] QStyleSheetStyle: Draw menu item also when font is set Task-number: QTBUG-64055 Change-Id: I0674e7b43bb56aa1834c8df10794714dbcc4e5e3 Reviewed-by: Andy Shaw --- src/widgets/styles/qstylesheetstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 6a99d21988e..e8b90b87b30 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3655,7 +3655,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if ((pseudo == PseudoElement_MenuSeparator) && subRule.hasDrawable()) { subRule.drawRule(p, opt->rect); } else if ((pseudo == PseudoElement_Item) - && (allRules.hasBox() || allRules.hasBorder() + && (allRules.hasBox() || allRules.hasBorder() || subRule.hasFont || (allRules.background() && !allRules.background()->pixmap.isNull()))) { subRule.drawRule(p, opt->rect); if (subRule.hasBackground()) { From dc0bb57f8600374b7279d5c14456a33a9d0c0476 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 11 Dec 2017 21:59:42 -0800 Subject: [PATCH 077/102] Fix an issue causing asset catalogs to be miscompiled with iOS simulator This works around the inability to build iOS apps for a "generic" simulator by explicitly setting the Xcode build setting ENABLE_ONLY_ACTIVE_RESOURCES to NO in order to ensure that all variants of assets in an asset catalog are built when targeting iOS simulator devices. Otherwise, we will simply build for whatever the first simulator in the list happens to be. If the application is then deployed to a different simulator, some of the assets needed for that device variant may be missing. This "helps" QTCREATORBUG-19447 but is not a workaround since this fix is necessary for command line builds anyways, even though it's unlikely to crop up in practice there, since one would have to manually deploy the built application bundle to the simulator using simctl rather than going through Xcode (which would rebuild for the appropriate device). Change-Id: Ia41c48dcc715fe79a2c50db66a0ca7a1fea159c2 Reviewed-by: Vikas Pachdha Reviewed-by: Oswald Buddenhagen --- mkspecs/features/uikit/xcodebuild.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/uikit/xcodebuild.mk b/mkspecs/features/uikit/xcodebuild.mk index 0b3ad632b6c..7d3275df65f 100644 --- a/mkspecs/features/uikit/xcodebuild.mk +++ b/mkspecs/features/uikit/xcodebuild.mk @@ -90,7 +90,7 @@ DESTINATION_MESSAGE = "Running $(call tolower,$(CONFIGURATION)) $(ACTION) \ xcodebuild-%: @$(if $(DESTINATION_NAME), echo $(DESTINATION_MESSAGE),) - xcodebuild $(ACTION) $(XCODEBUILD_FLAGS) -project $(TARGET).xcodeproj -scheme $(TARGET) $(if $(SDK), -sdk $(SDK),) $(if $(CONFIGURATION), -configuration $(CONFIGURATION),) $(if $(DESTINATION), -destination $(DESTINATION) -destination-timeout 1,) $(if $(INSTALL_ROOT), DSTROOT=$(INSTALL_ROOT),) + xcodebuild $(ACTION) $(XCODEBUILD_FLAGS) -project $(TARGET).xcodeproj -scheme $(TARGET) $(if $(SDK), -sdk $(SDK),) $(if $(CONFIGURATION), -configuration $(CONFIGURATION),) $(if $(DESTINATION), -destination $(DESTINATION) -destination-timeout 1,) $(if $(DESTINATION_ID),, ENABLE_ONLY_ACTIVE_RESOURCES=NO) $(if $(INSTALL_ROOT), DSTROOT=$(INSTALL_ROOT),) xcodebuild-check-device_%: DESTINATION_ID=$(lastword $(subst _, ,$@)) From fddc5a27b180d7afde37e2c004cee95302e907ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 14 Dec 2017 12:32:35 +0100 Subject: [PATCH 078/102] macOS: Enable using CoreGraphics helper functions from C++ sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If32c96d224bfb90ba22661b6f5ac3c920acb39d2 Reviewed-by: Morten Johan Sørvig --- src/gui/painting/qcoregraphics_p.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h index d74c4d0711f..6b6a1e800e3 100644 --- a/src/gui/painting/qcoregraphics_p.h +++ b/src/gui/painting/qcoregraphics_p.h @@ -56,13 +56,15 @@ #include #include -#ifdef Q_OS_MACOS + +#if defined(__OBJC__) && defined(Q_OS_MACOS) #include +#define HAVE_APPKIT #endif QT_BEGIN_NAMESPACE -#ifdef Q_OS_MACOS +#ifdef HAVE_APPKIT Q_GUI_EXPORT NSImage *qt_mac_create_nsimage(const QPixmap &pm); Q_GUI_EXPORT NSImage *qt_mac_create_nsimage(const QIcon &icon, int defaultSize = 0); Q_GUI_EXPORT QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size); @@ -78,7 +80,7 @@ Q_GUI_EXPORT CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice * Q_GUI_EXPORT void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform); -#ifdef Q_OS_MACOS +#ifdef HAVE_APPKIT Q_GUI_EXPORT QColor qt_mac_toQColor(const NSColor *color); Q_GUI_EXPORT QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup = QPalette::Normal); #endif @@ -124,4 +126,6 @@ private: QT_END_NAMESPACE +#undef HAVE_APPKIT + #endif // QCOREGRAPHICS_P_H From 039ac7d20c1643246f9041204d59096e143127a7 Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Tue, 21 Nov 2017 13:12:24 +0200 Subject: [PATCH 079/102] Add mkspec for INTEGRITY Multivisor on the Renesas Salvator-X Change-Id: Ie8d2f5c022a6a2396534cebf1f17cbb8df92cb27 Reviewed-by: Oswald Buddenhagen Reviewed-by: Kimmo Ollila Reviewed-by: Laszlo Agocs --- mkspecs/integrity-armv8-rcar/qmake.conf | 33 +++++++++++++++++ mkspecs/integrity-armv8-rcar/qplatformdefs.h | 39 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 mkspecs/integrity-armv8-rcar/qmake.conf create mode 100644 mkspecs/integrity-armv8-rcar/qplatformdefs.h diff --git a/mkspecs/integrity-armv8-rcar/qmake.conf b/mkspecs/integrity-armv8-rcar/qmake.conf new file mode 100644 index 00000000000..46091f6a913 --- /dev/null +++ b/mkspecs/integrity-armv8-rcar/qmake.conf @@ -0,0 +1,33 @@ +# +# qmake configuration for INTEGRITY armv7 targets +# + +# armv7 common includes work for armv8-A as well +include(../common/ghs-integrity-armv7.conf) + +DEFINES += INTEGRITY + +# This define is used because the RCar INTEGRITY EGL library expects same +# parameter types as Symbian. The parameter types are defined in eglplatform.h. +DEFINES += __WINSCW__ + +QTPLUGIN.platforms += qeglfs +QT_QPA_DEFAULT_PLATFORM = eglfs + +QMAKE_LIBS_EGL += -lEGL -lIMGegl -lsrv_um -lsrv_init -lpvrWSEGL_WM -lncg_usr.a -lmmgr_usr -lwm_usr -lprr_usr +QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lIMGegl -lglslcompiler -lusc -lsrv_um -lsrv_init -lpvrWSEGL_WM -lncg_usr.a -lmmgr_usr -lwm_usr -lprr_usr +QMAKE_LIBS_GUI = -lmmgr_usr -lwm_usr -lprr_usr + +QMAKE_CFLAGS += -bigswitch +QMAKE_CXXFLAGS += -bigswitch +QMAKE_LFLAGS += -bigswitch + +EGLFS_DEVICE_INTEGRATION = eglfs_rcar + +# OpenGL libraries have a dependency on libEGL +dirs = $$(GL_INC_DIR) +QMAKE_INCDIR_EGL = $$split(dirs, $$QMAKE_DIRLIST_SEP) +QMAKE_INCDIR_OPENGL_ES2 = $$QMAKE_INCDIR_EGL +dirs = $$(GL_LIB_DIR) +QMAKE_LIBDIR_EGL = $$split(dirs, $$QMAKE_DIRLIST_SEP) +QMAKE_LIBDIR_OPENGL_ES2 = $$QMAKE_LIBDIR_EGL diff --git a/mkspecs/integrity-armv8-rcar/qplatformdefs.h b/mkspecs/integrity-armv8-rcar/qplatformdefs.h new file mode 100644 index 00000000000..55afd0c3c7b --- /dev/null +++ b/mkspecs/integrity-armv8-rcar/qplatformdefs.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Green Hills Software. All rights reserved. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/integrity/qplatformdefs.h" + +#endif // QPLATFORMDEFS_H From f2f75c02287f936067e3e04ea452fbe8bbab14d1 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 12 Dec 2017 13:45:39 +0100 Subject: [PATCH 080/102] Doc: Fix paths to 3rdparty license files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix paths added in 870423f98ba4a3a. This caused havoc on case sensitive file systems. [ChangeLog][Third-Party Code] Fixed glitch in attribution documentation for Freetype licenses / Qt Gui. Task-number: QTBUG-65138 Change-Id: Idb20a1ead772337f97a1262da42c62f6aef04a54 Reviewed-by: Topi Reiniö --- src/3rdparty/freetype/qt_attribution.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index e00f2062b04..4be86e92b6d 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -9,7 +9,7 @@ "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", + "LicenseFile": "LICENSE.txt", "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." }, { @@ -22,7 +22,7 @@ "Homepage": "http://www.freetype.org", "License": "zlib License", "LicenseId": "Zlib", - "LicenseFile": "ZLIB-LICENSE.TXT", + "LicenseFile": "ZLIB-LICENSE.txt", "Copyright": "Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler" }, { @@ -35,7 +35,7 @@ "Homepage": "http://www.freetype.org", "License": "MIT License", "LicenseId": "MIT", - "LicenseFile": "BDF-LICENSE.TXT", + "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" @@ -50,7 +50,7 @@ Copyright 2001-2002, 2011 Francesco Zappa Nardelli" "Homepage": "http://www.freetype.org", "License": "MIT License", "LicenseId": "MIT", - "LicenseFile": "PCF-LICENSE.TXT", + "LicenseFile": "PCF-LICENSE.txt", "Copyright": "Copyright (C) 2000 by Francesco Zappa Nardelli" } ] From 034e92b0f4f49432e170184fb84e29c315d3f279 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 14 Dec 2017 13:15:05 +0100 Subject: [PATCH 081/102] Android: Set correct input hints when queried through getCursorCapsMode getCursorCapsMode() now matches the Java implementation in QtActivityDelegate.showSoftwareKeyboard() which is given to the Android keyboard on InputConnection creation. The reason we only saw this bug with some Android keyboards was that many keyboards never call getCursorCapsMode and just rely on the initial hints. Task-number: QTBUG-51865 Change-Id: I2aae024d9c77ea14e087e3f51a413d15a684179c Reviewed-by: Paul Olav Tvete Reviewed-by: Christian Stromme --- src/plugins/platforms/android/qandroidinputcontext.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index ccc7f06b6be..fe4c5be4cba 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -847,11 +847,11 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/) const uint qtInputMethodHints = query->value(Qt::ImHints).toUInt(); - if (qtInputMethodHints & Qt::ImhPreferUppercase) - res = CAP_MODE_SENTENCES; + if (!(qtInputMethodHints & Qt::ImhLowercaseOnly) && !(qtInputMethodHints & Qt::ImhNoAutoUppercase)) + res |= CAP_MODE_SENTENCES; if (qtInputMethodHints & Qt::ImhUppercaseOnly) - res = CAP_MODE_CHARACTERS; + res |= CAP_MODE_CHARACTERS; return res; } From dffa01a438f971089f6609bc8c2406ca19fba724 Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Tue, 21 Nov 2017 13:09:09 +0200 Subject: [PATCH 082/102] Add EGLFS integration plugin for Salvator-X on INTEGRITY Multivisor This plugin uses the Renesas RISP Window Manager. Change-Id: If813c46ab8d39e966c0a969610841867885dd473 Reviewed-by: Laszlo Agocs --- src/gui/configure.json | 23 ++- .../deviceintegration/deviceintegration.pro | 1 + .../eglfs_rcar/eglfs_rcar.json | 3 + .../eglfs_rcar/eglfs_rcar.pro | 19 +++ .../eglfs_rcar/qeglfsrcarintegration.cpp | 159 ++++++++++++++++++ .../eglfs_rcar/qeglfsrcarintegration.h | 66 ++++++++ .../eglfs_rcar/qeglfsrcarmain.cpp | 57 +++++++ 7 files changed, 327 insertions(+), 1 deletion(-) create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp diff --git a/src/gui/configure.json b/src/gui/configure.json index 9710ee4e202..23ed9487a89 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -716,6 +716,22 @@ }, "use": "egl" }, + "egl-rcar": { + "label": "RCAR EGL", + "type": "compile", + "test": { + "include": [ "EGL/egl.h" ], + "tail": [ + "extern \"C\" {", + "extern unsigned long PVRGrfxServerInit(void);", + "}" + ], + "main": [ + "PVRGrfxServerInit();" + ] + }, + "use": "egl opengl_es2" + }, "evdev": { "label": "evdev", "type": "compile", @@ -1094,6 +1110,11 @@ "condition": "features.eglfs && tests.egl-viv", "output": [ "privateFeature" ] }, + "eglfs_rcar": { + "label": "EGLFS RCAR", + "condition": "config.integrity && features.eglfs && tests.egl-rcar", + "output": [ "privateFeature" ] + }, "eglfs_viv_wl": { "label": "EGLFS i.Mx6 Wayland", "condition": "features.eglfs_viv && libs.wayland_server", @@ -1576,7 +1597,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "section": "EGLFS details", "condition": "features.eglfs", "entries": [ - "eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_egldevice", "eglfs_gbm", "eglfs_mali", "eglfs_brcm", "egl_x11" + "eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_rcar", "eglfs_egldevice", "eglfs_gbm", "eglfs_mali", "eglfs_brcm", "egl_x11" ] }, "linuxfb", "vnc", "mirclient", diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 2cddbe9beb7..92ee83fd8f8 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -7,6 +7,7 @@ qtConfig(eglfs_egldevice): SUBDIRS *= eglfs_kms_support eglfs_kms_egldevice qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm qtConfig(eglfs_mali): SUBDIRS += eglfs_mali qtConfig(eglfs_viv): SUBDIRS += eglfs_viv +qtConfig(eglfs_rcar): SUBDIRS += eglfs_rcar qtConfig(eglfs_viv_wl): SUBDIRS += eglfs_viv_wl qtConfig(eglfs_openwfd): SUBDIRS += eglfs_openwfd qtConfig(opengl): SUBDIRS += eglfs_emu diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json new file mode 100644 index 00000000000..77b3083eef5 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_rcar" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro new file mode 100644 index 00000000000..04236449a0b --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro @@ -0,0 +1,19 @@ +TARGET = qeglfs-rcar-integration + +QT += core-private gui-private eglfsdeviceintegration-private + +INCLUDEPATH += $$PWD/../../api +CONFIG += egl +DEFINES += LINUX=1 EGL_API_FB=1 +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsrcarmain.cpp \ + $$PWD/qeglfsrcarintegration.cpp + +HEADERS += $$PWD/qeglfsrcarintegration.h + +OTHER_FILES += $$PWD/eglfs_rcar.json + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSRcarIntegrationPlugin +load(qt_plugin) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp new file mode 100644 index 00000000000..98cf1d3bfb9 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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$ +** +****************************************************************************/ + +#include +#include +#include +#include "INTEGRITY.h" +#include "qeglfsrcarintegration.h" + +#define RCAR_DEFAULT_DISPLAY 1 +#define RCAR_DEFAULT_WM_LAYER 2 + +extern "C" unsigned long PVRGrfxServerInit(void); + +QT_BEGIN_NAMESPACE + +void QEglFSRcarIntegration::platformInit() +{ + QEglFSDeviceIntegration::platformInit(); + + PVRGrfxServerInit(); + + mScreenSize = q_screenSizeFromFb(0); + mNativeDisplay = (NativeDisplayType)EGL_DEFAULT_DISPLAY; +} + +QSize QEglFSRcarIntegration::screenSize() const +{ + return mScreenSize; +} + +EGLNativeDisplayType QEglFSRcarIntegration::platformDisplay() const +{ + return mNativeDisplay; +} + +static r_wm_WinColorFmt_t getWMColorFormat(const QSurfaceFormat &format) +{ + const int a = format.alphaBufferSize(); + const int r = format.redBufferSize(); + const int g = format.greenBufferSize(); + const int b = format.blueBufferSize(); + + switch (r) { + case 4: + if (g == 4 && b == 4 && a == 4) + return R_WM_COLORFMT_ARGB4444; + break; + case 5: + if (g == 6 && b == 5 && a == 0) + return R_WM_COLORFMT_RGB565; + else if (g == 5 && b == 5 && a == 1) + return R_WM_COLORFMT_ARGB1555; + break; + case 8: + if (g == 8 && b == 8 && a == 0) + return R_WM_COLORFMT_RGB0888; + else if (g == 8 && b == 8 && a == 8) + return R_WM_COLORFMT_ARGB8888; + break; + } + + qFatal("Unsupported color format: R:%d G:%d B:%d A:%d", r, g, b, a); + return R_WM_COLORFMT_LAST; +} + +EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) +{ + bool ok; + + mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); + if (!ok) + mNativeDisplayID = RCAR_DEFAULT_DISPLAY; + + r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); + + mNativeWindow = (EGLNativeWindowTypeREL*)malloc(sizeof(EGLNativeWindowTypeREL)); + memset(mNativeWindow, 0, sizeof(EGLNativeWindowTypeREL)); + + mNativeWindow->ColorFmt = getWMColorFormat(format); + mNativeWindow->PosX = 0; + mNativeWindow->PosY = 0; + mNativeWindow->PosZ = qEnvironmentVariableIntValue("QT_QPA_WM_LAYER", &ok); + if (!ok) + mNativeWindow->PosZ = RCAR_DEFAULT_WM_LAYER; + mNativeWindow->Pitch = size.width(); + mNativeWindow->Width = size.width(); + mNativeWindow->Height = size.height(); + mNativeWindow->Alpha = format.alphaBufferSize(); + + if (format.swapBehavior() == QSurfaceFormat::DefaultSwapBehavior) + mNativeWindow->Surface.BufNum = 3; + else + mNativeWindow->Surface.BufNum = format.swapBehavior(); + + mNativeWindow->Surface.Type = R_WM_SURFACE_FB; + mNativeWindow->Surface.BufMode = R_WM_WINBUF_ALLOC_INTERNAL; + + wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to create window layer: %d", wm_err); + wm_err = R_WM_DevEventRegister(mNativeDisplayID, R_WM_EVENT_VBLANK, 0); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to Register vsync event: %d", wm_err); + wm_err = R_WM_WindowEnable(mNativeDisplayID, mNativeWindow); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to Enable window surface: %d", wm_err); + + return static_cast(mNativeWindow); +} + +void QEglFSRcarIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + R_WM_WindowDisable(mNativeDisplayID, mNativeWindow); + usleep(100000); //Needed to allow Window Manager make the window transparent + R_WM_WindowDelete(mNativeDisplayID, mNativeWindow); + R_WM_DevDeinit(mNativeDisplayID); + free(mNativeWindow); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h new file mode 100644 index 00000000000..08911594f9b --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QEGLFSVIVINTEGRATION_H +#define QEGLFSVIVINTEGRATION_H + +#include "private/qeglfsdeviceintegration_p.h" +#include "EGL/eglext_REL.h" + +QT_BEGIN_NAMESPACE + +class QEglFSRcarIntegration : public QEglFSDeviceIntegration +{ +public: + void platformInit() override; + QSize screenSize() const override; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override; + void destroyNativeWindow(EGLNativeWindowType window) override; + EGLNativeDisplayType platformDisplay() const override; + +private: + QSize mScreenSize; + EGLNativeDisplayType mNativeDisplay; + EGLNativeWindowTypeREL *mNativeWindow; + int mNativeDisplayID; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp new file mode 100644 index 00000000000..6cf3e1387de --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarmain.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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$ +** +****************************************************************************/ + +#include "INTEGRITY.h" +#include "private/qeglfsdeviceintegration_p.h" +#include "qeglfsrcarintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSRcarIntegrationPlugin : public QEglFSDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_rcar.json") + +public: + QEglFSDeviceIntegration *create() override { return new QEglFSRcarIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsrcarmain.moc" From c10f2aaeb77c3da609be0f7d88ed6641a256953d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 11 Dec 2017 10:18:44 +0100 Subject: [PATCH 083/102] Disable WiFi bearer plugins on macOS and Windows Scanning for WiFi networks is causing network disruptions in the form of higher latency, sometimes globally for all running applications. In practice, the default configuration selection algorithm in QNetworkConfigurationManager prefers configurations from the generic bearer plugin, due to the way the plugins are ordered. Removing the platform WiFi bearers should have no effect on default network configuration selection. Task-number: QTBUG-40332 Change-Id: I778281c41a1aaec1949c220a9266677bd788a57a Reviewed-by: Timur Pocheptsov --- src/plugins/bearer/bearer.pro | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index b362722b282..824fd0388f9 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -6,11 +6,6 @@ QT_FOR_CONFIG += network-private SUBDIRS += connman networkmanager } -#win32:SUBDIRS += nla -win32:SUBDIRS += generic -win32:!winrt: SUBDIRS += nativewifi -darwin:qtConfig(corewlan): SUBDIRS += corewlan -mac:SUBDIRS += generic android:SUBDIRS += android isEmpty(SUBDIRS):SUBDIRS = generic From 9fbd9e066e6df19fef8eed77ec27c74124330c0a Mon Sep 17 00:00:00 2001 From: Karim Pinter Date: Fri, 15 Dec 2017 13:01:58 +0200 Subject: [PATCH 084/102] Derive QPpsObjectPrivate from QObjectPrivate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes 5d4089299ab4c39463e228e5896a3010268a36f2 commit, which was causing a build break if qnx pps is enabled. Change-Id: I8c29f48bde0187a9db02d6325e8a9a0fae760bcb Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qppsobjectprivate_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h index e1d54e58de0..dae44e36091 100644 --- a/src/corelib/kernel/qppsobjectprivate_p.h +++ b/src/corelib/kernel/qppsobjectprivate_p.h @@ -57,13 +57,15 @@ #include #include +#include QT_BEGIN_NAMESPACE class QSocketNotifier; -class QPpsObjectPrivate +class QPpsObjectPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QPpsObject) public: explicit QPpsObjectPrivate(const QString &path); From 93dabeba9dc5f6cbab60e65b3cc8df5fe48745a9 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 17 Nov 2017 20:57:00 +0100 Subject: [PATCH 085/102] QTreeView: Make sure QHeaderView is notified on layoutChanged() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QHeaderViewPrivate::_q_layoutChanged() was not called when used in a QTreeView because it was explicitly disconnected in setModel(). The disconnect was added sometime prio to Qt 4.3, but there the signal was connected to the doItemsLayout() slot. This was correct since QTreeView::doItemsLayout() is calling header->doItemsLayout(). In Qt 4.3.0 _q_layoutChanged() was introduced and the disconnect was adjusted. But since _q_layoutChanged() is doing much more than doItemsLayout() (e.g. restoring hidden sections), functionality was lost. The problem was already observed for Qt 4.6 (QTBUG-18196) but only partially fixed. Task-number: QTBUG-41124 Task-number: QTBUG-54610 Change-Id: Id13a9930d0163812e12a0287016bab9c3aa02068 Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qtreeview.cpp | 3 --- .../itemviews/qtreeview/tst_qtreeview.cpp | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index bbbadecff82..20e99d2aeef 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -237,9 +237,6 @@ void QTreeView::setModel(QAbstractItemModel *model) // QAbstractItemView connects to a private slot disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); - // do header layout after the tree - disconnect(d->model, SIGNAL(layoutChanged()), - d->header, SLOT(_q_layoutChanged())); // QTreeView has a public slot for this connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(rowsRemoved(QModelIndex,int,int))); diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index dfcaa9b5b91..5de0ca6c229 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -313,6 +313,17 @@ public: endRemoveColumns(); } + void removeAddLastColumnLayoutChanged() // for taskQTBUG_41124 + { + // make sure QHeaderView::_q_layoutChanged() is called + emit layoutAboutToBeChanged(); + --cols; + emit layoutChanged(); + emit layoutAboutToBeChanged(); + ++cols; + emit layoutChanged(); + } + void removeAllColumns() { beginRemoveColumns(QModelIndex(), 0, cols - 1); @@ -1306,6 +1317,19 @@ void tst_QTreeView::columnHidden() for (int c = 0; c < model.columnCount(); ++c) QCOMPARE(view.isColumnHidden(c), true); view.update(); + + // QTBUG_41124: + // QHeaderViewPrivate::_q_layoutChanged was not called because it was + // disconnected in QTreeView::setModel(). _q_layoutChanged restores + // the hidden sections which is tested here + view.setColumnHidden(model.cols - 1, true); + model.removeAddLastColumnLayoutChanged(); + // we removed the last column and added a new one + // (with layoutToBeChanged/layoutChanged() for both) so column + // 1 is a new column and therefore must not be hidden when + // _q_layoutChanged() is called and is doing the right stuff + QCOMPARE(view.isColumnHidden(model.cols - 1), false); + } void tst_QTreeView::rowHidden() From 3841a7dd49667ceabdcbc416fa1e149bed7ed86e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 12 Dec 2017 15:53:44 +0100 Subject: [PATCH 086/102] Prevent infinite relayout when adding scrollbars When one scrollbar is added, this may cause the other to be needed as well. This change does a second calculation immediately instead of relying on a signal through a QueuedConnection. Task-number: QTBUG-62818 Task-number: QTBUG-56280 Change-Id: Iee9a083e3a6cd3765e6bb9206687a8a6e7f99cff Reviewed-by: Paul Olav Tvete Reviewed-by: Andy Nichols --- src/widgets/widgets/qabstractscrollarea.cpp | 25 ++++++++++++++++----- src/widgets/widgets/qabstractscrollarea_p.h | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 249ebd35d32..c6d66bafd4b 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -333,17 +333,28 @@ void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on) #endif void QAbstractScrollAreaPrivate::layoutChildren() +{ + bool needH = false; + bool needV = false; + layoutChildren_helper(&needH, &needV); + // Call a second time if one scrollbar was needed and not the other to + // check if it needs to readjust accordingly + if (needH != needV) + layoutChildren_helper(&needH, &needV); +} + +void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrollbar, bool *needVerticalScrollbar) { Q_Q(QAbstractScrollArea); bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, hbar); - bool needh = (hbarpolicy != Qt::ScrollBarAlwaysOff) && ((hbarpolicy == Qt::ScrollBarAlwaysOn && !htransient) - || ((hbarpolicy == Qt::ScrollBarAsNeeded || htransient) - && hbar->minimum() < hbar->maximum() && !hbar->sizeHint().isEmpty())); + bool needh = *needHorizontalScrollbar || ((hbarpolicy != Qt::ScrollBarAlwaysOff) && ((hbarpolicy == Qt::ScrollBarAlwaysOn && !htransient) + || ((hbarpolicy == Qt::ScrollBarAsNeeded || htransient) + && hbar->minimum() < hbar->maximum() && !hbar->sizeHint().isEmpty()))); bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar); - bool needv = (vbarpolicy != Qt::ScrollBarAlwaysOff) && ((vbarpolicy == Qt::ScrollBarAlwaysOn && !vtransient) - || ((vbarpolicy == Qt::ScrollBarAsNeeded || vtransient) - && vbar->minimum() < vbar->maximum() && !vbar->sizeHint().isEmpty())); + bool needv = *needVerticalScrollbar || ((vbarpolicy != Qt::ScrollBarAlwaysOff) && ((vbarpolicy == Qt::ScrollBarAlwaysOn && !vtransient) + || ((vbarpolicy == Qt::ScrollBarAsNeeded || vtransient) + && vbar->minimum() < vbar->maximum() && !vbar->sizeHint().isEmpty()))); QStyleOption opt(0); opt.init(q); @@ -522,6 +533,8 @@ void QAbstractScrollAreaPrivate::layoutChildren() viewportRect.adjust(left, top, -right, -bottom); viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last + *needHorizontalScrollbar = needh; + *needVerticalScrollbar = needv; } /*! diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h index c52e7f9fd49..49f97bcb61a 100644 --- a/src/widgets/widgets/qabstractscrollarea_p.h +++ b/src/widgets/widgets/qabstractscrollarea_p.h @@ -95,6 +95,7 @@ public: void init(); void layoutChildren(); + void layoutChildren_helper(bool *needHorizontalScrollbar, bool *needVerticalScrollbar); // ### Fix for 4.4, talk to Bjoern E or Girish. virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {} bool canStartScrollingAt( const QPoint &startPos ); From 0857db89bf2d36a1501c708521daacdbc83d5c5b Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 6 Dec 2017 17:45:53 +0100 Subject: [PATCH 087/102] Widgets: check if parent exists before calling parent->locale() If a top level, parentless widget has Qt::WA_WindowPropagation set, Qt will crash when trying to resolve the widgets locale. The reason is that we try to access the QLocale of the non-existing parent. This patch will add a check if a parent exists before trying to access it. Task-number: QTBUG-61213 Change-Id: I09a6351a12dc1fffab3069b70e3d7b3932317c85 Reviewed-by: Edward Welbourne --- src/widgets/kernel/qwidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index b57a0d47798..b38565493e1 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6007,9 +6007,9 @@ void QWidgetPrivate::resolveLocale() Q_Q(const QWidget); if (!q->testAttribute(Qt::WA_SetLocale)) { - setLocale_helper(q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation) - ? QLocale() - : q->parentWidget()->locale()); + QWidget *parent = q->parentWidget(); + setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) + ? QLocale() : parent->locale()); } } From b0938cb6c1fa29ec2d2a4fb9273e515cd0d6c08e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 17 Dec 2017 11:42:41 +0100 Subject: [PATCH 088/102] QGestureManager: fix UB (invalid pointer comparison) Comparing pointers with op< that do not point into the same array is UB. Fix, in the usual way, by using std::less. Change-Id: Id2c957557719887b2016632d683dbab8af07b34c Reviewed-by: Thiago Macieira --- src/widgets/kernel/qgesturemanager_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h index e57652afbac..3df80bab55c 100644 --- a/src/widgets/kernel/qgesturemanager_p.h +++ b/src/widgets/kernel/qgesturemanager_p.h @@ -59,6 +59,8 @@ #ifndef QT_NO_GESTURES +#include + QT_BEGIN_NAMESPACE class QBasicTimer; @@ -112,7 +114,7 @@ private: ObjectGesture(QObject *o, const Qt::GestureType &g) : object(o), gesture(g) { } inline bool operator<(const ObjectGesture &rhs) const { - if (object < rhs.object) + if (std::less{}(object, rhs.object)) return true; if (object == rhs.object) return gesture < rhs.gesture; From 3af9d774316ef0edf65acb478871d89231b930f2 Mon Sep 17 00:00:00 2001 From: Karim Pinter Date: Fri, 15 Dec 2017 12:56:47 +0200 Subject: [PATCH 089/102] Fix pps and imf support for QNX builds Change from config to feature in the json and pro files. Change-Id: I58ddac3c4ad739253bae010f1d5023fc1d481047 Reviewed-by: Oswald Buddenhagen --- src/corelib/configure.json | 2 +- src/corelib/kernel/kernel.pri | 2 +- src/gui/configure.json | 2 +- src/plugins/platforms/qnx/qnx.pro | 20 ++++++------- src/plugins/platforms/qnx/qqnxintegration.cpp | 29 +++++++++---------- src/plugins/platforms/qnx/qqnxintegration.h | 8 ++--- 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 3db9942123b..6002e1d4fc8 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -509,7 +509,7 @@ "label": "PPS", "emitIf": "config.qnx", "condition": "libs.pps", - "output": [ "privateConfig" ] + "output": [ "privateFeature" ] }, "qeventtransition": { "label": "QEventTransition class", diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 29bd5bbc6c1..9bc6e198f83 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -187,7 +187,7 @@ vxworks { kernel/qfunctions_vxworks.h } -qqnx_pps { +qnx:qtConfig(qqnx_pps) { QMAKE_USE_PRIVATE += pps SOURCES += \ kernel/qppsattribute.cpp \ diff --git a/src/gui/configure.json b/src/gui/configure.json index 23ed9487a89..1252dc507c2 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -956,7 +956,7 @@ "label": "IMF", "emitIf": "config.qnx", "condition": "libs.imf", - "output": [ "privateConfig" ] + "output": [ "privateFeature" ] }, "integrityfb": { "label": "INTEGRITY framebuffer", diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 34be6d582e2..15d33200e5f 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -81,26 +81,26 @@ qtConfig(opengles2) { QMAKE_USE += opengl_es2 egl } -CONFIG(qqnx_pps) { - DEFINES += QQNX_PPS - - SOURCES += qqnxclipboard.cpp \ - qqnxbuttoneventnotifier.cpp \ +qtConfig(qqnx_pps) { + SOURCES += qqnxbuttoneventnotifier.cpp \ qqnxnavigatorpps.cpp \ qqnxnavigatoreventnotifier.cpp \ qqnxvirtualkeyboardpps.cpp - HEADERS += qqnxclipboard.h \ - qqnxbuttoneventnotifier.h \ + HEADERS += qqnxbuttoneventnotifier.h \ qqnxnavigatorpps.h \ qqnxnavigatoreventnotifier.h \ qqnxvirtualkeyboardpps.h QMAKE_USE += pps - !contains(DEFINES, QT_NO_CLIPBOARD): LIBS += -lclipboard - CONFIG(qqnx_imf) { - DEFINES += QQNX_IMF + qtConfig(clipboard) { + SOURCES += qqnxclipboard.cpp + HEADERS += qqnxclipboard.h + LIBS += -lclipboard + } + + qtConfig(qqnx_imf) { HEADERS += qqnxinputcontext_imf.h SOURCES += qqnxinputcontext_imf.cpp } else { diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index eee05817092..072510e0528 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -56,17 +56,16 @@ #include "qqnxeglwindow.h" #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) #include "qqnxnavigatorpps.h" #include "qqnxnavigatoreventnotifier.h" #include "qqnxvirtualkeyboardpps.h" #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) # include "qqnxbuttoneventnotifier.h" # include "qqnxclipboard.h" - -# if defined(QQNX_IMF) +# if QT_CONFIG(qqnx_imf) # include "qqnxinputcontext_imf.h" # else # include "qqnxinputcontext_noimf.h" @@ -126,7 +125,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) , m_screenEventThread(0) , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) , m_virtualKeyboard(0) -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) , m_navigatorEventNotifier(0) , m_inputContext(0) , m_buttonsNotifier(new QQnxButtonEventNotifier()) @@ -150,7 +149,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) Q_SCREEN_CRITICALERROR(screen_create_context(&ms_screenContext, SCREEN_APPLICATION_CONTEXT), "Failed to create screen context"); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Create/start navigator event notifier m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler); @@ -168,7 +167,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler); m_screenEventThread->start(); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Create/start the keyboard class. m_virtualKeyboard = new QQnxVirtualKeyboardPps(); @@ -177,7 +176,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection); #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) m_navigator = new QQnxNavigatorPps(); #endif @@ -192,16 +191,16 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)), primaryDisplay(), SLOT(keyboardHeightChanged(int))); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Set up the input context m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard); -#if defined(QQNX_IMF) +#if QT_CONFIG(qqnx_imf) m_screenEventHandler->addScreenEventFilter(m_inputContext); #endif #endif } -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // delay invocation of start() to the time the event loop is up and running // needed to have the QThread internals of the main thread properly initialized QMetaObject::invokeMethod(m_buttonsNotifier, "start", Qt::QueuedConnection); @@ -224,7 +223,7 @@ QQnxIntegration::~QQnxIntegration() #endif // Stop/destroy navigator event notifier -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) delete m_navigatorEventNotifier; #endif delete m_navigatorEventHandler; @@ -248,7 +247,7 @@ QQnxIntegration::~QQnxIntegration() QQnxGLContext::shutdownContext(); #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) // Destroy the hardware button notifier delete m_buttonsNotifier; @@ -318,7 +317,7 @@ QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLCont } #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QPlatformInputContext *QQnxIntegration::inputContext() const { qIntegrationDebug(); @@ -361,7 +360,7 @@ QPlatformClipboard *QQnxIntegration::clipboard() const { qIntegrationDebug(); -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) if (!m_clipboard) m_clipboard = new QQnxClipboard; #endif diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index b2008baa0cf..d1ebb1d4bf6 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -41,7 +41,7 @@ #define QQNXINTEGRATION_H #include - +#include #include #include @@ -61,7 +61,7 @@ class QQnxServices; class QSimpleDrag; -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) class QQnxInputContext; class QQnxNavigatorEventNotifier; class QQnxButtonEventNotifier; @@ -96,7 +96,7 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; #endif -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QPlatformInputContext *inputContext() const override; #endif @@ -143,7 +143,7 @@ private: QQnxScreenEventThread *m_screenEventThread; QQnxNavigatorEventHandler *m_navigatorEventHandler; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; -#if defined(QQNX_PPS) +#if QT_CONFIG(qqnx_pps) QQnxNavigatorEventNotifier *m_navigatorEventNotifier; QQnxInputContext *m_inputContext; QQnxButtonEventNotifier *m_buttonsNotifier; From 77347a3699f8f236e1d440fb514ff8225ed5971b Mon Sep 17 00:00:00 2001 From: Alexander Shevchenko Date: Tue, 19 Dec 2017 11:20:07 +0200 Subject: [PATCH 090/102] unify windows mkspecs: delete redundants mingw-w64 toolchain: - remove 'QMAKE_CXXFLAGS_THREAD' variable definition, since 'QMAKE_CFLAGS_THREAD' variable not set for mingw-w64 toolchain. ICC on Windows toolchain: - remove 'QMAKE_LFLAGS', 'QMAKE_LFLAGS_RELEASE', 'QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO' and 'QMAKE_LFLAGS_DEBUG' definitions, since they're properly set in 'msvc-desktop.conf', - remove 'DSP_EXTENSION' variable, which doesn't occur anywhere else within QtBase; its most recent search results relate to Visual Studio 6.0 and Intel Fortran. Change-Id: I2ce5c2c9e9ca2c09c1acfcf8c60381d318e8e380 Reviewed-by: Oswald Buddenhagen --- mkspecs/win32-g++/qmake.conf | 1 - mkspecs/win32-icc/qmake.conf | 6 ------ 2 files changed, 7 deletions(-) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index cf43797b95d..39ecf005444 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -30,7 +30,6 @@ QMAKE_CFLAGS_WARN_ON += -Wextra QMAKE_CFLAGS_SSE2 += -mstackrealign QMAKE_CXX = $${CROSS_COMPILE}g++ -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD QMAKE_CXXFLAGS_RTTI_ON = -frtti QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index a25c979d9af..9506097e7f3 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -48,16 +48,10 @@ QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG QMAKE_LINK = xilink -QMAKE_LFLAGS = /NOLOGO -QMAKE_LFLAGS_RELEASE = -QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = -QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LIB = xilib /NOLOGO -DSP_EXTENSION = .dsp - include(../common/angle.conf) load(qt_config) From 17d231039b53c03e67d025f1f72bbd529e98fcbd Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Wed, 13 Dec 2017 21:29:21 +0000 Subject: [PATCH 091/102] Don't crash with null receiver/context in new-style connects old style connects have protection against null sender and null receiver, but new style only had against null sender. Change-Id: Ie555ac078412918e60c3b60830fe1f3abfb7f5af Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 2 +- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3f50716cd73..086b8a51ba9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4796,7 +4796,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject) { - if (!sender || !slotObj || !senderMetaObject) { + if (!sender || !receiver || !slotObj || !senderMetaObject) { qWarning("QObject::connect: invalid null parameter"); if (slotObj) slotObj->destroyIfLastRef(); diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 642d48d7216..f1e58921c0c 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -150,6 +150,7 @@ private slots: void deleteLaterInAboutToBlockHandler(); void mutableFunctor(); void checkArgumentsForNarrowing(); + void nullReceiver(); }; struct QObjectCreatedOnShutdown @@ -7380,6 +7381,16 @@ void tst_QObject::checkArgumentsForNarrowing() #undef FITS } +void tst_QObject::nullReceiver() +{ + QObject o; + QObject *nullObj = nullptr; // Passing nullptr directly doesn't compile with gcc 4.8 + QVERIFY(!connect(&o, &QObject::destroyed, nullObj, &QObject::deleteLater)); + QVERIFY(!connect(&o, &QObject::destroyed, nullObj, [] {})); + QVERIFY(!connect(&o, &QObject::destroyed, nullObj, Functor_noexcept())); + QVERIFY(!connect(&o, SIGNAL(destroyed()), nullObj, SLOT(deleteLater()))); +} + // Test for QtPrivate::HasQ_OBJECT_Macro Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro::Value); Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro::Value); From 33a72ee6f3ed85c3d5f694c2a3ab90b1f50786ea Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 19 Dec 2017 14:30:59 +0100 Subject: [PATCH 092/102] winrt: Register ssl socket upgrade callback in Xaml thread Task-number: QTBUG-65354 Change-Id: If628c73b05854c13086708c193995062c8b9f9e4 Reviewed-by: Miguel Costa Reviewed-by: Maurice Kalinowski --- src/network/ssl/qsslsocket_winrt.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index ca65f8a015f..762b393738a 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -443,8 +444,11 @@ void QSslSocketBackendPrivate::continueHandshake() return; } - hr = op->put_Completed(Callback( - this, &QSslSocketBackendPrivate::onSslUpgrade).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([this, op]() { + HRESULT hr = op->put_Completed(Callback( + this, &QSslSocketBackendPrivate::onSslUpgrade).Get()); + return hr; + }); Q_ASSERT_SUCCEEDED(hr); } From eef2d1af332d4d393734687dcdc80931f3a6dabc Mon Sep 17 00:00:00 2001 From: Alexander Shevchenko Date: Wed, 20 Dec 2017 00:48:59 +0200 Subject: [PATCH 093/102] unify windows mkspecs: reorder variables and flags Common changes to mingw-w64, ICC on Windows, and MSVC toolchains: - set similar order of variables and its splitting into sections, - set similar order of flags in variables and the way they are set. mingw-w64 toolchain: - move 'gcc-base.conf' include before setting Windows specific flags, similar to include 'msvc-desktop.conf' in ICC on Windows toolchain; this leads to consistency with other toolchains and allows to safely override common GCC variables with Windows specific ones, when needed, - move 'QMAKE_EXT_OBJ' and 'QMAKE_EXT_RES' variables to the linker flags section, according to its purpose. MSVC toolchain: - set flags order in 'CONFIG' variable, similar to mingw-w64 toolchain. Change-Id: I417cc8f7959c669dd504f2c5c11eb879a7989bd4 Reviewed-by: Oswald Buddenhagen --- mkspecs/common/msvc-desktop.conf | 5 ++--- mkspecs/win32-g++/qmake.conf | 11 ++++++----- mkspecs/win32-icc/qmake.conf | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf index 5a26add083b..496ca1179dd 100644 --- a/mkspecs/common/msvc-desktop.conf +++ b/mkspecs/common/msvc-desktop.conf @@ -15,7 +15,7 @@ MAKEFILE_GENERATOR = MSVC.NET QMAKE_PLATFORM = win32 QMAKE_COMPILER = msvc -CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe +CONFIG += incremental flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe DEFINES += UNICODE _UNICODE WIN32 QMAKE_COMPILER_DEFINES += _WIN32 contains(QMAKE_TARGET.arch, x86_64) { @@ -35,7 +35,7 @@ QMAKE_CFLAGS = -nologo -Zc:wchar_t QMAKE_CFLAGS_WARN_ON = -W3 QMAKE_CFLAGS_WARN_OFF = -W0 QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE -MD -QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -MD -Zi +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MD QMAKE_CFLAGS_DEBUG = -Zi -MDd QMAKE_CFLAGS_YACC = QMAKE_CFLAGS_LTCG = -GL @@ -98,7 +98,6 @@ QMAKE_LIBS_OPENGL = glu32.lib opengl32.lib gdi32.lib user32.lib QMAKE_LIBS_OPENGL_ES2 = gdi32.lib user32.lib QMAKE_LIBS_OPENGL_ES2_DEBUG = gdi32.lib user32.lib QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib - QMAKE_LIBS_QT_ENTRY = -lqtmain QMAKE_IDL = midl /NOLOGO diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 39ecf005444..a4955e99f30 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -8,18 +8,17 @@ # load(device_config) +include(../common/gcc-base.conf) include(../common/g++-base.conf) +# modifications to gcc-base.conf and g++-base.conf + MAKEFILE_GENERATOR = MINGW QMAKE_PLATFORM = win32 mingw CONFIG += debug_and_release debug_and_release_target precompile_header DEFINES += UNICODE _UNICODE QMAKE_COMPILER_DEFINES += __GNUC__ WIN32 -QMAKE_EXT_OBJ = .o -QMAKE_EXT_RES = _res.o - - QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_LEX = flex QMAKE_LEXFLAGS = @@ -27,6 +26,7 @@ QMAKE_YACC = bison -y QMAKE_YACCFLAGS = -d QMAKE_CFLAGS += -fno-keep-inline-dllexport QMAKE_CFLAGS_WARN_ON += -Wextra + QMAKE_CFLAGS_SSE2 += -mstackrealign QMAKE_CXX = $${CROSS_COMPILE}g++ @@ -53,6 +53,8 @@ equals(QMAKE_HOST.os, Windows) { QMAKE_LINK_OBJECT_MAX = 10 QMAKE_LINK_OBJECT_SCRIPT = object_script } +QMAKE_EXT_OBJ = .o +QMAKE_EXT_RES = _res.o QMAKE_PREFIX_SHLIB = QMAKE_EXTENSION_SHLIB = dll QMAKE_PREFIX_STATICLIB = lib @@ -78,6 +80,5 @@ QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_NM = $${CROSS_COMPILE}nm -P include(../common/angle.conf) -include(../common/gcc-base.conf) load(qt_config) diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index 9506097e7f3..4d18b1cc55e 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -17,9 +17,10 @@ QMAKE_CC = icl QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809,3373 QMAKE_CFLAGS_WARN_ON = -W3 /Qwd673 QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673 -QMAKE_CFLAGS_DEBUG = -Zi -MDd -Od +QMAKE_CFLAGS_DEBUG = -Od -Zi -MDd QMAKE_CFLAGS_LTCG = -Qipo QMAKE_CFLAGS_DISABLE_LTCG = -Qno-ipo + QMAKE_CFLAGS_SSE2 = -QxSSE2 QMAKE_CFLAGS_SSE3 = -QxSSE3 QMAKE_CFLAGS_SSSE3 = -QxSSSE3 From 2f96813349681889ad2987173dad18f8f1d3b612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 21 Dec 2017 13:07:14 +0100 Subject: [PATCH 094/102] Fix typo in QSslKey Change-Id: I201f4af1dd43a8e74d26652b50f3ad6074952888 Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslkey_qt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index 3c5dc830d32..fd76d3353af 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -94,7 +94,7 @@ static OidLengthMap createOidMap() oids.insert(oids.cend(), QByteArrayLiteral("1.3.132.0.8"), 160); // secp160r1 oids.insert(oids.cend(), QByteArrayLiteral("1.3.132.0.9"), 160); // secp160k1 oids.insert(oids.cend(), QByteArrayLiteral("1.3.36.3.3.2.8.1.1.11"), 384); // brainpoolP384r1 - oids.insert(oids.cend(), QByteArrayLiteral("1.3.36.3.3.2.8.1.1.13"), 521); // brainpoolP512r1 + oids.insert(oids.cend(), QByteArrayLiteral("1.3.36.3.3.2.8.1.1.13"), 512); // brainpoolP512r1 oids.insert(oids.cend(), QByteArrayLiteral("1.3.36.3.3.2.8.1.1.7"), 256); // brainpoolP256r1 return oids; } From 83fa66b6d23907ccd443344f9865fcf4ad14e3a9 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 14 Dec 2017 10:32:15 +0100 Subject: [PATCH 095/102] Add more code examples to QUrl documentation Code examples make it much easier to learn how an API behaves. One area that the patch tries to address is the distinction between a relative URL and a relative path. Change-Id: Ife52172816b89afb6cd810b07d3573480e2cd747 Reviewed-by: Thiago Macieira --- src/corelib/io/qurl.cpp | 110 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index cf7ed130bac..4587b9fcd6f 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -90,11 +90,6 @@ fromPercentEncoding() and toPercentEncoding() which deal with percent encoding and decoding of QString objects. - Calling isRelative() will tell whether or not the URL is - relative. A relative URL can be resolved by passing it as argument - to resolved(), which returns an absolute URL. isParentOf() is used - for determining whether one URL is a parent of another. - fromLocalFile() constructs a QUrl by parsing a local file path. toLocalFile() converts a URL to a local file path. @@ -116,6 +111,37 @@ from freedesktop.org, provided that the locale encodes file names using UTF-8 (required by IDN). + \section2 Relative URLs vs Relative Paths + + Calling isRelative() will return whether or not the URL is relative. + A relative URL has no \l {scheme}. For example: + + \code + qDebug() << QUrl("main.qml").isRelative(); // true: no scheme + qDebug() << QUrl("qml/main.qml").isRelative(); // true: no scheme + qDebug() << QUrl("file:main.qml").isRelative(); // false: has "file" scheme + qDebug() << QUrl("file:qml/main.qml").isRelative(); // false: has "file" scheme + \endcode + + Notice that a URL can be absolute while containing a relative path, and + vice versa: + + \code + // Absolute URL, relative path + QUrl url("file:file.txt"); + qDebug() << url.isRelative(); // false: has "file" scheme + qDebug() << QDir::isAbsolutePath(url.path()); // false: relative path + + // Relative URL, absolute path + url = QUrl("/home/user/file.txt"); + qDebug() << url.isRelative(); // true: has no scheme + qDebug() << QDir::isAbsolutePath(url.path()); // true: absolute path + \endcode + + A relative URL can be resolved by passing it as an argument to resolved(), + which returns an absolute URL. isParentOf() is used for determining whether + one URL is a parent of another. + \section2 Error checking QUrl is capable of detecting many errors in URLs while parsing it or when @@ -2539,6 +2565,12 @@ void QUrl::setPath(const QString &path, ParsingMode mode) /*! Returns the path of the URL. + \code + qDebug() << QUrl("file:file.txt").path(); // "file.txt" + qDebug() << QUrl("/home/user/file.txt").path(); // "/home/user/file.txt" + qDebug() << QUrl("http://www.example.com/test/123").path(); // "/test/123" + \endcode + The \a options argument controls how to format the path component. All values produce an unambiguous result. With QUrl::FullyDecoded, all percent-encoded sequences are decoded; otherwise, the returned value may @@ -2549,6 +2581,31 @@ void QUrl::setPath(const QString &path, ParsingMode mode) sequences are present. It is recommended to use that value when the result will be used in a non-URL context, such as sending to an FTP server. + An example of data loss is when you have non-Unicode percent-encoded sequences + and use FullyDecoded (the default): + + \code + qDebug() << QUrl("/foo%FFbar").path(); + \endcode + + In this example, there will be some level of data loss because the \c %FF cannot + be converted. + + Data loss can also occur when the path contains sub-delimiters (such as \c +): + + \code + qDebug() << QUrl("/foo+bar%2B").path(); // "/foo+bar+" + \endcode + + Other decoding examples: + + \code + const QUrl url("/tmp/Mambo %235%3F.mp3"); + qDebug() << url.path(QUrl::FullyDecoded); // "/tmp/Mambo #5?.mp3" + qDebug() << url.path(QUrl::PrettyDecoded); // "/tmp/Mambo #5?.mp3" + qDebug() << url.path(QUrl::FullyEncoded); // "/tmp/Mambo%20%235%3F.mp3" + \endcode + \sa setPath() */ QString QUrl::path(ComponentFormattingOptions options) const @@ -3257,6 +3314,8 @@ QUrl QUrl::resolved(const QUrl &relative) const equivalent to calling scheme().isEmpty(). Relative references are defined in RFC 3986 section 4.2. + + \sa {Relative URLs vs Relative Paths} */ bool QUrl::isRelative() const { @@ -3796,6 +3855,41 @@ bool QUrl::isDetached() const An empty \a localFile leads to an empty URL (since Qt 5.4). + \code + qDebug() << QUrl::fromLocalFile("file.txt"); // QUrl("file:file.txt") + qDebug() << QUrl::fromLocalFile("/home/user/file.txt"); // QUrl("file:///home/user/file.txt") + qDebug() << QUrl::fromLocalFile("file:file.txt"); // doesn't make sense; expects path, not url with scheme + \endcode + + In the first line in snippet above, a file URL is constructed from a + local, relative path. A file URL with a relative path only makes sense + if there is a base URL to resolve it against. For example: + + \code + QUrl url = QUrl::fromLocalFile("file.txt"); + QUrl baseUrl = QUrl("file:/home/user/"); + // wrong: prints QUrl("file:file.txt"), as url already has a scheme + qDebug() << baseUrl.resolved(url); + \endcode + + To resolve such a URL, it's necessary to remove the scheme beforehand: + + \code + // correct: prints QUrl("file:///home/user/file.txt") + url.setScheme(QString()); + qDebug() << baseUrl.resolved(url); + \endcode + + For this reason, it is better to use a relative URL (that is, no scheme) + for relative file paths: + + \code + QUrl url = QUrl("file.txt"); + QUrl baseUrl = QUrl("file:/home/user/"); + // prints QUrl("file:///home/user/file.txt") + qDebug() << baseUrl.resolved(url); + \endcode + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators() */ QUrl QUrl::fromLocalFile(const QString &localFile) @@ -3840,6 +3934,12 @@ QUrl QUrl::fromLocalFile(const QString &localFile) returned value in the form found on SMB networks (for example, "//servername/path/to/file.txt"). + \code + qDebug() << QUrl("file:file.txt").toLocalFile(); // "file:file.txt" + qDebug() << QUrl("file:/home/user/file.txt").toLocalFile(); // "file:///home/user/file.txt" + qDebug() << QUrl("file.txt").toLocalFile(); // ""; wasn't a local file as it had no scheme + \endcode + Note: if the path component of this URL contains a non-UTF-8 binary sequence (such as %80), the behaviour of this function is undefined. From ffc8409aa58c04c1dd140001976b55925ac959f6 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Mon, 15 Sep 2014 14:09:22 -0700 Subject: [PATCH 096/102] Use AccessCheck for current user effective file permissions On Windows, QFileInfo.isWritable() was returning true in situations where the file would only be writable with elevated privileges. Using AccessCheck instead of GetEffectiveRightsFromAcl to get the correct results. Done-with: Friedemann Kleint Done-with: Edward Welbourne Task-number: QTBUG-30148 Change-Id: I7a3468ac069bf782ca312078e3a84107b6cd468c Reviewed-by: Friedemann Kleint --- src/corelib/io/qfilesystemengine_win.cpp | 64 ++++++++++++++++--- .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 25 ++++++-- 2 files changed, 74 insertions(+), 15 deletions(-) mode change 100644 => 100755 src/corelib/io/qfilesystemengine_win.cpp mode change 100644 => 100755 tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp old mode 100644 new mode 100755 index b01aa557563..c9a56a81cc4 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -178,6 +178,7 @@ static TRUSTEE_W currentUserTrusteeW; static TRUSTEE_W worldTrusteeW; static PSID currentUserSID = 0; static PSID worldSID = 0; +static HANDLE currentUserImpersonatedToken = nullptr; /* Deletes the allocated SIDs during global static cleanup @@ -198,6 +199,11 @@ SidCleanup::~SidCleanup() ::FreeSid(worldSID); worldSID = 0; } + + if (currentUserImpersonatedToken) { + ::CloseHandle(currentUserImpersonatedToken); + currentUserImpersonatedToken = nullptr; + } } Q_GLOBAL_STATIC(SidCleanup, initSidCleanup) @@ -254,6 +260,12 @@ static void resolveLibs() ::CloseHandle(token); } + token = nullptr; + if (::OpenProcessToken(hnd, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &token)) { + ::DuplicateToken(token, SecurityImpersonation, ¤tUserImpersonatedToken); + ::CloseHandle(token); + } + typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); if (ptrAllocateAndInitializeSid) { @@ -721,15 +733,49 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst ACCESS_MASK access_mask; TRUSTEE_W trustee; if (what & QFileSystemMetaData::UserPermissions) { // user - data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; - if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - data.entryFlags |= QFileSystemMetaData::UserReadPermission; - if(access_mask & WriteMask) - data.entryFlags|= QFileSystemMetaData::UserWritePermission; - if(access_mask & ExecMask) - data.entryFlags|= QFileSystemMetaData::UserExecutePermission; + // Using AccessCheck because GetEffectiveRightsFromAcl doesn't account for elevation + if (currentUserImpersonatedToken) { + GENERIC_MAPPING mapping = {FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS}; + PRIVILEGE_SET privileges; + DWORD grantedAccess; + BOOL result; + + data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; + DWORD genericAccessRights = GENERIC_READ; + ::MapGenericMask(&genericAccessRights, &mapping); + + DWORD privilegesLength = sizeof(privileges); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + } + + privilegesLength = sizeof(privileges); + genericAccessRights = GENERIC_WRITE; + ::MapGenericMask(&genericAccessRights, &mapping); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserWritePermission; + } + + privilegesLength = sizeof(privileges); + genericAccessRights = GENERIC_EXECUTE; + ::MapGenericMask(&genericAccessRights, &mapping); + if (::AccessCheck(pSD, currentUserImpersonatedToken, genericAccessRights, + &mapping, &privileges, &privilegesLength, &grantedAccess, &result) && result) { + data.entryFlags |= QFileSystemMetaData::UserExecutePermission; + } + } else { // fallback to GetEffectiveRightsFromAcl + data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; + if (ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) + access_mask = ACCESS_MASK(-1); + if (access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + if (access_mask & WriteMask) + data.entryFlags|= QFileSystemMetaData::UserWritePermission; + if (access_mask & ExecMask) + data.entryFlags|= QFileSystemMetaData::UserExecutePermission; + } } if (what & QFileSystemMetaData::OwnerPermissions) { // owner data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions; diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp old mode 100644 new mode 100755 index f35dab2cad1..efb261ce7ea --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -64,6 +64,14 @@ #define Q_NO_SYMLINKS #endif +#if defined(Q_OS_WIN) +QT_BEGIN_NAMESPACE +extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; +QT_END_NAMESPACE +# ifndef Q_OS_WINRT +bool IsUserAdmin(); +# endif +#endif #if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) inline bool qt_isEvilFsTypeName(const char *name) @@ -1634,6 +1642,15 @@ void tst_QFileInfo::isWritable() QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData()); QVERIFY(!fi.isWritable()); #endif + +#if defined (Q_OS_WIN) && !defined(Q_OS_WINRT) + QScopedValueRollback ntfsMode(qt_ntfs_permission_lookup); + qt_ntfs_permission_lookup = 1; + QFileInfo fi2(QFile::decodeName(qgetenv("SystemRoot") + "/system.ini")); + QVERIFY(fi2.exists()); + QCOMPARE(fi2.isWritable(), IsUserAdmin()); +#endif + #if defined (Q_OS_QNX) // On QNX /etc is usually on a read-only filesystem QVERIFY(!QFileInfo("/etc/passwd").isWritable()); #elif defined (Q_OS_UNIX) && !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups @@ -1807,7 +1824,7 @@ void tst_QFileInfo::detachingOperations() } #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) -BOOL IsUserAdmin() +bool IsUserAdmin() { BOOL b; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; @@ -1825,13 +1842,9 @@ BOOL IsUserAdmin() FreeSid(AdministratorsGroup); } - return(b); + return b != FALSE; } -QT_BEGIN_NAMESPACE -extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; -QT_END_NAMESPACE - #endif // Q_OS_WIN && !Q_OS_WINRT #ifndef Q_OS_WINRT From 44ef95a885f440a33e79ff3f9a79d4bb6d408dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 19 Dec 2017 19:58:29 +0100 Subject: [PATCH 097/102] iOS: Don't send all touch events async Commit 77942a1bdf9 introduced the QScopedValueRollback, but without assigning it to a local temporary, so the value was rolled back immediately, resulting in always sending touch events async. Change-Id: Ic7f65c3d38c46813ff06694e883dae3df138b9d4 Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosscreen.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 521495b42fc..5717483a810 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -204,7 +204,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) - (void)sendEvent:(UIEvent *)event { - QScopedValueRollback(self->_sendingEvent, YES); + QScopedValueRollback sendingEvent(self->_sendingEvent, YES); [super sendEvent:event]; } From 3d7cdb64fca260b303b44263312af3eb65eb175e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 22 Dec 2017 18:13:46 -0200 Subject: [PATCH 098/102] qfloat16: NaN is not infinite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I39332e0a867442d58082fffd1502b7010424f0f8 Reviewed-by: André Hartmann Reviewed-by: Allan Sandfeld Jensen --- src/corelib/global/qfloat16_p.h | 4 ++-- tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qfloat16_p.h b/src/corelib/global/qfloat16_p.h index ae52e644351..f3fc96e1198 100644 --- a/src/corelib/global/qfloat16_p.h +++ b/src/corelib/global/qfloat16_p.h @@ -61,9 +61,9 @@ static inline bool qt_is_inf(qfloat16 d) Q_DECL_NOTHROW bool is_inf; uchar *ch = (uchar *)&d; if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - is_inf = (ch[0] & 0x7c) == 0x7c; + is_inf = (ch[0] & 0x7c) == 0x7c && (ch[0] & 0x02) == 0; else - is_inf = (ch[1] & 0x7c) == 0x7c; + is_inf = (ch[1] & 0x7c) == 0x7c && (ch[1] & 0x02) == 0; return is_inf; } diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index 9bd87e3f212..6b98e3a8238 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -158,12 +158,14 @@ void tst_qfloat16::qNan() qfloat16 nan = qQNaN(); QVERIFY(!(0. > nan)); QVERIFY(!(0. < nan)); + QVERIFY(!qIsInf(nan)); QVERIFY(qIsNaN(nan)); QVERIFY(qIsNaN(nan + 1.f)); QVERIFY(qIsNaN(-nan)); qfloat16 inf = qInf(); QVERIFY(inf > qfloat16(0)); QVERIFY(-inf < qfloat16(0)); + QVERIFY(!qIsNaN(inf)); QVERIFY(qIsInf(inf)); QVERIFY(qIsInf(-inf)); QVERIFY(qIsInf(2.f*inf)); From 597b96b8fa2fc8b9331db8ecc85d742be83fbec5 Mon Sep 17 00:00:00 2001 From: Joni Jantti Date: Fri, 22 Dec 2017 09:39:06 +0200 Subject: [PATCH 099/102] Blacklist tst_QDateTime::operator_eqeq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This autotest fails on the new Ubuntu 16.04 template with UTC timezone in the system settings. Task-number: QTBUG-65435 Change-Id: I397f01ab3fed354a4eeec8b05415226a75fce5a1 Reviewed-by: Tony Sarajärvi --- tests/auto/corelib/tools/qdatetime/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/auto/corelib/tools/qdatetime/BLACKLIST diff --git a/tests/auto/corelib/tools/qdatetime/BLACKLIST b/tests/auto/corelib/tools/qdatetime/BLACKLIST new file mode 100644 index 00000000000..e78f5cfd879 --- /dev/null +++ b/tests/auto/corelib/tools/qdatetime/BLACKLIST @@ -0,0 +1,3 @@ +[operator_eqeq] +ubuntu-16.04 +b2qt From e548406d2820b066bdc66c1080976c7710353ae8 Mon Sep 17 00:00:00 2001 From: Joni Jantti Date: Fri, 22 Dec 2017 12:07:13 +0200 Subject: [PATCH 100/102] Blacklist tst_QUdpSocket on Ubuntu 16.04 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tst_QUdpSocket::broadcasting and tst_QUdpSocket::pendingDatagramSize fail on the new Ubuntu 16.04 clean template. Task-number: QTBUG-65440 Change-Id: I0e973b9c90b7c5827406bac8138370b61992a115 Reviewed-by: Tony Sarajärvi --- tests/auto/network/socket/qudpsocket/BLACKLIST | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST index 5adb05d3f26..3951be16abc 100644 --- a/tests/auto/network/socket/qudpsocket/BLACKLIST +++ b/tests/auto/network/socket/qudpsocket/BLACKLIST @@ -22,7 +22,12 @@ osx osx [broadcasting] osx +ubuntu-16.04 [zeroLengthDatagram] osx [linkLocalIPv6] redhatenterpriselinuxworkstation-6.6 +[pendingDatagramSize] +ubuntu-16.04 +[readyReadForEmptyDatagram] +ubuntu-16.04 From 6f7b64e2a97034f84991e644abd609e73895ffb9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 26 Dec 2017 23:39:33 -0200 Subject: [PATCH 101/102] QMap: fix another UB (invalid cast) relating to QMap's end Like in commit 75cdf654bcc192ba73a8834e507583a59140e7e4, we use the pointer value of the QMap header (which is of type QMapNodeBase) as a sentinel. It's never dereferenced. In that commit, the issue was calling end() directly; in here, it happens when iterating forward from any element, which means nextNode() can reach back to the header. However, using static_cast is wrong, so we use reinterpret_cast. Change-Id: I39332e0a867442d58082fffd15040317704a87ce Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qmap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 37ed24000d3..43acf09ea97 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -115,9 +115,9 @@ struct QMapNode : public QMapNodeBase inline QMapNode *leftNode() const { return static_cast(left); } inline QMapNode *rightNode() const { return static_cast(right); } - inline const QMapNode *nextNode() const { return static_cast(QMapNodeBase::nextNode()); } + inline const QMapNode *nextNode() const { return reinterpret_cast(QMapNodeBase::nextNode()); } inline const QMapNode *previousNode() const { return static_cast(QMapNodeBase::previousNode()); } - inline QMapNode *nextNode() { return static_cast(QMapNodeBase::nextNode()); } + inline QMapNode *nextNode() { return reinterpret_cast(QMapNodeBase::nextNode()); } inline QMapNode *previousNode() { return static_cast(QMapNodeBase::previousNode()); } QMapNode *copy(QMapData *d) const; From 44da5b863597e761df3545dc7ff02a9b53bbb13d Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Wed, 27 Dec 2017 12:42:26 -0800 Subject: [PATCH 102/102] Allow moc to handle Unicode output filenames on Windows with MSVC The C standard library functions cannot handle UTF-8 filenames. Instead, we need to use the wide-character versions which accept UTF-16 input. Task-number: QTBUG-65492 Change-Id: If4b3b4eeeec4f3bbb428b8f6b0311a65d01463b0 Reviewed-by: Thiago Macieira --- src/tools/moc/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 98cc9652abc..dfcc23f0d6b 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -486,8 +486,8 @@ int runMoc(int argc, char **argv) // 3. and output meta object code if (output.size()) { // output file specified -#if defined(_MSC_VER) && _MSC_VER >= 1400 - if (fopen_s(&out, QFile::encodeName(output).constData(), "w")) +#if defined(_MSC_VER) + if (_wfopen_s(&out, reinterpret_cast(output.utf16()), L"w") != 0) #else out = fopen(QFile::encodeName(output).constData(), "w"); // create output file if (!out)