From 7499e642e04799e831debf03d03e49c225a05e82 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Nov 2015 11:54:03 -0800 Subject: QVariant: retain duplicate keys when converting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-49520 Change-Id: I3e15a26e0e424169ac2bffff1417e3f4398c2277 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant.h | 4 +-- .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 41 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 4c7e498280..bed0e193db 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -772,7 +772,7 @@ namespace QtPrivate { QVariantHash l; l.reserve(iter.size()); for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) - l.insert(it.key().toString(), it.value()); + l.insertMulti(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); @@ -788,7 +788,7 @@ namespace QtPrivate { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantMap l; for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) - l.insert(it.key().toString(), it.value()); + l.insertMulti(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 6da8f55e61..40eb2e5c9d 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -2,6 +2,7 @@ ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Olivier Goffart +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -2491,14 +2492,26 @@ void tst_QVariant::variantMap() QVariant v = map; QVariantMap map2 = qvariant_cast(v); + QCOMPARE(map2.value("test").toInt(), 42); + QCOMPARE(map2, map); + map2 = v.toMap(); QCOMPARE(map2.value("test").toInt(), 42); + QCOMPARE(map2, map); QVariant v2 = QVariant(QMetaType::type("QVariantMap"), &map); QCOMPARE(qvariant_cast(v2).value("test").toInt(), 42); QVariant v3 = QVariant(QMetaType::type("QMap"), &map); QCOMPARE(qvariant_cast(v3).value("test").toInt(), 42); + + // multi-keys + map.insertMulti("test", 47); + v = map; + map2 = qvariant_cast(v); + QCOMPARE(map2, map); + map2 = v.toMap(); + QCOMPARE(map2, map); } void tst_QVariant::variantHash() @@ -2508,14 +2521,26 @@ void tst_QVariant::variantHash() QVariant v = hash; QVariantHash hash2 = qvariant_cast(v); + QCOMPARE(hash2.value("test").toInt(), 42); + QCOMPARE(hash2, hash); + hash2 = v.toHash(); QCOMPARE(hash2.value("test").toInt(), 42); + QCOMPARE(hash2, hash); QVariant v2 = QVariant(QMetaType::type("QVariantHash"), &hash); QCOMPARE(qvariant_cast(v2).value("test").toInt(), 42); QVariant v3 = QVariant(QMetaType::type("QHash"), &hash); QCOMPARE(qvariant_cast(v3).value("test").toInt(), 42); + + // multi-keys + hash.insertMulti("test", 47); + v = hash; + hash2 = qvariant_cast(v); + QCOMPARE(hash2, hash); + hash2 = v.toHash(); + QCOMPARE(hash2, hash); } class CustomQObject : public QObject { @@ -3233,24 +3258,40 @@ void tst_QVariant::convertIterables() const map.insert("3", 4); QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); + + map.insertMulti("3", 5); + QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); + QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); } { QVariantMap map; map.insert("3", 4); QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); + + map.insertMulti("3", 5); + QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); + QCOMPARE(QVariant::fromValue(map).value().count(), map.count()); } { QHash hash; hash.insert("3", 4); QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); + + hash.insertMulti("3", 5); + QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); + QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); } { QVariantHash hash; hash.insert("3", 4); QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); + + hash.insertMulti("3", 5); + QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); + QCOMPARE(QVariant::fromValue(hash).value().count(), hash.count()); } } -- cgit v1.2.3 From 401507b348936d346cec8734cac5cacad70a3174 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 3 Dec 2015 13:49:31 -0800 Subject: Fix constructing a QSharedPointer of a QEnableSharedFromThis type It should compile, since the std::shared_ptr does. [ChangeLog][QtCore][QSharedPointer] Fixed a problem that would cause a compilation error when constructing a QSharedPointer of a const type when the type derives from QEnableSharedFromThis. Task-number: QTBUG-49748 Change-Id: I8de47ed6c7be4847b99bffff141c84f5e0b6bea8 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qsharedpointer_impl.h | 2 +- .../tools/qsharedpointer/tst_qsharedpointer.cpp | 50 +++++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 1323dd6b1c..bd98cb326c 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -499,7 +499,7 @@ private: template inline void enableSharedFromThis(const QEnableSharedFromThis *ptr) { - ptr->initializeFromSharedPointer(*this); + ptr->initializeFromSharedPointer(constCast::type>()); } inline void enableSharedFromThis(...) {} diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 7741803224..b63485e91e 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -94,18 +94,18 @@ private slots: void creatingQObject(); void mixTrackingPointerCode(); void reentrancyWhileDestructing(); + void map(); + void hash(); + void qvariantCast(); + void sharedFromThis(); void threadStressTest_data(); void threadStressTest(); - void map(); - void hash(); void validConstructs(); void invalidConstructs_data(); void invalidConstructs(); - - void qvariantCast(); - void sharedFromThis(); - + // let invalidConstructs be the last test, because it's the slowest; + // add new tests above this block public slots: void cleanup() { safetyCheck(); } @@ -231,6 +231,14 @@ void tst_QSharedPointer::basics() QCOMPARE(sizeof(weakref), 2*sizeof(void*)); } + { + QSharedPointer ptr; + QWeakPointer weakref; + + QCOMPARE(sizeof(ptr), 2*sizeof(void*)); + QCOMPARE(sizeof(weakref), 2*sizeof(void*)); + } + QFETCH(bool, isNull); Data *aData = 0; if (!isNull) @@ -2171,6 +2179,16 @@ void tst_QSharedPointer::sharedFromThis() QVERIFY(const_scp.isNull()); QCOMPARE(Data::generationCounter, generations + 1); QCOMPARE(Data::destructorCounter, destructions); + + QWeakPointer wcp = sc.sharedFromThis(); + QVERIFY(wcp.isNull()); + QCOMPARE(Data::generationCounter, generations + 1); + QCOMPARE(Data::destructorCounter, destructions); + + QWeakPointer const_wcp = sc.sharedFromThis(); + QVERIFY(const_wcp.isNull()); + QCOMPARE(Data::generationCounter, generations + 1); + QCOMPARE(Data::destructorCounter, destructions); } QCOMPARE(Data::generationCounter, generations + 1); @@ -2182,6 +2200,11 @@ void tst_QSharedPointer::sharedFromThis() QVERIFY(const_scp.isNull()); QCOMPARE(Data::generationCounter, generations + 2); QCOMPARE(Data::destructorCounter, destructions + 1); + + QWeakPointer const_wcp = sc.sharedFromThis(); + QVERIFY(const_wcp.isNull()); + QCOMPARE(Data::generationCounter, generations + 2); + QCOMPARE(Data::destructorCounter, destructions + 1); } QCOMPARE(Data::generationCounter, generations + 2); @@ -2373,6 +2396,21 @@ void tst_QSharedPointer::sharedFromThis() QCOMPARE(Data::generationCounter, generations + 5); QCOMPARE(Data::destructorCounter, destructions + 5); + + { + QSharedPointer scp2(new SomeClass()); + QVERIFY(!scp2.isNull()); + QCOMPARE(Data::generationCounter, generations + 6); + QCOMPARE(Data::destructorCounter, destructions + 5); + + QWeakPointer wcp2(scp2.constCast()); + QVERIFY(!wcp2.isNull()); + QCOMPARE(Data::generationCounter, generations + 6); + QCOMPARE(Data::destructorCounter, destructions + 5); + } + + QCOMPARE(Data::generationCounter, generations + 6); + QCOMPARE(Data::destructorCounter, destructions + 6); } namespace ReentrancyWhileDestructing { -- cgit v1.2.3 From bdd4ddd8fae7ba14548e1b6f01f7b9d143261db2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 2 Dec 2015 11:08:56 -0800 Subject: QNetworkInterface: fix support for address labels on Linux interfaces Commit 64a1448d87727878d9789906b2f4f5b9e3d74e38 (Qt 5.2) caused QNetworkInterface to report address labels (a.k.a. interface aliases) as separate interfaces. This is caused by the fact that glibc, uClibc and MUSL copy the address label (netlink address attribute IFA_LABEL) to the ifa_name field, which made QNetworkInterfaceManager think that it was an interface it hadn't yet seen. Address labels are the old way to add more than one IP address to an interface on Linux, for example: ifconfig eth0:1 192.0.2.2 Those do not create a new interface, so the "eth0:1" label maps to the same interface index as the parent interface. This has been deprecated for 10 years, but there are still tools out there that add addresses in this manner. This commit restores behavior compatibility with Qt 4.2-5.1. The Qt 5.2-5.5 behavior is incorrect because it reports more than one interface with the same index. On systems configured like the above, the tst_QNetworkInterface::interfaceFromXXX test was failing. Change-Id: I8de47ed6c7be4847b99bffff141c2d9de8cf7329 Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_unix.cpp | 38 ++++++++++++++++++---- .../qnetworkinterface/tst_qnetworkinterface.cpp | 19 +++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index cc53087024..5e6d24dd44 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -314,10 +314,15 @@ static QList createInterfaces(ifaddrs *rawList) { QList interfaces; QSet seenInterfaces; - - // on Linux, AF_PACKET addresses carry the hardware address and interface index; - // scan for them first (they're usually first, but we have no guarantee this - // will be the case forever) + QVarLengthArray seenIndexes; // faster than QSet + + // On Linux, glibc, uClibc and MUSL obtain the address listing via two + // netlink calls: first an RTM_GETLINK to obtain the interface listing, + // then one RTM_GETADDR to get all the addresses (uClibc implementation is + // copied from glibc; Bionic currently doesn't support getifaddrs). They + // synthesize AF_PACKET addresses from the RTM_GETLINK responses, which + // means by construction they currently show up first in the interface + // listing. for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) { if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) { sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr; @@ -328,23 +333,30 @@ static QList createInterfaces(ifaddrs *rawList) iface->flags = convertFlags(ptr->ifa_flags); iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr); + Q_ASSERT(!seenIndexes.contains(iface->index)); + seenIndexes.append(iface->index); seenInterfaces.insert(iface->name); } } // see if we missed anything: - // virtual interfaces with no HW address have no AF_PACKET + // - virtual interfaces with no HW address have no AF_PACKET + // - interface labels have no AF_PACKET, but shouldn't be shown as a new interface for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) { if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) { QString name = QString::fromLatin1(ptr->ifa_name); if (seenInterfaces.contains(name)) continue; + int ifindex = if_nametoindex(ptr->ifa_name); + if (seenIndexes.contains(ifindex)) + continue; + QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; interfaces << iface; iface->name = name; iface->flags = convertFlags(ptr->ifa_flags); - iface->index = if_nametoindex(ptr->ifa_name); + iface->index = ifindex; } } @@ -423,7 +435,7 @@ static QList interfaceListing() interfaces = createInterfaces(interfaceListing); for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) { - // Get the interface index + // Find the interface QString name = QString::fromLatin1(ptr->ifa_name); QNetworkInterfacePrivate *iface = 0; QList::Iterator if_it = interfaces.begin(); @@ -433,6 +445,18 @@ static QList interfaceListing() iface = *if_it; break; } + + if (!iface) { + // it may be an interface label, search by interface index + int ifindex = if_nametoindex(ptr->ifa_name); + for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it) + if ((*if_it)->index == ifindex) { + // found this interface already + iface = *if_it; + break; + } + } + if (!iface) { // skip all non-IP interfaces continue; diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp index f7798bbb70..519ee0dc84 100644 --- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp +++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp @@ -55,6 +55,7 @@ private slots: void initTestCase(); void cleanupTestCase(); void dump(); + void consistencyCheck(); void loopbackIPv4(); void loopbackIPv6(); void localAddress(); @@ -148,6 +149,24 @@ void tst_QNetworkInterface::dump() } } +void tst_QNetworkInterface::consistencyCheck() +{ + QList ifaces = QNetworkInterface::allInterfaces(); + QSet interfaceNames; + QVector interfaceIndexes; + + foreach (const QNetworkInterface &iface, ifaces) { + QVERIFY2(!interfaceNames.contains(iface.name()), + "duplicate name = " + iface.name().toLocal8Bit()); + interfaceNames << iface.name(); + + QVERIFY2(!interfaceIndexes.contains(iface.index()), + "duplicate index = " + QByteArray::number(iface.index())); + if (iface.index()) + interfaceIndexes << iface.index(); + } +} + void tst_QNetworkInterface::loopbackIPv4() { QList all = QNetworkInterface::allAddresses(); -- cgit v1.2.3 From 3304ea8f0e915b6562d9d89621c42a46bf92dafa Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 4 Dec 2015 16:04:38 -0800 Subject: syncqt.pl: say "ERROR" when it's an error Change-Id: I0f2ce894387048f78465ffff141cdae9ea760175 Reviewed-by: Oswald Buddenhagen --- bin/syncqt.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 4016ea2d7c..cca654e3b4 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -764,7 +764,7 @@ while ( @ARGV ) { $var = "version"; $val = shift @ARGV; } elsif($arg =~/^-/) { - print STDERR "Unknown option: $arg\n\n" if (!$var); + print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var); showUsage(); } else { $basedir = locateSyncProfile($arg); @@ -777,7 +777,7 @@ while ( @ARGV ) { #do something if(!$var || $var eq "show_help") { - print STDERR "Unknown option: $arg\n\n" if (!$var); + print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var); showUsage(); } elsif ($var eq "copy") { if($val eq "yes") { -- cgit v1.2.3 From cbb2ce0f918c471a7306a2e6a91730aad6a01f7b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Sat, 5 Dec 2015 19:09:15 +0100 Subject: Remove Wow6432Node versions of Visual Studio registry keys The Visual Studio registry keys are stored in the 32 bit view. Extend qt_readRegistryKey with an option that enables the caller to choose the 32 bit or 64 bit registry view. We now read the Visual Studio registry keys from the 32 bit registry view even in a 64 bit build. Adding the next Visual Studio version will become a bit easier. Change-Id: I7300b992be6058f30a422e3f1fe0bafade6eea54 Reviewed-by: Oliver Wolff Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msvc_nmake.cpp | 22 ++++++---------------- qmake/generators/win32/msvc_vcproj.cpp | 19 ++----------------- tools/configure/environment.cpp | 9 ++------- tools/shared/windows/registry.cpp | 6 ++++-- tools/shared/windows/registry_p.h | 8 +++++++- 5 files changed, 21 insertions(+), 43 deletions(-) diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index a546e03b59..06c99b6e38 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -142,18 +142,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) const bool isPhone = project->isActiveConfig(QStringLiteral("winphone")); #ifdef Q_OS_WIN - QString regKeyPrefix; -#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501 - BOOL isWow64; - IsWow64Process(GetCurrentProcess(), &isWow64); - if (!isWow64) - regKeyPrefix = QStringLiteral("Software\\"); - else -#endif - regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\"); - - QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir"); - const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey); + QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir"); + const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY); if (vcInstallDir.isEmpty()) { fprintf(stderr, "Failed to find the Visual Studio installation directory.\n"); return false; @@ -161,13 +151,13 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) QString windowsPath; if (isPhone) { - windowsPath = "Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v"; + windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v"; } else { - windowsPath = "Microsoft\\Microsoft SDKs\\Windows\\v"; + windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v"; } - regKey = regKeyPrefix + windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder"); - const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey); + regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder"); + const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY); if (kitDir.isEmpty()) { fprintf(stderr, "Failed to find the Windows Kit installation directory.\n"); return false; diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index d70480b028..1e187075c8 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -70,21 +70,6 @@ struct DotNetCombo { const char *versionStr; const char *regKey; } dotNetCombo[] = { -#ifdef Q_OS_WIN64 - {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"}, - {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"}, - {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"}, - {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"}, - {NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"}, - {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"}, - {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"}, - {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"}, - {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"}, - {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"}, - {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"}, - {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"}, - {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"}, -#else {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"}, {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"}, {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"}, @@ -98,7 +83,6 @@ struct DotNetCombo { {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"}, {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"}, {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"}, -#endif {NETUnknown, "", ""}, }; @@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray()) int installed = 0; int i = 0; for(; dotNetCombo[i].version; ++i) { - QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey); + QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey, + KEY_WOW64_32KEY); if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) { lowestInstalledVersion = &dotNetCombo[i]; installPaths.insert(lowestInstalledVersion->version, path); diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 11064a757d..5e28fda11d 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -69,17 +69,11 @@ struct CompilerInfo{ {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"}, {CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe {CC_MSVC2005, "Microsoft (R) Visual Studio 2005 C/C++ Compiler (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe - {CC_MSVC2005, "Microsoft (R) Visual Studio 2005 C/C++ Compiler (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe {CC_MSVC2008, "Microsoft (R) Visual Studio 2008 C/C++ Compiler (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe - {CC_MSVC2008, "Microsoft (R) Visual Studio 2008 C/C++ Compiler (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe {CC_MSVC2010, "Microsoft (R) Visual Studio 2010 C/C++ Compiler (10.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\10.0", "cl.exe"}, // link.exe, lib.exe - {CC_MSVC2010, "Microsoft (R) Visual Studio 2010 C/C++ Compiler (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\10.0", "cl.exe"}, // link.exe, lib.exe {CC_MSVC2012, "Microsoft (R) Visual Studio 2012 C/C++ Compiler (11.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe - {CC_MSVC2012, "Microsoft (R) Visual Studio 2012 C/C++ Compiler (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe {CC_MSVC2013, "Microsoft (R) Visual Studio 2013 C/C++ Compiler (12.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0", "cl.exe"}, // link.exe, lib.exe - {CC_MSVC2013, "Microsoft (R) Visual Studio 2013 C/C++ Compiler (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0", "cl.exe"}, // link.exe, lib.exe // Microsoft skipped version 13 - {CC_MSVC2015, "Microsoft (R) Visual Studio 2015 C/C++ Compiler (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VS7\\14.0", "cl.exe"}, // link.exe, lib.exe {CC_MSVC2015, "Microsoft (R) Visual Studio 2015 C/C++ Compiler (14.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VS7\\14.0", "cl.exe"}, // link.exe, lib.exe {CC_UNKNOWN, "Unknown", 0, 0}, }; @@ -196,7 +190,8 @@ Compiler Environment::detectCompiler() QString paths = qgetenv("PATH"); QStringList pathlist = paths.toLower().split(";"); for(int i = 0; compiler_info[i].compiler; ++i) { - QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower(); + QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey, + KEY_WOW64_32KEY).toLower(); if (productPath.length()) { QStringList::iterator it; for(it = pathlist.begin(); it != pathlist.end(); ++it) { diff --git a/tools/shared/windows/registry.cpp b/tools/shared/windows/registry.cpp index c989ae279b..432c707e28 100644 --- a/tools/shared/windows/registry.cpp +++ b/tools/shared/windows/registry.cpp @@ -74,7 +74,7 @@ static QString keyName(const QString &rKey) } #endif -QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey) +QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned long options) { QString result; @@ -83,7 +83,8 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey) QString rSubkeyPath = keyPath(rSubkey); HKEY handle = 0; - LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle); + LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, + KEY_READ | options, &handle); if (res != ERROR_SUCCESS) return QString(); @@ -152,6 +153,7 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey) #else Q_UNUSED(parentHandle); Q_UNUSED(rSubkey) + Q_UNUSED(options); #endif return result; diff --git a/tools/shared/windows/registry_p.h b/tools/shared/windows/registry_p.h index e13f9e6f46..4fa2d6aa9f 100644 --- a/tools/shared/windows/registry_p.h +++ b/tools/shared/windows/registry_p.h @@ -63,8 +63,14 @@ QT_BEGIN_NAMESPACE * If the key is not found, or the registry cannot be accessed (for example * if this code is compiled for a platform other than Windows), a null * string is returned. + * + * 32-bit code reads from the registry's 32 bit view (Wow6432Node), + * 64 bit code reads from the 64 bit view. + * Pass KEY_WOW64_32KEY to access the 32 bit view regardless of the + * application's architecture, KEY_WOW64_64KEY respectively. */ -QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey); +QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, + unsigned long options = 0); QT_END_NAMESPACE -- cgit v1.2.3 From 64ab4de4b0abb19fad18e009dfd094f1ae6a78c1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 25 Nov 2015 11:57:36 +0100 Subject: Teach qmake's #include parser to recognize C++11 Raw strings. Can't sensibly test unless the compiler does support raw strings, since any test that would catch qmake's (prior) inability to parse raw strings would necessarily confuse the C++ compiler in the same way. This even applies (in test app code) to any #if-ery around the raw string, since tokenization happens before preprocessor directives are resolved. So the #if-ery on Q_COMPILER_RAW_STRINGS has to be in tst_qmake.cpp, not the test app it builds. Change-Id: I4a461f515adff288b54fb273fd9996f9b906d11c Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 47 +++++++++++++++++----- tests/auto/tools/qmake/testdata/rawString/main.cpp | 37 +++++++++++++++++ .../auto/tools/qmake/testdata/rawString/object1.h | 41 +++++++++++++++++++ .../tools/qmake/testdata/rawString/rawString.pro | 4 ++ tests/auto/tools/qmake/tst_qmake.cpp | 19 +++++++++ 5 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 tests/auto/tools/qmake/testdata/rawString/main.cpp create mode 100644 tests/auto/tools/qmake/testdata/rawString/object1.h create mode 100644 tests/auto/tools/qmake/testdata/rawString/rawString.pro diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 0f11745f4c..b939a9c9d4 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -555,15 +555,44 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) // quoted strings if (buffer[x] == '\'' || buffer[x] == '"') { - const char term = buffer[x]; - while (++x < buffer_len) { - if (buffer[x] == term) { - ++x; - break; - } else if (buffer[x] == '\\') { - ++x; - } else if (qmake_endOfLine(buffer[x])) { - ++line_count; + // It might be a C++11 raw string. + bool israw = false; + if (buffer[x] == '"' && x > 0) { + int y = x; + while (--y > 0 && (buffer[y] == '8' || buffer[y] == 'u' || buffer[y] == 'U')) {} // skip + israw = (buffer[y] == 'R'); + } + if (israw) { + x++; + const char *const delim = buffer + x; + while (x < buffer_len && buffer[x] != '(') + x++; + /* + Not checking correctness (trust real compiler to do that): + - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; + - at most 16 bytes in delim + */ + + const int delimlen = buffer + x - delim; + while (++x < buffer_len + && (buffer[x] != ')' + || (delimlen > 0 && + strncmp(buffer + x + 1, delim, delimlen)) + || buffer[x + 1 + delimlen] != '"')) {} // skip + // buffer[x] is ')' + x += 1 + delimlen; // 1 for ')', then delim + // buffer[x] is '"' + } else { + const char term = buffer[x]; + while (++x < buffer_len) { + if (buffer[x] == term) { + ++x; + break; + } else if (buffer[x] == '\\') { + ++x; + } else if (qmake_endOfLine(buffer[x])) { + ++line_count; + } } } } diff --git a/tests/auto/tools/qmake/testdata/rawString/main.cpp b/tests/auto/tools/qmake/testdata/rawString/main.cpp new file mode 100644 index 0000000000..fb7008a1a9 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/main.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +static const char raw[] = R"blah(lorem " ipsum /*)blah"; +#include + +int main () { return 0; } diff --git a/tests/auto/tools/qmake/testdata/rawString/object1.h b/tests/auto/tools/qmake/testdata/rawString/object1.h new file mode 100644 index 0000000000..07af4229fb --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/object1.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +class Object1 : public QObject +{ + Q_OBJECT +}; + diff --git a/tests/auto/tools/qmake/testdata/rawString/rawString.pro b/tests/auto/tools/qmake/testdata/rawString/rawString.pro new file mode 100644 index 0000000000..d2d8132ceb --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/rawString.pro @@ -0,0 +1,4 @@ +DESTDIR = ./ + +HEADERS += object1.h +SOURCES += main.cpp diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp index ac94d1a2b9..d216a54575 100644 --- a/tests/auto/tools/qmake/tst_qmake.cpp +++ b/tests/auto/tools/qmake/tst_qmake.cpp @@ -79,6 +79,7 @@ private slots: void one_space(); void findMocs(); void findDeps(); + void rawString(); #if defined(Q_OS_MAC) void bundle_spaces(); #endif @@ -406,6 +407,24 @@ void tst_qmake::findDeps() QVERIFY( test_compiler.removeMakefile(workDir) ); } +void tst_qmake::rawString() +{ +#ifdef Q_COMPILER_RAW_STRINGS + QString workDir = base_path + "/testdata/rawString"; + + QVERIFY( test_compiler.qmake(workDir, "rawString") ); + QVERIFY( test_compiler.make(workDir) ); + QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.makeClean(workDir) ); + QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.makeDistClean(workDir ) ); + QVERIFY( !test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.removeMakefile(workDir) ); +#else + QSKIP("Test for C++11 raw strings depends on compiler support for them"); +#endif +} + struct TempFile : QFile { -- cgit v1.2.3 From 2baeeb4026e55955a329480b2550a4353291f8ca Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 7 Dec 2015 17:05:35 +0100 Subject: Win: Use native separators in QLibrary errors Fixes output like plugin cannot be loaded for module "QtWebEngine": Cannot load library D:/dev/qt/5.6/msvc-2015-32/qtbase/qml/QtWebEngine/qtwebengineplugind.dll: The specified procedure could not be found. Change-Id: I159113a6a1f40b924905da15267a42e5b627d56e Reviewed-by: Friedemann Kleint Reviewed-by: Thiago Macieira --- src/corelib/plugin/qlibrary_win.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index c1ce198c84..f5604a24bd 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -124,7 +124,8 @@ bool QLibraryPrivate::load_sys() SetErrorMode(oldmode); #endif if (!pHnd) { - errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string()); + errorString = QLibrary::tr("Cannot load library %1: %2").arg( + QDir::toNativeSeparators(fileName)).arg(qt_error_string()); } else { // Query the actual name of the library that was loaded errorString.clear(); @@ -148,7 +149,8 @@ bool QLibraryPrivate::load_sys() bool QLibraryPrivate::unload_sys() { if (!FreeLibrary(pHnd)) { - errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string()); + errorString = QLibrary::tr("Cannot unload library %1: %2").arg( + QDir::toNativeSeparators(fileName)).arg(qt_error_string()); return false; } errorString.clear(); @@ -164,7 +166,8 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) #endif if (!address) { errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( - QString::fromLatin1(symbol)).arg(fileName).arg(qt_error_string()); + QString::fromLatin1(symbol)).arg( + QDir::toNativeSeparators(fileName)).arg(qt_error_string()); } else { errorString.clear(); } -- cgit v1.2.3 From 6de49f4ab6e6c8c6e664f7dd6c8c441bf7685a56 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 11 Oct 2015 15:01:06 +0200 Subject: QString: where possible, re-use existing capacity in op(QChar/QL1S) If the LHS is detached and has existing capacity that is large enough to hold the RHS, re-use the memory instead of allocating a new buffer and throwing away the old. Change-Id: I53d42825da92c264c7301e8e771cba9fb35c321b Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 22 +++++++- src/corelib/tools/qstring.h | 7 +-- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 66 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 7 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index d1b5327f5c..71d0be1dcf 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1818,6 +1818,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW Assigns the Latin-1 string \a str to this string. */ +QString &QString::operator=(QLatin1String other) +{ + if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull) + d->size = other.size(); + d->data()[other.size()] = 0; + qt_from_latin1(d->data(), other.latin1(), other.size()); + } else { + *this = fromLatin1(other.latin1(), other.size()); + } + return *this; +} /*! \fn QString &QString::operator=(const QByteArray &ba) @@ -1868,7 +1879,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW */ QString &QString::operator=(QChar ch) { - return operator=(QString(ch)); + if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull) + // re-use existing capacity: + ushort *dat = d->data(); + dat[0] = ch.unicode(); + dat[1] = 0; + d->size = 1; + } else { + operator=(QString(ch)); + } + return *this; } /*! diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index d21708efb9..1d04bcb457 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -221,7 +221,7 @@ public: inline ~QString(); QString &operator=(QChar c); QString &operator=(const QString &) Q_DECL_NOTHROW; - inline QString &operator=(QLatin1String latin1); + QString &operator=(QLatin1String latin1); #ifdef Q_COMPILER_RVALUE_REFS inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); } inline QString &operator=(QString &&other) Q_DECL_NOTHROW @@ -884,11 +884,6 @@ inline void QString::detach() { if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); } inline bool QString::isDetached() const { return !d->ref.isShared(); } -inline QString &QString::operator=(QLatin1String s) -{ - *this = fromLatin1(s.latin1(), s.size()); - return *this; -} inline void QString::clear() { if (!isNull()) *this = QString(); } inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d) diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index cc9f250be9..907dcf17e1 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -582,6 +582,7 @@ private slots: void compareQLatin1Strings(); void fromQLatin1StringWithLength(); void assignQLatin1String(); + void assignQChar(); void isRightToLeft_data(); void isRightToLeft(); void unicodeStrings(); @@ -6598,6 +6599,71 @@ void tst_QString::assignQLatin1String() QCOMPARE(foo.size(), latin1subfoo.size()); QCOMPARE(foo, QString::fromLatin1("foo")); + // check capacity re-use: + QString s; + QCOMPARE(s.capacity(), 0); + + // assign to null QString: + s = latin1foo; + QCOMPARE(s, QString::fromLatin1("foo")); + QCOMPARE(s.capacity(), 3); + + // assign to non-null QString with enough capacity: + s = QString::fromLatin1("foofoo"); + const int capacity = s.capacity(); + s = latin1foo; + QCOMPARE(s, QString::fromLatin1("foo")); + QCOMPARE(s.capacity(), capacity); + + // assign to shared QString (enough capacity, but can't use): + s = QString::fromLatin1("foofoo"); + QString s2 = s; + s = latin1foo; + QCOMPARE(s, QString::fromLatin1("foo")); + QCOMPARE(s.capacity(), 3); + + // assign to QString with too little capacity: + s = QString::fromLatin1("fo"); + QCOMPARE(s.capacity(), 2); + s = latin1foo; + QCOMPARE(s, QString::fromLatin1("foo")); + QCOMPARE(s.capacity(), 3); + +} + +void tst_QString::assignQChar() +{ + const QChar sp = QLatin1Char(' '); + QString s; + QCOMPARE(s.capacity(), 0); + + // assign to null QString: + s = sp; + QCOMPARE(s, QString(sp)); + QCOMPARE(s.capacity(), 1); + + // assign to non-null QString with enough capacity: + s = QLatin1String("foo"); + const int capacity = s.capacity(); + QCOMPARE(capacity, 3); + s = sp; + QCOMPARE(s, QString(sp)); + QCOMPARE(s.capacity(), capacity); + + // assign to shared QString (enough capacity, but can't use): + s = QLatin1String("foo"); + QString s2 = s; + s = sp; + QCOMPARE(s, QString(sp)); + QCOMPARE(s.capacity(), 1); + + // assign to empty QString: + s = QString(""); + s.detach(); + QCOMPARE(s.capacity(), 0); + s = sp; + QCOMPARE(s, QString(sp)); + QCOMPARE(s.capacity(), 1); } void tst_QString::isRightToLeft_data() -- cgit v1.2.3 From f044b3cc673ce854eae909cfbb7f00647acc61c8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 4 Dec 2015 12:29:22 +0100 Subject: QWinRTFontDatabase: Add "Arial" as alias for "Helvetica". Otherwise, the first font from the list is used ("Algerian" or similar), making the widgets/richtext/textedit example look bad. Change-Id: Ia5bb8879f167fef7ad7e81611760ee042abf8da3 Reviewed-by: Oliver Wolff Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 14 ++++++++++++++ src/plugins/platforms/winrt/qwinrtfontdatabase.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index c348faf015..9bd51218a4 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -428,6 +428,20 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl return engine; } +QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const +{ + Q_UNUSED(style) + Q_UNUSED(styleHint) + Q_UNUSED(script) + + QStringList result; + if (family == QLatin1String("Helvetica")) + result.append(QStringLiteral("Arial")); + return result; +} + void QWinRTFontDatabase::releaseHandle(void *handle) { if (!handle) diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index a88092e432..41619f5bd8 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -60,6 +60,8 @@ public: void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE; void releaseHandle(void *handle) Q_DECL_OVERRIDE; private: QHash m_fonts; -- cgit v1.2.3 From 52e994c8a37e9e9b84f32e2c75b8219242481384 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 9 Jul 2015 18:02:38 +0100 Subject: Favor OpenGLES 3 on iOS if available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First tries OpenGLES 3 context since it’s strictly compatible with OpenGLES 2. If it fails, then try 2. This is required to use QOpenGLFramebufferObject::blitFramebuffer without having to look at using an Apple-specific extension. Change-Id: I01f8f058fa82e7f2c90d1b894ad36f3d3939c994 Reviewed-by: Tor Arne Vestbø Reviewed-by: Laszlo Agocs --- src/plugins/platforms/ios/qioscontext.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index fe0ca33c13..cc42b6057e 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -48,9 +48,11 @@ QIOSContext::QIOSContext(QOpenGLContext *context) , m_format(context->format()) { m_format.setRenderableType(QSurfaceFormat::OpenGLES); - m_eaglContext = [[EAGLContext alloc] - initWithAPI:EAGLRenderingAPI(m_format.majorVersion()) - sharegroup:m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil]; + EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil; + for (int version = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3; + version >= m_format.majorVersion() && !m_eaglContext; --version) { + m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup]; + } if (m_eaglContext != nil) { EAGLContext *originalContext = [EAGLContext currentContext]; -- cgit v1.2.3 From c5e972eb87c5dbdbc0fc2ff15759ff0adaea8dfa Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 7 Dec 2015 18:15:07 +0100 Subject: QFileDialog: Call reject() on Key_Escape even when itemview has focus Replace hide() call (present in itemViewKeyboardEvent since Qt 4.5) by reject(). Add signal spy to existing test function. QDialog doc states that reject() will always be called on Key_Escape. hide() is not enough: it makes exec() terminate and return the proper value, but the signals finished(int) and rejected() will not be sent. Task-number: QTBUG-7690 Change-Id: Ica4ae2843574478c5b9a7672f871f3ef3f16f3c9 Done-with: Jan Blumschein Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 2 +- .../dialogs/qfiledialog2/tst_qfiledialog2.cpp | 33 ++++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index e62fab6f08..bdfa27282f 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3793,7 +3793,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { Q_Q(QFileDialog); if (event->matches(QKeySequence::Cancel)) { - q->hide(); + q->reject(); return true; } diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index d48c718d4d..b04711b282 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -130,6 +130,7 @@ private slots: #endif void completionOnLevelAfterRoot(); void task233037_selectingDirectory(); + void task235069_hideOnEscape_data(); void task235069_hideOnEscape(); void task203703_returnProperSeparator(); void task228844_ensurePreviousSorting(); @@ -770,26 +771,36 @@ void tst_QFileDialog2::task233037_selectingDirectory() current.rmdir("test"); } +void tst_QFileDialog2::task235069_hideOnEscape_data() +{ + QTest::addColumn("childName"); + QTest::newRow("listView") << QStringLiteral("listView"); + QTest::newRow("fileNameEdit") << QStringLiteral("fileNameEdit"); + QTest::newRow("treeView") << QStringLiteral("treeView"); +} + void tst_QFileDialog2::task235069_hideOnEscape() { + QFETCH(QString, childName); QDir current = QDir::currentPath(); + QNonNativeFileDialog fd; + QSignalSpy spyFinished(&fd, &QDialog::finished); + QVERIFY(spyFinished.isValid()); + QSignalSpy spyRejected(&fd, &QDialog::rejected); + QVERIFY(spyRejected.isValid()); fd.setViewMode(QFileDialog::List); fd.setDirectory(current.absolutePath()); - fd.setAcceptMode( QFileDialog::AcceptSave); + fd.setAcceptMode(QFileDialog::AcceptSave); fd.show(); - QListView *list = fd.findChild("listView"); - list->setFocus(); + QWidget *child = fd.findChild(childName); + QVERIFY(child); + child->setFocus(); QTest::qWait(200); - QTest::keyClick(list, Qt::Key_Escape); + QTest::keyClick(child, Qt::Key_Escape); QCOMPARE(fd.isVisible(), false); - QNonNativeFileDialog fd2; - fd2.setDirectory(current.absolutePath()); - fd2.setAcceptMode( QFileDialog::AcceptSave); - fd2.show(); - QLineEdit *edit = fd2.findChild("fileNameEdit"); - QTest::keyClick(edit, Qt::Key_Escape); - QCOMPARE(fd2.isVisible(), false); + QCOMPARE(spyFinished.count(), 1); // QTBUG-7690 + QCOMPARE(spyRejected.count(), 1); // reject(), don't hide() } #ifdef QT_BUILD_INTERNAL -- cgit v1.2.3 From e98922bbde9e66e5355afa61857c1ecb70ee8df1 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 26 Nov 2015 14:52:24 +0100 Subject: iOS: support edit action 'select' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we don't populate the edit menu from qtquickcontrols anymore (because of shortcut issues), report to UIKit that we support select so that the action shows in the menu. Change-Id: I92508da4e1789c361d778cc6c1c77c86308f4c73 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 9ca5e22b90..434ba2edc6 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -382,6 +382,13 @@ [self sendShortcut:QKeySequence::Paste]; } +- (void)select:(id)sender +{ + Q_UNUSED(sender); + [self sendShortcut:QKeySequence::MoveToPreviousWord]; + [self sendShortcut:QKeySequence::SelectNextWord]; +} + - (void)selectAll:(id)sender { Q_UNUSED(sender); -- cgit v1.2.3 From 7bee5fa2ce5ef7ed3f1da1a336c21a74ceeaec7c Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 25 Nov 2015 12:30:41 +0100 Subject: iOS: filter edit menu actions depending on selection state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When showing an edit menu on iOS, UIKit will always populate the menu with actions according to what the current first responder supports. But it doesn't make sense to show all the actions every time the menu opens, so introduce some filtering depending on selection state. Change-Id: I943a09928233a3a10de003fe15ed8fd8b6fc1e18 Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 434ba2edc6..770dadd3e4 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -364,6 +364,32 @@ [self sendKeyPressRelease:key modifiers:modifiers]; } +- (BOOL)canPerformAction:(SEL)action withSender:(id)sender +{ + bool isEditAction = (action == @selector(cut:) + || action == @selector(copy:) + || action == @selector(paste:) + || action == @selector(delete:) + || action == @selector(toggleBoldface:) + || action == @selector(toggleItalics:) + || action == @selector(toggleUnderline:) + || action == @selector(undo) + || action == @selector(redo)); + + bool isSelectAction = (action == @selector(select:) + || action == @selector(selectAll:) + || action == @selector(paste:) + || action == @selector(undo) + || action == @selector(redo)); + + const bool unknownAction = !isEditAction && !isSelectAction; + const bool hasSelection = ![self selectedTextRange].empty; + + if (unknownAction) + return [super canPerformAction:action withSender:sender]; + return (hasSelection && isEditAction) || (!hasSelection && isSelectAction); +} + - (void)cut:(id)sender { Q_UNUSED(sender); -- cgit v1.2.3 From 7ee0415d276dce633b2738e9a3c45f3ef5a05518 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 8 Dec 2015 14:20:44 +0100 Subject: Align signature with generic native socket engine This allows to use readDatagram on WinRT like on any other platform, ie using two arguments. Fixes compilation in auto-tests. Change-Id: I4a6e34dc72d2845faab9067ce67800d8b386c344 Reviewed-by: Oliver Wolff --- src/network/socket/qnativesocketengine_winrt_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 912b7db973..c48b0e85d9 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -96,7 +96,7 @@ public: qint64 read(char *data, qint64 maxlen); qint64 write(const char *data, qint64 len); - qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions); + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone); qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header); bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; -- cgit v1.2.3 From b1f553b68e153ee7a5ca2b4fb9e5122e02525404 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 8 Dec 2015 09:51:33 +0100 Subject: doc: fix the shortcut for QListWidget::itemActivated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-49805 Change-Id: Ia7317e9c6ad5b5f6c17ff1e197ec690ebc20da3d Reviewed-by: Topi Reiniö --- src/widgets/itemviews/qlistwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 0e1e56e966..d4d22c8bef 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -1262,7 +1262,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, activated when the user clicks or double clicks on it, depending on the system configuration. It is also activated when the user presses the activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS - X it is \uicontrol{Ctrl+0}). + X it is \uicontrol{Command+O}). */ /*! -- cgit v1.2.3 From 7afc139e0801fd6390065f23d5870cbadbb92b9d Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 7 Dec 2015 12:23:44 +0100 Subject: Doc: do not claim that SUBDIRS.depends is only available for Makefiles This information is outdated. Change-Id: Ic2e10f7c858eed6f1b7c550995cb29004b4bd280 Reviewed-by: Oswald Buddenhagen --- qmake/doc/src/qmake-manual.qdoc | 1 - 1 file changed, 1 deletion(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 6915c2e5c1..e59b0ddcbe 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2408,7 +2408,6 @@ \row \li .file \li Specify the subproject \c pro file explicitly. Cannot be used in conjunction with \c .subdir modifier. \row \li .depends \li This subproject depends on specified subproject. - Available only on platforms that use makefiles. \row \li .makefile \li The makefile of subproject. Available only on platforms that use makefiles. \row \li .target \li Base string used for makefile targets related to this -- cgit v1.2.3 From 8f74fe1b66aed3ca26a9721359472c86d0beeb5b Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 7 Dec 2015 12:15:13 +0100 Subject: Doc: Circumvented qdoc parsing by removing '!' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qdoc gave warning "Cannot link this to anything" Task-number: QTBUG-43810 Change-Id: Id903040ed7b2860a2ec64a52f7fbe8269c6927b0 Reviewed-by: Martin Smith Reviewed-by: Topi Reiniö --- src/corelib/tools/qstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 71d0be1dcf..8c06ec4045 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5686,7 +5686,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const */ namespace QUnicodeTables { -/*! +/* \internal Converts the \a str string starting from the position pointed to by the \a it iterator, using the Unicode case traits \c Traits, and returns the -- cgit v1.2.3 From 1b61390856ce336c82f7b99def574775893bf4f2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 1 Dec 2015 12:31:14 +0100 Subject: Reduce flushes with repaint() when GL-based compositing is active Task-number: QTBUG-49655 Change-Id: I7a5d08f681a7d87709aac745154730764040e922 Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qwindow_p.h | 2 ++ src/gui/painting/qplatformbackingstore.cpp | 2 ++ .../qopenglcompositorbackingstore.cpp | 3 +++ src/widgets/kernel/qwidgetbackingstore.cpp | 20 ++++++++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 23a6d800c0..6880edaada 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -50,6 +50,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -187,6 +188,7 @@ public: #endif bool compositing; + QElapsedTimer lastComposeTime; }; diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 4e26d8f741..cda2446a5e 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -301,6 +301,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i return; } + QWindowPrivate::get(window)->lastComposeTime.start(); + QOpenGLFunctions *funcs = context->functions(); funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio()); funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1); diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index 6f71fb637f..fee3146f04 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "qopenglcompositorbackingstore_p.h" #include "qopenglcompositor_p.h" @@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi dstCtx->makeCurrent(dstWin); + QWindowPrivate::get(window)->lastComposeTime.start(); + m_textures->clear(); for (int i = 0; i < textures->count(); ++i) m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i), diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index b86c376385..17187002ca 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -448,6 +448,26 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi if (!widget) return; +#ifndef QT_NO_OPENGL + // Having every repaint() leading to a sync/flush is bad as it causes + // compositing and waiting for vsync each and every time. Change to + // UpdateLater, except for approx. once per frame to prevent starvation in + // case the control does not get back to the event loop. + QWidget *w = widget->window(); + if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) { + int refresh = 60; + QScreen *ws = w->windowHandle()->screen(); + if (ws) + refresh = ws->refreshRate(); + QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle()); + if (wd->lastComposeTime.isValid()) { + const qint64 elapsed = wd->lastComposeTime.elapsed(); + if (elapsed <= qint64(1000.0f / refresh)) + updateTime = UpdateLater; + } + } +#endif + switch (updateTime) { case UpdateLater: updateRequestSent = true; -- cgit v1.2.3 From 01fe8906f3733622f469c3ee56b78befba3d9d61 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 7 Dec 2015 12:18:20 +0100 Subject: Fix QAction MenuRole documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib5e5353480b640f5bcc0e21682de168fadde78fc Reviewed-by: Topi Reiniö --- src/widgets/kernel/qaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 1563d020b6..31cb1915e4 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -255,7 +255,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) \value TextHeuristicRole This action should be put in the application menu based on the action's text as described in the QMenuBar documentation. \value ApplicationSpecificRole This action should be put in the application menu with an application specific role - \value AboutQtRole This action matches handles the "About Qt" menu item. + \value AboutQtRole This action handles the "About Qt" menu item. \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of the menu item will be set to "About ". The application name is fetched from the \c{Info.plist} file in the application's bundle (See \l{Qt for OS X - Deployment}). -- cgit v1.2.3 From 3414be909df60fa8a726c692b2a93f6b36a9c474 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 8 Dec 2015 10:32:39 +0100 Subject: Fix QAction::menuRole() documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I9299948ba99634ea92f8b5cd4405e814e86f6aa6 Reviewed-by: Topi Reiniö --- src/widgets/kernel/qaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 31cb1915e4..2c4e4d3125 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -1231,7 +1231,7 @@ void QAction::activate(ActionEvent event) \since 4.2 This indicates what role the action serves in the application menu on Mac - OS X. By default all action have the TextHeuristicRole, which means that + OS X. By default all actions have the TextHeuristicRole, which means that the action is added based on its text (see QMenuBar for more information). The menu role can only be changed before the actions are put into the menu -- cgit v1.2.3 From 5ac2b391333d0b3047b64dd840a8109274b0fe88 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Dec 2015 17:00:56 +0100 Subject: Fix URL to "The Microsoft Windows User Experience". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-49799 Change-Id: Ie03ac06966ed97888c0a348a3f2195fd7cbd299a Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- src/widgets/doc/src/guibooks.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/doc/src/guibooks.qdoc b/src/widgets/doc/src/guibooks.qdoc index 8a1198c328..b3afe06961 100644 --- a/src/widgets/doc/src/guibooks.qdoc +++ b/src/widgets/doc/src/guibooks.qdoc @@ -76,7 +76,7 @@ advises against will produce more easily comprehensible software. Doing what it tells you to do may also help. - \b{\l{http://www.amazon.com/exec/obidos/ASIN/047159900X/trolltech/t}{The + \b{\l{http://www.amazon.com/New-Windows-Interface-Microsoft-Press/dp/1556156790/}{The Microsoft Windows User Experience}}, ISBN 1-55615-679-0, is Microsoft's look and feel bible. Indispensable for everyone who has customers that worship Microsoft, and it's quite good, too. -- cgit v1.2.3 From 893f2ade8573af56f761a1361dfe1e1f03154bdd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Dec 2015 16:19:30 +0100 Subject: Fix debug operator for QRegion. Use QDebugStateSaver, drop the multiline format, check for null, empty and output rectangular regions as: QRegion(0,0 252x188) and complicated regions as: QRegion(size=4, bounds=(0,0 278x262) - [(0,0 278x13), (0,13 13x188), (265,13 13x188), (0,201 278x61)]) Change-Id: I82b8f58af08f7128e6cf2c2c8b06c4684fc6a9c8 Reviewed-by: Shawn Rutledge Reviewed-by: Gunnar Sletta --- src/gui/painting/qregion.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index e6b777a30e..5e648eabf5 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -41,7 +41,7 @@ #include "qimage.h" #include "qbitmap.h" -#include +#include QT_BEGIN_NAMESPACE @@ -422,11 +422,32 @@ QDataStream &operator>>(QDataStream &s, QRegion &r) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug s, const QRegion &r) { - QVector rects = r.rects(); - s.nospace() << "QRegion(size=" << rects.size() << "), " - << "bounds = " << r.boundingRect() << '\n'; - for (int i=0; i rects = r.rects(); + const int count = rects.size(); + if (count > 1) + s << "size=" << count << ", bounds=("; + QtDebugUtils::formatQRect(s, r.boundingRect()); + if (count > 1) { + s << ") - ["; + for (int i = 0; i < count; ++i) { + if (i) + s << ", "; + s << '('; + QtDebugUtils::formatQRect(s, rects.at(i)); + s << ')'; + } + s << ']'; + } + } + s << ')'; return s; } #endif -- cgit v1.2.3 From fcedf8998ebab0c67b2e606b2e89e738e0137a3d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 8 Dec 2015 10:39:57 +0100 Subject: fortuneserver/fortuneclient: Fix layout for WinRT. Use the new API QStyleHints::showIsMaximized(). Change-Id: I1342b3c29ef4ccfcf635a32d403f9aa7ce0cb4e4 Reviewed-by: Oliver Wolff --- examples/network/fortuneclient/client.cpp | 2 +- examples/network/fortuneserver/server.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/network/fortuneclient/client.cpp b/examples/network/fortuneclient/client.cpp index b4c3d9328d..42fed30445 100644 --- a/examples/network/fortuneclient/client.cpp +++ b/examples/network/fortuneclient/client.cpp @@ -117,7 +117,7 @@ Client::Client(QWidget *parent) //! [4] QGridLayout *mainLayout = Q_NULLPTR; - if (QGuiApplication::styleHints()->showIsFullScreen()) { + if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) { QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this); outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); QHBoxLayout *outerHorizontalLayout = new QHBoxLayout; diff --git a/examples/network/fortuneserver/server.cpp b/examples/network/fortuneserver/server.cpp index 28f0230894..089f594cab 100644 --- a/examples/network/fortuneserver/server.cpp +++ b/examples/network/fortuneserver/server.cpp @@ -100,7 +100,7 @@ Server::Server(QWidget *parent) buttonLayout->addStretch(1); QVBoxLayout *mainLayout = Q_NULLPTR; - if (QGuiApplication::styleHints()->showIsFullScreen()) { + if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) { QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this); outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); QHBoxLayout *outerHorizontalLayout = new QHBoxLayout; -- cgit v1.2.3 From b880b7e1ac15f3458c009d63002c872e7521eeab Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 8 Dec 2015 11:27:45 +0100 Subject: Standarddialogs example: Adapt layout for fullscreen platforms. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Insert a group box depending on style hints. Change-Id: I1b49dc31d5bd32c92d88f95be0683d5223329c11 Reviewed-by: Topi Reiniö Reviewed-by: Oliver Wolff --- examples/widgets/dialogs/standarddialogs/dialog.cpp | 16 +++++++++++++--- examples/widgets/dialogs/standarddialogs/main.cpp | 12 ++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/examples/widgets/dialogs/standarddialogs/dialog.cpp b/examples/widgets/dialogs/standarddialogs/dialog.cpp index b4232c36f6..b28cf0f934 100644 --- a/examples/widgets/dialogs/standarddialogs/dialog.cpp +++ b/examples/widgets/dialogs/standarddialogs/dialog.cpp @@ -98,9 +98,19 @@ int DialogOptionsWidget::value() const Dialog::Dialog(QWidget *parent) : QWidget(parent) { - QVBoxLayout *mainLayout = new QVBoxLayout(this); + QVBoxLayout *verticalLayout; + if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) { + QHBoxLayout *horizontalLayout = new QHBoxLayout(this); + QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName(), this); + horizontalLayout->addWidget(groupBox); + horizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored)); + verticalLayout = new QVBoxLayout(groupBox); + } else { + verticalLayout = new QVBoxLayout(this); + } + QToolBox *toolbox = new QToolBox; - mainLayout->addWidget(toolbox); + verticalLayout->addWidget(toolbox); errorMessageDialog = new QErrorMessage(this); @@ -291,7 +301,7 @@ Dialog::Dialog(QWidget *parent) layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0); toolbox->addItem(page, tr("Message Boxes")); - setWindowTitle(tr("Standard Dialogs")); + setWindowTitle(QGuiApplication::applicationDisplayName()); } void Dialog::setInteger() diff --git a/examples/widgets/dialogs/standarddialogs/main.cpp b/examples/widgets/dialogs/standarddialogs/main.cpp index a13e37905c..8a8ee2ac0b 100644 --- a/examples/widgets/dialogs/standarddialogs/main.cpp +++ b/examples/widgets/dialogs/standarddialogs/main.cpp @@ -39,6 +39,7 @@ ****************************************************************************/ #include +#include #include #include #include @@ -49,6 +50,7 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); + QGuiApplication::setApplicationDisplayName(Dialog::tr("Standard Dialogs")); #ifndef QT_NO_TRANSLATION QString translatorFileName = QLatin1String("qt_"); @@ -59,10 +61,12 @@ int main(int argc, char *argv[]) #endif Dialog dialog; - const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog); - dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3); - dialog.move((availableGeometry.width() - dialog.width()) / 2, - (availableGeometry.height() - dialog.height()) / 2); + if (!QGuiApplication::styleHints()->showIsFullScreen() && !QGuiApplication::styleHints()->showIsMaximized()) { + const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog); + dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3); + dialog.move((availableGeometry.width() - dialog.width()) / 2, + (availableGeometry.height() - dialog.height()) / 2); + } dialog.show(); return app.exec(); -- cgit v1.2.3 From b64c11f46490840629a72ebe78316342c9f6ff31 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 9 Dec 2015 10:31:57 +0100 Subject: Doc: Online template: dynamically load footer content Add a line to load footer content from the global style folder. Change-Id: If57f13c2301e6145a26b3a4d04c7cb4695fe55fe Reviewed-by: Leena Miettinen --- doc/global/html-header-online.qdocconf | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/global/html-header-online.qdocconf b/doc/global/html-header-online.qdocconf index 450eb1120b..02b7375d32 100644 --- a/doc/global/html-header-online.qdocconf +++ b/doc/global/html-header-online.qdocconf @@ -36,6 +36,7 @@ HTML.headerscripts = \ " \n" \ " \n" \ -- cgit v1.2.3 From b4d3f9bd82afed69036015fbfe71526050e0effb Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 9 Dec 2015 12:36:10 +0100 Subject: Check for any existing file in XCOMPOSEFILE. Before this change, it was checked if the path ends with "Compose", which was an invalid assumption as the file can have any name (see [1]) This replaces the check with a check for any existing file (which wasn't checked before). [1] http://www.x.org/releases/X11R7.7/doc/man/man5/Compose.5.xhtml Done-with: Florian Bruhin Task-number: QTBUG-41557 Change-Id: If4fb58d4c1ed695f2d611236abfe97964b548678 Reviewed-by: Gatis Paeglis --- .../platforminputcontexts/compose/generator/qtablegenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index ad9877eb25..4126456f90 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -263,11 +263,11 @@ QString TableGenerator::findComposeFile() { // check if XCOMPOSEFILE points to a Compose file if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) { - QString path(qgetenv("XCOMPOSEFILE")); - if (path.endsWith(QLatin1String("Compose"))) + const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE")); + if (QFile::exists(path)) return path; else - qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file"); + qWarning("$XCOMPOSEFILE doesn't point to an existing file"); } // check if user’s home directory has a file named .XCompose -- cgit v1.2.3 From 6e6f27b6ec4455bf42343bac575109ed1de20c3a Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Mon, 7 Dec 2015 22:09:35 +0100 Subject: Use CROSS_COMPILE when setting PKG_CONFIG. If CROSS_COMPILE is set on a Debian multiarch platform, then PKG_CONFIG should be set the same way as the other cross compilation tools. Change-Id: Id359a6bbdcbf8a136a0268a82301fc086a2adcfe Reviewed-by: Oswald Buddenhagen --- mkspecs/devices/common/linux_device_pre.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkspecs/devices/common/linux_device_pre.conf b/mkspecs/devices/common/linux_device_pre.conf index 16becbdd52..cfbdc23d63 100644 --- a/mkspecs/devices/common/linux_device_pre.conf +++ b/mkspecs/devices/common/linux_device_pre.conf @@ -23,3 +23,6 @@ QMAKE_AR = $${CROSS_COMPILE}ar cqs QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_NM = $${CROSS_COMPILE}nm -P QMAKE_STRIP = $${CROSS_COMPILE}strip + +contains(DISTRO_OPTS, deb-multi-arch): \ + PKG_CONFIG = $${CROSS_COMPILE}pkg-config -- cgit v1.2.3 From bf4b2810999f9c1b0512437101170d93e3ff9613 Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Fri, 23 Oct 2015 00:59:45 +0200 Subject: Add generic g++ spec for arm devices. A minimal device spec that can be used to build for arm devices. Change-Id: I4c9949d8cc59ad534fc7617034f6beb40d6a987e Reviewed-by: Oswald Buddenhagen --- mkspecs/devices/linux-arm-generic-g++/qmake.conf | 9 ++++++ .../devices/linux-arm-generic-g++/qplatformdefs.h | 34 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 mkspecs/devices/linux-arm-generic-g++/qmake.conf create mode 100644 mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h diff --git a/mkspecs/devices/linux-arm-generic-g++/qmake.conf b/mkspecs/devices/linux-arm-generic-g++/qmake.conf new file mode 100644 index 0000000000..3dbd297b94 --- /dev/null +++ b/mkspecs/devices/linux-arm-generic-g++/qmake.conf @@ -0,0 +1,9 @@ +# +# Generic qmake configuration for building with g++ on arm devices. +# +# A minimal configure line could look something like this: +# ./configure -device arm-generic-g++ -device-option CROSS_COMPILE=arm-linux-gnueabi- + +include(../common/linux_device_pre.conf) +include(../common/linux_arm_device_post.conf) +load(qt_config) diff --git a/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h b/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h new file mode 100644 index 0000000000..5ae49b35dd --- /dev/null +++ b/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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$ +** +****************************************************************************/ + +#include "../../linux-g++/qplatformdefs.h" -- cgit v1.2.3 From 7d2c87311e682eabc9b7a3b1e1b4e2f21d0623bf Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 8 Dec 2015 13:50:24 +0100 Subject: QProcessPrivate::startProcess - fix invalid encodedProgramName (OS X) CFBundleCopyExecutableURL returns different URLs (can be absolute or relative) for the same bundle (caching) - and this results in an invalid encodedProgramName (in case we try to start the same process twice), for example, if we start: QProcess p; p.start("nestedDir/nested.app") twice, the second time we'll have an error trying to start something like nestedDir/nested.app/_and_here_absolute_url. Change-Id: I8ac42e20fe3b9fe8b80d5b5c663672e77d88269d Task-number: QTBUG-49837 Reviewed-by: Jake Petroules --- src/corelib/io/qprocess_unix.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index a5488f48cc..8eb5ac9564 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -92,6 +92,7 @@ QT_END_NAMESPACE #include #include #include +#include #include #include #include @@ -362,11 +363,14 @@ void QProcessPrivate::startProcess() static QBasicMutex cfbundleMutex; QMutexLocker lock(&cfbundleMutex); QCFType bundle = CFBundleCreate(0, url); - url = CFBundleCopyExecutableURL(bundle); + // 'executableURL' can be either relative or absolute ... + QCFType executableURL = CFBundleCopyExecutableURL(bundle); + // not to depend on caching - make sure it's always absolute. + url = CFURLCopyAbsoluteURL(executableURL); } if (url) { - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8(); + const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8(); } } #endif -- cgit v1.2.3 From 0ea3d630b1fd1fc21c65c43063792e4cbf0c2cdf Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 8 Dec 2015 11:42:24 +0100 Subject: winrt: Store exit code in pid file We have to call Exit() to successfully close an application as done in 25dcc90d799fba3e3f0391783ed07cb22cd1115a. Unfortunately Exit() always sets the exit code to 1 and this cannot be changed programmatically. Hence write the exit code into the pid file which is created when launched via winrtrunner. winrtrunner then fetches the content and passes the exit code to its callee. This implies that the pidFile is not deleted by the app itself anymore. Task-number: QTBUG-38654 Change-Id: Ib9b6ae4a0d61c9bf7e530e984aae3ad6204c39a0 Reviewed-by: Oliver Wolff --- src/winmain/qtmain_winrt.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 473c41ab8e..5d2abcccc7 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -140,6 +140,8 @@ public: hr = applicationFactory->CreateInstance(this, &base, &core); RETURN_VOID_IF_FAILED("Failed to create application container instance"); + + pidFile = INVALID_HANDLE_VALUE; } ~AppContainer() @@ -157,6 +159,13 @@ public: int argc = app->args.count(); char **argv = app->args.data(); const int res = main(argc, argv); + if (app->pidFile != INVALID_HANDLE_VALUE) { + const QByteArray resString = QByteArray::number(res); + WriteFile(app->pidFile, reinterpret_cast(resString.constData()), + resString.size(), NULL, NULL); + FlushFileBuffers(app->pidFile); + CloseHandle(app->pidFile); + } app->core->Exit(); return res; }, this, CREATE_SUSPENDED, nullptr); @@ -248,11 +257,10 @@ private: .absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid")); CREATEFILE2_EXTENDED_PARAMETERS params = { sizeof(CREATEFILE2_EXTENDED_PARAMETERS), - FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE + FILE_ATTRIBUTE_NORMAL }; - // (Unused) handle will automatically be closed when the app exits - CreateFile2(reinterpret_cast(pidFileName.utf16()), - 0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, ¶ms); + pidFile = CreateFile2(reinterpret_cast(pidFileName.utf16()), + GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, 0); // Install the develMode message handler #ifndef Q_OS_WINPHONE defaultMessageHandler = qInstallMessageHandler(devMessageHandler); @@ -315,6 +323,7 @@ private: QByteArray commandLine; QVarLengthArray args; HANDLE mainThread; + HANDLE pidFile; }; // Main entry point for Appx containers -- cgit v1.2.3 From ea8a92c9c93f74b23c4520d7bef357a7a8ec00df Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 9 Nov 2015 11:50:17 +0100 Subject: Clarify what time-zone "transitions" are. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idad5b841c3c693e2040ca606894187988615c9b0 Reviewed-by: Topi Reiniö --- src/corelib/tools/qtimezone.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 57c1838b76..333a5c3471 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -695,6 +695,11 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const /*! Returns \c true if the system backend supports obtaining transitions. + + Transitions are changes in the time-zone: these happen when DST turns on or + off and when authorities alter the offsets for the time-zone. + + \sa nextTransition(), previousTransition(), transitions() */ bool QTimeZone::hasTransitions() const -- cgit v1.2.3 From e8c7f77854c23b962cae1018feccc8842c92b954 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 4 Dec 2015 13:42:11 +0100 Subject: Doc: Online style: CSS fixes for image alignment - Remove duplicated rules - Add a rule for class centerAlign - Remove width restriction from paragraphs in table cells These fixes enable proper horizontal center-align of images in table cells. Change-Id: I68a4863fe642a552260dfd6dbbb5d9675a8d2b4d Reviewed-by: Venugopal Shivashankar --- doc/global/template/style/online.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css index c7758d0ca8..be278a27da 100644 --- a/doc/global/template/style/online.css +++ b/doc/global/template/style/online.css @@ -1258,15 +1258,15 @@ li a.active { color:#404244; line-height:1.16em } -.mainContent table p { - margin:0px; - padding:0px -} .mainContent table p { margin:0px; padding:0px; + max-width:initial; min-height:2em } +.mainContent table p.centerAlign { + text-align:center +} .context h2 { font-size:2.1875em } -- cgit v1.2.3 From b8922c35ba9090b0d030baca4f38c5f468440098 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 2 Dec 2015 23:17:57 +0100 Subject: Register QPA Menu, Dialog & SysTray enums & flags This allows QML Menu, Dialog & SystemTrayIcon to use the same enums without having to duplicate them. Change-Id: I1401583d3ae2ef07cdc795d2765fba07c9b30f2f Reviewed-by: Friedemann Kleint Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Frederik Gladhorn --- src/gui/kernel/qplatformdialoghelper.h | 17 +++++++++++++++++ src/gui/kernel/qplatformmenu.h | 2 ++ src/gui/kernel/qplatformsystemtrayicon.h | 2 ++ 3 files changed, 21 insertions(+) diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 936dbdfa89..5b2f4ece77 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -104,6 +104,7 @@ public: }; Q_DECLARE_FLAGS(StandardButtons, StandardButton) + Q_FLAG(StandardButtons) enum ButtonRole { // keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole @@ -128,6 +129,7 @@ public: Reverse = 0x40000000, EOL = InvalidRole }; + Q_ENUM(ButtonRole) enum ButtonLayout { // keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout @@ -167,6 +169,7 @@ QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QColorDialogOptions { + Q_GADGET public: enum ColorDialogOption { ShowAlphaChannel = 0x00000001, @@ -175,6 +178,7 @@ public: }; Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption) + Q_FLAG(ColorDialogOptions) QColorDialogOptions(); QColorDialogOptions(const QColorDialogOptions &rhs); @@ -226,6 +230,7 @@ private: class Q_GUI_EXPORT QFontDialogOptions { + Q_GADGET public: enum FontDialogOption { NoButtons = 0x00000001, @@ -237,6 +242,7 @@ public: }; Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption) + Q_FLAG(FontDialogOptions) QFontDialogOptions(); QFontDialogOptions(const QFontDialogOptions &rhs); @@ -279,11 +285,19 @@ private: class Q_GUI_EXPORT QFileDialogOptions { + Q_GADGET public: enum ViewMode { Detail, List }; + Q_ENUM(ViewMode) + enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly }; + Q_ENUM(FileMode) + enum AcceptMode { AcceptOpen, AcceptSave }; + Q_ENUM(AcceptMode) + enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount }; + Q_ENUM(DialogLabel) enum FileDialogOption { @@ -297,6 +311,7 @@ public: DontUseCustomDirectoryIcons = 0x00000080 }; Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption) + Q_FLAG(FileDialogOptions) QFileDialogOptions(); QFileDialogOptions(const QFileDialogOptions &rhs); @@ -396,9 +411,11 @@ private: class Q_GUI_EXPORT QMessageDialogOptions { + Q_GADGET public: // Keep in sync with QMessageBox::Icon enum Icon { NoIcon, Information, Warning, Critical, Question }; + Q_ENUM(Icon) QMessageDialogOptions(); QMessageDialogOptions(const QMessageDialogOptions &rhs); diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index 1022d0ed4a..bc0b3a4870 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -63,6 +63,7 @@ public: // They could be added as public QAction roles if necessary. CutRole, CopyRole, PasteRole, SelectAllRole, RoleCount }; + Q_ENUM(MenuRole) virtual void setTag(quintptr tag) = 0; virtual quintptr tag()const = 0; @@ -91,6 +92,7 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject Q_OBJECT public: enum MenuType { DefaultMenu = 0, EditMenu }; + Q_ENUM(MenuType) virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0; virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0; diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h index 437f5e02b1..6ef2d1538f 100644 --- a/src/gui/kernel/qplatformsystemtrayicon.h +++ b/src/gui/kernel/qplatformsystemtrayicon.h @@ -57,8 +57,10 @@ public: Trigger, MiddleClick }; + Q_ENUM(ActivationReason) enum MessageIcon { NoIcon, Information, Warning, Critical }; + Q_ENUM(MessageIcon) QPlatformSystemTrayIcon(); ~QPlatformSystemTrayIcon(); -- cgit v1.2.3 From 784167fb517157d611d4084a96e0d7bd79cb2f46 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 30 Nov 2015 05:38:10 +0400 Subject: Fix swapped descriptions for [-no]-optimized-tools Change-Id: I5953b83ec2b4adee953caea0cb1e39d54b78bebb Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 9422b9fe07..4e2f54afe1 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1819,8 +1819,8 @@ bool Configure::displayHelp() desc("BUILDDEV", "yes", "-developer-build", "Compile and link Qt with Qt developer options (including auto-tests exporting)\n"); - desc("RELEASE_TOOLS", "yes", "-optimized-tools", "Do not build optimized host tools even in debug build."); - desc("RELEASE_TOOLS", "no", "-no-optimized-tools", "Build optimized host tools even in debug build.\n"); + desc("RELEASE_TOOLS", "yes", "-optimized-tools", "Build optimized host tools even in debug build."); + desc("RELEASE_TOOLS", "no", "-no-optimized-tools", "Do not build optimized host tools even in debug build.\n"); desc("OPENSOURCE", "opensource", "-opensource", "Compile and link the Open-Source Edition of Qt."); desc("COMMERCIAL", "commercial", "-commercial", "Compile and link the Commercial Edition of Qt.\n"); -- cgit v1.2.3 From 8e07227f82696c27c4b201df62c7f3705d63cfe5 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 1 Dec 2015 00:05:04 +0400 Subject: configureapp: Add missing empty line between paragraphs Change-Id: I0f6424471d64976a6c93876e18da3c77000d6390 Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 4e2f54afe1..03a9d73ecf 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1971,7 +1971,7 @@ bool Configure::displayHelp() desc("FREETYPE", "no", "-no-freetype", "Do not compile in Freetype2 support."); desc("FREETYPE", "yes", "-qt-freetype", "Use the libfreetype bundled with Qt."); - desc("FREETYPE", "system","-system-freetype", "Use the libfreetype provided by the system."); + desc("FREETYPE", "system","-system-freetype", "Use the libfreetype provided by the system.\n"); desc("HARFBUZZ", "no", "-no-harfbuzz", "Do not compile in HarfBuzz-NG support."); desc("HARFBUZZ", "qt", "-qt-harfbuzz", "Use HarfBuzz-NG bundled with Qt to do text shaping.\n" -- cgit v1.2.3 From c79396fc4a896cb6a2f6b784e0a73b557c2c5396 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 1 Dec 2015 00:06:25 +0400 Subject: configureapp: Print FontConfig in "Third Party Libraries" section ...just like in config.summary Change-Id: Idb34cdd39f706d7a7e75dfc0388d0a1fdb1f2317 Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 03a9d73ecf..160ccf5778 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1923,9 +1923,6 @@ bool Configure::displayHelp() desc("LARGE_FILE", "yes", "-largefile", "Enables Qt to access files larger than 4 GB.\n"); - desc("FONT_CONFIG", "yes", "-fontconfig", "Build with FontConfig support."); - desc("FONT_CONFIG", "no", "-no-fontconfig", "Do not build with FontConfig support.\n"); - desc("POSIX_IPC", "yes", "-posix-ipc", "Enable POSIX IPC.\n"); desc("QT_GLIB", "yes", "-glib", "Compile Glib support.\n"); @@ -1973,6 +1970,9 @@ bool Configure::displayHelp() desc("FREETYPE", "yes", "-qt-freetype", "Use the libfreetype bundled with Qt."); desc("FREETYPE", "system","-system-freetype", "Use the libfreetype provided by the system.\n"); + desc("FONT_CONFIG", "yes", "-fontconfig", "Build with FontConfig support."); + desc("FONT_CONFIG", "no", "-no-fontconfig", "Do not build with FontConfig support.\n"); + desc("HARFBUZZ", "no", "-no-harfbuzz", "Do not compile in HarfBuzz-NG support."); desc("HARFBUZZ", "qt", "-qt-harfbuzz", "Use HarfBuzz-NG bundled with Qt to do text shaping.\n" "It can still be disabled by setting\n" -- cgit v1.2.3 From f0c75bb050badf69e5e24bc44a2b2de601b11069 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 3 Dec 2015 08:13:46 +0100 Subject: QPlatformTheme: added TabButtonFont and GroupBoxTitleFont Which is needed by Qt Labs Controls. Change-Id: I2f91a1cbe8218170f894189b56f3fef77207eaec Reviewed-by: J-P Nurmi --- src/gui/kernel/qplatformtheme.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 69cc2f90af..36fa7a65aa 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -164,6 +164,8 @@ public: SmallFont, MiniFont, FixedFont, + GroupBoxTitleFont, + TabButtonFont, NFonts }; -- cgit v1.2.3 From 0d54b0f4ddb3ec3e14f39d954eb43b10100bbce9 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 10 Dec 2015 14:58:12 +0100 Subject: QFileSystemModel: do not unwatch directories if removal fails ... otherwise we would not detect subsequent file/directories added into the non-removed one. Change-Id: I43018dfb9a9c6c0399190800da3f0d572ec5d8d8 Task-number: QTBUG-49307 Reviewed-by: David Faure --- src/widgets/dialogs/qfilesystemmodel.cpp | 20 ++++++++------ .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 31 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 5dd8c05734..995d0c7700 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -198,13 +198,14 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const bool QFileSystemModel::remove(const QModelIndex &aindex) { const QString path = filePath(aindex); + const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively(); #ifndef QT_NO_FILESYSTEMWATCHER - QFileSystemModelPrivate * d = const_cast(d_func()); - d->fileInfoGatherer.removePath(path); + if (success) { + QFileSystemModelPrivate * d = const_cast(d_func()); + d->fileInfoGatherer.removePath(path); + } #endif - if (QFileInfo(path).isFile()) - return QFile::remove(path); - return QDir(path).removeRecursively(); + return success; } /*! @@ -1607,11 +1608,14 @@ bool QFileSystemModel::event(QEvent *event) bool QFileSystemModel::rmdir(const QModelIndex &aindex) { QString path = filePath(aindex); + const bool success = QDir().rmdir(path); #ifndef QT_NO_FILESYSTEMWATCHER - QFileSystemModelPrivate * d = const_cast(d_func()); - d->fileInfoGatherer.removePath(path); + if (success) { + QFileSystemModelPrivate * d = const_cast(d_func()); + d->fileInfoGatherer.removePath(path); + } #endif - return QDir().rmdir(path); + return success; } /*! diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 3252650d12..996d919591 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -123,6 +123,8 @@ private slots: void permissions_data(); void permissions(); + void doNotUnwatchOnFailedRmdir(); + protected: bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList()); @@ -1043,6 +1045,35 @@ void tst_QFileSystemModel::permissions() // checks QTBUG-20503 QCOMPARE(fileInfoPermissions, modelPermissions); } +void tst_QFileSystemModel::doNotUnwatchOnFailedRmdir() +{ + const QString tmp = flatDirTestPath; + + QFileSystemModel model; + + const QTemporaryDir tempDir(tmp + '/' + QStringLiteral("doNotUnwatchOnFailedRmdir-XXXXXX")); + QVERIFY(tempDir.isValid()); + + const QModelIndex rootIndex = model.setRootPath(tempDir.path()); + + // create a file in the directory so to prevent it from deletion + { + QFile file(tempDir.path() + '/' + QStringLiteral("file1")); + QVERIFY(file.open(QIODevice::WriteOnly)); + } + + QCOMPARE(model.rmdir(rootIndex), false); + + // create another file + { + QFile file(tempDir.path() + '/' + QStringLiteral("file2")); + QVERIFY(file.open(QIODevice::WriteOnly)); + } + + // the model must now detect this second file + QTRY_COMPARE(model.rowCount(rootIndex), 2); +} + QTEST_MAIN(tst_QFileSystemModel) #include "tst_qfilesystemmodel.moc" -- cgit v1.2.3 From 40c927e7331ea4ac9ca50de48560b700e657cded Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 8 Dec 2015 18:28:24 +0100 Subject: XCB: prevent a fp division by zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For certain devices vci->resolution is zero, which causes a SIGFPE if FE_INVALID exceptions are enabled. Try to prevent that. Task-number: QTBUG-42717 Change-Id: I388735f5dfb6218496787dbb74cf0c0f43cc928f Reviewed-by: Alexander Volkov Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 8097cce709..1a123703a5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) #endif // XCB_USE_XINPUT22 case XIValuatorClass: { XIValuatorClassInfo *vci = reinterpret_cast(classinfo); + // Some devices (mice) report a resolution of 0; they will be excluded later, + // for now just prevent a division by zero + const int vciResolution = vci->resolution ? vci->resolution : 1; if (vci->label == atom(QXcbAtom::AbsMTPositionX)) caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition; else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) @@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) caps |= QTouchDevice::Pressure; else if (vci->label == atom(QXcbAtom::RelX)) { hasRelativeCoords = true; - dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution); + dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution); } else if (vci->label == atom(QXcbAtom::RelY)) { hasRelativeCoords = true; - dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution); + dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution); } else if (vci->label == atom(QXcbAtom::AbsX)) { caps |= QTouchDevice::Position; - dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution); + dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution); } else if (vci->label == atom(QXcbAtom::AbsY)) { caps |= QTouchDevice::Position; - dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution); + dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution); } break; } -- cgit v1.2.3 From 56f6252e7285c9c61a99416fa2a8571fd67c597f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 1 Dec 2015 16:27:09 +0100 Subject: xcb: compare to previous state when sending geometry and expose events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By calculating the previous geometry and passing it on when calling handleGeometryChange we can detect cases where setGeometry() on a QWindow didn't result in the expected geometry. The new (actual) geometry is delivered as a resize event. This also allows us to only send expose events when the size of the window has actually changed (instead of also sending when the window has just moved). Due to the async delivery of geometry changes on the xcb platform we need to avoid using QWindowPrivate's cached state of the geometry, as that will result in duplicate resize events when events are not flushed in between two system resize events coming in with the same size. Change-Id: I3d4abe4a1095dd96e6e354288d5b646c623c30dd Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/xcb/qxcbwindow.cpp | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6023ee6b29..98bcc62d4c 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2007,21 +2007,42 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } } - const QRect rect = QRect(pos, QSize(event->width, event->height)); - QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect); + // The original geometry requested by setGeometry() might be different + // from what we end up with after applying window constraints. + QRect requestedGeometry = geometry(); + + const QRect actualGeometry = QRect(pos, QSize(event->width, event->height)); + QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry); QXcbScreen *currentScreen = m_xcbScreen; m_xcbScreen = static_cast(newScreen); if (!newScreen) return; - QPlatformWindow::setGeometry(rect); - QWindowSystemInterface::handleGeometryChange(window(), rect); + // Persist the actual geometry so that QWindow::geometry() can + // be queried in the resize event. + QPlatformWindow::setGeometry(actualGeometry); + + // As we're delivering the geometry change through QPA in n async fashion we can't + // pass on the current geometry of the QWindowPrivate, as that may have not been + // updated yet by a geometry change that's still in the QPA event queue. Instead + // we fall back to the default argument value of QRect(), which will result in + // QGuiApplication looking up the previous geometry from QWindowPrivate, but this + // time in sync with the even delivery/processing. + QWindowSystemInterface::handleGeometryChange(window(), actualGeometry, + requestedGeometry != actualGeometry ? requestedGeometry : QRect()); + if (newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - if (m_mapped) - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + // For expose events we have no way of telling QGuiApplication to used the locally + // cached version of the previous state, so we may in some situations end up with + // an additional expose event. + QRect previousGeometry = requestedGeometry != actualGeometry ? + requestedGeometry : qt_window_private(window())->geometry; + + if (m_mapped && actualGeometry.size() != previousGeometry.size()) + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size())); if (m_usingSyncProtocol && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; -- cgit v1.2.3 From 824af4aac959d95402d70fb235433aafb20d5c43 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 9 Dec 2015 23:16:22 +0100 Subject: QFileDialog test: make the right subwidget visible It makes little sense to give focus to a hidden widget; in order to make the treeview visible, we need to set the view mode to Detail. Change-Id: I453111e83593a790a656651b603a9c9b1a78dd9d Task-number: QTBUG-7690 Reviewed-by: Jan Blumschein Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Friedemann Kleint --- tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index b04711b282..b457558879 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -774,14 +774,16 @@ void tst_QFileDialog2::task233037_selectingDirectory() void tst_QFileDialog2::task235069_hideOnEscape_data() { QTest::addColumn("childName"); - QTest::newRow("listView") << QStringLiteral("listView"); - QTest::newRow("fileNameEdit") << QStringLiteral("fileNameEdit"); - QTest::newRow("treeView") << QStringLiteral("treeView"); + QTest::addColumn("viewMode"); + QTest::newRow("listView") << QStringLiteral("listView") << QFileDialog::List; + QTest::newRow("fileNameEdit") << QStringLiteral("fileNameEdit") << QFileDialog::List; + QTest::newRow("treeView") << QStringLiteral("treeView") << QFileDialog::Detail; } void tst_QFileDialog2::task235069_hideOnEscape() { QFETCH(QString, childName); + QFETCH(QFileDialog::ViewMode, viewMode); QDir current = QDir::currentPath(); QNonNativeFileDialog fd; @@ -789,7 +791,7 @@ void tst_QFileDialog2::task235069_hideOnEscape() QVERIFY(spyFinished.isValid()); QSignalSpy spyRejected(&fd, &QDialog::rejected); QVERIFY(spyRejected.isValid()); - fd.setViewMode(QFileDialog::List); + fd.setViewMode(viewMode); fd.setDirectory(current.absolutePath()); fd.setAcceptMode(QFileDialog::AcceptSave); fd.show(); -- cgit v1.2.3 From 2e8ff4ba1b7bff0b34d0492c5cb7758c445a6305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 10 Dec 2015 17:45:26 +0100 Subject: Fix broken QIOSContext setup due to missing 0-initialization of EAGLContext Change-Id: Ia4dbb2e3b055a7899c4a3e02698c5776ea7f73ea Reviewed-by: Mike Krus Reviewed-by: Laszlo Agocs --- src/plugins/platforms/ios/qioscontext.mm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index cc42b6057e..8bdb4bcdb3 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -45,14 +45,15 @@ QIOSContext::QIOSContext(QOpenGLContext *context) : QPlatformOpenGLContext() , m_sharedContext(static_cast(context->shareHandle())) + , m_eaglContext(0) , m_format(context->format()) { m_format.setRenderableType(QSurfaceFormat::OpenGLES); + EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil; - for (int version = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3; - version >= m_format.majorVersion() && !m_eaglContext; --version) { + const int preferredVersion = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3; + for (int version = preferredVersion; !m_eaglContext && version >= m_format.majorVersion(); --version) m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup]; - } if (m_eaglContext != nil) { EAGLContext *originalContext = [EAGLContext currentContext]; -- cgit v1.2.3 From 4a318a61824216ac499ff8b0b0c55dea90501005 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 10 Dec 2015 23:52:07 +0100 Subject: QJsonObject::(const_)iterator: add pointer typedef Otherwise they're unusable with std::algorithms or anything else that requires iterator_traits. Change-Id: Ia29c1e7c1778844e37d43eaa8aef2871afe3c991 Reviewed-by: Thiago Macieira --- src/corelib/json/qjsonobject.cpp | 10 ++++++++++ src/corelib/json/qjsonobject.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index b7dfe88434..c225606717 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -693,6 +693,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const \internal */ +/*! \typedef QJsonObject::iterator::pointer + + \internal +*/ + /*! \fn QJsonObject::iterator::iterator() Constructs an uninitialized iterator. @@ -895,6 +900,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const \internal */ +/*! \typedef QJsonObject::const_iterator::pointer + + \internal +*/ + /*! \fn QJsonObject::const_iterator::const_iterator() Constructs an uninitialized iterator. diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h index 19c938fd83..5b475f52ae 100644 --- a/src/corelib/json/qjsonobject.h +++ b/src/corelib/json/qjsonobject.h @@ -104,6 +104,7 @@ public: typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValueRef reference; + typedef QJsonValuePtr pointer; Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {} Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {} @@ -146,6 +147,7 @@ public: typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValue reference; + typedef QJsonValuePtr pointer; Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {} Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index) -- cgit v1.2.3 From 604ef6d4a7108d6c5632a1c85d0f248249f6dbe5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 Nov 2015 13:09:26 +0100 Subject: automatically put TESTDATA into RESOURCES on android/ios/winrt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QFINDTESTDATA is already prepared to find it there. Change-Id: I467392786ce6bcfbf1bd0b6079f60c9df06834b1 Reviewed-by: Tor Arne Vestbø Reviewed-by: Oliver Wolff Reviewed-by: Maurice Kalinowski --- mkspecs/features/qt_build_config.prf | 3 +++ mkspecs/features/testcase.prf | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf index 7197f84c9a..eaf23cf63a 100644 --- a/mkspecs/features/qt_build_config.prf +++ b/mkspecs/features/qt_build_config.prf @@ -55,6 +55,9 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR cross_compile: \ CONFIG += force_bootstrap +android|ios|winrt: \ + CONFIG += builtin_testdata + CONFIG += \ create_prl link_prl \ prepare_docs qt_docs_targets \ diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index 6f6f073f70..6bac0546c3 100644 --- a/mkspecs/features/testcase.prf +++ b/mkspecs/features/testcase.prf @@ -79,7 +79,7 @@ isEmpty(BUILDS)|build_pass { INSTALLS += target } -contains(INSTALLS, target) { +!builtin_testdata:contains(INSTALLS, target) { # Install testdata and helpers as well, but only if we're actually installing the test. # # Testdata is installed relative to the directory containing the testcase @@ -180,6 +180,20 @@ contains(INSTALLS, target) { } } +builtin_testdata { + ALL_TESTDATA = $$TESTDATA $$GENERATED_TESTDATA + # RESOURCES does not support wildcards (for good reasons) + for(td, ALL_TESTDATA): \ + testdata.files += $$files($$absolute_path($$td, $$_PRO_FILE_PWD_)) + !isEmpty(testdata.files) { + testdata.base = $$_PRO_FILE_PWD_ + RESOURCES += testdata + } + + !isEmpty(TEST_HELPER_INSTALLS): \ + error("This platform does not support tests which require helpers.") +} + macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) { QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle -- cgit v1.2.3 From cf6d671a11bc77da9d9898a3c7d419b184501b44 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Dec 2015 13:34:58 +0100 Subject: winrt: Use Windows 10 features when available OpenFileMappingFromApp has been added for Windows 10. Using it, QSharedMemory autotests succeed without any failure. Change-Id: I5a4fbec004f121f41909ae13f3db02c384810645 Reviewed-by: Andrew Knight --- src/corelib/kernel/qsharedmemory_win.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index 5cc54b1def..ac4ef39e8f 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -101,7 +101,11 @@ HANDLE QSharedMemoryPrivate::handle() Q_UNIMPLEMENTED(); hand = 0; #elif defined(Q_OS_WINRT) +#if _MSC_VER >= 1900 + hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast(nativeKey.utf16())); +#else hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, (PCWSTR)nativeKey.utf16()); +#endif #elif defined(Q_OS_WINCE) // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. -- cgit v1.2.3 From b6503d17955520fc4d4c598993ffe8a94b7fa20f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 9 Dec 2015 10:50:40 +0100 Subject: QWidgetBackingStore::markDirty(): Clamp dirty region to window size. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Graphics effects may exceed the window size, causing platform backing store operations to fail (see QWidgetPrivate::effectiveRectFor()). Task-number: QTBUG-49785 Change-Id: Iff16da599397d19acb86010fe7023f3ce15b6d6f Reviewed-by: Morten Johan Sørvig --- src/widgets/kernel/qwidgetbackingstore.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 17187002ca..3f7f9291b6 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -641,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); - const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint()))); + QRect translatedRect = widgetRect; + if (widget != tlw) + translatedRect.translate(widget->mapTo(tlw, QPoint())); + // Graphics effects may exceed window size, clamp. + translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size())); if (qt_region_strictContains(dirty, translatedRect)) { if (updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); -- cgit v1.2.3 From fda85b6d570702950e85d343745606c35ee02961 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 11 Dec 2015 13:30:57 +0100 Subject: winrt: Readd parameters to the pid-file's CreateFile2 call Recent changes to the main file accidently removed the parameter from the call. Change-Id: I4cce48327d43d9ea3fe4fd82c2f5768aa4bc6d5c Reviewed-by: Andrew Knight --- src/winmain/qtmain_winrt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 5d2abcccc7..080f1637f1 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -260,7 +260,7 @@ private: FILE_ATTRIBUTE_NORMAL }; pidFile = CreateFile2(reinterpret_cast(pidFileName.utf16()), - GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, 0); + GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, ¶ms); // Install the develMode message handler #ifndef Q_OS_WINPHONE defaultMessageHandler = qInstallMessageHandler(devMessageHandler); -- cgit v1.2.3 From 8fd05e6289a3190a9e1e5056ecff2a0e02aac2c2 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 18 Nov 2015 14:29:19 +0100 Subject: Don't ignore first character after a string. The parser in QMakeSourceFileInfo::findDeps() would step over the closing quote of a string, only to have a for loop then step over the character just after that closing quote, which was thus never studied; this could lead to problems in various ways. Fixed that and expanded findDeps() test to catch regressions. Task-number: QTBUG-17533 Change-Id: I7dec5222e38fa188495b39376ffee70bc7bbc87f Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 11 ++++------- tests/auto/tools/qmake/testdata/findDeps/main.cpp | 3 +++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index b939a9c9d4..43f368f0be 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -584,17 +584,14 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) // buffer[x] is '"' } else { const char term = buffer[x]; - while (++x < buffer_len) { - if (buffer[x] == term) { + while (++x < buffer_len && buffer[x] != term) { + if (buffer[x] == '\\') ++x; - break; - } else if (buffer[x] == '\\') { - ++x; - } else if (qmake_endOfLine(buffer[x])) { + else if (qmake_endOfLine(buffer[x])) ++line_count; - } } } + // for loop's ++x shall step over the closing quote. } beginning = 0; } diff --git a/tests/auto/tools/qmake/testdata/findDeps/main.cpp b/tests/auto/tools/qmake/testdata/findDeps/main.cpp index 0df3f9b7c3..d5dd5b81d3 100644 --- a/tests/auto/tools/qmake/testdata/findDeps/main.cpp +++ b/tests/auto/tools/qmake/testdata/findDeps/main.cpp @@ -35,6 +35,9 @@ / #include "needed.cpp" // if not ignored, symbol needed() won't be available ... +// Check we're not confused by string juxtaposition: +static const char text[] = "lorem ""ipsum /*"; + #include /**/ #include /**//**/ #include -- cgit v1.2.3 From 0c33a823c560bdf18a513ae460eea4d7bdf9e115 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 24 Nov 2015 15:09:41 +0300 Subject: xcb: Don't cache the screen for a window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QXcbWindow::m_xcbScreen was introduced in 4e1b09fa8ff1a9ab42c0a29a2efe1ae7f4700d71 (Keep screen geometries from overlapping) to map the window geometry for the right screen, because it wasn't possible to rely on QPlatformWindow::screen(). But we don't need it since a705b4ec1f6f7133390054f8b6b8077ef0550311 (Introduce cross platform high-dpi scaling), because QGuiApplication triggers GeometryChangeEvent right after processing WindowScreenChangedEvent. So just use QPlatformWindow::screen() instead of cached m_xcbScreen. m_xcbScreen was also used in d4bc56cb4218f6f8378f04c23865156b349b037d (Fix screen detection on configureNotify) to compare the new screen after receiving ConfigureNotify to the correct old screen. Just send WindowScreenChangedEvent event and leave making the comparison to QGuiApplication. Change-Id: Ibe717ae4bf4c40b0a04cd62fe2ecaee5df5f4060 Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 16 ++++++---------- src/plugins/platforms/xcb/qxcbwindow.h | 2 -- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 98bcc62d4c..6add0a6333 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0; QXcbScreen *QXcbWindow::parentScreen() { - return parent() ? static_cast(parent())->parentScreen() : m_xcbScreen; + return parent() ? static_cast(parent())->parentScreen() : xcbScreen(); } // Returns \c true if we should set WM_TRANSIENT_FOR on \a w @@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) , m_window(0) - , m_xcbScreen(0) , m_syncCounter(0) , m_gravity(XCB_GRAVITY_STATIC) , m_mapped(false) @@ -322,7 +321,6 @@ void QXcbWindow::create() QRect rect = windowGeometry(); QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast(screenForGeometry(rect)); - m_xcbScreen = platformScreen; if (type == Qt::Desktop) { m_window = platformScreen->root(); m_depth = platformScreen->screen()->root_depth; @@ -638,13 +636,12 @@ void QXcbWindow::setGeometry(const QRect &rect) propagateSizeHints(); - QXcbScreen *currentScreen = m_xcbScreen; + QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *newScreen = parent() ? parentScreen() : static_cast(screenForGeometry(rect)); if (!newScreen) newScreen = xcbScreen(); - m_xcbScreen = newScreen; const QRect wmGeometry = windowToWmGeometry(rect); if (newScreen && newScreen != currentScreen) @@ -2013,9 +2010,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * const QRect actualGeometry = QRect(pos, QSize(event->width, event->height)); QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry); - - QXcbScreen *currentScreen = m_xcbScreen; - m_xcbScreen = static_cast(newScreen); if (!newScreen) return; @@ -2032,8 +2026,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QWindowSystemInterface::handleGeometryChange(window(), actualGeometry, requestedGeometry != actualGeometry ? requestedGeometry : QRect()); - if (newScreen != currentScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + // QPlatformScreen::screen() is updated asynchronously, so we can't compare it + // with the newScreen. Just send the WindowScreenChanged event and QGuiApplication + // will make the comparison later. + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); // For expose events we have no way of telling QGuiApplication to used the locally // cached version of the previous state, so we may in some situations end up with diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 43e66a774d..0d146730e5 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -214,8 +214,6 @@ protected: xcb_window_t m_window; - QXcbScreen *m_xcbScreen; - uint m_depth; QImage::Format m_imageFormat; bool m_imageRgbSwap; -- cgit v1.2.3 From a094af001795c9651b299d700a992150d1aba33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Fri, 16 Oct 2015 22:51:59 +0200 Subject: xcb: Use a placeholder QScreen when there are no outputs connected If no screens are available, windows could disappear, could stop rendering graphics, or the application could crash. This is a real use case in several scenarios: with x11vnc, when all monitors are physically disconnected from a desktop machine, or in some cases even when the monitor sleeps. Now when the last screen is disconnected, it is transformed into a fake screen. When a physical screen appears, the fake QScreen is transformed into a representation of the physical screen. Every virtual desktop has its own fake screen, and primary screens must belong to the primary virtual desktop. It fixes updating screen geometry on temporarily disabled screens in the middle of the mode switch. Expected results: Windows don't disappear, the application doesn't crash, and QMenu is displayed on the appropriate screen. This reverts patch 51ada7734ad780178ecced11e0dff454dfc2e5f2 Change-Id: I6e8eb682b0c8425d08ffdaecbd4c6c7700c914b4 Task-number: QTBUG-42985 Reviewed-by: Shawn Rutledge --- src/gui/kernel/qscreen.cpp | 4 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 273 +++++++++++++++------------ src/plugins/platforms/xcb/qxcbconnection.h | 10 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 49 +++-- src/plugins/platforms/xcb/qxcbscreen.h | 10 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 38 +--- src/plugins/platforms/xcb/qxcbwindow.h | 1 - 7 files changed, 212 insertions(+), 173 deletions(-) diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index fb322ae74f..52e7686439 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -116,8 +116,8 @@ QScreen::~QScreen() bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle()); // Move any leftover windows to the primary screen - foreach (QWindow *window, QGuiApplication::topLevelWindows()) { - if (window->screen() != this) + foreach (QWindow *window, QGuiApplication::allWindows()) { + if (!window->isTopLevel() || window->screen() != this) continue; const bool wasVisible = window->isVisible(); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 50d49ca798..231fe9af3f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran return 0; } -QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop, - xcb_randr_output_t outputId, - xcb_randr_get_output_info_reply_t *output) -{ - QString name; - if (output) - name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), - xcb_randr_get_output_info_name_length(output)); - else { - QByteArray displayName = m_displayName; - int dotPos = displayName.lastIndexOf('.'); - if (dotPos != -1) - displayName.truncate(dotPos); - name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number()); - } - - return new QXcbScreen(this, virtualDesktop, outputId, output, name); -} - -bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) -{ - xcb_generic_error_t *error = 0; - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), rootWindow); - QScopedPointer primary ( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { - qWarning("failed to get the primary output of the screen"); - free(error); - error = NULL; - } - const bool isPrimary = primary ? (primary->output == output) : false; - - return isPrimary; -} - QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow) { foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) { @@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) // Not for us return; - qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc; QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc); + qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc + << "mode" << crtc.mode << "relevant screen" << screen; // Only update geometry when there's a valid mode on the CRTC // CRTC with node mode could mean that output has been disabled, and we'll // get RRNotifyOutputChange notification for that. @@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) { qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected"; - - // Known screen removed -> delete it - m_screens.removeOne(screen); - virtualDesktop->removeScreen(screen); - - QXcbIntegration::instance()->destroyScreen(screen); - - // QTBUG-40174, QTBUG-42985: If all screens are removed, wait - // and start rendering again later if a screen becomes available. - + destroyScreen(screen); } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { // New XRandR output is available and it's enabled if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { @@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) QScopedPointer outputInfo( xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); - screen = createScreen(virtualDesktop, output.output, outputInfo.data()); - qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; - - screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); - virtualDesktop->addScreen(screen); - m_screens << screen; - QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); + // Find a fake screen + foreach (QPlatformScreen *scr, virtualDesktop->screens()) { + QXcbScreen *xcbScreen = (QXcbScreen *)scr; + if (xcbScreen->output() == XCB_NONE) { + screen = xcbScreen; + break; + } + } - // Windows which had null screens have already had expose events by now. - // They need to be told the screen is back, it's OK to render. - foreach (QWindow *window, QGuiApplication::topLevelWindows()) { - QXcbWindow *xcbWin = static_cast(window->handle()); - if (xcbWin) - xcbWin->maybeSetScreen(screen); + if (screen) { + QString nameWas = screen->name(); + // Transform the fake screen into a physical screen + screen->setOutput(output.output, outputInfo.data()); + updateScreen(screen, output); + qCDebug(lcQpaScreen) << "output" << screen->name() + << "is connected and enabled; was fake:" << nameWas; + } else { + screen = createScreen(virtualDesktop, output, outputInfo.data()); + qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; } } - // else ignore disabled screens } else if (screen) { - // Screen has been disabled -> remove if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { + // Screen has been disabled xcb_randr_get_output_info_cookie_t outputInfoCookie = xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); QScopedPointer outputInfo( xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); if (outputInfo->crtc == XCB_NONE) { qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; - m_screens.removeOne(screen); - virtualDesktop->removeScreen(screen); - QXcbIntegration::instance()->destroyScreen(screen); + destroyScreen(screen); } else { qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch"; + // Reset crtc to skip RRCrtcChangeNotify events, + // because they may be invalid in the middle of the mode switch + screen->setCrtc(XCB_NONE); } } else { - // Just update existing screen - screen->updateGeometry(output.config_timestamp); - const bool wasPrimary = screen->isPrimary(); - screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); - if (screen->mode() != output.mode) - screen->updateRefreshRate(output.mode); - - // If the screen became primary, reshuffle the order in QGuiApplicationPrivate - if (!wasPrimary && screen->isPrimary()) { - const int idx = m_screens.indexOf(screen); - m_screens.swap(0, idx); - QXcbIntegration::instance()->setPrimaryScreen(screen); - } + updateScreen(screen, output); qCDebug(lcQpaScreen) << "output has changed" << screen; } } + + qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); + } +} + +bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) +{ + xcb_generic_error_t *error = 0; + xcb_randr_get_output_primary_cookie_t primaryCookie = + xcb_randr_get_output_primary(xcb_connection(), rootWindow); + QScopedPointer primary ( + xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); + if (!primary || error) { + qWarning("failed to get the primary output of the screen"); + free(error); + error = NULL; + } + const bool isPrimary = primary ? (primary->output == output) : false; + + return isPrimary; +} + +void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange) +{ + screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid + screen->updateGeometry(outputChange.config_timestamp); + if (screen->mode() != outputChange.mode) + screen->updateRefreshRate(outputChange.mode); + // Only screen which belongs to the primary virtual desktop can be a primary screen + if (screen->screenNumber() == m_primaryScreenNumber) { + if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) { + screen->setPrimary(true); + + // If the screen became primary, reshuffle the order in QGuiApplicationPrivate + const int idx = m_screens.indexOf(screen); + if (idx > 0) { + m_screens.first()->setPrimary(false); + m_screens.swap(0, idx); + } + screen->virtualDesktop()->setPrimaryScreen(screen); + QXcbIntegration::instance()->setPrimaryScreen(screen); + } + } +} + +QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop, + const xcb_randr_output_change_t &outputChange, + xcb_randr_get_output_info_reply_t *outputInfo) +{ + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo); + // Only screen which belongs to the primary virtual desktop can be a primary screen + if (screen->screenNumber() == m_primaryScreenNumber) + screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output)); + + if (screen->isPrimary()) { if (!m_screens.isEmpty()) - qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); - else - qCDebug(lcQpaScreen) << "no outputs"; + m_screens.first()->setPrimary(false); + + m_screens.prepend(screen); + } else { + m_screens.append(screen); + } + virtualDesktop->addScreen(screen); + QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); + + return screen; +} + +void QXcbConnection::destroyScreen(QXcbScreen *screen) +{ + QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop(); + if (virtualDesktop->screens().count() == 1) { + // If there are no other screens on the same virtual desktop, + // then transform the physical screen into a fake screen. + const QString nameWas = screen->name(); + screen->setOutput(XCB_NONE, Q_NULLPTR); + qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen; + } else { + // There is more than one screen on the same virtual desktop, remove the screen + m_screens.removeOne(screen); + virtualDesktop->removeScreen(screen); + + // When primary screen is removed, set the new primary screen + // which belongs to the primary virtual desktop. + if (screen->isPrimary()) { + QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0); + newPrimary->setPrimary(true); + const int idx = m_screens.indexOf(newPrimary); + if (idx > 0) + m_screens.swap(0, idx); + QXcbIntegration::instance()->setPrimaryScreen(newPrimary); + } + + QXcbIntegration::instance()->destroyScreen(screen); } } @@ -338,8 +377,7 @@ void QXcbConnection::initializeScreens() { xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int xcbScreenNumber = 0; // screen number in the xcb sense - QXcbScreen* primaryScreen = Q_NULLPTR; - bool hasOutputs = false; + QXcbScreen *primaryScreen = Q_NULLPTR; while (it.rem) { // Each "screen" in xcb terminology is a virtual desktop, // potentially a collection of separate juxtaposed monitors. @@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens() xcb_screen_t *xcbScreen = it.data; QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber); m_virtualDesktops.append(virtualDesktop); - QList siblings; - int outputCount = 0; if (has_randr_extension) { xcb_generic_error_t *error = NULL; // RRGetScreenResourcesCurrent is fast but it may return nothing if the @@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens() } else { xcb_timestamp_t timestamp; xcb_randr_output_t *outputs = Q_NULLPTR; - outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data()); + int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data()); if (outputCount) { timestamp = resources_current->config_timestamp; outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data()); @@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens() qWarning("failed to get the primary output of the screen"); free(error); } else { + QList siblings; for (int i = 0; i < outputCount; i++) { QScopedPointer output( xcb_randr_get_output_info_reply(xcb_connection(), @@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens() continue; } - QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data()); + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data()); siblings << screen; - hasOutputs = true; m_screens << screen; // There can be multiple outputs per screen, use either @@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens() } } } + virtualDesktop->setScreens(siblings); } } } } - virtualDesktop->setScreens(siblings); + if (virtualDesktop->screens().isEmpty()) { + // If there are no XRandR outputs or XRandR extension is missing, + // then create a fake/legacy screen. + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR); + qCDebug(lcQpaScreen) << "created fake screen" << screen; + m_screens << screen; + if (m_primaryScreenNumber == xcbScreenNumber) { + primaryScreen = screen; + primaryScreen->setPrimary(true); + } + virtualDesktop->addScreen(screen); + } xcb_screen_next(&it); ++xcbScreenNumber; } // for each xcb screen @@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens() foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) virtualDesktop->subscribeToXFixesSelectionNotify(); - // If there's no randr extension, or there was some error above, or we found a - // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X), - // but the dimensions are known anyway, and we don't already have any lingering - // (possibly disconnected) screens, then showing windows should be possible, - // so create one screen. (QTBUG-31389) - QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0); - if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) { - QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR); - virtualDesktop->setScreens(QList() << screen); - m_screens << screen; - primaryScreen = screen; - primaryScreen->setPrimary(true); - qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen; - } - - // Ensure the primary screen is first in the list - if (primaryScreen) { - Q_ASSERT(!m_screens.isEmpty()); - if (m_screens.first() != primaryScreen) { - m_screens.removeOne(primaryScreen); - m_screens.prepend(primaryScreen); + if (m_virtualDesktops.isEmpty()) { + qFatal("QXcbConnection: no screens available"); + } else { + // Ensure the primary screen is first on the list + if (primaryScreen) { + if (m_screens.first() != primaryScreen) { + m_screens.removeOne(primaryScreen); + m_screens.prepend(primaryScreen); + } } - } - // Push the screens to QApplication - QXcbIntegration *integration = QXcbIntegration::instance(); - foreach (QXcbScreen* screen, m_screens) { - qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')'; - integration->screenAdded(screen, screen->isPrimary()); - } + // Push the screens to QGuiApplication + foreach (QXcbScreen *screen, m_screens) { + qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")"; + QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); + } - if (!m_screens.isEmpty()) qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); + } } QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName) @@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeXFixes(); initializeScreens(); - if (m_screens.isEmpty()) - qFatal("QXcbConnection: no screens available"); - initializeXRender(); m_xi2Enabled = false; #if defined(XCB_USE_XINPUT2) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 3c82170679..fb7cc137b9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -518,15 +518,17 @@ private: void initializeXShape(); void initializeXKB(); void handleClientMessageEvent(const xcb_client_message_event_t *event); - QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop, - xcb_randr_output_t outputId = XCB_NONE, - xcb_randr_get_output_info_reply_t *output = 0); QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc); QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output); QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow); + void updateScreens(const xcb_randr_notify_event_t *event); bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output); + void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange); + QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop, + const xcb_randr_output_change_t &outputChange, + xcb_randr_get_output_info_reply_t *outputInfo); + void destroyScreen(QXcbScreen *screen); void initializeScreens(); - void updateScreens(const xcb_randr_notify_event_t *event); bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const; bool m_xi2Enabled; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 0e99d58679..f05432ef68 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s) ((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s); } +void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s) +{ + const int idx = m_screens.indexOf(s); + Q_ASSERT(idx > -1); + m_screens.swap(0, idx); +} + QXcbXSettings *QXcbVirtualDesktop::xSettings() const { if (!m_xSettings) { @@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea() } QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, - xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, - QString outputName) + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output) : QXcbObject(connection) , m_virtualDesktop(virtualDesktop) , m_output(outputId) - , m_crtc(output ? output->crtc : 0) + , m_crtc(output ? output->crtc : XCB_NONE) , m_mode(XCB_NONE) , m_primary(false) , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) - , m_outputName(outputName) + , m_outputName(getOutputName(output)) , m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize()) , m_virtualSize(virtualDesktop->size()) , m_virtualSizeMillimeters(virtualDesktop->physicalSize()) @@ -268,6 +274,22 @@ QXcbScreen::~QXcbScreen() delete m_cursor; } +QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo) +{ + QString name; + if (outputInfo) { + name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo), + xcb_randr_get_output_info_name_length(outputInfo)); + } else { + QByteArray displayName = connection()->displayName(); + int dotPos = displayName.lastIndexOf('.'); + if (dotPos != -1) + displayName.truncate(dotPos); + name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + + QString::number(m_virtualDesktop->number()); + } + return name; +} QWindow *QXcbScreen::topLevelAt(const QPoint &p) const { @@ -392,6 +414,16 @@ QPlatformCursor *QXcbScreen::cursor() const return m_cursor; } +void QXcbScreen::setOutput(xcb_randr_output_t outputId, + xcb_randr_get_output_info_reply_t *outputInfo) +{ + m_output = outputId; + m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE; + m_mode = XCB_NONE; + m_outputName = getOutputName(outputInfo); + // TODO: Send an event to the QScreen instance that the screen changed its name +} + /*! \brief handle the XCB screen change event and update properties @@ -460,19 +492,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan updateGeometry(change_event->timestamp); - QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation); QDpi ldpi = logicalDpi(); QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second); - - // Windows which had null screens have already had expose events by now. - // They need to be told the screen is back, it's OK to render. - foreach (QWindow *window, QGuiApplication::topLevelWindows()) { - QXcbWindow *xcbWin = static_cast(window->handle()); - if (xcbWin) - xcbWin->maybeSetScreen(this); - } } void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index c68c290791..79620f40ec 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -72,6 +72,7 @@ public: void setScreens(QList sl) { m_screens = sl; } void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); } void addScreen(QPlatformScreen *s); + void setPrimaryScreen(QPlatformScreen *s); QXcbXSettings *xSettings() const; @@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen { public: QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, - xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, - QString outputName); + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo); ~QXcbScreen(); + QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo); + QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; @@ -137,6 +139,10 @@ public: xcb_randr_crtc_t crtc() const { return m_crtc; } xcb_randr_mode_t mode() const { return m_mode; } + void setOutput(xcb_randr_output_t outputId, + xcb_randr_get_output_info_reply_t *outputInfo); + void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; } + void windowShown(QXcbWindow *window); QString windowManagerName() const { return m_windowManagerName; } bool syncRequestSupported() const { return m_syncRequestSupported; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6add0a6333..bdbb9e9fe0 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -622,14 +622,6 @@ void QXcbWindow::destroy() m_pendingSyncRequest->invalidate(); } -void QXcbWindow::maybeSetScreen(QXcbScreen *screen) -{ - if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) { - QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast(screen)->screen()); - QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size()))); - } -} - void QXcbWindow::setGeometry(const QRect &rect) { QPlatformWindow::setGeometry(rect); @@ -845,15 +837,13 @@ void QXcbWindow::hide() Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); // send synthetic UnmapNotify event according to icccm 4.1.4 - if (xcbScreen()) { - xcb_unmap_notify_event_t event; - event.response_type = XCB_UNMAP_NOTIFY; - event.event = xcbScreen()->root(); - event.window = m_window; - event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); - } + xcb_unmap_notify_event_t event; + event.response_type = XCB_UNMAP_NOTIFY; + event.event = xcbScreen()->root(); + event.window = m_window; + event.from_configure = false; + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); xcb_flush(xcb_connection()); @@ -1181,8 +1171,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.data.data32[3] = 0; event.data.data32[4] = 0; - if (!xcbScreen()) - return; Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); } @@ -1435,8 +1423,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) xcb_parent_id = qXcbParent->xcb_window(); m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow; } else { - if (!xcbScreen()) - return; xcb_parent_id = xcbScreen()->root(); m_embedded = false; } @@ -1992,7 +1978,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * { bool fromSendEvent = (event->response_type & 0x80); QPoint pos(event->x, event->y); - if (!parent() && !fromSendEvent && xcbScreen()) { + if (!parent() && !fromSendEvent) { // Do not trust the position, query it instead. xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(), 0, 0); @@ -2305,8 +2291,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) return; const QPoint local(event->event_x, event->event_y); - if (!xcbScreen()) - return; QPoint global = QPoint(event->root_x, event->root_y); QWindowSystemInterface::handleEnterEvent(window(), local, global); } @@ -2324,8 +2308,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event) if (enterWindow) { QPoint local(enter->event_x, enter->event_y); - if (!xcbScreen()) - return; QPoint global = QPoint(event->root_x, event->root_y); QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); @@ -2341,8 +2323,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev connection()->setTime(event->time); const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; - if (!xcbScreen()) - return; if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { if (propertyDeleted) @@ -2662,8 +2642,6 @@ bool QXcbWindow::needsSync() const void QXcbWindow::postSyncWindowRequest() { - if (!xcbScreen()) - return; if (!m_pendingSyncRequest) { QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); m_pendingSyncRequest = e; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 0d146730e5..69c0819959 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -167,7 +167,6 @@ public: virtual void create(); virtual void destroy(); - void maybeSetScreen(QXcbScreen *screen); QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const; public Q_SLOTS: -- cgit v1.2.3 From d729c3459f4472874c8fb53eb2d6039fd503a7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 9 Dec 2015 15:28:05 +0100 Subject: iOS: Enable non-pixman NEON drawhelpers for both 32 and 64-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pixman drawhelpers are implemented using GAS syntax, which the Clang assembler doesn't handle, nor do they work on 64-bit ARM, so we disable them selectively. They are only used for 16-bit surfaces anyways, so it not a big deal on iOS. (cherry picked from commit 49568df95450733dc4c273945e5ced218132c123) Change-Id: I70848981c794739d40a6a2d9a537307bc80d61a6 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Tor Arne Vestbø --- src/3rdparty/pixman/pixman-arm-neon-asm.S | 4 ++++ src/gui/painting/painting.pri | 10 ++++------ src/gui/painting/qdrawhelper_neon.cpp | 10 +++++----- src/gui/painting/qdrawhelper_neon_asm.S | 4 ++++ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/3rdparty/pixman/pixman-arm-neon-asm.S b/src/3rdparty/pixman/pixman-arm-neon-asm.S index eb8cc4c966..bd9371eadb 100644 --- a/src/3rdparty/pixman/pixman-arm-neon-asm.S +++ b/src/3rdparty/pixman/pixman-arm-neon-asm.S @@ -34,6 +34,8 @@ * - pixman_composite_over_n_8_0565_asm_neon */ +#if defined(ENABLE_PIXMAN_DRAWHELPERS) + /* Prevent the stack from becoming executable for no reason... */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits @@ -1707,3 +1709,5 @@ generate_composite_function \ 0, /* dst_r_basereg */ \ 0, /* src_basereg */ \ 0 /* mask_basereg */ + +#endif \ No newline at end of file diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 5b25c2fd95..1e516e4581 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -101,12 +101,10 @@ SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \ painting/qimagescale_sse4.cpp AVX2_SOURCES += painting/qdrawhelper_avx2.cpp -!ios { - CONFIG += no_clang_integrated_as - NEON_SOURCES += painting/qdrawhelper_neon.cpp - NEON_HEADERS += painting/qdrawhelper_neon_p.h - !contains(QT_ARCH, "arm64"): NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S -} +NEON_SOURCES += painting/qdrawhelper_neon.cpp +NEON_HEADERS += painting/qdrawhelper_neon_p.h +NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S +!ios:!contains(QT_ARCH, "arm64"): DEFINES += ENABLE_PIXMAN_DRAWHELPERS MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 413fddcfdc..e3f5d5bac7 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -135,7 +135,7 @@ static inline uint16x8_t qvsource_over_u16(uint16x8_t src16, uint16x8_t dst16, u return vaddq_u16(src16, qvbyte_mul_u16(dst16, alpha16, half)); } -#if !defined(Q_PROCESSOR_ARM_64) +#if defined(ENABLE_PIXMAN_DRAWHELPERS) extern "C" void pixman_composite_over_8888_0565_asm_neon (int32_t w, int32_t h, @@ -352,7 +352,7 @@ void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl, void qt_blend_argb32_on_argb32_scanline_neon(uint *dest, const uint *src, int length, uint const_alpha) { if (const_alpha == 255) { -#if !defined(Q_PROCESSOR_ARM_64) +#if defined(ENABLE_PIXMAN_DRAWHELPERS) pixman_composite_scanline_over_asm_neon(length, dest, src); #else qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, 256); @@ -372,7 +372,7 @@ void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl, uint16x8_t half = vdupq_n_u16(0x80); uint16x8_t full = vdupq_n_u16(0xff); if (const_alpha == 256) { -#if !defined(Q_PROCESSOR_ARM_64) +#if defined(ENABLE_PIXMAN_DRAWHELPERS) pixman_composite_over_8888_8888_asm_neon(w, h, (uint32_t *)destPixels, dbpl / 4, (uint32_t *)srcPixels, sbpl / 4); #else for (int y=0; y Date: Thu, 10 Dec 2015 18:42:42 +0100 Subject: QLineEdit: a validator fixup() should keep it modified; add failing test I still have no idea how to fix this properly given the absolute mess of QWidgetLineControl. For now add a failing test. Change-Id: Ieb5ad6994c8ce7deb0cd0f2f47d51073d042244e Task-number: QTBUG-49295 Reviewed-by: Marc Mutz --- .../widgets/widgets/qlineedit/tst_qlineedit.cpp | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 666960d98e..b46609c371 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -229,6 +229,7 @@ private slots: void isModified(); void edited(); + void fixupDoesNotModify_QTBUG_49295(); void insert(); void setSelection_data(); @@ -2844,6 +2845,29 @@ void tst_QLineEdit::edited() QVERIFY(testWidget->isModified()); } +void tst_QLineEdit::fixupDoesNotModify_QTBUG_49295() +{ + QLineEdit *testWidget = ensureTestWidget(); + + ValidatorWithFixup val; + testWidget->setValidator(&val); + testWidget->setText("foo"); + QVERIFY(!testWidget->isModified()); + QVERIFY(!testWidget->hasAcceptableInput()); + + QTest::keyClicks(testWidget, QStringLiteral("bar")); + QVERIFY(testWidget->isModified()); + QVERIFY(!testWidget->hasAcceptableInput()); + + // trigger a fixup, which should not reset the modified flag + QFocusEvent lostFocus(QEvent::FocusOut); + qApp->sendEvent(testWidget, &lostFocus); + + QVERIFY(testWidget->hasAcceptableInput()); + QEXPECT_FAIL("", "QTBUG-49295: a fixup of a line edit should keep it modified", Continue); + QVERIFY(testWidget->isModified()); +} + void tst_QLineEdit::insert() { QLineEdit *testWidget = ensureTestWidget(); -- cgit v1.2.3 From fa9008566c163f95d99c3551beb4335f28461289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 10 Dec 2015 17:59:04 +0100 Subject: Remove iOS workaround for pixman drawhelpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I8636993571b04d8cda74708777ba3ef2bac09fb5 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qdrawhelper.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 8f5eb4d095..bf7a50e227 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -32,11 +32,6 @@ ****************************************************************************/ #include -#ifdef Q_OS_IOS -// We don't build the NEON drawhelpers as they are implemented partly -// in GAS syntax assembly, which is not supported by the iOS toolchain. -#undef __ARM_NEON__ -#endif #include #include @@ -6425,7 +6420,7 @@ static void qInitDrawhelperFunctions() #endif // SSE2 -#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) +#if defined(__ARM_NEON__) qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; @@ -6446,7 +6441,7 @@ static void qInitDrawhelperFunctions() qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon; -#if !defined(Q_PROCESSOR_ARM_64) +#if defined(ENABLE_PIXMAN_DRAWHELPERS) // The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64 qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon; -- cgit v1.2.3 From 69efc425b2cb0ed81a5ec0b6c4c498fdfdefca51 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 10 Dec 2015 19:38:18 +0100 Subject: QFileSystemModel autotest: fix a broken sort() test The test was comparing an "unsorted" file listing read from disk with a reference listing, checking whether the two were different. Obviously that's a nonsense test, as there's no stable order for the entries returned by readdir_r and friends. Change-Id: I1d781a6513c42bb0b585d02e57a771c5336c7df4 Reviewed-by: Marc Mutz --- .../dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 996d919591..8c8872e807 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -822,18 +822,21 @@ void tst_QFileSystemModel::sort() QModelIndex parent = myModel->index(dirPath, 0); QList expectedOrder; expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + ".." << dirPath + QChar('/') + "."; - //File dialog Mode means sub trees are not sorted, only the current root + if (fileDialogMode) { - // FIXME: we were only able to disableRecursiveSort in developer builds, so we can only - // stably perform this test for developer builds -#ifdef QT_BUILD_INTERNAL - QList actualRows; + // File dialog Mode means sub trees are not sorted, only the current root. + // There's no way we can check that the sub tree is "not sorted"; just check if it + // has the same contents of the expected list + QList actualRows; for(int i = 0; i < myModel->rowCount(parent); ++i) { actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(); } - QVERIFY(actualRows != expectedOrder); -#endif + + std::sort(expectedOrder.begin(), expectedOrder.end()); + std::sort(actualRows.begin(), actualRows.end()); + + QCOMPARE(actualRows, expectedOrder); } else { for(int i = 0; i < myModel->rowCount(parent); ++i) { -- cgit v1.2.3 From be9df4bc82b3f62854906761b7661bc2778b513e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Dec 2015 16:33:20 +0100 Subject: QWindowsBackingStore::flush(): Add warning for UpdateLayeredWindowIndirect() failures. Task-number: QTBUG-49785 Change-Id: I881e6d294ae6b23e280e727ee1fc48ee6562f2fe Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsbackingstore.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index bd5c35037d..135c9eb601 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty}; - QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info); + const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info); + if (!result) + qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d)," + " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(), + r.width(), r.height(), dirtyRect.width(), dirtyRect.height(), + dirtyRect.x(), dirtyRect.y()); } else { QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA); } -- cgit v1.2.3 From 3b093034b638a69b4dc91212d1743638864a1337 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 10 Dec 2015 20:29:24 +0100 Subject: QFileSystemModel: report special files which are not symlinks Since special files have file size == -1, they were always filtered out by QFileSystemModel, even when passing QDir::System as filtering option. Keep them instead. The testcase is more convoluted than it should be because QFSM is so broken that it returns valid indexes for invisible elements in the model (such as filtered out elements). Change-Id: I023a9813dbfeed7be99dded42c66b1191afdc17e Task-number: QTBUG-20968 Reviewed-by: Marc Mutz --- src/widgets/dialogs/qfilesystemmodel.cpp | 4 -- .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 44 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 995d0c7700..d23737f130 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -1791,10 +1791,6 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV node->fileName = fileName; } - if (info.size() == -1 && !info.isSymLink()) { - removeNode(parentNode, fileName); - continue; - } if (*node != info ) { node->populate(info); bypassFilters.remove(node); diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 8c8872e807..d370a647b4 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -124,6 +124,7 @@ private slots: void permissions(); void doNotUnwatchOnFailedRmdir(); + void specialFiles(); protected: bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList()); @@ -1077,6 +1078,49 @@ void tst_QFileSystemModel::doNotUnwatchOnFailedRmdir() QTRY_COMPARE(model.rowCount(rootIndex), 2); } +static QSet fileListUnderIndex(const QFileSystemModel *model, const QModelIndex &parent) +{ + QSet fileNames; + const int rowCount = model->rowCount(parent); + for (int i = 0; i < rowCount; ++i) + fileNames.insert(model->index(i, 0, parent).data(QFileSystemModel::FileNameRole).toString()); + return fileNames; +} + +void tst_QFileSystemModel::specialFiles() +{ + QFileSystemModel model; + + model.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); + + // Can't simply verify if the model returns a valid model index for a special file + // as it will always return a valid index for existing files, + // even if the file is not visible with the given filter. + +#if defined(Q_OS_UNIX) + const QModelIndex rootIndex = model.setRootPath(QStringLiteral("/dev/")); + const QString testFileName = QStringLiteral("null"); +#elif defined(Q_OS_WIN) + const QModelIndex rootIndex = model.setRootPath(flatDirTestPath); + + const QString testFileName = QStringLiteral("linkSource.lnk"); + + QFile file(flatDirTestPath + QLatin1String("/linkTarget.txt")); + QVERIFY(file.open(QIODevice::WriteOnly)); + file.close(); + QVERIFY(file.link(flatDirTestPath + '/' + testFileName)); +#else + QSKIP("Not implemented"); + QModelIndex rootIndex; + QString testFileName; +#endif + + QTRY_VERIFY(fileListUnderIndex(&model, rootIndex).contains(testFileName)); + + model.setFilter(QDir::AllEntries | QDir::Hidden); + + QTRY_VERIFY(!fileListUnderIndex(&model, rootIndex).contains(testFileName)); +} QTEST_MAIN(tst_QFileSystemModel) #include "tst_qfilesystemmodel.moc" -- cgit v1.2.3 From fd527592b7156b7b0d352faa2557924ad13e4095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Sun, 13 Dec 2015 13:53:31 +0000 Subject: Don't detach the color table vector Change-Id: Iec7814b0aca74ddc9744af358561b18b96d7a266 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Marc Mutz --- src/gui/painting/qpaintengine_raster.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 6b8136c52d..207e31d91a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3653,8 +3653,9 @@ QImage::Format QRasterBuffer::prepare(QImage *image) drawHelper = qDrawHelper + format; if (image->depth() == 1 && image->colorTable().size() == 2) { monoDestinationWithClut = true; - destColor0 = qPremultiply(image->colorTable()[0]); - destColor1 = qPremultiply(image->colorTable()[1]); + const QVector colorTable = image->colorTable(); + destColor0 = qPremultiply(colorTable[0]); + destColor1 = qPremultiply(colorTable[1]); } return format; -- cgit v1.2.3 From acdd57cb4329724004a0beee8cdfca99d26d9f6c Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 8 Dec 2015 14:22:19 +0100 Subject: Fix compilation for WinRT TEST_HELPER_INSTALLS cannot be used on platforms with no QProcess support. Change-Id: I2a6a283d94ca4487fc628449c53fc37140dd291d Reviewed-by: Oliver Wolff --- tests/auto/corelib/global/qlogging/qlogging.pro | 6 +++--- tests/auto/corelib/global/qlogging/test/test.pro | 2 +- tests/auto/corelib/kernel/qobject/qobject.pro | 6 +++--- tests/auto/corelib/kernel/qobject/test/test.pro | 2 +- tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro | 4 +++- tests/auto/corelib/thread/qthreadstorage/test/test.pro | 2 +- tests/auto/corelib/tools/qlocale/qlocale.pro | 4 ++-- tests/auto/corelib/tools/qlocale/test/test.pro | 2 +- tests/auto/gui/kernel/qclipboard/qclipboard.pro | 2 +- tests/auto/gui/kernel/qclipboard/test/test.pro | 2 +- tests/auto/network/access/qnetworkreply/qnetworkreply.pro | 2 +- tests/auto/network/access/qnetworkreply/test/test.pro | 2 +- tests/auto/network/bearer/qnetworksession/qnetworksession.pro | 2 +- tests/auto/network/bearer/qnetworksession/test/test.pro | 2 +- tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp | 4 ++++ tests/auto/testlib/selftests/selftests.pro | 2 +- tests/auto/testlib/selftests/test/test.pro | 2 +- tests/auto/widgets/kernel/qapplication/qapplication.pro | 2 +- tests/auto/widgets/kernel/qapplication/test/test.pro | 9 ++++++--- 19 files changed, 34 insertions(+), 25 deletions(-) diff --git a/tests/auto/corelib/global/qlogging/qlogging.pro b/tests/auto/corelib/global/qlogging/qlogging.pro index 4d3823cdbe..f1ca6570a0 100644 --- a/tests/auto/corelib/global/qlogging/qlogging.pro +++ b/tests/auto/corelib/global/qlogging/qlogging.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS += \ - app \ - test +!winrt: SUBDIRS += app + +SUBDIRS += test diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro index fdebf45281..64a63ce28a 100644 --- a/tests/auto/corelib/global/qlogging/test/test.pro +++ b/tests/auto/corelib/global/qlogging/test/test.pro @@ -7,5 +7,5 @@ QT = core testlib SOURCES = ../tst_qlogging.cpp DEFINES += QT_MESSAGELOGCONTEXT -TEST_HELPER_INSTALLS = ../app/app +!winrt: TEST_HELPER_INSTALLS = ../app/app DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/kernel/qobject/qobject.pro b/tests/auto/corelib/kernel/qobject/qobject.pro index 6a7cf07f51..bd83396ca0 100644 --- a/tests/auto/corelib/kernel/qobject/qobject.pro +++ b/tests/auto/corelib/kernel/qobject/qobject.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS += \ - signalbug \ - test +!winrt: SUBDIRS+= signalbug + +SUBDIRS += test diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test/test.pro index 0a15ae384e..3ac728931d 100644 --- a/tests/auto/corelib/kernel/qobject/test/test.pro +++ b/tests/auto/corelib/kernel/qobject/test/test.pro @@ -4,5 +4,5 @@ TARGET = ../tst_qobject QT = core-private network testlib SOURCES = ../tst_qobject.cpp -TEST_HELPER_INSTALLS = ../signalbug/signalbug +!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro b/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro index 2fa973d2f7..e81038a4be 100644 --- a/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro +++ b/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro @@ -1,5 +1,7 @@ TEMPLATE = subdirs SUBDIRS = \ - crashonexit \ test + +!winrt: SUBDIRS += crashonexit + CONFIG += ordered parallel_test diff --git a/tests/auto/corelib/thread/qthreadstorage/test/test.pro b/tests/auto/corelib/thread/qthreadstorage/test/test.pro index 8b7caf1e24..d97d474e51 100644 --- a/tests/auto/corelib/thread/qthreadstorage/test/test.pro +++ b/tests/auto/corelib/thread/qthreadstorage/test/test.pro @@ -5,6 +5,6 @@ CONFIG += console QT = core testlib SOURCES = ../tst_qthreadstorage.cpp -TEST_HELPER_INSTALLS = ../crashonexit/crashonexit +!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qlocale/qlocale.pro b/tests/auto/corelib/tools/qlocale/qlocale.pro index abbe31d1ef..5161200260 100644 --- a/tests/auto/corelib/tools/qlocale/qlocale.pro +++ b/tests/auto/corelib/tools/qlocale/qlocale.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs -SUBDIRS += test \ - syslocaleapp +SUBDIRS += test +!winrt: SUBDIRS+=syslocaleapp diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/tools/qlocale/test/test.pro index df12d35a09..60afb29233 100644 --- a/tests/auto/corelib/tools/qlocale/test/test.pro +++ b/tests/auto/corelib/tools/qlocale/test/test.pro @@ -14,7 +14,7 @@ win32 { } } -TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp +!winrt: TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 blackberry:LIBS += -lpps diff --git a/tests/auto/gui/kernel/qclipboard/qclipboard.pro b/tests/auto/gui/kernel/qclipboard/qclipboard.pro index d97c58dea0..b9fd2080e7 100644 --- a/tests/auto/gui/kernel/qclipboard/qclipboard.pro +++ b/tests/auto/gui/kernel/qclipboard/qclipboard.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = copier paster +!winrt: SUBDIRS = copier paster test.depends += $$SUBDIRS SUBDIRS += test diff --git a/tests/auto/gui/kernel/qclipboard/test/test.pro b/tests/auto/gui/kernel/qclipboard/test/test.pro index 586404871f..f27c582de2 100644 --- a/tests/auto/gui/kernel/qclipboard/test/test.pro +++ b/tests/auto/gui/kernel/qclipboard/test/test.pro @@ -15,6 +15,6 @@ wince* { DEPLOYMENT += rsc reg_resource } -TEST_HELPER_INSTALLS = \ +!winrt: TEST_HELPER_INSTALLS = \ ../copier/copier \ ../paster/paster diff --git a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro index 7cb6fddbaf..bd10c77252 100644 --- a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro +++ b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -!wince: SUBDIRS += echo +!winrt:!wince: SUBDIRS += echo test.depends += $$SUBDIRS SUBDIRS += test diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro index b683f620df..772bb55990 100644 --- a/tests/auto/network/access/qnetworkreply/test/test.pro +++ b/tests/auto/network/access/qnetworkreply/test/test.pro @@ -13,4 +13,4 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \ contains(QT_CONFIG,xcb): CONFIG+=insignificant_test # unstable, QTBUG-21102 win32:CONFIG += insignificant_test # QTBUG-24226 -TEST_HELPER_INSTALLS = ../echo/echo +!winrt: TEST_HELPER_INSTALLS = ../echo/echo diff --git a/tests/auto/network/bearer/qnetworksession/qnetworksession.pro b/tests/auto/network/bearer/qnetworksession/qnetworksession.pro index f1cb47d14e..cd480fb73b 100644 --- a/tests/auto/network/bearer/qnetworksession/qnetworksession.pro +++ b/tests/auto/network/bearer/qnetworksession/qnetworksession.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = lackey +!winrt:SUBDIRS = lackey test.depends = $$SUBDIRS SUBDIRS += test diff --git a/tests/auto/network/bearer/qnetworksession/test/test.pro b/tests/auto/network/bearer/qnetworksession/test/test.pro index dd7618b4ad..c95baa2b81 100644 --- a/tests/auto/network/bearer/qnetworksession/test/test.pro +++ b/tests/auto/network/bearer/qnetworksession/test/test.pro @@ -15,4 +15,4 @@ CONFIG(debug_and_release) { DESTDIR = .. } -TEST_HELPER_INSTALLS = ../lackey/lackey +!winrt: TEST_HELPER_INSTALLS = ../lackey/lackey diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index c7d655af3d..257df13343 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -466,7 +466,9 @@ void tst_QSslSocket::constructing() QCOMPARE(socket.peerAddress(), QHostAddress()); QVERIFY(socket.peerName().isEmpty()); QCOMPARE(socket.peerPort(), quint16(0)); +#ifndef QT_NO_NETWORKPROXY QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy); +#endif QCOMPARE(socket.readBufferSize(), qint64(0)); QCOMPARE(socket.socketDescriptor(), (qintptr)-1); QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket); @@ -2187,6 +2189,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnected() void tst_QSslSocket::resetProxy() { +#ifndef QT_NO_NETWORKPROXY QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; @@ -2226,6 +2229,7 @@ void tst_QSslSocket::resetProxy() socket2.setProxy(goodProxy); socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString())); +#endif // QT_NO_NETWORKPROXY } void tst_QSslSocket::ignoreSslErrorsList_data() diff --git a/tests/auto/testlib/selftests/selftests.pro b/tests/auto/testlib/selftests/selftests.pro index 1d39e6a899..091f0dd5a1 100644 --- a/tests/auto/testlib/selftests/selftests.pro +++ b/tests/auto/testlib/selftests/selftests.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -include(selftests.pri) +!winrt: include(selftests.pri) SUBDIRS = $$SUBPROGRAMS test diff --git a/tests/auto/testlib/selftests/test/test.pro b/tests/auto/testlib/selftests/test/test.pro index 0a31810105..d94b45ce89 100644 --- a/tests/auto/testlib/selftests/test/test.pro +++ b/tests/auto/testlib/selftests/test/test.pro @@ -16,5 +16,5 @@ win32 { RESOURCES += ../selftests.qrc include(../selftests.pri) -for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}" +!winrt: for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}" diff --git a/tests/auto/widgets/kernel/qapplication/qapplication.pro b/tests/auto/widgets/kernel/qapplication/qapplication.pro index 5154c915cd..21bfb50aee 100644 --- a/tests/auto/widgets/kernel/qapplication/qapplication.pro +++ b/tests/auto/widgets/kernel/qapplication/qapplication.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -SUBDIRS = desktopsettingsaware modal +!winrt: SUBDIRS = desktopsettingsaware modal test.depends += $$SUBDIRS SUBDIRS += test diff --git a/tests/auto/widgets/kernel/qapplication/test/test.pro b/tests/auto/widgets/kernel/qapplication/test/test.pro index b617c228ac..908aa846c0 100644 --- a/tests/auto/widgets/kernel/qapplication/test/test.pro +++ b/tests/auto/widgets/kernel/qapplication/test/test.pro @@ -9,7 +9,10 @@ TARGET = ../tst_qapplication TESTDATA = ../test/test.pro ../tmp/README -SUBPROGRAMS = desktopsettingsaware modal -win32:!wince: SUBPROGRAMS += wincmdline +!winrt { + SUBPROGRAMS = desktopsettingsaware modal + win32:!wince: SUBPROGRAMS += wincmdline + + for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}" +} -for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}" -- cgit v1.2.3 From 127b9fa5b0d6dfdf666b1e6593b848ae33556020 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Fri, 11 Dec 2015 14:45:53 +0100 Subject: remove visual studio specific argument "-ServerName:" is only used for Visual Studio and causes bad side- effects when using QCommandLineParser. Change-Id: Ifef652bbb65df9279a39ae3c74ddbb563c87bd90 Reviewed-by: David Faure Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/winmain/qtmain_winrt.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 080f1637f1..098ae45dc8 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -243,6 +243,9 @@ private: } } + if (args.count() >= 2 && strncmp(args.at(1), "-ServerName:", 12) == 0) + args.remove(1); + bool develMode = false; bool debugWait = false; foreach (const char *arg, args) { -- cgit v1.2.3 From 7f92edb7ac55bc27de25a2274e2d2435d8aaab49 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Dec 2015 12:23:38 +0100 Subject: winrt: Avoid blocking for the first processEvents run When calling WaitForMultipleObjectsEx, do not use a timeout for the initial call. This saves around 10% of blocking invocations in the QEventLoop autotests. Change-Id: Ib24436ed11de1865e31f9ff0ddf6ce1bc5562f42 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index 58b87bd36b..df070dd1ae 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -201,14 +201,16 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherWinRT); + DWORD waitTime = 0; do { // Additional user events have to be handled before timer events, but the function may not // return yet. const bool userEventsSent = sendPostedEvents(flags); - emit aboutToBlock(); const QVector timerHandles = d->timerIdToHandle.values().toVector(); - DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE); + if (waitTime) + emit aboutToBlock(); + DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE); if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) { const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0); ResetEvent(handle); @@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) if (userEventsSent) return true; + + // We cannot wait infinitely like on other platforms, as + // WaitForMultipleObjectsEx might not return. + // For instance win32 uses MsgWaitForMultipleObjects to hook + // into the native event loop, while WinRT handles those + // via callbacks. + waitTime = 1; } while (flags & QEventLoop::WaitForMoreEvents); return false; } -- cgit v1.2.3 From 980fd570cd91114d323413e8ddc5313bdb454d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 14 Dec 2015 14:29:22 +0100 Subject: xcb: Don't try to detect cases where the WM restricts geometry changes This caused issues in upstream tests that didn't expect to have their geometry requests not being respected by the WM. Task-number: QTBUG-49912 Change-Id: Iec99f341d81488de6026f04c99dff45a0d3f8587 Reviewed-by: Simon Hausmann --- src/plugins/platforms/xcb/qxcbwindow.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index bdbb9e9fe0..bec167fec2 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2003,14 +2003,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * // be queried in the resize event. QPlatformWindow::setGeometry(actualGeometry); - // As we're delivering the geometry change through QPA in n async fashion we can't - // pass on the current geometry of the QWindowPrivate, as that may have not been - // updated yet by a geometry change that's still in the QPA event queue. Instead - // we fall back to the default argument value of QRect(), which will result in - // QGuiApplication looking up the previous geometry from QWindowPrivate, but this - // time in sync with the even delivery/processing. - QWindowSystemInterface::handleGeometryChange(window(), actualGeometry, - requestedGeometry != actualGeometry ? requestedGeometry : QRect()); + // FIXME: In the case of the requestedGeometry not matching the actualGeometry due + // to e.g. the window manager applying restrictions to the geometry, the application + // will never see a move/resize event if the actualGeometry is the same as the current + // geometry, and may think the requested geometry was fulfilled. + QWindowSystemInterface::handleGeometryChange(window(), actualGeometry); // QPlatformScreen::screen() is updated asynchronously, so we can't compare it // with the newScreen. Just send the WindowScreenChanged event and QGuiApplication -- cgit v1.2.3 From adb914f4b9b723099824fd51a09a9b30bed4ec6c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 11 Dec 2015 12:50:45 +0100 Subject: QtNetwork: Standardize error message about IPv6 addresses for nameservers. Add a const char * message with QDnsLookupRunnable's translation context and use that for untranslated warnings and errorString. Change-Id: I1b6c9fb259fb9ff824a0c3829b2c00c36aaecdfa Reviewed-by: Richard J. Moore --- src/network/kernel/qdnslookup.cpp | 3 +++ src/network/kernel/qdnslookup_p.h | 2 ++ src/network/kernel/qdnslookup_unix.cpp | 4 ++-- src/network/kernel/qdnslookup_win.cpp | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 150beb4d39..4a275f0700 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -148,6 +148,9 @@ static void qt_qdnsservicerecord_sort(QList &records) } } +const char *QDnsLookupPrivate::msgNoIpV6NameServerAdresses = + QT_TRANSLATE_NOOP("QDnsLookupRunnable", "IPv6 addresses for nameservers are currently not supported"); + /*! \class QDnsLookup \brief The QDnsLookup class represents a DNS lookup. diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 0ac37f6636..3c8c4d5824 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -89,6 +89,8 @@ public: void _q_lookupFinished(const QDnsLookupReply &reply); + static const char *msgNoIpV6NameServerAdresses; + bool isFinished; QString name; QDnsLookup::Type type; diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index a5e97c4a93..dc8ec5a300 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -166,9 +166,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN ns->sin6_addr.s6_addr[i] = ipv6Address[i]; } #else - qWarning("IPv6 addresses for nameservers is currently not supported"); + qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses); reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); + reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses); return; #endif } diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp index 4a6c631983..df0203bebb 100644 --- a/src/network/kernel/qdnslookup_win.cpp +++ b/src/network/kernel/qdnslookup_win.cpp @@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN // For supoprting IPv6 nameserver addresses, we'll need to switch // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6 // address in the nameserver list - qWarning("IPv6 addresses for nameservers are currently not supported"); + qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses); reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("IPv6 addresses for nameservers are currently not supported"); + reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses); return; } } -- cgit v1.2.3 From d47baa7236fb0c44e85c1247eedec444aefe428c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 9 Dec 2015 14:49:48 +0100 Subject: Revert "tests: fixed compilation of tst_qtextstream" This reverts commit 9a6a58a95af31816627550c573c1b2ac39fc404e, which was a work-around for a qmake bug, now fixed. Task-number: QTBUG-19393 Change-Id: Id467bb5907a88f03eac0e29a90f4ff7e97045423 Reviewed-by: Oswald Buddenhagen --- tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp index 6e58642eb6..3ab53848d8 100644 --- a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp @@ -2729,7 +2729,7 @@ void tst_QTextStream::readBomSeekBackReadBomAgain() QFile::remove("utf8bom"); QFile file("utf8bom"); QVERIFY(file.open(QFile::ReadWrite)); - file.write("\xef\xbb\xbf" "Andreas"); + file.write("\xef\xbb\xbf""Andreas"); file.seek(0); QCOMPARE(file.pos(), qint64(0)); -- cgit v1.2.3 From 214e271b93b9c9f4f52d2e56956cf5c8da9b4251 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 24 Nov 2015 14:45:52 +0100 Subject: Rewrote qmake's #include-detection to be more faithful to CPP. The C preprocessor allows backslash-newline anywhere and allows comments anywhere it allows space. Testing wilfully perverse applications of that revealed qmake's parsing of #include directives wasn't very robust. So rework to actually follow the rules and add those tests. Change-Id: If5cc7bfb65f9994e9ab9ed216dd1ee7285c63934 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 338 ++++++++++++++------- .../tools/qmake/testdata/findDeps/findDeps.pro | 5 +- tests/auto/tools/qmake/testdata/findDeps/main.cpp | 47 ++- tests/auto/tools/qmake/testdata/findDeps/objecta.h | 41 +++ tests/auto/tools/qmake/testdata/findDeps/objectf.h | 41 +++ tests/auto/tools/qmake/testdata/rawString/main.cpp | 3 +- 6 files changed, 362 insertions(+), 113 deletions(-) create mode 100644 tests/auto/tools/qmake/testdata/findDeps/objecta.h create mode 100644 tests/auto/tools/qmake/testdata/findDeps/objectf.h diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 43f368f0be..656acdc6ba 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -388,6 +388,40 @@ QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep) return QFileInfo(dep.real()); } +static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines) +{ + // Join physical lines to make logical lines, as in the C preprocessor + while (offset + 1 < buffer_len + && buffer[offset] == '\\' + && qmake_endOfLine(buffer[offset + 1])) { + offset += 2; + ++*lines; + if (offset < buffer_len + && buffer[offset - 1] == '\r' + && buffer[offset] == '\n') // CRLF + offset++; + } + return offset; +} + +static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start, + const char *needle, int needle_len, + int *matchlen, int *lines) +{ + int x = start; + for (int n = 0; n < needle_len && x < buffer_len; + n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) { + if (buffer[x] != needle[n]) + return false; + } + // That also skipped any remaining BSNLs immediately after the match. + + // Tell caller how long the match was: + *matchlen = x - start; + + return true; +} + bool QMakeSourceFileInfo::findDeps(SourceFile *file) { if(file->dep_checked || file->type == TYPE_UNKNOWN) @@ -426,6 +460,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) file->deps = new SourceDependChildren; int line_count = 1; + enum { + /* + States of C preprocessing (for TYPE_C only), after backslash-newline + elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989 + section 2.1.1.2's phase 4). We're about to study buffer[x] to decide + on which transition to do. + */ + AtStart, // start of logical line; a # may start a preprocessor directive + HadHash, // saw a # at start, looking for preprocessor keyword + WantName, // saw #include or #import, waiting for name + InCode // after directive, parsing non-#include directive or in actual code + } cpp_state = AtStart; for(int x = 0; x < buffer_len; ++x) { bool try_local = true; @@ -505,144 +551,232 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) ++line_count; } else if(file->type == QMakeSourceFileInfo::TYPE_QRC) { } else if(file->type == QMakeSourceFileInfo::TYPE_C) { - for(int beginning=1; x < buffer_len; ++x) { + // We've studied all buffer[i] for i < x + for (; x < buffer_len; ++x) { + // How to handle backslash-newline (BSNL) pairs: +#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count) + // Seek code or directive, skipping comments and space: for(; x < buffer_len; ++x) { + x = SKIP_BSNL(x); if (buffer[x] == ' ' || buffer[x] == '\t') { // keep going - } else if (buffer[x] == '/' && x + 1 < buffer_len && - (buffer[x + 1] == '/' || buffer[x + 1] == '*')) { - ++x; - if (buffer[x] == '/') { // C++-style comment - for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip - beginning = 1; - } else { // C-style comment + } else if (buffer[x] == '/') { + int extralines = 0; + int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines); + if (buffer[y] == '/') { // C++-style comment + line_count += extralines; + x = SKIP_BSNL(y + 1); + while (x < buffer_len && !qmake_endOfLine(buffer[x])) + x = SKIP_BSNL(x + 1); // skip + + cpp_state = AtStart; + ++line_count; + } else if (buffer[y] == '*') { // C-style comment + line_count += extralines; + x = y; while (++x < buffer_len) { + x = SKIP_BSNL(x); if (buffer[x] == '*') { - if (x + 1 < buffer_len && buffer[x + 1] == '/') { - ++x; // skip '*'; for loop skips '/'. + extralines = 0; + y = skipEscapedLineEnds(buffer, buffer_len, + x + 1, &extralines); + if (y < buffer_len && buffer[y] == '/') { + line_count += extralines; + x = y; // for loop shall step past this break; } } else if (qmake_endOfLine(buffer[x])) { ++line_count; } } + } else { + // buffer[x] is the division operator + break; } } else if (qmake_endOfLine(buffer[x])) { ++line_count; - beginning = 1; + cpp_state = AtStart; } else { + /* Drop out of phases 1, 2, 3, into phase 4 */ break; } } + // Phase 4 study of buffer[x]: if(x >= buffer_len) break; - // preprocessor directive - if (beginning && buffer[x] == '#') { - // Advance to start of preprocessing directive - while (++x < buffer_len - && (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip - - if (qmake_endOfLine(buffer[x])) { - ++line_count; - beginning = 1; - continue; + switch (cpp_state) { + case HadHash: + { + // Read keyword; buffer[x] starts first preprocessing token after # + const char *const keyword = buffer + x; + int clean = x; + while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') { + // skip over keyword, consolidating it if it contains BSNLs + // (see WantName's similar code consolidating inc, below) + if (clean < x) + buffer[clean++] = buffer[x]; + else + clean++; + + x = SKIP_BSNL(x + 1); } + const int keyword_len = buffer + clean - keyword; + x--; // Still need to study buffer[x] next time round for loop. + + cpp_state = + ((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C + || (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C + ? WantName : InCode; break; } - // quoted strings - if (buffer[x] == '\'' || buffer[x] == '"') { - // It might be a C++11 raw string. - bool israw = false; - if (buffer[x] == '"' && x > 0) { - int y = x; - while (--y > 0 && (buffer[y] == '8' || buffer[y] == 'u' || buffer[y] == 'U')) {} // skip - israw = (buffer[y] == 'R'); - } - if (israw) { - x++; - const char *const delim = buffer + x; - while (x < buffer_len && buffer[x] != '(') - x++; + case WantName: + { + char term = buffer[x]; + if (term == '<') { + try_local = false; + term = '>'; + } else if (term != '"') { /* - Not checking correctness (trust real compiler to do that): - - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; - - at most 16 bytes in delim - */ - - const int delimlen = buffer + x - delim; - while (++x < buffer_len - && (buffer[x] != ')' - || (delimlen > 0 && - strncmp(buffer + x + 1, delim, delimlen)) - || buffer[x + 1 + delimlen] != '"')) {} // skip - // buffer[x] is ')' - x += 1 + delimlen; // 1 for ')', then delim - // buffer[x] is '"' - } else { - const char term = buffer[x]; - while (++x < buffer_len && buffer[x] != term) { - if (buffer[x] == '\\') - ++x; - else if (qmake_endOfLine(buffer[x])) - ++line_count; + Possibly malformed, but this may be something like: + #include IDENTIFIER + which does work, if #define IDENTIFIER "filename" is + in effect. This is beyond this noddy preprocessor's + powers of tracking. So give up and resume searching + for a directive. We haven't made sense of buffer[x], + so back up to ensure we do study it (now as code) next + time round the loop. + */ + x--; + cpp_state = InCode; + continue; + } + + x = SKIP_BSNL(x + 1); + inc = buffer + x; + int clean = x; // offset if we need to clear \-newlines + for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) { + if (qmake_endOfLine(buffer[x])) { // malformed + cpp_state = AtStart; + ++line_count; + break; } + + /* + If we do skip any BSNLs, we need to consolidate the + surviving text by copying to lower indices. For that + to be possible, we also have to keep 'clean' advanced + in step with x even when we've yet to see any BSNLs. + */ + if (clean < x) + buffer[clean++] = buffer[x]; + else + clean++; } - // for loop's ++x shall step over the closing quote. - } - beginning = 0; - } - if(x >= buffer_len) - break; + if (cpp_state == WantName) + buffer[clean] = '\0'; + else // i.e. malformed + inc = 0; - // Got a preprocessor directive - const char *const keyword = buffer + x; - for (; - x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z'; - x++) {} // skip over identifier - int keyword_len = buffer + x - keyword; - for (; - x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t'); - x++) {} // skip spaces after keyword - - /* Keyword with nothing after it, e.g. #endif: not interesting. */ - if (qmake_endOfLine(buffer[x])) - keyword_len = 0; - - if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C - || (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C - char term = buffer[x]; - if(term == '<') { - try_local = false; - term = '>'; - } else if(term != '"') { //wtf? - continue; + cpp_state = InCode; // hereafter + break; } - x++; - inc = buffer + x; - for (; - buffer[x] != term && !qmake_endOfLine(buffer[x]); - ++x) {} // skip until end of include name - buffer[x] = '\0'; - } else if (buffer[x] == '\'' || buffer[x] == '"') { - const char term = buffer[x++]; - while(x < buffer_len) { - if (buffer[x] == term) + + case AtStart: + // Preprocessor directive? + if (buffer[x] == '#') { + cpp_state = HadHash; break; - if (buffer[x] == '\\') { - x+=2; - } else { - if (qmake_endOfLine(buffer[x])) - ++line_count; - ++x; } + cpp_state = InCode; + // ... and fall through to handle buffer[x] as such. + case InCode: + // matching quotes (string literals and character literals) + if (buffer[x] == '\'' || buffer[x] == '"') { + // It might be a C++11 raw string. + bool israw = false; + if (buffer[x] == '"' && x > 0) { + int y = x - 1; + while (y > 0 && buffer[y] != 'R') { + if (buffer[y] == '8' || buffer[y] == 'u' || buffer[y] == 'U') + y--; + else if (y > 1 && qmake_endOfLine(buffer[y]) + && buffer[y - 1] == '\\') + y -= 2; + else if (y > 2 && buffer[y] == '\n' + && buffer[y - 1] == '\r' + && buffer[y - 2] == '\\') + y -= 3; + else + break; + } + israw = (buffer[y] == 'R'); + } + if (israw) { + x = SKIP_BSNL(x + 1); + const char *const delim = buffer + x; + int clean = x; + while (x < buffer_len && buffer[x] != '(') { + if (clean < x) + buffer[clean++] = buffer[x]; + else + clean++; + + x = SKIP_BSNL(x + 1); + } + /* + Not checking correctness (trust real compiler to do that): + - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; + - at most 16 bytes in delim + + Raw strings are surely defined after phase 2, when + BSNLs are resolved; so the delimiter's exclusion + of '\\' and space (including newlines) applies too + late to save us the need to cope with BSNLs in it. + */ + + const int delimlen = buffer + clean - delim; + int matchlen = delimlen, extralines = 0; + while ((x = SKIP_BSNL(x + 1)) < buffer_len + && (buffer[x] != ')' + || (delimlen > 0 && + !matchWhileUnsplitting(buffer, buffer_len, + x + 1, delim, delimlen, + &matchlen, &extralines)) + || buffer[x + 1 + matchlen] != '"')) { + // skip, but keep track of lines + if (qmake_endOfLine(buffer[x])) + ++line_count; + extralines = 0; + } + line_count += extralines; // from the match + // buffer[x] is ')' + x += 1 + matchlen; // 1 for ')', then delim + // buffer[x] is '"' + } else { + const char term = buffer[x]; + while (++x < buffer_len && buffer[x] != term) { + if (buffer[x] == '\\') + ++x; + else if (qmake_endOfLine(buffer[x])) + ++line_count; + } + } + // for loop's ++x shall step over the closing quote. + } + // else: buffer[x] is just some code; move on. + break; } - } else { - --x; + + if (inc) // We were in WantName and found a name. + break; +#undef SKIP_BSNL } + if(x >= buffer_len) + break; } if(inc) { diff --git a/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro b/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro index 2713296f5b..afb3f65297 100644 --- a/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro +++ b/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro @@ -1,4 +1,5 @@ DESTDIR = ./ +gcc: QMAKE_CXXFLAGS += -Wno-comment HEADERS += object1.h \ object2.h \ @@ -8,5 +9,7 @@ HEADERS += object1.h \ object6.h \ object7.h \ object8.h \ - object9.h + object9.h \ + objecta.h \ + objectf.h SOURCES += main.cpp needed.cpp diff --git a/tests/auto/tools/qmake/testdata/findDeps/main.cpp b/tests/auto/tools/qmake/testdata/findDeps/main.cpp index d5dd5b81d3..3f4f5def3c 100644 --- a/tests/auto/tools/qmake/testdata/findDeps/main.cpp +++ b/tests/auto/tools/qmake/testdata/findDeps/main.cpp @@ -39,23 +39,52 @@ static const char text[] = "lorem ""ipsum /*"; #include -/**/ #include -/**//**/ #include -/*'*/ #include -/* -*/ #include - -// +/**/ #include "\ +moc_object2.cpp\ +" +/**//**/ #include +/*'"*/ #include +/*"' +*/ #include /* +#include "missing.cpp" +*/// a backslash newline does make the next line part of this comment \ +/* so this text is in last line's C++-style comment, not a C-comment ! #include +#if 0 +#pragma "ignore me" '&' L"me" +#line 4321 "main.cpp" more /* preprocessing */ tokens +#endif static void function1(); -#include +#include/* every comment +gets replaced (in phase 3) by a single +space */ static void function2(); /**/ -#include +#include \ + static void function3(); // #include +/* backslash-newline elimination happens in phase 2 *\ +/ # /* and that's valid here, too. *\ +/ include/* and, of course, here *\ +/// while we're here, ... \ +#include "needed.cpp" int main () { extern int needed(void); return needed(); } + +/* + Deliberately end file in a #include, with nothing after it but the mandatory + (unescaped) newline at the end of every source file. +*/ +#include "moc_objectf.cpp" diff --git a/tests/auto/tools/qmake/testdata/findDeps/objecta.h b/tests/auto/tools/qmake/testdata/findDeps/objecta.h new file mode 100644 index 0000000000..b9813b9e18 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/findDeps/objecta.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +class ObjectA : public QObject +{ + Q_OBJECT +}; + diff --git a/tests/auto/tools/qmake/testdata/findDeps/objectf.h b/tests/auto/tools/qmake/testdata/findDeps/objectf.h new file mode 100644 index 0000000000..5dead815a0 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/findDeps/objectf.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +class ObjectF : public QObject +{ + Q_OBJECT +}; + diff --git a/tests/auto/tools/qmake/testdata/rawString/main.cpp b/tests/auto/tools/qmake/testdata/rawString/main.cpp index fb7008a1a9..604986666a 100644 --- a/tests/auto/tools/qmake/testdata/rawString/main.cpp +++ b/tests/auto/tools/qmake/testdata/rawString/main.cpp @@ -31,7 +31,8 @@ ** ****************************************************************************/ -static const char raw[] = R"blah(lorem " ipsum /*)blah"; +static const char raw[] = R"blah(lorem " ipsum /*)blah"\ +; #include int main () { return 0; } -- cgit v1.2.3 From 40804ad86876865b67d10f937a4de2a3cc9978e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Tue, 8 Dec 2015 10:31:35 +0200 Subject: Extend blacklisting of tst_qsettings to OSX 10.11 This test is marked as blacklisted on 10.10, and it is found to still fail in 10.11. Task-number: QTBUG-49834 Change-Id: Ibddb1af6b61f3fca2b2aea18102bbaa5390a40d3 Reviewed-by: Simon Hausmann --- tests/auto/corelib/io/qsettings/BLACKLIST | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/corelib/io/qsettings/BLACKLIST b/tests/auto/corelib/io/qsettings/BLACKLIST index 1cba99b66c..317e97730e 100644 --- a/tests/auto/corelib/io/qsettings/BLACKLIST +++ b/tests/auto/corelib/io/qsettings/BLACKLIST @@ -1,2 +1,3 @@ [isWritable:native] osx-10.10 +osx-10.11 -- cgit v1.2.3 From 0150cd3617bca177ecfbd65379c8c0ed6e2fe6ed Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Fri, 11 Dec 2015 22:28:57 +0100 Subject: QCocoaWindow - resize embedded views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when QCocoaWindow::setCocoaGeometry is called on windows embedded into a native cocoa gui, QPlatformWindow::setGeometry does not apply the geometry. we therefore need to set the frame on the embedded view manually. related tasks: Task-number: QTBUG-47632 Task-number: QTBUG-45269 Change-Id: I976e4606d36bb4afc74b0834105bceab8a6f8cbd Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 5a59a842c6..3b5909a37e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -503,7 +503,11 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) QMacAutoReleasePool pool; if (m_contentViewIsEmbedded) { - QPlatformWindow::setGeometry(rect); + if (m_qtView) { + [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; + } else { + QPlatformWindow::setGeometry(rect); + } return; } -- cgit v1.2.3 From 482165057dfb1cc6ef4281e693dd8127aa0d6f6e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 10 Dec 2015 14:10:01 +0100 Subject: Add support for reading fonts from TTC files on Windows Embedded Task-number: QTBUG-49810 Change-Id: Ibfc999a15b17899ab2c87d6741dc69b0871699bb Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/windows/qwindowsfontdatabase_ft.cpp | 73 ++++++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 16cc2afef6..308eafc20c 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -194,7 +194,14 @@ typedef struct { quint16 stringOffset; } NAME_RECORD; -static QString fontNameFromTTFile(const QString &filename) +typedef struct { + quint32 tag; + quint16 majorVersion; + quint16 minorVersion; + quint32 numFonts; +} TTC_TABLE_HEADER; + +static QString fontNameFromTTFile(const QString &filename, int startPos = 0) { QFile f(filename); QString retVal; @@ -202,6 +209,7 @@ static QString fontNameFromTTFile(const QString &filename) qint64 bytesToRead; if (f.open(QIODevice::ReadOnly)) { + f.seek(startPos); OFFSET_TABLE ttOffsetTable; bytesToRead = sizeof(OFFSET_TABLE); bytesRead = f.read((char*)&ttOffsetTable, bytesToRead); @@ -282,6 +290,37 @@ static QString fontNameFromTTFile(const QString &filename) return retVal; } +static QStringList fontNamesFromTTCFile(const QString &filename) +{ + QFile f(filename); + QStringList retVal; + qint64 bytesRead; + qint64 bytesToRead; + + if (f.open(QIODevice::ReadOnly)) { + TTC_TABLE_HEADER ttcTableHeader; + bytesToRead = sizeof(TTC_TABLE_HEADER); + bytesRead = f.read((char*)&ttcTableHeader, bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion); + ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion); + ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts); + + if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2) + return retVal; + QVarLengthArray offsetTable(ttcTableHeader.numFonts); + bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts; + bytesRead = f.read((char*)offsetTable.data(), bytesToRead); + if (bytesToRead != bytesRead) + return retVal; + f.close(); + for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i) + retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i])); + } + return retVal; +} + static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); } static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); } static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); } @@ -308,20 +347,28 @@ static QString findFontFile(const QString &faceName) //empty the cache first, as it seems that it is dirty settings.remove(QString()); - QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System); - + QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System); + const QLatin1Char lowerF('f'); + const QLatin1Char upperF('F'); while (it.hasNext()) { const QString fontFile = it.next(); - const QString fontName = fontNameFromTTFile(fontFile); - if (fontName.isEmpty()) - continue; - fontCache.insert(fontName, fontFile); - settings.setValue(fontName, fontFile); - - if (localizedName(fontName)) { - QString englishFontName = getEnglishName(fontName); - fontCache.insert(englishFontName, fontFile); - settings.setValue(englishFontName, fontFile); + QStringList fontNames; + const QChar c = fontFile[fontFile.size() - 1]; + if (c == lowerF || c == upperF) + fontNames << fontNameFromTTFile(fontFile); + else + fontNames << fontNamesFromTTCFile(fontFile); + foreach (const QString fontName, fontNames) { + if (fontName.isEmpty()) + continue; + fontCache.insert(fontName, fontFile); + settings.setValue(fontName, fontFile); + + if (localizedName(fontName)) { + QString englishFontName = getEnglishName(fontName); + fontCache.insert(englishFontName, fontFile); + settings.setValue(englishFontName, fontFile); + } } } settings.endGroup(); -- cgit v1.2.3 From bece6fa0b9409918ce9c57c59d61537b304c9812 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Dec 2015 10:49:47 +0100 Subject: QDockAreaLayout/QPlaceHolderItem: Store geometry excluding frame. Previously, the geometry stored for floating dock widgets in QPlaceHolderItem::topLevelRect and QDockAreaLayoutInfo::saveState() included the window frame (frame position/content area size). This does not work in the case where a floating dock widget is deleted since the geometry is determined after reparenting the widget when the frame geometry is no longer available. Change the behavior to store the geometry excluding frame to avoid such problems and adapt QDockWidgetPrivate::setWindowState() accordingly. Task-number: QTBUG-49832 Task-number: QTBUG-45780 Change-Id: I84b5c80df6e1c9e738bbb1407b9047cc84719ce0 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qdockarealayout.cpp | 3 ++- src/widgets/widgets/qdockwidget.cpp | 8 +------- .../auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp | 16 +++++++++++++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 06c20adb9d..8c79425e44 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const stream << flags; if (w->isWindow()) { - stream << w->x() << w->y() << w->width() << w->height(); + const QRect geometry = w->geometry(); + stream << geometry.x() << geometry.y() << geometry.width() << geometry.height(); } else { stream << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize()); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 292681584d..67eb466ba8 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1093,14 +1093,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect q->setWindowFlags(flags); - if (!rect.isNull()) { - if (floating) { - q->resize(rect.size()); - q->move(rect.topLeft()); - } else { + if (!rect.isNull()) q->setGeometry(rect); - } - } updateButtons(); diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 70df31ed69..713dc6b9b8 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -761,6 +761,9 @@ void tst_QDockWidget::restoreDockWidget() { QByteArray geometry; QByteArray state; + + const bool isXcb = !QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive); + const QString name = QStringLiteral("main"); const QRect availableGeometry = QApplication::desktop()->availableGeometry(); const QSize size = availableGeometry.size() / 5; @@ -785,11 +788,22 @@ void tst_QDockWidget::restoreDockWidget() QVERIFY(dock->isFloating()); state = saveWindow.saveState(); geometry = saveWindow.saveGeometry(); + + // QTBUG-49832: Delete and recreate the dock; it should be restored to the same position. + delete dock; + dock = createTestDock(saveWindow); + QVERIFY(saveWindow.restoreDockWidget(dock)); + dock->show(); + QVERIFY(QTest::qWaitForWindowExposed(dock)); + QTRY_VERIFY(dock->isFloating()); + if (!isXcb) // Avoid Window manager positioning issues + QTRY_COMPARE(dock->pos(), dockPos); } QVERIFY(!geometry.isEmpty()); QVERIFY(!state.isEmpty()); + // QTBUG-45780: Completely recreate the dock widget from the saved state. { QMainWindow restoreWindow; restoreWindow.setObjectName(name); @@ -804,7 +818,7 @@ void tst_QDockWidget::restoreDockWidget() restoreWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow)); QTRY_VERIFY(dock->isFloating()); - if (!QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive)) + if (isXcb) QSKIP("Skip due to Window manager positioning issues", Abort); QTRY_COMPARE(dock->pos(), dockPos); } -- cgit v1.2.3 From b0e422aa5299281fdb5cea60d5dd0ece4e362f48 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 15 Dec 2015 07:20:22 +0400 Subject: Use proper class namespace in QBasicFontDatabase sub-classes Do not assume QBasicFontDatabase doesn't reimplement fallbacksForFamily() and use the proper chaining instead. Change-Id: I822d1902843a3a13517b7025761b88439fd75ced Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/qandroidplatformfontdatabase.cpp | 2 +- src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index a8bbec9400..5725f5793e 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -74,7 +74,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';'))); else result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';'))); - result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; } diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 308eafc20c..1b6ee0f383 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -724,7 +724,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); - result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result; -- cgit v1.2.3 From 674b0e23829395699a3fb4863505f3afbf54a467 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 14 Dec 2015 09:51:56 +0400 Subject: QWinRTFontDatabase: Return the base class' fallbacksForFamily instead of an empty list. Even if QBasicFontDatabase::fallbacksForFamily() returns an empty list ;) Change-Id: Ib4a63e7898d2708737dd694f0629bdb68b2eb3a1 Reviewed-by: Lars Knoll --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index 9bd51218a4..793256a83f 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -439,6 +439,7 @@ QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont: QStringList result; if (family == QLatin1String("Helvetica")) result.append(QStringLiteral("Arial")); + result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; } -- cgit v1.2.3 From b8189ddd80ff922fe11dfc1eb8bdb6a33eee0dfe Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 14 Dec 2015 00:50:33 +0400 Subject: Use the cached font fallback families list in QFont::defaultFamily() Change-Id: Iba1d9db05f7a09aabb81d0429e6081cd7710d381 Reviewed-by: Marc Mutz Reviewed-by: Lars Knoll --- src/gui/text/qfont.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 7d9d00713c..947c538234 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2110,6 +2110,9 @@ QString QFont::lastResortFamily() const return QString::fromLatin1("helvetica"); } +extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, QChar::Script script); + /*! \fn QString QFont::defaultFamily() const @@ -2120,8 +2123,7 @@ QString QFont::lastResortFamily() const */ QString QFont::defaultFamily() const { - QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal + const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal , QFont::StyleHint(d->request.styleHint), QChar::Script_Common); if (!fallbacks.isEmpty()) return fallbacks.first(); -- cgit v1.2.3 From 85eb7d9897c0186747cce585a9f9ef9cfe0b627a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 10 Nov 2015 20:37:03 +0100 Subject: Complete a test for QFilePrivate::fileName offset on Linux This extends the test suite introduced in 497f0af1f7 for a known-to-be-good case also for 32 bit systems. Change-Id: Ia231bcb9b0102c28483d932be18767662b7a6afd Reviewed-by: Christian Stenger --- tests/auto/other/toolsupport/tst_toolsupport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp index bbd787bf38..f3c99af8ba 100644 --- a/tests/auto/other/toolsupport/tst_toolsupport.cpp +++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp @@ -114,7 +114,7 @@ void tst_toolsupport::offsets_data() if (sizeof(void *) == 8) { QTestData &data = QTest::newRow("QFilePrivate::fileName") << pmm_to_offsetof(&QFilePrivate::fileName); - data << -1 << 248; + data << 168 << 248; } #endif -- cgit v1.2.3 From 769027dcb3d9bd9f6a0fa7a97adf9ea3142904c4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 11 Dec 2015 12:13:58 +0100 Subject: don't call qtAddToolEnv() directly qtPrepareTool() does it anyway, so this saves repeated manipulations. for now, this is just nicer, but soon it will be a requirement. Change-Id: I5184e0e4597c6d5a4d7dd4cc4d81e7f742a79fc8 Reviewed-by: Joerg Bornemann --- mkspecs/features/qml_plugin.prf | 5 +++-- mkspecs/features/qt_docs.prf | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf index 1bc05caefe..daedeca3a0 100644 --- a/mkspecs/features/qml_plugin.prf +++ b/mkspecs/features/qml_plugin.prf @@ -90,7 +90,6 @@ load(qt_common) qmlplugindump = qmlplugindump importpath.name = QML2_IMPORT_PATH } - qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump) importpath.value = for(qmod, QTREPOS) { qml1_target: \ @@ -100,7 +99,9 @@ load(qt_common) exists($$qmod): importpath.value += $$shell_path($$qmod) } importpath.value = $$unique(importpath.value) - qtAddToolEnv(QMLPLUGINDUMP, importpath) + QT_TOOL_ENV = importpath + qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump) + QT_TOOL_ENV = TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, ) qmltypes.target = qmltypes qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index bcc16ada78..15bd12072a 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -18,7 +18,19 @@ QMAKE_DOCS_TARGET = $$replace(QMAKE_DOCS, ^(.*/)?(.*)\\.qdocconf$, \\2) isEmpty(QMAKE_DOCS_TARGETDIR): QMAKE_DOCS_TARGETDIR = $$QMAKE_DOCS_TARGET QMAKE_DOCS_OUTPUTDIR = $$QMAKE_DOCS_BASE_OUTDIR/$$QMAKE_DOCS_TARGETDIR +qtver.name = QT_VERSION +qtver.value = $$VERSION +isEmpty(qtver.value): qtver.value = $$MODULE_VERSION +isEmpty(qtver.value): error("No version for documentation specified.") +qtmver.name = QT_VER +qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1) +qtvertag.name = QT_VERSION_TAG +qtvertag.value = $$replace(qtver.value, \.,) +qtdocs.name = QT_INSTALL_DOCS +qtdocs.value = $$[QT_INSTALL_DOCS/src] +QT_TOOL_ENV = qtver qtmver qtvertag qtdocs qtPrepareTool(QDOC, qdoc) +QT_TOOL_ENV = QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR !build_online_docs: \ QDOC += -installdir $$[QT_INSTALL_DOCS] @@ -43,17 +55,6 @@ DOC_INDEXES = PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get] DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get] } -qtver.name = QT_VERSION -qtver.value = $$VERSION -isEmpty(qtver.value): qtver.value = $$MODULE_VERSION -isEmpty(qtver.value): error("No version for documentation specified.") -qtmver.name = QT_VER -qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1) -qtvertag.name = QT_VERSION_TAG -qtvertag.value = $$replace(qtver.value, \.,) -qtdocs.name = QT_INSTALL_DOCS -qtdocs.value = $$[QT_INSTALL_DOCS/src] -qtAddToolEnv(QDOC, qtver qtmver qtvertag qtdocs) doc_command = $$QDOC $$QMAKE_DOCS prepare_docs { prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors -- cgit v1.2.3 From 209a26c6c4187a15cc6297000ad729392aac6454 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 26 Nov 2015 10:31:28 +0100 Subject: qmake: Fix comment false-alarm bug in findMocs(). If a / wasn't part of a comment-start, it and the character after it were none the less stepped over. If the character after started an enclosure, this would duly be missed, leading to mis-parsing of the subsequent text. As for similar bug recently fixed in findDeps(). Change-Id: Ie5329ec633c23a554b42a6351723c980e27fb9a9 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 2 ++ tests/auto/tools/qmake/testdata/findMocs/object7.h | 1 + 2 files changed, 3 insertions(+) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 656acdc6ba..53e0954749 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -919,6 +919,8 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) ++line_count; } } + } else { // not a comment, in fact; undo the extra x++ we did. + x--; } } } else if (buffer[x] == '\'' || buffer[x] == '"') { diff --git a/tests/auto/tools/qmake/testdata/findMocs/object7.h b/tests/auto/tools/qmake/testdata/findMocs/object7.h index 92b4672d6b..3922a542e0 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/object7.h +++ b/tests/auto/tools/qmake/testdata/findMocs/object7.h @@ -33,6 +33,7 @@ /**//*'*/ #include +#define bogon /"/*" class Object7 : public QObject { -- cgit v1.2.3 From 5e7492325a745908e11403b1f729a840c180fc6c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 8 Dec 2015 14:50:45 +0100 Subject: qmake: teach moc-detector to handle C++-11 raw strings As for the #include-parser, the moc-detector's minimal C preprocessor could be confused by a raw string into ignoring large chunks of code. Change-Id: Id688e9a1f04628ce75a51a7d15269078c734288e Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 166 +++++++++++---------- .../auto/tools/qmake/testdata/rawString/object1.h | 3 +- 2 files changed, 86 insertions(+), 83 deletions(-) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 53e0954749..635a775cb3 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -422,6 +422,87 @@ static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start, return true; } +/* Advance from an opening quote at buffer[offset] to the matching close quote. */ +static int scanPastString(char *buffer, int buffer_len, int offset, int *lines) +{ + // It might be a C++11 raw string. + bool israw = false; + if (buffer[offset] == '"' && offset > 0) { + int explore = offset - 1; + while (explore > 0 && buffer[explore] != 'R') { + if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') { + explore--; + } else if (explore > 1 && qmake_endOfLine(buffer[explore]) + && buffer[explore - 1] == '\\') { + explore -= 2; + } else if (explore > 2 && buffer[explore] == '\n' + && buffer[explore - 1] == '\r' + && buffer[explore - 2] == '\\') { + explore -= 3; + } else { + break; + } + } + israw = (buffer[explore] == 'R'); + } + + if (israw) { +#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines) + + offset = SKIP_BSNL(offset + 1); + const char *const delim = buffer + offset; + int clean = offset; + while (offset < buffer_len && buffer[offset] != '(') { + if (clean < offset) + buffer[clean++] = buffer[offset]; + else + clean++; + + offset = SKIP_BSNL(offset + 1); + } + /* + Not checking correctness (trust real compiler to do that): + - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; + - at most 16 bytes in delim + + Raw strings are surely defined after phase 2, when BSNLs are resolved; + so the delimiter's exclusion of '\\' and space (including newlines) + applies too late to save us the need to cope with BSNLs in it. + */ + + const int delimlen = buffer + clean - delim; + int matchlen = delimlen, extralines = 0; + while ((offset = SKIP_BSNL(offset + 1)) < buffer_len + && (buffer[offset] != ')' + || (delimlen > 0 && + !matchWhileUnsplitting(buffer, buffer_len, + offset + 1, delim, delimlen, + &matchlen, &extralines)) + || buffer[offset + 1 + matchlen] != '"')) { + // skip, but keep track of lines + if (qmake_endOfLine(buffer[offset])) + ++*lines; + extralines = 0; + } + *lines += extralines; // from the match + // buffer[offset] is ')' + offset += 1 + matchlen; // 1 for ')', then delim + // buffer[offset] is '"' + +#undef SKIP_BSNL + } else { // Traditional string or char literal: + const char term = buffer[offset]; + while (++offset < buffer_len && buffer[offset] != term) { + if (buffer[offset] == '\\') + ++offset; + else if (qmake_endOfLine(buffer[offset])) + ++*lines; + } + } + + return offset; +} + bool QMakeSourceFileInfo::findDeps(SourceFile *file) { if(file->dep_checked || file->type == TYPE_UNKNOWN) @@ -696,75 +777,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) case InCode: // matching quotes (string literals and character literals) if (buffer[x] == '\'' || buffer[x] == '"') { - // It might be a C++11 raw string. - bool israw = false; - if (buffer[x] == '"' && x > 0) { - int y = x - 1; - while (y > 0 && buffer[y] != 'R') { - if (buffer[y] == '8' || buffer[y] == 'u' || buffer[y] == 'U') - y--; - else if (y > 1 && qmake_endOfLine(buffer[y]) - && buffer[y - 1] == '\\') - y -= 2; - else if (y > 2 && buffer[y] == '\n' - && buffer[y - 1] == '\r' - && buffer[y - 2] == '\\') - y -= 3; - else - break; - } - israw = (buffer[y] == 'R'); - } - if (israw) { - x = SKIP_BSNL(x + 1); - const char *const delim = buffer + x; - int clean = x; - while (x < buffer_len && buffer[x] != '(') { - if (clean < x) - buffer[clean++] = buffer[x]; - else - clean++; - - x = SKIP_BSNL(x + 1); - } - /* - Not checking correctness (trust real compiler to do that): - - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; - - at most 16 bytes in delim - - Raw strings are surely defined after phase 2, when - BSNLs are resolved; so the delimiter's exclusion - of '\\' and space (including newlines) applies too - late to save us the need to cope with BSNLs in it. - */ - - const int delimlen = buffer + clean - delim; - int matchlen = delimlen, extralines = 0; - while ((x = SKIP_BSNL(x + 1)) < buffer_len - && (buffer[x] != ')' - || (delimlen > 0 && - !matchWhileUnsplitting(buffer, buffer_len, - x + 1, delim, delimlen, - &matchlen, &extralines)) - || buffer[x + 1 + matchlen] != '"')) { - // skip, but keep track of lines - if (qmake_endOfLine(buffer[x])) - ++line_count; - extralines = 0; - } - line_count += extralines; // from the match - // buffer[x] is ')' - x += 1 + matchlen; // 1 for ')', then delim - // buffer[x] is '"' - } else { - const char term = buffer[x]; - while (++x < buffer_len && buffer[x] != term) { - if (buffer[x] == '\\') - ++x; - else if (qmake_endOfLine(buffer[x])) - ++line_count; - } - } + x = scanPastString(buffer, buffer_len, x, &line_count); // for loop's ++x shall step over the closing quote. } // else: buffer[x] is just some code; move on. @@ -924,19 +937,10 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) } } } else if (buffer[x] == '\'' || buffer[x] == '"') { - const char term = buffer[x++]; - while(x < buffer_len) { - if (buffer[x] == term) - break; - if (buffer[x] == '\\') { - x+=2; - } else { - if (qmake_endOfLine(buffer[x])) - ++line_count; - ++x; - } - } + x = scanPastString(buffer, buffer_len, x, &line_count); + // Leaves us on closing quote; for loop's x++ steps us past it. } + if (Option::debug_level && qmake_endOfLine(buffer[x])) ++line_count; if (buffer_len > x + 2 && buffer[x + 1] == 'Q' && diff --git a/tests/auto/tools/qmake/testdata/rawString/object1.h b/tests/auto/tools/qmake/testdata/rawString/object1.h index 07af4229fb..1435624f7b 100644 --- a/tests/auto/tools/qmake/testdata/rawString/object1.h +++ b/tests/auto/tools/qmake/testdata/rawString/object1.h @@ -31,11 +31,10 @@ ** ****************************************************************************/ - +#define rawstring R"blah(lorem " ipsum /*)blah"; #include class Object1 : public QObject { Q_OBJECT }; - -- cgit v1.2.3 From 935ddbd3a2350dd57978894b00d7a57a7488d571 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 9 Dec 2015 14:37:11 +0100 Subject: qmake: simplify file-reading loop in findMocs Change-Id: If436215c6041551782750f107021fcccbd447b32 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 635a775cb3..037ad06ad3 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -872,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) files_changed = true; file->moc_checked = true; - int buffer_len; + int buffer_len = 0; char *buffer = 0; { struct stat fst; @@ -890,9 +890,9 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) return false; //shouldn't happen } buffer = getBuffer(fst.st_size); - for(int have_read = buffer_len = 0; - (have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len)); - buffer_len += have_read) ; + while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len)) + buffer_len += have_read; + QT_CLOSE(fd); } -- cgit v1.2.3 From 44c6c3ae27183daea033bf8ef108606e24a8b9ee Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Dec 2015 13:34:02 +0100 Subject: winrt: Align error code handling with WinCE Both specify 87 (invalid parameter) as error code for non existing shared memory. Change-Id: I02b02da106e9e4e574a21359c25bc2a03e385a7c Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- src/corelib/kernel/qsharedmemory_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index ac4ef39e8f..f90763d308 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -58,7 +58,7 @@ void QSharedMemoryPrivate::setErrorString(QLatin1String function) errorString = QSharedMemory::tr("%1: already exists").arg(function); break; case ERROR_FILE_NOT_FOUND: -#ifdef Q_OS_WINCE +#if defined(Q_OS_WINCE) || (defined(Q_OS_WINRT) && _MSC_VER < 1900) // This happens on CE only if no file is present as CreateFileMappingW // bails out with this error code case ERROR_INVALID_PARAMETER: -- cgit v1.2.3 From a6ef446d4c57b8f3d8a4f4dd85e98baba1583b2d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 14 Dec 2015 18:06:54 +0100 Subject: DirectWrite: Fix clipping bug with grayscale AA rendering The code is using the same rasterizer for A8 and A32 glyphs, in the former case it's just converting to grayscale afterwards. Therefore, we need to pad the glyph cache with the same number of pixels for both cases. [ChangeLog][Windows][DirectWrite] Fixed clipping bug when rendering unhinted text with grayscale antialiasing. Task-number: QTBUG-49562 Change-Id: If85ff768451116278f6d2ccd1e77b5ce0664087d Reviewed-by: Konstantin Ritt Reviewed-by: Simon Hausmann --- src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 593ac7d810..2cd00d7b81 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -487,7 +487,7 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) { - QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform()); + QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, QTransform()); QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); @@ -709,9 +709,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) { Q_UNUSED(pos); - int margin = 0; - if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB) - margin = glyphMargin(QFontEngine::Format_A32); + Q_UNUSED(format); + + int margin = glyphMargin(QFontEngine::Format_A32); glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix); gm.width += margin * 2; gm.height += margin * 2; -- cgit v1.2.3 From 8a401371ea6baeb827c7fa57befd5e183949fca7 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 15 Dec 2015 12:46:51 +0100 Subject: DirectWrite: Implement transforms for grayscale aa When cleartype rendering was turned off, transforms would be badly broken with the DirectWrite engine because we did not implement the appropriate code path there. In Qt 5.6, this would become especially visible, since DirectWrite is always used when high-dpi scaling is enabled. [ChangeLog][Windows][DirectWrite] Added transformation support to DirectWrite engine when using grayscale antialiasing. Task-number: QTBUG-49562 Change-Id: Ic5f7dd5b020a85ed1b6473c511a67cdb5ed5cedb Reviewed-by: Konstantin Ritt Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: Alessandro Portale --- src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp | 9 +++++++-- src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 2cd00d7b81..5e2e9f6454 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -485,9 +485,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const return 0; } -QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) { - QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, QTransform()); + QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t); QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); @@ -504,6 +504,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub return alphaMap; } +QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +{ + return alphaMapForGlyph(glyph, subPixelPosition, QTransform()); +} + bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const { return true; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index da772469e9..cee8691d69 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -86,6 +86,7 @@ public: bool supportsSubPixelPositions() const; QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t); QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform); QFontEngine *cloneWithSize(qreal pixelSize) const; -- cgit v1.2.3 From e664251a77417a96e6c3fc27b6d530e208411886 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 15 Dec 2015 23:38:28 +0400 Subject: Cache font fallback families to reduce startup time Change-Id: I593708d76d513028ba1b59621b83cbc32e63d4e6 Reviewed-by: Lars Knoll --- src/gui/text/qfontdatabase.cpp | 55 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 80908122a8..1b9852c20c 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated() Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name)); } + +struct FallbacksCacheKey { + QString family; + QFont::Style style; + QFont::StyleHint styleHint; + QChar::Script script; +}; + +inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW +{ + return lhs.script == rhs.script && + lhs.styleHint == rhs.styleHint && + lhs.style == rhs.style && + lhs.family == rhs.family; +} + +inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW +{ + return !operator==(lhs, rhs); +} + +inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW +{ + QtPrivate::QHashCombine hash; + seed = hash(seed, key.family); + seed = hash(seed, int(key.style)); + seed = hash(seed, int(key.styleHint)); + seed = hash(seed, int(key.script)); + return seed; +} + + class QFontDatabasePrivate { public: QFontDatabasePrivate() - : count(0), families(0), reregisterAppFonts(false) + : count(0), families(0), + fallbacksCache(64), + reregisterAppFonts(false) { } ~QFontDatabasePrivate() { @@ -443,6 +478,7 @@ public: int count; QtFontFamily **families; + QCache fallbacksCache; struct ApplicationFont { @@ -461,6 +497,8 @@ public: void QFontDatabasePrivate::invalidate() { QFontCache::instance()->clear(); + + fallbacksCache.clear(); free(); QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate(); emit static_cast(QCoreApplication::instance())->fontDatabaseChanged(); @@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive)) void qt_cleanupFontDatabase() { QFontDatabasePrivate *db = privateDb(); - if (db) + if (db) { + db->fallbacksCache.clear(); db->free(); + } } // used in qfontengine_x11.cpp @@ -800,9 +840,15 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) { + QFontDatabasePrivate *db = privateDb(); + + const FallbacksCacheKey cacheKey = { family, style, styleHint, script }; + + if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey)) + return *fallbacks; + // make sure that the db has all fallback families QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); - QFontDatabasePrivate *db = privateDb(); QStringList::iterator i; for (i = retList.begin(); i != retList.end(); ++i) { @@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo --i; } } + + db->fallbacksCache.insert(cacheKey, new QStringList(retList)); + return retList; } -- cgit v1.2.3 From efcd4d6f866d731a930b48a20f68b4bbee9146fe Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 11 Dec 2015 13:29:01 +0100 Subject: ensure that we don't leak QT_TOOL_ENV beyond qt_tool.prf the variable is later re-used by qtPrepareTool(), so the tools used to build the tool would get excess variables passed. Change-Id: Ib1bdd2211b4a8615e2be9ba0310822f373f5efb0 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_tool.prf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/qt_tool.prf b/mkspecs/features/qt_tool.prf index 3f0301a292..839c3d6b88 100644 --- a/mkspecs/features/qt_tool.prf +++ b/mkspecs/features/qt_tool.prf @@ -64,3 +64,5 @@ DEFINES *= QT_USE_QSTRINGBUILDER cache(QT_TOOL.$${MODULE}.$$var, transient) } +# The variable is re-used by qtPrepareTool(), and we really don't want that. +unset(QT_TOOL_ENV) -- cgit v1.2.3 From 7ec40ab52ea5434791a8d02a8eb20724f24cefc6 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 14 Dec 2015 14:14:16 +0100 Subject: QOpenGLTexturePrivate: remove unused member variable Change-Id: I4d897c522087654649547c0ca4750ba4dbfa5cbf Reviewed-by: Sean Harmer --- src/gui/opengl/qopengltexture_p.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h index ac9d44db42..40ceb1936c 100644 --- a/src/gui/opengl/qopengltexture_p.h +++ b/src/gui/opengl/qopengltexture_p.h @@ -156,7 +156,6 @@ public: bool autoGenerateMipMaps; bool storageAllocated; - QPair glVersion; QOpenGLTextureHelper *texFuncs; QOpenGLTexture::Features features; -- cgit v1.2.3 From a5b254ff23b9ca3099a9f13e93727e1cd52c8720 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 14 Dec 2015 14:16:12 +0100 Subject: QOpenGLTexture: check textureId for knowing whether a texture was created Change-Id: I0775ad9538a7793dc6628abe4556404634ae0462 Reviewed-by: Sean Harmer --- src/gui/opengl/qopengltexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 301b2ad13d..33c0d0bb60 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -175,7 +175,7 @@ bool QOpenGLTexturePrivate::create() void QOpenGLTexturePrivate::destroy() { - if (!context) { + if (!textureId) { // not created or already destroyed return; } -- cgit v1.2.3 From 08ee579cf025ad868bb405835b57d31e512b6fd6 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 14 Dec 2015 14:23:46 +0100 Subject: QOpenGLTexture: fix the number of faces returned by faces() Change-Id: I7bf08eee357fb9641ff9118edcf97809f98605b7 Reviewed-by: Sean Harmer --- src/gui/opengl/qopengltexture.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 33c0d0bb60..02dee5a90a 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -97,9 +97,11 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge break; case QOpenGLTexture::TargetCubeMap: bindingTarget = QOpenGLTexture::BindingTargetCubeMap; + faces = 6; break; case QOpenGLTexture::TargetCubeMapArray: bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray; + faces = 6; break; case QOpenGLTexture::Target2DMultisample: bindingTarget = QOpenGLTexture::BindingTarget2DMultisample; -- cgit v1.2.3 From 0b10d41c3db0d1a43e754a2bd923a0df8915d0e5 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 17 Dec 2015 09:30:16 +0200 Subject: Android: Fix crash at exit Delay the exit call until Java part finishes the execution. We must be sure all the threads are stopped (hanged), when we call exit, otherwise java thread will try to use static vars that are freed by the qt thread. We also need to call exit from Qt thread, otherwise Qt will complain about it. Change-Id: Ia1e7a4d7d56c39d38313f040aab618ec5a68dfb6 Reviewed-by: Christian Stromme --- .../qtproject/qt5/android/QtActivityDelegate.java | 1 + .../jar/src/org/qtproject/qt5/android/QtNative.java | 7 ++++++- src/plugins/platforms/android/androidjnimain.cpp | 20 ++++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) 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 4575d8a1d3..dd5a7b4fec 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -919,6 +919,7 @@ public class QtActivityDelegate public void onDestroy() { if (m_quitApp) { + QtNative.terminateQt(); if (m_debuggerProcess != null) m_debuggerProcess.destroy(); System.exit(0);// FIXME remove it or find a better way diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 8880c003e7..2349ea6db1 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -294,7 +294,12 @@ public class QtNative private static void quitApp() { - m_activity.finish(); + runAction(new Runnable() { + @Override + public void run() { + m_activity.finish(); + } + }); } //@ANDROID-9 diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index f500d6e413..dd9154f8d2 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -91,6 +92,8 @@ extern "C" typedef int (*Main)(int, char **); //use the standard main method to static Main m_main = nullptr; static void *m_mainLibraryHnd = nullptr; static QList m_applicationParams; +pthread_t m_qtAppThread = 0; +static sem_t m_exitSemaphore, m_terminateSemaphore; struct SurfaceData { @@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/) if (vm != 0) vm->DetachCurrentThread(); + sem_post(&m_terminateSemaphore); + sem_wait(&m_exitSemaphore); + sem_destroy(&m_exitSemaphore); + // We must call exit() to ensure that all global objects will be destructed exit(ret); return 0; @@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para return false; } - pthread_t appThread; - return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0; + if (sem_init(&m_exitSemaphore, 0, 0) == -1) + return false; + + if (sem_init(&m_terminateSemaphore, 0, 0) == -1) + return false; + + return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0; } @@ -518,6 +530,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/) static void terminateQt(JNIEnv *env, jclass /*clazz*/) { + sem_wait(&m_terminateSemaphore); + sem_destroy(&m_terminateSemaphore); env->DeleteGlobalRef(m_applicationClass); env->DeleteGlobalRef(m_classLoaderObject); if (m_resourcesObj) @@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) m_androidPlatformIntegration = nullptr; delete m_androidAssetsFileEngineHandler; m_androidAssetsFileEngineHandler = nullptr; + sem_post(&m_exitSemaphore); + pthread_join(m_qtAppThread, nullptr); } static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h) -- cgit v1.2.3 From e362774df22846e100237739c0cb7190100d265b Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 11 Dec 2015 10:57:16 +0100 Subject: iOS: include marked text when reporting IM textInRange and endOfDocument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed marked text should be seen as a part of the text document. This is different from Qt IM (ImSurroundingText), which handles marked text on the side. The reason we can assume this is that the range we are given as argument to textInRange exceeds the documents length when having marked text appended to the end, suggesting that it tries to read / verify the current marked text. In addition, keyboards like Japanese-Kana will not update and function correctly unless marked text is included. Note that the docs seems to imply that you cannot have marked text and text selection at the same time, unless the selection is contained within the marked text (using the dedicated selectedRange argument to setMarkedText). If this turns out to be incorrect, we might need to adjust the methods dealing with selection to also include marked text as well. Task-number: QTBUG-49946 Change-Id: Ifedd792ec66db435806f57fca157e1abbbf121a8 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 770dadd3e4..2e8c0cb4db 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -613,7 +613,8 @@ - (UITextPosition *)endOfDocument { - int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length(); + QString surroundingText = [self currentImeState:Qt::ImSurroundingText].toString(); + int endPosition = surroundingText.length() + m_markedText.length(); return [QUITextPosition positionWithIndex:endPosition]; } @@ -644,9 +645,18 @@ - (NSString *)textInRange:(UITextRange *)range { + QString text = [self currentImeState:Qt::ImSurroundingText].toString(); + if (!m_markedText.isEmpty()) { + // [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed + // marked text should be seen as a part of the text document. This is different from + // ImSurroundingText, which excludes it. + int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt(); + text = text.left(cursorPos) + m_markedText + text.mid(cursorPos); + } + int s = static_cast([range start]).index; int e = static_cast([range end]).index; - return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString(); + return text.mid(s, e - s).toNSString(); } - (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange -- cgit v1.2.3 From bace82bffe7289d1a10ad652c4510b193d71c922 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 16 Dec 2015 23:38:13 +0100 Subject: iOS: notify application when edit menu is closed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The edit menu will also close if the user taps outside it, not only when selecting a menu item. But we never caught this case, which left QMenu to belive that it was still open. Change-Id: Iae071b4fc5fdc44d7d05b4dd767042907e337957 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosmenu.mm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 7aea3729fd..612f8c43a2 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -61,11 +61,23 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; { if (self = [super init]) { [self setVisibleMenuItems:visibleMenuItems]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(menuClosed) + name:UIMenuControllerDidHideMenuNotification object:nil]; } return self; } +-(void)dealloc +{ + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:UIMenuControllerDidHideMenuNotification object:nil]; + [super dealloc]; +} + - (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems { m_visibleMenuItems = visibleMenuItems; @@ -85,6 +97,11 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; [[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO]; } +-(void)menuClosed +{ + QIOSMenu::currentMenu()->dismiss(); +} + - (id)targetForAction:(SEL)action withSender:(id)sender { Q_UNUSED(sender); -- cgit v1.2.3 From 8885344ad48abe9a707868ce5677f32b05338a50 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 11 Dec 2015 15:13:11 +0100 Subject: iOS: Don't hide keyboard on "Done" button when focus object has changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the focus object changed programmatically for example to the next input field in a window, we want to keep the keyboard open. This strangely only worked if the inputs had different IM hints because this made the keyboard appear again. Change-Id: I52e66bb7d2ff97ae7084173769d9b5c2d0c549b5 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 2e8c0cb4db..e6ea43652f 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -925,6 +925,14 @@ if ([text isEqualToString:@"\n"]) { [self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier]; + // An onEnter handler of a TextInput might move to the next input by calling + // nextInput.forceActiveFocus() which changes the focusObject. + // In that case we don't want to hide the VKB. + if (focusObject != QGuiApplication::focusObject()) { + qImDebug() << "focusObject already changed, not resigning first responder."; + return; + } + if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo || self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch) [self resignFirstResponder]; -- cgit v1.2.3 From e78ca787ae459f2769a6b0126dad4700408bfb46 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 14 Dec 2015 09:58:04 +0100 Subject: iOS: Clear focusObject if first responder is set to null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In certain cases we were still showing a cursor in a TextInput even though the keyboard was hidden programmatically. Change-Id: I48ebb6b8bc0382236b1ea5835e68eae48ece2b4f Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index e6ea43652f..320b1cac61 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -318,7 +318,11 @@ // a regular responder transfer to another window. In the former case, iOS // will set the new first-responder to our next-responder, and in the latter // case we'll have an active responder candidate. - if ([UIResponder currentFirstResponder] == [self nextResponder]) { + if (![UIResponder currentFirstResponder]) { + // No first responder set anymore, sync this with Qt by clearing the + // focus object. + m_inputContext->clearCurrentFocusObject(); + } else if ([UIResponder currentFirstResponder] == [self nextResponder]) { // We have resigned the keyboard, and transferred first responder back to the parent view Q_ASSERT(!FirstResponderCandidate::currentCandidate()); if ([self currentImeState:Qt::ImEnabled].toBool()) { -- cgit v1.2.3 From 879409fd0ffa2466dbd9f7274a4417b34ed18360 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 16 Dec 2015 14:50:35 +0100 Subject: Use Q_CONSTRUCTOR_FUNCTION instead of doing the same manually Use the macro we have that does exactly what we want without the boiler plate code. Change-Id: I25c67a71f83f91f50128c8a54033ee53ad28e88a Reviewed-by: Erik Verbruggen --- src/gui/image/qimage_conversions.cpp | 11 +---------- src/gui/painting/qdrawhelper.cpp | 19 ++++++------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index cbdcf49da7..cc79e73534 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -2967,15 +2967,6 @@ static void qInitImageConversions() #endif } -class QImageConversionsInitializer { -public: - QImageConversionsInitializer() - { - qInitImageConversions(); - } -}; - -// Ensure initialization if this object file is linked. -static QImageConversionsInitializer qImageConversionsInitializer; +Q_CONSTRUCTOR_FUNCTION(qInitImageConversions); QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index bf7a50e227..87ceb9a89d 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6323,8 +6323,13 @@ void qt_memfill32(quint32 *dest, quint32 color, int count) template const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); #endif +extern void qInitBlendFunctions(); + static void qInitDrawhelperFunctions() { + // Set up basic blend function tables. + qInitBlendFunctions(); + #ifdef __SSE2__ qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; @@ -6518,19 +6523,7 @@ static void qInitDrawhelperFunctions() #endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2 } -extern void qInitBlendFunctions(); -class DrawHelperInitializer { -public: - DrawHelperInitializer() - { - // Set up basic blend function tables. - qInitBlendFunctions(); - // Set up architecture optimized methods for the current machine. - qInitDrawhelperFunctions(); - } -}; - // Ensure initialization if this object file is linked. -static DrawHelperInitializer drawHelperInitializer; +Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions); QT_END_NAMESPACE -- cgit v1.2.3 From d6efc0aab30c5dc927aa8a0c743ab0c3775321a4 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 9 Dec 2015 10:27:58 +0100 Subject: qmake: teach findMocs to handle backslash-newline gracefully. Change-Id: Id71352c0cf71ab84bd81d4f3d11bb19dc7965903 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 83 ++++++++++++---------- .../tools/qmake/testdata/findMocs/findMocs.pro | 3 +- tests/auto/tools/qmake/testdata/findMocs/main.cpp | 5 +- tests/auto/tools/qmake/testdata/findMocs/object1.h | 4 +- tests/auto/tools/qmake/testdata/findMocs/object2.h | 4 +- tests/auto/tools/qmake/testdata/findMocs/object3.h | 4 +- tests/auto/tools/qmake/testdata/findMocs/object4.h | 3 +- tests/auto/tools/qmake/testdata/findMocs/object8.h | 50 +++++++++++++ tests/auto/tools/qmake/testdata/findMocs/object9.h | 41 +++++++++++ 9 files changed, 150 insertions(+), 47 deletions(-) create mode 100644 tests/auto/tools/qmake/testdata/findMocs/object8.h create mode 100644 tests/auto/tools/qmake/testdata/findMocs/object9.h diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 037ad06ad3..1f94a53c81 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -902,13 +902,24 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) /* qmake ignore Q_GADGET */ /* qmake ignore Q_OBJECT */ for(int x = 0; x < buffer_len; x++) { +#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count) + x = SKIP_BSNL(x); if (buffer[x] == '/') { - ++x; - if(buffer_len >= x) { - if (buffer[x] == '/') { // C++-style comment - for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip - } else if (buffer[x] == '*') { // C-style comment - for(++x; x < buffer_len; ++x) { + int extralines = 0; + int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines); + if (buffer_len > y) { + // If comment, advance to the character that ends it: + if (buffer[y] == '/') { // C++-style comment + line_count += extralines; + x = y; + do { + x = SKIP_BSNL(x + 1); + } while (x < buffer_len && !qmake_endOfLine(buffer[x])); + + } else if (buffer[y] == '*') { // C-style comment + line_count += extralines; + x = SKIP_BSNL(y + 1); + for (; x < buffer_len; x = SKIP_BSNL(x + 1)) { if (buffer[x] == 't' || buffer[x] == 'q') { // ignore if(buffer_len >= (x + 20) && !strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) { @@ -924,58 +935,58 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) ignore_qgadget = true; } } else if (buffer[x] == '*') { - if (buffer_len >= x + 1 && buffer[x + 1] == '/') { - ++x; + extralines = 0; + y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines); + if (buffer_len > y && buffer[y] == '/') { + line_count += extralines; + x = y; break; } } else if (Option::debug_level && qmake_endOfLine(buffer[x])) { ++line_count; } } - } else { // not a comment, in fact; undo the extra x++ we did. - x--; } + // else: don't update x, buffer[x] is just the division operator. } } else if (buffer[x] == '\'' || buffer[x] == '"') { x = scanPastString(buffer, buffer_len, x, &line_count); // Leaves us on closing quote; for loop's x++ steps us past it. } - if (Option::debug_level && qmake_endOfLine(buffer[x])) + if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x])) ++line_count; - if (buffer_len > x + 2 && buffer[x + 1] == 'Q' && - buffer[x + 2] == '_' && !isCWordChar(buffer[x])) { - ++x; - int match = 0; - static const char *interesting[] = { "OBJECT", "GADGET" }; - for (int interest = 0, m1, m2; interest < 2; ++interest) { + if (buffer_len > x + 8 && !isCWordChar(buffer[x])) { + int morelines = 0; + int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines); + if (buffer[y] == 'Q') { + static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" }; + for (int interest = 0; interest < 2; ++interest) { if(interest == 0 && ignore_qobject) continue; else if(interest == 1 && ignore_qgadget) continue; - for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) { - if (interesting[interest][m1] != buffer[x + 2 + m1]) { - m2 = -1; - break; + + int matchlen = 0, extralines = 0; + if (matchWhileUnsplitting(buffer, buffer_len, y, + interesting[interest], + strlen(interesting[interest]), + &matchlen, &extralines) + && y + matchlen < buffer_len + && !isCWordChar(buffer[y + matchlen])) { + if (Option::debug_level) { + buffer[y + matchlen] = '\0'; + debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", + file->file.real().toLatin1().constData(), + line_count + morelines, buffer + y); + } + file->mocable = true; + return true; } - ++m2; - } - if(m1 == m2) { - match = m2 + 2; - break; } } - if (match && !isCWordChar(buffer[x + match])) { - if (Option::debug_level) { - buffer[x + match] = '\0'; - debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", - file->file.real().toLatin1().constData(), - line_count, buffer + x); - } - file->mocable = true; - return true; - } } +#undef SKIP_BSNL } return true; } diff --git a/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro b/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro index a4a7dc987d..af672c2621 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro +++ b/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro @@ -1,4 +1,5 @@ DESTDIR = ./ -HEADERS += object1.h object2.h object3.h object4.h object5.h object6.h object7.h +HEADERS += object1.h object2.h object3.h object4.h \ + object5.h object6.h object7.h object8.h object9.h SOURCES += main.cpp diff --git a/tests/auto/tools/qmake/testdata/findMocs/main.cpp b/tests/auto/tools/qmake/testdata/findMocs/main.cpp index 8e0ef9fc41..3f566c4af4 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/main.cpp +++ b/tests/auto/tools/qmake/testdata/findMocs/main.cpp @@ -39,6 +39,7 @@ #include #include #include +#include "object8.h" +#include -int main () {} - +int main() { return 0; } diff --git a/tests/auto/tools/qmake/testdata/findMocs/object1.h b/tests/auto/tools/qmake/testdata/findMocs/object1.h index e0857f4297..1fcac5f511 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/object1.h +++ b/tests/auto/tools/qmake/testdata/findMocs/object1.h @@ -37,6 +37,6 @@ class Object1 : public QObject { - Q_OBJECT + Q\ +_OBJECT }; - diff --git a/tests/auto/tools/qmake/testdata/findMocs/object2.h b/tests/auto/tools/qmake/testdata/findMocs/object2.h index cc60269cd3..a52489b44c 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/object2.h +++ b/tests/auto/tools/qmake/testdata/findMocs/object2.h @@ -36,6 +36,6 @@ class Object2 : public QObject { - Q_OBJECT + Q_\ +OBJECT }; - diff --git a/tests/auto/tools/qmake/testdata/findMocs/object3.h b/tests/auto/tools/qmake/testdata/findMocs/object3.h index c66edee6e1..c481a0796d 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/object3.h +++ b/tests/auto/tools/qmake/testdata/findMocs/object3.h @@ -37,6 +37,6 @@ class Object3 : public QObject { - Q_OBJECT + Q_OBJ\ +ECT }; - diff --git a/tests/auto/tools/qmake/testdata/findMocs/object4.h b/tests/auto/tools/qmake/testdata/findMocs/object4.h index 73bf9cdaa3..eb38652f14 100644 --- a/tests/auto/tools/qmake/testdata/findMocs/object4.h +++ b/tests/auto/tools/qmake/testdata/findMocs/object4.h @@ -44,10 +44,9 @@ class Object4 : public QObject Comment ends there --> /*/ // Now we poison moc, just to make sure this doesn't get moc'ed :) -class NonMocObject +class NonMocObject4 /* : QObject */ { /* qmake ignore Q_OBJECT */ Q_OBJECT }; - diff --git a/tests/auto/tools/qmake/testdata/findMocs/object8.h b/tests/auto/tools/qmake/testdata/findMocs/object8.h new file mode 100644 index 0000000000..51096e4c27 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/findMocs/object8.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#define Q_OBJECTOID_THING // empty + +class Object8 : public QObject +{ + Q_OBJECT\ +OID_THING +}; + +// Now we poison moc, just to make sure this doesn't get moc'ed :) +class NonMocObject8 +/* : QObject */ +{ + /* qmake ignore Q_OBJECT */ + Q_OBJECT +}; diff --git a/tests/auto/tools/qmake/testdata/findMocs/object9.h b/tests/auto/tools/qmake/testdata/findMocs/object9.h new file mode 100644 index 0000000000..bda50355d9 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/findMocs/object9.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#define juxtaposed "lorem ""ipsum /*" + +class Object9 : public QObject +{ + Q_OBJECT +}; -- cgit v1.2.3 From 4815f1cda42010659370ce2b80739a14d46ad21b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 15 Dec 2015 16:56:09 +0100 Subject: qmake: Combine two variables into an array to simplify a loop. Change-Id: If787ed4a72c5fb91bb4a9e908ab3f6443b9358b9 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 1f94a53c81..047d17f18a 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -898,7 +898,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData()); int line_count = 1; - bool ignore_qobject = false, ignore_qgadget = false; + bool ignore[2] = { false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET /* qmake ignore Q_GADGET */ /* qmake ignore Q_OBJECT */ for(int x = 0; x < buffer_len; x++) { @@ -926,13 +926,13 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"", file->file.real().toLatin1().constData(), line_count); x += 20; - ignore_qobject = true; + ignore[0] = true; } else if(buffer_len >= (x + 20) && !strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) { debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"", file->file.real().toLatin1().constData(), line_count); x += 20; - ignore_qgadget = true; + ignore[1] = true; } } else if (buffer[x] == '*') { extralines = 0; @@ -962,10 +962,8 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file) if (buffer[y] == 'Q') { static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" }; for (int interest = 0; interest < 2; ++interest) { - if(interest == 0 && ignore_qobject) - continue; - else if(interest == 1 && ignore_qgadget) - continue; + if (ignore[interest]) + continue; int matchlen = 0, extralines = 0; if (matchWhileUnsplitting(buffer, buffer_len, y, -- cgit v1.2.3 From 69839e55c13000ee9bf8d8e9d74b70096a92ae51 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 14 Dec 2015 15:40:42 +0100 Subject: Windows: fix fullscreen OpenGL window issues with an opt-in function Windows automatically disables DWM for opengl windows that have the exact dimensions of the primary screen. This causes numerous issues, such as menus and popups not showing up, and alt+tab misbehavior. Adding a one pixel border via WS_BORDER solves all of these issues. This is done by a QWindowsWindowFunctions to make it opt-in as turning it on can cause an unwanted change in the look of the window so it is up to the user to decide if they want this. [ChangeLog][Platform Specific Changes][Windows] Add a function to QWindowsWindowFunctions to enable working around a limitation with showing other top level windows when showing a fullscreen OpenGL based window. Task-number: QTBUG-41309 Task-number: QTBUG-41883 Task-number: QTBUG-42410 Change-Id: I8c5c785f5024737cd034b2b703671632a8102700 Reviewed-by: Laszlo Agocs Reviewed-by: Friedemann Kleint --- .../windowsfunctions/qwindowswindowfunctions.h | 9 ++++++++ .../windowsfunctions/qwindowswindowfunctions.qdoc | 26 ++++++++++++++++++++++ .../platforms/windows/qwindowsnativeinterface.cpp | 2 ++ src/plugins/platforms/windows/qwindowswindow.cpp | 17 ++++++++++++++ src/plugins/platforms/windows/qwindowswindow.h | 6 +++-- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h index 4c6d01cc52..720f7f31be 100644 --- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h +++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h @@ -60,6 +60,15 @@ public: if (func) func(window, type); } + + typedef void (*SetHasBorderInFullScreen)(QWindow *window, bool border); + static const QByteArray setHasBorderInFullScreenIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreen"); } + static void setHasBorderInFullScreen(QWindow *window, bool border) + { + SetHasBorderInFullScreen func = reinterpret_cast(QGuiApplication::platformFunction(setHasBorderInFullScreenIdentifier())); + if (func) + func(window, border); + } }; Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes) diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc index 84fae2f56d..d6b8764e7b 100644 --- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc +++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc @@ -69,3 +69,29 @@ This is a convenience function that can be used directly instead of resolving the function pointer. \a window and \a type will be relayed to the function retrieved by QGuiApplication */ + +/*! + \typedef QWindowsWindowFunctions::SetHasBorderInFullScreen + + This is the typedef for the function returned by QGuiApplication::platformFunction when passed setHasBorderInFullScreenIdentifier. +*/ + +/*! + \fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier() + \since 5.6 + + This function returns the bytearray that can be used to query + QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function. +*/ + +/*! + \fn void QWindowsWindowFunctions::setHasBorderInFullScreen(QWindow *window, bool border) + \since 5.6 + + This is a convenience function that can be used directly instead of resolving the function pointer. + \a window and \a border will be relayed to the function retrieved by QGuiApplication. When \a border + is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows + inside the application to appear on top when required. + + See also \l [QtDoc] {Fullscreen OpenGL Based Windows} +*/ diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index db8b2ec094..659ef79c18 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -234,6 +234,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun { if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier()) return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); + else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()) + return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic); return Q_NULLPTR; } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 611d586b19..5aae1aafc5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1735,6 +1735,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) newStyle |= WS_SYSMENU; if (visible) newStyle |= WS_VISIBLE; + if (testFlag(HasBorderInFullScreen)) + newStyle |= WS_BORDER; setStyle(newStyle); // Use geometry of QWindow::screen() within creation or the virtual screen the // window is in (QTBUG-31166, QTBUG-30724). @@ -2371,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent() #endif } +void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border) +{ + if (!window->handle()) + return; + static_cast(window->handle())->setHasBorderInFullScreen(border); +} + +void QWindowsWindow::setHasBorderInFullScreen(bool border) +{ + if (border) + setFlag(HasBorderInFullScreen); + else + clearFlag(HasBorderInFullScreen); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 4172a3d850..710cab8597 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -137,7 +137,8 @@ public: WithinMaximize = 0x40000, MaximizeToFullScreen = 0x80000, InputMethodDisabled = 0x100000, - Compositing = 0x200000 + Compositing = 0x200000, + HasBorderInFullScreen = 0x400000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -251,7 +252,8 @@ public: static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); - + static void setHasBorderInFullScreenStatic(QWindow *window, bool border); + void setHasBorderInFullScreen(bool border); private: inline void show_sys() const; inline void hide_sys() const; -- cgit v1.2.3 From ac5c2aaf35bba3048aeff5c26cf0aa704fe63df6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 14 Dec 2015 12:02:29 +0100 Subject: Windows: Clear key recorder when application becomes inactive. When keys are pressed and the application becomes inactive before they are released, the stored state becomes inconsistent. Task-number: QTBUG-49930 Change-Id: Ide86b1d9052df060f30f7c02b81a4f2ae15d28e7 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowskeymapper.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 4c0b94e6e7..c5dff60114 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -86,10 +86,15 @@ QT_BEGIN_NAMESPACE The code originates from \c qkeymapper_win.cpp. */ +static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state); + QWindowsKeyMapper::QWindowsKeyMapper() : m_useRTLExtensions(false), m_keyGrabber(0) { memset(keyLayout, 0, sizeof(keyLayout)); + QGuiApplication *app = static_cast(QGuiApplication::instance()); + QObject::connect(app, &QGuiApplication::applicationStateChanged, + app, clearKeyRecorderOnApplicationInActive); } QWindowsKeyMapper::~QWindowsKeyMapper() @@ -144,6 +149,12 @@ struct KeyRecorder }; static KeyRecorder key_recorder; +static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state) +{ + if (state == Qt::ApplicationInactive) + key_recorder.clearKeys(); +} + KeyRecord *KeyRecorder::findKey(int code, bool remove) { KeyRecord *result = 0; -- cgit v1.2.3 From e3288f246b44ba2b6d90b90eb99ab61f496d8d57 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 9 Dec 2015 18:06:20 +0100 Subject: Windows: Restore window geometry after normal->maximized->fullscreen->normal. - Do not save geometry when going from maximized->fullscreen - Use SW_SHOWNA instead SW_SHOWNOACTIVATE as otherwise the maximized geometry is restored. - Add a test for Windows. Task-number: QTBUG-49709 Change-Id: Ic81e7398ee90d499a50b02192a45cb09276a2105 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowswindow.cpp | 4 +- tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 67 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 5aae1aafc5..cac8ec5ecc 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1720,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) if (!m_savedStyle) { m_savedStyle = style(); #ifndef Q_OS_WINCE - if (oldState == Qt::WindowMinimized) { + if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) { const QRect nf = normalFrameGeometry(m_data.hwnd); if (nf.isValid()) m_savedFrameGeometry = nf; @@ -1771,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) // preserve maximized state if (visible) { setFlag(WithinMaximize); - ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA); clearFlag(WithinMaximize); } m_savedStyle = 0; diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 2219306b81..a89f0da4d2 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -95,6 +95,8 @@ private slots: void windowsTransientChildren(); void requestUpdate(); void initTestCase(); + void stateChange_data(); + void stateChange(); void cleanup(); private: @@ -272,6 +274,18 @@ static inline bool qFuzzyCompareWindowPosition(const QPoint &p1, const QPoint p2 return (p1 - p2).manhattanLength() <= fuzz; } +static inline bool qFuzzyCompareWindowSize(const QSize &s1, const QSize &s2, int fuzz) +{ + const int manhattanLength = qAbs(s1.width() - s2.width()) + qAbs(s1.height() - s2.height()); + return manhattanLength <= fuzz; +} + +static inline bool qFuzzyCompareWindowGeometry(const QRect &r1, const QRect &r2, int fuzz) +{ + return qFuzzyCompareWindowPosition(r1.topLeft(), r2.topLeft(), fuzz) + && qFuzzyCompareWindowSize(r1.size(), r2.size(), fuzz); +} + static QString msgPointMismatch(const QPoint &p1, const QPoint p2) { QString result; @@ -279,6 +293,13 @@ static QString msgPointMismatch(const QPoint &p1, const QPoint p2) return result; } +static QString msgRectMismatch(const QRect &r1, const QRect &r2) +{ + QString result; + QDebug(&result) << r1 << "!=" << r2; + return result; +} + void tst_QWindow::positioning() { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability( @@ -394,6 +415,52 @@ void tst_QWindow::positioningDuringMinimized() QTRY_COMPARE(window.geometry(), newGeometry); } +// QTBUG-49709: Verify that the normal geometry is correctly restored +// when executing a sequence of window state changes. So far, Windows +// only where state changes have immediate effect. + +typedef QList WindowStateList; + +Q_DECLARE_METATYPE(WindowStateList) + +void tst_QWindow::stateChange_data() +{ + QTest::addColumn("stateSequence"); + + QTest::newRow("normal->min->normal") << + (WindowStateList() << Qt::WindowMinimized << Qt::WindowNoState); + QTest::newRow("normal->maximized->normal") << + (WindowStateList() << Qt::WindowMaximized << Qt::WindowNoState); + QTest::newRow("normal->fullscreen->normal") << + (WindowStateList() << Qt::WindowFullScreen << Qt::WindowNoState); + QTest::newRow("normal->maximized->fullscreen->normal") << + (WindowStateList() << Qt::WindowMaximized << Qt::WindowFullScreen << Qt::WindowNoState); +} + +void tst_QWindow::stateChange() +{ + QFETCH(WindowStateList, stateSequence); + + if (QGuiApplication::platformName().compare(QLatin1String("windows"), Qt::CaseInsensitive)) + QSKIP("Windows-only test"); + + Window window; + window.setTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1Char(' ') + QLatin1String(QTest::currentDataTag())); + const QRect normalGeometry(m_availableTopLeft + QPoint(40, 40), m_testWindowSize); + window.setGeometry(normalGeometry); + // explicitly use non-fullscreen show. show() can be fullscreen on some platforms + window.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + foreach (Qt::WindowState state, stateSequence) { + window.setWindowState(state); + QCoreApplication::processEvents(); + } + const QRect geometry = window.geometry(); + const int fuzz = int(QHighDpiScaling::factor(&window)); + QVERIFY2(qFuzzyCompareWindowGeometry(geometry, normalGeometry, fuzz), + qPrintable(msgRectMismatch(geometry, normalGeometry))); +} + class PlatformWindowFilter : public QObject { Q_OBJECT -- cgit v1.2.3