diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 36 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml.pro | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 20 | ||||
-rw-r--r-- | src/qml/qtqml.tracepoints | 14 | ||||
-rw-r--r-- | src/quick/accessible/qaccessiblequickitem.cpp | 16 | ||||
-rw-r--r-- | src/quick/accessible/qaccessiblequickitem_p.h | 1 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d.cpp | 12 | ||||
-rw-r--r-- | src/quick/items/qquickaccessibleattached_p.h | 8 | ||||
-rw-r--r-- | src/quick/items/qquicktextcontrol.cpp | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquickaccessible/data/text.qml (renamed from tests/auto/quick/qquickaccessible/data/statictext.qml) | 18 | ||||
-rw-r--r-- | tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp | 46 |
14 files changed, 150 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore index 57606bfacf..9905dd1fdc 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ wrapper.bat *.*# core .qmake.cache +.qmake.stash .qmake.vars *.prl tags diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index cd3953044b..41bdc3ae92 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1550,15 +1550,12 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit; - const QV4::CompiledData::Unit *jsUnit = nullptr; - std::function<QV4::CompiledData::QmlUnit *(QV4::CompiledData::QmlUnit *, uint)> unitFinalizer - = [](QV4::CompiledData::QmlUnit *unit, uint) { - return unit; - }; + QV4::CompiledData::Unit *jsUnit = nullptr; + const bool finalize = !compilationUnit->data; // We may already have unit data if we're loading an ahead-of-time generated cache file. - if (compilationUnit->data) { - jsUnit = compilationUnit->data; + if (!finalize) { + jsUnit = const_cast<QV4::CompiledData::Unit *>(compilationUnit->data); output.javaScriptCompilationUnit->dynamicStrings = output.jsGenerator.stringTable.allStrings(); } else { QV4::CompiledData::Unit *createdUnit; @@ -1585,20 +1582,6 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen createdUnit->sourceFileIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.fileName); createdUnit->finalUrlIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.finalUrl); - - // Combine the qml data into the general unit data. - unitFinalizer = [&jsUnit](QV4::CompiledData::QmlUnit *qmlUnit, uint qmlDataSize) { - void *ptr = const_cast<QV4::CompiledData::Unit*>(jsUnit); - QV4::CompiledData::Unit *newUnit = (QV4::CompiledData::Unit *)realloc(ptr, jsUnit->unitSize + qmlDataSize); - jsUnit = newUnit; - newUnit->offsetToQmlUnit = newUnit->unitSize; - newUnit->unitSize += qmlDataSize; - memcpy(const_cast<QV4::CompiledData::QmlUnit *>(newUnit->qmlUnit()), qmlUnit, qmlDataSize); - free(const_cast<QV4::CompiledData::QmlUnit*>(qmlUnit)); - qmlUnit = nullptr; - newUnit->generateChecksum(); - return const_cast<QV4::CompiledData::QmlUnit*>(newUnit->qmlUnit()); - }; } // No more new strings after this point, we're calculating offsets. @@ -1765,7 +1748,16 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen } } - qmlUnit = unitFinalizer(qmlUnit, totalSize); + if (finalize) { + // Combine the qml data into the general unit data. + jsUnit = static_cast<QV4::CompiledData::Unit *>(realloc(jsUnit, jsUnit->unitSize + totalSize)); + jsUnit->offsetToQmlUnit = jsUnit->unitSize; + jsUnit->unitSize += totalSize; + memcpy(jsUnit->qmlUnit(), qmlUnit, totalSize); + free(qmlUnit); + jsUnit->generateChecksum(); + qmlUnit = jsUnit->qmlUnit(); + } static const bool showStats = qEnvironmentVariableIsSet("QML_SHOW_UNIT_STATS"); if (showStats) { diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 3e89c25c7d..4a90c841bb 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -904,6 +904,10 @@ struct Unit return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit); } + QmlUnit *qmlUnit() { + return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit); + } + bool isSingleton() const { return flags & Unit::IsSingleton; } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index ec44f42933..d348a79861 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -65,6 +65,8 @@ #include <private/qv4baselinejit_p.h> #endif +#include <qtqml_tracepoints_p.h> + #undef COUNT_INSTRUCTIONS enum { ShowWhenDeoptimiationHappens = 0 }; @@ -422,6 +424,10 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine) CHECK_STACK_LIMITS(engine); Function *function = frame->v4Function; + Q_TRACE_SCOPE(QQmlV4_function_call, engine, function->name()->toQString(), + function->compilationUnit->fileName(), + function->compiledFunction->location.line, + function->compiledFunction->location.column); Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling QV4::Debugging::Debugger *debugger = engine->debugger(); diff --git a/src/qml/qml.pro b/src/qml/qml.pro index ca3282556e..5cb51e0d03 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -4,6 +4,9 @@ QT = core-private qtConfig(qml-network): \ QT += network +TRACEPOINT_PROVIDER = $$PWD/qtqml.tracepoints +CONFIG += qt_tracepoints + DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000 diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 26d3b5b6c1..18105aa75f 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -57,6 +57,8 @@ #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qjsvalue_p.h> +#include <qtqml_tracepoints_p.h> + QT_USE_NAMESPACE namespace { @@ -1161,6 +1163,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo { const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index); QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj); + Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url()); + QString typeName; + Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, typeName); ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine)); @@ -1174,8 +1179,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo if (obj->flags & QV4::CompiledData::Object::IsComponent) { isComponent = true; QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent); - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( - compilationUnit.data(), obj, QStringLiteral("<component>"), context->url())); + typeName = QStringLiteral("<component>"); QQmlComponentPrivate::get(component)->creationContext = context; instance = component; ddata = QQmlData::get(instance, /*create*/true); @@ -1186,8 +1190,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo installPropertyCache = !typeRef->isFullyDynamicType; QQmlType type = typeRef->type; if (type.isValid()) { - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( - compilationUnit.data(), obj, type.qmlTypeName(), context->url())); + typeName = type.qmlTypeName(); void *ddataMemory = nullptr; type.create(&instance, &ddataMemory, sizeof(QQmlData)); @@ -1219,9 +1222,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo sharedState->allCreatedObjects.push(instance); } else { Q_ASSERT(typeRef->compilationUnit); - Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( - compilationUnit.data(), obj, typeRef->compilationUnit->fileName(), - context->url())); + typeName = typeRef->compilationUnit->fileName(); if (typeRef->compilationUnit->unitData()->isSingleton()) { recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex))); @@ -1248,6 +1249,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo ddata = QQmlData::get(instance, /*create*/true); } + + Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( + compilationUnit.data(), obj, typeName, context->url())); + Q_UNUSED(typeName); // only relevant for tracing + ddata->lineNumber = obj->location.line; ddata->columnNumber = obj->location.column; diff --git a/src/qml/qtqml.tracepoints b/src/qml/qtqml.tracepoints new file mode 100644 index 0000000000..841748f201 --- /dev/null +++ b/src/qml/qtqml.tracepoints @@ -0,0 +1,14 @@ +{ +namespace QV4 { +class ExecutionEngine; +namespace CompiledData { +class CompilationUnit; +class Object; +} // CompiledData +} // QV4 +} + +QQmlObjectCreator_createInstance_entry(const QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Object *object, const QUrl &url) +QQmlObjectCreator_createInstance_exit(const QString &typeName) +QQmlV4_function_call_entry(const QV4::ExecutionEngine *engine, const QString &function, const QString &fileName, int line, int column) +QQmlV4_function_call_exit() diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 98e7663c96..b87203c3ef 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -382,6 +382,22 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const return QString(); } +void QAccessibleQuickItem::setText(QAccessible::Text textType, const QString &text) +{ + if (role() != QAccessible::EditableText) + return; + if (textType != QAccessible::Value) + return; + + if (QTextDocument *doc = textDocument()) { + doc->setPlainText(text); + return; + } + auto textPropertyName = "text"; + if (object()->metaObject()->indexOfProperty(textPropertyName) >= 0) + object()->setProperty(textPropertyName, text); +} + void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t) { QAccessible::Role r = role(); diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h index 5375d37bf0..931e995f0f 100644 --- a/src/quick/accessible/qaccessiblequickitem_p.h +++ b/src/quick/accessible/qaccessiblequickitem_p.h @@ -83,6 +83,7 @@ public: QAccessible::State state() const override; QAccessible::Role role() const override; QString text(QAccessible::Text) const override; + void setText(QAccessible::Text, const QString &text) override; bool isAccessible() const; diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 5640721c6f..0f104a122f 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -2000,7 +2000,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(const QV4::FunctionO \since QtQuick 2.11 Returns an array of qreals representing the dash pattern of the line. - \sa setLineDash() + \sa setLineDash(), lineDashOffset */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) { @@ -2022,7 +2022,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::Fun /*! \qmlmethod QtQuick::Context2D::setLineDash(array pattern) \since QtQuick 2.11 - Sets the dash pattern to the given pattern + Sets the dash pattern to the given pattern. \a pattern a list of numbers that specifies distances to alternately draw a line and a gap. @@ -2041,7 +2041,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getLineDash(const QV4::Fun \endcode \endtable - \sa setLineDash + \sa getLineDash(), lineDashOffset */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) { @@ -2083,8 +2083,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setLineDash(const QV4::Fun \qmlproperty real QtQuick::Context2D::lineDashOffset \since QtQuick 2.11 - Holds the current line dash offset - The default line dash ofset value is 0 + Holds the current line dash offset. + The default line dash offset value is \c 0. + + \sa getLineDash(), setLineDash() */ QV4::ReturnedValue QQuickJSContext2D::method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) { diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 215a1e5db6..e292c280df 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -128,13 +128,19 @@ public: case QAccessible::Button: case QAccessible::MenuItem: case QAccessible::PageTab: - case QAccessible::EditableText: case QAccessible::SpinBox: case QAccessible::ComboBox: case QAccessible::Terminal: case QAccessible::ScrollBar: m_state.focusable = true; break; + case QAccessible::EditableText: + m_state.editable = true; + m_state.focusable = true; + break; + case QAccessible::StaticText: + m_state.readOnly = true; + break; default: break; } diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index a7a90c9134..caef24293a 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1297,6 +1297,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) || e->preeditString() != cursor.block().layout()->preeditAreaText() || e->replacementLength() > 0; bool forceSelectionChanged = false; + int oldCursorPos = cursor.position(); cursor.beginEditBlock(); if (isGettingInput) { @@ -1365,6 +1366,8 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) QTextCursorPrivate *cursor_d = QTextCursorPrivate::getPrivate(&cursor); if (cursor_d) cursor_d->setX(); + if (cursor.position() != oldCursorPos) + emit q->cursorPositionChanged(); q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged || isGettingInput); selectionChanged(forceSelectionChanged); } diff --git a/tests/auto/quick/qquickaccessible/data/statictext.qml b/tests/auto/quick/qquickaccessible/data/text.qml index 1092f33daf..88f292a61f 100644 --- a/tests/auto/quick/qquickaccessible/data/statictext.qml +++ b/tests/auto/quick/qquickaccessible/data/text.qml @@ -28,4 +28,22 @@ Item { Accessible.name: "The Hello 2 accessible text" Accessible.description: "A text description" } + + TextInput { + x: 100 + y: 80 + width: 200 + height: 40 + text: "A text input" + Accessible.role: Accessible.EditableText + } + + TextEdit { + x: 100 + y: 120 + width: 200 + height: 100 + text: "A multi-line text edit\nTesting Accessibility." + Accessible.role: Accessible.EditableText + } } diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp index 1bfeb94161..243d87f212 100644 --- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp +++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp @@ -130,7 +130,7 @@ void tst_QQuickAccessible::commonTests_data() { QTest::addColumn<QString>("accessibleRoleFileName"); - QTest::newRow("StaticText") << "statictext.qml"; + QTest::newRow("Text") << "text.qml"; QTest::newRow("PushButton") << "pushbutton.qml"; } @@ -302,7 +302,7 @@ void tst_QQuickAccessible::basicPropertiesTest() QCOMPARE(app->childCount(), 0); QQuickView *window = new QQuickView(); - window->setSource(testFileUrl("statictext.qml")); + window->setSource(testFileUrl("text.qml")); window->show(); QCOMPARE(app->childCount(), 1); @@ -312,7 +312,7 @@ void tst_QQuickAccessible::basicPropertiesTest() QAccessibleInterface *item = iface->child(0); QVERIFY(item); - QCOMPARE(item->childCount(), 2); + QCOMPARE(item->childCount(), 4); QCOMPARE(item->rect().size(), QSize(400, 400)); QCOMPARE(item->role(), QAccessible::Client); QCOMPARE(iface->indexOfChild(item), 0); @@ -338,10 +338,50 @@ void tst_QQuickAccessible::basicPropertiesTest() QCOMPARE(text2->rect().y(), item->rect().y() + 40); QCOMPARE(text2->role(), QAccessible::StaticText); QCOMPARE(item->indexOfChild(text2), 1); + QCOMPARE(text2->state().editable, 0); + QCOMPARE(text2->state().readOnly, 1); QCOMPARE(iface->indexOfChild(text2), -1); QCOMPARE(text2->indexOfChild(item), -1); + // TextInput + QAccessibleInterface *textInput = item->child(2); + QVERIFY(textInput); + QCOMPARE(textInput->childCount(), 0); + QCOMPARE(textInput->role(), QAccessible::EditableText); + QCOMPARE(textInput->state().editable, 1); + QCOMPARE(textInput->state().readOnly, 0); + QCOMPARE(textInput->state().multiLine, 0); + QCOMPARE(textInput->state().focusable, 1); + QCOMPARE(textInput->text(QAccessible::Value), "A text input"); + auto textInterface = textInput->textInterface(); + QVERIFY(textInterface); + auto editableTextInterface = textInput->editableTextInterface(); + QEXPECT_FAIL("", "EditableTextInterface is not implemented", Continue); + QVERIFY(editableTextInterface); + auto newText = QString("a new text"); + textInput->setText(QAccessible::Value, newText); + QCOMPARE(textInput->text(QAccessible::Value), newText); + + // TextEdit + QAccessibleInterface *textEdit = item->child(3); + QVERIFY(textEdit); + QCOMPARE(textEdit->childCount(), 0); + QCOMPARE(textEdit->role(), QAccessible::EditableText); + QCOMPARE(textEdit->state().editable, 1); + QCOMPARE(textEdit->state().readOnly, 0); + QCOMPARE(textEdit->state().focusable, 1); + QCOMPARE(textEdit->text(QAccessible::Value), "A multi-line text edit\nTesting Accessibility."); + auto textEditTextInterface = textEdit->textInterface(); + QVERIFY(textEditTextInterface); + auto textEditEditableTextInterface = textEdit->editableTextInterface(); + QEXPECT_FAIL("", "EditableTextInterface is not implemented", Continue); + QVERIFY(textEditEditableTextInterface); + textEdit->setText(QAccessible::Value, newText); + QCOMPARE(textEdit->text(QAccessible::Value), newText); + QEXPECT_FAIL("", "multi line is not implemented", Continue); + QCOMPARE(textInput->state().multiLine, 1); + delete window; QTestAccessibility::clearEvents(); } |