aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.2.138
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp19
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h2
-rw-r--r--src/qml/compiler/qv4regalloc.cpp16
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h17
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc2
-rw-r--r--src/qml/jsapi/qjsvalue.cpp2
-rw-r--r--src/qml/jsruntime/qv4alloca_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp7
-rw-r--r--src/qml/jsruntime/qv4mm.cpp8
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp93
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h3
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp11
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h1
-rw-r--r--src/qml/qml/qqmlcompiler.cpp1
-rw-r--r--src/qml/qml/qqmlinstruction_p.h4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp11
-rw-r--r--src/qml/qml/qqmlmetatype_p.h1
-rw-r--r--src/quick/items/qquickflickable.cpp1
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp38
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h9
-rw-r--r--src/quick/items/qquickpincharea.cpp47
-rw-r--r--src/quick/items/qquickpincharea_p.h9
-rw-r--r--src/quick/items/qquicktext.cpp8
-rw-r--r--src/quick/items/qquickwindow.cpp2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp197
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h8
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp34
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode.cpp4
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp18
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp19
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml9
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro3
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp30
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp64
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp40
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp18
-rw-r--r--tools/qmlplugindump/main.cpp94
-rw-r--r--tools/qmlplugindump/qmlstreamwriter.cpp10
-rw-r--r--tools/qmlplugindump/qmlstreamwriter.h2
42 files changed, 681 insertions, 237 deletions
diff --git a/dist/changes-5.2.1 b/dist/changes-5.2.1
new file mode 100644
index 0000000000..c5371185f0
--- /dev/null
+++ b/dist/changes-5.2.1
@@ -0,0 +1,38 @@
+Qt 5.2.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.2.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ http://qt-project.org/doc/qt-5.2
+
+The Qt version 5.2 series is binary compatible with the 5.1.x series.
+Applications compiled for 5.1 will continue to run with 5.2.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ http://bugreports.qt-project.org/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtQml
+-----
+
+ - [QTBUG-35979] Fixed JavaScript Array.pop() not updating the
+ internal array length correctly
+
+QtQuick
+-------
+
+ - [QTBUG-35128] Fixed TextInput to call fixup() on its validator when
+ being accepted or losing focus, and the validator reports that the input
+ is in "intermediate" state ie. the input should be fixed up.
+ - [QTBUG-34517] Fixed an issue that caused QQuickTextInput to not
+ accept delete/home/backspace/left/right keys when the key was used
+ in a shortcut.
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 6df94e713d..b8b16a4151 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -1966,12 +1966,21 @@ void InstructionSelection::visitRet(V4IR::Ret *s)
Assembler::ScratchRegister);
_as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
} else if (t->type == V4IR::UInt32Type) {
- Address tmp = addressForArgument(0);
- _as->storeUInt32((Assembler::RegisterID) t->index, Pointer(tmp));
- _as->load64(tmp, Assembler::ReturnValueRegister);
+ Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
+ Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
+ _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
+ _as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ Assembler::Jump done = _as->jump();
+ intRange.link(_as);
+ _as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
+ quint64 tag = QV4::Value::_Integer_Type;
+ _as->or64(Assembler::TrustedImm64(tag << 32),
+ Assembler::ReturnValueRegister);
+ done.link(_as);
} else {
- _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index,
- Assembler::ReturnValueRegister);
+ _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister);
quint64 tag;
switch (t->type) {
case V4IR::SInt32Type:
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index f5d4e469e5..a146220015 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -1481,6 +1481,7 @@ protected:
typedef Assembler::Address Address;
typedef Assembler::Pointer Pointer;
+#if !defined(ARGUMENTS_IN_REGISTERS)
Address addressForArgument(int index) const
{
// StackFrameRegister points to its old value on the stack, and above
@@ -1488,6 +1489,7 @@ protected:
// values before reaching the first argument.
return Address(Assembler::StackFrameRegister, (index + 2) * sizeof(void*));
}
+#endif
Pointer baseAddressForCallArguments()
{
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index f95cd55b04..2f1f64e523 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -860,7 +860,6 @@ private:
if (it->end() < successorStart)
continue;
- bool lifeTimeHole = false;
bool isPhiTarget = false;
Expr *moveFrom = 0;
@@ -906,9 +905,7 @@ private:
predIt->temp().type);
} else {
int spillSlot = _assignedSpillSlots.value(predIt->temp(), -1);
- if (spillSlot == -1)
- lifeTimeHole = true;
- else
+ if (spillSlot != -1)
moveFrom = createTemp(Temp::StackSlot, spillSlot, predIt->temp().type);
}
break;
@@ -916,9 +913,11 @@ private:
}
}
if (!moveFrom) {
-#if defined(QT_NO_DEBUG)
- Q_UNUSED(lifeTimeHole);
-#else
+#if !defined(QT_NO_DEBUG)
+ bool lifeTimeHole = false;
+ if (it->ranges().first().start <= successorStart && it->ranges().last().end >= successorStart)
+ lifeTimeHole = !it->covers(successorStart);
+
Q_ASSERT(!_info->isPhiTarget(it->temp()) || it->isSplitFromInterval() || lifeTimeHole);
if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) {
const int successorEnd = successor->statements.last()->id;
@@ -960,9 +959,6 @@ private:
moveTo = createTemp(Temp::StackSlot, spillSlot, it->temp().type);
} else {
moveTo = createTemp(Temp::PhysicalRegister, platformRegister(*it), it->temp().type);
- const int spillSlot = _assignedSpillSlots.value(it->temp(), -1);
- if (isPhiTarget && spillSlot != -1)
- mapping.add(moveFrom, createTemp(Temp::StackSlot, spillSlot, it->temp().type));
}
// add move to mapping
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 6d7c0dcb51..c3329dbb89 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -57,6 +57,7 @@
#include <private/qqmlboundsignal_p.h>
// this contains QUnifiedTimer
#include <private/qabstractanimation_p.h>
+#include <private/qv4function_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@@ -401,8 +402,20 @@ struct QQmlBindingProfiler {
struct QQmlHandlingSignalProfiler {
QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression)
{
- Q_QML_PROFILE(startHandlingSignal(expression->sourceFile(), expression->lineNumber(),
- expression->columnNumber()));
+ if (QQmlProfilerService::enabled) {
+ if (expression->sourceFile().isEmpty()) {
+ QV4::Function *function = expression->function();
+ if (function) {
+ Q_QML_PROFILE(startHandlingSignal(
+ function->sourceFile(), function->compiledFunction->location.line,
+ function->compiledFunction->location.column));
+ }
+ } else {
+ Q_QML_PROFILE(startHandlingSignal(
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber()));
+ }
+ }
}
~QQmlHandlingSignalProfiler()
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 19cd3b3f02..d3d3174193 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -238,7 +238,7 @@
Usage:
\code
// First, define the singleton type provider function (callback).
- static QJSValue *example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
+ static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 0734e92b19..c8de31ef78 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -746,7 +746,7 @@ static bool js_equal(const QString &string, QV4::ValueRef value)
if (value->isNumber())
return __qmljs_string_to_number(string) == value->asDouble();
if (value->isBoolean())
- return __qmljs_string_to_number(string) == value->booleanValue();
+ return __qmljs_string_to_number(string) == double(value->booleanValue());
if (value->isObject()) {
Scope scope(value->objectValue()->engine());
ScopedValue p(scope, __qmljs_to_primitive(value, PREFERREDTYPE_HINT));
diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h
index f507d174e1..e51c6dff00 100644
--- a/src/qml/jsruntime/qv4alloca_p.h
+++ b/src/qml/jsruntime/qv4alloca_p.h
@@ -50,7 +50,9 @@
# define alloca _alloca
# endif
#else
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
# include <alloca.h>
#endif
+#endif
#endif
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 995c711a02..299d11a4a1 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -77,6 +77,9 @@
#if USE(PTHREADS)
# include <pthread.h>
# include <sys/resource.h>
+#if HAVE(PTHREAD_NP_H)
+# include <pthread_np.h>
+#endif
#endif
QT_BEGIN_NAMESPACE
@@ -109,7 +112,11 @@ quintptr getStackLimit()
# else
void* stackBottom = 0;
pthread_attr_t attr;
+#if HAVE(PTHREAD_NP_H) && OS(FREEBSD)
+ if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
+#else
if (pthread_getattr_np(pthread_self(), &attr) == 0) {
+#endif
size_t stackSize = 0;
pthread_attr_getstack(&attr, &stackBottom, &stackSize);
pthread_attr_destroy(&attr);
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 0af0fea49a..0ba0b18cda 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -67,6 +67,10 @@
#include <sys/storage.h> // __tls()
#endif
+#if USE(PTHREADS) && HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -234,7 +238,11 @@ MemoryManager::MemoryManager()
# else
void* stackBottom = 0;
pthread_attr_t attr;
+#if HAVE(PTHREAD_NP_H) && OS(FREEBSD)
+ if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
+#else
if (pthread_getattr_np(pthread_self(), &attr) == 0) {
+#endif
size_t stackSize = 0;
pthread_attr_getstack(&attr, &stackBottom, &stackSize);
pthread_attr_destroy(&attr);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index aafecb5ad8..95b6569196 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -237,6 +237,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("RegExp"))
{
setVTable(staticVTable());
+ clearLastMatch();
+}
+
+void RegExpCtor::clearLastMatch()
+{
+ lastMatch = Primitive::nullValue();
+ lastInput = engine()->newIdentifier(QString());
+ lastMatchStart = 0;
+ lastMatchEnd = 0;
}
ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
@@ -299,6 +308,14 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
+void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e)
+{
+ RegExpCtor *This = static_cast<RegExpCtor*>(that);
+ This->lastMatch.mark(e);
+ This->lastInput.mark(e);
+ FunctionObject::markObjects(that, e);
+}
+
void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
{
Scope scope(engine);
@@ -306,6 +323,28 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+
+ // Properties deprecated in the spec but required by "the web" :(
+ ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, 0);
+ ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, 0);
+ ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, 0);
+
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
@@ -333,7 +372,11 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint));
- int result = r->value->match(s, offset, matchOffsets);
+ const int result = r->value->match(s, offset, matchOffsets);
+
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ regExpCtor->clearLastMatch();
+
if (result == -1) {
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
return Encode::null();
@@ -351,10 +394,14 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayData->put(i, v);
}
array->setArrayLengthUnchecked(len);
-
array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result);
array->memberData[Index_ArrayInput].value = arg.asReturnedValue();
+ regExpCtor->lastMatch = array;
+ regExpCtor->lastInput = arg->stringValue();
+ regExpCtor->lastMatchStart = matchOffsets[0];
+ regExpCtor->lastMatchEnd = matchOffsets[1];
+
if (r->global)
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
@@ -395,4 +442,46 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
return Encode::undefined();
}
+template <int index>
+ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
+{
+ Scope scope(ctx);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
+ if (result->isUndefined())
+ return ctx->engine->newString(QString())->asReturnedValue();
+ return result.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
+{
+ Scope scope(ctx);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
+ if (result->isUndefined())
+ return ctx->engine->newString(QString())->asReturnedValue();
+ return result.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
+{
+ return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput->toQString();
+ return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput->toQString();
+ return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index d306efb218..a4cb4b9fb5 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -107,8 +107,15 @@ struct RegExpCtor: FunctionObject
V4_OBJECT
RegExpCtor(ExecutionContext *scope);
+ SafeValue lastMatch;
+ SafeString lastInput;
+ int lastMatchStart;
+ int lastMatchEnd;
+ void clearLastMatch();
+
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
+ static void markObjects(Managed *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
@@ -120,6 +127,13 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_test(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_compile(CallContext *ctx);
+
+ template <int index>
+ static ReturnedValue method_get_lastMatch_n(CallContext *ctx);
+ static ReturnedValue method_get_lastParen(CallContext *ctx);
+ static ReturnedValue method_get_input(CallContext *ctx);
+ static ReturnedValue method_get_leftContext(CallContext *ctx);
+ static ReturnedValue method_get_rightContext(CallContext *ctx);
};
}
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 21f45745cb..2c71a36a3d 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -65,6 +65,9 @@ struct Scope {
explicit Scope(ExecutionEngine *e)
: engine(e)
+#ifndef QT_NO_DEBUG
+ , size(0)
+#endif
{
mark = engine->jsStackTop;
}
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 68160edf5e..bc56fe1f2d 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -136,6 +136,17 @@ QString QQmlBoundSignalExpression::expression() const
}
}
+QV4::Function *QQmlBoundSignalExpression::function() const
+{
+ if (m_expressionFunctionValid) {
+ Q_ASSERT (context() && engine());
+ QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
+ QV4::Scoped<QV4::FunctionObject> v(scope, m_v8function.value());
+ return v ? v->function : 0;
+ }
+ return 0;
+}
+
// Parts of this function mirror code in QQmlExpressionPrivate::value() and v8value().
// Changes made here may need to be made there and vice versa.
void QQmlBoundSignalExpression::evaluate(void **a)
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index feb79d5484..fe0dbd380e 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -90,6 +90,7 @@ public:
quint16 lineNumber() const { return m_line; }
quint16 columnNumber() const { return m_column; }
QString expression() const;
+ QV4::Function *function() const;
QObject *target() const { return m_target; }
QQmlEngine *engine() const { return context() ? context()->engine : 0; }
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index cd0dea975b..e36f3fd967 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -1681,6 +1681,7 @@ static AST::FunctionDeclaration *convertSignalHandlerExpressionToFunctionDeclara
AST::FunctionBody *body = new (pool) AST::FunctionBody(elements);
AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine->newStringRef(signalName), paramList, body);
+ functionDeclaration->functionToken = statement->firstSourceLocation();
return functionDeclaration;
}
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index aeda9832f3..d76c9f9f64 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -151,8 +151,10 @@ QT_BEGIN_NAMESPACE
#ifdef QML_THREADED_VME_INTERPRETER
# define QML_INSTR_HEADER void *code;
+# define QML_INSTR_HEADER_INIT this->code = 0;
#else
# define QML_INSTR_HEADER quint8 instructionType;
+# define QML_INSTR_HEADER_INIT this->instructionType = 0;
#endif
#define QML_INSTR_ENUM(I, FMT) I,
@@ -547,6 +549,8 @@ FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE);
template<int Instr>
class QQmlInstructionData : public QQmlInstructionMeta<Instr>::DataType
{
+public:
+ QQmlInstructionData() : QQmlInstructionMeta<Instr>::DataType() { QML_INSTR_HEADER_INIT }
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 1dd8ce0e3e..90d3ca3308 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1836,6 +1836,17 @@ QList<QQmlType*> QQmlMetaType::qmlTypes()
}
/*!
+ Returns the list of all registered types.
+*/
+QList<QQmlType*> QQmlMetaType::qmlAllTypes()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ return data->types;
+}
+
+/*!
Returns the list of registered QML singleton types.
*/
QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 6c19da6b15..019e6b8821 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -80,6 +80,7 @@ public:
static QList<QString> qmlTypeNames();
static QList<QQmlType*> qmlTypes();
static QList<QQmlType*> qmlSingletonTypes();
+ static QList<QQmlType*> qmlAllTypes();
static QQmlType *qmlType(const QString &qualifiedName, int, int);
static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 7cc37e0556..333c11cb29 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -2309,6 +2309,7 @@ void QQuickFlickable::timelineCompleted()
return;
}
movementEnding();
+ d->updateBeginningEnd();
}
void QQuickFlickable::movementStarting()
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 6b273dcd43..973f6efdcc 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -324,7 +324,6 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
: QQuickItem(parent),
- _currentWindow(0),
_minimumTouchPoints(0),
_maximumTouchPoints(INT_MAX),
_stealMouse(false)
@@ -334,8 +333,8 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
if (qmlVisualTouchDebugging()) {
setFlag(QQuickItem::ItemHasContents);
}
-#ifdef Q_OS_MAC
- connect(this, &QQuickItem::windowChanged, this, &QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow);
+#ifdef Q_OS_OSX
+ setAcceptHoverEvents(true); // needed to enable touch events on mouse hover.
#endif
}
@@ -548,28 +547,31 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
_pressedTouchPoints.append(dtp);
}
-void QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow(QWindow *window)
+#ifdef Q_OS_OSX
+void QQuickMultiPointTouchArea::hoverEnterEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ setTouchEventsEnabled(true);
+}
+
+void QQuickMultiPointTouchArea::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ setTouchEventsEnabled(false);
+}
+
+void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable)
{
-#ifdef Q_OS_MAC
// Resolve function for enabling touch events from the (cocoa) platform plugin.
typedef void (*RegisterTouchWindowFunction)(QWindow *, bool);
RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>(
QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (!registerTouchWindow)
- return; // Not necessarily an error, Qt migh be using a different platform plugin.
-
- // Disable touch on the old window, enable on the new window.
- if (_currentWindow)
- registerTouchWindow(_currentWindow, false);
- if (window)
- registerTouchWindow(window, true);
- // Save the current window, setTouchEventsEnabledForWindow will be called
- // with a null window on disable.
- _currentWindow = window;
-#else // Q_OS_MAC
- Q_UNUSED(window)
-#endif
+ return; // Not necessarily an error, Qt might be using a different platform plugin.
+
+ registerTouchWindow(window(), enable);
}
+#endif // Q_OS_OSX
void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
{
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 2e1f2a98fb..83cc407401 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -250,9 +250,11 @@ protected:
bool shouldFilter(QEvent *event);
void grabGesture();
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
-protected Q_SLOTS:
- void setTouchEventsEnabledForWindow(QWindow *window);
+#ifdef Q_OS_OSX
+ void hoverEnterEvent(QHoverEvent *event);
+ void hoverLeaveEvent(QHoverEvent *event);
+ void setTouchEventsEnabled(bool enable);
+#endif
private:
void ungrab();
@@ -261,7 +263,6 @@ private:
QList<QObject*> _releasedTouchPoints;
QList<QObject*> _pressedTouchPoints;
QList<QObject*> _movedTouchPoints;
- QWindow *_currentWindow;
int _minimumTouchPoints;
int _maximumTouchPoints;
bool _stealMouse;
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index 419792aaa5..f741a08512 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -248,14 +248,13 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
QQuickPinchArea::QQuickPinchArea(QQuickItem *parent)
: QQuickItem(*(new QQuickPinchAreaPrivate), parent)
- , _currentWindow(0)
{
Q_D(QQuickPinchArea);
d->init();
setAcceptedMouseButtons(Qt::LeftButton);
setFiltersChildMouseEvents(true);
-#ifdef Q_OS_MAC
- connect(this, &QQuickItem::windowChanged, this, &QQuickPinchArea::setTouchEventsEnabledForWindow);
+#ifdef Q_OS_OSX
+ setAcceptHoverEvents(true); // needed to enable touch events on mouse hover.
#endif
}
@@ -537,37 +536,39 @@ void QQuickPinchArea::itemChange(ItemChange change, const ItemChangeData &value)
QQuickItem::itemChange(change, value);
}
-QQuickPinch *QQuickPinchArea::pinch()
+#ifdef Q_OS_OSX
+void QQuickPinchArea::hoverEnterEvent(QHoverEvent *event)
{
- Q_D(QQuickPinchArea);
- if (!d->pinch)
- d->pinch = new QQuickPinch;
- return d->pinch;
+ Q_UNUSED(event);
+ setTouchEventsEnabled(true);
}
-void QQuickPinchArea::setTouchEventsEnabledForWindow(QWindow *window)
+void QQuickPinchArea::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_UNUSED(event);
+ setTouchEventsEnabled(false);
+}
+
+void QQuickPinchArea::setTouchEventsEnabled(bool enable)
{
-#ifdef Q_OS_MAC
// Resolve function for enabling touch events from the (cocoa) platform plugin.
typedef void (*RegisterTouchWindowFunction)(QWindow *, bool);
RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>(
QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (!registerTouchWindow)
- return; // Not necessarily an error, Qt migh be using a different platform plugin.
-
- // Disable touch on the old window, enable on the new window.
- if (_currentWindow)
- registerTouchWindow(_currentWindow, false);
- if (window)
- registerTouchWindow(window, true);
- // Save the current window, setTouchEventsEnabledForWindow will be called
- // with a null window on disable.
- _currentWindow = window;
-#else // Q_OS_MAC
- Q_UNUSED(window)
-#endif
+ return; // Not necessarily an error, Qt might be using a different platform plugin.
+
+ registerTouchWindow(window(), enable);
}
+#endif // Q_OS_OSX
+QQuickPinch *QQuickPinchArea::pinch()
+{
+ Q_D(QQuickPinchArea);
+ if (!d->pinch)
+ d->pinch = new QQuickPinch;
+ return d->pinch;
+}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index c991145fc7..81bdbda3a1 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -282,9 +282,11 @@ protected:
virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry);
virtual void itemChange(ItemChange change, const ItemChangeData& value);
-
-private Q_SLOTS:
- void setTouchEventsEnabledForWindow(QWindow *window);
+#ifdef Q_OS_OSX
+ void hoverEnterEvent(QHoverEvent *event);
+ void hoverLeaveEvent(QHoverEvent *event);
+ void setTouchEventsEnabled(bool enable);
+#endif
private:
void updatePinch();
@@ -292,7 +294,6 @@ private:
void handleRelease();
private:
- QWindow *_currentWindow;
Q_DISABLE_COPY(QQuickPinchArea)
Q_DECLARE_PRIVATE(QQuickPinchArea)
};
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index beb2039924..5b5dd0ef03 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -2088,7 +2088,7 @@ QRectF QQuickText::boundingRect() const
Q_D(const QQuickText);
QRectF rect = d->layedOutTextRect;
- rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), d->hAlign));
+ rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), effectiveHAlign()));
rect.moveTop(QQuickTextUtil::alignedY(rect.height(), height(), d->vAlign));
if (d->style != Normal)
@@ -2225,11 +2225,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
const QColor linkColor = QColor::fromRgba(d->linkColor);
if (d->richText) {
- const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), d->hAlign);
+ const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign());
d->ensureDoc();
node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor);
} else if (d->layedOutTextRect.width() > 0) {
- const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), d->hAlign);
+ const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign());
int unelidedLineCount = d->lineCount;
if (d->elideLayout)
unelidedLineCount -= 1;
@@ -2501,7 +2501,7 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const
link = anchorAt(elideLayout, translatedMousePos);
return link;
} else if (richText && extra.isAllocated() && extra->doc) {
- translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), hAlign);
+ translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign());
return extra->doc->documentLayout()->anchorAt(translatedMousePos);
}
return QString();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index c57ca5e838..a311971266 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -343,6 +343,8 @@ void QQuickWindowPrivate::syncSceneGraph()
if (clearBeforeRendering)
mode |= QSGRenderer::ClearColorBuffer;
renderer->setClearMode(mode);
+
+ context->endSync();
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 700ec051ff..1a9669f9ab 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -599,11 +599,6 @@ void Element::computeBounds()
boundsOutsideFloatRange = bounds.isOutsideFloatRange();
}
-RenderNodeElement::~RenderNodeElement()
-{
- delete fbo;
-}
-
bool Batch::isMaterialCompatible(Element *e) const
{
// If material has changed between opaque and translucent, it is not compatible
@@ -751,6 +746,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_nextRenderOrder(0)
, m_partialRebuild(false)
, m_partialRebuildRoot(0)
+ , m_useDepthBuffer(true)
, m_opaqueBatches(16)
, m_alphaBatches(16)
, m_batchPool(16)
@@ -761,6 +757,8 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_zRange(0)
, m_currentMaterial(0)
, m_currentShader(0)
+ , m_currentClip(0)
+ , m_currentClipType(NoClip)
, m_vao(0)
{
setNodeUpdater(new Updater(this));
@@ -809,6 +807,8 @@ Renderer::Renderer(QSGRenderContext *ctx)
m_vao = new QOpenGLVertexArrayObject(this);
m_vao->create();
}
+
+ m_useDepthBuffer = ctx->openglContext()->format().depthBufferSize() > 0;
}
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@@ -1005,6 +1005,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
snode->data = e;
Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node)));
m_renderNodeElements.insert(e->renderNode, e);
+ m_useDepthBuffer = false;
+ m_rebuild |= FullRebuild;
}
QSGNODE_TRAVERSE(node)
@@ -1250,7 +1252,7 @@ void Renderer::buildRenderLists(QSGNode *node)
Q_ASSERT(e);
bool opaque = gn->inheritedOpacity() > OPAQUE_LIMIT && !(gn->activeMaterial()->flags() & QSGMaterial::Blending);
- if (opaque)
+ if (opaque && m_useDepthBuffer)
m_opaqueRenderList << e;
else
m_alphaRenderList << e;
@@ -1631,10 +1633,13 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
}
}
- float *vzorder = (float *) *zData;
- float zorder = 1.0f - e->order * m_zRange;
- for (int i=0; i<vCount; ++i)
- vzorder[i] = zorder;
+ if (m_useDepthBuffer) {
+ float *vzorder = (float *) *zData;
+ float zorder = 1.0f - e->order * m_zRange;
+ for (int i=0; i<vCount; ++i)
+ vzorder[i] = zorder;
+ *zData += vCount * sizeof(float);
+ }
int iCount = g->indexCount();
quint16 *indices = (quint16 *) *indexData;
@@ -1658,7 +1663,6 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
}
*vertexData += vCount * vSize;
- *zData += vCount * sizeof(float);
*indexData += iCount * sizeof(quint16);
*iBase += vCount;
*indexCount += iCount;
@@ -1754,8 +1758,9 @@ void Renderer::uploadBatch(Batch *b)
int bufferSize = b->vertexCount * g->sizeOfVertex();
int ibufferSize = 0;
if (b->merged) {
- bufferSize += b->vertexCount * sizeof(float);
ibufferSize = b->indexCount * sizeof(quint16);
+ if (m_useDepthBuffer)
+ bufferSize += b->vertexCount * sizeof(float);
} else {
ibufferSize = unmergedIndexSize;
}
@@ -1777,7 +1782,7 @@ void Renderer::uploadBatch(Batch *b)
#ifdef QSG_SEPARATE_INDEX_BUFFER
char *indexData = b->ibo.data;
#else
- char *indexData = zData + b->vertexCount * sizeof(float);
+ char *indexData = zData + (m_useDepthBuffer ? b->vertexCount * sizeof(float) : 0);
#endif
quint16 iOffset = 0;
@@ -1857,7 +1862,7 @@ void Renderer::uploadBatch(Batch *b)
dump << ") ";
offset += attr.tupleSize * size_of_type(attr.type);
}
- if (b->merged) {
+ if (b->merged && m_useDepthBuffer) {
float zorder = ((float*)(b->vbo.data + b->vertexCount * g->sizeOfVertex()))[i];
dump << " Z:(" << zorder << ")";
}
@@ -1907,10 +1912,10 @@ void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (batch->isOpaque)
glDisable(GL_DEPTH_TEST);
- ClipType type = updateStencilClip(m_currentClip);
+ m_currentClipType = updateStencilClip(m_currentClip);
if (batch->isOpaque) {
glEnable(GL_DEPTH_TEST);
- if (type & StencilClip)
+ if (m_currentClipType & StencilClip)
glDepthMask(true);
}
}
@@ -2025,7 +2030,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
QSGMaterial *material = gn->activeMaterial();
- ShaderManager::Shader *sms = m_shaderManager->prepareMaterial(material);
+ ShaderManager::Shader *sms = m_useDepthBuffer ? m_shaderManager->prepareMaterial(material) : m_shaderManager->prepareMaterialNoRewrite(material);
QSGMaterialShader *program = sms->program;
if (m_currentShader != sms)
@@ -2054,7 +2059,8 @@ void Renderer::renderMergedBatch(const Batch *batch)
glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, g->sizeOfVertex(), (void *) (qintptr) (offset + draw.vertices));
offset += a.tupleSize * size_of_type(a.type);
}
- glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders));
+ if (m_useDepthBuffer)
+ glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders));
glDrawElements(g->drawingMode(), draw.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (indexBase + draw.indices));
}
@@ -2136,8 +2142,10 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
m_current_determinant = m_current_model_view_matrix.determinant();
m_current_projection_matrix = projectionMatrix();
- m_current_projection_matrix(2, 2) = m_zRange;
- m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
+ if (m_useDepthBuffer) {
+ m_current_projection_matrix(2, 2) = m_zRange;
+ m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
+ }
program->updateState(state(dirty), material, m_currentMaterial);
@@ -2187,25 +2195,25 @@ void Renderer::renderBatches()
<< " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches...";
}
- for (QHash<QSGRenderNode *, RenderNodeElement *>::const_iterator it = m_renderNodeElements.constBegin();
- it != m_renderNodeElements.constEnd(); ++it) {
- prepareRenderNode(it.value());
- }
-
QRect r = viewportRect();
glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
glClearColor(clearColor().redF(), clearColor().greenF(), clearColor().blueF(), clearColor().alphaF());
+
+ if (m_useDepthBuffer) {
#if defined(QT_OPENGL_ES)
- glClearDepthf(1);
+ glClearDepthf(1);
#else
- glClearDepth(1);
+ glClearDepth(1);
#endif
-
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glDepthMask(true);
+ glDisable(GL_BLEND);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(false);
+ }
glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glDepthMask(true);
glColorMask(true, true, true, true);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
@@ -2232,7 +2240,8 @@ void Renderer::renderBatches()
}
glEnable(GL_BLEND);
- glDepthMask(false);
+ if (m_useDepthBuffer)
+ glDepthMask(false);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (Q_LIKELY(renderAlpha)) {
@@ -2252,7 +2261,6 @@ void Renderer::renderBatches()
updateStencilClip(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
}
void Renderer::deleteRemovedElements()
@@ -2404,33 +2412,15 @@ void Renderer::render()
m_vao->release();
}
-void Renderer::prepareRenderNode(RenderNodeElement *e)
+void Renderer::renderRenderNode(Batch *batch)
{
- if (e->fbo && e->fbo->size() != deviceRect().size()) {
- delete e->fbo;
- e->fbo = 0;
- }
+ if (Q_UNLIKELY(debug_render))
+ qDebug() << " -" << batch << "rendernode";
- if (!e->fbo)
- e->fbo = new QOpenGLFramebufferObject(deviceRect().size(), QOpenGLFramebufferObject::CombinedDepthStencil);
- e->fbo->bind();
+ Q_ASSERT(batch->first->isRenderNode);
+ RenderNodeElement *e = (RenderNodeElement *) batch->first;
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- QSGRenderNode::RenderState state;
- QMatrix4x4 pm = projectionMatrix();
- state.projectionMatrix = &pm;
- state.scissorEnabled = false;
- state.stencilEnabled = false;
+ setActiveShader(0, 0);
QSGNode *clip = e->renderNode->parent();
e->renderNode->m_clip_list = 0;
@@ -2442,6 +2432,16 @@ void Renderer::prepareRenderNode(RenderNodeElement *e)
clip = clip->parent();
}
+ updateClip(e->renderNode->m_clip_list, batch);
+
+ QSGRenderNode::RenderState state;
+ QMatrix4x4 pm = projectionMatrix();
+ state.projectionMatrix = &pm;
+ state.scissorEnabled = m_currentClipType & ScissorClip;
+ state.stencilEnabled = m_currentClipType & StencilClip;
+ state.scissorRect = m_current_scissor_rect;
+ state.stencilValue = m_current_stencil_value;
+
QSGNode *xform = e->renderNode->parent();
QMatrix4x4 matrix;
while (xform != rootNode()) {
@@ -2463,66 +2463,51 @@ void Renderer::prepareRenderNode(RenderNodeElement *e)
opacity = opacity->parent();
}
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
e->renderNode->render(state);
e->renderNode->m_matrix = 0;
+ e->renderNode->m_clip_list = 0;
- bindable()->bind();
-}
-
-void Renderer::renderRenderNode(Batch *batch)
-{
- updateStencilClip(0);
- m_currentClip = 0;
-
- setActiveShader(0, 0);
-
- if (!m_shaderManager->blitProgram) {
- m_shaderManager->blitProgram = new QOpenGLShaderProgram();
-
- QSGShaderSourceBuilder::initializeProgramFromFiles(
- m_shaderManager->blitProgram,
- QStringLiteral(":/scenegraph/shaders/rendernode.vert"),
- QStringLiteral(":/scenegraph/shaders/rendernode.frag"));
- m_shaderManager->blitProgram->bindAttributeLocation("av", 0);
- m_shaderManager->blitProgram->bindAttributeLocation("at", 1);
- m_shaderManager->blitProgram->link();
-
- Q_ASSERT(m_shaderManager->blitProgram->isLinked());
+ QSGRenderNode::StateFlags changes = e->renderNode->changedStates();
+ if (changes & QSGRenderNode::ViewportState) {
+ QRect r = viewportRect();
+ glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
}
- RenderNodeElement *e = static_cast<RenderNodeElement *>(batch->first);
- glBindTexture(GL_TEXTURE_2D, e->fbo->texture());
-
- m_shaderManager->blitProgram->bind();
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ if (changes & QSGRenderNode::StencilState) {
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilMask(0xff);
+ glDisable(GL_STENCIL_TEST);
+ }
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
+ if (changes & (QSGRenderNode::StencilState | QSGRenderNode::ScissorState)) {
+ glDisable(GL_SCISSOR_TEST);
+ m_currentClip = 0;
+ m_currentClipType = NoClip;
+ }
- float z = 1.0f - e->order * m_zRange;
+ if (changes & QSGRenderNode::DepthState)
+ glDisable(GL_DEPTH_TEST);
- float av[] = { -1, -1, z,
- 1, -1, z,
- -1, 1, z,
- 1, 1, z };
- float at[] = { 0, 0,
- 1, 0,
- 0, 1,
- 1, 1 };
+ if (changes & QSGRenderNode::ColorState)
+ bindable()->reactivate();
- glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, av);
- glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, at);
+ if (changes & QSGRenderNode::BlendState) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ if (changes & QSGRenderNode::CullState) {
+ glFrontFace(isMirrored() ? GL_CW : GL_CCW);
+ glDisable(GL_CULL_FACE);
+ }
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
- glBindTexture(GL_TEXTURE_2D, 0);
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 001c3b21ab..0aa84da185 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -194,15 +194,11 @@ struct RenderNodeElement : public Element {
RenderNodeElement(QSGRenderNode *rn)
: Element(0)
, renderNode(rn)
- , fbo(0)
{
isRenderNode = true;
}
- ~RenderNodeElement();
-
QSGRenderNode *renderNode;
- QOpenGLFramebufferObject *fbo;
};
struct BatchRootInfo {
@@ -436,7 +432,6 @@ private:
void renderUnmergedBatch(const Batch *batch);
void updateClip(const QSGClipNode *clipList, const Batch *batch);
const QMatrix4x4 &matrixForRoot(Node *node);
- void prepareRenderNode(RenderNodeElement *e);
void renderRenderNode(Batch *batch);
void setActiveShader(QSGMaterialShader *program, ShaderManager::Shader *shader);
@@ -460,6 +455,8 @@ private:
bool m_partialRebuild;
QSGNode *m_partialRebuildRoot;
+ bool m_useDepthBuffer;
+
QHash<QSGRenderNode *, RenderNodeElement *> m_renderNodeElements;
QDataBuffer<Batch *> m_opaqueBatches;
QDataBuffer<Batch *> m_alphaBatches;
@@ -483,6 +480,7 @@ private:
QSGMaterialShader *m_currentProgram;
ShaderManager::Shader *m_currentShader;
const QSGClipNode *m_currentClip;
+ ClipType m_currentClipType;
// For minimal OpenGL core profile support
QOpenGLVertexArrayObject *m_vao;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 90803db9fe..829d33a0d7 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -210,10 +210,17 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
static bool dumped = false;
if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) {
dumped = true;
- qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR);
- qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER);
- qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION);
- qDebug() << "GL_EXTENSIONS:\n " << QByteArray((const char *) glGetString(GL_EXTENSIONS)).replace(" ", "\n ").constData();
+ QSurfaceFormat format = renderContext->openglContext()->format();
+ qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
+ qDebug() << "Depth Buffer: " << format.depthBufferSize();
+ qDebug() << "Stencil Buffer: " << format.stencilBufferSize();
+ qDebug() << "Samples: " << format.samples();
+ qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR);
+ qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER);
+ qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION);
+ QSet<QByteArray> exts = renderContext->openglContext()->extensions();
+ QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e;
+ qDebug() << "GL_EXTENSIONS: " << all.constData();
}
d->mutex.unlock();
@@ -282,8 +289,10 @@ QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc)
QSurfaceFormat QSGContext::defaultSurfaceFormat() const
{
QSurfaceFormat format;
- format.setDepthBufferSize(24);
- format.setStencilBufferSize(8);
+ static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
+ static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER");
+ format.setDepthBufferSize(useDepth ? 24 : 0);
+ format.setStencilBufferSize(useStencil ? 8 : 0);
if (QQuickWindow::hasDefaultAlphaBuffer())
format.setAlphaBufferSize(8);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
@@ -349,6 +358,12 @@ QSGRenderContext::~QSGRenderContext()
invalidate();
}
+void QSGRenderContext::endSync()
+{
+ qDeleteAll(m_texturesToDelete);
+ m_texturesToDelete.clear();
+}
+
static QBasicMutex qsg_framerender_mutex;
void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
@@ -466,6 +481,9 @@ void QSGRenderContext::invalidate()
if (!m_gl)
return;
+ qDeleteAll(m_texturesToDelete);
+ m_texturesToDelete.clear();
+
qDeleteAll(m_textures.values());
m_textures.clear();
@@ -608,10 +626,8 @@ QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, Q
void QSGRenderContext::textureFactoryDestroyed(QObject *o)
{
m_mutex.lock();
- QSGTexture *t = m_textures.take(static_cast<QQuickTextureFactory *>(o));
+ m_texturesToDelete << m_textures.take(static_cast<QQuickTextureFactory *>(o));
m_mutex.unlock();
- if (t)
- t->deleteLater();
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index c562a909c5..c1bf78a018 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -94,6 +94,7 @@ public:
virtual void invalidate();
virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId);
+ virtual void endSync();
virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
QSGDepthStencilBufferManager *depthStencilBufferManager();
@@ -124,6 +125,7 @@ protected:
QMutex m_mutex;
QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
+ QSet<QSGTexture *> m_texturesToDelete;
QSGAtlasTexture::Manager *m_atlasManager;
QSGDepthStencilBufferManager *m_depthStencilManager;
diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
index fb989fd6fb..810a503cee 100644
--- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
@@ -385,7 +385,7 @@ void QSGDefaultRectangleNode::updateGeometry()
int borderTail = 0;
int outerAAHead = 0;
int outerAATail = 0;
- bool hasFill = m_color.rgba() != 0 || !stops.isEmpty();
+ bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
if (hasFill)
indexCount += fillIndexCount;
if (m_antialiasing) {
@@ -609,7 +609,7 @@ void QSGDefaultRectangleNode::updateGeometry()
int borderTail = 0;
int outerAAHead = 0;
int outerAATail = 0;
- bool hasFill = m_color.rgba() != 0 || !stops.isEmpty();
+ bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
if (hasFill)
indexCount += fillIndexCount;
if (m_antialiasing) {
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 6e0fdc7290..d080c59198 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -48,6 +48,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QSurface>
+#include <QtGui/qpa/qplatformnativeinterface.h>
#include <private/qsgtexture_p.h>
@@ -144,10 +145,21 @@ Atlas::Atlas(const QSize &size)
{
#ifdef QT_OPENGL_ES
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
+ QString *deviceName =
+ static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
+ static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
+#else
+ static bool wrongfullyReportsBgra8888Support = false;
+#endif
+
const char *ext = (const char *) glGetString(GL_EXTENSIONS);
- if (strstr(ext, "GL_EXT_bgra")
- || strstr(ext, "GL_EXT_texture_format_BGRA8888")
- || strstr(ext, "GL_IMG_texture_format_BGRA8888")) {
+ if (!wrongfullyReportsBgra8888Support
+ && (strstr(ext, "GL_EXT_bgra")
+ || strstr(ext, "GL_EXT_texture_format_BGRA8888")
+ || strstr(ext, "GL_IMG_texture_format_BGRA8888"))) {
m_internalFormat = m_externalFormat = GL_BGRA;
#ifdef Q_OS_IOS
} else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index d84ccb7a1f..ae1bec3f42 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -47,8 +47,10 @@
#include <qthread.h>
#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlglobal_p.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qpa/qplatformnativeinterface.h>
-#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(__UCLIBC__)
#define CAN_BACKTRACE_EXECINFO
#endif
@@ -679,14 +681,25 @@ void QSGPlainTexture::bind()
GLenum externalFormat = GL_RGBA;
GLenum internalFormat = GL_RGBA;
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
+ QString *deviceName =
+ static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
+ static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
+#else
+ static bool wrongfullyReportsBgra8888Support = false;
+#endif
+
QOpenGLContext *context = QOpenGLContext::currentContext();
if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
externalFormat = GL_BGRA;
#ifdef QT_OPENGL_ES
internalFormat = GL_BGRA;
#endif
- } else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
- || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) {
+ } else if (!wrongfullyReportsBgra8888Support
+ && (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
+ || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) {
externalFormat = GL_BGRA;
internalFormat = GL_BGRA;
#ifdef Q_OS_IOS
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
new file mode 100644
index 0000000000..25e63669c4
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 400
+ height: 400
+
+ onWidthChanged: console.log(width);
+ Component.onCompleted: width = 500;
+}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
index 87d8b647d1..647d761dc4 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
@@ -19,4 +19,5 @@ OTHER_FILES += \
data/test.qml \
data/exit.qml \
data/scenegraphTest.qml \
- data/TestImage_2x2.png
+ data/TestImage_2x2.png \
+ data/signalSourceLocation.qml
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 56ed65f54d..9d2e0ecbb4 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -181,6 +181,7 @@ private slots:
void scenegraphData();
void profileOnExit();
void controlFromJS();
+ void signalSourceLocation();
};
void QQmlProfilerClient::messageReceived(const QByteArray &message)
@@ -513,6 +514,35 @@ void tst_QQmlProfilerService::controlFromJS()
QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
+void tst_QQmlProfilerService::signalSourceLocation()
+{
+ connect(true, "signalSourceLocation.qml");
+ QVERIFY(m_client);
+ QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
+
+ m_client->setTraceState(true);
+ while (!(m_process->output().contains(QLatin1String("500"))))
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
+ m_client->setTraceState(false);
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+
+ // must start with "StartTrace"
+ QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
+
+ QVERIFY(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml"));
+ QVERIFY(m_client->traceMessages[14].line == 8);
+ QVERIFY(m_client->traceMessages[14].column == 28);
+
+ QVERIFY(m_client->traceMessages[16].detailData.endsWith("signalSourceLocation.qml"));
+ QVERIFY(m_client->traceMessages[16].line == 7);
+ QVERIFY(m_client->traceMessages[16].column == 21);
+
+ // must end with "EndTrace"
+ QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+}
+
QTEST_MAIN(tst_QQmlProfilerService)
#include "tst_qqmlprofilerservice.moc"
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index a1662b495c..ba99b34935 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -148,6 +148,8 @@ private slots:
void functionDeclarationsInConditionals();
void arrayPop_QTBUG_35979();
+
+ void regexpLastMatch();
};
tst_QJSEngine::tst_QJSEngine()
@@ -2705,6 +2707,68 @@ void tst_QJSEngine::arrayPop_QTBUG_35979()
QCOMPARE(result.toString(), QString("1,3"));
}
+void tst_QJSEngine::regexpLastMatch()
+{
+ QJSEngine eng;
+
+ QCOMPARE(eng.evaluate("RegExp.input").toString(), QString());
+
+ QJSValue hasProperty;
+
+ for (int i = 1; i < 9; ++i) {
+ hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$" + QString::number(i) + "\")");
+ QVERIFY(hasProperty.isBool());
+ QVERIFY(hasProperty.toBool());
+ }
+
+ hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$0\")");
+ QVERIFY(hasProperty.isBool());
+ QVERIFY(!hasProperty.toBool());
+
+ hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$10\")");
+ QVERIFY(!hasProperty.toBool());
+
+ hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"lastMatch\")");
+ QVERIFY(hasProperty.toBool());
+ hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$&\")");
+ QVERIFY(hasProperty.toBool());
+
+ QJSValue result = eng.evaluate(""
+ "var re = /h(el)l(o)/\n"
+ "var text = \"blah hello world\"\n"
+ "text.match(re)\n");
+ QVERIFY(!result.isError());
+ QJSValue match = eng.evaluate("RegExp.$1");
+ QCOMPARE(match.toString(), QString("el"));
+ match = eng.evaluate("RegExp.$2");
+ QCOMPARE(match.toString(), QString("o"));
+ for (int i = 3; i <= 9; ++i) {
+ match = eng.evaluate("RegExp.$" + QString::number(i));
+ QVERIFY(match.isString());
+ QCOMPARE(match.toString(), QString());
+ }
+ QCOMPARE(eng.evaluate("RegExp.input").toString(), QString("blah hello world"));
+ QCOMPARE(eng.evaluate("RegExp.lastParen").toString(), QString("o"));
+ QCOMPARE(eng.evaluate("RegExp.leftContext").toString(), QString("blah "));
+ QCOMPARE(eng.evaluate("RegExp.rightContext").toString(), QString(" world"));
+
+ QCOMPARE(eng.evaluate("RegExp.lastMatch").toString(), QString("hello"));
+
+ result = eng.evaluate(""
+ "var re = /h(ello)/\n"
+ "var text = \"hello\"\n"
+ "text.match(re)\n");
+ QVERIFY(!result.isError());
+ match = eng.evaluate("RegExp.$1");
+ QCOMPARE(match.toString(), QString("ello"));
+ for (int i = 2; i <= 9; ++i) {
+ match = eng.evaluate("RegExp.$" + QString::number(i));
+ QVERIFY(match.isString());
+ QCOMPARE(match.toString(), QString());
+ }
+
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 86321c775e..59b54e7ba5 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -1440,17 +1440,23 @@ void tst_qquickflickable::stopAtBounds_data()
{
QTest::addColumn<bool>("transpose");
QTest::addColumn<bool>("invert");
-
- QTest::newRow("left") << false << false;
- QTest::newRow("right") << false << true;
- QTest::newRow("top") << true << false;
- QTest::newRow("bottom") << true << true;
+ QTest::addColumn<bool>("pixelAligned");
+
+ QTest::newRow("left") << false << false << false;
+ QTest::newRow("right") << false << true << false;
+ QTest::newRow("top") << true << false << false;
+ QTest::newRow("bottom") << true << true << false;
+ QTest::newRow("left,pixelAligned") << false << false << true;
+ QTest::newRow("right,pixelAligned") << false << true << true;
+ QTest::newRow("top,pixelAligned") << true << false << true;
+ QTest::newRow("bottom,pixelAligned") << true << true << true;
}
void tst_qquickflickable::stopAtBounds()
{
QFETCH(bool, transpose);
QFETCH(bool, invert);
+ QFETCH(bool, pixelAligned);
QQuickView view;
view.setSource(testFileUrl("stopAtBounds.qml"));
@@ -1469,6 +1475,7 @@ void tst_qquickflickable::stopAtBounds()
flickable->setContentY(invert ? 100 : 0);
else
flickable->setContentX(invert ? 100 : 0);
+ flickable->setPixelAligned(pixelAligned);
const int threshold = qApp->styleHints()->startDragDistance();
@@ -1518,6 +1525,29 @@ void tst_qquickflickable::stopAtBounds()
}
QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+
+ if (transpose) {
+ flickable->setContentY(invert ? 100 : 0);
+ } else {
+ flickable->setContentX(invert ? 100 : 0);
+ }
+ if (invert)
+ flick(&view, QPoint(20,20), QPoint(100,100), 100);
+ else
+ flick(&view, QPoint(100,100), QPoint(20,20), 100);
+
+ QVERIFY(flickable->isFlicking());
+ if (transpose) {
+ if (invert)
+ QTRY_COMPARE(flickable->isAtYBeginning(), true);
+ else
+ QTRY_COMPARE(flickable->isAtYEnd(), true);
+ } else {
+ if (invert)
+ QTRY_COMPARE(flickable->isAtXBeginning(), true);
+ else
+ QTRY_COMPARE(flickable->isAtXEnd(), true);
+ }
}
void tst_qquickflickable::nestedMouseAreaUsingTouch()
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index d241ac2d70..e6a74bb062 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -1724,6 +1724,12 @@ void tst_qquicktext::linkInteraction_data()
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center())
<< singleLineLink
<< singleLineLink << singleLineLink;
+ QTest::newRow("click on mirrored link")
+ << singleLineText << 240.
+ << "horizontalAlignment: Text.AlignLeft; LayoutMirroring.enabled: true"
+ << (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignTop).center())
+ << singleLineLink
+ << singleLineLink << singleLineLink;
QTest::newRow("click on center aligned link")
<< singleLineText << 240.
<< "horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter"
@@ -2545,6 +2551,18 @@ void tst_qquicktext::boundingRect()
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
QCOMPARE(text->boundingRect().height(), line.height());
+ QQuickItemPrivate::get(text)->setLayoutMirror(true);
+ QCOMPARE(text->boundingRect().x(), qreal(0));
+ QCOMPARE(text->boundingRect().y(), qreal(0));
+ QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
+ QCOMPARE(text->boundingRect().height(), line.height());
+
+ text->setHAlign(QQuickText::AlignLeft);
+ QCOMPARE(text->boundingRect().x(), text->width() - line.naturalTextWidth());
+ QCOMPARE(text->boundingRect().y(), qreal(0));
+ QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
+ QCOMPARE(text->boundingRect().height(), line.height());
+
text->setWrapMode(QQuickText::Wrap);
QCOMPARE(text->boundingRect().right(), text->width());
QCOMPARE(text->boundingRect().y(), qreal(0));
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 6939ce92e2..d53005109e 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -98,14 +98,14 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met
const QMetaObject *meta = object->metaObject();
if (verbose)
- qDebug() << "Processing object" << meta->className();
+ std::cerr << "Processing object" << qPrintable( meta->className() ) << std::endl;
collectReachableMetaObjects(meta, metas);
for (int index = 0; index < meta->propertyCount(); ++index) {
QMetaProperty prop = meta->property(index);
if (QQmlMetaType::isQObject(prop.userType())) {
if (verbose)
- qDebug() << " Processing property" << prop.name();
+ std::cerr << " Processing property" << qPrintable( prop.name() ) << std::endl;
currentProperty = QString("%1::%2").arg(meta->className(), prop.name());
// if the property was not initialized during construction,
@@ -175,20 +175,41 @@ QByteArray convertToId(const QMetaObject *mo)
if (!className.isEmpty())
return className;
- qWarning() << "Found a QMetaObject without a className, generating a random name";
+ std::cerr << "Found a QMetaObject without a className, generating a random name" << std::endl;
className = QByteArray("error-unknown-name-");
className.append(QByteArray::number(generatedNames.size()));
generatedNames.insert(mo, className);
return className;
}
-QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const QList<QQmlType *> &skip = QList<QQmlType *>())
+
+// Collect all metaobjects for types registered with qmlRegisterType() without parameters
+void collectReachableMetaObjectsWithoutQmlName( QSet<const QMetaObject *>& metas ) {
+ foreach (const QQmlType *ty, QQmlMetaType::qmlAllTypes()) {
+ if ( ! metas.contains(ty->metaObject()) ) {
+ if (!ty->isComposite()) {
+ collectReachableMetaObjects(ty, &metas);
+ } else {
+ qmlTypesByCompositeName[ty->elementName()] = ty;
+ }
+ }
+ }
+}
+
+QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
+ QSet<const QMetaObject *> &noncreatables,
+ QSet<const QMetaObject *> &singletons,
+ const QList<QQmlType *> &skip = QList<QQmlType *>())
{
QSet<const QMetaObject *> metas;
metas.insert(FriendlyQObject::qtMeta());
QHash<QByteArray, QSet<QByteArray> > extensions;
foreach (const QQmlType *ty, QQmlMetaType::qmlTypes()) {
+ if (!ty->isCreatable())
+ noncreatables.insert(ty->metaObject());
+ if (ty->isSingleton())
+ singletons.insert(ty->metaObject());
if (!ty->isComposite()) {
qmlTypesByCppName[ty->metaObject()->className()].insert(ty);
if (ty->isExtendedType())
@@ -255,15 +276,15 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (ty->isSingleton()) {
QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo();
if (!siinfo) {
- qWarning() << "Internal error, " << tyName
- << "(" << QString::fromUtf8(ty->typeName()) << ")"
- << " is singleton, but has no singletonInstanceInfo";
+ std::cerr << "Internal error, " << qPrintable(tyName)
+ << "(" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")"
+ << " is singleton, but has no singletonInstanceInfo" << std::endl;
continue;
}
if (siinfo->qobjectCallback) {
if (verbose)
- qDebug() << "Trying to get singleton for " << tyName
- << " (" << siinfo->typeName << ")";
+ std::cerr << "Trying to get singleton for " << qPrintable(tyName)
+ << " (" << qPrintable( siinfo->typeName ) << ")" << std::endl;
siinfo->init(engine);
collectReachableMetaObjects(object, &metas);
object = siinfo->qobjectApi(engine);
@@ -273,8 +294,8 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
}
} else {
if (verbose)
- qDebug() << "Trying to create object " << tyName
- << " (" << QString::fromUtf8(ty->typeName()) << ")";
+ std::cerr << "Trying to create object " << qPrintable( tyName )
+ << " (" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")" << std::endl;
object = ty->create();
}
@@ -282,15 +303,17 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (object) {
if (verbose)
- qDebug() << "Got " << tyName
- << " (" << QString::fromUtf8(ty->typeName()) << ")";
+ std::cerr << "Got " << qPrintable( tyName )
+ << " (" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")" << std::endl;
collectReachableMetaObjects(object, &metas);
} else {
- qWarning() << "Could not create" << tyName;
+ std::cerr << "Could not create" << qPrintable(tyName) << std::endl;
}
}
}
+ collectReachableMetaObjectsWithoutQmlName(metas);
+
return metas;
}
@@ -406,6 +429,12 @@ public:
qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType->minorVersion()));
+ if (compositeType->isCreatable())
+ qml->writeIsCreatable(false);
+
+ if (compositeType->isSingleton())
+ qml->writeIsSingleton(true);
+
for (int index = mainMeta->classInfoCount() - 1 ; index >= 0 ; --index) {
QMetaClassInfo classInfo = mainMeta->classInfo(index);
if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
@@ -437,7 +466,7 @@ public:
qml->writeEndObject();
}
- void dump(const QMetaObject *meta)
+ void dump(const QMetaObject *meta, bool isUncreatable, bool isSingleton)
{
qml->writeStartObject("Component");
@@ -469,6 +498,12 @@ public:
std::sort(exportStrings.begin(), exportStrings.end());
qml->writeArrayBinding(QLatin1String("exports"), exportStrings);
+ if (isUncreatable)
+ qml->writeIsCreatable(false);
+
+ if (isSingleton)
+ qml->writeIsSingleton(true);
+
// write meta object revisions
QStringList metaObjectRevisions;
foreach (const QString &exportString, exportStrings) {
@@ -622,7 +657,6 @@ private:
}
};
-
enum ExitCode {
EXIT_INVALIDARGUMENTS = 1,
EXIT_SEGV = 2,
@@ -642,12 +676,12 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
- qWarning() << qPrintable(QString(
+ std::cerr << qPrintable(QString(
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
- appName));
+ appName)) << std::endl;
}
int main(int argc, char *argv[])
@@ -726,14 +760,14 @@ int main(int argc, char *argv[])
|| arg == QLatin1String("-defaultplatform")) {
continue;
} else {
- qWarning() << "Invalid argument: " << arg;
+ std::cerr << "Invalid argument: " << qPrintable(arg) << std::endl;
return EXIT_INVALIDARGUMENTS;
}
}
if (action == Uri) {
if (positionalArgs.size() != 3 && positionalArgs.size() != 4) {
- qWarning() << "Incorrect number of positional arguments";
+ std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
pluginImportUri = positionalArgs[1];
@@ -742,7 +776,7 @@ int main(int argc, char *argv[])
pluginImportPath = positionalArgs[3];
} else if (action == Path) {
if (positionalArgs.size() != 2 && positionalArgs.size() != 3) {
- qWarning() << "Incorrect number of positional arguments";
+ std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
pluginImportPath = QDir::fromNativeSeparators(positionalArgs[1]);
@@ -750,7 +784,7 @@ int main(int argc, char *argv[])
pluginImportVersion = positionalArgs[2];
} else if (action == Builtins) {
if (positionalArgs.size() != 1) {
- qWarning() << "Incorrect number of positional arguments";
+ std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
}
@@ -760,7 +794,7 @@ int main(int argc, char *argv[])
if (!pluginImportPath.isEmpty()) {
QDir cur = QDir::current();
cur.cd(pluginImportPath);
- pluginImportPath = cur.absolutePath();
+ pluginImportPath = cur.canonicalPath();
QDir::setCurrent(pluginImportPath);
engine.addImportPath(pluginImportPath);
}
@@ -773,13 +807,15 @@ int main(int argc, char *argv[])
c.create();
if (!c.errors().isEmpty()) {
foreach (const QQmlError &error, c.errors())
- qWarning() << error.toString();
+ std::cerr << qPrintable( error.toString() ) << std::endl;
return EXIT_IMPORTERROR;
}
}
// find all QMetaObjects reachable from the builtin module
- QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine);
+ QSet<const QMetaObject *> uncreatableMetas;
+ QSet<const QMetaObject *> singletonMetas;
+ QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas);
QList<QQmlType *> defaultTypes = QQmlMetaType::qmlTypes();
// add some otherwise unreachable QMetaObjects
@@ -797,7 +833,7 @@ int main(int argc, char *argv[])
QByteArray importCode;
QQmlType *qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
if (!qtObjectType) {
- qWarning() << "Could not find QtObject type";
+ std::cerr << "Could not find QtObject type" << std::endl;
importCode = QByteArray("import QtQuick 2.0\n");
} else {
QString module = qtObjectType->qmlTypeName();
@@ -826,12 +862,12 @@ int main(int argc, char *argv[])
c.create();
if (!c.errors().isEmpty()) {
foreach (const QQmlError &error, c.errors())
- qWarning() << error.toString();
+ std::cerr << qPrintable( error.toString() ) << std::endl;
return EXIT_IMPORTERROR;
}
}
- QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, defaultTypes);
+ QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, defaultTypes);
candidates.subtract(defaultReachable);
// Also eliminate meta objects with the same classname.
@@ -873,7 +909,7 @@ int main(int argc, char *argv[])
if (relocatable)
dumper.setRelocatableModuleUri(pluginImportUri);
foreach (const QMetaObject *meta, nameToMeta) {
- dumper.dump(meta);
+ dumper.dump(meta, uncreatableMetas.contains(meta), singletonMetas.contains(meta));
}
foreach (const QQmlType *compositeType, qmlTypesByCompositeName)
dumper.dumpComposite(&engine, compositeType, defaultReachableNames);
diff --git a/tools/qmlplugindump/qmlstreamwriter.cpp b/tools/qmlplugindump/qmlstreamwriter.cpp
index 629e30b814..44bdcfea74 100644
--- a/tools/qmlplugindump/qmlstreamwriter.cpp
+++ b/tools/qmlplugindump/qmlstreamwriter.cpp
@@ -183,6 +183,16 @@ void QmlStreamWriter::writePotentialLine(const QByteArray &line)
}
}
+void QmlStreamWriter::writeIsCreatable(bool isCreatable) {
+ writeIndent();
+ m_stream->write(QString("isCreatable: %1\n").arg(isCreatable ? "true" : "false").toUtf8());
+}
+
+void QmlStreamWriter::writeIsSingleton(bool isSingleton) {
+ writeIndent();
+ m_stream->write(QString("isSingleton: %1\n").arg(isSingleton ? "true" : "false").toUtf8());
+}
+
void QmlStreamWriter::flushPotentialLinesWithNewlines()
{
if (m_maybeOneline)
diff --git a/tools/qmlplugindump/qmlstreamwriter.h b/tools/qmlplugindump/qmlstreamwriter.h
index 9d8052911c..ee5740a48b 100644
--- a/tools/qmlplugindump/qmlstreamwriter.h
+++ b/tools/qmlplugindump/qmlstreamwriter.h
@@ -63,6 +63,8 @@ public:
void writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue);
void writeArrayBinding(const QString &name, const QStringList &elements);
void write(const QString &data);
+ void writeIsCreatable(bool isCreatable);
+ void writeIsSingleton(bool isSingleton);
private:
void writeIndent();