aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/imports.pro3
-rw-r--r--src/imports/settings/settings.pro3
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp10
-rw-r--r--src/qml/compiler/qv4compileddata_p.h4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h1
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp37
-rw-r--r--src/qml/compiler/qv4ssa.cpp4
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc4
-rw-r--r--src/qml/jsruntime/qv4value_p.h5
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h4
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp4
-rw-r--r--src/quick/doc/snippets/qml/localstorage/dbtransaction.js31
-rw-r--r--src/quick/items/qquickdrag.cpp2
-rw-r--r--src/quick/items/qquickitem.cpp4
-rw-r--r--src/quick/items/qquicktextinput.cpp4
-rw-r--r--src/quick/items/qquickwindow.cpp1
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp3
-rw-r--r--src/quick/util/qquickshortcut.cpp55
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp18
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp7
-rw-r--r--tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp64
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicktextedit/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp16
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml18
-rw-r--r--tools/qmljs/qmljs.cpp45
30 files changed, 276 insertions, 83 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index affc1db2c0..cad02a2980 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -6,9 +6,10 @@ SUBDIRS += \
folderlistmodel \
localstorage \
models \
- settings \
statemachine
+qtConfig(settings): SUBDIRS += settings
+
qtHaveModule(quick) {
SUBDIRS += \
layouts \
diff --git a/src/imports/settings/settings.pro b/src/imports/settings/settings.pro
index 3d7c9c31b8..29229f59cb 100644
--- a/src/imports/settings/settings.pro
+++ b/src/imports/settings/settings.pro
@@ -1,6 +1,3 @@
-load(qfeatures)
-requires(!contains(QT_DISABLED_FEATURES, settings))
-
CXX_MODULE = qml
TARGET = qmlsettingsplugin
TARGETPATH = Qt/labs/settings
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 11c8641e21..2467239be2 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
!contains(QT_CONFIG, no-qml-debug):SUBDIRS += qmltooling
-SUBDIRS += scenegraph
+qtHaveModule(quick):SUBDIRS += scenegraph
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
index 31873f7915..b0f59717ac 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp
@@ -70,7 +70,7 @@ void QDebugMessageServiceImpl::sendDebugMessage(QtMsgType type,
//We just eavesdrop and forward the messages to a port
//only if a client is connected to it.
QQmlDebugPacket ws;
- ws << QByteArray("MESSAGE") << type << buf.toUtf8();
+ ws << QByteArray("MESSAGE") << int(type) << buf.toUtf8();
ws << QByteArray(ctxt.file) << ctxt.line << QByteArray(ctxt.function);
ws << QByteArray(ctxt.category) << timer.nsecsElapsed();
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index a4320098c0..90e817e2fc 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -101,7 +101,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
ds << static_cast<qint64>(d.locationId);
messages.append(ds.squeezedData());
ds.clear();
- ds << d.time << QQmlProfilerDefinitions::RangeData
+ ds << d.time << int(QQmlProfilerDefinitions::RangeData)
<< static_cast<quint32>(d.detailType)
<< (i->location.sourceFile.isEmpty() ? i->url.toString() :
i->location.sourceFile);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index eee1dd7eae..eae5e0a795 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -76,7 +76,7 @@ qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &m
while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) {
const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos];
- d << props.timestamp << MemoryAllocation << props.type << props.size;
+ d << props.timestamp << int(MemoryAllocation) << int(props.type) << props.size;
++m_memoryPos;
messages.append(d.squeezedData());
d.clear();
@@ -120,7 +120,7 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
return finalizeMessages(until, messages, m_stack.top(), d);
appendMemoryEvents(m_stack.top(), messages, d);
- d << m_stack.pop() << RangeEnd << Javascript;
+ d << m_stack.pop() << int(RangeEnd) << int(Javascript);
messages.append(d.squeezedData());
d.clear();
}
@@ -134,19 +134,19 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
appendMemoryEvents(props.start, messages, d);
auto location = m_functionLocations.find(props.id);
- d << props.start << RangeStart << Javascript;
+ d << props.start << int(RangeStart) << int(Javascript);
if (trackLocations)
d << static_cast<qint64>(props.id);
if (location != m_functionLocations.end()) {
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << RangeLocation << Javascript << location->file << location->line
+ d << props.start << int(RangeLocation) << int(Javascript) << location->file << location->line
<< location->column;
if (trackLocations)
d << static_cast<qint64>(props.id);
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << RangeData << Javascript << location->name;
+ d << props.start << int(RangeData) << int(Javascript) << location->name;
if (trackLocations) {
d << static_cast<qint64>(props.id);
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 8f68131ced..90cbe04505 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -71,7 +71,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x06
+#define QV4_DATA_STRUCTURE_VERSION 0x07
class QIODevice;
class QQmlPropertyCache;
@@ -587,7 +587,7 @@ struct Import
ImportFile = 0x2,
ImportScript = 0x3
};
- quint8 type;
+ LEUInt32 type;
LEUInt32 uriIndex;
LEUInt32 qualifierIndex;
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index b83bcdb83b..ca4e0b73d4 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -253,6 +253,7 @@ union Instr
{
enum Type {
FOR_EACH_MOTH_INSTR(MOTH_INSTR_ENUM)
+ LastInstruction
};
struct instr_common {
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 5dd722bfc2..1f5c22eb97 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -1477,6 +1477,17 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit
QByteArray padding;
+#ifdef MOTH_THREADED_INTERPRETER
+ // Map from instruction label back to instruction type. Only needed when persisting
+ // already linked compilation units;
+ QHash<void*, int> reverseInstructionMapping;
+ if (engine) {
+ void **instructions = VME::instructionJumpTable();
+ for (int i = 0; i < Instr::LastInstruction; ++i)
+ reverseInstructionMapping.insert(instructions[i], i);
+ }
+#endif
+
for (int i = 0; i < codeRefs.size(); ++i) {
const CompiledData::Function *compiledFunction = unit->functionAt(i);
@@ -1493,8 +1504,30 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit
return false;
}
- const void *codePtr = codeRefs.at(i).constData();
- written = device->write(reinterpret_cast<const char *>(codePtr), compiledFunction->codeSize);
+ QByteArray code = codeRefs.at(i);
+
+#ifdef MOTH_THREADED_INTERPRETER
+ if (!reverseInstructionMapping.isEmpty()) {
+ char *codePtr = code.data(); // detaches
+ int index = 0;
+ while (index < code.size()) {
+ Instr *genericInstr = reinterpret_cast<Instr *>(codePtr + index);
+
+ genericInstr->common.instructionType = reverseInstructionMapping.value(genericInstr->common.code);
+
+ switch (genericInstr->common.instructionType) {
+ #define REVERSE_INSTRUCTION(InstructionType, Member) \
+ case Instr::InstructionType: \
+ index += InstrMeta<(int)Instr::InstructionType>::Size; \
+ break;
+
+ FOR_EACH_MOTH_INSTR(REVERSE_INSTRUCTION)
+ }
+ }
+ }
+#endif
+
+ written = device->write(code.constData(), compiledFunction->codeSize);
if (written != qint64(compiledFunction->codeSize)) {
*errorString = device->errorString();
return false;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index a98cf6d338..4fa0cf421b 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -5077,6 +5077,10 @@ void mergeBasicBlocks(IR::Function *function, DefUses *du, DominatorTree *dt)
BasicBlock *successor = bb->out.first();
if (successor->in.size() != 1) continue; // more than one incoming edge
+ // Loop header? No efficient way to update the other blocks that refer to this as containing group,
+ // so don't do merging yet.
+ if (successor->isGroupStart()) continue;
+
// Ok, we can merge the two basic blocks.
if (DebugBlockMerging) {
qDebug("Merging L%d into L%d", successor->index(), bb->index());
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index cc2fe90483..ac6600f38c 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -52,8 +52,8 @@ remain with C++ by invoking QQmlEngine::setObjectOwnership() with
QQmlEngine::CppOwnership specified.
Additionally, the QML engine respects the normal QObject parent ownership
-semantics of Qt C++ objects, and will not ever take ownership of a QObject
-instance which already has a parent.
+semantics of Qt C++ objects, and will never delete a QObject instance which
+has a parent.
\section1 Basic Qt Data Types
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 4428c48d80..6d5cff4ecc 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -175,10 +175,7 @@ public:
Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
-#if defined(V4_BOOTSTRAP)
- Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; }
- Q_ALWAYS_INLINE void setM(Heap::Base *b) { Q_UNUSED(b); Q_UNREACHABLE(); }
-#elif defined(QV4_USE_64_BIT_VALUE_ENCODING)
+#if defined(QV4_USE_64_BIT_VALUE_ENCODING)
Q_ALWAYS_INLINE Heap::Base *m() const
{
Heap::Base *b;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index b820777973..630d04938a 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -468,7 +468,7 @@ private:
QQmlPropertyData *ensureResolved(QQmlPropertyData*) const;
- void resolve(QQmlPropertyData *) const;
+ Q_NEVER_INLINE void resolve(QQmlPropertyData *) const;
void updateRecur(const QMetaObject *);
template<typename K>
@@ -677,7 +677,7 @@ bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
{
- if (p && p->notFullyResolved())
+ if (p && Q_UNLIKELY(p->notFullyResolved()))
resolve(p);
return p;
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 58eab508ad..03236ce2f7 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -67,10 +67,6 @@ int QAccessibleQuickItem::childCount() const
QRect QAccessibleQuickItem::rect() const
{
const QRect r = itemScreenRect(item());
-
- if (!r.isValid()) {
- qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r;
- }
return r;
}
diff --git a/src/quick/doc/snippets/qml/localstorage/dbtransaction.js b/src/quick/doc/snippets/qml/localstorage/dbtransaction.js
index 07d8a5618b..40eb6d2804 100644
--- a/src/quick/doc/snippets/qml/localstorage/dbtransaction.js
+++ b/src/quick/doc/snippets/qml/localstorage/dbtransaction.js
@@ -39,30 +39,47 @@
****************************************************************************/
//![0]
+var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000);
db.transaction(
try {
function(tx) {
- tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO trip_log VALUES(?, ?, ?)',
+ [ '01/10/2016','Sylling - Vikersund', '53' ]);
}
} catch (err) {
- console.log("Error inserting into table Greeting");
+ console.log("Error inserting into table Greeting: " + err);
}
)
//![0]
//![1]
+// Retrieve activity date, description and distance based on minimum
+// distance parameter Pdistance
+function db_distance_select(Pdistance)
+{
+var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000);
db.transaction(
function(tx) {
- var results = tx.executeSql('SELECT salutation FROM Greeting WHERE salutee=?;', 'world');
+ var results = tx.executeSql('SELECT rowid,
+ date,
+ trip_desc,
+ distance FROM trip_log
+ where distance >= ?',[Pdistance]');
+ for (var i = 0; i < results.rows.length; i++) {
+ listModel.append({"id": results.rows.item(i).rowid,
+ "date": results.rows.item(i).date,
+ "trip_desc": results.rows.item(i).trip_desc,
+ "distance": results.rows.item(i).distance});
+ }
}
- console.log("We greeted in this most respectful way: " + results.rows.item(0).value);
-)
+}
//![1]
//![2]
-var db = LocalStorage.openDatabaseSync("QQmlExampleDB", "", "The Example QML SQL!", 1000000);
+var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000);
if (db.version == '0.1') {
db.changeVersion('0.1', '0.2', function(tx) {
- tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]);
+ tx.executeSql('INSERT INTO trip_log VALUES(?, ?, ?)',
+ [ '01/10/2016','Sylling - Vikersund', '53' ]);
}
});
//![2]
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index b943c28661..cbb052856e 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -749,7 +749,7 @@ void QQuickDragAttached::cancel()
*/
/*!
- \qmlattachedsignal QtQuick::Drag::dragFinished(DropAction action)
+ \qmlattachedsignal QtQuick::Drag::dragFinished(DropAction dropAction)
This signal is emitted when a drag finishes and the drag was started with the
\l startDrag() method or started automatically using the \l dragType property.
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index fd872a5912..a05bb1617e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6303,7 +6303,7 @@ QPointF QQuickItem::position() const
void QQuickItem::setX(qreal v)
{
Q_D(QQuickItem);
- if (qIsNaN(v))
+ if (qt_is_nan(v))
return;
if (d->x == v)
return;
@@ -6320,7 +6320,7 @@ void QQuickItem::setX(qreal v)
void QQuickItem::setY(qreal v)
{
Q_D(QQuickItem);
- if (qIsNaN(v))
+ if (qt_is_nan(v))
return;
if (d->y == v)
return;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 9a43ee8bdf..16278ad744 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -2340,8 +2340,8 @@ QString QQuickTextInput::preeditText() const
If true, the user can use the mouse to select text in some
platform-specific way. Note that for some platforms this may
- not be an appropriate interaction (eg. may conflict with how
- the text needs to behave inside a Flickable.
+ not be an appropriate interaction (it may conflict with how
+ the text needs to behave inside a \l Flickable, for example).
*/
bool QQuickTextInput::selectByMouse() const
{
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index f81c939ec6..dec5b44e2a 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1799,6 +1799,7 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event
if (item->contains(p)) {
QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(),
event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
+ wheel.setTimestamp(event->timestamp());
wheel.accept();
QCoreApplication::sendEvent(item, &wheel);
if (wheel.isAccepted()) {
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
index 3751891455..7fab9aeae8 100644
--- a/src/quick/scenegraph/qsgcontextplugin.cpp
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -148,9 +148,9 @@ QSGAdaptationBackendData *contextFactory()
}
}
+#ifndef QT_NO_LIBRARY
// Then try the plugins.
if (!backendData->factory) {
-#ifndef QT_NO_LIBRARY
const int index = loader()->indexOf(requestedBackend);
if (index != -1)
backendData->factory = qobject_cast<QSGContextFactoryInterface*>(loader()->instance(index));
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 3501f30487..b001899915 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -240,7 +240,8 @@ bool QSG24BitTextMaskShader::useSRGB() const
// m_useSRGB is true, but if some QOGLFBO was bound check it's texture format:
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLFramebufferObject *qfbo = QOpenGLContextPrivate::get(ctx)->qgl_current_fbo;
- return !qfbo || qfbo->format().internalTextureFormat() == GL_SRGB8_ALPHA8_EXT;
+ bool fboInvalid = QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid;
+ return !qfbo || fboInvalid || qfbo->format().internalTextureFormat() == GL_SRGB8_ALPHA8_EXT;
#else
return m_useSRGB;
#endif
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 9725ddd671..3e04161639 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -41,10 +41,9 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
+#include <QtQuick/private/qtquickglobal_p.h>
#include <QtGui/private/qguiapplication_p.h>
-QT_BEGIN_NAMESPACE
-
/*!
\qmltype Shortcut
\instantiates QQuickShortcut
@@ -89,6 +88,39 @@ QT_BEGIN_NAMESPACE
The corresponding handler is \c onActivatedAmbiguously.
*/
+static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context)
+{
+ switch (context) {
+ case Qt::ApplicationShortcut:
+ return true;
+ case Qt::WindowShortcut:
+ while (obj && !obj->isWindowType()) {
+ obj = obj->parent();
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(obj))
+ obj = item->window();
+ }
+ return obj && obj == QGuiApplication::focusWindow();
+ default:
+ return false;
+ }
+}
+
+typedef bool (*ContextMatcher)(QObject *, Qt::ShortcutContext);
+
+Q_GLOBAL_STATIC_WITH_ARGS(ContextMatcher, ctxMatcher, (qQuickShortcutContextMatcher))
+
+Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher()
+{
+ return *ctxMatcher();
+}
+
+Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher)
+{
+ *ctxMatcher() = matcher;
+}
+
+QT_BEGIN_NAMESPACE
+
QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_id(0),
m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut)
{
@@ -278,30 +310,13 @@ bool QQuickShortcut::event(QEvent *event)
return false;
}
-static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context)
-{
- switch (context) {
- case Qt::ApplicationShortcut:
- return true;
- case Qt::WindowShortcut:
- while (obj && !obj->isWindowType()) {
- obj = obj->parent();
- if (QQuickItem *item = qobject_cast<QQuickItem *>(obj))
- obj = item->window();
- }
- return obj && obj == QGuiApplication::focusWindow();
- default:
- return false;
- }
-}
-
void QQuickShortcut::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context)
{
ungrabShortcut();
if (m_completed && !sequence.isEmpty()) {
QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- m_id = pApp->shortcutMap.addShortcut(this, sequence, context, qQuickShortcutContextMatcher);
+ m_id = pApp->shortcutMap.addShortcut(this, sequence, context, *ctxMatcher());
if (!m_enabled)
pApp->shortcutMap.setShortcutEnabled(false, m_id, this);
if (!m_autorepeat)
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 81018aa68e..2c7dde1b8d 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -194,6 +194,8 @@ private slots:
void withNoContext();
void holeInPropertyData();
+ void basicBlockMergeAfterLoopPeeling();
+
signals:
void testSignal();
};
@@ -4059,6 +4061,22 @@ void tst_QJSEngine::holeInPropertyData()
QVERIFY(ok.toBool());
}
+void tst_QJSEngine::basicBlockMergeAfterLoopPeeling()
+{
+ QJSEngine engine;
+ QJSValue ok = engine.evaluate(
+ "function crashMe() {\n"
+ " var seen = false;\n"
+ " while (globalVar) {\n"
+ " if (seen)\n"
+ " return;\n"
+ " seen = true;\n"
+ " }\n"
+ "}\n");
+ QVERIFY(!ok.isCallable());
+
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 536bb40dcc..d0139b6cdf 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -48,7 +48,7 @@ public:
TestItem(QQuickItem *parent = 0)
: QQuickItem(parent), focused(false), pressCount(0), releaseCount(0)
, wheelCount(0), acceptIncomingTouchEvents(true)
- , touchEventReached(false) {}
+ , touchEventReached(false), timestamp(0) {}
bool focused;
int pressCount;
@@ -56,6 +56,7 @@ public:
int wheelCount;
bool acceptIncomingTouchEvents;
bool touchEventReached;
+ ulong timestamp;
protected:
virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
@@ -65,7 +66,7 @@ protected:
touchEventReached = true;
event->setAccepted(acceptIncomingTouchEvents);
}
- virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
+ virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; timestamp = event->timestamp(); }
};
class TestWindow: public QQuickWindow
@@ -1432,12 +1433,14 @@ void tst_qquickitem::wheelEvent()
item->setVisible(visible);
QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
+ event.setTimestamp(123456UL);
event.setAccepted(false);
QGuiApplication::sendEvent(&window, &event);
if (shouldReceiveWheelEvents) {
QVERIFY(event.isAccepted());
QCOMPARE(item->wheelCount, 1);
+ QCOMPARE(item->timestamp, 123456UL);
} else {
QVERIFY(!event.isAccepted());
QCOMPARE(item->wheelCount, 0);
diff --git a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
index 35a1aa8757..2df94bb84a 100644
--- a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
+++ b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
@@ -43,6 +43,8 @@ private slots:
void sequence();
void context_data();
void context();
+ void matcher_data();
+ void matcher();
};
Q_DECLARE_METATYPE(Qt::Key)
@@ -344,6 +346,68 @@ void tst_QQuickShortcut::context()
|| inactiveWindow->property("ambiguousShortcut").toString() == ambiguousShortcut);
}
+typedef bool (*ShortcutContextMatcher)(QObject *, Qt::ShortcutContext);
+extern ShortcutContextMatcher qt_quick_shortcut_context_matcher();
+extern void qt_quick_set_shortcut_context_matcher(ShortcutContextMatcher matcher);
+
+static ShortcutContextMatcher lastMatcher = nullptr;
+
+static bool trueMatcher(QObject *, Qt::ShortcutContext)
+{
+ lastMatcher = trueMatcher;
+ return true;
+}
+
+static bool falseMatcher(QObject *, Qt::ShortcutContext)
+{
+ lastMatcher = falseMatcher;
+ return false;
+}
+
+Q_DECLARE_METATYPE(ShortcutContextMatcher)
+
+void tst_QQuickShortcut::matcher_data()
+{
+ QTest::addColumn<ShortcutContextMatcher>("matcher");
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<QVariant>("shortcut");
+ QTest::addColumn<QString>("activatedShortcut");
+
+ ShortcutContextMatcher tm = trueMatcher;
+ ShortcutContextMatcher fm = falseMatcher;
+
+ QTest::newRow("F1") << tm << Qt::Key_F1 << shortcutMap("F1", Qt::ApplicationShortcut) << "F1";
+ QTest::newRow("F2") << fm << Qt::Key_F2 << shortcutMap("F2", Qt::ApplicationShortcut) << "";
+}
+
+void tst_QQuickShortcut::matcher()
+{
+ QFETCH(ShortcutContextMatcher, matcher);
+ QFETCH(Qt::Key, key);
+ QFETCH(QVariant, shortcut);
+ QFETCH(QString, activatedShortcut);
+
+ ShortcutContextMatcher defaultMatcher = qt_quick_shortcut_context_matcher();
+ QVERIFY(defaultMatcher);
+
+ qt_quick_set_shortcut_context_matcher(matcher);
+ QVERIFY(qt_quick_shortcut_context_matcher() == matcher);
+
+ QQmlApplicationEngine engine(testFileUrl("shortcuts.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(engine.rootObjects().value(0));
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ window->setProperty("shortcuts", QVariantList() << shortcut);
+ QTest::keyClick(window, key);
+
+ QVERIFY(lastMatcher == matcher);
+ QCOMPARE(window->property("activatedShortcut").toString(), activatedShortcut);
+
+ qt_quick_set_shortcut_context_matcher(defaultMatcher);
+}
+
QTEST_MAIN(tst_QQuickShortcut)
#include "tst_qquickshortcut.moc"
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
index f400af1d10..531d981159 100644
--- a/tests/auto/quick/qquicktext/BLACKLIST
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -1,7 +1,5 @@
[dependentImplicitSizes]
*
-[mouseSelection]
-*
[lineLaidOutRelayout]
msvc-2015
[fontSizeMode]
diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST
deleted file mode 100644
index 492d81531a..0000000000
--- a/tests/auto/quick/qquicktextedit/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[mouseSelection]
-*
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 3c899c1e34..5ed0e9eea7 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -2072,12 +2072,18 @@ void tst_qquicktextedit::mouseSelection()
else if (clicks == 3)
QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ if (clicks == 2) {
+ // QTBUG-50022: Since qtbase commit beef975, QTestLib avoids generating
+ // double click events by adding 500ms delta to release event timestamps.
+ // Send a double click event by hand to ensure the correct sequence:
+ // press, release, press, _dbl click_, move, release.
+ QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QGuiApplication::sendEvent(textEditObject, &dblClickEvent);
+ }
QTest::mouseMove(&window, p2);
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
- QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
-
// Clicking and shift to clicking between the same points should select the same text.
textEditObject->setCursorPosition(0);
if (clicks > 1)
@@ -2086,9 +2092,6 @@ void tst_qquicktextedit::mouseSelection()
QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
QTest::mouseClick(&window, Qt::LeftButton, Qt::ShiftModifier, p2);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
-
- // ### This is to prevent double click detection from carrying over to the next test.
- QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
}
void tst_qquicktextedit::dragMouseSelection()
@@ -3029,9 +3032,6 @@ void tst_qquicktextedit::middleClickPaste()
// Middle click pastes the selected text, assuming the platform supports it.
QTest::mouseClick(&window, Qt::MiddleButton, Qt::NoModifier, p3);
- // ### This is to prevent double click detection from carrying over to the next test.
- QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
-
if (QGuiApplication::clipboard()->supportsSelection())
QCOMPARE(textEditObject->text().mid(1, selectedText.length()), selectedText);
else
diff --git a/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml b/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml
new file mode 100644
index 0000000000..d1a289e24f
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml
@@ -0,0 +1,18 @@
+// test use of Fixedsys font on Windows
+
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+
+ Text {
+ anchors.fill: parent
+ wrapMode: Text.Wrap
+ font.family: "Fixedsys"
+ font.pixelSize: 20
+ text: "Foobar"
+ }
+}
+
+
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index 93276c1574..d09d2f7d0c 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -51,6 +51,8 @@ QT_REQUIRE_CONFIG(qml_interpreter);
#include <QtCore/QCoreApplication>
#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDateTime>
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
@@ -147,6 +149,7 @@ int main(int argc, char *argv[])
#endif
bool runAsQml = false;
+ bool cache = false;
if (!args.isEmpty()) {
if (args.constFirst() == QLatin1String("--jit")) {
@@ -166,6 +169,11 @@ int main(int argc, char *argv[])
args.removeFirst();
}
+ if (args.constFirst() == QLatin1String("--cache")) {
+ cache = true;
+ args.removeFirst();
+ }
+
if (args.constFirst() == QLatin1String("--help")) {
std::cerr << "Usage: qmljs [|--jit|--interpret|--qml] file..." << std::endl;
return EXIT_SUCCESS;
@@ -199,15 +207,38 @@ int main(int argc, char *argv[])
for (const QString &fn : qAsConst(args)) {
QFile file(fn);
if (file.open(QFile::ReadOnly)) {
- const QString code = QString::fromUtf8(file.readAll());
- file.close();
+ QScopedPointer<QV4::Script> script;
+ if (cache && QFile::exists(fn + QLatin1Char('c'))) {
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = iSelFactory->createUnitForLoading();
+ QString error;
+ if (unit->loadFromDisk(QUrl::fromLocalFile(fn), iSelFactory, &error)) {
+ script.reset(new QV4::Script(&vm, nullptr, unit));
+ } else {
+ std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl;
+ }
+ }
+ if (!script) {
+ const QString code = QString::fromUtf8(file.readAll());
+ file.close();
+ script.reset(new QV4::Script(ctx, code, fn));
+ script->parseAsBinding = runAsQml;
+ script->parse();
+ }
QV4::ScopedValue result(scope);
- QV4::Script script(ctx, code, fn);
- script.parseAsBinding = runAsQml;
- script.parse();
- if (!scope.engine->hasException)
- result = script.run();
+ if (!scope.engine->hasException) {
+ const auto unit = script->compilationUnit;
+ if (cache && unit && !(unit->data->flags & QV4::CompiledData::Unit::StaticData)) {
+ if (unit->data->sourceTimeStamp == 0) {
+ const_cast<QV4::CompiledData::Unit*>(unit->data)->sourceTimeStamp = QFileInfo(fn).lastModified().toMSecsSinceEpoch();
+ }
+ QString saveError;
+ if (!unit->saveToDisk(QUrl::fromLocalFile(fn), &saveError)) {
+ std::cout << "Error saving JS cache file: " << qPrintable(saveError) << std::endl;
+ }
+ }
+ result = script->run();
+ }
if (scope.engine->hasException) {
QV4::StackTrace trace;
QV4::ScopedValue ex(scope, scope.engine->catchException(&trace));