aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.qmake.conf2
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp2
-rw-r--r--src/plugins/accessible/accessible.pro2
-rw-r--r--src/plugins/accessible/quick/accessible.json3
-rw-r--r--src/plugins/accessible/quick/quick.pro23
-rw-r--r--src/plugins/accessible/shared/qaccessiblebase.pri3
-rw-r--r--src/plugins/plugins.pro3
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp6
-rw-r--r--src/qml/compiler/qv4isel_p.cpp6
-rw-r--r--src/qml/compiler/qv4jsir.cpp687
-rw-r--r--src/qml/compiler/qv4jsir_p.h96
-rw-r--r--src/qml/compiler/qv4ssa.cpp107
-rw-r--r--src/qml/jit/qv4regalloc.cpp161
-rw-r--r--src/quick/accessible/accessible.pri16
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp (renamed from src/plugins/accessible/quick/qaccessiblequickitem.cpp)4
-rw-r--r--src/quick/accessible/qaccessiblequickitem_p.h (renamed from src/plugins/accessible/quick/qaccessiblequickitem.h)4
-rw-r--r--src/quick/accessible/qaccessiblequickview.cpp (renamed from src/plugins/accessible/quick/qaccessiblequickview.cpp)8
-rw-r--r--src/quick/accessible/qaccessiblequickview_p.h (renamed from src/plugins/accessible/quick/qaccessiblequickview.h)2
-rw-r--r--src/quick/accessible/qqmlaccessible.cpp (renamed from src/plugins/accessible/shared/qqmlaccessible.cpp)6
-rw-r--r--src/quick/accessible/qqmlaccessible_p.h (renamed from src/plugins/accessible/shared/qqmlaccessible.h)0
-rw-r--r--src/quick/accessible/qquickaccessiblefactory.cpp (renamed from src/plugins/accessible/quick/main.cpp)51
-rw-r--r--src/quick/accessible/qquickaccessiblefactory_p.h55
-rw-r--r--src/quick/doc/snippets/qml/itemGrab.qml87
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc3
-rw-r--r--src/quick/items/items.pri6
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp2
-rw-r--r--src/quick/items/qquickdrag.cpp14
-rw-r--r--src/quick/items/qquickdrag_p.h6
-rw-r--r--src/quick/items/qquickitem.cpp77
-rw-r--r--src/quick/items/qquickitem.h8
-rw-r--r--src/quick/items/qquickitem_p.h7
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp399
-rw-r--r--src/quick/items/qquickitemgrabresult.h89
-rw-r--r--src/quick/items/qquickitemsmodule.cpp5
-rw-r--r--src/quick/items/qquicklistview.cpp2
-rw-r--r--src/quick/items/qquickmousearea.cpp12
-rw-r--r--src/quick/items/qquickpincharea.cpp74
-rw-r--r--src/quick/items/qquickpincharea_p.h1
-rw-r--r--src/quick/items/qquickpositioners.cpp4
-rw-r--r--src/quick/items/qquickrendercontrol.cpp3
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp10
-rw-r--r--src/quick/items/qquicktextinput.cpp103
-rw-r--r--src/quick/items/qquicktextinput_p.h9
-rw-r--r--src/quick/items/qquicktextinput_p_p.h3
-rw-r--r--src/quick/items/qquickwindow.cpp325
-rw-r--r--src/quick/items/qquickwindow.h8
-rw-r--r--src/quick/items/qquickwindow_p.h11
-rw-r--r--src/quick/qtquick2.cpp5
-rw-r--r--src/quick/qtquickglobal_p.h7
-rw-r--r--src/quick/quick.pro3
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp47
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h9
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp6
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp316
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h15
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp5
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp38
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.h4
-rw-r--r--src/quick/util/qquickpixmapcache.cpp26
-rw-r--r--src/quick/util/qquickpixmapcache_p.h1
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp6
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebugclient.h2
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp8
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp12
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp18
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp8
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp83
-rw-r--r--tests/auto/qmltest/item/tst_layerInPositioner.qml207
-rw-r--r--tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml160
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml84
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml81
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml81
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp30
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp16
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp19
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp35
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp20
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp5
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp24
-rw-r--r--tests/auto/quick/qquickitem/qquickitem.pro1
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp4
-rw-r--r--tests/auto/quick/qquickitem2/data/grabToImage.qml60
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp110
-rw-r--r--tests/auto/quick/qquicklistview/data/sizeTransitions.qml101
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp53
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp16
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp45
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro1
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp91
-rw-r--r--tests/auto/quick/qquickpincharea/qquickpincharea.pro1
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp25
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp10
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp6
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp9
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp55
-rw-r--r--tests/auto/quick/qquickwindow/qquickwindow.pro1
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp156
-rw-r--r--tests/auto/quick/rendernode/data/matrix.qml87
-rw-r--r--tests/auto/quick/rendernode/rendernode.pro2
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp79
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp23
-rw-r--r--tests/auto/quick/shared/viewtestutil.h4
-rw-r--r--tests/auto/quick/touchmouse/touchmouse.pro1
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp117
-rw-r--r--tests/auto/shared/testhttpserver.cpp15
-rw-r--r--tests/auto/shared/testhttpserver.h5
-rw-r--r--tests/manual/httpserver/main.cpp6
-rw-r--r--tools/qmleasing/qmleasing.pro3
110 files changed, 3812 insertions, 1178 deletions
diff --git a/.gitignore b/.gitignore
index 7c37e4daff..c14d237ee3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,6 +100,7 @@ tests/auto/qlibrary/libmylib.so*
tests/auto/qresourceengine/runtime_resource.rcc
tools/qtestlib/chart/chart*
tools/qtestlib/updater/updater*
+tools/qmleasing/qmleasing
tools/qmltestrunner/qmltestrunner
tools/activeqt/testcon/testcon.tlb
translations/*.qm
diff --git a/.qmake.conf b/.qmake.conf
index d170e6d272..28e9cfd9ba 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.3.1
+MODULE_VERSION = 5.4.0
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 5dc4332d69..1f28d8009e 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -446,7 +446,7 @@ void QQuickFolderListModel::setFolder(const QUrl &folder)
/*!
- \qmlproperty url QQuickFolderListModel::rootFolder
+ \qmlproperty url FolderListModel::rootFolder
When the rootFolder is set, then this folder will
be threated as the root in the file system, so that
diff --git a/src/plugins/accessible/accessible.pro b/src/plugins/accessible/accessible.pro
deleted file mode 100644
index b97d323a08..0000000000
--- a/src/plugins/accessible/accessible.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TEMPLATE = subdirs
-qtHaveModule(quick): SUBDIRS += quick
diff --git a/src/plugins/accessible/quick/accessible.json b/src/plugins/accessible/quick/accessible.json
deleted file mode 100644
index b21218f19c..0000000000
--- a/src/plugins/accessible/quick/accessible.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "QQuickWindow", "QQuickItem" ]
-}
diff --git a/src/plugins/accessible/quick/quick.pro b/src/plugins/accessible/quick/quick.pro
deleted file mode 100644
index 115f9bebad..0000000000
--- a/src/plugins/accessible/quick/quick.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-TARGET = qtaccessiblequick
-
-PLUGIN_TYPE = accessible
-PLUGIN_EXTENDS = quick
-PLUGIN_CLASS_NAME = AccessibleQuickFactory
-load(qt_plugin)
-
-include ($$PWD/../shared/qaccessiblebase.pri)
-
-QT += core-private gui-private qml-private quick-private
-
-#DEFINES+=Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
-
-SOURCES += \
- main.cpp \
- qaccessiblequickview.cpp \
- qaccessiblequickitem.cpp
-
-HEADERS += \
- qaccessiblequickview.h \
- qaccessiblequickitem.h
-
-OTHERFILES += accessible.json
diff --git a/src/plugins/accessible/shared/qaccessiblebase.pri b/src/plugins/accessible/shared/qaccessiblebase.pri
deleted file mode 100644
index 827df0f132..0000000000
--- a/src/plugins/accessible/shared/qaccessiblebase.pri
+++ /dev/null
@@ -1,3 +0,0 @@
-INCLUDEPATH += $$PWD
-SOURCES += $$PWD/qqmlaccessible.cpp
-HEADERS += $$PWD/qqmlaccessible.h
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 9ef8c7ab72..664a457608 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,5 +1,2 @@
TEMPLATE = subdirs
SUBDIRS += qmltooling
-contains(QT_CONFIG, accessibility) {
- SUBDIRS += accessible
-}
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 1110b3f29d..ede150c67b 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -2155,7 +2155,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
#endif // QT_NO_DATESTRING
case QVariant::Point: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
return false;
@@ -2173,7 +2173,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
break;
case QVariant::Size: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
return false;
@@ -2191,7 +2191,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
break;
case QVariant::Rect: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: rect expected"));
return false;
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 429688090c..c055cffd0d 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -226,7 +226,7 @@ void IRDecoder::visitMove(IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
- s->dump(qout, IR::Stmt::MIR);
+ IRPrinter(&qout).print(s);
qout << endl;
Q_ASSERT(!"TODO");
}
@@ -402,7 +402,7 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
}
Q_UNIMPLEMENTED();
- call->dump(qout); qout << endl;
+ IRPrinter(&qout).print(call); qout << endl;
Q_ASSERT(!"TODO!");
Q_UNREACHABLE();
}
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5d30d6e3b9..501758145a 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -45,6 +45,8 @@
#ifndef V4_BOOTSTRAP
#include <private/qqmlpropertycache_p.h>
#endif
+
+#include <QtCore/QBuffer>
#include <QtCore/qtextstream.h>
#include <QtCore/qdebug.h>
#include <QtCore/qset.h>
@@ -275,104 +277,6 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
}
};
-static QString dumpStart(const Expr *e) {
- if (e->type == UnknownType)
-// return QStringLiteral("**UNKNOWN**");
- return QString();
-
- QString result = typeName(e->type);
-#ifndef V4_BOOTSTRAP
- const Temp *temp = const_cast<Expr*>(e)->asTemp();
- if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
- result += QLatin1Char('<');
- result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(temp->memberResolver.data)->className());
- result += QLatin1Char('>');
- }
-#endif
- result += QLatin1Char('{');
- return result;
-}
-
-static const char *dumpEnd(const Expr *e) {
- if (e->type == UnknownType)
- return "";
- else
- return "}";
-}
-
-void Const::dump(QTextStream &out) const
-{
- if (type != UndefinedType && type != NullType)
- out << dumpStart(this);
- switch (type) {
- case QV4::IR::UndefinedType:
- out << "undefined";
- break;
- case QV4::IR::NullType:
- out << "null";
- break;
- case QV4::IR::BoolType:
- out << (value ? "true" : "false");
- break;
- case QV4::IR::MissingType:
- out << "missing";
- break;
- default:
- if (int(value) == 0 && int(value) == value) {
- if (isNegative(value))
- out << "-0";
- else
- out << "0";
- } else {
- out << QString::number(value, 'g', 16);
- }
- break;
- }
- if (type != UndefinedType && type != NullType)
- out << dumpEnd(this);
-}
-
-void String::dump(QTextStream &out) const
-{
- out << '"' << escape(*value) << '"';
-}
-
-QString String::escape(const QString &s)
-{
- QString r;
- for (int i = 0; i < s.length(); ++i) {
- const QChar ch = s.at(i);
- if (ch == QLatin1Char('\n'))
- r += QStringLiteral("\\n");
- else if (ch == QLatin1Char('\r'))
- r += QStringLiteral("\\r");
- else if (ch == QLatin1Char('\\'))
- r += QStringLiteral("\\\\");
- else if (ch == QLatin1Char('"'))
- r += QStringLiteral("\\\"");
- else if (ch == QLatin1Char('\''))
- r += QStringLiteral("\\'");
- else
- r += ch;
- }
- return r;
-}
-
-void RegExp::dump(QTextStream &out) const
-{
- char f[3];
- int i = 0;
- if (flags & RegExp_Global)
- f[i++] = 'g';
- if (flags & RegExp_IgnoreCase)
- f[i++] = 'i';
- if (flags & RegExp_Multiline)
- f[i++] = 'm';
- f[i] = 0;
-
- out << '/' << *value << '/' << f;
-}
-
void Name::initGlobal(const QString *id, quint32 line, quint32 column)
{
this->id = id;
@@ -453,33 +357,6 @@ static const char *builtin_to_string(Name::Builtin b)
return "builtin_(###FIXME)";
};
-void Name::dump(QTextStream &out) const
-{
- if (id)
- out << *id;
- else
- out << builtin_to_string(builtin);
-}
-
-void Temp::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- switch (kind) {
- case Formal: out << '#' << index; break;
- case ScopedFormal: out << '#' << index
- << '@' << scope; break;
- case Local: out << '$' << index; break;
- case ScopedLocal: out << '$' << index
- << '@' << scope; break;
- case VirtualRegister: out << '%' << index; break;
- case PhysicalRegister: out << (type == DoubleType ? "fp" : "r")
- << index; break;
- case StackSlot: out << '&' << index; break;
- default: out << "INVALID";
- }
- out << dumpEnd(this);
-}
-
bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
{
if (t1.kind < t2.kind) return true;
@@ -489,151 +366,6 @@ bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
return t1.scope < t2.scope;
}
-void Closure::dump(QTextStream &out) const
-{
- QString name = functionName ? *functionName : QString();
- if (name.isEmpty())
- name.sprintf("%x", value);
- out << "closure(" << name << ')';
-}
-
-void Convert::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- out << "convert(";
- expr->dump(out);
- out << ')' << dumpEnd(this);
-}
-
-void Unop::dump(QTextStream &out) const
-{
- out << dumpStart(this) << opname(op);
- expr->dump(out);
- out << dumpEnd(this);
-}
-
-void Binop::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- left->dump(out);
- out << ' ' << opname(op) << ' ';
- right->dump(out);
- out << dumpEnd(this);
-}
-
-void Call::dump(QTextStream &out) const
-{
- base->dump(out);
- out << '(';
- for (ExprList *it = args; it; it = it->next) {
- if (it != args)
- out << ", ";
- it->expr->dump(out);
- }
- out << ')';
-}
-
-void New::dump(QTextStream &out) const
-{
- out << "new ";
- base->dump(out);
- out << '(';
- for (ExprList *it = args; it; it = it->next) {
- if (it != args)
- out << ", ";
- it->expr->dump(out);
- }
- out << ')';
-}
-
-void Subscript::dump(QTextStream &out) const
-{
- base->dump(out);
- out << '[';
- index->dump(out);
- out << ']';
-}
-
-void Member::dump(QTextStream &out) const
-{
- if (kind != MemberOfEnum && attachedPropertiesIdOrEnumValue != 0 && !base->asTemp())
- out << "[[attached property from " << attachedPropertiesIdOrEnumValue << "]]";
- else
- base->dump(out);
- out << '.' << *name;
-#ifndef V4_BOOTSTRAP
- if (property)
- out << " (meta-property " << property->coreIndex << " <" << QMetaType::typeName(property->propType) << ">)";
-#endif
-}
-
-void Exp::dump(QTextStream &out, Mode)
-{
- out << "(void) ";
- expr->dump(out);
- out << ';';
-}
-
-void Move::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
-
- target->dump(out);
- out << ' ';
- if (swap)
- out << "<=> ";
- else
- out << "= ";
-// if (source->type != target->type)
-// out << typeName(source->type) << "_to_" << typeName(target->type) << '(';
- source->dump(out);
-// if (source->type != target->type)
-// out << ')';
- out << ';';
-}
-
-void Jump::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
- out << "goto " << 'L' << target->index() << ';';
-}
-
-void CJump::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
- out << "if (";
- cond->dump(out);
- if (mode == HIR)
- out << ") goto " << 'L' << iftrue->index() << "; else goto " << 'L' << iffalse->index() << ';';
- else
- out << ") goto " << 'L' << iftrue->index() << ";";
-}
-
-void Ret::dump(QTextStream &out, Mode)
-{
- out << "return";
- if (expr) {
- out << ' ';
- expr->dump(out);
- }
- out << ';';
-}
-
-void Phi::dump(QTextStream &out, Stmt::Mode mode)
-{
- Q_UNUSED(mode);
-
- targetTemp->dump(out);
- out << " = phi(";
- for (int i = 0, ei = d->incoming.size(); i < ei; ++i) {
- if (i > 0)
- out << ", ";
- if (d->incoming[i])
- d->incoming[i]->dump(out);
- }
- out << ");";
-}
-
Function *Module::newFunction(const QString &name, Function *outer)
{
Function *f = new Function(this, outer, name);
@@ -734,21 +466,6 @@ int Function::liveBasicBlocksCount() const
return count;
}
-void Function::dump(QTextStream &out, Stmt::Mode mode)
-{
- QString n = name ? *name : QString();
- if (n.isEmpty())
- n.sprintf("%p", this);
- out << "function " << n << "() {" << endl;
- foreach (const QString *formal, formals)
- out << "\treceive " << *formal << ';' << endl;
- foreach (const QString *local, locals)
- out << "\tlocal " << *local << ';' << endl;
- foreach (BasicBlock *bb, basicBlocks())
- bb->dump(out, mode);
- out << '}' << endl;
-}
-
void Function::removeSharedExpressions()
{
RemoveSharedExpressions removeSharedExpressions;
@@ -1028,23 +745,6 @@ Stmt *BasicBlock::RET(Temp *expr)
return s;
}
-void BasicBlock::dump(QTextStream &out, Stmt::Mode mode)
-{
- out << 'L' << index() << ':';
- if (catchBlock)
- out << " (catchBlock L" << catchBlock->index() << ")";
- out << endl;
- foreach (Stmt *s, statements()) {
- out << '\t';
- s->dump(out, mode);
-
- if (s->location.isValid())
- out << " // line: " << s->location.startLine << " ; column: " << s->location.startColumn;
-
- out << endl;
- }
-}
-
void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
{
Q_ASSERT(!isRemoved());
@@ -1189,6 +889,387 @@ void CloneExpr::visitMember(Member *e)
cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->attachedPropertiesIdOrEnumValue);
}
+IRPrinter::IRPrinter(QTextStream *out)
+ : out(out)
+ , printElse(true)
+{
+}
+
+IRPrinter::~IRPrinter()
+{
+}
+
+void IRPrinter::print(Stmt *s)
+{
+ s->accept(this);
+}
+
+void IRPrinter::print(const Expr &e)
+{
+ const_cast<Expr *>(&e)->accept(this);
+}
+
+void IRPrinter::print(Expr *e)
+{
+ e->accept(this);
+}
+
+void IRPrinter::print(Function *f)
+{
+ QString n = f->name ? *f->name : QString();
+ if (n.isEmpty())
+ n.sprintf("%p", f);
+ *out << "function " << n << '(';
+
+ for (int i = 0; i < f->formals.size(); ++i) {
+ if (i != 0)
+ *out << ", ";
+ *out << *f->formals.at(i);
+ }
+ *out << ')' << endl
+ << '{' << endl;
+
+ foreach (const QString *local, f->locals)
+ *out << " var " << *local << ';' << endl;
+
+ foreach (BasicBlock *bb, f->basicBlocks())
+ if (!bb->isRemoved())
+ print(bb);
+ *out << '}' << endl;
+}
+
+void IRPrinter::print(BasicBlock *bb)
+{
+ bool prevPrintElse = false;
+ std::swap(printElse, prevPrintElse);
+ printBlockStart(bb);
+
+ foreach (Stmt *s, bb->statements()) {
+ QByteArray str;
+ QBuffer buf(&str);
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ QTextStream *prevOut = &os;
+ std::swap(out, prevOut);
+ if (s->id > 0)
+ *out << s->id << ": ";
+ s->accept(this);
+ if (s->location.isValid()) {
+ out->flush();
+ for (int i = 58 - str.length(); i > 0; --i)
+ *out << ' ';
+ *out << " // line: " << s->location.startLine << " column: " << s->location.startColumn;
+ }
+
+ out->flush();
+ std::swap(out, prevOut);
+
+ *out << " " << str;
+ *out << endl;
+
+ if (s->asCJump()) {
+ *out << " else goto L" << s->asCJump()->iffalse->index() << ";" << endl;
+ }
+ }
+
+ std::swap(printElse, prevPrintElse);
+}
+
+void IRPrinter::visitExp(Exp *s)
+{
+ *out << "(void) ";
+ s->expr->accept(this);
+ *out << ';';
+}
+
+void IRPrinter::visitMove(Move *s)
+{
+ s->target->accept(this);
+ *out << ' ';
+ if (s->swap)
+ *out << "<=> ";
+ else
+ *out << "= ";
+ s->source->accept(this);
+ *out << ';';
+}
+
+void IRPrinter::visitJump(Jump *s)
+{
+ *out << "goto L" << s->target->index() << ';';
+}
+
+void IRPrinter::visitCJump(CJump *s)
+{
+ *out << "if (";
+ s->cond->accept(this);
+ *out << ") goto L" << s->iftrue->index() << ';';
+ if (printElse)
+ *out << " else goto L" << s->iffalse->index() << ';';
+}
+
+void IRPrinter::visitRet(Ret *s)
+{
+ *out << "return";
+ if (s->expr) {
+ *out << ' ';
+ s->expr->accept(this);
+ }
+ *out << ';';
+}
+
+void IRPrinter::visitPhi(Phi *s)
+{
+ s->targetTemp->accept(this);
+ *out << " = phi(";
+ for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) {
+ if (i > 0)
+ *out << ", ";
+ if (s->d->incoming[i])
+ s->d->incoming[i]->accept(this);
+ }
+ *out << ");";
+}
+
+void IRPrinter::visitConst(Const *e)
+{
+ if (e->type != UndefinedType && e->type != NullType)
+ *out << dumpStart(e);
+ switch (e->type) {
+ case QV4::IR::UndefinedType:
+ *out << "undefined";
+ break;
+ case QV4::IR::NullType:
+ *out << "null";
+ break;
+ case QV4::IR::BoolType:
+ *out << (e->value ? "true" : "false");
+ break;
+ case QV4::IR::MissingType:
+ *out << "missing";
+ break;
+ default:
+ if (int(e->value) == 0 && int(e->value) == e->value) {
+ if (isNegative(e->value))
+ *out << "-0";
+ else
+ *out << "0";
+ } else {
+ *out << QString::number(e->value, 'g', 16);
+ }
+ break;
+ }
+ if (e->type != UndefinedType && e->type != NullType)
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitString(String *e)
+{
+ *out << '"' << escape(*e->value) << '"';
+}
+
+void IRPrinter::visitRegExp(RegExp *e)
+{
+ char f[3];
+ int i = 0;
+ if (e->flags & RegExp::RegExp_Global)
+ f[i++] = 'g';
+ if (e->flags & RegExp::RegExp_IgnoreCase)
+ f[i++] = 'i';
+ if (e->flags & RegExp::RegExp_Multiline)
+ f[i++] = 'm';
+ f[i] = 0;
+
+ *out << '/' << *e->value << '/' << f;
+}
+
+void IRPrinter::visitName(Name *e)
+{
+ if (e->id)
+ *out << *e->id;
+ else
+ *out << builtin_to_string(e->builtin);
+}
+
+void IRPrinter::visitTemp(Temp *e)
+{
+ *out << dumpStart(e);
+ switch (e->kind) {
+ case Temp::Formal: *out << '#' << e->index; break;
+ case Temp::ScopedFormal: *out << '#' << e->index
+ << '@' << e->scope; break;
+ case Temp::Local: *out << '$' << e->index; break;
+ case Temp::ScopedLocal: *out << '$' << e->index
+ << '@' << e->scope; break;
+ case Temp::VirtualRegister: *out << '%' << e->index; break;
+ case Temp::PhysicalRegister: *out << (e->type == DoubleType ? "fp" : "r")
+ << e->index; break;
+ case Temp::StackSlot: *out << '&' << e->index; break;
+ default: *out << "INVALID";
+ }
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitClosure(Closure *e)
+{
+ QString name = e->functionName ? *e->functionName : QString();
+ if (name.isEmpty())
+ name.sprintf("%x", e->value);
+ *out << "closure(" << name << ')';
+}
+
+void IRPrinter::visitConvert(Convert *e)
+{
+ *out << dumpStart(e);
+ *out << "convert(";
+ e->expr->accept(this);
+ *out << ')' << dumpEnd(e);
+}
+
+void IRPrinter::visitUnop(Unop *e)
+{
+ *out << dumpStart(e) << opname(e->op);
+ e->expr->accept(this);
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitBinop(Binop *e)
+{
+ *out << dumpStart(e);
+ e->left->accept(this);
+ *out << ' ' << opname(e->op) << ' ';
+ e->right->accept(this);
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitCall(Call *e)
+{
+ e->base->accept(this);
+ *out << '(';
+ for (ExprList *it = e->args; it; it = it->next) {
+ if (it != e->args)
+ *out << ", ";
+ it->expr->accept(this);
+ }
+ *out << ')';
+}
+
+void IRPrinter::visitNew(New *e)
+{
+ *out << "new ";
+ e->base->accept(this);
+ *out << '(';
+ for (ExprList *it = e->args; it; it = it->next) {
+ if (it != e->args)
+ *out << ", ";
+ it->expr->accept(this);
+ }
+ *out << ')';
+}
+
+void IRPrinter::visitSubscript(Subscript *e)
+{
+ e->base->accept(this);
+ *out << '[';
+ e->index->accept(this);
+ *out << ']';
+}
+
+void IRPrinter::visitMember(Member *e)
+{
+ if (e->kind != Member::MemberOfEnum
+ && e->attachedPropertiesIdOrEnumValue != 0 && !e->base->asTemp())
+ *out << "[[attached property from " << e->attachedPropertiesIdOrEnumValue << "]]";
+ else
+ e->base->accept(this);
+ *out << '.' << *e->name;
+#ifndef V4_BOOTSTRAP
+ if (e->property)
+ *out << " (meta-property " << e->property->coreIndex
+ << " <" << QMetaType::typeName(e->property->propType)
+ << ">)";
+#endif
+}
+
+QString IRPrinter::escape(const QString &s)
+{
+ QString r;
+ for (int i = 0; i < s.length(); ++i) {
+ const QChar ch = s.at(i);
+ if (ch == QLatin1Char('\n'))
+ r += QStringLiteral("\\n");
+ else if (ch == QLatin1Char('\r'))
+ r += QStringLiteral("\\r");
+ else if (ch == QLatin1Char('\\'))
+ r += QStringLiteral("\\\\");
+ else if (ch == QLatin1Char('"'))
+ r += QStringLiteral("\\\"");
+ else if (ch == QLatin1Char('\''))
+ r += QStringLiteral("\\'");
+ else
+ r += ch;
+ }
+ return r;
+}
+
+QString IRPrinter::dumpStart(const Expr *e)
+{
+ if (e->type == UnknownType)
+ return QString();
+
+ QString result = typeName(e->type);
+#ifndef V4_BOOTSTRAP
+ const Temp *temp = const_cast<Expr*>(e)->asTemp();
+ if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
+ result += QLatin1Char('<');
+ result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(temp->memberResolver.data)->className());
+ result += QLatin1Char('>');
+ }
+#endif
+ result += QLatin1Char('{');
+ return result;
+}
+
+const char *IRPrinter::dumpEnd(const Expr *e)
+{
+ if (e->type == UnknownType)
+ return "";
+ else
+ return "}";
+}
+
+void IRPrinter::printBlockStart(BasicBlock *bb)
+{
+ if (bb->isRemoved()) {
+ *out << "(block has been removed)";
+ return;
+ }
+
+ QByteArray str;
+ str.append('L');
+ str.append(QByteArray::number(bb->index()));
+ str.append(':');
+ if (bb->catchBlock) {
+ str.append(" (exception handler L");
+ str.append(QByteArray::number(bb->catchBlock->index()));
+ str.append(')');
+ }
+ for (int i = 66 - str.length(); i; --i)
+ str.append(' ');
+ *out << str;
+
+ *out << "// predecessor blocks:";
+ foreach (BasicBlock *in, bb->in)
+ *out << " L" << in->index();
+ if (bb->in.isEmpty())
+ *out << " (none)";
+ if (BasicBlock *container = bb->containingGroup())
+ *out << "; container block: L" << container->index();
+ if (bb->isGroupStart())
+ *out << "; group start";
+ *out << endl;
+}
+
} // end of namespace IR
} // end of namespace QV4
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 9eff90dd30..2940fd50f4 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -268,7 +268,6 @@ struct Q_AUTOTEST_EXPORT Expr {
virtual New *asNew() { return 0; }
virtual Subscript *asSubscript() { return 0; }
virtual Member *asMember() { return 0; }
- virtual void dump(QTextStream &out) const = 0;
};
struct ExprList {
@@ -295,8 +294,6 @@ struct Const: Expr {
virtual void accept(ExprVisitor *v) { v->visitConst(this); }
virtual Const *asConst() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct String: Expr {
@@ -309,9 +306,6 @@ struct String: Expr {
virtual void accept(ExprVisitor *v) { v->visitString(this); }
virtual String *asString() { return this; }
-
- virtual void dump(QTextStream &out) const;
- static QString escape(const QString &s);
};
struct RegExp: Expr {
@@ -333,8 +327,6 @@ struct RegExp: Expr {
virtual void accept(ExprVisitor *v) { v->visitRegExp(this); }
virtual RegExp *asRegExp() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Name: Expr {
@@ -376,8 +368,6 @@ struct Name: Expr {
virtual void accept(ExprVisitor *v) { v->visitName(this); }
virtual bool isLValue() { return true; }
virtual Name *asName() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Q_AUTOTEST_EXPORT Temp: Expr {
@@ -415,8 +405,6 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
virtual void accept(ExprVisitor *v) { v->visitTemp(this); }
virtual bool isLValue() { return !isReadOnly; }
virtual Temp *asTemp() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
inline bool operator==(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
@@ -442,8 +430,6 @@ struct Closure: Expr {
virtual void accept(ExprVisitor *v) { v->visitClosure(this); }
virtual Closure *asClosure() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Convert: Expr {
@@ -457,8 +443,6 @@ struct Convert: Expr {
virtual void accept(ExprVisitor *v) { v->visitConvert(this); }
virtual Convert *asConvert() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Unop: Expr {
@@ -473,8 +457,6 @@ struct Unop: Expr {
virtual void accept(ExprVisitor *v) { v->visitUnop(this); }
virtual Unop *asUnop() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Binop: Expr {
@@ -491,8 +473,6 @@ struct Binop: Expr {
virtual void accept(ExprVisitor *v) { v->visitBinop(this); }
virtual Binop *asBinop() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Call: Expr {
@@ -513,8 +493,6 @@ struct Call: Expr {
virtual void accept(ExprVisitor *v) { v->visitCall(this); }
virtual Call *asCall() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct New: Expr {
@@ -535,8 +513,6 @@ struct New: Expr {
virtual void accept(ExprVisitor *v) { v->visitNew(this); }
virtual New *asNew() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Subscript: Expr {
@@ -552,8 +528,6 @@ struct Subscript: Expr {
virtual void accept(ExprVisitor *v) { v->visitSubscript(this); }
virtual bool isLValue() { return true; }
virtual Subscript *asSubscript() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Member: Expr {
@@ -605,16 +579,9 @@ struct Member: Expr {
virtual void accept(ExprVisitor *v) { v->visitMember(this); }
virtual bool isLValue() { return true; }
virtual Member *asMember() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Stmt {
- enum Mode {
- HIR,
- MIR
- };
-
struct Data {
QVector<Expr *> incoming; // used by Phi nodes
};
@@ -641,7 +608,6 @@ struct Stmt {
virtual CJump *asCJump() { return 0; }
virtual Ret *asRet() { return 0; }
virtual Phi *asPhi() { return 0; }
- virtual void dump(QTextStream &out, Mode mode = HIR) = 0;
private: // For memory management in BasicBlock
friend struct BasicBlock;
@@ -662,7 +628,6 @@ struct Exp: Stmt {
virtual void accept(StmtVisitor *v) { v->visitExp(this); }
virtual Exp *asExp() { return this; }
- virtual void dump(QTextStream &out, Mode);
};
struct Move: Stmt {
@@ -680,7 +645,6 @@ struct Move: Stmt {
virtual void accept(StmtVisitor *v) { v->visitMove(this); }
virtual Move *asMove() { return this; }
- virtual void dump(QTextStream &out, Mode mode = HIR);
};
struct Jump: Stmt {
@@ -695,8 +659,6 @@ struct Jump: Stmt {
virtual void accept(StmtVisitor *v) { v->visitJump(this); }
virtual Jump *asJump() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct CJump: Stmt {
@@ -715,8 +677,6 @@ struct CJump: Stmt {
virtual void accept(StmtVisitor *v) { v->visitCJump(this); }
virtual CJump *asCJump() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct Ret: Stmt {
@@ -731,8 +691,6 @@ struct Ret: Stmt {
virtual void accept(StmtVisitor *v) { v->visitRet(this); }
virtual Ret *asRet() { return this; }
-
- virtual void dump(QTextStream &out, Mode);
};
struct Phi: Stmt {
@@ -740,8 +698,6 @@ struct Phi: Stmt {
virtual void accept(StmtVisitor *v) { v->visitPhi(this); }
virtual Phi *asPhi() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct Q_QML_PRIVATE_EXPORT Module {
@@ -871,8 +827,6 @@ public:
Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
Stmt *RET(Temp *expr);
- void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
-
BasicBlock *containingGroup() const
{
Q_ASSERT(!isRemoved());
@@ -1024,8 +978,6 @@ struct Function {
int liveBasicBlocksCount() const;
- void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
-
void removeSharedExpressions();
int indexOfArgument(const QStringRef &string) const;
@@ -1116,6 +1068,52 @@ private:
IR::Expr *cloned;
};
+class IRPrinter: public StmtVisitor, public ExprVisitor
+{
+public:
+ IRPrinter(QTextStream *out);
+ virtual ~IRPrinter();
+
+ void print(Stmt *s);
+ void print(Expr *e);
+ void print(const Expr &e);
+
+ virtual void print(Function *f);
+ virtual void print(BasicBlock *bb);
+
+ virtual void visitExp(Exp *s);
+ virtual void visitMove(Move *s);
+ virtual void visitJump(Jump *s);
+ virtual void visitCJump(CJump *s);
+ virtual void visitRet(Ret *s);
+ virtual void visitPhi(Phi *s);
+
+ virtual void visitConst(Const *e);
+ virtual void visitString(String *e);
+ virtual void visitRegExp(RegExp *e);
+ virtual void visitName(Name *e);
+ virtual void visitTemp(Temp *e);
+ virtual void visitClosure(Closure *e);
+ virtual void visitConvert(Convert *e);
+ virtual void visitUnop(Unop *e);
+ virtual void visitBinop(Binop *e);
+ virtual void visitCall(Call *e);
+ virtual void visitNew(New *e);
+ virtual void visitSubscript(Subscript *e);
+ virtual void visitMember(Member *e);
+
+ static QString escape(const QString &s);
+
+protected:
+ QString dumpStart(const Expr *e);
+ const char *dumpEnd(const Expr *e);
+ void printBlockStart(BasicBlock *bb);
+
+protected:
+ QTextStream *out;
+ bool printElse;
+};
+
} // end of namespace IR
} // end of namespace QV4
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 97114b9507..48c68533ba 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -50,7 +50,6 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QSet>
-#include <QtCore/QBuffer>
#include <QtCore/QLinkedList>
#include <QtCore/QStack>
#include <qv4runtime_p.h>
@@ -75,96 +74,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
void showMeTheCode(IR::Function *function)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
- if (showCode) {
- QVector<Stmt *> code;
- QHash<Stmt *, BasicBlock *> leader;
-
- foreach (BasicBlock *block, function->basicBlocks()) {
- if (block->isRemoved() || block->isEmpty())
- continue;
- leader.insert(block->statements().first(), block);
- foreach (Stmt *s, block->statements()) {
- code.append(s);
- }
- }
-
- QString name;
- if (function->name && !function->name->isEmpty())
- name = *function->name;
- else
- name.sprintf("%p", function);
-
- qout << "function " << name << "(";
- for (int i = 0; i < function->formals.size(); ++i) {
- if (i != 0)
- qout << ", ";
- qout << *function->formals.at(i);
- }
- qout << ")" << endl
- << "{" << endl;
-
- foreach (const QString *local, function->locals) {
- qout << " var " << *local << ';' << endl;
- }
-
- for (int i = 0; i < code.size(); ++i) {
- Stmt *s = code.at(i);
- Q_ASSERT(s);
-
- if (BasicBlock *bb = leader.value(s)) {
- qout << endl;
- QByteArray str;
- str.append('L');
- str.append(QByteArray::number(bb->index()));
- str.append(':');
- if (bb->catchBlock) {
- str.append(" (exception handler L");
- str.append(QByteArray::number(bb->catchBlock->index()));
- str.append(')');
- }
- for (int i = 66 - str.length(); i; --i)
- str.append(' ');
- qout << str;
- qout << "// predecessor blocks:";
- foreach (BasicBlock *in, bb->in)
- qout << " L" << in->index();
- if (bb->in.isEmpty())
- qout << "(none)";
- if (BasicBlock *container = bb->containingGroup())
- qout << "; container block: L" << container->index();
- if (bb->isGroupStart())
- qout << "; group start";
- qout << endl;
- }
- Stmt *n = (i + 1) < code.size() ? code.at(i + 1) : 0;
-
- QByteArray str;
- QBuffer buf(&str);
- buf.open(QIODevice::WriteOnly);
- QTextStream out(&buf);
- if (s->id > 0)
- out << s->id << ": ";
- s->dump(out, Stmt::MIR);
- if (s->location.isValid()) {
- out.flush();
- for (int i = 58 - str.length(); i > 0; --i)
- out << ' ';
- out << " // line: " << s->location.startLine << " column: " << s->location.startColumn;
- }
-
- out.flush();
-
- qout << " " << str;
- qout << endl;
-
- if (n && s->asCJump()) {
- qout << " else goto L" << s->asCJump()->iffalse->index() << ";" << endl;
- }
- }
-
- qout << "}" << endl
- << endl;
- }
+ if (showCode)
+ IRPrinter(&qout).print(function);
}
class ProcessedBlocks
@@ -1395,14 +1306,15 @@ public:
void dump() const
{
+ IRPrinter printer(&qout);
foreach (const UntypedTemp &var, _defUses.keys()) {
const DefUse &du = _defUses[var];
- var.temp.dump(qout);
+ printer.print(const_cast<Temp *>(&var.temp));
qout<<" -> defined in block "<<du.blockOfStatement->index()<<", statement: ";
- du.defStmt->dump(qout);
+ printer.print(du.defStmt);
qout<<endl<<" uses:"<<endl;
foreach (Stmt *s, du.uses) {
- qout<<" ";s->dump(qout);qout<<endl;
+ qout<<" ";printer.print(s);qout<<endl;
}
}
}
@@ -3581,13 +3493,14 @@ public:
qout << endl;
}
+ IRPrinter printer(&qout);
for (int i = 0, ei = _liveIn.size(); i != ei; ++i) {
qout << "L" << i <<" live-in: ";
QList<Temp> live = QList<Temp>::fromSet(_liveIn.at(i));
std::sort(live.begin(), live.end());
for (int i = 0; i < live.size(); ++i) {
if (i > 0) qout << ", ";
- live[i].dump(qout);
+ printer.print(&live[i]);
}
qout << endl;
}
@@ -3778,7 +3691,7 @@ LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
}
void LifeTimeInterval::dump(QTextStream &out) const {
- _temp.dump(out);
+ IRPrinter(&out).print(const_cast<Temp *>(&_temp));
out << ": ends at " << _end << " with ranges ";
if (_ranges.isEmpty())
out << "(none)";
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index b5765cd589..a66eab005f 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -44,9 +44,9 @@
#include <algorithm>
-//#define DEBUG_REGALLOC
-
namespace {
+enum { DebugRegAlloc = 0 };
+
struct Use {
enum RegisterFlag { MustHaveRegister = 0, CouldHaveRegister = 1 };
unsigned flag : 1;
@@ -143,16 +143,19 @@ public:
_hints[t].append(hint);
}
-#ifdef DEBUG_REGALLOC
void dump() const
{
+ if (!DebugRegAlloc)
+ return;
+
QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinter printer(&qout);
qout << "RegAllocInfo:" << endl << "Defs/uses:" << endl;
QList<Temp> temps = _defs.keys();
std::sort(temps.begin(), temps.end());
foreach (const Temp &t, temps) {
- t.dump(qout);
+ printer.print(t);
qout << " def at " << _defs[t].defStmt << " ("
<< (_defs[t].canHaveReg ? "can" : "can NOT")
<< " have a register, and "
@@ -181,17 +184,16 @@ public:
std::sort(hinted.begin(), hinted.end());
foreach (const Temp &t, hinted) {
qout << "\t";
- t.dump(qout);
+ printer.print(t);
qout << ": ";
QList<Temp> hints = _hints[t];
for (int i = 0; i < hints.size(); ++i) {
if (i > 0) qout << ", ";
- hints[i].dump(qout);
+ printer.print(hints[i]);
}
qout << endl;
}
}
-#endif // DEBUG_REGALLOC
protected: // IRDecoder
virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Temp *) {}
@@ -747,25 +749,25 @@ private:
cleanOldIntervals();
_liveAtEnd[bb] = _intervalForTemp.values();
-#ifdef DEBUG_REGALLOC
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Intervals live at the start of L" << bb->index << ":" << endl;
- if (_liveAtStart[bb].isEmpty())
- os << "\t(none)" << endl;
- foreach (const LifeTimeInterval *i, _liveAtStart[bb]) {
- os << "\t";
- i->dump(os);
- os << endl;
- }
- os << "Intervals live at the end of L" << bb->index << ":" << endl;
- if (_liveAtEnd[bb].isEmpty())
- os << "\t(none)" << endl;
- foreach (const LifeTimeInterval *i, _liveAtEnd[bb]) {
- os << "\t";
- i->dump(os);
- os << endl;
+ if (DebugRegAlloc) {
+ QTextStream os(stdout, QIODevice::WriteOnly);
+ os << "Intervals live at the start of L" << bb->index() << ":" << endl;
+ if (_liveAtStart[bb].isEmpty())
+ os << "\t(none)" << endl;
+ foreach (const LifeTimeInterval *i, _liveAtStart[bb]) {
+ os << "\t";
+ i->dump(os);
+ os << endl;
+ }
+ os << "Intervals live at the end of L" << bb->index() << ":" << endl;
+ if (_liveAtEnd[bb].isEmpty())
+ os << "\t(none)" << endl;
+ foreach (const LifeTimeInterval *i, _liveAtEnd[bb]) {
+ os << "\t";
+ i->dump(os);
+ os << endl;
+ }
}
-#endif
bb->setStatements(newStatements);
}
@@ -842,10 +844,10 @@ private:
void resolveEdge(BasicBlock *predecessor, BasicBlock *successor)
{
-#ifdef DEBUG_REGALLOC
- Optimizer::showMeTheCode(_function);
- qDebug() << "Resolving edge" << predecessor->index << "->" << successor->index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ Optimizer::showMeTheCode(_function);
+ qDebug() << "Resolving edge" << predecessor->index() << "->" << successor->index();
+ }
MoveMapping mapping;
@@ -972,9 +974,8 @@ private:
}
mapping.order();
-#ifdef DEBUG_REGALLOC
- mapping.dump();
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ mapping.dump();
bool insertIntoPredecessor = successor->in.size() > 1;
mapping.insertMoves(insertIntoPredecessor ? predecessor : successor, _function,
@@ -1091,9 +1092,8 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
_assignedSpillSlots.reserve(function->tempCount);
_activeSpillSlots.resize(function->tempCount);
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** Running regalloc for function" << (function->name ? qPrintable(*function->name) : "NO NAME") << "***";
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** Running regalloc for function" << (function->name ? qPrintable(*function->name) : "NO NAME") << "***";
_unhandled = opt.lifeTimeIntervals();
_handled.reserve(_unhandled.size());
@@ -1101,8 +1101,7 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
_info.reset(new RegAllocInfo);
_info->collect(function);
-#ifdef DEBUG_REGALLOC
- {
+ if (DebugRegAlloc) {
QTextStream qout(stdout, QIODevice::WriteOnly);
qout << "Ranges:" << endl;
QVector<LifeTimeInterval> intervals = _unhandled;
@@ -1111,9 +1110,8 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
r.dump(qout);
qout << endl;
}
+ _info->dump();
}
- _info->dump();
-#endif // DEBUG_REGALLOC
prepareRanges();
@@ -1121,9 +1119,8 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
linearScan();
-#ifdef DEBUG_REGALLOC
- dump();
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ dump();
std::sort(_handled.begin(), _handled.end(), LifeTimeInterval::lessThan);
ResolutionPhase(_handled, function, _info.data(), _assignedSpillSlots, _normalRegisters, _fpRegisters).run();
@@ -1246,10 +1243,9 @@ void RegisterAllocator::linearScan()
} else {
assignSpillSlot(current.temp(), current.start(), current.end());
_inactive += current;
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating stack slot" << _assignedSpillSlots[current.temp()]
- << "for %" << current.temp().index << "as it cannot be loaded in a register";
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating stack slot" << _assignedSpillSlots[current.temp()]
+ << "for %" << current.temp().index << "as it cannot be loaded in a register";
}
}
@@ -1350,24 +1346,21 @@ void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current, const int
if (freeUntilPos_reg == 0) {
// no register available without spilling
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** no register available for %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** no register available for %" << current.temp().index;
return;
} else if (current.end() < freeUntilPos_reg) {
// register available for the whole interval
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating register" << reg << "for the whole interval of %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating register" << reg << "for the whole interval of %" << current.temp().index;
current.setReg(reg);
_lastAssignedRegister.insert(current.temp(), reg);
} else {
// register available for the first part of the interval
current.setReg(reg);
_lastAssignedRegister.insert(current.temp(), reg);
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating register" << reg << "for the first part of interval of %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating register" << reg << "for the first part of interval of %" << current.temp().index;
split(current, freeUntilPos_reg, true);
}
}
@@ -1427,19 +1420,19 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current, const int
if (current.start() > nextUsePos_reg) {
// all other intervals are used before current, so it is best to spill current itself
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "*** splitting current for range ";current.dump(out);out<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "*** splitting current for range ";current.dump(out);out<<endl;
+ }
Q_ASSERT(!_info->useMustHaveReg(current.temp(), position));
split(current, position + 1, true);
_inactive.append(current);
} else {
// spill intervals that currently block reg
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "*** spilling intervals that block reg "<<reg<<" for interval ";current.dump(out);out<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "*** spilling intervals that block reg "<<reg<<" for interval ";current.dump(out);out<<endl;
+ }
current.setReg(reg);
_lastAssignedRegister.insert(current.temp(), reg);
LifeTimeInterval *nextUse = nextUseRangeForReg[reg];
@@ -1463,9 +1456,10 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current, const int
: _fixedRegisterRanges.at(reg);
int ni = nextIntersection(current, fixedRegRange, position);
if (ni != -1) {
-#ifdef DEBUG_REGALLOC
- out << "***-- current range intersects with a fixed reg use at "<<ni<<", so splitting it."<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***-- current range intersects with a fixed reg use at "<<ni<<", so splitting it."<<endl;
+ }
split(current, ni, true);
}
}
@@ -1544,18 +1538,19 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
{ // TODO: check if we can always skip the optional register uses
Q_ASSERT(!current.isFixedInterval());
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
+ }
assignSpillSlot(current.temp(), current.start(), current.end());
const int defPosition = _info->def(current.temp());
if (beforePosition < defPosition) {
-#ifdef DEBUG_REGALLOC
- out << "***** split before position is before or at definition, so not splitting."<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***** split before position is before or at definition, so not splitting."<<endl;
+ }
return;
}
@@ -1581,14 +1576,13 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
Q_ASSERT(lastUse < beforePosition);
-#ifdef DEBUG_REGALLOC
- out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
-#endif // DEBUG_REGALLOC
LifeTimeInterval newInterval = current.split(lastUse, nextUse);
-#ifdef DEBUG_REGALLOC
- out << "***** new interval: "; newInterval.dump(out); out << endl;
- out << "***** preceding interval: "; current.dump(out); out << endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
+ out << "***** new interval: "; newInterval.dump(out); out << endl;
+ out << "***** preceding interval: "; current.dump(out); out << endl;
+ }
if (newInterval.isValid()) {
if (current.reg() != LifeTimeInterval::Invalid)
_info->addHint(current.temp(), current.reg());
@@ -1634,7 +1628,8 @@ void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
void RegisterAllocator::dump() const
{
-#ifdef DEBUG_REGALLOC
+ if (!DebugRegAlloc)
+ return;
QTextStream qout(stdout, QIODevice::WriteOnly);
{
@@ -1648,6 +1643,7 @@ void RegisterAllocator::dump() const
}
{
+ IRPrinter printer(&qout);
qout << "Spill slots:" << endl;
QList<Temp> temps = _assignedSpillSlots.keys();
if (temps.isEmpty())
@@ -1655,9 +1651,8 @@ void RegisterAllocator::dump() const
std::sort(temps.begin(), temps.end());
foreach (const Temp &t, temps) {
qout << "\t";
- t.dump(qout);
+ printer.print(t);
qout << " -> " << _assignedSpillSlots[t] << endl;
}
}
-#endif // DEBUG_REGALLOC
}
diff --git a/src/quick/accessible/accessible.pri b/src/quick/accessible/accessible.pri
new file mode 100644
index 0000000000..88ff747488
--- /dev/null
+++ b/src/quick/accessible/accessible.pri
@@ -0,0 +1,16 @@
+
+QT += core-private gui-private qml-private
+
+#DEFINES+=Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
+
+SOURCES += \
+ $$PWD/qqmlaccessible.cpp \
+ $$PWD/qaccessiblequickview.cpp \
+ $$PWD/qaccessiblequickitem.cpp \
+ $$PWD/qquickaccessiblefactory.cpp \
+
+HEADERS += \
+ $$PWD/qqmlaccessible_p.h \
+ $$PWD/qaccessiblequickview_p.h \
+ $$PWD/qaccessiblequickitem_p.h \
+ $$PWD/qquickaccessiblefactory_p.h \
diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 164144c052..c8b2d9ec3e 100644
--- a/src/plugins/accessible/quick/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qaccessiblequickitem.h"
+#include "qaccessiblequickitem_p.h"
#include <QtGui/qtextdocument.h>
diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.h b/src/quick/accessible/qaccessiblequickitem_p.h
index b486720c68..d1facf2199 100644
--- a/src/plugins/accessible/quick/qaccessiblequickitem.h
+++ b/src/quick/accessible/qaccessiblequickitem_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -44,7 +44,7 @@
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
-#include "qqmlaccessible.h"
+#include <QtQuick/private/qqmlaccessible_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/accessible/quick/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp
index 1240b2ef4c..05e37d6240 100644
--- a/src/plugins/accessible/quick/qaccessiblequickview.cpp
+++ b/src/quick/accessible/qaccessiblequickview.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,15 +39,15 @@
**
****************************************************************************/
-#include "qaccessiblequickview.h"
+#include "qaccessiblequickview_p.h"
#include <QtGui/qguiapplication.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquickitem_p.h>
-#include "qaccessiblequickitem.h"
-#include "qqmlaccessible.h"
+#include "qaccessiblequickitem_p.h"
+#include "qqmlaccessible_p.h"
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/plugins/accessible/quick/qaccessiblequickview.h b/src/quick/accessible/qaccessiblequickview_p.h
index 41c34c5432..f14d4c9584 100644
--- a/src/plugins/accessible/quick/qaccessiblequickview.h
+++ b/src/quick/accessible/qaccessiblequickview_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
diff --git a/src/plugins/accessible/shared/qqmlaccessible.cpp b/src/quick/accessible/qqmlaccessible.cpp
index ecf4e56acf..abe94537a9 100644
--- a/src/plugins/accessible/shared/qqmlaccessible.cpp
+++ b/src/quick/accessible/qqmlaccessible.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <qnamespace.h>
-#include "qqmlaccessible.h"
+#include "qqmlaccessible_p.h"
#ifndef QT_NO_ACCESSIBILITY
@@ -148,8 +148,8 @@ void QQmlAccessible::doAction(const QString &actionName)
{
// Look for and call the accessible[actionName]Action() function on the item.
// This allows for overriding the default action handling.
- const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action";
- if (object()->metaObject()->indexOfMethod(functionName + "()") != -1) {
+ const QByteArray functionName = QByteArrayLiteral("accessible") + actionName.toLatin1() + QByteArrayLiteral("Action");
+ if (object()->metaObject()->indexOfMethod(QByteArray(functionName + QByteArrayLiteral("()"))) != -1) {
QMetaObject::invokeMethod(object(), functionName);
return;
}
diff --git a/src/plugins/accessible/shared/qqmlaccessible.h b/src/quick/accessible/qqmlaccessible_p.h
index b6da016b2d..b6da016b2d 100644
--- a/src/plugins/accessible/shared/qqmlaccessible.h
+++ b/src/quick/accessible/qqmlaccessible_p.h
diff --git a/src/plugins/accessible/quick/main.cpp b/src/quick/accessible/qquickaccessiblefactory.cpp
index 6c7be155ce..d0e7f0f5e8 100644
--- a/src/plugins/accessible/quick/main.cpp
+++ b/src/quick/accessible/qquickaccessiblefactory.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,50 +39,16 @@
**
****************************************************************************/
+#include "qquickaccessiblefactory_p.h"
-#include "qqmlaccessible.h"
-#include "qaccessiblequickview.h"
-#include "qaccessiblequickitem.h"
-
-#include <QtQuick/QQuickWindow>
-#include <QtQuick/QQuickItem>
+#include "qaccessiblequickview_p.h"
+#include "qaccessiblequickitem_p.h"
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquickaccessibleattached_p.h>
-
-#include <qaccessibleplugin.h>
-#include <qvariant.h>
-#include <qplugin.h>
-#include <qaccessible.h>
-
-#ifndef QT_NO_ACCESSIBILITY
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
-class AccessibleQuickFactory : public QAccessiblePlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QAccessibleFactoryInterface" FILE "accessible.json")
-
-public:
- AccessibleQuickFactory();
-
- QStringList keys() const;
- QAccessibleInterface *create(const QString &classname, QObject *object);
-};
-
-AccessibleQuickFactory::AccessibleQuickFactory()
-{
-}
-
-QStringList AccessibleQuickFactory::keys() const
-{
- QStringList list;
- list << QLatin1String("QQuickWindow");
- list << QLatin1String("QQuickItem");
- return list;
-}
-
-QAccessibleInterface *AccessibleQuickFactory::create(const QString &classname, QObject *object)
+QAccessibleInterface *qQuickAccessibleFactory(const QString &classname, QObject *object)
{
if (classname == QLatin1String("QQuickWindow")) {
return new QAccessibleQuickWindow(qobject_cast<QQuickWindow *>(object));
@@ -98,8 +64,5 @@ QAccessibleInterface *AccessibleQuickFactory::create(const QString &classname, Q
return 0;
}
+#endif
QT_END_NAMESPACE
-
-#include "main.moc"
-
-#endif // QT_NO_ACCESSIBILITY
diff --git a/src/quick/accessible/qquickaccessiblefactory_p.h b/src/quick/accessible/qquickaccessiblefactory_p.h
new file mode 100644
index 0000000000..792364b7fa
--- /dev/null
+++ b/src/quick/accessible/qquickaccessiblefactory_p.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKACCESSIBLEFACTORY_H
+#define QQUICKACCESSIBLEFACTORY_H
+
+#include <QtGui/qaccessible.h>
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
+
+QAccessibleInterface *qQuickAccessibleFactory(const QString &classname, QObject *object);
+
+#endif
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/doc/snippets/qml/itemGrab.qml b/src/quick/doc/snippets/qml/itemGrab.qml
new file mode 100644
index 0000000000..4ceaea6133
--- /dev/null
+++ b/src/quick/doc/snippets/qml/itemGrab.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ width: 320
+ height: 480
+
+//! [grab-source]
+Rectangle {
+ id: source
+ width: 100
+ height: 100
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+}
+//! [grab-source]
+
+//! [grab-image-target]
+Image {
+ id: image
+}
+//! [grab-image-target]
+ Timer {
+ repeat: false
+ running: true
+ interval: 1000
+ onTriggered: {
+//! [grab-to-file]
+
+ // ...
+ source.grabToImage(function(result) {
+ result.save("something.png");
+ });
+//! [grab-to-file]
+
+//! [grab-to-cache]
+
+ // ...
+ source.grabToImage(function(result) {
+ image.source = result.url;
+ },
+ Qt.size(50, 50));
+//! [grab-to-cache]
+ }
+ }
+}
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index 7fc9bea032..3f9de28c9d 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -322,7 +322,8 @@ set of Particle System types for Qt Quick 2
/*!
\qmlmodule QtQuick 2.2
-\brief The Provides graphical primitives for use in QML.
+\title Qt Quick QML Types
+\brief This module provides graphical primitives for use in QML.
The \l{Qt Quick} module provides graphical primitive types. They can be used with the following import
\code
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index cb378b424b..add909d0cb 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -75,7 +75,8 @@ HEADERS += \
$$PWD/qquickitemviewtransition_p.h \
$$PWD/qquickscreen_p.h \
$$PWD/qquickwindowmodule_p.h \
- $$PWD/qquickframebufferobject.h
+ $$PWD/qquickframebufferobject.h \
+ $$PWD/qquickitemgrabresult.h
SOURCES += \
$$PWD/qquickevents.cpp \
@@ -128,7 +129,8 @@ SOURCES += \
$$PWD/qquickitemviewtransition.cpp \
$$PWD/qquickwindowmodule.cpp \
$$PWD/qquickscreen.cpp \
- $$PWD/qquickframebufferobject.cpp
+ $$PWD/qquickframebufferobject.cpp \
+ $$PWD/qquickitemgrabresult.cpp
SOURCES += \
$$PWD/qquickshadereffect.cpp \
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index bfe957e943..533f1cabed 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -498,7 +498,6 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
return 0;
m_sheetSize = QSizeF(image.size());
m_material->texture = window()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
m_spriteEngine->start(0);
m_material->animT = 0;
m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width();
@@ -677,6 +676,7 @@ void QQuickAnimatedSprite::prepareNextFrame()
m_material->animW = w;
m_material->animH = h;
m_material->animT = m_interpolate ? progress : 0.0;
+ m_material->texture->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 6c36032d3c..7e5b357e9c 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -791,7 +791,7 @@ void QQuickDragAttached::startDrag(QQmlV4Function *args)
QQuickDrag::QQuickDrag(QObject *parent)
: QObject(parent), _target(0), _axis(XAndYAxis), _xmin(-FLT_MAX),
_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false),
- _threshold(qApp->styleHints()->startDragDistance())
+ _smoothed(true), _threshold(qApp->styleHints()->startDragDistance())
{
}
@@ -885,6 +885,18 @@ void QQuickDrag::setYmax(qreal m)
emit maximumYChanged();
}
+bool QQuickDrag::smoothed() const
+{
+ return _smoothed;
+}
+
+void QQuickDrag::setSmoothed(bool smooth)
+{
+ if (_smoothed != smooth) {
+ _smoothed = smooth;
+ emit smoothedChanged();
+ }
+}
qreal QQuickDrag::threshold() const
{
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index d9021d0f6d..eebe07469a 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -157,6 +157,7 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
+ Q_PROPERTY(bool smoothed READ smoothed WRITE setSmoothed NOTIFY smoothedChanged)
// Note, threshold was added in QtQuick 2.2 but REVISION is not supported (or needed) for grouped
// properties See QTBUG-33179
Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged RESET resetThreshold)
@@ -185,6 +186,9 @@ public:
qreal ymax() const;
void setYmax(qreal);
+ bool smoothed() const;
+ void setSmoothed(bool smooth);
+
qreal threshold() const;
void setThreshold(qreal);
void resetThreshold();
@@ -206,6 +210,7 @@ Q_SIGNALS:
void maximumYChanged();
void activeChanged();
void filterChildrenChanged();
+ void smoothedChanged();
void thresholdChanged();
private:
@@ -217,6 +222,7 @@ private:
qreal _ymax;
bool _active : 1;
bool _filterChildren: 1;
+ bool _smoothed : 1;
qreal _threshold;
Q_DISABLE_COPY(QQuickDrag)
};
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index ef2eac4b61..da8ca9fd5d 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -59,6 +59,7 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qnumeric.h>
#include <QtGui/qpa/qplatformtheme.h>
+#include <QtCore/qloggingcategory.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlengine_p.h>
@@ -87,25 +88,24 @@ QT_BEGIN_NAMESPACE
static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
#endif
-#ifdef FOCUS_DEBUG
-void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1);
-void printFocusTree(QQuickItem *item, QQuickItem *scope, int depth)
-{
- qWarning()
- << QByteArray(depth, '\t').constData()
- << (scope && QQuickItemPrivate::get(scope)->subFocusItem == item ? '*' : ' ')
- << item->hasFocus()
- << item->hasActiveFocus()
- << item->isFocusScope()
- << item;
- foreach (QQuickItem *child, item->childItems()) {
- printFocusTree(
- child,
- item->isFocusScope() || !scope ? item : scope,
- item->isFocusScope() || !scope ? depth + 1 : depth);
+void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
+{
+ if (DBG_FOCUS().isEnabled(QtDebugMsg)) {
+ qCDebug(DBG_FOCUS)
+ << QByteArray(depth, '\t').constData()
+ << (scope && QQuickItemPrivate::get(scope)->subFocusItem == item ? '*' : ' ')
+ << item->hasFocus()
+ << item->hasActiveFocus()
+ << item->isFocusScope()
+ << item;
+ foreach (QQuickItem *child, item->childItems()) {
+ debugFocusTree(
+ child,
+ item->isFocusScope() || !scope ? item : scope,
+ item->isFocusScope() || !scope ? depth + 1 : depth);
+ }
}
}
-#endif
static void QQuickItem_parentNotifier(QObject *o, qintptr, QQmlNotifier **n)
{
@@ -657,13 +657,13 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
break;
case Qt::Key_Tab:
if (d->tab) {
- setFocusNavigation(d->tab, "tab");
+ setFocusNavigation(d->tab, "tab", Qt::TabFocusReason);
event->accept();
}
break;
case Qt::Key_Backtab:
if (d->backtab) {
- setFocusNavigation(d->backtab, "backtab");
+ setFocusNavigation(d->backtab, "backtab", Qt::BacktabFocusReason);
event->accept();
}
break;
@@ -725,14 +725,15 @@ void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
}
-void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir)
+void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir,
+ Qt::FocusReason reason)
{
QQuickItem *initialItem = currentItem;
bool isNextItem = false;
do {
isNextItem = false;
if (currentItem->isVisible() && currentItem->isEnabled()) {
- currentItem->forceActiveFocus(Qt::OtherFocusReason);
+ currentItem->forceActiveFocus(reason);
} else {
QObject *attached =
qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
@@ -2261,14 +2262,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
if (current == startItem && from == firstFromItem) {
// wrapped around, avoid endless loops
if (originalItem == contentItem) {
-#ifdef FOCUS_DEBUG
- qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
-#endif
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
return item->window()->contentItem();
} else {
-#ifdef FOCUS_DEBUG
- qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
-#endif
+ qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
return startItem;
}
}
@@ -2507,6 +2504,12 @@ void QQuickItem::stackAfter(const QQuickItem *sibling)
*/
/*!
+ \qmlproperty Window QtQuick::Item::window
+ \since 5.4
+ This property holds the window in which the item is rendered.
+ */
+
+/*!
Returns the window in which this item is rendered.
The item does not have a window until it has been assigned into a scene. The
@@ -5390,6 +5393,17 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
emit q->enabledChanged();
}
+bool QQuickItemPrivate::isTransparentForPositioner() const
+{
+ return extra.isAllocated() && extra.value().transparentForPositioner;
+}
+
+void QQuickItemPrivate::setTransparentForPositioner(bool transparent)
+{
+ extra.value().transparentForPositioner = transparent;
+}
+
+
QString QQuickItemPrivate::dirtyToString() const
{
#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
@@ -5818,10 +5832,6 @@ qreal QQuickItem::y() const
}
/*!
- \property QQuickItem::pos
- \internal
- */
-/*!
\internal
*/
QPointF QQuickItem::position() const
@@ -7249,6 +7259,7 @@ void QQuickItemLayer::activate()
{
Q_ASSERT(!m_effectSource);
m_effectSource = new QQuickShaderEffectSource();
+ QQuickItemPrivate::get(m_effectSource)->setTransparentForPositioner(true);
QQuickItem *parentItem = m_item->parentItem();
if (parentItem) {
@@ -7314,6 +7325,7 @@ void QQuickItemLayer::activateEffect()
}
m_effect->setVisible(m_item->isVisible());
m_effect->setProperty(m_name, qVariantFromValue<QObject *>(m_effectSource));
+ QQuickItemPrivate::get(m_effect)->setTransparentForPositioner(true);
m_effectComponent->completeCreate();
}
@@ -7630,7 +7642,8 @@ QQuickItemPrivate::ExtraData::ExtraData()
#endif
effectRefCount(0), hideRefCount(0),
opacityNode(0), clipNode(0), rootNode(0), beforePaintNode(0),
- acceptedMouseButtons(0), origin(QQuickItem::Center)
+ acceptedMouseButtons(0), origin(QQuickItem::Center),
+ transparentForPositioner(false)
{
}
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 2b08cc2598..91940c7cf0 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -52,6 +52,7 @@
#include <QtGui/qfont.h>
#include <QtGui/qaccessible.h>
+
QT_BEGIN_NAMESPACE
class QQuickItem;
@@ -92,6 +93,7 @@ class QTouchEvent;
class QSGNode;
class QSGTransformNode;
class QSGTextureProvider;
+class QQuickItemGrabResult;
class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
{
@@ -145,6 +147,8 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged)
Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged)
+ Q_PROPERTY(QQuickWindow *window READ window NOTIFY windowChanged REVISION 2)
+
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL)
Q_ENUMS(TransformOrigin)
@@ -308,6 +312,10 @@ public:
bool keepTouchGrab() const;
void setKeepTouchGrab(bool);
+ // implemented in qquickitemgrabresult.cpp
+ Q_REVISION(2) Q_INVOKABLE bool grabToImage(const QJSValue &callback, const QSize &targetSize = QSize());
+ QSharedPointer<QQuickItemGrabResult> grabToImage(const QSize &targetSize = QSize());
+
Q_INVOKABLE virtual bool contains(const QPointF &point) const;
QTransform itemTransform(QQuickItem *, bool *) const;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 96cb9e8843..dbd4d51941 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -368,6 +368,7 @@ public:
Qt::MouseButtons acceptedMouseButtons;
QQuickItem::TransformOrigin origin:5;
+ uint transparentForPositioner : 1;
QObjectList resourcesList;
};
@@ -545,6 +546,9 @@ public:
void deliverInputMethodEvent(QInputMethodEvent *);
#endif
+ bool isTransparentForPositioner() const;
+ void setTransparentForPositioner(bool trans);
+
bool calcEffectiveVisible() const;
bool setEffectiveVisibleRecur(bool);
bool calcEffectiveEnable() const;
@@ -686,7 +690,8 @@ Q_SIGNALS:
private:
virtual void keyPressed(QKeyEvent *event, bool post);
virtual void keyReleased(QKeyEvent *event, bool post);
- void setFocusNavigation(QQuickItem *currentItem, const char *dir);
+ void setFocusNavigation(QQuickItem *currentItem, const char *dir,
+ Qt::FocusReason reason = Qt::OtherFocusReason);
};
class QQuickLayoutMirroringAttached : public QObject
diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp
new file mode 100644
index 0000000000..93b9261c44
--- /dev/null
+++ b/src/quick/items/qquickitemgrabresult.cpp
@@ -0,0 +1,399 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickitemgrabresult.h"
+
+#include "qquickwindow.h"
+#include "qquickitem.h"
+#include "qquickshadereffectsource_p.h"
+
+#include <QtQml/QQmlEngine>
+
+#include <private/qquickpixmapcache_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+const QEvent::Type Event_Grab_Completed = static_cast<QEvent::Type>(QEvent::User + 1);
+
+class QQuickItemGrabResultPrivate : public QObjectPrivate
+{
+public:
+ QQuickItemGrabResultPrivate()
+ : cacheEntry(0)
+ , texture(0)
+ {
+ }
+
+ ~QQuickItemGrabResultPrivate()
+ {
+ delete cacheEntry;
+ }
+
+ void ensureImageInCache() const {
+ if (url.isEmpty() && !image.isNull()) {
+ url.setScheme(QStringLiteral("ItemGrabber"));
+ url.setPath(QVariant::fromValue(item.data()).toString());
+ static uint counter = 0;
+ url.setFragment(QString::number(++counter));
+ cacheEntry = new QQuickPixmap(url, image);
+ }
+ }
+
+ static QQuickItemGrabResult *create(QQuickItem *item, const QSize &size);
+
+ QImage image;
+
+ mutable QUrl url;
+ mutable QQuickPixmap *cacheEntry;
+
+ QQmlEngine *qmlEngine;
+ QJSValue callback;
+
+ QPointer<QQuickItem> item;
+ QPointer<QQuickWindow> window;
+ QQuickShaderEffectTexture *texture;
+ QSizeF itemSize;
+ QSize textureSize;
+};
+
+/*!
+ * \qmlproperty url QtQuick::ItemGrabResult::url
+ *
+ * This property holds a URL which can be used in conjunction with
+ * URL based image consumers, such as the QtQuick::Image type.
+ *
+ * The URL is valid while there is a reference in QML or JavaScript
+ * to the ItemGrabResult or while the image the URL references is
+ * actively used.
+ *
+ * The URL does not represent a valid file or location to read it from, it
+ * is primarily a key to access images through Qt Quick's image-based types.
+ */
+
+/*!
+ * \property QQuickItemGrabResult::url
+ *
+ * This property holds a URL which can be used in conjunction with
+ * URL based image consumers, such as the QtQuick::Image type.
+ *
+ * The URL is valid until the QQuickItemGrabResult object is deleted.
+ *
+ * The URL does not represent a valid file or location to read it from, it
+ * is primarily a key to access images through Qt Quick's image-based types.
+ */
+
+/*!
+ * \qmlproperty variant QtQuick::ItemGrabResult::image
+ *
+ * This property holds the pixel results from a grab in the
+ * form of a QImage.
+ */
+
+/*!
+ * \property QQuickItemGrabResult::image
+ *
+ * This property holds the pixel results from a grab.
+ *
+ * If the grab is not yet complete or if it failed,
+ * an empty image is returned.
+ */
+
+/*!
+ \class QQuickItemGrabResult
+ \inmodule QtQuick
+ \brief The QQuickItemGrabResult contains the result from QQuickItem::grabToImage().
+
+ \sa QQuickItem::grabToImage()
+ */
+
+/*!
+ * \fn void QQuickItemGrabResult::ready()
+ *
+ * This signal is emitted when the grab has completed.
+ */
+
+/*!
+ * \qmltype ItemGrabResult
+ * \instantiates QQuickItemGrabResult
+ * \inherits QtObject
+ * \inqmlmodule QtQuick
+ * \ingroup qtquick-visual
+ * \brief Contains the results from a call to Item::grabToImage().
+ *
+ * The ItemGrabResult is a small container used to encapsulate
+ * the results from Item::grabToImage().
+ *
+ * \sa Item::grabToImage()
+ */
+
+QQuickItemGrabResult::QQuickItemGrabResult(QObject *parent)
+ : QObject(*new QQuickItemGrabResultPrivate, parent)
+{
+}
+
+/*!
+ * \qmlmethod bool QtQuick::ItemGrabResult::saveToFile(fileName)
+ *
+ * Saves the grab result as an image to \a fileName. Returns true
+ * if successful; otherwise returns false.
+ */
+
+/*!
+ * Saves the grab result as an image to \a fileName. Returns true
+ * if successful; otherwise returns false.
+ */
+bool QQuickItemGrabResult::saveToFile(const QString &fileName)
+{
+ Q_D(QQuickItemGrabResult);
+ return d->image.save(fileName);
+}
+
+QUrl QQuickItemGrabResult::url() const
+{
+ Q_D(const QQuickItemGrabResult);
+ d->ensureImageInCache();
+ return d->url;
+}
+
+QImage QQuickItemGrabResult::image() const
+{
+ Q_D(const QQuickItemGrabResult);
+ return d->image;
+}
+
+/*!
+ * \internal
+ */
+bool QQuickItemGrabResult::event(QEvent *e)
+{
+ Q_D(QQuickItemGrabResult);
+ if (e->type() == Event_Grab_Completed) {
+ // JS callback
+ if (d->qmlEngine && d->callback.isCallable())
+ d->callback.call(QJSValueList() << d->qmlEngine->newQObject(this));
+ else
+ Q_EMIT ready();
+ return true;
+ }
+ return QObject::event(e);
+}
+
+void QQuickItemGrabResult::setup()
+{
+ Q_D(QQuickItemGrabResult);
+ if (!d->item) {
+ disconnect(d->window.data(), &QQuickWindow::beforeSynchronizing, this, &QQuickItemGrabResult::setup);
+ disconnect(d->window.data(), &QQuickWindow::afterRendering, this, &QQuickItemGrabResult::render);
+ QCoreApplication::postEvent(this, new QEvent(Event_Grab_Completed));
+ return;
+ }
+
+ d->texture = new QQuickShaderEffectTexture(d->item);
+ d->texture->setItem(QQuickItemPrivate::get(d->item)->itemNode());
+ d->itemSize = QSizeF(d->item->width(), d->item->height());
+}
+
+void QQuickItemGrabResult::render()
+{
+ Q_D(QQuickItemGrabResult);
+ if (!d->texture)
+ return;
+
+ d->texture->setRect(QRectF(0, d->itemSize.height(), d->itemSize.width(), -d->itemSize.height()));
+ QSGContext *sg = QSGRenderContext::from(QOpenGLContext::currentContext())->sceneGraphContext();
+ const QSize minSize = sg->minimumFBOSize();
+ d->texture->setSize(QSize(qMax(minSize.width(), d->textureSize.width()),
+ qMax(minSize.height(), d->textureSize.height())));
+ d->texture->scheduleUpdate();
+ d->texture->updateTexture();
+ d->image = d->texture->toImage();
+
+ delete d->texture;
+ d->texture = 0;
+
+ disconnect(d->window.data(), &QQuickWindow::beforeSynchronizing, this, &QQuickItemGrabResult::setup);
+ disconnect(d->window.data(), &QQuickWindow::afterRendering, this, &QQuickItemGrabResult::render);
+ QCoreApplication::postEvent(this, new QEvent(Event_Grab_Completed));
+}
+
+QQuickItemGrabResult *QQuickItemGrabResultPrivate::create(QQuickItem *item, const QSize &targetSize)
+{
+ QSize size = targetSize;
+ if (size.isEmpty())
+ size = QSize(item->width(), item->height());
+
+ if (size.width() < 1 || size.height() < 1) {
+ qWarning("Item::grabToImage: item has invalid dimensions");
+ return 0;
+ }
+
+ if (!item->window()) {
+ qWarning("Item::grabToImage: item is not attached to a window");
+ return 0;
+ }
+
+ if (!item->window()->isVisible()) {
+ qWarning("Item::grabToImage: item's window is not visible");
+ return 0;
+ }
+
+ QQuickItemGrabResult *result = new QQuickItemGrabResult();
+ QQuickItemGrabResultPrivate *d = result->d_func();
+ d->item = item;
+ d->window = item->window();
+ d->textureSize = size;
+
+ QQuickItemPrivate::get(item)->refFromEffectItem(false);
+
+ // trigger sync & render
+ item->window()->update();
+
+ return result;
+}
+
+/*!
+ * Grabs the item into an in-memory image.
+ *
+ * The grab happens asynchronously and the signal QQuickItemGrabResult::ready()
+ * is emitted when the grab has been completed.
+ *
+ * Use \a targetSize to specify the size of the target image. By default, the
+ * result will have the same size as item.
+ *
+ * If the grab could not be initiated, the function returns a \c null.
+ *
+ * \note This function will render the item to an offscreen surface and
+ * copy that surface from the GPU's memory into the CPU's memory, which can
+ * be quite costly. For "live" preview, use \l {QtQuick::Item::layer.enabled} {layers}
+ * or ShaderEffectSource.
+ *
+ * \sa QQuickWindow::grabWindow()
+ */
+QSharedPointer<QQuickItemGrabResult> QQuickItem::grabToImage(const QSize &targetSize)
+{
+ QQuickItemGrabResult *result = QQuickItemGrabResultPrivate::create(this, targetSize);
+ if (!result)
+ return QSharedPointer<QQuickItemGrabResult>();
+
+ connect(window(), &QQuickWindow::beforeSynchronizing, result, &QQuickItemGrabResult::setup, Qt::DirectConnection);
+ connect(window(), &QQuickWindow::afterRendering, result, &QQuickItemGrabResult::render, Qt::DirectConnection);
+
+ return QSharedPointer<QQuickItemGrabResult>(result);
+}
+
+/*!
+ * \qmlmethod bool QtQuick::Item::grabToImage(callback, targetSize)
+ *
+ * Grabs the item into an in-memory image.
+ *
+ * The grab happens asynchronously and the JavaScript function \a callback is
+ * invoked when the grab is completed.
+ *
+ * Use \a targetSize to specify the size of the target image. By default, the result
+ * will have the same size as the item.
+ *
+ * If the grab could not be initiated, the function returns \c false.
+ *
+ * The following snippet shows how to grab an item and store the results to
+ * a file.
+ *
+ * \snippet qml/itemGrab.qml grab-source
+ * \snippet qml/itemGrab.qml grab-to-file
+ *
+ * The following snippet shows how to grab an item and use the results in
+ * another image element.
+ *
+ * \snippet qml/itemGrab.qml grab-image-target
+ * \snippet qml/itemGrab.qml grab-to-cache
+ *
+ * \note This function will render the item to an offscreen surface and
+ * copy that surface from the GPU's memory into the CPU's memory, which can
+ * be quite costly. For "live" preview, use \l {QtQuick::Item::layer.enabled} {layers}
+ * or ShaderEffectSource.
+ */
+
+/*!
+ * \internal
+ * Only visible from QML.
+ */
+bool QQuickItem::grabToImage(const QJSValue &callback, const QSize &targetSize)
+{
+ QQmlEngine *engine = qmlEngine(this);
+ if (!engine) {
+ qWarning("Item::grabToImage: no QML Engine");
+ return false;
+ }
+
+ if (!callback.isCallable()) {
+ qWarning("Item::grabToImage: 'callback' is not a function");
+ return false;
+ }
+
+ QSize size = targetSize;
+ if (size.isEmpty())
+ size = QSize(width(), height());
+
+ if (size.width() < 1 || size.height() < 1) {
+ qWarning("Item::grabToImage: item has invalid dimensions");
+ return false;
+ }
+
+ if (!window()) {
+ qWarning("Item::grabToImage: item is not attached to a window");
+ return false;
+ }
+
+ QQuickItemGrabResult *result = QQuickItemGrabResultPrivate::create(this, size);
+ if (!result)
+ return false;
+
+ connect(window(), &QQuickWindow::beforeSynchronizing, result, &QQuickItemGrabResult::setup, Qt::DirectConnection);
+ connect(window(), &QQuickWindow::afterRendering, result, &QQuickItemGrabResult::render, Qt::DirectConnection);
+
+ QQuickItemGrabResultPrivate *d = result->d_func();
+ d->qmlEngine = engine;
+ d->callback = callback;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemgrabresult.h b/src/quick/items/qquickitemgrabresult.h
new file mode 100644
index 0000000000..5297002bb8
--- /dev/null
+++ b/src/quick/items/qquickitemgrabresult.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKITEMGRABRESULT_H
+#define QQUICKITEMGRABRESULT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QSize>
+#include <QtCore/QUrl>
+#include <QtGui/QImage>
+#include <QtQml/QJSValue>
+#include <QtQuick/qtquickglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+
+class QQuickItemGrabResultPrivate;
+
+class Q_QUICK_EXPORT QQuickItemGrabResult : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickItemGrabResult)
+
+ Q_PROPERTY(QImage image READ image CONSTANT)
+ Q_PROPERTY(QUrl url READ url CONSTANT)
+public:
+ QImage image() const;
+ QUrl url() const;
+
+ Q_INVOKABLE bool saveToFile(const QString &fileName);
+
+protected:
+ bool event(QEvent *);
+
+Q_SIGNALS:
+ void ready();
+
+private Q_SLOTS:
+ void setup();
+ void render();
+
+private:
+ friend class QQuickItem;
+
+ QQuickItemGrabResult(QObject *parent = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 10c1780799..2f20dd763b 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -43,6 +43,7 @@
#include "qquickitem.h"
#include "qquickitem_p.h"
+#include "qquickitemgrabresult.h"
#include "qquickevents_p_p.h"
#include "qquickrectangle_p.h"
#include "qquickfocusscope_p.h"
@@ -183,8 +184,10 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit");
qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
qmlRegisterType<QQuickTextInput,2>(uri,2,2,"TextInput");
+ qmlRegisterType<QQuickTextInput,3>(uri,2,4,"TextInput");
qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
+ qmlRegisterType<QQuickItemGrabResult>();
qmlRegisterType<QQuickItemLayer>();
qmlRegisterType<QQuickAnchors>();
qmlRegisterType<QQuickKeyEvent>();
@@ -265,6 +268,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickText, 3>(uri, 2, 3, "Text");
qmlRegisterType<QQuickTextEdit, 3>(uri, 2, 3, "TextEdit");
qmlRegisterType<QQuickImage, 1>(uri, 2, 3,"Image");
+
+ qmlRegisterType<QQuickItem, 2>(uri, 2, 4, "Item");
}
static void initResources()
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index ba4f1c53ba..ec13fa5a6b 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1378,6 +1378,8 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
// position all subsequent items
if (visibleItems.count() && item == visibleItems.first()->item) {
FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.first());
+ if (listItem->transitionScheduledOrRunning())
+ return;
if (orient == QQuickListView::Vertical) {
const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height();
qreal diff = newGeometry.height() - oldGeometry.height();
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index baa48291e2..01d1305260 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -483,6 +483,10 @@ qreal QQuickMouseArea::mouseY() const
\qmlproperty bool QtQuick::MouseArea::enabled
This property holds whether the item accepts mouse events.
+ \note Due to historical reasons, this property is not equivalent to
+ Item.enabled. It only affects mouse events, and its effect does not
+ propagate to child items.
+
By default, this property is true.
*/
bool QQuickMouseArea::isEnabled() const
@@ -719,7 +723,9 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
|| QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) {
setKeepMouseGrab(true);
d->stealMouse = true;
- d->startScene = event->windowPos();
+
+ if (d->drag->smoothed())
+ d->startScene = event->windowPos();
}
d->moved = true;
@@ -1246,6 +1252,10 @@ void QQuickMouseArea::setCursorShape(Qt::CursorShape shape)
start. By default this is bound to a platform dependent value. This property was added in
Qt Quick 2.2.
+ If \c drag.smoothed is \c true, the target will be moved only after the drag operation has
+ started. If set to \c false, the target will be moved straight to the current mouse position.
+ By default, this property is \c true. This property was added in Qt Quick 2.4
+
\snippet qml/mousearea/mouseareadragfilter.qml dragfilter
*/
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index 1f00e6a74d..234f78c380 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -320,7 +320,6 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
// it's always going to accept the touches, and that means the item underneath
// will not get them (unless the PA's parent is doing parent filtering,
// as the Flickable does, for example).
-
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
@@ -333,18 +332,52 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
updatePinch();
break;
case QEvent::TouchEnd:
- d->touchPoints.clear();
- updatePinch();
+ clearPinch();
break;
default:
QQuickItem::event(event);
}
}
+void QQuickPinchArea::clearPinch()
+{
+ Q_D(QQuickPinchArea);
+
+ d->touchPoints.clear();
+ if (d->inPinch) {
+ d->inPinch = false;
+ QPointF pinchCenter = mapFromScene(d->sceneLastCenter);
+ QQuickPinchEvent pe(pinchCenter, d->pinchLastScale, d->pinchLastAngle, d->pinchRotation);
+ pe.setStartCenter(d->pinchStartCenter);
+ pe.setPreviousCenter(pinchCenter);
+ pe.setPreviousAngle(d->pinchLastAngle);
+ pe.setPreviousScale(d->pinchLastScale);
+ pe.setStartPoint1(mapFromScene(d->sceneStartPoint1));
+ pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
+ pe.setPoint1(mapFromScene(d->lastPoint1));
+ pe.setPoint2(mapFromScene(d->lastPoint2));
+ emit pinchFinished(&pe);
+ if (d->pinch && d->pinch->target())
+ d->pinch->setActive(false);
+ }
+ d->pinchStartDist = 0;
+ d->pinchActivated = false;
+ d->initPinch = false;
+ d->pinchRejected = false;
+ d->stealMouse = false;
+ d->id1 = -1;
+ QQuickWindow *win = window();
+ if (win && win->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+}
+
void QQuickPinchArea::updatePinch()
{
Q_D(QQuickPinchArea);
+ QQuickWindow *win = window();
+
if (d->touchPoints.count() < 2) {
setKeepMouseGrab(false);
QQuickWindow *c = window();
@@ -379,6 +412,7 @@ void QQuickPinchArea::updatePinch()
QTouchEvent::TouchPoint touchPoint1 = d->touchPoints.at(0);
QTouchEvent::TouchPoint touchPoint2 = d->touchPoints.at(d->touchPoints. count() >= 2 ? 1 : 0);
+
QRectF bounds = clipRect();
// Pinch is not started unless there are exactly two touch points
// AND one or more of the points has just now been pressed (wasn't pressed already)
@@ -391,6 +425,13 @@ void QQuickPinchArea::updatePinch()
d->sceneStartPoint2 = touchPoint2.scenePos();
d->pinchActivated = true;
d->initPinch = true;
+
+ int touchMouseId = QQuickWindowPrivate::get(win)->touchMouseId;
+ if (touchPoint1.id() == touchMouseId || touchPoint2.id() == touchMouseId) {
+ if (win && win->mouseGrabberItem() != this) {
+ grabMouse();
+ }
+ }
}
if (d->pinchActivated && !d->pinchRejected) {
const int dragThreshold = qApp->styleHints()->startDragDistance();
@@ -449,10 +490,12 @@ void QQuickPinchArea::updatePinch()
if (pe.accepted()) {
d->inPinch = true;
d->stealMouse = true;
- QQuickWindow *c = window();
- if (c && c->mouseGrabberItem() != this)
+ if (win && win->mouseGrabberItem() != this)
grabMouse();
setKeepMouseGrab(true);
+ grabTouchPoints(QVector<int>() << touchPoint1.id() << touchPoint2.id());
+ d->inPinch = true;
+ d->stealMouse = true;
if (d->pinch && d->pinch->target()) {
d->pinchStartPos = pinch()->target()->position();
d->pinchStartScale = d->pinch->target()->scale();
@@ -528,22 +571,19 @@ bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
return QQuickItem::childMouseEventFilter(i, e);
switch (e->type()) {
case QEvent::TouchBegin:
+ clearPinch(); // fall through
case QEvent::TouchUpdate: {
- QTouchEvent *touch = static_cast<QTouchEvent*>(e);
- if (touch->touchPoints().count() > 1) {
- touchEvent(touch);
- } else {
- d->touchPoints.clear();
- for (int i = 0; i < touch->touchPoints().count(); ++i)
- if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
- d->touchPoints << touch->touchPoints().at(i);
- updatePinch();
- }
+ QTouchEvent *touch = static_cast<QTouchEvent*>(e);
+ d->touchPoints.clear();
+ for (int i = 0; i < touch->touchPoints().count(); ++i)
+ if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
+ d->touchPoints << touch->touchPoints().at(i);
+ updatePinch();
}
+ e->setAccepted(d->inPinch);
return d->inPinch;
case QEvent::TouchEnd:
- d->touchPoints.clear();
- updatePinch();
+ clearPinch();
break;
default:
break;
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index 81bdbda3a1..7f2a379a8f 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -289,6 +289,7 @@ protected:
#endif
private:
+ void clearPinch();
void updatePinch();
void handlePress();
void handleRelease();
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 0ef871be43..6236f0047b 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -305,6 +305,8 @@ void QQuickBasePositioner::prePositioning()
for (int ii = 0; ii < children.count(); ++ii) {
QQuickItem *child = children.at(ii);
+ if (QQuickItemPrivate::get(child)->isTransparentForPositioner())
+ continue;
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
PositionedItem posItem(child);
int wIdx = oldItems.find(posItem);
@@ -1038,7 +1040,7 @@ void QQuickRow::reportConflictingAnchors()
\image gridLayout_example.png
- If an item within a Column is not \l {Item::}{visible}, or if it has a width or
+ If an item within a Grid is not \l {Item::}{visible}, or if it has a width or
height of 0, the item will not be laid out and it will not be visible within the
column. Also, since a Grid automatically positions its children, a child
item within a Grid should not set its \l {Item::x}{x} or \l {Item::y}{y} positions
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index e2a26836cf..55736c33c3 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -140,6 +140,9 @@ void QQuickRenderControl::polishItems()
return;
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->flushDelayedTouchEvent();
+ if (!d->window)
+ return;
cd->polishItems();
}
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index ebeff599f4..44cafe347e 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -710,9 +710,15 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
if (window())
d->derefWindow();
}
- m_sourceItem = item;
- if (item) {
+ if (window() == item->window()) {
+ m_sourceItem = item;
+ } else {
+ qWarning("ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.");
+ m_sourceItem = 0;
+ }
+
+ if (m_sourceItem) {
QQuickItemPrivate *d = QQuickItemPrivate::get(item);
// 'item' needs a window to get a scene graph node. It usually gets one through its
// parent, but if the source item is "inline" rather than a reference -- i.e.
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 597025b796..883d0c744d 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -881,6 +881,8 @@ void QQuickTextInput::setFocusOnPress(bool b)
Whether the TextInput should scroll when the text is longer than the width. By default this is
set to true.
+
+ \sa ensureVisible()
*/
bool QQuickTextInput::autoScroll() const
{
@@ -1721,33 +1723,24 @@ void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
-void QQuickTextInputPrivate::updateHorizontalScroll()
+void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int preeditLength)
{
Q_Q(QQuickTextInput);
-#ifndef QT_NO_IM
- QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
- const int preeditLength = m_textLayout.preeditAreaText().length();
-#else
- QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor);
-#endif
+ QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor);
const qreal width = qMax<qreal>(0, q->width());
qreal cix = 0;
qreal widthUsed = 0;
- if (currentLine.isValid()) {
-#ifndef QT_NO_IM
- cix = currentLine.cursorToX(m_cursor + preeditLength);
-#else
- cix = currentLine.cursorToX(m_cursor);
-#endif
+ if (textLine.isValid()) {
+ cix = textLine.cursorToX(position + preeditLength);
const qreal cursorWidth = cix >= 0 ? cix : width - cix;
- widthUsed = qMax(currentLine.naturalTextWidth(), cursorWidth);
+ widthUsed = qMax(textLine.naturalTextWidth(), cursorWidth);
}
int previousScroll = hscroll;
- if (!autoScroll || widthUsed <= width || m_echoMode == QQuickTextInput::NoEcho) {
+ if (widthUsed <= width) {
hscroll = 0;
} else {
- Q_ASSERT(currentLine.isValid());
+ Q_ASSERT(textLine.isValid());
if (cix - hscroll >= width) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - width;
@@ -1767,7 +1760,7 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
if (preeditLength > 0) {
// check to ensure long pre-edit text doesn't push the cursor
// off to the left
- cix = currentLine.cursorToX(m_cursor + qMax(0, m_preeditCursor - 1));
+ cix = textLine.cursorToX(position + qMax(0, preeditCursor - 1));
if (cix < hscroll)
hscroll = cix;
}
@@ -1777,6 +1770,20 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
textLayoutDirty = true;
}
+void QQuickTextInputPrivate::updateHorizontalScroll()
+{
+ if (autoScroll && m_echoMode != QQuickTextInput::NoEcho) {
+#ifndef QT_NO_IM
+ const int preeditLength = m_textLayout.preeditAreaText().length();
+ ensureVisible(m_cursor, m_preeditCursor, preeditLength);
+#else
+ ensureVisible(m_cursor);
+#endif
+ } else {
+ hscroll = 0;
+ }
+}
+
void QQuickTextInputPrivate::updateVerticalScroll()
{
Q_Q(QQuickTextInput);
@@ -2063,9 +2070,8 @@ void QQuickTextInput::insert(int position, const QString &text)
{
Q_D(QQuickTextInput);
if (d->m_echoMode == QQuickTextInput::Password) {
- int delay = qGuiApp->styleHints()->passwordMaskDelay();
- if (delay > 0)
- d->m_passwordEchoTimer.start(delay, this);
+ if (d->m_passwordMaskDelay > 0)
+ d->m_passwordEchoTimer.start(d->m_passwordMaskDelay, this);
}
if (position < 0 || position > d->m_text.length())
return;
@@ -2245,6 +2251,34 @@ void QQuickTextInput::setPasswordCharacter(const QString &str)
}
/*!
+ \qmlproperty int QtQuick::TextInput::passwordMaskDelay
+ \since 5.4
+
+ Sets the delay before visible character is masked with password character, in milliseconds.
+
+ The reset method will be called by assigning undefined.
+*/
+int QQuickTextInput::passwordMaskDelay() const
+{
+ Q_D(const QQuickTextInput);
+ return d->m_passwordMaskDelay;
+}
+
+void QQuickTextInput::setPasswordMaskDelay(int delay)
+{
+ Q_D(QQuickTextInput);
+ if (d->m_passwordMaskDelay != delay) {
+ d->m_passwordMaskDelay = delay;
+ emit passwordMaskDelayChanged(delay);
+ }
+}
+
+void QQuickTextInput::resetPasswordMaskDelay()
+{
+ setPasswordMaskDelay(qGuiApp->styleHints()->passwordMaskDelay());
+}
+
+/*!
\qmlproperty string QtQuick::TextInput::displayText
This is the text displayed in the TextInput.
@@ -2607,14 +2641,16 @@ void QQuickTextInputPrivate::init()
}
}
-void QQuickTextInput::updateCursorRectangle()
+void QQuickTextInput::updateCursorRectangle(bool scroll)
{
Q_D(QQuickTextInput);
if (!isComponentComplete())
return;
- d->updateHorizontalScroll();
- d->updateVerticalScroll();
+ if (scroll) {
+ d->updateHorizontalScroll();
+ d->updateVerticalScroll();
+ }
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
update();
emit cursorRectangleChanged();
@@ -3484,9 +3520,8 @@ void QQuickTextInputPrivate::internalInsert(const QString &s)
{
Q_Q(QQuickTextInput);
if (m_echoMode == QQuickTextInput::Password) {
- int delay = qGuiApp->styleHints()->passwordMaskDelay();
- if (delay > 0)
- m_passwordEchoTimer.start(delay, q);
+ if (m_passwordMaskDelay > 0)
+ m_passwordEchoTimer.start(m_passwordMaskDelay, q);
}
Q_ASSERT(!hasSelectedText()); // insert(), processInputMethodEvent() call removeSelectedText() first.
if (m_maskData) {
@@ -4376,5 +4411,21 @@ void QQuickTextInputPrivate::deleteEndOfLine()
finishChange(priorState);
}
+/*!
+ \qmlmethod QtQuick::TextInput::ensureVisible(int position)
+ \since 5.4
+
+ Scrolls the contents of the text input so that the specified character
+ \a position is visible inside the boundaries of the text input.
+
+ \sa autoScroll
+*/
+void QQuickTextInput::ensureVisible(int position)
+{
+ Q_D(QQuickTextInput);
+ d->ensureVisible(position);
+ updateCursorRectangle(false);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 042859df17..66cabb9cfe 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -94,6 +94,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged)
+ Q_PROPERTY(int passwordMaskDelay READ passwordMaskDelay WRITE setPasswordMaskDelay RESET resetPasswordMaskDelay NOTIFY passwordMaskDelayChanged REVISION 3)
Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged)
Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged)
Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
@@ -225,6 +226,10 @@ public:
QString passwordCharacter() const;
void setPasswordCharacter(const QString &str);
+ int passwordMaskDelay() const;
+ void setPasswordMaskDelay(int delay);
+ void resetPasswordMaskDelay();
+
QString displayText() const;
QQmlComponent* cursorDelegate() const;
@@ -296,6 +301,7 @@ Q_SIGNALS:
void inputMaskChanged(const QString &inputMask);
void echoModeChanged(EchoMode echoMode);
void passwordCharacterChanged();
+ Q_REVISION(3) void passwordMaskDelayChanged(int delay);
void displayTextChanged();
void activeFocusOnPressChanged(bool activeFocusOnPress);
void autoScrollChanged(bool autoScroll);
@@ -349,11 +355,12 @@ public Q_SLOTS:
void redo();
void insert(int position, const QString &text);
void remove(int start, int end);
+ Q_REVISION(3) void ensureVisible(int position);
private Q_SLOTS:
void selectionChanged();
void createCursor();
- void updateCursorRectangle();
+ void updateCursorRectangle(bool scroll = true);
void q_canPasteChanged();
void q_updateAlignment();
void triggerPreprocess();
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 21bd1bd6d7..facc6356a1 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -111,6 +111,7 @@ public:
, mouseSelectionMode(QQuickTextInput::SelectCharacters)
, m_layoutDirection(Qt::LayoutDirectionAuto)
, m_passwordCharacter(qApp->styleHints()->passwordMaskCharacter())
+ , m_passwordMaskDelay(qApp->styleHints()->passwordMaskDelay())
, focusOnPress(true)
, cursorVisible(false)
, cursorPending(false)
@@ -147,6 +148,7 @@ public:
void init();
void startCreatingCursor();
+ void ensureVisible(int position, int preeditCursor = 0, int preeditLength = 0);
void updateHorizontalScroll();
void updateVerticalScroll();
bool determineHorizontalAlignment();
@@ -250,6 +252,7 @@ public:
QChar m_blank;
QChar m_passwordCharacter;
+ int m_passwordMaskDelay;
bool focusOnPress:1;
bool cursorVisible:1;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index e78f9141a8..a95c13f161 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -75,9 +75,16 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch");
+Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse");
+Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus");
+Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty");
+
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-bool QQuickWindowPrivate::defaultAlphaBuffer(0);
+bool QQuickWindowPrivate::defaultAlphaBuffer = false;
+bool QQuickWindowPrivate::defaultFormatInitialized = false;
+QSurfaceFormat QQuickWindowPrivate::defaultFormat;
void QQuickWindowPrivate::updateFocusItemTransform()
{
@@ -103,9 +110,9 @@ public:
// Allow incubation for 1/3 of a frame.
m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
- m_animation_driver = m_renderLoop->animationDriver();
- if (m_animation_driver) {
- connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
+ QAnimationDriver *animationDriver = m_renderLoop->animationDriver();
+ if (animationDriver) {
+ connect(animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()));
connect(m_renderLoop, SIGNAL(timeToIncubate()), this, SLOT(incubate()));
}
}
@@ -151,7 +158,6 @@ protected:
private:
QSGRenderLoop *m_renderLoop;
int m_incubation_time;
- QAnimationDriver *m_animation_driver;
int m_timer;
};
@@ -189,16 +195,6 @@ thus the first item that has focus will get it (assuming the scope doesn't alrea
have a scope focused item), and the other items will have their focus cleared.
*/
-
-// #define FOCUS_DEBUG
-// #define MOUSE_DEBUG
-// #define TOUCH_DEBUG
-// #define DIRTY_DEBUG
-
-#ifdef FOCUS_DEBUG
-void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1);
-#endif
-
QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
: transformNode(0)
{
@@ -404,12 +400,14 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, renderer(0)
, windowManager(0)
, renderControl(0)
+ , touchRecursionGuard(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
, persistentGLContext(true)
, persistentSceneGraph(true)
, lastWheelEventAccepted(false)
, componentCompleted(true)
+ , lastFocusReason(Qt::OtherFocusReason)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
@@ -458,11 +456,13 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
}
q->setSurfaceType(QWindow::OpenGLSurface);
- q->setFormat(sg->defaultSurfaceFormat());
+ q->setFormat(q->defaultFormat());
animationController = new QQuickAnimatorController();
animationController->m_window = q;
+ delayedTouch = 0;
+
QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
@@ -706,14 +706,12 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
Q_ASSERT(item);
Q_ASSERT(scope || item == contentItem);
-#ifdef FOCUS_DEBUG
- qWarning() << "QQuickWindowPrivate::setFocusInScope():";
- qWarning() << " scope:" << (QObject *)scope;
+ qCDebug(DBG_FOCUS) << "QQuickWindowPrivate::setFocusInScope():";
+ qCDebug(DBG_FOCUS) << " scope:" << (QObject *)scope;
if (scope)
- qWarning() << " scopeSubFocusItem:" << (QObject *)QQuickItemPrivate::get(scope)->subFocusItem;
- qWarning() << " item:" << (QObject *)item;
- qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
-#endif
+ qCDebug(DBG_FOCUS) << " scopeSubFocusItem:" << (QObject *)QQuickItemPrivate::get(scope)->subFocusItem;
+ qCDebug(DBG_FOCUS) << " item:" << (QObject *)item;
+ qCDebug(DBG_FOCUS) << " activeFocusItem:" << (QObject *)activeFocusItem;
QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -721,6 +719,8 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
QQuickItem *currentActiveFocusItem = activeFocusItem;
QQuickItem *newActiveFocusItem = 0;
+ lastFocusReason = reason;
+
QVarLengthArray<QQuickItem *, 20> changed;
// Does this change the active focus?
@@ -809,12 +809,10 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
Q_ASSERT(item);
Q_ASSERT(scope || item == contentItem);
-#ifdef FOCUS_DEBUG
- qWarning() << "QQuickWindowPrivate::clearFocusInScope():";
- qWarning() << " scope:" << (QObject *)scope;
- qWarning() << " item:" << (QObject *)item;
- qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem;
-#endif
+ qCDebug(DBG_FOCUS) << "QQuickWindowPrivate::clearFocusInScope():";
+ qCDebug(DBG_FOCUS) << " scope:" << (QObject *)scope;
+ qCDebug(DBG_FOCUS) << " item:" << (QObject *)item;
+ qCDebug(DBG_FOCUS) << " activeFocusItem:" << (QObject *)activeFocusItem;
QQuickItemPrivate *scopePrivate = 0;
if (scope) {
@@ -827,6 +825,8 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
QQuickItem *oldActiveFocusItem = 0;
QQuickItem *newActiveFocusItem = 0;
+ lastFocusReason = reason;
+
QVarLengthArray<QQuickItem *, 20> changed;
Q_ASSERT(item == contentItem || item == scopePrivate->subFocusItem);
@@ -1483,10 +1483,7 @@ void QQuickWindow::mousePressEvent(QMouseEvent *event)
return;
}
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons();
-#endif
-
+ qCDebug(DBG_MOUSE) << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons();
d->deliverMouseEvent(event);
}
@@ -1500,9 +1497,7 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
return;
}
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
-#endif
+ qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
if (!d->mouseGrabberItem) {
QWindow::mouseReleaseEvent(event);
@@ -1524,9 +1519,7 @@ void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
return;
}
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons();
-#endif
+ qCDebug(DBG_MOUSE) << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons();
if (!d->mouseGrabberItem && (event->buttons() & event->button()) == event->buttons()) {
if (d->deliverInitialMousePressEvent(d->contentItem, event))
@@ -1565,9 +1558,7 @@ void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
return;
}
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons();
-#endif
+ qCDebug(DBG_MOUSE) << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons();
#ifndef QT_NO_CURSOR
d->updateCursor(event->windowPos());
@@ -1706,9 +1697,7 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event
void QQuickWindow::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickWindow);
-#ifdef MOUSE_DEBUG
- qWarning() << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta();
-#endif
+ qCDebug(DBG_MOUSE) << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta();
//if the actual wheel event was accepted, accept the compatibility wheel event and return early
if (d->lastWheelEventAccepted && event->angleDelta().isNull() && event->phase() == Qt::ScrollUpdate)
@@ -1723,9 +1712,7 @@ void QQuickWindow::wheelEvent(QWheelEvent *event)
bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
{
-#ifdef TOUCH_DEBUG
- qWarning("touchCancelEvent");
-#endif
+ qCDebug(DBG_TOUCH) << event;
Q_Q(QQuickWindow);
// A TouchCancel event will typically not contain any points.
// Deliver it to all items that have active touches.
@@ -1744,18 +1731,104 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
return true;
}
+static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION");
+
// check what kind of touch we have (begin/update) and
// call deliverTouchPoints to actually dispatch the points
-bool QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
-{
-#ifdef TOUCH_DEBUG
- if (event->type() == QEvent::TouchBegin)
- qWarning() << "touchBeginEvent";
- else if (event->type() == QEvent::TouchUpdate)
- qWarning() << "touchUpdateEvent points";
- else if (event->type() == QEvent::TouchEnd)
- qWarning("touchEndEvent");
-#endif
+void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
+{
+ qCDebug(DBG_TOUCH) << event;
+ Q_Q(QQuickWindow);
+
+ if (qquickwindow_no_touch_compression || touchRecursionGuard) {
+ reallyDeliverTouchEvent(event);
+ return;
+ }
+
+ Qt::TouchPointStates states = event->touchPointStates();
+ if (((states & (Qt::TouchPointMoved | Qt::TouchPointStationary)) != 0)
+ && ((states & (Qt::TouchPointPressed | Qt::TouchPointReleased)) == 0)) {
+ // we can only compress something that isn't a press or release
+ if (!delayedTouch) {
+ delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints());
+ delayedTouch->setTimestamp(event->timestamp());
+ if (windowManager)
+ windowManager->maybeUpdate(q);
+ return;
+ } else {
+ // check if this looks like the last touch event
+ if (delayedTouch->type() == event->type() &&
+ delayedTouch->device() == event->device() &&
+ delayedTouch->modifiers() == event->modifiers() &&
+ delayedTouch->touchPoints().count() == event->touchPoints().count())
+ {
+ // possible match.. is it really the same?
+ bool mismatch = false;
+
+ QList<QTouchEvent::TouchPoint> tpts = event->touchPoints();
+ Qt::TouchPointStates states;
+ for (int i = 0; i < event->touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &tp = tpts.at(i);
+ const QTouchEvent::TouchPoint &tp2 = delayedTouch->touchPoints().at(i);
+ if (tp.id() != tp2.id()) {
+ mismatch = true;
+ break;
+ }
+
+ if (tp2.state() == Qt::TouchPointMoved && tp.state() == Qt::TouchPointStationary)
+ tpts[i].setState(Qt::TouchPointMoved);
+
+ states |= tpts.at(i).state();
+ }
+
+ // same touch event? then merge if so
+ if (!mismatch) {
+ delayedTouch->setTouchPoints(tpts);
+ delayedTouch->setTimestamp(event->timestamp());
+ return;
+ }
+ }
+
+ // otherwise; we need to deliver the delayed event first, and
+ // then delay this one..
+ reallyDeliverTouchEvent(delayedTouch);
+ delete delayedTouch;
+ delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints());
+ delayedTouch->setTimestamp(event->timestamp());
+ return;
+ }
+ } else {
+ if (delayedTouch) {
+ // deliver the delayed touch first
+ reallyDeliverTouchEvent(delayedTouch);
+ delete delayedTouch;
+ delayedTouch = 0;
+ }
+ reallyDeliverTouchEvent(event);
+ }
+}
+
+void QQuickWindowPrivate::flushDelayedTouchEvent()
+{
+ if (delayedTouch) {
+ reallyDeliverTouchEvent(delayedTouch);
+ delete delayedTouch;
+ delayedTouch = 0;
+
+ // To flush pending meta-calls triggered from the recently flushed touch events.
+ // This is safe because flushDelayedEvent is only called from eventhandlers.
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
+}
+
+void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event)
+{
+ qCDebug(DBG_TOUCH) << " - delivering" << event;
+
+ // If users spin the eventloop as a result of touch delivery, we disable
+ // touch compression and send events directly. This is because we consider
+ // the usecase a bit evil, but we at least don't want to lose events.
+ ++touchRecursionGuard;
// List of all items that received an event before
// When we have TouchBegin this is and will stay empty
@@ -1805,7 +1878,7 @@ bool QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
Q_ASSERT(itemForTouchPointId.isEmpty());
}
- return event->isAccepted();
+ --touchRecursionGuard;
}
// This function recurses and sends the events to the individual items
@@ -2462,9 +2535,7 @@ void QQuickWindowPrivate::cleanupNodesOnShutdown()
void QQuickWindowPrivate::updateDirtyNodes()
{
-#ifdef DIRTY_DEBUG
- qWarning() << "QQuickWindowPrivate::updateDirtyNodes():";
-#endif
+ qCDebug(DBG_DIRTY) << "QQuickWindowPrivate::updateDirtyNodes():";
cleanupNodes();
@@ -2477,9 +2548,7 @@ void QQuickWindowPrivate::updateDirtyNodes()
QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
itemPriv->removeFromDirtyList();
-#ifdef DIRTY_DEBUG
- qWarning() << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
-#endif
+ qCDebug(DBG_DIRTY) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
updateDirtyNode(item);
}
}
@@ -2816,7 +2885,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
\internal
\since 5.1
- \inmodule QtQuick.Window
+ \inmodule QtQuick
\brief Notification that a \l QQuickWindow is about to be closed
*/
@@ -3445,6 +3514,130 @@ void QQuickWindow::resetOpenGLState()
}
/*!
+ * \brief QQuickWindow::setDefaultFormat
+ * \since 5.4
+ * @brief Sets the global default surface format that is used for all new QQuickWindow instances.
+ *
+ * While it is possible to specify a QSurfaceFormat for every QQuickWindow by
+ * calling the member function setFormat(), windows may also be created from
+ * QML by using the Window and ApplicationWindow elements. In this case there
+ * is no C++ code involved in the creation of the window instance, yet
+ * applications may still wish to set certain surface format values, for
+ * example to request a given OpenGL version or profile. Such applications can
+ * call this static functions in main(). \a format will be used for all Quick
+ * windows created afterwards.
+ *
+ * \note The default value for the default format is not necessarily a
+ * default-constructed QSurfaceFormat. It may already have depth, stencil and alpha
+ * buffer sizes set. Unless there is a need to change all these sizes, the format should
+ * first be queried via defaultFormat() and the changes should be applied to that,
+ * instead of merely starting with default-constructed QSurfaceFormat.
+ *
+ * \sa setFormat(), format(), defaultFormat()
+ */
+void QQuickWindow::setDefaultFormat(const QSurfaceFormat &format)
+{
+ QQuickWindowPrivate::defaultFormatInitialized = true;
+ QQuickWindowPrivate::defaultFormat = format;
+}
+
+/*!
+ * \brief QQuickWindow::defaultFormat
+ * \since 5.4
+ * \return The global default surface format that is used for all QQuickWindow instances.
+ * \note This function requires a QGuiApplication or QApplication instance.
+ */
+QSurfaceFormat QQuickWindow::defaultFormat()
+{
+ if (!QQuickWindowPrivate::defaultFormatInitialized) {
+ QQuickWindowPrivate::defaultFormatInitialized = true;
+ QQuickWindowPrivate::defaultFormat = QSGRenderLoop::instance()->sceneGraphContext()->defaultSurfaceFormat();
+ }
+ return QQuickWindowPrivate::defaultFormat;
+}
+
+/*!
+ * \brief QQuickWindow::glslVersion
+ * \since 5.4
+ * \return The OpenGL Shading Language version for this window.
+ *
+ * QML components that need to be usable on different platforms and environments may need
+ * to deal with different OpenGL versions if they include ShaderEffect items. The source
+ * code for a given shader may not be compatible with an OpenGL context that targets a
+ * different OpenGL version or profile, hence it might be necessary to provide multiple
+ * versions of the shader. This property helps in deciding which shader source should be
+ * chosen.
+ *
+ * The value corresponds to GLSL version declarations, for example an OpenGL 4.2 core
+ * profile context will result in the value \e{420 core}, while an OpenGL ES 3.0 context
+ * gives \e{300 es}. For OpenGL (ES) 2 the value will be an empty string since the
+ * corresponding shading language does not use version declarations.
+ *
+ * \note The value does not necessarily indicate that the shader source must target that
+ * specific version. For example, compatibility profiles and ES 3.x all allow using
+ * OpenGL 2 style shaders. The most important for reusable components is to check for
+ * core profiles since these do not accept shaders with the old syntax.
+ *
+ * \sa setFormat(), glslIsCoreProfile()
+ */
+QString QQuickWindow::glslVersion() const
+{
+ QString ver;
+ QOpenGLContext *ctx = openglContext();
+ if (ctx) {
+ const QSurfaceFormat fmt = ctx->format();
+ if (fmt.renderableType() == QSurfaceFormat::OpenGLES
+ && fmt.majorVersion() >= 3) {
+ ver += QLatin1Char(fmt.majorVersion() + '0');
+ ver += QLatin1Char(fmt.minorVersion() + '0');
+ ver += QLatin1String("0 es");
+ } else if (fmt.renderableType() == QSurfaceFormat::OpenGL
+ && fmt.majorVersion() >= 3) {
+ if (fmt.version() == qMakePair(3, 0)) {
+ ver = QStringLiteral("130");
+ } else if (fmt.version() == qMakePair(3, 1)) {
+ ver = QStringLiteral("140");
+ } else if (fmt.version() == qMakePair(3, 2)) {
+ ver = QStringLiteral("150");
+ } else {
+ ver += QLatin1Char(fmt.majorVersion() + '0');
+ ver += QLatin1Char(fmt.minorVersion() + '0');
+ ver += QLatin1Char('0');
+ }
+ if (fmt.version() >= qMakePair(3, 2)) {
+ if (fmt.profile() == QSurfaceFormat::CoreProfile)
+ ver += QStringLiteral(" core");
+ else if (fmt.profile() == QSurfaceFormat::CompatibilityProfile)
+ ver += QStringLiteral(" compatibility");
+ }
+ }
+ }
+ return ver;
+}
+
+/*!
+ * \brief QQuickWindow::glslIsCoreProfile
+ * \since 5.4
+ * \return True if the window is rendering using OpenGL core profile.
+ *
+ * This is convenience function to check if the window's OpenGL context is a core profile
+ * context. It is more efficient to perform the check via this function than parsing the
+ * string returned from glslVersion().
+ *
+ * Resusable QML components will typically use this function in bindings in order to
+ * choose between core and non core profile compatible shader sources.
+ *
+ * To retrieve more information about the shading language, use glslVersion().
+ *
+ * \sa glslVersion()
+ */
+bool QQuickWindow::glslIsCoreProfile() const
+{
+ QOpenGLContext *ctx = openglContext();
+ return ctx ? ctx->format().profile() == QSurfaceFormat::CoreProfile : false;
+}
+
+/*!
\qmlproperty string Window::title
The window's title in the windowing system.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 2572f31375..1a4adb0785 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -67,6 +67,8 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1)
+ Q_PROPERTY(QString glslVersion READ glslVersion CONSTANT REVISION 2)
+ Q_PROPERTY(bool glslIsCoreProfile READ glslIsCoreProfile CONSTANT REVISION 2)
Q_CLASSINFO("DefaultProperty", "data")
Q_DECLARE_PRIVATE(QQuickWindow)
public:
@@ -136,6 +138,12 @@ public:
QOpenGLContext *openglContext() const;
+ static void setDefaultFormat(const QSurfaceFormat &format);
+ static QSurfaceFormat defaultFormat();
+
+ QString glslVersion() const;
+ bool glslIsCoreProfile() const;
+
Q_SIGNALS:
void frameSwapped();
Q_REVISION(2) void openglContextCreated(QOpenGLContext *context);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 421651b483..8faaf6489b 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -141,8 +141,10 @@ public:
#endif
bool deliverTouchPoints(QQuickItem *, QTouchEvent *, const QList<QTouchEvent::TouchPoint> &, QSet<int> *,
QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *);
- bool deliverTouchEvent(QTouchEvent *);
+ void deliverTouchEvent(QTouchEvent *);
+ void reallyDeliverTouchEvent(QTouchEvent *);
bool deliverTouchCancelEvent(QTouchEvent *);
+ void flushDelayedTouchEvent();
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints);
QTouchEvent *touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent);
@@ -210,6 +212,8 @@ public:
QSGRenderLoop *windowManager;
QQuickRenderControl *renderControl;
QQuickAnimatorController *animationController;
+ QTouchEvent *delayedTouch;
+ int touchRecursionGuard;
QColor clearColor;
@@ -223,6 +227,8 @@ public:
uint lastWheelEventAccepted : 1;
bool componentCompleted : 1;
+ Qt::FocusReason lastFocusReason;
+
QOpenGLFramebufferObject *renderTarget;
uint renderTargetId;
QSize renderTargetSize;
@@ -247,6 +253,9 @@ public:
QString *untranslatedMessage,
bool isEs);
+ static bool defaultFormatInitialized;
+ static QSurfaceFormat defaultFormat;
+
private:
static void cleanupNodesOnShutdown(QQuickItem *);
};
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 9d2a0b0f75..fe24c2512a 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -44,6 +44,7 @@
#include <private/qquickutilmodule_p.h>
#include <private/qquickvaluetypes_p.h>
#include <private/qquickitemsmodule_p.h>
+#include <private/qquickaccessiblefactory_p.h>
#include <private/qqmlenginedebugservice_p.h>
#include <private/qqmldebugstatesdelegate_p.h>
@@ -190,6 +191,10 @@ void QQmlQtQuick2Module::defineModule()
QQuickValueTypes::registerValueTypes();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::installFactory(&qQuickAccessibleFactory);
+#endif
+
if (QQmlDebugService::isDebuggingEnabled()) {
QQmlEngineDebugService::instance()->setStatesDelegate(
new QQmlQtQuick2DebugStatesDelegate);
diff --git a/src/quick/qtquickglobal_p.h b/src/quick/qtquickglobal_p.h
index f67a08c218..cd4cb61ebb 100644
--- a/src/quick/qtquickglobal_p.h
+++ b/src/quick/qtquickglobal_p.h
@@ -42,6 +42,8 @@
#ifndef QTQUICKGLOBAL_P_H
#define QTQUICKGLOBAL_P_H
+#include <QtCore/qloggingcategory.h>
+
//
// W A R N I N G
// -------------
@@ -61,6 +63,11 @@ QT_BEGIN_NAMESPACE
void QQuick_initializeProviders();
+Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH)
+Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE)
+Q_DECLARE_LOGGING_CATEGORY(DBG_FOCUS)
+Q_DECLARE_LOGGING_CATEGORY(DBG_DIRTY)
+
QT_END_NAMESPACE
#endif // QTQUICKGLOBAL_P_H
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 38e743cc5c..6e08662e61 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -29,6 +29,9 @@ include(util/util.pri)
include(scenegraph/scenegraph.pri)
include(items/items.pri)
include(designer/designer.pri)
+contains(QT_CONFIG, accessibility) {
+ include(accessible/accessible.pri)
+}
HEADERS += \
qtquickglobal.h \
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index e8f803f2a9..c9115f35fc 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -606,11 +606,6 @@ void Element::computeBounds()
BatchCompatibility Batch::isMaterialCompatible(Element *e) const
{
- // If material has changed between opaque and translucent, it is not compatible
- QSGMaterial *m = e->node->activeMaterial();
- if (isOpaque != ((m->flags() & QSGMaterial::Blending) == 0))
- return BatchBreaksOnBlending;
-
Element *n = first;
// Skip to the first node other than e which has not been removed
while (n && (n == e || n->removed))
@@ -621,6 +616,7 @@ BatchCompatibility Batch::isMaterialCompatible(Element *e) const
if (!n)
return BatchIsCompatible;
+ QSGMaterial *m = e->node->activeMaterial();
QSGMaterial *nm = n->node->activeMaterial();
return (nm->type() == m->type() && nm->compare(m) == 0)
? BatchIsCompatible
@@ -838,10 +834,12 @@ static void qsg_wipeBatch(Batch *batch, QOpenGLFunctions *funcs)
Renderer::~Renderer()
{
- // Clean up batches and buffers
- for (int i=0; i<m_opaqueBatches.size(); ++i) qsg_wipeBatch(m_opaqueBatches.at(i), this);
- for (int i=0; i<m_alphaBatches.size(); ++i) qsg_wipeBatch(m_alphaBatches.at(i), this);
- for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
+ if (QOpenGLContext::currentContext()) {
+ // Clean up batches and buffers
+ for (int i=0; i<m_opaqueBatches.size(); ++i) qsg_wipeBatch(m_opaqueBatches.at(i), this);
+ for (int i=0; i<m_alphaBatches.size(); ++i) qsg_wipeBatch(m_alphaBatches.at(i), this);
+ for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
+ }
// The shadowtree
qDeleteAll(m_nodes.values());
@@ -1185,11 +1183,12 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
if (state & QSGNode::DirtyMaterial && node->type() == QSGNode::GeometryNodeType) {
Element *e = shadowNode->element();
if (e) {
- if (e->batch) {
- BatchCompatibility compat = e->batch->isMaterialCompatible(e);
- if (compat == BatchBreaksOnBlending)
- m_rebuild |= Renderer::FullRebuild;
- else if (compat == BatchBreaksOnCompare)
+ bool blended = hasMaterialWithBlending(static_cast<QSGGeometryNode *>(node));
+ if (e->isMaterialBlended != blended) {
+ m_rebuild |= Renderer::FullRebuild;
+ e->isMaterialBlended = blended;
+ } else if (e->batch) {
+ if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
invalidateBatchAndOverlappingRenderOrders(e->batch);
} else {
m_rebuild |= Renderer::BuildBatches;
@@ -1464,7 +1463,7 @@ void Renderer::prepareOpaqueBatches()
{
for (int i=m_opaqueRenderList.size() - 1; i >= 0; --i) {
Element *ei = m_opaqueRenderList.at(i);
- if (!ei || ei->batch)
+ if (!ei || ei->batch || ei->node->geometry()->vertexCount() == 0)
continue;
Batch *batch = newBatch();
batch->first = ei;
@@ -1486,7 +1485,7 @@ void Renderer::prepareOpaqueBatches()
continue;
if (ej->root != ei->root)
break;
- if (ej->batch)
+ if (ej->batch || ej->node->geometry()->vertexCount() == 0)
continue;
QSGGeometryNode *gnj = ej->node;
@@ -1557,6 +1556,9 @@ void Renderer::prepareAlphaBatches()
continue;
}
+ if (ei->node->geometry()->vertexCount() == 0)
+ continue;
+
Batch *batch = newBatch();
batch->first = ei;
batch->root = ei->root;
@@ -1583,6 +1585,8 @@ void Renderer::prepareAlphaBatches()
continue;
QSGGeometryNode *gnj = ej->node;
+ if (gnj->geometry()->vertexCount() == 0)
+ continue;
if (gni->clipList() == gnj->clipList()
&& gni->geometry()->drawingMode() == gnj->geometry()->drawingMode()
@@ -2473,11 +2477,14 @@ void Renderer::renderRenderNode(Batch *batch)
QSGNode *xform = e->renderNode->parent();
QMatrix4x4 matrix;
- while (xform != rootNode()) {
+ QSGNode *root = rootNode();
+ if (e->root) {
+ matrix = qsg_matrixForRoot(e->root);
+ root = e->root->sgNode;
+ }
+ while (xform != root) {
if (xform->type() == QSGNode::TransformNodeType) {
- matrix = static_cast<QSGTransformNode *>(xform)->combinedMatrix();
- if (e->root)
- matrix = qsg_matrixForRoot(e->root) * matrix;
+ matrix = matrix * static_cast<QSGTransformNode *>(xform)->combinedMatrix();
break;
}
xform = xform->parent();
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 44b7b8740d..89a33cb8c4 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -67,6 +67,12 @@ class Updater;
class Renderer;
class ShaderManager;
+inline bool hasMaterialWithBlending(QSGGeometryNode *n)
+{
+ return (n->opaqueMaterial() ? n->opaqueMaterial()->flags() & QSGMaterial::Blending
+ : n->material()->flags() & QSGMaterial::Blending);
+}
+
struct Pt {
float x, y;
@@ -163,6 +169,7 @@ struct Element {
, removed(false)
, orphaned(false)
, isRenderNode(false)
+ , isMaterialBlended(n ? hasMaterialWithBlending(n) : false)
{
}
@@ -187,6 +194,7 @@ struct Element {
uint removed : 1;
uint orphaned : 1;
uint isRenderNode : 1;
+ uint isMaterialBlended : 1;
};
struct RenderNodeElement : public Element {
@@ -233,7 +241,6 @@ struct DrawSet
enum BatchCompatibility
{
- BatchBreaksOnBlending,
BatchBreaksOnCompare,
BatchIsCompatible
};
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index e76aa1bbb5..38de4a5c39 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -352,6 +352,12 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (!current)
return;
+ if (!data.grabOnly) {
+ cd->flushDelayedTouchEvent();
+ // Event delivery/processing triggered the window to be deleted or stop rendering.
+ if (!m_windows.contains(window))
+ return;
+ }
cd->polishItems();
emit window->afterAnimating();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 0aa30280e5..1ba54ea19e 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -50,6 +51,8 @@
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
+#include <qpa/qwindowsysteminterface.h>
+
#include <QtQuick/QQuickWindow>
#include <private/qquickwindow_p.h>
@@ -154,35 +157,25 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
// RL: Render Loop
// RT: Render Thread
-// Passed from the RL to the RT when a window is rendeirng on screen
-// and should be added to the render loop.
-const QEvent::Type WM_Expose = QEvent::Type(QEvent::User + 1);
-
// Passed from the RL to the RT when a window is removed obscured and
// should be removed from the render loop.
-const QEvent::Type WM_Obscure = QEvent::Type(QEvent::User + 2);
-
-// Passed from the RL to itself to initiate a polishAndSync() call.
-//const QEvent::Type WM_LockAndSync = QEvent::Type(QEvent::User + 3); // not used for now
+const QEvent::Type WM_Obscure = QEvent::Type(QEvent::User + 1);
// Passed from the RL to RT when GUI has been locked, waiting for sync
// (updatePaintNode())
-const QEvent::Type WM_RequestSync = QEvent::Type(QEvent::User + 4);
+const QEvent::Type WM_RequestSync = QEvent::Type(QEvent::User + 2);
// Passed by the RT to itself to trigger another render pass. This is
// typically a result of QQuickWindow::update().
-const QEvent::Type WM_RequestRepaint = QEvent::Type(QEvent::User + 5);
+const QEvent::Type WM_RequestRepaint = QEvent::Type(QEvent::User + 3);
// Passed by the RL to the RT to free up maybe release SG and GL contexts
// if no windows are rendering.
-const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 7);
+const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
// Passed by the RL to the RT when a QQuickWindow::grabWindow() is
// called.
-const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 9);
-
-// Passed by RL to RT when polish fails and we need to reset the expose sycle.
-const QEvent::Type WM_ResetExposeCycle = QEvent::Type(QEvent::User + 10);
+const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5);
template <typename T> T *windowFor(const QList<T> list, QQuickWindow *window)
{
@@ -215,11 +208,12 @@ public:
QOffscreenSurface *fallbackSurface;
};
-class WMExposeEvent : public WMWindowEvent
+class WMSyncEvent : public WMWindowEvent
{
public:
- WMExposeEvent(QQuickWindow *c) : WMWindowEvent(c, WM_Expose), size(c->size()) { }
+ WMSyncEvent(QQuickWindow *c, bool inExpose) : WMWindowEvent(c, WM_RequestSync), size(c->size()), syncInExpose(inExpose) { }
QSize size;
+ bool syncInExpose;
};
@@ -285,7 +279,6 @@ public:
, pendingUpdate(0)
, sleeping(false)
, syncResultedInChanges(false)
- , exposeCycle(NoExpose)
, active(false)
, window(0)
, stopEventProcessing(false)
@@ -309,7 +302,7 @@ public:
void run();
void syncAndRender();
- void sync();
+ void sync(bool inExpose);
void requestRepaint()
{
@@ -332,13 +325,8 @@ public slots:
public:
enum UpdateRequest {
SyncRequest = 0x01,
- RepaintRequest = 0x02
- };
-
- enum ExposeCycle {
- NoExpose,
- ExposePendingSync,
- ExposePendingSwap
+ RepaintRequest = 0x02,
+ ExposeRequest = 0x04 | RepaintRequest | SyncRequest
};
QSGThreadedRenderLoop *wm;
@@ -350,7 +338,6 @@ public:
uint pendingUpdate;
bool sleeping;
bool syncResultedInChanges;
- ExposeCycle exposeCycle;
volatile bool active;
@@ -373,21 +360,6 @@ bool QSGRenderThread::event(QEvent *e)
{
switch ((int) e->type()) {
- case WM_Expose: {
- QSG_RT_DEBUG("WM_Expose");
- WMExposeEvent *se = static_cast<WMExposeEvent *>(e);
- Q_ASSERT(!window || window == se->window);
- windowSize = se->size;
- window = se->window;
- Q_ASSERT(exposeCycle == NoExpose);
- exposeCycle = ExposePendingSync;
- return true; }
-
- case WM_ResetExposeCycle:
- QSG_RT_DEBUG("WM_ResetExposeCycle");
- exposeCycle = NoExpose;
- return true;
-
case WM_Obscure: {
QSG_RT_DEBUG("WM_Obscure");
@@ -397,6 +369,7 @@ bool QSGRenderThread::event(QEvent *e)
if (window) {
QQuickWindowPrivate::get(window)->fireAboutToStop();
QSG_RT_DEBUG(" - removed window...");
+ gl->doneCurrent();
window = 0;
}
waitCondition.wakeOne();
@@ -404,34 +377,38 @@ bool QSGRenderThread::event(QEvent *e)
return true; }
- case WM_RequestSync:
+ case WM_RequestSync: {
QSG_RT_DEBUG("WM_RequestSync");
+ WMSyncEvent *se = static_cast<WMSyncEvent *>(e);
if (sleeping)
stopEventProcessing = true;
- if (window)
- pendingUpdate |= SyncRequest;
- if (exposeCycle == ExposePendingSync) {
- pendingUpdate |= RepaintRequest;
- exposeCycle = ExposePendingSwap;
+ window = se->window;
+ windowSize = se->size;
+
+ pendingUpdate |= SyncRequest;
+ if (se->syncInExpose) {
+ QSG_RT_DEBUG(" - triggered from expose");
+ pendingUpdate |= ExposeRequest;
}
- return true;
+ return true; }
case WM_TryRelease: {
QSG_RT_DEBUG("WM_TryRelease");
mutex.lock();
- wm->m_locked = true;
+ wm->m_lockedForSync = true;
WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e);
if (!window || wme->inDestructor) {
QSG_RT_DEBUG(" - setting exit flag and invalidating GL");
invalidateOpenGL(wme->window, wme->inDestructor, wme->fallbackSurface);
active = gl;
+ Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateOpenGL()", "Thread's active state is not set to false when shutting down");
if (sleeping)
stopEventProcessing = true;
} else {
QSG_RT_DEBUG(" - not releasing anything because we have active windows...");
}
waitCondition.wakeOne();
- wm->m_locked = false;
+ wm->m_lockedForSync = false;
mutex.unlock();
return true;
}
@@ -489,11 +466,8 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor,
bool wipeGL = inDestructor || (wipeSG && !window->isPersistentOpenGLContext());
bool current = gl->makeCurrent(fallback ? static_cast<QSurface *>(fallback) : static_cast<QSurface *>(window));
- if (!current) {
-#ifndef QT_NO_DEBUG
- qWarning() << "Scene Graph failed to acquire GL context during cleanup";
-#endif
- return;
+ if (Q_UNLIKELY(!current)) {
+ QSG_RT_DEBUG(" - cleanup without an OpenGL context");
}
// The canvas nodes must be cleaned up regardless if we are in the destructor..
@@ -502,14 +476,16 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor,
dd->cleanupNodesOnShutdown();
} else {
QSG_RT_DEBUG(" - persistent SG, avoiding cleanup");
- gl->doneCurrent();
+ if (current)
+ gl->doneCurrent();
return;
}
sgrc->invalidate();
QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- gl->doneCurrent();
+ if (current)
+ gl->doneCurrent();
QSG_RT_DEBUG(" - invalidated scenegraph..");
if (wipeGL) {
@@ -525,12 +501,12 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor,
Enters the mutex lock to make sure GUI is blocking and performs
sync, then wakes GUI.
*/
-void QSGRenderThread::sync()
+void QSGRenderThread::sync(bool inExpose)
{
QSG_RT_DEBUG("sync()");
mutex.lock();
- Q_ASSERT_X(wm->m_locked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
+ Q_ASSERT_X(wm->m_lockedForSync, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
bool current = false;
if (windowSize.width() > 0 && windowSize.height() > 0)
@@ -557,11 +533,13 @@ void QSGRenderThread::sync()
QSG_RT_DEBUG(" - window has bad size, waiting...");
}
- waitCondition.wakeOne();
- mutex.unlock();
+ if (!inExpose) {
+ QSG_RT_DEBUG(" - sync complete, waking GUI");
+ waitCondition.wakeOne();
+ mutex.unlock();
+ }
}
-
void QSGRenderThread::syncAndRender()
{
#ifndef QSG_NO_RENDER_TIMING
@@ -578,16 +556,15 @@ void QSGRenderThread::syncAndRender()
syncResultedInChanges = false;
- bool repaintRequested = pendingUpdate & RepaintRequest;
- bool syncRequested = pendingUpdate & SyncRequest;
+ uint pending = pendingUpdate;
pendingUpdate = 0;
- if (syncRequested) {
+ if (pending & SyncRequest) {
QSG_RT_DEBUG(" - update pending, doing sync");
- sync();
+ sync(pending == ExposeRequest);
}
- if (!syncResultedInChanges && !(repaintRequested)) {
+ if (!syncResultedInChanges && ((pending & RepaintRequest) == 0)) {
QSG_RT_DEBUG(" - no changes, rendering aborted");
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
@@ -631,13 +608,11 @@ void QSGRenderThread::syncAndRender()
// that to avoid blocking the GUI thread in the case where it
// has started rendering with a bad window, causing makeCurrent to
// fail or if the window has a bad size.
- mutex.lock();
- if (exposeCycle == ExposePendingSwap) {
+ if (pending == ExposeRequest) {
QSG_RT_DEBUG(" - waking GUI after expose");
- exposeCycle = NoExpose;
waitCondition.wakeOne();
+ mutex.unlock();
}
- mutex.unlock();
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing)
@@ -824,49 +799,14 @@ void QSGThreadedRenderLoop::startOrStopAnimationTimer()
}
/*
- Adds this window to the list of tracked windows in this window
- manager. show() does not trigger rendering to start, that happens
- in expose.
- */
-
-void QSGThreadedRenderLoop::show(QQuickWindow *window)
-{
- QSG_GUI_DEBUG(window, "show()");
-
- if (Window *w = windowFor(m_windows, window)) {
- /* Safeguard ourselves against misbehaving platform plugins.
- *
- * When being shown, the window should not be exposed as the
- * platform plugin is only told to show after we send the show
- * event. If we are already shown at this time and we don't have
- * an active rendering thread we don't trust the plugin to send
- * us another expose event, so make this explicit call to
- * handleExposure.
- *
- * REF: QTCREATORBUG-10699
- */
- if (window->isExposed() && (!w->thread || !w->thread->window))
- handleExposure(w);
- return;
- }
-
- QSG_GUI_DEBUG(window, " - now tracking new window");
-
- Window win;
- win.window = window;
- win.actualWindowFormat = window->format();
- win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
- win.timerId = 0;
- win.updateDuringSync = false;
- m_windows << win;
-}
-
-
-
-/*
Removes this window from the list of tracked windowes in this
window manager. hide() will trigger obscure, which in turn will
stop rendering.
+
+ This function will be called during QWindow::close() which will
+ also destroy the QPlatformWindow so it is important that this
+ triggers handleObscurity() and that rendering for that window
+ is fully done and over with by the time this function exits.
*/
void QSGThreadedRenderLoop::hide(QQuickWindow *window)
@@ -889,17 +829,21 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
{
QSG_GUI_DEBUG(window, "windowDestroyed()");
- if (window->isVisible())
- hide(window);
- releaseResources(window, true);
+ Window *w = windowFor(m_windows, window);
+ if (!w)
+ return;
+
+ handleObscurity(w);
+ releaseResources(w, true);
+
+ QSGRenderThread *thread = w->thread;
+ while (thread->isRunning())
+ QThread::yieldCurrentThread();
+ Q_ASSERT(thread->thread() == QThread::currentThread());
+ delete thread;
for (int i=0; i<m_windows.size(); ++i) {
if (m_windows.at(i).window == window) {
- QSGRenderThread *thread = m_windows.at(i).thread;
- while (thread->isRunning())
- QThread::yieldCurrentThread();
- Q_ASSERT(thread->thread() == QThread::currentThread());
- delete thread;
m_windows.removeAt(i);
break;
}
@@ -912,14 +856,12 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
{
QSG_GUI_DEBUG(window, "exposureChanged()");
- Window *w = windowFor(m_windows, window);
- if (!w)
- return;
-
if (window->isExposed()) {
- handleExposure(w);
+ handleExposure(window);
} else {
- handleObscurity(w);
+ Window *w = windowFor(m_windows, window);
+ if (w)
+ handleObscurity(w);
}
}
@@ -927,9 +869,22 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
Will post an event to the render thread that this window should
start to render.
*/
-void QSGThreadedRenderLoop::handleExposure(Window *w)
+void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
{
- QSG_GUI_DEBUG(w->window, "handleExposure");
+ QSG_GUI_DEBUG(window, "handleExposure");
+
+ Window *w = windowFor(m_windows, window);
+ if (!w) {
+ QSG_GUI_DEBUG(window, " - adding window to list");
+ Window win;
+ win.window = window;
+ win.actualWindowFormat = window->format();
+ win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
+ win.timerId = 0;
+ win.updateDuringSync = false;
+ m_windows << win;
+ w = &m_windows.last();
+ }
if (w->window->width() <= 0 || w->window->height() <= 0
|| !w->window->geometry().intersects(w->window->screen()->availableGeometry())) {
@@ -982,20 +937,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
QSG_GUI_DEBUG(w->window, " - render thread already running");
}
- w->thread->postEvent(new WMExposeEvent(w->window));
- bool synced = polishAndSync(w);
-
- if (synced) {
- w->thread->mutex.lock();
- if (w->thread->exposeCycle != QSGRenderThread::NoExpose) {
- QSG_GUI_DEBUG(w->window, " - waiting for swap to complete...");
- w->thread->waitCondition.wait(&w->thread->mutex);
- }
- Q_ASSERT(w->thread->exposeCycle == QSGRenderThread::NoExpose);
- w->thread->mutex.unlock();
- } else {
- w->thread->postEvent(new QEvent(WM_ResetExposeCycle));
- }
+ polishAndSync(w, true);
QSG_GUI_DEBUG(w->window, " - handleExposure completed...");
startOrStopAnimationTimer();
@@ -1017,7 +959,6 @@ void QSGThreadedRenderLoop::handleObscurity(Window *w)
w->thread->waitCondition.wait(&w->thread->mutex);
w->thread->mutex.unlock();
}
-
startOrStopAnimationTimer();
}
@@ -1038,7 +979,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
if (!QCoreApplication::instance())
return;
- Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || m_locked,
+ Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || m_lockedForSync,
"QQuickItem::update()",
"Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
@@ -1081,21 +1022,24 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window)
}
+void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window)
+{
+ Window *w = windowFor(m_windows, window);
+ if (w)
+ releaseResources(w, false);
+}
/*!
* Release resources will post an event to the render thread to
* free up the SG and GL resources and exists the render thread.
*/
-void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestructor)
+void QSGThreadedRenderLoop::releaseResources(Window *w, bool inDestructor)
{
- QSG_GUI_DEBUG(window, "releaseResources requested...");
-
- Window *w = windowFor(m_windows, window);
- if (!w)
- return;
+ QSG_GUI_DEBUG(w->window, "releaseResources requested...");
w->thread->mutex.lock();
if (w->thread->isRunning() && w->thread->active) {
+ QQuickWindow *window = w->window;
// The platform window might have been destroyed before
// hide/release/windowDestroyed is called, so we need to have a
@@ -1105,16 +1049,15 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru
// create it here and pass it on to QSGRenderThread::invalidateGL()
QOffscreenSurface *fallback = 0;
if (!window->handle()) {
- QSG_GUI_DEBUG(w->window, " - using fallback surface");
+ QSG_GUI_DEBUG(window, " - using fallback surface");
fallback = new QOffscreenSurface();
fallback->setFormat(w->actualWindowFormat);
fallback->create();
}
- QSG_GUI_DEBUG(w->window, " - posting release request to render thread");
+ QSG_GUI_DEBUG(window, " - posting release request to render thread");
w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback));
w->thread->waitCondition.wait(&w->thread->mutex);
-
delete fallback;
}
w->thread->mutex.unlock();
@@ -1124,15 +1067,35 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru
/* Calls polish on all items, then requests synchronization with the render thread
* and blocks until that is complete. Returns false if it aborted; otherwise true.
*/
-bool QSGThreadedRenderLoop::polishAndSync(Window *w)
+void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
{
QSG_GUI_DEBUG(w->window, "polishAndSync()");
- if (!w->window->isExposed() || !w->window->isVisible() || w->window->size().isEmpty()) {
+ QQuickWindow *window = w->window;
+ if (!window->isExposed() || !window->isVisible() || window->size().isEmpty()) {
QSG_GUI_DEBUG(w->window, " - not exposed, aborting...");
killTimer(w->timerId);
w->timerId = 0;
- return false;
+ return;
+ }
+
+ // Flush pending touch events.
+ // First we force flushing of the windowing system events, so that we're
+ // working with the latest possible data. This can trigger event processing
+ // which in turn can stop rendering this window, so verify that before
+ // proceeding. Then we flush the touch event and as that also does event
+ // processing, verify again that we still are active and rendering.
+ QWindowSystemInterface::flushWindowSystemEvents();
+ w = windowFor(m_windows, window);
+ if (w) {
+ QQuickWindowPrivate::get(window)->flushDelayedTouchEvent();
+ w = windowFor(m_windows, window);
+ }
+ if (!w) {
+ QSG_GUI_DEBUG(w->window, " - removed after event flushing..");
+ killTimer(w->timerId);
+ w->timerId = 0;
+ return;
}
@@ -1146,7 +1109,7 @@ bool QSGThreadedRenderLoop::polishAndSync(Window *w)
timer.start();
#endif
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(w->window);
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->polishItems();
#ifndef QSG_NO_RENDER_TIMING
@@ -1156,22 +1119,22 @@ bool QSGThreadedRenderLoop::polishAndSync(Window *w)
w->updateDuringSync = false;
- emit w->window->afterAnimating();
+ emit window->afterAnimating();
- QSG_GUI_DEBUG(w->window, " - lock for sync...");
+ QSG_GUI_DEBUG(window, " - lock for sync...");
w->thread->mutex.lock();
- m_locked = true;
- w->thread->postEvent(new QEvent(WM_RequestSync));
+ m_lockedForSync = true;
+ w->thread->postEvent(new WMSyncEvent(window, inExpose));
- QSG_GUI_DEBUG(w->window, " - wait for sync...");
+ QSG_GUI_DEBUG(window, " - wait for sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
waitTime = timer.nsecsElapsed();
#endif
w->thread->waitCondition.wait(&w->thread->mutex);
- m_locked = false;
+ m_lockedForSync = false;
w->thread->mutex.unlock();
- QSG_GUI_DEBUG(w->window, " - unlocked after sync...");
+ QSG_GUI_DEBUG(window, " - unlocked after sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
@@ -1182,9 +1145,9 @@ bool QSGThreadedRenderLoop::polishAndSync(Window *w)
w->timerId = 0;
if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
- QSG_GUI_DEBUG(w->window, " - animations advancing");
+ QSG_GUI_DEBUG(window, " - animations advancing");
m_animation_driver->advance();
- QSG_GUI_DEBUG(w->window, " - animations done");
+ QSG_GUI_DEBUG(window, " - animations done");
// We need to trigger another sync to keep animations running...
maybePostPolishRequest(w);
emit timeToIncubate();
@@ -1196,7 +1159,7 @@ bool QSGThreadedRenderLoop::polishAndSync(Window *w)
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing)
qDebug(" - Gui Thread: window=%p, polish=%d, lock=%d, block/sync=%d -- animations=%d",
- w->window,
+ window,
int(polishTime/1000000),
int((waitTime - polishTime)/1000000),
int((syncTime - waitTime)/1000000),
@@ -1208,8 +1171,17 @@ bool QSGThreadedRenderLoop::polishAndSync(Window *w)
syncTime - waitTime,
timer.nsecsElapsed() - syncTime));
#endif
+}
- return true;
+QSGThreadedRenderLoop::Window *QSGThreadedRenderLoop::windowForTimer(int timerId) const
+{
+ for (int i=0; i<m_windows.size(); ++i) {
+ if (m_windows.at(i).timerId == timerId) {
+ return const_cast<Window *>(&m_windows.at(i));
+ break;
+ }
+ }
+ return 0;
}
bool QSGThreadedRenderLoop::event(QEvent *e)
@@ -1224,13 +1196,7 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
emit timeToIncubate();
} else {
QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> Polish & Sync");
- Window *w = 0;
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).timerId == te->timerId()) {
- w = const_cast<Window *>(&m_windows.at(i));
- break;
- }
- }
+ Window *w = windowForTimer(te->timerId());
if (w)
polishAndSync(w);
}
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index 82ab2cdaa0..b86b3c73a4 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -58,8 +58,8 @@ class QSGThreadedRenderLoop : public QSGRenderLoop
public:
QSGThreadedRenderLoop();
- void show(QQuickWindow *window);
- void hide(QQuickWindow *window);
+ void show(QQuickWindow *) {}
+ void hide(QQuickWindow *);
void windowDestroyed(QQuickWindow *window);
void exposureChanged(QQuickWindow *window);
@@ -73,7 +73,7 @@ public:
QAnimationDriver *animationDriver() const;
- void releaseResources(QQuickWindow *window) { releaseResources(window, false); }
+ void releaseResources(QQuickWindow *window);
bool event(QEvent *);
@@ -94,8 +94,9 @@ private:
friend class QSGRenderThread;
- void releaseResources(QQuickWindow *window, bool inDestructor);
+ void releaseResources(Window *window, bool inDestructor);
bool checkAndResetForceUpdate(QQuickWindow *window);
+ Window *windowForTimer(int timerId) const;
bool anyoneShowing() const;
void initialize();
@@ -103,10 +104,10 @@ private:
void startOrStopAnimationTimer();
void maybePostPolishRequest(Window *w);
void waitForReleaseComplete();
- bool polishAndSync(Window *w);
+ void polishAndSync(Window *w, bool inExpose = false);
void maybeUpdate(Window *window);
- void handleExposure(Window *w);
+ void handleExposure(QQuickWindow *w);
void handleObscurity(Window *w);
@@ -117,7 +118,7 @@ private:
int m_animation_timer;
int m_exhaust_delay;
- bool m_locked;
+ bool m_lockedForSync;
};
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index e20f9cdb9e..dc12d00490 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -442,6 +442,11 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
if (!m_gl->makeCurrent(window))
return;
+ d->flushDelayedTouchEvent();
+ // Event delivery or processing has caused the window to stop rendering.
+ if (!windowData(window))
+ return;
+
QSG_RENDER_TIMING_SAMPLE(time_start);
RLDEBUG(" - polishing");
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index e37344b21c..1ff7d11162 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -191,11 +191,9 @@ Atlas::~Atlas()
void Atlas::invalidate()
{
- Q_ASSERT(QOpenGLContext::currentContext());
- if (m_texture_id) {
+ if (m_texture_id && QOpenGLContext::currentContext())
glDeleteTextures(1, &m_texture_id);
- m_texture_id = 0;
- }
+ m_texture_id = 0;
}
Texture *Atlas::create(const QImage &image)
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
index 4512577f23..bbf115fa2a 100644
--- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
@@ -52,10 +52,12 @@ public:
: QSGGeometryNodePrivate()
, m_texCoordMode(QSGSimpleTextureNode::NoTransform)
, isAtlasTexture(false)
+ , ownsTexture(false)
{}
QSGSimpleTextureNode::TextureCoordinatesTransformMode m_texCoordMode;
uint isAtlasTexture : 1;
+ uint ownsTexture : 1;
};
static void qsgsimpletexturenode_update(QSGGeometry *g,
@@ -113,6 +115,16 @@ QSGSimpleTextureNode::QSGSimpleTextureNode()
}
/*!
+ Destroys the texture node
+ */
+QSGSimpleTextureNode::~QSGSimpleTextureNode()
+{
+ Q_D(QSGSimpleTextureNode);
+ if (d->ownsTexture)
+ delete m_material.texture();
+}
+
+/*!
Sets the filtering to be used for this texture node to \a filtering.
For smooth scaling, use QSGTexture::Linear; for normal scaling, use
@@ -170,6 +182,10 @@ QRectF QSGSimpleTextureNode::rect() const
/*!
Sets the texture of this texture node to \a texture.
+ Use setOwnsTexture() to set whether the node should take
+ ownership of the texture. By default, the node does not
+ take ownership.
+
\warning A texture node must have a texture before being added
to the scenegraph to be rendered.
*/
@@ -246,4 +262,26 @@ QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::text
return d->m_texCoordMode;
}
+/*!
+ Sets whether the node takes ownership of the texture to \a owns.
+
+ By default, the node does not take ownership of the texture.
+
+ \sa setTexture()
+ */
+void QSGSimpleTextureNode::setOwnsTexture(bool owns)
+{
+ Q_D(QSGSimpleTextureNode);
+ d->ownsTexture = owns;
+}
+
+/*!
+ Returns \c true if the node takes ownership of the texture; otherwise returns \c false.
+ */
+bool QSGSimpleTextureNode::ownsTexture() const
+{
+ Q_D(const QSGSimpleTextureNode);
+ return d->ownsTexture;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h
index 0c0b58442c..d971f00326 100644
--- a/src/quick/scenegraph/util/qsgsimpletexturenode.h
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h
@@ -54,6 +54,7 @@ class Q_QUICK_EXPORT QSGSimpleTextureNode : public QSGGeometryNode
{
public:
QSGSimpleTextureNode();
+ ~QSGSimpleTextureNode();
void setRect(const QRectF &rect);
inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
@@ -75,6 +76,9 @@ public:
void setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode);
TextureCoordinatesTransformMode textureCoordinatesTransform() const;
+ void setOwnsTexture(bool owns);
+ bool ownsTexture() const;
+
private:
QSGGeometry m_geometry;
QSGOpaqueTextureMaterial m_opaque_material;
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index a7f9174219..b90ca47fd1 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -508,6 +508,7 @@ void QQuickPixmapReader::processJobs()
replies.remove(reply);
reply->close();
}
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
// deleteLater, since not owned by this thread
job->deleteLater();
}
@@ -664,7 +665,11 @@ void QQuickPixmapReader::cancel(QQuickPixmapReply *reply)
// XXX
if (threadObject) threadObject->processJobs();
} else {
- jobs.removeAll(reply);
+ // If loading was started (reply removed from jobs) but the reply was never processed
+ // (otherwise it would have deleted itself) we need to profile an error.
+ if (jobs.removeAll(reply) == 0) {
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(reply->url));
+ }
delete reply;
}
mutex.unlock();
@@ -898,7 +903,9 @@ bool QQuickPixmapReply::event(QEvent *event)
data->textureFactory = de->textureFactory;
data->implicitSize = de->implicitSize;
Q_QUICK_PROFILE(pixmapLoadingFinished(data->url,
- data->requestSize.width() > 0 ? data->requestSize : data->implicitSize));
+ data->textureFactory != 0 && data->textureFactory->textureSize().isValid() ?
+ data->textureFactory->textureSize() :
+ (data->requestSize.isValid() ? data->requestSize : data->implicitSize)));
} else {
Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(data->url));
data->errorString = de->errorString;
@@ -907,6 +914,8 @@ bool QQuickPixmapReply::event(QEvent *event)
data->reply = 0;
emit finished();
+ } else {
+ Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
}
delete this;
@@ -975,10 +984,10 @@ void QQuickPixmapData::removeFromCache()
{
if (inCache) {
QQuickPixmapKey key = { &url, &requestSize };
- Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
- url, pixmapStore()->m_cache.count()));
pixmapStore()->m_cache.remove(key);
inCache = false;
+ Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
+ url, pixmapStore()->m_cache.count()));
}
}
@@ -1075,6 +1084,12 @@ QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &siz
load(engine, url, size);
}
+QQuickPixmap::QQuickPixmap(const QUrl &url, const QImage &image)
+{
+ d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize());
+ d->addToCache();
+}
+
QQuickPixmap::~QQuickPixmap()
{
if (d) {
@@ -1242,8 +1257,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
d = createPixmapDataSync(this, engine, url, requestSize, &ok);
if (ok) {
- Q_QUICK_PROFILE(pixmapLoadingFinished(url,
- d->requestSize.width() > 0 ? d->requestSize : d->implicitSize));
+ Q_QUICK_PROFILE(pixmapLoadingFinished(url, QSize(width(), height())));
if (options & QQuickPixmap::Cache)
d->addToCache();
return;
diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h
index aa1761e896..6ab1ff6482 100644
--- a/src/quick/util/qquickpixmapcache_p.h
+++ b/src/quick/util/qquickpixmapcache_p.h
@@ -78,6 +78,7 @@ public:
QQuickPixmap();
QQuickPixmap(QQmlEngine *, const QUrl &);
QQuickPixmap(QQmlEngine *, const QUrl &, const QSize &);
+ QQuickPixmap(const QUrl &, const QImage &image);
~QQuickPixmap();
enum Status { Null, Ready, Error, Loading };
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
index 610d80d559..022ba8c440 100644
--- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
@@ -84,7 +84,8 @@ QQmlEngineDebugClient::QQmlEngineDebugClient(
QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("QmlDebugger"), connection),
m_nextId(0),
- m_valid(false)
+ m_valid(false),
+ m_connection(connection)
{
}
@@ -467,6 +468,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
{
m_valid = false;
QDataStream ds(data);
+ ds.setVersion(m_connection->dataStreamVersion());
+
+
int queryId;
QByteArray type;
ds >> type >> queryId;
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
index 1d4b95a9e3..2712692389 100644
--- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
+++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
@@ -242,6 +242,8 @@ private:
QmlDebugObjectReference m_object;
QList<QmlDebugObjectReference> m_objects;
QVariant m_exprResult;
+
+ QQmlDebugConnection *m_connection;
};
#endif // QQMLENGINEDEBUGCLIENT_H
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index dbf28a5471..d5a5f10634 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -267,8 +267,8 @@ void tst_qqmlcomponent::qmlCreateParentReference()
void tst_qqmlcomponent::async()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -287,8 +287,8 @@ void tst_qqmlcomponent::async()
void tst_qqmlcomponent::asyncHierarchy()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
// ensure that the item hierarchy is compiled correctly.
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index a1e36b42e6..770d6b8197 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -4171,8 +4171,8 @@ void tst_qqmlecmascript::importScripts()
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory() + "/remote");
QStringList importPathList = engine.importPathList();
@@ -5999,8 +5999,8 @@ void tst_qqmlecmascript::include()
// Remote - error
{
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFileUrl("include_remote_missing.qml"));
@@ -6024,8 +6024,8 @@ void tst_qqmlecmascript::includeRemoteSuccess()
#endif
// Remote - success
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFileUrl("include_remote.qml"));
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 3561635351..be417df325 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -2298,7 +2298,8 @@ void tst_qqmllanguage::basicRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, url);
@@ -2342,7 +2343,8 @@ void tst_qqmllanguage::importsRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
testType(qml,type,error);
@@ -2434,7 +2436,8 @@ void tst_qqmllanguage::importsInstalledRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QString serverdir = "http://127.0.0.1:14447/lib/";
@@ -2500,7 +2503,8 @@ void tst_qqmllanguage::importsPath()
QFETCH(QString, qml);
QFETCH(QString, value);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
engine.setImportPathList(QStringList(defaultImportPathList) << importPath);
@@ -3076,7 +3080,8 @@ void tst_qqmllanguage::registeredCompositeType()
// QTBUG-18268
void tst_qqmllanguage::remoteLoadCrash()
{
- TestHTTPServer server(14448);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14448), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -3566,7 +3571,8 @@ void tst_qqmllanguage::compositeSingletonQmlDirError()
// Load a remote composite singleton type via qmldir that defines the type as a singleton
void tst_qqmllanguage::compositeSingletonRemote()
{
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFile("singletonTest15.qml"));
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index 15be1fdbc0..1861b37bea 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -247,8 +247,8 @@ void tst_qqmlmoduleplugin::importPluginWithQmlFile()
void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(m_dataImportsDirectory);
QQmlEngine engine;
@@ -268,8 +268,8 @@ void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
void tst_qqmlmoduleplugin::remoteImportWithUnquotedUri()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(m_dataImportsDirectory);
QQmlEngine engine;
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 17becb3714..e1ccde2c42 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -240,13 +240,12 @@ void tst_qqmlxmlhttprequest::open()
QFETCH(QString, url);
QFETCH(bool, remote);
- QScopedPointer<TestHTTPServer> server; // ensure deletion in case test fails
+ TestHTTPServer server;
if (remote) {
- server.reset(new TestHTTPServer(SERVER_PORT));
- QVERIFY(server->isValid());
- QVERIFY(server->wait(testFileUrl("open_network.expect"),
- testFileUrl("open_network.reply"),
- testFileUrl("testdocument.html")));
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("open_network.expect"),
+ testFileUrl("open_network.reply"),
+ testFileUrl("testdocument.html")));
}
QQmlComponent component(&engine, qmlFile);
@@ -322,8 +321,8 @@ void tst_qqmlxmlhttprequest::open_arg_count()
// Test valid setRequestHeader() calls
void tst_qqmlxmlhttprequest::setRequestHeader()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
@@ -340,8 +339,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader()
// Test valid setRequestHeader() calls with different header cases
void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
@@ -397,8 +396,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
{
QFETCH(QString, name);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("open_network.expect"),
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
@@ -423,8 +422,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
// Test that attempting to set a header after a request is sent throws an exception
void tst_qqmlxmlhttprequest::setRequestHeader_sent()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("open_network.expect"),
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
@@ -475,8 +474,8 @@ void tst_qqmlxmlhttprequest::send_alreadySent()
void tst_qqmlxmlhttprequest::send_ignoreData()
{
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_GET.expect"),
testFileUrl("send_ignoreData.reply"),
testFileUrl("testdocument.html")));
@@ -492,8 +491,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_HEAD.expect"),
testFileUrl("send_ignoreData.reply"),
QUrl()));
@@ -509,8 +508,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_DELETE.expect"),
testFileUrl("send_ignoreData.reply"),
QUrl()));
@@ -532,8 +531,8 @@ void tst_qqmlxmlhttprequest::send_withdata()
QFETCH(QString, file_expected);
QFETCH(QString, file_qml);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl(file_expected),
testFileUrl("send_data.reply"),
testFileUrl("testdocument.html")));
@@ -602,8 +601,8 @@ void tst_qqmlxmlhttprequest::abort_opened()
// Test abort() aborts in progress send
void tst_qqmlxmlhttprequest::abort()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("abort.expect"),
testFileUrl("abort.reply"),
testFileUrl("testdocument.html")));
@@ -626,8 +625,8 @@ void tst_qqmlxmlhttprequest::getResponseHeader()
{
QQmlEngine engine; // Avoid cookie contamination
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
testFileUrl("getResponseHeader.reply"),
testFileUrl("testdocument.html")));
@@ -693,8 +692,8 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders()
{
QQmlEngine engine; // Avoid cookie contamination
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
testFileUrl("getResponseHeader.reply"),
testFileUrl("testdocument.html")));
@@ -754,8 +753,8 @@ void tst_qqmlxmlhttprequest::status()
QFETCH(QUrl, replyUrl);
QFETCH(int, status);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
testFileUrl("testdocument.html")));
@@ -793,8 +792,8 @@ void tst_qqmlxmlhttprequest::statusText()
QFETCH(QUrl, replyUrl);
QFETCH(QString, statusText);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
testFileUrl("testdocument.html")));
@@ -833,8 +832,8 @@ void tst_qqmlxmlhttprequest::responseText()
QFETCH(QUrl, bodyUrl);
QFETCH(QString, responseText);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
bodyUrl));
@@ -934,8 +933,8 @@ void tst_qqmlxmlhttprequest::invalidMethodUsage()
void tst_qqmlxmlhttprequest::redirects()
{
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirecttarget.html");
server.serveDirectory(dataDirectory());
@@ -951,8 +950,8 @@ void tst_qqmlxmlhttprequest::redirects()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirectmissing.html");
server.serveDirectory(dataDirectory());
@@ -968,8 +967,8 @@ void tst_qqmlxmlhttprequest::redirects()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirect.html");
server.serveDirectory(dataDirectory());
@@ -1070,8 +1069,8 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
// ensure that we don't crash by attempting to evaluate
// without a valid calling context.
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQmlComponent component(&engine, testFileUrl("stateChangeCallingContext.qml"));
diff --git a/tests/auto/qmltest/item/tst_layerInPositioner.qml b/tests/auto/qmltest/item/tst_layerInPositioner.qml
new file mode 100644
index 0000000000..9144fe1d8f
--- /dev/null
+++ b/tests/auto/qmltest/item/tst_layerInPositioner.qml
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 400
+ height: 400
+
+ TestCase {
+ id: testCase
+ name: "transparentForPositioner"
+ when: windowShown
+ function test_endresult() {
+ var image = grabImage(root);
+
+ // Row of red, green, blue and white box inside blue
+ // At 10,10, spanning 10x10 pixels each
+ verify(image.pixel(10, 10) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(20, 10) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(30, 10) == Qt.rgba(0, 0, 1, 1));
+
+ // Column of red, green, blue and white box inside blue
+ // At 10,30, spanning 10x10 pixels each
+ verify(image.pixel(10, 30) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(10, 40) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(10, 50) == Qt.rgba(0, 0, 1, 1));
+
+ // Flow of red, green, blue and white box inside blue
+ // At 30,30, spanning 10x10 pixels each, wrapping after two boxes
+ verify(image.pixel(30, 30) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(40, 30) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(30, 40) == Qt.rgba(0, 0, 1, 1));
+
+ // Flow of red, green, blue and white box inside blue
+ // At 100,10, spanning 10x10 pixels each, wrapping after two boxes
+ verify(image.pixel(60, 10) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(70, 10) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(60, 20) == Qt.rgba(0, 0, 1, 1));
+ }
+ }
+
+ Component {
+ id: greenPassThrough
+ ShaderEffect {
+ fragmentShader:
+ "
+ uniform lowp sampler2D source;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor = texture2D(source, qt_TexCoord0) * vec4(0, 1, 0, 1);
+ }
+ "
+ }
+ }
+
+ Row {
+ id: theRow
+ x: 10
+ y: 10
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInRow
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Column {
+ id: theColumn
+ x: 10
+ y: 30
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInColumn
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Flow {
+ id: theFlow
+ x: 30
+ y: 30
+ width: 20
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInFlow
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Grid {
+ id: theGrid
+ x: 60
+ y: 10
+ columns: 2
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInGrid
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+}
diff --git a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
new file mode 100644
index 0000000000..4f827bbf33
--- /dev/null
+++ b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 400
+ height: 400
+
+ TestCase {
+ id: testCase
+ name: "item-grabber"
+ when: imageOnDisk.ready && imageOnDiskSmall.ready && imageInCache.ready && imageInCacheSmall.ready
+ function test_endresult() {
+ var image = grabImage(root);
+
+ // imageOnDisk at (0, 0) - (100x100)
+ compare(imageOnDisk.width, 100);
+ compare(imageOnDisk.height, 100);
+ verify(image.pixel(0, 0) === Qt.rgba(1, 0, 0, 1)); // Use verify because compare doesn't support colors (QTBUG-34878)
+ verify(image.pixel(99, 99) === Qt.rgba(0, 0, 1, 1));
+
+ // imageOnDiskSmall at (100, 0) - 50x50
+ compare(imageOnDiskSmall.width, 50);
+ compare(imageOnDiskSmall.height, 50);
+ verify(image.pixel(100, 0) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(149, 49) === Qt.rgba(0, 0, 1, 1));
+
+ // imageInCache at (0, 100) - 100x100
+ compare(imageInCache.width, 100);
+ compare(imageInCache.height, 100);
+ verify(image.pixel(0, 100) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(99, 199) === Qt.rgba(0, 0, 1, 1));
+
+ // imageInCacheSmall at (100, 100) - 50x50
+ compare(imageInCacheSmall.width, 50);
+ compare(imageInCacheSmall.height, 50);
+ verify(image.pixel(100, 100) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(149, 149) === Qt.rgba(0, 0, 1, 1));
+
+ // After all that has been going on, it should only have been called that one time..
+ compare(imageOnDisk.callCount, 1);
+ }
+
+ onWindowShownChanged: {
+ box.grabToImage(imageOnDisk.handleGrab);
+ box.grabToImage(imageOnDiskSmall.handleGrab, Qt.size(50, 50));
+ box.grabToImage(imageInCache.handleGrab);
+ box.grabToImage(imageInCacheSmall.handleGrab, Qt.size(50, 50));
+ }
+
+ }
+
+ Rectangle {
+ id: box
+ width: 100
+ height: 100
+ color: "red";
+
+ visible: false
+
+ Rectangle {
+ anchors.bottom: parent.bottom;
+ anchors.right: parent.right;
+ width: 10
+ height: 10
+ color: "blue";
+ }
+ }
+
+ Image {
+ id: imageOnDisk
+ x: 0
+ y: 0
+ property int callCount: 0;
+ property bool ready: false;
+ function handleGrab(result) {
+ if (!result.saveToFile("image.png"))
+ print("Error: Failed to save image to disk...");
+ source = "image.png";
+ ready = true;
+ ++callCount;
+ }
+ }
+
+ Image {
+ id: imageOnDiskSmall
+ x: 100
+ y: 0
+ property bool ready: false;
+ function handleGrab(result) {
+ if (!result.saveToFile("image_small.png"))
+ print("Error: Failed to save image to disk...");
+ source = "image_small.png";
+ ready = true;
+ }
+ }
+
+ Image {
+ id: imageInCache
+ x: 0
+ y: 100
+ property bool ready: false;
+ function handleGrab(result) {
+ source = result.url;
+ ready = true;
+ }
+ }
+
+ Image {
+ id: imageInCacheSmall
+ x: 100
+ y: 100
+ property bool ready: false;
+ function handleGrab(result) {
+ source = result.url;
+ ready = true;
+ }
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
new file mode 100644
index 0000000000..ba0289fadc
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Window 2.0
+import QtTest 1.0
+
+Item {
+ width: 100
+ height: 100
+
+ Window {
+ id: win
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+
+ title: "QML window"
+
+ onFrameSwapped: {
+ if (shaderSource.sourceItem) {
+ rendered = true;
+ } else {
+ var com = Qt.createQmlObject('import QtQuick 2.2; Rectangle { color: "red"; width: 100; height: 100 }', win);
+ shaderSource.sourceItem = com;
+ }
+ }
+
+ ShaderEffectSource {
+ id: shaderSource
+ }
+
+ }
+
+ TestCase {
+ when: win.rendered;
+ name: "shadersource-dynamic-sourceobject"
+ function test_endresult() {
+ var image = grabImage(shaderSource);
+ compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
new file mode 100644
index 0000000000..d9959d7fad
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.0
+
+import QtTest 1.0
+
+Item {
+ Rectangle {
+ id: box
+ color: "red"
+ }
+
+ Window {
+ id: childWindow
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+ onFrameSwapped: rendered = true;
+
+ ShaderEffectSource {
+ id: theSource
+ sourceItem: box
+ }
+
+ ShaderEffect {
+ property variant source: theSource;
+ anchors.fill: parent
+ }
+ }
+
+ TestCase {
+ name: "shadersource-from-other-window"
+ when: childWindow.isRendered
+ function test_endresult() {
+ verify(true); // that we got here without problems...
+ }
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
new file mode 100644
index 0000000000..436705befc
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.0
+
+import QtTest 1.0
+
+Item {
+ Rectangle {
+ id: box
+ color: "red"
+ }
+
+ ShaderEffectSource {
+ id: theSource
+ sourceItem: box
+ }
+
+ Window {
+ id: childWindow
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+ onFrameSwapped: rendered = true;
+
+ ShaderEffect {
+ property variant source: theSource;
+ anchors.fill: parent
+ }
+ }
+
+ TestCase {
+ name: "shadersource-from-other-window"
+ when: childWindow.isRendered
+ function test_endresult() {
+ verify(true); // that we got here without problems...
+ }
+ }
+}
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index 662e78ef6c..212337957e 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -52,6 +52,8 @@
#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/qsgsimplerectnode.h>
+#include <QtQuick/qsgsimpletexturenode.h>
+#include <QtQuick/private/qsgtexture_p.h>
class NodesTest : public QObject
{
@@ -74,6 +76,8 @@ private Q_SLOTS:
void isBlockedCheck();
+ void textureNodeTextureOwnership();
+
private:
QOffscreenSurface *surface;
QOpenGLContext *context;
@@ -259,6 +263,32 @@ void NodesTest::isBlockedCheck()
QVERIFY(!updater.isNodeBlocked(node, &root));
}
+void NodesTest::textureNodeTextureOwnership()
+{
+ { // Check that it is not deleted by default
+ QPointer<QSGTexture> texture(new QSGPlainTexture());
+
+ QSGSimpleTextureNode *tn = new QSGSimpleTextureNode();
+ QVERIFY(!tn->ownsTexture());
+
+ tn->setTexture(texture);
+ delete tn;
+ QVERIFY(!texture.isNull());
+ }
+
+ { // Check that it is deleted when we so desire
+ QPointer<QSGTexture> texture(new QSGPlainTexture());
+
+ QSGSimpleTextureNode *tn = new QSGSimpleTextureNode();
+ tn->setOwnsTexture(true);
+ QVERIFY(tn->ownsTexture());
+
+ tn->setTexture(texture);
+ delete tn;
+ QVERIFY(texture.isNull());
+ }
+}
+
QTEST_MAIN(NodesTest);
#include "tst_nodestest.moc"
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index d10963b579..49bbb3a4c5 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -259,8 +259,8 @@ void tst_qquickanimatedimage::remote()
QFETCH(QString, fileName);
QFETCH(bool, paused);
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -324,8 +324,8 @@ void tst_qquickanimatedimage::invalidSource()
void tst_qquickanimatedimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -390,8 +390,8 @@ void tst_qquickanimatedimage::sourceSizeChanges()
void tst_qquickanimatedimage::qtbug_16520()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -413,8 +413,8 @@ void tst_qquickanimatedimage::qtbug_16520()
void tst_qquickanimatedimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index dfcef43a7e..0993d03ee4 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -60,6 +60,7 @@ private slots:
void state();
void layoutDirection();
void inputMethod();
+ void cleanup();
private:
QQmlEngine engine;
@@ -69,6 +70,14 @@ tst_qquickapplication::tst_qquickapplication()
{
}
+void tst_qquickapplication::cleanup()
+{
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ QTest::waitForEvents();
+ }
+}
+
void tst_qquickapplication::active()
{
QQmlComponent component(&engine);
@@ -98,12 +107,19 @@ void tst_qquickapplication::active()
QVERIFY(item->property("active").toBool());
QVERIFY(item->property("active2").toBool());
- // not active again
QWindowSystemInterface::handleWindowActivated(0);
+#ifdef Q_OS_OSX
+ // OS X has the concept of "reactivation"
+ QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+#else
+ // not active again
QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
QVERIFY(!item->property("active").toBool());
QVERIFY(!item->property("active2").toBool());
+#endif
}
void tst_qquickapplication::state()
@@ -117,6 +133,7 @@ void tst_qquickapplication::state()
" target: Qt.application; "
" onStateChanged: state2 = Qt.application.state; "
" } "
+ " Component.onCompleted: state2 = Qt.application.state; "
"}", QUrl::fromLocalFile(""));
QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
QVERIFY(item);
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index 4e7b6522dd..c02a5c7a87 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -143,11 +143,10 @@ void tst_qquickborderimage::imageSource()
QFETCH(bool, remote);
QFETCH(QString, error);
- TestHTTPServer *server = 0;
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
if (!error.isEmpty())
@@ -177,7 +176,6 @@ void tst_qquickborderimage::imageSource()
}
delete obj;
- delete server;
}
void tst_qquickborderimage::clearSource()
@@ -292,11 +290,11 @@ void tst_qquickborderimage::sciSource()
QFETCH(bool, valid);
bool remote = source.startsWith("http");
- TestHTTPServer *server = 0;
+
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\"; width: 300; height: 300 }";
@@ -325,7 +323,6 @@ void tst_qquickborderimage::sciSource()
}
delete obj;
- delete server;
}
void tst_qquickborderimage::sciSource_data()
@@ -435,11 +432,10 @@ void tst_qquickborderimage::statusChanges()
QFETCH(bool, remote);
QFETCH(QQuickImageBase::Status, finalStatus);
- TestHTTPServer *server = 0;
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory(), TestHTTPServer::Delay);
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
QString componentStr = "import QtQuick 2.0\nBorderImage { width: 300; height: 300 }";
@@ -452,18 +448,17 @@ void tst_qquickborderimage::statusChanges()
QVERIFY(obj != 0);
obj->setSource(source);
if (remote)
- server->sendDelayedItem();
+ server.sendDelayedItem();
QTRY_VERIFY(obj->status() == finalStatus);
QCOMPARE(spy.count(), emissions);
delete obj;
- delete server;
}
void tst_qquickborderimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -528,8 +523,8 @@ void tst_qquickborderimage::sourceSizeChanges()
void tst_qquickborderimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 8ab86bf2d3..7cc3350b05 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -100,7 +100,7 @@ private slots:
void pressDelayWithLoader();
private:
- void flickWithTouch(QWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
+ void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
QQmlEngine engine;
};
@@ -1349,20 +1349,18 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QTRY_VERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f));
}
-void tst_qquickflickable::flickWithTouch(QWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to)
+void tst_qquickflickable::flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to)
{
- QTest::touchEvent(window, touchDevice)
- .press(0, from, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).press(0, from, window);
+ QQuickTouchUtils::flush(window);
+
QPoint diff = to - from;
for (int i = 1; i <= 8; ++i) {
- QTest::touchEvent(window, touchDevice)
- .move(0, from + i*diff/8, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).move(0, from + i*diff/8, window);
+ QQuickTouchUtils::flush(window);
}
- QTest::touchEvent(window, touchDevice)
- .release(0, to, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).release(0, to, window);
+ QQuickTouchUtils::flush(window);
}
void tst_qquickflickable::nestedStopAtBounds_data()
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index bcb496eab7..5c2bbf1650 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -75,8 +75,7 @@ private:
TestHTTPServer server;
};
-tst_qquickfontloader::tst_qquickfontloader() :
- server(SERVER_PORT)
+tst_qquickfontloader::tst_qquickfontloader()
{
}
@@ -84,7 +83,7 @@ void tst_qquickfontloader::initTestCase()
{
QQmlDataTest::initTestCase();
server.serveDirectory(dataDirectory());
- QVERIFY(server.isValid());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
}
void tst_qquickfontloader::noFont()
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 0e012c5c6a..7951cb07cf 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -177,9 +177,9 @@ void tst_qquickimage::imageSource()
QFETCH(bool, cache);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
if (remote) {
- QVERIFY(server.isValid());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
}
@@ -529,8 +529,8 @@ void tst_qquickimage::noLoading()
{
qRegisterMetaType<QQuickImageBase::Status>();
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
@@ -690,8 +690,8 @@ void tst_qquickimage::nullPixmapPaint()
void tst_qquickimage::imageCrash_QTBUG_22125()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
{
@@ -761,8 +761,8 @@ void tst_qquickimage::sourceSize()
void tst_qquickimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -827,8 +827,8 @@ void tst_qquickimage::sourceSizeChanges()
void tst_qquickimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -935,8 +935,8 @@ void tst_qquickimage::correctStatus()
void tst_qquickimage::highdpi()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QString componentStr = "import QtQuick 2.0\nImage { source: srcImage ; }";
diff --git a/tests/auto/quick/qquickitem/qquickitem.pro b/tests/auto/quick/qquickitem/qquickitem.pro
index d4bd0874d8..1d8ae0148b 100644
--- a/tests/auto/quick/qquickitem/qquickitem.pro
+++ b/tests/auto/quick/qquickitem/qquickitem.pro
@@ -3,6 +3,7 @@ TARGET = tst_qquickitem
SOURCES += tst_qquickitem.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
macx:CONFIG -= app_bundle
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 2db510a69e..40327b0666 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -51,6 +51,7 @@
#include <QTimer>
#include <QQmlEngine>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
class TestItem : public QQuickItem
{
@@ -1313,6 +1314,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QVERIFY(item->touchEventReached);
@@ -1336,6 +1338,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
@@ -1359,6 +1362,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
diff --git a/tests/auto/quick/qquickitem2/data/grabToImage.qml b/tests/auto/quick/qquickitem2/data/grabToImage.qml
new file mode 100644
index 0000000000..9f25210ee2
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/grabToImage.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+ Rectangle {
+ objectName: "myItem";
+ width: 100
+ height: 100
+ color: "red"
+ Rectangle {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ width: 10
+ height: 10
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index bcfafac93b..e7f0adb24d 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -43,6 +43,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQuick/qquickitemgrabresult.h>
#include <QtQuick/qquickview.h>
#include <QtGui/private/qinputmethod_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@@ -91,6 +92,7 @@ private slots:
void keyNavigation_RightToLeft();
void keyNavigation_skipNotVisible();
void keyNavigation_implicitSetting();
+ void keyNavigation_focusReason();
void layoutMirroring();
void layoutMirroringIllegalParent();
void smooth();
@@ -120,6 +122,8 @@ private slots:
void contains();
void childAt();
+ void grab();
+
private:
QQmlEngine engine;
bool qt_tab_all_widgets() {
@@ -215,6 +219,21 @@ public:
int mKey;
};
+class FocusEventFilter : public QObject
+{
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) {
+ if ((event->type() == QEvent::FocusIn) || (event->type() == QEvent::FocusOut)) {
+ QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
+ lastFocusReason = focusEvent->reason();
+ return false;
+ } else
+ return QObject::eventFilter(watched, event);
+ }
+public:
+ Qt::FocusReason lastFocusReason;
+};
+
QML_DECLARE_TYPE(KeyTestItem);
class HollowTestItem : public QQuickItem
@@ -1961,6 +1980,62 @@ void tst_QQuickItem::keyNavigation_implicitSetting()
delete window;
}
+void tst_QQuickItem::keyNavigation_focusReason()
+{
+ QQuickView *window = new QQuickView(0);
+ window->setBaseSize(QSize(240,320));
+
+ FocusEventFilter focusEventFilter;
+
+ window->setSource(testFileUrl("keynavigationtest.qml"));
+ window->show();
+ window->requestActivate();
+
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(QGuiApplication::focusWindow() == window);
+
+ // install event filter on first item
+ QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on second item
+ item = findItem<QQuickItem>(window->rootObject(), "item2");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on third item
+ item = findItem<QQuickItem>(window->rootObject(), "item3");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on last item
+ item = findItem<QQuickItem>(window->rootObject(), "item4");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ // tab
+ QKeyEvent key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::TabFocusReason);
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::BacktabFocusReason);
+
+ // some arbitrary cursor key
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::OtherFocusReason);
+
+ delete window;
+}
+
void tst_QQuickItem::smooth()
{
QQmlComponent component(&engine);
@@ -2737,6 +2812,41 @@ void tst_QQuickItem::childAt()
QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(0));
}
+void tst_QQuickItem::grab()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("grabToImage.qml"));
+ view.show();
+ QTest::qWaitForWindowExposed(&view);
+
+ QQuickItem *root = qobject_cast<QQuickItem *>(view.rootObject());
+ QVERIFY(root);
+ QQuickItem *item = root->findChild<QQuickItem *>("myItem");
+ QVERIFY(item);
+
+ { // Default size (item is 100x100)
+ QSharedPointer<QQuickItemGrabResult> result = item->grabToImage();
+ QSignalSpy spy(result.data(), SIGNAL(ready()));
+ QTRY_VERIFY(spy.size() > 0);
+ QVERIFY(!result->url().isEmpty());
+ QImage image = result->image();
+ QCOMPARE(image.pixel(0, 0), qRgb(255, 0, 0));
+ QCOMPARE(image.pixel(99, 99), qRgb(0, 0, 255));
+ }
+
+ { // Smaller size
+ QSharedPointer<QQuickItemGrabResult> result = item->grabToImage(QSize(50, 50));
+ QVERIFY(!result.isNull());
+ QSignalSpy spy(result.data(), SIGNAL(ready()));
+ QTRY_VERIFY(spy.size() > 0);
+ QVERIFY(!result->url().isEmpty());
+ QImage image = result->image();
+ QCOMPARE(image.pixel(0, 0), qRgb(255, 0, 0));
+ QCOMPARE(image.pixel(49, 49), qRgb(0, 0, 255));
+ }
+
+}
+
QTEST_MAIN(tst_QQuickItem)
diff --git a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
new file mode 100644
index 0000000000..6dfc5ee70a
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Window 2.1
+
+Rectangle {
+ id: root
+ width: 500
+ height: 600
+ property int animationDuration: 10
+ property int itemHeight: 40
+
+ Rectangle {
+ id: sightingsListPanel
+ border.width: 2
+ border.color: "lightgray"
+ y: 200
+ anchors.fill: parent
+ anchors.topMargin: 200
+ anchors.leftMargin: 200
+ ListView {
+ id: list
+ objectName: "list"
+ orientation: topToBottom ? ListView.Vertical : ListView.Horizontal
+ property bool transitionFinished: false
+ property bool scriptActionExecuted : false
+ anchors { fill: parent; margins: parent.border.width; }
+ model: testModel
+ delegate: listDelegate
+ // clip when we have no animation running
+ clip: false
+ add: Transition {
+ id: trans
+ onRunningChanged: {
+ if (!running)
+ list.transitionFinished = true;
+ }
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: -100; duration: root.animationDuration }
+ NumberAnimation { properties: "y"; from: -100; duration: root.animationDuration }
+ NumberAnimation { properties: "width"; from: 1; to: list.width; duration: root.animationDuration;}
+ // Commenting out the height animation and it works
+ NumberAnimation { properties: "height"; from: 1; to: root.itemHeight; duration: root.animationDuration }
+ }
+ ScriptAction { script: list.scriptActionExecuted = true;}
+ }
+
+ }
+ }
+ // Delegate for defining a template for an item in the list
+ Component {
+ id: listDelegate
+ Rectangle {
+ id: background
+ width: list.width
+ height: root.itemHeight
+ border.width: 2
+ radius: 3
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 5cc3c7e642..c05434166d 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -194,6 +194,9 @@ private slots:
void populateTransitions();
void populateTransitions_data();
+ void sizeTransitions();
+ void sizeTransitions_data();
+
void addTransitions();
void addTransitions_data();
void moveTransitions();
@@ -5799,6 +5802,56 @@ void tst_QQuickListView::populateTransitions_data()
QTest::newRow("empty to start with, no populate") << false << false << false;
}
+
+/*
+ * Tests if the first visible item is not repositioned if the same item
+ * resized + changes position during a transition. The test does not test the
+ * actual position while it is transitioning (since its timing sensitive), but
+ * rather tests if the transition has reached its target state properly.
+ **/
+void tst_QQuickListView::sizeTransitions()
+{
+ QFETCH(bool, topToBottom);
+ QQuickView *window = getView();
+ QQmlContext *ctxt = window->rootContext();
+ QaimModel model;
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("topToBottom", topToBottom);
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", &model);
+ window->setSource(testFileUrl("sizeTransitions.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+ // the following will start the transition
+ model.addItem(QLatin1String("Test"), "");
+
+ // This ensures early failure in case of failure (in which case
+ // transitionFinished == true and scriptActionExecuted == false)
+ QTRY_COMPARE(listview->property("scriptActionExecuted").toBool() ||
+ listview->property("transitionFinished").toBool(), true);
+ QCOMPARE(listview->property("scriptActionExecuted").toBool(), true);
+ QCOMPARE(listview->property("transitionFinished").toBool(), true);
+
+ releaseView(window);
+ delete testObject;
+}
+
+void tst_QQuickListView::sizeTransitions_data()
+{
+ QTest::addColumn<bool>("topToBottom");
+
+ QTest::newRow("TopToBottom")
+ << true;
+
+ QTest::newRow("LeftToRight")
+ << false;
+}
+
void tst_QQuickListView::addTransitions()
{
QFETCH(int, initialItemCount);
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 877bb59613..9ac2663f24 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -446,8 +446,8 @@ void tst_QQuickLoader::noResize()
void tst_QQuickLoader::networkRequestUrl()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -470,8 +470,8 @@ void tst_QQuickLoader::networkRequestUrl()
/* XXX Component waits until all dependencies are loaded. Is this actually possible? */
void tst_QQuickLoader::networkComponent()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQmlComponent component(&engine);
@@ -503,8 +503,8 @@ void tst_QQuickLoader::networkComponent()
void tst_QQuickLoader::failNetworkRequest()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QTest::ignoreMessage(QtWarningMsg, SERVER_ADDR "/IDontExist.qml: File not found");
@@ -718,8 +718,8 @@ void tst_QQuickLoader::initialPropertyValues()
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
foreach (const QString &warning, expectedWarnings)
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index d0a1c18885..ee29ed2075 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -86,6 +86,7 @@ private slots:
void resetDrag();
void dragging_data() { acceptedButton_data(); }
void dragging();
+ void dragSmoothed();
void dragThreshold();
void invalidDrag_data() { rejectedButton_data(); }
void invalidDrag();
@@ -334,6 +335,50 @@ void tst_QQuickMouseArea::dragging()
QCOMPARE(blackRect->y(), 61.0);
}
+void tst_QQuickMouseArea::dragSmoothed()
+{
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QQuickDrag *drag = mouseRegion->drag();
+ drag->setThreshold(5);
+
+ mouseRegion->setAcceptedButtons(Qt::LeftButton);
+ QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == drag->target());
+ QVERIFY(!drag->active());
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QVERIFY(!drag->active());
+ QTest::mouseMove(&window, QPoint(100, 102), 50);
+ QTest::mouseMove(&window, QPoint(100, 106), 50);
+ QTest::mouseMove(&window, QPoint(100, 122), 50);
+ QTRY_COMPARE(blackRect->x(), 50.0);
+ QTRY_COMPARE(blackRect->y(), 66.0);
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100,122));
+
+ // reset rect position
+ blackRect->setX(50.0);
+ blackRect->setY(50.0);
+
+ // now try with smoothed disabled
+ drag->setSmoothed(false);
+ QVERIFY(!drag->active());
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QVERIFY(!drag->active());
+ QTest::mouseMove(&window, QPoint(100, 102), 50);
+ QTest::mouseMove(&window, QPoint(100, 106), 50);
+ QTest::mouseMove(&window, QPoint(100, 122), 50);
+ QTRY_COMPARE(blackRect->x(), 50.0);
+ QTRY_COMPARE(blackRect->y(), 72.0);
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 122));
+}
void tst_QQuickMouseArea::dragThreshold()
{
diff --git a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
index d3abc198d9..5724a7179e 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
+++ b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
@@ -8,6 +8,7 @@ SOURCES += tst_qquickmultipointtoucharea.cpp
TESTDATA = data/*
include(../../shared/util.pri)
+include(../shared/util.pri)
QT += core-private gui-private qml-private quick-private testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 1d4932c432..842babddd9 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -48,12 +48,14 @@
#include <QtQuick/qquickview.h>
#include <QtGui/QScreen>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
class tst_QQuickMultiPointTouchArea : public QQmlDataTest
{
Q_OBJECT
public:
tst_QQuickMultiPointTouchArea() : device(0) { }
+
private slots:
void initTestCase() {
QQmlDataTest::initTestCase();
@@ -118,6 +120,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -126,6 +129,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QMetaObject::invokeMethod(area, "clearCounts");
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 1);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -136,6 +140,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
sequence.move(0, p1).move(1, p2).stationary(2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
@@ -146,6 +151,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
p3 += QPoint(10,10);
sequence.release(0, p1).release(1, p2)
.move(2, p3).press(3, p4).press(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 1);
@@ -154,6 +160,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QMetaObject::invokeMethod(area, "clearCounts");
sequence.release(2, p3).release(3, p4).release(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -177,12 +184,14 @@ void tst_QQuickMultiPointTouchArea::release()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
p1 += QPoint(0,10);
sequence.move(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point1->x(), qreal(20)); QCOMPARE(point1->y(), qreal(110));
@@ -190,6 +199,7 @@ void tst_QQuickMultiPointTouchArea::release()
p1 += QPoint(4,10);
sequence.release(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
//test that a release without a prior move to the release position successfully updates the point's position
QCOMPARE(point1->pressed(), false);
@@ -216,12 +226,14 @@ void tst_QQuickMultiPointTouchArea::reuse()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.release(0, p1).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
//we shouldn't reuse point 1 yet
QCOMPARE(point1->pressed(), false);
@@ -230,24 +242,28 @@ void tst_QQuickMultiPointTouchArea::reuse()
//back to base state (no touches)
sequence.release(1, p2).release(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), false);
QCOMPARE(point2->pressed(), false);
QCOMPARE(point3->pressed(), false);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.release(0, p1).stationary(1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), false);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.press(4, p4).stationary(1).commit();
+ QQuickTouchUtils::flush(window.data());
//the new touch point should reuse point 1
QCOMPARE(point1->pressed(), true);
@@ -283,6 +299,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -291,6 +308,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -304,6 +322,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
p1 += QPoint(0,10);
p2 += QPoint(5,0);
sequence.move(0, p1).move(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -315,6 +334,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -323,6 +343,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).stationary(1).stationary(2).press(3, p4).press(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -342,6 +363,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
p4 += QPoint(1,-1);
p5 += QPoint(-7,10);
sequence.move(0, p1).move(1, p2).move(2, p3).move(3, p4).move(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -356,6 +378,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->x(), qreal(93)); QCOMPARE(point23->y(), qreal(30));
sequence.release(0, p1).release(1, p2).release(2, p3).release(3, p4).release(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -388,6 +411,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -396,6 +420,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -409,6 +434,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p1 += QPoint(0,10);
p2 += QPoint(5,0);
sequence.move(0, p1).move(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -420,6 +446,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -435,6 +462,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
sequence.stationary(0).stationary(1).stationary(2).press(3, QPoint(80,180)).press(4, QPoint(100,180)).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -455,6 +483,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 += QPoint(17,17);
p3 += QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -472,6 +501,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 += QPoint(17,17);
p3 += QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -489,6 +519,7 @@ void tst_QQuickMultiPointTouchArea::nested()
sequence.release(0, p1).release(1, p2).release(2, p3).commit();
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -497,11 +528,13 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->pressed(), false);
sequence.release(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
//test with grabbing turned off
window->rootObject()->setProperty("grabInnerArea", false);
sequence.press(0, p1).press(1, p2).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -513,6 +546,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 -= QPoint(17,17);
p3 -= QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -530,6 +564,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 -= QPoint(17,17);
p3 -= QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -545,6 +580,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
sequence.release(0, p1).release(1, p2).release(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
}
void tst_QQuickMultiPointTouchArea::inFlickable()
@@ -569,25 +605,30 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
//moving one point vertically
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
QTest::touchEvent(window.data(), device).release(0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -595,6 +636,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 = QPoint(20,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -604,18 +646,22 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QCOMPARE(point11->pressed(), false);
@@ -625,7 +671,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -633,6 +679,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 = QPoint(20,100);
p2 = QPoint(40,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
+ QQuickTouchUtils::flush(window.data());
// ensure that mouse events do not fall through to the Flickable
mpta->setMaximumTouchPoints(3);
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
@@ -643,34 +690,42 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() == 0);
QCOMPARE(point11->pressed(), true);
@@ -678,7 +733,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
}
// test that dragging out of a Flickable containing a MPTA doesn't harm Flickable's state.
@@ -699,28 +754,34 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
// move point horizontally, out of Flickable area
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
QVERIFY(!flickable->isMoving());
QVERIFY(point11->pressed());
QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
QTest::qWait(50);
@@ -729,26 +790,32 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
// Check that we can still move the Flickable
p1 = QPoint(50,100);
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QVERIFY(flickable->isMoving());
QCOMPARE(point11->pressed(), true);
QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::qWait(50);
QTRY_VERIFY(!flickable->isMoving());
@@ -859,7 +926,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Touch both, release one, manipulate other touchpoint with mouse
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).press(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -867,12 +936,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QTest::touchEvent(window.data(), device).release(1, touch1);
touch1.setY(20);
QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
QTest::touchEvent(window.data(), device).release(2, touch2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+ QQuickTouchUtils::flush(window.data());
// Start with mouse, move it, touch second point, move it
QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
@@ -882,12 +953,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
touch2.setX(60);
QTest::touchEvent(window.data(), device).press(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
touch2.setY(150);
QTest::touchEvent(window.data(), device).move(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -895,6 +968,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Touch third point - nothing happens
QTest::touchEvent(window.data(), device).press(4, touch3);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -903,7 +977,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
QTest::touchEvent(window.data(), device).release(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(4, touch3);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -922,12 +998,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
QCOMPARE(touch2rect->property("y").toInt(), touch1.y());
QTest::touchEvent(window.data(), device).press(2, touch2).press(3, touch3).press(4, touch4);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
@@ -942,6 +1020,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1).release(2, touch2).release(3, touch3).release(4, touch4);
+ QQuickTouchUtils::flush(window.data());
}
dualmpta->setProperty("mouseEnabled", false);
@@ -964,13 +1043,16 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("y").toInt(), 10);
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
touch1.setY(150);
QTest::touchEvent(window.data(), device).move(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QTest::touchEvent(window.data(), device).press(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -979,7 +1061,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -1028,7 +1112,6 @@ void tst_QQuickMultiPointTouchArea::transformedTouchArea_data()
QTest::newRow("3rd point inside")
<< QPoint(140, 260) << QPoint(260, 140) << QPoint(200, 140) << 0 << 0 << 1;
-
QTest::newRow("all points inside")
<< QPoint(200, 140) << QPoint(200, 260) << QPoint(140, 200) << 1 << 2 << 3;
diff --git a/tests/auto/quick/qquickpincharea/qquickpincharea.pro b/tests/auto/quick/qquickpincharea/qquickpincharea.pro
index 970ce48851..fa14afa261 100644
--- a/tests/auto/quick/qquickpincharea/qquickpincharea.pro
+++ b/tests/auto/quick/qquickpincharea/qquickpincharea.pro
@@ -6,6 +6,7 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquickpincharea.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index b9d314b63e..1dbce1b730 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -48,6 +48,7 @@
#include <QtQuick/qquickview.h>
#include <QtQml/qqmlcontext.h>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
class tst_QQuickPinchArea: public QQmlDataTest
{
@@ -232,15 +233,18 @@ void tst_QQuickPinchArea::scale()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -248,6 +252,7 @@ void tst_QQuickPinchArea::scale()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.5);
QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
@@ -260,8 +265,10 @@ void tst_QQuickPinchArea::scale()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->scale(), 2.0);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
}
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -293,12 +300,15 @@ void tst_QQuickPinchArea::pan()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 += QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -306,6 +316,7 @@ void tst_QQuickPinchArea::pan()
p1 += QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
}
QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50
@@ -316,11 +327,13 @@ void tst_QQuickPinchArea::pan()
p1 += QPoint(100,100);
p2 += QPoint(100,100);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->x(), 140.0);
QCOMPARE(blackRect->y(), 160.0);
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -355,12 +368,15 @@ void tst_QQuickPinchArea::retouch()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -368,6 +384,7 @@ void tst_QQuickPinchArea::retouch()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(startedSpy.count(), 1);
@@ -382,6 +399,7 @@ void tst_QQuickPinchArea::retouch()
// Hold down the first finger but release the second one
pinchSequence.stationary(0).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 0);
@@ -390,9 +408,11 @@ void tst_QQuickPinchArea::retouch()
// Keep holding down the first finger and re-touch the second one, then move them both
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
// Lifting and retouching results in onPinchStarted being called again
QCOMPARE(startedSpy.count(), 2);
@@ -401,6 +421,7 @@ void tst_QQuickPinchArea::retouch()
QCOMPARE(window->rootObject()->property("pointCount").toInt(), 2);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
QCOMPARE(startedSpy.count(), 2);
@@ -456,14 +477,18 @@ void tst_QQuickPinchArea::transformedPinchArea()
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device);
// start pinch
pinchSequence.press(0, p1, view).commit();
+ QQuickTouchUtils::flush(view);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, view).commit();
+ QQuickTouchUtils::flush(view);
pinchSequence.stationary(0).move(1, p2 + QPoint(threshold * 2, 0), view).commit();
+ QQuickTouchUtils::flush(view);
QCOMPARE(pinchArea->property("pinching").toBool(), shouldPinch);
// release pinch
pinchSequence.release(0, p1, view).release(1, p2, view).commit();
+ QQuickTouchUtils::flush(view);
QCOMPARE(pinchArea->property("pinching").toBool(), false);
}
}
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index 75bd468aef..f104154205 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -59,7 +59,7 @@ class tst_qquickpixmapcache : public QQmlDataTest
{
Q_OBJECT
public:
- tst_qquickpixmapcache() : server(14452) {}
+ tst_qquickpixmapcache() {}
private slots:
void initTestCase();
@@ -116,6 +116,8 @@ void tst_qquickpixmapcache::initTestCase()
{
QQmlDataTest::initTestCase();
+ QVERIFY2(server.listen(14452), qPrintable(server.errorString()));
+
// This avoids a race condition/deadlock bug in network config
// manager when it is accessed by the HTTP server thread before
// anything else. Bug report can be found at:
@@ -379,7 +381,8 @@ void tst_qquickpixmapcache::shrinkcache()
void createNetworkServer()
{
QEventLoop eventLoop;
- TestHTTPServer server(14453);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14453), qPrintable(server.errorString()));
server.serveDirectory(QQmlDataTest::instance()->testFile("http"));
QTimer::singleShot(100, &eventLoop, SLOT(quit()));
eventLoop.exec();
@@ -407,7 +410,8 @@ void tst_qquickpixmapcache::networkCrash()
// QTBUG-22125
void tst_qquickpixmapcache::lockingCrash()
{
- TestHTTPServer server(14453);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14453), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"), TestHTTPServer::Delay);
{
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index d36c55d687..9ca7cafe3d 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -2029,7 +2029,8 @@ void tst_qquicktext::embeddedImages()
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"));
if (!error.isEmpty())
@@ -2767,7 +2768,8 @@ void tst_qquicktext::imgTagsBaseUrl()
QFETCH(QUrl, contextUrl);
QFETCH(qreal, imgHeight);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile(""));
QByteArray baseUrlFragment;
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 1ffd67cbf1..f8fc4c10da 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -2604,7 +2604,8 @@ void tst_qquicktextedit::cursorDelegate()
void tst_qquicktextedit::remoteCursorDelegate()
{
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQuickView view;
@@ -2741,7 +2742,8 @@ void tst_qquicktextedit::delegateLoading()
QFETCH(QString, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
server.serveDirectory(testFile("http"));
@@ -5215,7 +5217,8 @@ void tst_qquicktextedit::embeddedImages()
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"));
if (!error.isEmpty())
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index e125c33a56..fc1be16bc8 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -232,6 +232,8 @@ private slots:
void baselineOffset_data();
void baselineOffset();
+ void ensureVisible();
+
private:
void simulateKey(QWindow *, int key);
@@ -2490,7 +2492,7 @@ void tst_qquicktextinput::copyAndPaste()
QCOMPARE(textInput->selectedText(), QString("Hello world!"));
QCOMPARE(textInput->selectedText().length(), 12);
textInput->setCursorPosition(0);
- QVERIFY(textInput->canPaste());
+ QTRY_VERIFY(textInput->canPaste());
textInput->paste();
QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
QCOMPARE(textInput->text().length(), 24);
@@ -2544,7 +2546,7 @@ void tst_qquicktextinput::copyAndPaste()
QClipboard *clipboard = QGuiApplication::clipboard();
QVERIFY(clipboard);
clipboard->clear();
- QVERIFY(!textInput->canPaste());
+ QTRY_VERIFY(!textInput->canPaste());
// test that copy functionality is disabled
// when echo mode is set to hide text/password mode
@@ -2612,7 +2614,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
QClipboard *clipboard = QGuiApplication::clipboard();
QVERIFY(clipboard);
clipboard->clear();
- QVERIFY(!textInput->canPaste());
+ QTRY_VERIFY(!textInput->canPaste());
// test that copy functionality is disabled
// when echo mode is set to hide text/password mode
@@ -2853,7 +2855,8 @@ void tst_qquicktextinput::cursorDelegate()
void tst_qquicktextinput::remoteCursorDelegate()
{
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQuickView view;
@@ -6463,6 +6466,50 @@ void tst_qquicktextinput::baselineOffset()
}
}
+void tst_qquicktextinput::ensureVisible()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+ QVERIFY(input);
+
+ input->setWidth(QFontMetrics(input->font()).averageCharWidth() * 3);
+ input->setText("Hello World");
+
+ QTextLayout layout;
+ layout.setText(input->text());
+ layout.setFont(input->font());
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ input->ensureVisible(0);
+
+ QCOMPARE(input->boundingRect().x(), qreal(0));
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+
+ QSignalSpy cursorSpy(input, SIGNAL(cursorRectangleChanged()));
+ QVERIFY(cursorSpy.isValid());
+
+ input->ensureVisible(input->length());
+
+ QCOMPARE(cursorSpy.count(), 1);
+
+ QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth());
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro
index 6bce209df9..e95b7dbb10 100644
--- a/tests/auto/quick/qquickwindow/qquickwindow.pro
+++ b/tests/auto/quick/qquickwindow/qquickwindow.pro
@@ -3,6 +3,7 @@ TARGET = tst_qquickwindow
SOURCES += tst_qquickwindow.cpp
include (../../shared/util.pri)
+include(../shared/util.pri)
macx:CONFIG -= app_bundle
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index b05146fa3a..a2e2980223 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -49,6 +49,7 @@
#include <QtQuick/private/qquickrectangle_p.h>
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
+#include "../shared/viewtestutil.h"
#include <QSignalSpy>
#include <qpa/qwindowsysteminterface.h>
#include <private/qquickwindow_p.h>
@@ -327,6 +328,7 @@ private slots:
void animationsWhileHidden();
void focusObject();
+ void focusReason();
void ignoreUnhandledMouseEvents();
@@ -359,6 +361,9 @@ private slots:
void contentItemSize();
+ void defaultSurfaceFormat();
+ void glslVersion();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -392,7 +397,7 @@ void tst_qquickwindow::aboutToStopSignal()
window.hide();
- QVERIFY(spy.count() > 0);
+ QTRY_VERIFY(spy.count() > 0);
}
//If the item calls update inside updatePaintNode, it should schedule another sync pass
@@ -519,7 +524,7 @@ void tst_qquickwindow::touchEvent_basic()
// press multiple points
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -530,9 +535,9 @@ void tst_qquickwindow::touchEvent_basic()
// touch point on top item moves to bottom item, but top item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
@@ -540,9 +545,9 @@ void tst_qquickwindow::touchEvent_basic()
// touch point on bottom item moves to top item, but bottom item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
@@ -550,10 +555,10 @@ void tst_qquickwindow::touchEvent_basic()
// a single stationary press on an item shouldn't cause an event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).stationary(0)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -565,12 +570,13 @@ void tst_qquickwindow::touchEvent_basic()
// Otherwise you will get an assertion failure:
// ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickwindow.cpp
QTest::touchEvent(window, touchDevice).release(0, pos.toPoint(), window).release(1, pos.toPoint(), window);
+ QQuickTouchUtils::flush(window);
// move touch point from top item to bottom, and release
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(),window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
@@ -579,12 +585,12 @@ void tst_qquickwindow::touchEvent_basic()
// release while another point is pressed
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window)
.stationary(1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -832,12 +838,15 @@ void tst_qquickwindow::touchEvent_velocity()
tp.area = QRectF(pos, QSizeF(4, 4));
points << tp;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QVector2D velocity(1.5, 2.5);
points[0].velocity = velocity;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->touchEventCount, 2);
QCOMPARE(item->lastEvent.touchPoints.count(), 1);
QCOMPARE(item->lastVelocity, velocity);
@@ -849,7 +858,8 @@ void tst_qquickwindow::touchEvent_velocity()
QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
points[0].area.adjust(5, 5, 5, 5);
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->lastVelocity, transformedVelocity);
QPoint itemLocalPos = item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint();
QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].pos().toPoint();
@@ -857,7 +867,8 @@ void tst_qquickwindow::touchEvent_velocity()
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
delete item;
}
@@ -889,14 +900,19 @@ void tst_qquickwindow::mouseFromTouch_basic()
tp.area = QRectF(pos, QSizeF(4, 4));
points << tp;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QVector2D velocity(1.5, 2.5);
points[0].velocity = velocity;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
// The item should have received a mouse press, move, and release.
QCOMPARE(item->mousePressNum, 1);
@@ -915,16 +931,20 @@ void tst_qquickwindow::mouseFromTouch_basic()
points[0].velocity = velocity;
points[0].area = QRectF(pos, QSizeF(4, 4));
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity);
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
QCoreApplication::processEvents();
+ QQuickTouchUtils::flush(window);
delete item;
}
@@ -1272,6 +1292,33 @@ void tst_qquickwindow::focusObject()
QCOMPARE(focusObjectSpy.count(), 3);
}
+void tst_qquickwindow::focusReason()
+{
+ QQuickWindow *window = new QQuickWindow;
+ QScopedPointer<QQuickWindow> cleanup(window);
+ window->resize(200, 200);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickItem *firstItem = new QQuickItem;
+ firstItem->setSize(QSizeF(100, 100));
+ firstItem->setParentItem(window->contentItem());
+
+ QQuickItem *secondItem = new QQuickItem;
+ secondItem->setSize(QSizeF(100, 100));
+ secondItem->setParentItem(window->contentItem());
+
+ firstItem->forceActiveFocus(Qt::OtherFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::OtherFocusReason);
+
+ secondItem->forceActiveFocus(Qt::TabFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::TabFocusReason);
+
+ firstItem->forceActiveFocus(Qt::BacktabFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::BacktabFocusReason);
+
+}
+
void tst_qquickwindow::ignoreUnhandledMouseEvents()
{
QQuickWindow *window = new QQuickWindow;
@@ -1828,6 +1875,79 @@ void tst_qquickwindow::contentItemSize()
QCOMPARE(QSizeF(rect->width(), rect->height()), size);
}
+void tst_qquickwindow::defaultSurfaceFormat()
+{
+ // It is quite difficult to verify anything for real since the resulting format after
+ // surface/context creation can be anything, depending on the platform and drivers,
+ // and many options and settings may fail in various configurations, but test at
+ // least using some harmless settings to check that the global, static format is
+ // taken into account in the requested format.
+
+ QSurfaceFormat savedDefaultFormat = QQuickWindow::defaultFormat();
+
+ // Verify that depth and stencil are set, as they should be, unless they are disabled
+ // via environment variables.
+ QVERIFY(savedDefaultFormat.depthBufferSize() >= 16);
+ QVERIFY(savedDefaultFormat.stencilBufferSize() >= 8);
+
+ QSurfaceFormat format = savedDefaultFormat;
+ format.setSwapInterval(0);
+ format.setRedBufferSize(8);
+ format.setGreenBufferSize(8);
+ format.setBlueBufferSize(8);
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ format.setOption(QSurfaceFormat::DebugContext);
+ QQuickWindow::setDefaultFormat(format);
+
+ QQuickWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ const QSurfaceFormat reqFmt = window.requestedFormat();
+ QCOMPARE(format.swapInterval(), reqFmt.swapInterval());
+ QCOMPARE(format.redBufferSize(), reqFmt.redBufferSize());
+ QCOMPARE(format.greenBufferSize(), reqFmt.greenBufferSize());
+ QCOMPARE(format.blueBufferSize(), reqFmt.blueBufferSize());
+ QCOMPARE(format.profile(), reqFmt.profile());
+ QCOMPARE(int(format.options()), int(reqFmt.options()));
+
+ QQuickWindow::setDefaultFormat(savedDefaultFormat);
+}
+
+void tst_qquickwindow::glslVersion()
+{
+ QQuickWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // Core profile is never requested by default.
+ QVERIFY(!window.glslIsCoreProfile());
+
+ // Get the format from the context, not the window. The actual OpenGL version and
+ // related settings are associated with the context and are only written back to the
+ // context's format.
+ QSurfaceFormat format = window.openglContext()->format();
+
+ if (format.renderableType() == QSurfaceFormat::OpenGL) {
+ if (format.majorVersion() == 2)
+ QCOMPARE(window.glslVersion(), QString());
+ else if (format.majorVersion() == 3)
+ QVERIFY(window.glslVersion().startsWith('3')
+ || window.glslVersion() == QStringLiteral("130")
+ || window.glslVersion() == QStringLiteral("140")
+ || window.glslVersion() == QStringLiteral("150"));
+ else if (format.majorVersion() == 4)
+ QVERIFY(window.glslVersion().startsWith('4'));
+ QVERIFY(!window.glslVersion().contains(QStringLiteral("core")));
+ QVERIFY(!window.glslVersion().contains(QStringLiteral("es")));
+ } else if (format.renderableType() == QSurfaceFormat::OpenGLES) {
+ if (format.majorVersion() == 2)
+ QCOMPARE(window.glslVersion(), QString());
+ else
+ QVERIFY(window.glslVersion().contains(QStringLiteral("es")));
+ }
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/rendernode/data/matrix.qml b/tests/auto/quick/rendernode/data/matrix.qml
new file mode 100644
index 0000000000..8b721e5075
--- /dev/null
+++ b/tests/auto/quick/rendernode/data/matrix.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import RenderNode 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; no-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; no-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; no-rotation"; clip: true }
+ }
+
+
+ Item { x: 10; y: 10; width: 10; height: 10; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; parent-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; parent-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; parent-rotation"; clip: true }
+ }
+
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; self-rotation"; rotation: 90 }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true;
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; self-rotation"; rotation: 90}
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; self-rotation"; clip: true; rotation: 90 }
+ }
+
+}
diff --git a/tests/auto/quick/rendernode/rendernode.pro b/tests/auto/quick/rendernode/rendernode.pro
index b55b7b0bec..bedcefde86 100644
--- a/tests/auto/quick/rendernode/rendernode.pro
+++ b/tests/auto/quick/rendernode/rendernode.pro
@@ -14,4 +14,6 @@ QT += core-private gui-private qml-private quick-private testlib
OTHER_FILES += \
data/RenderOrder.qml \
data/MessUpState.qml \
+ data/matrix.qml
+
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 06338e09e2..98e31329a0 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -72,6 +72,7 @@ public:
private slots:
void renderOrder();
void messUpState();
+ void matrix();
};
class ClearNode : public QSGRenderNode
@@ -261,6 +262,84 @@ void tst_rendernode::messUpState()
QCOMPARE(fb.pixel(x2, y5), qRgb(0x00, 0x00, 0x00));
}
+class StateRecordingRenderNode : public QSGRenderNode
+{
+public:
+ StateFlags changedStates() { return StateFlags(-1); }
+ void render(const RenderState &) {
+ matrices[name] = *matrix();
+
+ }
+
+ QString name;
+ static QHash<QString, QMatrix4x4> matrices;
+};
+
+QHash<QString, QMatrix4x4> StateRecordingRenderNode::matrices;
+
+class StateRecordingRenderNodeItem : public QQuickItem
+{
+ Q_OBJECT
+public:
+ StateRecordingRenderNodeItem() { setFlag(ItemHasContents, true); }
+ QSGNode *updatePaintNode(QSGNode *r, UpdatePaintNodeData *) {
+ if (r)
+ return r;
+ StateRecordingRenderNode *rn = new StateRecordingRenderNode();
+ rn->name = objectName();
+ return rn;
+ }
+};
+
+void tst_rendernode::matrix()
+{
+ qmlRegisterType<StateRecordingRenderNodeItem>("RenderNode", 1, 0, "StateRecorder");
+ StateRecordingRenderNode::matrices.clear();
+ runTest("matrix.qml");
+
+ QMatrix4x4 noRotateOffset;
+ noRotateOffset.translate(20, 20);
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+
+ QMatrix4x4 parentRotation;
+ parentRotation.translate(10, 10); // parent at x/y: 10
+ parentRotation.translate(5, 5); // rotate 90 around center (width/height: 10)
+ parentRotation.rotate(90, 0, 0, 1);
+ parentRotation.translate(-5, -5);
+ parentRotation.translate(10, 10); // StateRecorder at: x/y: 10
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+
+ QMatrix4x4 selfRotation;
+ selfRotation.translate(10, 10); // parent at x/y: 10
+ selfRotation.translate(10, 10); // StateRecorder at: x/y: 10
+ selfRotation.rotate(90, 0, 0, 1); // rotate 90, width/height: 0
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+}
+
QTEST_MAIN(tst_rendernode)
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 0e3964d52d..aa6d7c4a93 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -47,6 +47,9 @@
#include <QtTest/QTest>
+#include <private/qquickwindow_p.h>
+
+
QQuickView *QQuickViewTestUtil::createView()
{
QQuickView *window = new QQuickView(0);
@@ -341,3 +344,23 @@ QList<QPair<QString,QString> > QQuickViewTestUtil::ListRange::getModelDataValues
return data;
}
+namespace QQuickTouchUtils {
+
+ /* QQuickWindow does event compression and only delivers events just
+ * before it is about to render the next frame. Since some tests
+ * rely on events being delivered immediately AND that no other
+ * event processing has occurred in the meanwhile, we flush the
+ * event manually and immediately.
+ */
+ void flush(QQuickWindow *window) {
+ if (!window)
+ return;
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
+ if (!wd || !wd->delayedTouch)
+ return;
+ wd->reallyDeliverTouchEvent(wd->delayedTouch);
+ delete wd->delayedTouch;
+ wd->delayedTouch = 0;
+ }
+
+}
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index 5b0b10b69c..e10966ddba 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -166,6 +166,10 @@ namespace QQuickViewTestUtil
}
}
+namespace QQuickTouchUtils {
+ void flush(QQuickWindow *window);
+}
+
Q_DECLARE_METATYPE(QQuickViewTestUtil::QaimModel*)
Q_DECLARE_METATYPE(QQuickViewTestUtil::ListChange)
Q_DECLARE_METATYPE(QList<QQuickViewTestUtil::ListChange>)
diff --git a/tests/auto/quick/touchmouse/touchmouse.pro b/tests/auto/quick/touchmouse/touchmouse.pro
index 445bee08ae..7d23dfc0ae 100644
--- a/tests/auto/quick/touchmouse/touchmouse.pro
+++ b/tests/auto/quick/touchmouse/touchmouse.pro
@@ -8,6 +8,7 @@ macx:CONFIG -= app_bundle
SOURCES += tst_touchmouse.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 5b4ad0ffa3..1d947b4d8c 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -58,6 +58,7 @@
#include <QtQml/qqmlproperty.h>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
struct Event
{
@@ -221,12 +222,15 @@ void tst_TouchMouse::simpleTouchEvent()
QPoint p1;
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
eventItem1->eventList.clear();
@@ -234,11 +238,14 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->acceptTouch = true;
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 3);
eventItem1->eventList.clear();
@@ -251,6 +258,7 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -268,10 +276,12 @@ void tst_TouchMouse::simpleTouchEvent()
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 6);
QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
@@ -286,13 +296,16 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
eventItem1->eventList.clear();
@@ -304,13 +317,16 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 3);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
eventItem1->eventList.clear();
@@ -376,6 +392,7 @@ void tst_TouchMouse::mouse()
// item 2 doesn't accept anything, thus it sees a touch pass by
QPoint p1 = QPoint(30, 30);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -412,14 +429,17 @@ void tst_TouchMouse::touchOverMouse()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QCOMPARE(eventItem2->eventList.size(), 1);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 3);
QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd);
eventItem2->eventList.clear();
@@ -456,6 +476,7 @@ void tst_TouchMouse::mouseOverTouch()
QPoint p1 = QPoint(20, 20);
QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
@@ -510,10 +531,12 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(20, 130);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTRY_COMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
@@ -522,9 +545,11 @@ void tst_TouchMouse::buttonOnFlickable()
// touch button
p1 = QPoint(10, 310);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 1);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.size(), 0);
@@ -536,8 +561,10 @@ void tst_TouchMouse::buttonOnFlickable()
// click above button, no events please
p1 = QPoint(10, 90);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
eventItem1->eventList.clear();
@@ -548,6 +575,7 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -560,12 +588,13 @@ void tst_TouchMouse::buttonOnFlickable()
p1 += QPoint(0, -10);
QPoint p2 = p1 + QPoint(0, -10);
QPoint p3 = p2 + QPoint(0, -10);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p1, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p2, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
// we cannot really know when the events get grabbed away
QVERIFY(eventItem1->eventList.size() >= 4);
@@ -578,6 +607,7 @@ void tst_TouchMouse::buttonOnFlickable()
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window, device).release(0, p3, window);
+ QQuickTouchUtils::flush(window);
delete window;
}
@@ -625,6 +655,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
// Flickable initially steals events
QCOMPARE(eventItem1->eventList.size(), 0);
// but we'll get the delayed mouse press after a delay
@@ -641,12 +672,13 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
p1 += QPoint(0, -10);
QPoint p2 = p1 + QPoint(0, -10);
QPoint p3 = p2 + QPoint(0, -10);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p1, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p2, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
QVERIFY(flickable->isMovingVertically());
// flickable should have the mouse grab, and have moved the itemForTouchPointId
@@ -656,6 +688,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
QTest::touchEvent(window, device).release(0, p3, window);
+ QQuickTouchUtils::flush(window);
// We should not have received any synthesised mouse events from Qt gui.
QCOMPARE(filteredEventList.count(), 0);
@@ -709,7 +742,9 @@ void tst_TouchMouse::buttonOnTouch()
// Normal touch click
QPoint p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -730,7 +765,9 @@ void tst_TouchMouse::buttonOnTouch()
// Start the events after each other
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).stationary(0).press(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(button1->scale(), 1.0);
@@ -738,20 +775,24 @@ void tst_TouchMouse::buttonOnTouch()
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(button1->scale(), 1.5);
qDebug() << "Button scale: " << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QVERIFY(eventItem1->eventList.isEmpty());
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
@@ -765,6 +806,7 @@ void tst_TouchMouse::buttonOnTouch()
p1 = QPoint(40, 110);
p2 = QPoint(60, 110);
QTest::touchEvent(window, device).press(0, p1, window).press(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(button1->scale(), 1.0);
QCOMPARE(eventItem1->eventList.count(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -774,20 +816,24 @@ void tst_TouchMouse::buttonOnTouch()
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
//QCOMPARE(button1->scale(), 1.5);
qDebug() << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(eventItem1->eventList.size(), 99);
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
@@ -816,18 +862,22 @@ void tst_TouchMouse::pinchOnFlickable()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
+ QQuickTouchUtils::flush(window);
QGuiApplication::processEvents();
QTest::qWait(10);
@@ -840,27 +890,35 @@ void tst_TouchMouse::pinchOnFlickable()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ QQuickTouchUtils::flush(window);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
}
@@ -885,17 +943,22 @@ void tst_TouchMouse::flickableOnPinch()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::qWait(1000);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::qWait(1000);
@@ -909,26 +972,33 @@ void tst_TouchMouse::flickableOnPinch()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
}
@@ -953,16 +1023,19 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
- QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
//QVERIFY(flickable->isMovingHorizontally());
@@ -975,26 +1048,33 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
// PinchArea should steal the event after flicking started
@@ -1002,14 +1082,18 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
flickable->setContentX(0.0);
p = QPoint(100, 100);
pinchSequence.press(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QGuiApplication::processEvents();
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
@@ -1019,20 +1103,26 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
p1 = QPoint(40, 100);
p2 = QPoint(60, 100);
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
pinchSequence.release(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
}
/*
@@ -1066,16 +1156,17 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne()
// tap the front mouse area (see qml file)
QPoint p1(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
- QTest::qWait(1);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomClickedSpy.count(), 1);
QCOMPARE(bottomDoubleClickedSpy.count(), 0);
- QTest::qWait(15);
QTest::touchEvent(window, device).press(0, p1, window);
- QTest::qWait(1);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomClickedSpy.count(), 1);
QCOMPARE(bottomDoubleClickedSpy.count(), 1);
diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp
index d3de584084..231f22b35b 100644
--- a/tests/auto/shared/testhttpserver.cpp
+++ b/tests/auto/shared/testhttpserver.cpp
@@ -71,7 +71,8 @@ slowFiles/slowMain.qml
\endcode
it can be added like this:
\code
-TestHTTPServer server(14445);
+TestHTTPServer server;
+QVERIFY2(server.listen(14445), qPrintable(server.errorString()));
server.serveDirectory("disconnect", TestHTTPServer::Disconnect);
server.serveDirectory("files");
server.serveDirectory("slowFiles", TestHTTPServer::Delay);
@@ -87,17 +88,21 @@ The following request urls will then result in the appropriate action:
\row \li http://localhost:14445/slowMain.qml \li slowMain.qml returned after 500ms
\endtable
*/
-TestHTTPServer::TestHTTPServer(quint16 port)
+TestHTTPServer::TestHTTPServer()
: m_state(AwaitingHeader)
{
QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
- server.listen(QHostAddress::LocalHost, port);
}
-bool TestHTTPServer::isValid() const
+bool TestHTTPServer::listen(quint16 port)
{
- return server.isListening();
+ return server.listen(QHostAddress::LocalHost, port);
+}
+
+QString TestHTTPServer::errorString() const
+{
+ return server.errorString();
}
bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h
index ae7d137143..a71386ddec 100644
--- a/tests/auto/shared/testhttpserver.h
+++ b/tests/auto/shared/testhttpserver.h
@@ -51,9 +51,10 @@ class TestHTTPServer : public QObject
{
Q_OBJECT
public:
- TestHTTPServer(quint16 port);
+ TestHTTPServer();
- bool isValid() const;
+ bool listen(quint16 port);
+ QString errorString() const;
enum Mode { Normal, Delay, Disconnect };
bool serveDirectory(const QString &, Mode = Normal);
diff --git a/tests/manual/httpserver/main.cpp b/tests/manual/httpserver/main.cpp
index ea729547ce..4ad44508b0 100644
--- a/tests/manual/httpserver/main.cpp
+++ b/tests/manual/httpserver/main.cpp
@@ -112,7 +112,11 @@ int main(int argc, char *argv[])
<< "\":\n\n" << QDir(directory).entryList(QDir::Files).join(QLatin1Char('\n'))
<< "\n\non http://localhost:" << port << '\n';
- TestHTTPServer server(port);
+ TestHTTPServer server;
+ if (!server.listen(port)) {
+ std::wcout << "Couldn't listen on port " << port << server.errorString().toLocal8Bit();
+ exit(-1);
+ }
server.serveDirectory(directory);
return a.exec();
diff --git a/tools/qmleasing/qmleasing.pro b/tools/qmleasing/qmleasing.pro
index eadcb304c4..e334faa77a 100644
--- a/tools/qmleasing/qmleasing.pro
+++ b/tools/qmleasing/qmleasing.pro
@@ -1,5 +1,4 @@
QT += qml quick widgets
-CONFIG -= app_bundle
SOURCES += main.cpp \
splineeditor.cpp \
@@ -17,3 +16,5 @@ FORMS += \
properties.ui \
pane.ui \
import.ui
+
+load(qt_app)