aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-12-12 10:35:21 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2018-01-04 14:41:16 +0100
commit2bee46e3f10e2c44d185d7a51a06830b68529676 (patch)
treeb65ac19203edfc2972b6020dd040e46c43b5d1fb /src
parent52f7ab28172cea3710a16775b7a512fce821fc77 (diff)
parent41293196b4db1aa7a0c616af312875c484639644 (diff)
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts: src/qml/memory/qv4mm.cpp src/qml/memory/qv4mmdefs_p.h src/quick/items/qquickwindow.cpp src/quick/items/qquickwindow_p.h tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp Change-Id: I7021fa1edf076627a67048f41f7b201220262b09
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp18
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp3
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h20
-rw-r--r--src/qml/memory/qv4mm.cpp39
-rw-r--r--src/qml/memory/qv4mm_p.h12
-rw-r--r--src/qml/memory/qv4mmdefs_p.h2
-rw-r--r--src/qml/qml/qqmldata_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp40
-rw-r--r--src/qml/qml/qqmlimport.cpp31
-rw-r--r--src/qml/qml/qqmlimport_p.h1
-rw-r--r--src/qml/qml/qqmlmetatype.cpp21
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp85
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp48
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp39
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h4
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h5
-rw-r--r--src/qml/types/qqmlinstantiator.cpp4
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp7
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h8
-rw-r--r--src/qmltest/qmltest.pro6
-rw-r--r--src/quick/items/qquickgridview.cpp10
-rw-r--r--src/quick/items/qquickitem.cpp14
-rw-r--r--src/quick/items/qquickitemsmodule.cpp3
-rw-r--r--src/quick/items/qquickitemview.cpp20
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--src/quick/items/qquicklistview.cpp10
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp37
-rw-r--r--src/quick/items/qquickpathview.cpp2
-rw-r--r--src/quick/items/qquickrepeater.cpp17
-rw-r--r--src/quick/items/qquickwindow.cpp65
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp4
-rw-r--r--src/quick/util/qquickshortcut.cpp3
-rw-r--r--src/quickwidgets/qquickwidget.cpp17
37 files changed, 448 insertions, 162 deletions
diff --git a/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp
index 16056addbd..d3bd1ac956 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/qquickwindowinspector.cpp
@@ -169,13 +169,29 @@ bool QQuickWindowInspector::eventFilter(QObject *obj, QEvent *event)
return QObject::eventFilter(obj, event);
}
+static Qt::WindowFlags fixFlags(Qt::WindowFlags flags)
+{
+ // If only the type flag is given, some other window flags are automatically assumed. When we
+ // add a flag, we need to make those explicit.
+ switch (flags) {
+ case Qt::Window:
+ return flags | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
+ case Qt::Dialog:
+ case Qt::Tool:
+ return flags | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ default:
+ return flags;
+ }
+}
+
void QQuickWindowInspector::setShowAppOnTop(bool appOnTop)
{
if (!m_parentWindow)
return;
Qt::WindowFlags flags = m_parentWindow->flags();
- Qt::WindowFlags newFlags = appOnTop ? (flags | Qt::WindowStaysOnTopHint) :
+ Qt::WindowFlags newFlags = appOnTop ? (fixFlags(flags) | Qt::WindowStaysOnTopHint) :
(flags & ~Qt::WindowStaysOnTopHint);
if (newFlags != flags)
m_parentWindow->setFlags(newFlags);
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
index 82bf9b0433..75bde2c66b 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
@@ -3046,7 +3046,7 @@ void QSGD3D12EnginePrivate::useRenderTargetAsTexture(uint id)
}
tframeData.activeTextures[tframeData.activeTextureCount++] =
- TransientFrameData::ActiveTexture::ActiveTexture(TransientFrameData::ActiveTexture::TypeRenderTarget, id);
+ TransientFrameData::ActiveTexture(TransientFrameData::ActiveTexture::TypeRenderTarget, id);
}
QImage QSGD3D12EnginePrivate::executeAndWaitReadbackRenderTarget(uint id)
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index bedcb5b164..5fd200efc1 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -120,7 +120,8 @@ void Profiler::startProfiling(quint64 features)
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
- (qint64)m_engine->memoryManager->getAllocatedMem(),
+ (qint64)m_engine->memoryManager->getAllocatedMem() -
+ (qint64)m_engine->memoryManager->getLargeItemsMem(),
HeapPage};
m_memory_data.append(heap);
MemoryAllocationProperties small = {timestamp,
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 9de597ad0e..08b4ba6c76 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -230,16 +230,24 @@ public:
bool trackAlloc(size_t size, MemoryType type)
{
- MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
- m_memory_data.append(allocation);
- return true;
+ if (size) {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
+ m_memory_data.append(allocation);
+ return true;
+ } else {
+ return false;
+ }
}
bool trackDealloc(size_t size, MemoryType type)
{
- MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
- m_memory_data.append(allocation);
- return true;
+ if (size) {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
+ m_memory_data.append(allocation);
+ return true;
+ } else {
+ return false;
+ }
}
quint64 featuresEnabled;
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index de97918fb0..8821d3c921 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -348,7 +348,8 @@ static void increaseFreedCountForClass(const char *className)
(*freedObjectStatsGlobal())[className]++;
}
-bool Chunk::sweep(ClassDestroyStatsCallback classCountPtr)
+//bool Chunk::sweep(ClassDestroyStatsCallback classCountPtr)
+bool Chunk::sweep(ExecutionEngine *engine)
{
bool hasUsedSlots = false;
SDUMP() << "sweeping chunk" << this;
@@ -387,13 +388,16 @@ bool Chunk::sweep(ClassDestroyStatsCallback classCountPtr)
HeapItem *itemToFree = o + index;
Heap::Base *b = *itemToFree;
const VTable *v = b->vtable();
- if (Q_UNLIKELY(classCountPtr))
- classCountPtr(v->className);
+// if (Q_UNLIKELY(classCountPtr))
+// classCountPtr(v->className);
if (v->destroy) {
v->destroy(b);
b->_checkIsDestroyed();
}
}
+ Q_V4_PROFILE_DEALLOC(engine, qPopulationCount((objectBitmap[i] | extendsBitmap[i])
+ - (blackBitmap[i] | e)) * Chunk::SlotSize,
+ Profiling::SmallItem);
objectBitmap[i] = blackBitmap[i];
grayBitmap[i] = 0;
hasUsedSlots |= (blackBitmap[i] != 0);
@@ -408,7 +412,7 @@ bool Chunk::sweep(ClassDestroyStatsCallback classCountPtr)
return hasUsedSlots;
}
-void Chunk::freeAll()
+void Chunk::freeAll(ExecutionEngine *engine)
{
// DEBUG << "sweeping chunk" << this << (*freeList);
HeapItem *o = realBase();
@@ -439,6 +443,8 @@ void Chunk::freeAll()
b->_checkIsDestroyed();
}
}
+ Q_V4_PROFILE_DEALLOC(engine, (qPopulationCount(objectBitmap[i]|extendsBitmap[i])
+ - qPopulationCount(e)) * Chunk::SlotSize, Profiling::SmallItem);
objectBitmap[i] = 0;
grayBitmap[i] = 0;
extendsBitmap[i] = e;
@@ -681,6 +687,7 @@ HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) {
if (!forceAllocation)
return 0;
Chunk *newChunk = chunkAllocator->allocate();
+ Q_V4_PROFILE_ALLOC(engine, Chunk::DataSize, Profiling::HeapPage);
chunks.push_back(newChunk);
nextFree = newChunk->first();
nFree = Chunk::AvailableSlots;
@@ -691,11 +698,12 @@ HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) {
done:
m->setAllocatedSlots(slotsRequired);
+ Q_V4_PROFILE_ALLOC(engine, slotsRequired * Chunk::SlotSize, Profiling::SmallItem);
// DEBUG << " " << hex << m->chunk() << m->chunk()->objectBitmap[0] << m->chunk()->extendsBitmap[0] << (m - m->chunk()->realBase());
return m;
}
-void BlockAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
+void BlockAllocator::sweep()
{
nextFree = 0;
nFree = 0;
@@ -704,13 +712,14 @@ void BlockAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
// qDebug() << "BlockAlloc: sweep";
usedSlotsAfterLastSweep = 0;
- auto isFree = [this, classCountPtr] (Chunk *c) {
- bool isUsed = c->sweep(classCountPtr);
+ auto isFree = [this] (Chunk *c) {
+ bool isUsed = c->sweep(engine);
if (isUsed) {
c->sortIntoBins(freeBins, NumBins);
usedSlotsAfterLastSweep += c->nUsedSlots();
} else {
+ Q_V4_PROFILE_DEALLOC(engine, Chunk::DataSize, Profiling::HeapPage);
chunkAllocator->free(c);
}
return !isUsed;
@@ -723,7 +732,8 @@ void BlockAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
void BlockAllocator::freeAll()
{
for (auto c : chunks) {
- c->freeAll();
+ c->freeAll(engine);
+ Q_V4_PROFILE_DEALLOC(engine, Chunk::DataSize, Profiling::HeapPage);
chunkAllocator->free(c);
}
}
@@ -776,6 +786,7 @@ HeapItem *HugeItemAllocator::allocate(size_t size) {
Chunk *c = chunkAllocator->allocate(size);
chunks.push_back(HugeChunk{c, size});
Chunk::setBit(c->objectBitmap, c->first() - c->realBase());
+ Q_V4_PROFILE_ALLOC(engine, size, Profiling::LargeItem);
return c->first();
}
@@ -798,8 +809,11 @@ void HugeItemAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
{
auto isBlack = [this, classCountPtr] (const HugeChunk &c) {
bool b = c.chunk->first()->isBlack();
- if (!b)
+ Chunk::clearBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase());
+ if (!b) {
+ Q_V4_PROFILE_DEALLOC(engine, c.size, Profiling::LargeItem);
freeHugeChunk(chunkAllocator, c, classCountPtr);
+ }
return !b;
};
@@ -828,6 +842,7 @@ void HugeItemAllocator::collectGrayItems(MarkStack *markStack)
void HugeItemAllocator::freeAll()
{
for (auto &c : chunks) {
+ Q_V4_PROFILE_DEALLOC(engine, c.size, Profiling::LargeItem);
freeHugeChunk(chunkAllocator, c, nullptr);
}
}
@@ -837,8 +852,8 @@ MemoryManager::MemoryManager(ExecutionEngine *engine)
: engine(engine)
, chunkAllocator(new ChunkAllocator)
, stackAllocator(chunkAllocator)
- , blockAllocator(chunkAllocator)
- , hugeItemAllocator(chunkAllocator)
+ , blockAllocator(chunkAllocator, engine)
+ , hugeItemAllocator(chunkAllocator, engine)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
, unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
@@ -1096,7 +1111,7 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt
}
}
- blockAllocator.sweep(classCountPtr);
+ blockAllocator.sweep();
hugeItemAllocator.sweep(classCountPtr);
}
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 17957d0cd6..e16a0ca544 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -118,8 +118,8 @@ struct StackAllocator {
};
struct BlockAllocator {
- BlockAllocator(ChunkAllocator *chunkAllocator)
- : chunkAllocator(chunkAllocator)
+ BlockAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine)
+ : chunkAllocator(chunkAllocator), engine(engine)
{
memset(freeBins, 0, sizeof(freeBins));
#if MM_DEBUG
@@ -153,7 +153,7 @@ struct BlockAllocator {
return used;
}
- void sweep(ClassDestroyStatsCallback classCountPtr);
+ void sweep();
void freeAll();
void resetBlackBits();
void collectGrayItems(MarkStack *markStack);
@@ -164,6 +164,7 @@ struct BlockAllocator {
size_t usedSlotsAfterLastSweep = 0;
HeapItem *freeBins[NumBins];
ChunkAllocator *chunkAllocator;
+ ExecutionEngine *engine;
std::vector<Chunk *> chunks;
#if MM_DEBUG
uint allocations[NumBins];
@@ -171,8 +172,8 @@ struct BlockAllocator {
};
struct HugeItemAllocator {
- HugeItemAllocator(ChunkAllocator *chunkAllocator)
- : chunkAllocator(chunkAllocator)
+ HugeItemAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine)
+ : chunkAllocator(chunkAllocator), engine(engine)
{}
HeapItem *allocate(size_t size);
@@ -189,6 +190,7 @@ struct HugeItemAllocator {
}
ChunkAllocator *chunkAllocator;
+ ExecutionEngine *engine;
struct HugeChunk {
Chunk *chunk;
size_t size;
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
index 328797fb5e..df69f928ef 100644
--- a/src/qml/memory/qv4mmdefs_p.h
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -190,6 +190,8 @@ struct Chunk {
void freeAll();
void resetBlackBits();
void collectGrayItems(QV4::MarkStack *markStack);
+ bool sweep(ExecutionEngine *engine);
+ void freeAll(ExecutionEngine *engine);
void sortIntoBins(HeapItem **bins, uint nBins);
};
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index d692feb975..63994a392d 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -76,6 +76,7 @@ class QQmlNotifierEndpoint;
namespace QV4 {
namespace CompiledData {
struct CompilationUnit;
+struct Binding;
}
}
@@ -216,12 +217,14 @@ public:
struct DeferredData {
unsigned int deferredIdx;
+ QMultiHash<int, const QV4::CompiledData::Binding *> bindings;
QV4::CompiledData::CompilationUnit *compilationUnit;//Not always the same as the other compilation unit
QQmlContextData *context;//Could be either context or outerContext
};
QV4::CompiledData::CompilationUnit *compilationUnit;
QVector<DeferredData *> deferredData;
+ void deferData(int objectIndex, QV4::CompiledData::CompilationUnit *, QQmlContextData *);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index f60f148495..20f9b6439d 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -720,8 +720,11 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
{
if (QQmlData *d = QQmlData::get(o)) {
if (d->ownContext) {
- for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext)
+ for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext) {
lc->invalidate();
+ if (lc->contextObject == o)
+ lc->contextObject = nullptr;
+ }
d->ownContext->invalidate();
if (d->ownContext->contextObject == o)
d->ownContext->contextObject = nullptr;
@@ -1672,13 +1675,40 @@ void QQmlData::NotifyList::layout()
todo = 0;
}
+void QQmlData::deferData(int objectIndex, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *context)
+{
+ QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
+ deferData->deferredIdx = objectIndex;
+ deferData->compilationUnit = compilationUnit;
+ deferData->compilationUnit->addref();
+ deferData->context = context;
+
+ const QV4::CompiledData::Object *compiledObject = compilationUnit->objectAt(objectIndex);
+ const QV4::CompiledData::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(objectIndex);
+
+ const QV4::CompiledData::Binding *binding = compiledObject->bindingTable();
+ for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) {
+ const QQmlPropertyData *property = propertyData.at(i);
+ if (property && binding->flags & QV4::CompiledData::Binding::IsDeferredBinding)
+ deferData->bindings.insert(property->coreIndex(), binding);
+ }
+
+ deferredData.append(deferData);
+}
+
void QQmlData::releaseDeferredData()
{
- for (DeferredData *deferData : qAsConst(deferredData)) {
- deferData->compilationUnit->release();
- delete deferData;
+ auto it = deferredData.begin();
+ while (it != deferredData.end()) {
+ DeferredData *deferData = *it;
+ if (deferData->bindings.isEmpty()) {
+ deferData->compilationUnit->release();
+ delete deferData;
+ it = deferredData.erase(it);
+ } else {
+ ++it;
+ }
}
- deferredData.clear();
}
void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index a7cafa1a93..8b0bd9d6ec 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1276,11 +1276,20 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ
QQmlTypeLoader &typeLoader = QQmlEnginePrivate::get(database->engine)->typeLoader;
- QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local);
+ // Interceptor might redirect remote files to local ones.
+ QQmlAbstractUrlInterceptor *interceptor = typeLoader.engine()->urlInterceptor();
+ QStringList localImportPaths = database->importPathList(
+ interceptor ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local);
// Search local import paths for a matching version
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin);
- for (const QString &qmldirPath : qmlDirPaths) {
+ for (QString qmldirPath : qmlDirPaths) {
+ if (interceptor) {
+ qmldirPath = QQmlFile::urlToLocalFileOrQrc(
+ interceptor->intercept(QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile));
+ }
+
QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
if (!absoluteFilePath.isEmpty()) {
QString url;
@@ -1489,6 +1498,10 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash)
? String_qmldir
: Slash_qmldir));
+ if (QQmlAbstractUrlInterceptor *interceptor = typeLoader->engine()->urlInterceptor()) {
+ qmldirUrl = interceptor->intercept(QUrl(qmldirUrl),
+ QQmlAbstractUrlInterceptor::QmldirFile).toString();
+ }
QString qmldirIdentifier;
if (QQmlFile::isLocalFile(qmldirUrl)) {
@@ -1588,8 +1601,8 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString &
if (import->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) {
if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) {
- // The implicit import qmldir can be empty
- if (uri != QLatin1String(".")) {
+ // The implicit import qmldir can be empty, and plugins have no extra versions
+ if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, vmaj, vmin)) {
QQmlError error;
if (QQmlMetaType::isAnyModule(uri))
error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin));
@@ -1717,6 +1730,16 @@ bool QQmlImports::isLocal(const QUrl &url)
return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
}
+QUrl QQmlImports::urlFromLocalFileOrQrcOrUrl(const QString &file)
+{
+ QUrl url(QLatin1String(file.at(0) == Colon ? "qrc" : "") + file);
+
+ // We don't support single character schemes as those conflict with windows drive letters.
+ if (url.scheme().length() < 2)
+ return QUrl::fromLocalFile(file);
+ return url;
+}
+
void QQmlImports::setDesignerSupportRequired(bool b)
{
designerSupportRequired = b;
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index a7b65c1048..6298dd9c22 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -191,6 +191,7 @@ public:
static bool isLocal(const QString &url);
static bool isLocal(const QUrl &url);
+ static QUrl urlFromLocalFileOrQrcOrUrl(const QString &);
static void setDesignerSupportRequired(bool b);
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 0f388cf7b7..1e4855f422 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -2402,6 +2402,27 @@ QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVe
return data->propertyCache(type, minorVersion);
}
+void qmlUnregisterType(int typeIndex)
+{
+ QMutexLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+ {
+ const QQmlTypePrivate *d = data->types.value(typeIndex).priv();
+ if (d) {
+ removeQQmlTypePrivate(data->idToType, d);
+ removeQQmlTypePrivate(data->nameToType, d);
+ removeQQmlTypePrivate(data->urlToType, d);
+ removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+ removeQQmlTypePrivate(data->metaObjectToType, d);
+ for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
+ QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
+ modulePrivate->remove(d);
+ }
+ data->types[typeIndex] = QQmlType();
+ }
+ }
+}
+
void QQmlMetaType::freeUnusedTypesAndCaches()
{
QMutexLocker lock(metaTypeDataLock());
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 85ee4d7b97..f381b4a010 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -75,6 +75,8 @@ class QQmlCompiledData;
namespace QV4 { struct String; }
+void Q_QML_PRIVATE_EXPORT qmlUnregisterType(int type);
+
class Q_QML_PRIVATE_EXPORT QQmlMetaType
{
public:
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 11fc3ceb44..7761eb4677 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -233,6 +233,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
return instance;
}
+// ### unify or keep in sync with populateDeferredBinding()
bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData)
{
QQmlData *declarativeData = QQmlData::get(instance);
@@ -283,6 +284,80 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::
qSwap(_qmlContext, qmlContext);
qSwap(_scopeObject, scopeObject);
+ deferredData->bindings.clear();
+ phase = ObjectsCreated;
+
+ return errors.isEmpty();
+}
+
+// ### unify or keep in sync with populateDeferredProperties()
+bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding)
+{
+ Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding);
+
+ QObject *instance = qmlProperty.object();
+ QQmlData *declarativeData = QQmlData::get(instance);
+ context = deferredData->context;
+ sharedState->rootContext = context;
+
+ QObject *bindingTarget = instance;
+
+ QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
+ QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
+
+ QObject *scopeObject = instance;
+ qSwap(_scopeObject, scopeObject);
+
+ QV4::Scope valueScope(v4);
+
+ Q_ASSERT(topLevelCreator);
+ if (!sharedState->allJavaScriptObjects)
+ sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
+
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+
+ qSwap(_qmlContext, qmlContext);
+
+ qSwap(_propertyCache, cache);
+ qSwap(_qobject, instance);
+
+ int objectIndex = deferredData->deferredIdx;
+ qSwap(_compiledObjectIndex, objectIndex);
+
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex);
+ qSwap(_compiledObject, obj);
+
+ qSwap(_ddata, declarativeData);
+ qSwap(_bindingTarget, bindingTarget);
+ qSwap(_vmeMetaObject, vmeMetaObject);
+
+ QQmlListProperty<void> savedList;
+ qSwap(_currentList, savedList);
+
+ const QQmlPropertyData &property = QQmlPropertyPrivate::get(qmlProperty)->core;
+
+ if (property.isQList()) {
+ void *argv[1] = { (void*)&_currentList };
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
+ } else if (_currentList.object) {
+ _currentList = QQmlListProperty<void>();
+ }
+
+ setPropertyBinding(&property, binding);
+
+ qSwap(_currentList, savedList);
+
+ qSwap(_vmeMetaObject, vmeMetaObject);
+ qSwap(_bindingTarget, bindingTarget);
+ qSwap(_ddata, declarativeData);
+ qSwap(_compiledObject, obj);
+ qSwap(_compiledObjectIndex, objectIndex);
+ qSwap(_qobject, instance);
+ qSwap(_propertyCache, cache);
+
+ qSwap(_qmlContext, qmlContext);
+ qSwap(_scopeObject, scopeObject);
+
phase = ObjectsCreated;
return errors.isEmpty();
@@ -1342,14 +1417,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);
- if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) {
- QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
- deferData->deferredIdx = _compiledObjectIndex;
- deferData->compilationUnit = compilationUnit;
- deferData->compilationUnit->addref();
- deferData->context = context;
- _ddata->deferredData.append(deferData);
- }
+ if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings)
+ _ddata->deferData(_compiledObjectIndex, compilationUnit, context);
if (_compiledObject->nFunctions > 0)
setupFunctions();
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index aa0165ec06..593d89e5d5 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -81,7 +81,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
QRecursionNode recursionNode;
};
-class QQmlObjectCreator
+class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
@@ -90,6 +90,7 @@ public:
QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0);
bool populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData);
+ bool populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding);
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
void cancel(QObject *object);
void clear();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 128e37d51b..a4db62eebf 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1436,8 +1436,13 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
// We haven't yet resolved this import
m_unresolvedImports.insert(import, 0);
- // Query any network import paths for this library
- QStringList remotePathList = importDatabase->importPathList(QQmlImportDatabase::Remote);
+ QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor();
+
+ // Query any network import paths for this library.
+ // Interceptor might redirect local paths.
+ QStringList remotePathList = importDatabase->importPathList(
+ interceptor ? QQmlImportDatabase::LocalOrRemote
+ : QQmlImportDatabase::Remote);
if (!remotePathList.isEmpty()) {
// Add this library and request the possible locations for it
if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
@@ -1448,8 +1453,18 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
int priority = 0;
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion);
for (const QString &qmldirPath : qmlDirPaths) {
- if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors))
+ if (interceptor) {
+ QUrl url = interceptor->intercept(
+ QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile);
+ if (!QQmlFile::isLocalFile(url)
+ && !fetchQmldir(url, import, ++priority, errors)) {
+ return false;
+ }
+ } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) {
return false;
+ }
+
}
}
}
@@ -1872,19 +1887,22 @@ It can also be a remote path for a remote directory import, but it will have bee
*/
const QQmlTypeLoaderQmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn)
{
- QUrl url(filePathIn); //May already contain http scheme
- if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"))
- return *(m_importQmlDirCache.value(filePathIn)); //Can't load the remote here, but should be cached
- else
- url = QUrl::fromLocalFile(filePathIn);
- if (engine() && engine()->urlInterceptor())
- url = engine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::QmldirFile);
- Q_ASSERT(url.scheme() == QLatin1String("file"));
QString filePath;
- if (url.scheme() == QLatin1String("file"))
- filePath = url.toLocalFile();
- else
- filePath = url.path();
+
+ // Try to guess if filePathIn is already a URL. This is necessarily fragile, because
+ // - paths can contain ':', which might make them appear as URLs with schemes.
+ // - windows drive letters appear as schemes (thus "< 2" below).
+ // - a "file:" URL is equivalent to the respective file, but will be treated differently.
+ // Yet, this heuristic is the best we can do until we pass more structured information here,
+ // for example a QUrl also for local files.
+ QUrl url(filePathIn);
+ if (url.scheme().length() < 2) {
+ filePath = filePathIn;
+ } else {
+ filePath = QQmlFile::urlToLocalFileOrQrc(url);
+ if (filePath.isEmpty()) // Can't load the remote here, but should be cached
+ return *(m_importQmlDirCache.value(filePathIn));
+ }
QQmlTypeLoaderQmldirContent *qmldir;
QQmlTypeLoaderQmldirContent **val = m_importQmlDirCache.value(filePath);
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 4ee1ab1b76..dc41a16e3b 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -931,7 +931,7 @@ void QQmlDelegateModelPrivate::setInitialState(QQDMIncubationTask *incubationTas
emitInitItem(incubationTask, cacheItem->object);
}
-QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bool asynchronous)
+QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
{
if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
qWarning() << "DelegateModel::item: index out range" << index << m_compositor.count(group);
@@ -962,7 +962,8 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
cacheItem->referenceObject();
if (cacheItem->incubationTask) {
- if (!asynchronous && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
+ bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
+ if (sync && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
// previously requested async - now needed immediately
cacheItem->incubationTask->forceCompletion();
}
@@ -971,7 +972,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
cacheItem->scriptRef += 1;
- cacheItem->incubationTask = new QQDMIncubationTask(this, asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
+ cacheItem->incubationTask = new QQDMIncubationTask(this, incubationMode);
cacheItem->incubationTask->incubating = cacheItem;
cacheItem->incubationTask->clear();
@@ -1026,7 +1027,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
to ensure a reference is held. Any call to item() which returns a valid item
must be matched by a call to release() in order to destroy the item.
*/
-QObject *QQmlDelegateModel::object(int index, bool asynchronous)
+QObject *QQmlDelegateModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
{
Q_D(QQmlDelegateModel);
if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
@@ -1034,11 +1035,17 @@ QObject *QQmlDelegateModel::object(int index, bool asynchronous)
return 0;
}
- QObject *object = d->object(d->m_compositorGroup, index, asynchronous);
- if (!object)
- return 0;
+ return d->object(d->m_compositorGroup, index, incubationMode);
+}
+
+QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index)
+{
+ Q_D(QQmlDelegateModel);
+ Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
+ if (!it->inCache())
+ return QQmlIncubator::Null;
- return object;
+ return d->m_cache.at(it.cacheIndex)->incubationTask->status();
}
QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index, const QString &name)
@@ -2637,7 +2644,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
return;
}
- QObject *object = model->object(group, index, false);
+ QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
if (object) {
QVector<Compositor::Insert> inserts;
Compositor::iterator it = model->m_compositor.find(group, index);
@@ -3125,7 +3132,7 @@ bool QQmlPartsModel::isValid() const
return m_model->isValid();
}
-QObject *QQmlPartsModel::object(int index, bool asynchronous)
+QObject *QQmlPartsModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
{
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
@@ -3134,7 +3141,7 @@ QObject *QQmlPartsModel::object(int index, bool asynchronous)
return 0;
}
- QObject *object = model->object(m_compositorGroup, index, asynchronous);
+ QObject *object = model->object(m_compositorGroup, index, incubationMode);
if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
QObject *part = package->part(m_part);
@@ -3184,6 +3191,16 @@ void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
m_watchedRoles = roles;
}
+QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index)
+{
+ QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
+ Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
+ if (!it->inCache())
+ return QQmlIncubator::Null;
+
+ return model->m_cache.at(it.cacheIndex)->incubationTask->status();
+}
+
int QQmlPartsModel::indexOf(QObject *item, QObject *) const
{
QHash<QObject *, QQuickPackage *>::const_iterator it = m_packaged.find(item);
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index 186144d107..71179fd8be 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -54,6 +54,7 @@
#include <private/qtqmlglobal_p.h>
#include <private/qqmllistcompositor_p.h>
#include <private/qqmlobjectmodel_p.h>
+#include <private/qqmlincubator_p.h>
#include <QtCore/qabstractitemmodel.h>
#include <QtCore/qstringlist.h>
@@ -109,11 +110,12 @@ public:
int count() const override;
bool isValid() const override { return delegate() != 0; }
- QObject *object(int index, bool asynchronous = false) override;
+ QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
ReleaseFlags release(QObject *object) override;
void cancel(int index) override;
QString stringValue(int index, const QString &role) override;
void setWatchedRoles(const QList<QByteArray> &roles) override;
+ QQmlIncubator::Status incubationStatus(int index) override;
int indexOf(QObject *object, QObject *objectContext) const override;
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 3759fe8667..6d061cdce4 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -256,7 +256,7 @@ public:
void connectModel(QQmlAdaptorModel *model);
void requestMoreIfNecessary();
- QObject *object(Compositor::Group group, int index, bool asynchronous);
+ QObject *object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode);
QQmlDelegateModel::ReleaseFlags release(QObject *object);
QString stringValue(Compositor::Group group, int index, const QString &name);
void emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
@@ -352,11 +352,12 @@ public:
int count() const override;
bool isValid() const override;
- QObject *object(int index, bool asynchronous = false) override;
+ QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
ReleaseFlags release(QObject *item) override;
QString stringValue(int index, const QString &role) override;
QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
void setWatchedRoles(const QList<QByteArray> &roles) override;
+ QQmlIncubator::Status incubationStatus(int index) override;
int indexOf(QObject *item, QObject *objectContext) const override;
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp
index 2de5875deb..6e2b66aea7 100644
--- a/src/qml/types/qqmlinstantiator.cpp
+++ b/src/qml/types/qqmlinstantiator.cpp
@@ -85,7 +85,7 @@ void QQmlInstantiatorPrivate::clear()
QObject *QQmlInstantiatorPrivate::modelObject(int index, bool async)
{
requestedIndex = index;
- QObject *o = instanceModel->object(index, async);
+ QObject *o = instanceModel->object(index, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
requestedIndex = -1;
return o;
}
@@ -123,7 +123,7 @@ void QQmlInstantiatorPrivate::_q_createdItem(int idx, QObject* item)
if (objects.contains(item)) //Case when it was created synchronously in regenerate
return;
if (requestedIndex != idx) // Asynchronous creation, reference the object
- (void)instanceModel->object(idx, false);
+ (void)instanceModel->object(idx);
item->setParent(q);
if (objects.size() < idx + 1) {
int modelCount = instanceModel->count();
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index dcd0360199..54da0867d4 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -267,7 +267,7 @@ bool QQmlObjectModel::isValid() const
return true;
}
-QObject *QQmlObjectModel::object(int index, bool)
+QObject *QQmlObjectModel::object(int index, QQmlIncubator::IncubationMode)
{
Q_D(QQmlObjectModel);
QQmlObjectModelPrivate::Item &item = d->children[index];
@@ -298,6 +298,11 @@ QString QQmlObjectModel::stringValue(int index, const QString &name)
return QQmlEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
}
+QQmlIncubator::Status QQmlObjectModel::incubationStatus(int)
+{
+ return QQmlIncubator::Ready;
+}
+
int QQmlObjectModel::indexOf(QObject *item, QObject *) const
{
Q_D(const QQmlObjectModel);
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
index fc4c03874f..c98fe13a6b 100644
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ b/src/qml/types/qqmlobjectmodel_p.h
@@ -52,6 +52,7 @@
//
#include <private/qtqmlglobal_p.h>
+#include <private/qqmlincubator_p.h>
#include <QtQml/qqml.h>
#include <QtCore/qobject.h>
@@ -74,11 +75,13 @@ public:
virtual int count() const = 0;
virtual bool isValid() const = 0;
- virtual QObject *object(int index, bool asynchronous=false) = 0;
+ QObject *object(int index, bool async) { return object(index, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested); }
+ virtual QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) = 0;
virtual ReleaseFlags release(QObject *object) = 0;
virtual void cancel(int) {}
virtual QString stringValue(int, const QString &) = 0;
virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
+ virtual QQmlIncubator::Status incubationStatus(int index) = 0;
virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
@@ -113,10 +116,11 @@ public:
int count() const override;
bool isValid() const override;
- QObject *object(int index, bool asynchronous = false) override;
+ QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
ReleaseFlags release(QObject *object) override;
QString stringValue(int index, const QString &role) override;
void setWatchedRoles(const QList<QByteArray> &) override {}
+ QQmlIncubator::Status incubationStatus(int index) override;
int indexOf(QObject *object, QObject *objectContext) const override;
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index d13e162ff4..c36cdb5b87 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -13,12 +13,6 @@ qtHaveModule(widgets) {
DEFINES += QT_QMLTEST_WITH_WIDGETS
}
-# Install qmltestcase.prf into the Qt mkspecs so that "CONFIG += qmltestcase"
-# can be used in customer applications to build against QtQuickTest.
-feature.path = $$[QT_INSTALL_DATA]/mkspecs/features
-feature.files = $$PWD/features/qmltestcase.prf
-INSTALLS += feature
-
SOURCES += \
$$PWD/quicktest.cpp \
$$PWD/quicktestevent.cpp \
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index c570b95a21..c56cfd3005 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -511,9 +511,11 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
FxGridItemSG *item = 0;
bool changed = false;
+ QQmlIncubator::IncubationMode incubationMode = doBuffer ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested;
+
while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << colPos << rowPos;
- if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, doBuffer))))
+ if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, incubationMode))))
break;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
item->setPosition(colPos, rowPos, true);
@@ -548,7 +550,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
colPos = colNum * colSize();
while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
- if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, doBuffer))))
+ if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, incubationMode))))
break;
--visibleIndex;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
@@ -2415,7 +2417,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
item->index = modelIndex + i;
if (!item)
- item = createItem(modelIndex + i);
+ item = createItem(modelIndex + i, QQmlIncubator::Synchronous);
if (!item)
return false;
@@ -2468,7 +2470,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
item->index = modelIndex + i;
bool newItem = !item;
if (!item)
- item = createItem(modelIndex + i);
+ item = createItem(modelIndex + i, QQmlIncubator::Synchronous);
if (!item)
return false;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 54fcbfbbf2..6b123d1dfe 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -7409,10 +7409,18 @@ void QQuickItem::unsetCursor()
void QQuickItem::grabMouse()
{
Q_D(QQuickItem);
- if (!d->window)
+ if (!d->window || d->window->mouseGrabberItem() == this)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- windowPriv->setMouseGrabber(this);
+ bool fromTouch = windowPriv->isDeliveringTouchAsMouse();
+ auto point = fromTouch ?
+ windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) :
+ windowPriv->pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0);
+ if (point) {
+ QQuickItem *oldGrabber = point->grabberItem();
+ point->setGrabberItem(this);
+ windowPriv->sendUngrabEvent(oldGrabber, fromTouch);
+ }
}
/*!
@@ -7430,7 +7438,7 @@ void QQuickItem::ungrabMouse()
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- windowPriv->removeGrabber(this, true, false);
+ windowPriv->removeGrabber(this, true, windowPriv->isDeliveringTouchAsMouse());
}
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 1406e5b547..fcf6e49135 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -287,7 +287,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickMultiPointTouchArea>("QtQuick", 2, 0, "MultiPointTouchArea");
qmlRegisterType<QQuickTouchPoint>("QtQuick", 2, 0, "TouchPoint");
- qmlRegisterType<QQuickGrabGestureEvent>();
+ qmlRegisterUncreatableType<QQuickGrabGestureEvent>(uri,major,minor, "GestureEvent",
+ QQuickMouseEvent::tr("GestureEvent is only available in the context of handling the gestureStarted signal from MultiPointTouchArea"));
#if QT_CONFIG(accessibility)
qmlRegisterUncreatableType<QQuickAccessibleAttached>("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties"));
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index c203f389ae..10f6c63170 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1729,7 +1729,7 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
FxViewItem *oldCurrentItem = currentItem;
int oldCurrentIndex = currentIndex;
currentIndex = modelIndex;
- currentItem = createItem(modelIndex, false);
+ currentItem = createItem(modelIndex, QQmlIncubator::AsynchronousIfNested);
if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
@@ -2325,11 +2325,11 @@ void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitiona
When the item becomes available, refill() will be called and the item
will be returned on the next call to createItem().
*/
-FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
+FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, QQmlIncubator::IncubationMode incubationMode)
{
Q_Q(QQuickItemView);
- if (requestedIndex == modelIndex && asynchronous)
+ if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
return 0;
for (int i=0; i<releasePendingTransition.count(); i++) {
@@ -2340,14 +2340,20 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
}
}
- if (asynchronous)
- requestedIndex = modelIndex;
inRequest = true;
- QObject* object = model->object(modelIndex, asynchronous);
+ QObject* object = model->object(modelIndex, incubationMode);
QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
+
if (!item) {
- if (object) {
+ if (!object) {
+ if (requestedIndex == -1 && model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
+ // The reason we didn't receive an item is because it's incubating async. We keep track
+ // of this by assigning the index we're waiting for to 'requestedIndex'. This will e.g. let
+ // the view avoid unnecessary layout calls until the item has been loaded.
+ requestedIndex = modelIndex;
+ }
+ } else {
model->release(object);
if (!delegateValidated) {
delegateValidated = true;
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index 2c04022cde..622ebb430f 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -206,7 +206,7 @@ public:
void refill(qreal from, qreal to);
void mirrorChange() override;
- FxViewItem *createItem(int modelIndex, bool asynchronous = false);
+ FxViewItem *createItem(int modelIndex,QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested);
virtual bool releaseItem(FxViewItem *item);
QQuickItem *createHighlightItem() const;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index a6236d9801..11eaf393ea 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -669,11 +669,13 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
}
}
+ QQmlIncubator::IncubationMode incubationMode = doBuffer ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested;
+
bool changed = false;
FxListItemSG *item = 0;
qreal pos = itemEnd;
while (modelIndex < model->count() && pos <= fillTo) {
- if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
+ if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, incubationMode))))
break;
qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
@@ -690,7 +692,7 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
return changed;
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
- if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
+ if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, incubationMode))))
break;
qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
--visibleIndex;
@@ -3271,7 +3273,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
item->index = modelIndex + i;
if (!item)
- item = createItem(modelIndex + i);
+ item = createItem(modelIndex + i, QQmlIncubator::Synchronous);
if (!item)
return false;
@@ -3313,7 +3315,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
item->index = modelIndex + i;
bool newItem = !item;
if (!item)
- item = createItem(modelIndex + i);
+ item = createItem(modelIndex + i, QQmlIncubator::Synchronous);
if (!item)
return false;
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 54136b1bbf..4f62d021a4 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -285,6 +285,43 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
emit uniqueIdChanged();
}
+
+/*!
+ \qmltype GestureEvent
+ \instantiates QQuickGrabGestureEvent
+ \inqmlmodule QtQuick
+ \ingroup qtquick-input-events
+ \brief The parameter given with the gestureStarted signal
+
+ The GestureEvent object has the current touch points, which you may choose
+ to interpret as a gesture, and an invokable method to grab the involved
+ points exclusively.
+*/
+
+/*!
+ \qmlproperty real QtQuick::GestureEvent::dragThreshold
+
+ This property holds the system setting for the distance a finger must move
+ before it is interpreted as a drag. It comes from
+ QStyleHints::startDragDistance().
+*/
+
+/*!
+ \qmlproperty list<TouchPoint> QtQuick::GestureEvent::touchPoints
+
+ This property holds the set of current touch points.
+*/
+
+/*!
+ \qmlmethod QtQuick::GestureEvent::grab()
+
+ Acquires an exclusive grab of the mouse and all the \l touchPoints, and
+ calls \l {QQuickItem::setKeepTouchGrab()}{setKeepTouchGrab()} and
+ \l {QQuickItem::setKeepMouseGrab()}{setKeepMouseGrab()} so that any
+ parent Item that \l {QQuickItem::filtersChildMouseEvents()}{filters} its
+ children's events will not be allowed to take over the grabs.
+*/
+
/*!
\qmltype MultiPointTouchArea
\instantiates QQuickMultiPointTouchArea
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index aac2b0296a..b9fea974ce 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -129,7 +129,7 @@ QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool async)
requestedIndex = modelIndex;
requestedZ = z;
inRequest = true;
- QObject *object = model->object(modelIndex, async);
+ QObject *object = model->object(modelIndex, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (!item) {
if (object) {
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 6fc4c0553a..658a7de3d4 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -401,7 +401,7 @@ void QQuickRepeater::regenerate()
void QQuickRepeaterPrivate::requestItems()
{
for (int i = 0; i < itemCount; i++) {
- QObject *object = model->object(i, false);
+ QObject *object = model->object(i, QQmlIncubator::AsynchronousIfNested);
if (object)
model->release(object);
}
@@ -410,7 +410,7 @@ void QQuickRepeaterPrivate::requestItems()
void QQuickRepeater::createdItem(int index, QObject *)
{
Q_D(QQuickRepeater);
- QObject *object = d->model->object(index, false);
+ QObject *object = d->model->object(index, QQmlIncubator::AsynchronousIfNested);
QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
emit itemAdded(index, item);
}
@@ -495,13 +495,20 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
QQuickItem *stackBefore = index + items.count() < d->deletables.count()
? d->deletables.at(index + items.count())
: this;
- for (int i = index; i < index + items.count(); ++i)
- d->deletables.at(i)->stackBefore(stackBefore);
+ if (stackBefore) {
+ for (int i = index; i < index + items.count(); ++i) {
+ if (i < d->deletables.count()) {
+ QPointer<QQuickItem> item = d->deletables.at(i);
+ if (item)
+ item->stackBefore(stackBefore);
+ }
+ }
+ }
} else for (int i = 0; i < insert.count; ++i) {
int modelIndex = index + i;
++d->itemCount;
d->deletables.insert(modelIndex, 0);
- QObject *object = d->model->object(modelIndex, false);
+ QObject *object = d->model->object(modelIndex, QQmlIncubator::AsynchronousIfNested);
if (object)
d->model->release(object);
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 530d165850..a056575f41 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -747,44 +747,6 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
return false;
}
-void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
-{
- Q_Q(QQuickWindow);
- if (q->mouseGrabberItem() == grabber)
- return;
-
- QQuickItem *oldGrabber = q->mouseGrabberItem();
- qCDebug(DBG_MOUSE_TARGET) << "grabber" << oldGrabber << "->" << grabber;
-
- if (grabber && touchMouseId != -1 && touchMouseDevice) {
- // update the touch item for mouse touch id to the new grabber
- qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << touchMouseId << "->" << q->mouseGrabberItem();
- auto point = pointerEventInstance(touchMouseDevice)->pointById(touchMouseId);
- if (point) {
- auto originalEvent = pointerEventInstance(point->pointerEvent()->device());
- for (int i = 0; i < originalEvent->pointCount(); ++i) {
- QQuickEventPoint *pt = originalEvent->point(i);
- if (pt->exclusiveGrabber())
- pt->cancelExclusiveGrab();
- }
- point->setGrabberItem(grabber);
- }
- } else {
- QQuickPointerEvent *event = pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
- Q_ASSERT(event->pointCount() == 1);
- auto point = event->point(0);
- point->setGrabberItem(grabber);
- }
-
-
- if (oldGrabber) {
- QEvent e(QEvent::UngrabMouse);
- hasFiltered.clear();
- if (!sendFilteredMouseEvent(&e, oldGrabber, oldGrabber->parentItem()))
- oldGrabber->mouseUngrabEvent();
- }
-}
-
void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids)
{
for (int i = 0; i < ids.count(); ++i) {
@@ -832,8 +794,14 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
{
Q_Q(QQuickWindow);
if (Q_LIKELY(mouse) && q->mouseGrabberItem() == grabber) {
- qCDebug(DBG_MOUSE_TARGET) << "removeGrabber" << q->mouseGrabberItem() << "-> null";
- setMouseGrabber(nullptr);
+ bool fromTouch = isDeliveringTouchAsMouse();
+ auto point = fromTouch ?
+ pointerEventInstance(touchMouseDevice)->pointById(touchMouseId) :
+ pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0);
+ QQuickItem *oldGrabber = point->grabberItem();
+ qCDebug(DBG_MOUSE_TARGET) << "removeGrabber" << oldGrabber << "-> null";
+ point->setGrabberItem(nullptr);
+ sendUngrabEvent(oldGrabber, fromTouch);
}
if (Q_LIKELY(touch)) {
bool ungrab = false;
@@ -853,6 +821,19 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
}
}
+void QQuickWindowPrivate::sendUngrabEvent(QQuickItem *grabber, bool touch)
+{
+ if (!grabber)
+ return;
+ QEvent e(QEvent::UngrabMouse);
+ hasFiltered.clear();
+ if (!sendFilteredMouseEvent(&e, grabber, grabber->parentItem())) {
+ grabber->mouseUngrabEvent();
+ if (touch)
+ grabber->touchUngrabEvent();
+ }
+}
+
/*!
Translates the data in \a touchEvent to this window. This method leaves the item local positions in
\a touchEvent untouched (these are filled in later).
@@ -1511,7 +1492,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
{
Q_D(const QQuickWindow);
- if (d->touchMouseId != -1 && d->touchMouseDevice) {
+ if (d->isDeliveringTouchAsMouse()) {
if (QQuickPointerEvent *event = d->queryPointerEventInstance(d->touchMouseDevice)) {
auto point = event->pointById(d->touchMouseId);
return point ? point->grabberItem() : nullptr;
@@ -1736,7 +1717,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
// release event: ungrab if no buttons are pressed anymore
if (mouseIsReleased)
- setMouseGrabber(nullptr);
+ removeGrabber(grabber, true, isDeliveringTouchAsMouse());
} else {
// if the grabber is not an Item, it must be a PointerHandler
auto handler = point->grabberPointerHandler();
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index b17fdf7a49..b2a6c2c2ac 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -141,10 +141,11 @@ public:
// Mouse positions are saved in widget coordinates
QPointF lastMousePosition;
bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
+ bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
void translateTouchEvent(QTouchEvent *touchEvent);
- void setMouseGrabber(QQuickItem *grabber);
void grabTouchPoints(QObject *grabber, const QVector<int> &ids);
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
+ void sendUngrabEvent(QQuickItem *grabber, bool touch);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
void deliverToPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &passiveGrabbers, QQuickPointerEvent *pointerEvent);
void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
index 666f1d0616..fabecfcbb8 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
@@ -83,7 +83,7 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGTransformNode *)
bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node)
{
// Make sure to translate the clip rect into world coordinates
- if (m_clipState.count() == 0 || m_clipState.top().isNull()) {
+ if (m_clipState.count() == 0 || (m_clipState.count() == 1 && m_clipState.top().isNull())) {
m_clipState.push(m_transformState.top().map(QRegion(node->clipRect().toRect())));
m_hasClip = true;
} else {
@@ -97,7 +97,7 @@ bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node)
void QSGSoftwareRenderableNodeUpdater::endVisit(QSGClipNode *)
{
m_clipState.pop();
- if (m_clipState.count() == 0 || m_clipState.top().isNull())
+ if (m_clipState.count() == 0 || (m_clipState.count() == 1 && m_clipState.top().isNull()))
m_hasClip = false;
}
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 2fe4962b1a..58f7fc8439 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -41,6 +41,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickrendercontrol.h>
#include <QtQuick/private/qtquickglobal_p.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -102,6 +103,8 @@ static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext conte
if (QQuickItem *item = qobject_cast<QQuickItem *>(obj))
obj = item->window();
}
+ if (QWindow *renderWindow = QQuickRenderControl::renderWindowFor(qobject_cast<QQuickWindow *>(obj)))
+ obj = renderWindow;
return obj && obj == QGuiApplication::focusWindow();
default:
return false;
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index bdf9401997..a64fabcfc2 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -1251,7 +1251,8 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
// event's localPos and windowPos, and screenPos into the event's screenPos. This way
// the windowPos in e is ignored and is replaced by localPos. This is necessary
// because QQuickWindow thinks of itself as a top-level window always.
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
}
@@ -1265,12 +1266,12 @@ void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
// As the second mouse press is suppressed in widget windows we emulate it here for QML.
// See QTBUG-25831
- QMouseEvent pressEvent(QEvent::MouseButtonPress, e->localPos(), e->screenPos(), e->button(),
- e->buttons(), e->modifiers());
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, e->localPos(), e->windowPos(), e->screenPos(),
+ e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &pressEvent);
e->setAccepted(pressEvent.isAccepted());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(),
- e->modifiers());
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
}
@@ -1330,7 +1331,8 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, e->button(),
e->buttons());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
}
@@ -1342,7 +1344,8 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, e->button(),
e->buttons());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
}