aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-04-21 21:40:24 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-04-21 21:40:25 +0200
commit327b489bd7b137aa6bce5e16ba3d47fe3f33f33c (patch)
tree2bd5d38f28aaefd874943da90b2c2d78543a91dc
parent152bca765bab4ce55d4a649896c92c3d4a4f1b30 (diff)
parent6555642db7b3b992335f98dc01863db4beea3fd4 (diff)
Merge remote-tracking branch 'origin/5.15' into 5.15.0
-rw-r--r--src/qml/qml/qqml.h5
-rw-r--r--src/qml/qml/qqmlengine.cpp1
-rw-r--r--src/qml/qml/qqmlplatform.cpp2
-rw-r--r--src/qml/qml/qqmltype.cpp2
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.cpp23
-rw-r--r--src/qmltyperegistrar/qmltypescreator.cpp31
-rw-r--r--src/quick/items/qquickwindow.cpp5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp43
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp13
-rw-r--r--src/quick/util/qquickanimatorjob.cpp1
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.h7
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp10
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h30
-rw-r--r--tests/auto/quick/qquickanimations/data/opacityAnimationFromZero.qml20
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp37
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST2
16 files changed, 200 insertions, 32 deletions
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 4adf100a1f..1621e3c02e 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -735,10 +735,15 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
}
+#ifdef Q_QDOC
+template <typename T>
+int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QObject*(QQmlEngine *, QJSEngine *)> callback)
+#else
template <typename T, typename F, typename std::enable_if<std::is_convertible<F, std::function<QObject *(QQmlEngine *, QJSEngine *)>>::value
&& !std::is_convertible<F, QObject *(*)(QQmlEngine *, QJSEngine *)>::value, void>::type* = nullptr>
inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
F&& callback)
+#endif
{
QML_GETTYPENAMES
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 5823ff8963..872a448bfd 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -422,6 +422,7 @@ The following functions are also on the Qt object.
\li \c "unix" - Other Unix-based OS
\li \c "windows" - Windows
\li \c "winrt" - WinRT / UWP
+ \li \c "wasm" - WebAssembly
\endlist
\row
diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp
index 0acf20bbb4..c1ad5c0886 100644
--- a/src/qml/qml/qqmlplatform.cpp
+++ b/src/qml/qml/qqmlplatform.cpp
@@ -76,6 +76,8 @@ QString QQmlPlatform::os()
return QStringLiteral("qnx");
#elif defined(Q_OS_UNIX)
return QStringLiteral("unix");
+#elif defined(Q_OS_WASM)
+ return QStringLiteral("wasm");
#else
return QStringLiteral("unknown");
#endif
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 96a35b0fe9..317d3c7ef5 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -276,7 +276,7 @@ void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
? compositePropertyCache(engine)
: nullptr;
- const QMetaObject *metaObject = !isEnumFromCacheSetup
+ const QMetaObject *metaObject = !isEnumFromBaseSetup
? baseMetaObject // beware: It could be a singleton type without metaobject
: nullptr;
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp
index 7756fda9e4..9aadd75acc 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.cpp
+++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp
@@ -62,6 +62,7 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef,
const QVector<QJsonObject> &foreign,
CollectMode mode)
{
+ const QJsonObject *origClassDef = classDef; // if we find QML.Foreign, classDef changes.
if (file.isEmpty() && classDef->value(QLatin1String("registerable")).toBool())
file = classDef->value(QLatin1String("inputFile")).toString();
const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray();
@@ -130,21 +131,33 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef,
collectExtraVersions(classDef, QString::fromLatin1("signals"), revisions);
}
- const auto supers = classDef->value(QLatin1String("superClasses")).toArray();
- if (!supers.isEmpty()) {
- const QJsonObject superObject = supers.first().toObject();
+ auto supers = classDef->value(QLatin1String("superClasses")).toArray();
+ if (classDef != origClassDef) {
+ const QJsonArray origSupers = origClassDef->value(QLatin1String("superClasses")).toArray();
+ for (const QJsonValue &origSuper : origSupers)
+ supers.append(origSuper);
+ }
+
+ for (const QJsonValue &superValue : qAsConst(supers)) {
+ const QJsonObject superObject = superValue.toObject();
if (superObject[QLatin1String("access")].toString() == QLatin1String("public")) {
const QString superName = superObject[QLatin1String("name")].toString();
- if (mode == TopLevel && superClass.isEmpty())
- superClass = superName;
if (const QJsonObject *other = findType(types, superName))
collect(other, types, foreign, mode == TopLevel ? SuperClass : AttachedType);
else if (const QJsonObject *other = findType(foreign, superName))
collect(other, types, foreign, mode == TopLevel ? SuperClass : AttachedType);
+ else // If we cannot locate a type for it, there is no point in recording the superClass
+ continue;
+
+ if (mode == TopLevel && superClass.isEmpty())
+ superClass = superName;
}
}
+ if (mode != TopLevel)
+ return;
+
if (addedInRevision == -1) {
revisions.append(0);
addedInRevision = 0;
diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp
index 1119f88282..e74550c6c2 100644
--- a/src/qmltyperegistrar/qmltypescreator.cpp
+++ b/src/qmltyperegistrar/qmltypescreator.cpp
@@ -224,6 +224,19 @@ void QmlTypesCreator::writeEnums(const QJsonArray &enums)
}
}
+static QJsonArray members(const QJsonObject *classDef, const QJsonObject *origClassDef, const QString &key)
+{
+ QJsonArray classDefMembers = classDef->value(key).toArray();
+
+ if (classDef != origClassDef) {
+ const QJsonArray origClassDefMembers = origClassDef->value(key).toArray();
+ for (const auto &member : origClassDefMembers)
+ classDefMembers.append(member);
+ }
+
+ return classDefMembers;
+}
+
void QmlTypesCreator::writeComponents()
{
const QLatin1String nameKey("name");
@@ -259,15 +272,15 @@ void QmlTypesCreator::writeComponents()
writeClassProperties(collector);
const QJsonObject *classDef = collector.resolvedClass;
- writeEnums(classDef->value(enumsKey).toArray());
+ writeEnums(members(classDef, &component, enumsKey));
QSet<QString> notifySignals;
- writeProperties(classDef->value(propertiesKey).toArray(), notifySignals);
+ writeProperties(members(classDef, &component, propertiesKey), notifySignals);
if (collector.isRootClass) {
// Hide destroyed() signals
- QJsonArray componentSignals = classDef->value(signalsKey).toArray();
+ QJsonArray componentSignals = members(classDef, &component, signalsKey);
for (auto it = componentSignals.begin(); it != componentSignals.end();) {
if (it->toObject().value(nameKey).toString() == destroyedName)
it = componentSignals.erase(it);
@@ -277,8 +290,10 @@ void QmlTypesCreator::writeComponents()
writeMethods(componentSignals, signalElement, notifySignals);
// Hide deleteLater() methods
- QJsonArray componentMethods = classDef->value(methodsKey).toArray()
- + classDef->value(slotsKey).toArray();
+ QJsonArray componentMethods = members(classDef, &component, methodsKey);
+ const QJsonArray componentSlots = members(classDef, &component, slotsKey);
+ for (const QJsonValue &componentSlot : componentSlots)
+ componentMethods.append(componentSlot);
for (auto it = componentMethods.begin(); it != componentMethods.end();) {
if (it->toObject().value(nameKey).toString() == deleteLaterName)
it = componentMethods.erase(it);
@@ -312,9 +327,9 @@ void QmlTypesCreator::writeComponents()
writeMethods(componentMethods, methodElement);
} else {
- writeMethods(classDef->value(signalsKey).toArray(), signalElement, notifySignals);
- writeMethods(classDef->value(slotsKey).toArray(), methodElement);
- writeMethods(classDef->value(methodsKey).toArray(), methodElement);
+ writeMethods(members(classDef, &component, signalsKey), signalElement, notifySignals);
+ writeMethods(members(classDef, &component, slotsKey), methodElement);
+ writeMethods(members(classDef, &component, methodsKey), methodElement);
}
m_qml.writeEndObject();
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 50b166b18f..48ba0ecc28 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4889,6 +4889,11 @@ void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
\note This function only has an effect when using the default OpenGL scene graph
adaptation.
+ \note This function will only reset the OpenGL context in relation to what has been changed
+ internally as part of the OpenGL scene graph. It does not reset anything that has been changed
+ externally such as direct OpenGL calls done inside the application code if those same calls are
+ not used internally.
+
\note This function has no effect when running on the RHI graphics
abstraction and the underlying RHI backend is not OpenGL.
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
index dd789b78c7..04e9b361ca 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareglyphnode.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qsgsoftwareglyphnode_p.h"
+#include <QtGui/private/qrawfont_p.h>
QT_BEGIN_NAMESPACE
@@ -52,28 +53,38 @@ QSGSoftwareGlyphNode::QSGSoftwareGlyphNode()
namespace {
QRectF calculateBoundingRect(const QPointF &position, const QGlyphRun &glyphs)
{
- qreal minX = 0;
- qreal minY = 0;
- qreal maxX = 0;
- qreal maxY = 0;
+ QFixed minX;
+ QFixed minY;
+ QFixed maxX;
+ QFixed maxY;
- for (int i = 0, n = qMin(glyphs.glyphIndexes().size(), glyphs.positions().size()); i < n; ++i) {
- QRectF glyphRect = glyphs.rawFont().boundingRect(glyphs.glyphIndexes()[i]);
- glyphRect.translate(glyphs.positions()[i]);
+ QRawFontPrivate *rawFontD = QRawFontPrivate::get(glyphs.rawFont());
+ QFontEngine *fontEngine = rawFontD->fontEngine;
+
+ QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None ? fontEngine->glyphFormat : QFontEngine::Format_A32;
+
+ const QVector<uint> glyphIndexes = glyphs.glyphIndexes();
+ const QVector<QPointF> glyphPositions = glyphs.positions();
+ for (int i = 0, n = qMin(glyphIndexes.size(), glyphPositions.size()); i < n; ++i) {
+ glyph_metrics_t gm = fontEngine->alphaMapBoundingBox(glyphIndexes.at(i), QFixed(), QTransform(), glyphFormat);
+
+ gm.x += QFixed::fromReal(glyphPositions.at(i).x());
+ gm.y += QFixed::fromReal(glyphPositions.at(i).y());
if (i == 0) {
- minX = glyphRect.left();
- minY = glyphRect.top();
- maxX = glyphRect.right();
- maxY = glyphRect.bottom();
+ minX = gm.x;
+ minY = gm.y;
+ maxX = gm.x + gm.width;
+ maxY = gm.y + gm.height;
} else {
- minX = qMin(glyphRect.left(), minX);
- minY = qMin(glyphRect.top(), minY);
- maxX = qMax(glyphRect.right(),maxX);
- maxY = qMax(glyphRect.bottom(), maxY);
+ minX = qMin(gm.x, minX);
+ minY = qMin(gm.y, minY);
+ maxX = qMax(gm.x + gm.width, maxX);
+ maxY = qMax(gm.y + gm.height, maxY);
}
}
- QRectF boundingRect(QPointF(minX, minY), QPointF(maxX, maxY));
+
+ QRectF boundingRect(QPointF(minX.toReal(), minY.toReal()), QPointF(maxX.toReal(), maxY.toReal()));
return boundingRect.translated(position - QPointF(0.0, glyphs.rawFont().ascent()));
}
}
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index 84a9669365..2bf70ddec6 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -38,7 +38,10 @@
****************************************************************************/
#include "qsgrhisupport_p.h"
-#include "qsgdefaultrendercontext_p.h"
+#include "qsgcontext_p.h"
+#if QT_CONFIG(opengl)
+# include "qsgdefaultrendercontext_p.h"
+#endif
#include <QtGui/qwindow.h>
#if QT_CONFIG(vulkan)
@@ -383,9 +386,15 @@ static const void *qsgrhi_mtl_rifResource(QSGRendererInterface::Resource res, co
}
#endif
-const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res, const QSGDefaultRenderContext *rc)
+const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res,
+ const QSGDefaultRenderContext *rc)
{
+#if QT_CONFIG(opengl)
QRhi *rhi = rc->rhi();
+#else
+ Q_UNUSED(rc)
+ QRhi *rhi = nullptr;
+#endif
if (res == QSGRendererInterface::RhiResource || !rhi)
return rhi;
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 0112a4b337..767be96403 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -582,6 +582,7 @@ void QQuickOpacityAnimatorJob::postSync()
}
d->extra.value().opacityNode = m_opacityNode;
+ updateCurrentTime(0);
}
Q_ASSERT(m_opacityNode);
}
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
index d5e5a060b4..dc9fbc84a8 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
@@ -30,6 +30,7 @@
#define FOREIGN_H
#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
class Foreign : public QObject
{
@@ -49,4 +50,10 @@ private:
int m_things = 0;
};
+class SizeGadget : public QSize
+{
+ Q_GADGET
+ Q_PROPERTY(int height READ height WRITE setHeight FINAL)
+};
+
#endif // FOREIGN_H
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index b3304963d8..1cfcd689c6 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -65,4 +65,14 @@ void tst_qmltyperegistrar::qmltypesHasFlags()
QVERIFY(qmltypesData.contains("isFlag: true"));
}
+void tst_qmltyperegistrar::superAndForeignTypes()
+{
+ QVERIFY(qmltypesData.contains("values: [\"Pixel\", \"Centimeter\", \"Inch\", \"Point\"]"));
+ QVERIFY(qmltypesData.contains("name: \"SizeGadget\""));
+ QVERIFY(qmltypesData.contains("prototype: \"SizeEnums\""));
+ QVERIFY(qmltypesData.contains("Property { name: \"height\"; type: \"int\" }"));
+ QVERIFY(qmltypesData.contains("Property { name: \"width\"; type: \"int\" }"));
+ QVERIFY(qmltypesData.contains("Method { name: \"sizeToString\"; type: \"string\" }"));
+}
+
QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index 07a28e1976..09485ab0b6 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -33,6 +33,35 @@
#include <QtQml/qqml.h>
+class SizeEnums
+{
+ Q_GADGET
+ QML_NAMED_ELEMENT(SizeEnums)
+ QML_UNCREATABLE("Element is not creatable.")
+
+public:
+ enum Unit { Pixel, Centimeter, Inch, Point };
+ Q_ENUM(Unit)
+};
+
+class SizeValueType : public SizeEnums
+{
+ QSize v;
+ Q_GADGET
+ Q_PROPERTY(int width READ width WRITE setWidth FINAL)
+ QML_NAMED_ELEMENT(MySize)
+ QML_FOREIGN(SizeGadget)
+
+public:
+ Q_INVOKABLE QString sizeToString() const
+ {
+ return QString::fromLatin1("%1x%2").arg(v.width()).arg(v.height());
+ }
+
+ int width() const { return v.width(); }
+ void setWidth(int width) { v.setWidth(width); }
+};
+
class Local : public Foreign
{
Q_OBJECT
@@ -58,6 +87,7 @@ private slots:
void qmltypesHasHppClassAndNoext();
void qmltypesHasFileNames();
void qmltypesHasFlags();
+ void superAndForeignTypes();
private:
QByteArray qmltypesData;
diff --git a/tests/auto/quick/qquickanimations/data/opacityAnimationFromZero.qml b/tests/auto/quick/qquickanimations/data/opacityAnimationFromZero.qml
new file mode 100644
index 0000000000..bfb8211706
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/opacityAnimationFromZero.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.14
+import QtQuick.Window 2.14
+
+Window {
+ width: 640
+ height: 480
+ Rectangle {
+ id: rect
+ width: 200
+ height: 200
+ color: "black"
+ OpacityAnimator {
+ target: rect
+ from: 0
+ to: 1
+ duration: 1000
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index e62d49ed6b..b4eb33eb7a 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -114,6 +114,7 @@ private slots:
void replacingTransitions();
void animationJobSelfDestruction();
void fastFlickingBug();
+ void opacityAnimationFromZero();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -1858,6 +1859,42 @@ void tst_qquickanimations::fastFlickingBug()
}
}
+void tst_qquickanimations::opacityAnimationFromZero()
+{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
+ // not easy to verify this in threaded render loop
+ // since it's difficult to capture the first frame when scene graph
+ // is renderred in another thread
+ qputenv("QSG_RENDER_LOOP", "basic");
+ auto cleanup = qScopeGuard([]() { qputenv("QSG_RENDER_LOOP", ""); });
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("opacityAnimationFromZero.qml"));
+ QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ if (!c.errors().isEmpty())
+ qDebug() << c.errorString();
+ QVERIFY(win);
+ win->setTitle(QTest::currentTestFunction());
+ win->show();
+ QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+
+ QImage img;
+ bool firstFrameSwapped = false;
+ QObject::connect(win.get(), &QQuickWindow::frameSwapped, win.get(), [&win, &img, &firstFrameSwapped]() {
+ if (firstFrameSwapped)
+ return;
+ else
+ firstFrameSwapped = true;
+ img = win->grabWindow();
+ if (img.width() < win->width())
+ QSKIP("Skipping due to grabWindow not functional");
+ });
+ QTRY_VERIFY(!img.isNull() && img.pixel(100, 100) > qRgb(10, 10, 10));
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
index 08a5249e2e..f50276a4f1 100644
--- a/tests/auto/quick/qquicktext/BLACKLIST
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -4,3 +4,5 @@ qemu
macos
[fontSizeMode]
opensuse-42.1
+[hAlignVisual]
+sles