aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/wtf/PageBlock.cpp2
-rw-r--r--src/3rdparty/masm/wtf/PageBlock.h5
-rw-r--r--src/particles/CMakeLists.txt1
-rw-r--r--src/particles/qquickparticleaffector_p.h3
-rw-r--r--src/particles/qquickparticleflatset_p.h156
-rw-r--r--src/particles/qquickparticlesystem.cpp2
-rw-r--r--src/particles/qquickparticlesystem_p.h3
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp23
-rw-r--r--src/qml/doc/snippets/qml/imports/merged-named-imports.qml4
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc15
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc10
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/imports.qdoc35
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/signals.qdoc53
-rw-r--r--src/qml/jsapi/qjsengine.cpp11
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4generatorobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h4
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp2
-rw-r--r--src/qmldebug/qqmlprofilerevent_p.h1
-rw-r--r--src/qmlmodels/qqmllistaccessor.cpp1
-rw-r--r--src/quick/CMakeLists.txt111
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp2
-rw-r--r--src/quick/designer/qquickdesignersupportproperties.cpp35
-rw-r--r--src/quick/designer/qquickdesignersupportproperties_p.h7
-rw-r--r--src/quick/doc/images/containmentMask-circle.gifbin0 -> 9926 bytes
-rw-r--r--src/quick/doc/images/containmentMask-shape.gifbin0 -> 11261 bytes
-rw-r--r--src/quick/doc/qtquick.qdocconf2
-rw-r--r--src/quick/doc/snippets/pointerHandlers/hoverTapKeyButton.qml73
-rw-r--r--src/quick/doc/snippets/pointerHandlers/tapHandlerButton.qml80
-rw-r--r--src/quick/doc/snippets/qml/item/containmentMask-circle-js.qml71
-rw-r--r--src/quick/doc/snippets/qml/item/containmentMask-shape.qml80
-rw-r--r--src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc64
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc67
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp11
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp16
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp24
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp43
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp15
-rw-r--r--src/quick/handlers/qquickwheelhandler.cpp2
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp5
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp11
-rw-r--r--src/quick/items/qquickcolorgroup.cpp2
-rw-r--r--src/quick/items/qquickdroparea.cpp1
-rw-r--r--src/quick/items/qquickflickable.cpp14
-rw-r--r--src/quick/items/qquickimage.cpp6
-rw-r--r--src/quick/items/qquickimagebase.cpp8
-rw-r--r--src/quick/items/qquickitem.cpp87
-rw-r--r--src/quick/items/qquickrendercontrol.cpp20
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp8
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h1
-rw-r--r--src/quick/items/qquickstateoperations.cpp2
-rw-r--r--src/quick/items/qquicktableview.cpp78
-rw-r--r--src/quick/items/qquicktext.cpp2
-rw-r--r--src/quick/items/qquicktextcontrol.cpp6
-rw-r--r--src/quick/items/qquicktextedit.cpp8
-rw-r--r--src/quick/items/qquicktextinput.cpp20
-rw-r--r--src/quick/items/qquicktextinput_p.h2
-rw-r--r--src/quick/items/qquicktextinput_p_p.h2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp5
-rw-r--r--src/quick/items/qquickwindow.cpp27
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp7
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp82
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h4
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp9
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp7
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode.cpp12
-rw-r--r--src/quick/scenegraph/util/qsgplaintexture.cpp7
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp49
-rw-r--r--src/quick/util/qquickdeliveryagent_p.h1
-rw-r--r--src/quick/util/qquickdeliveryagent_p_p.h1
-rw-r--r--src/quick/util/qquickstyledtext.cpp6
71 files changed, 1070 insertions, 471 deletions
diff --git a/src/3rdparty/masm/wtf/PageBlock.cpp b/src/3rdparty/masm/wtf/PageBlock.cpp
index e715ed262a..bc0e8d6f2d 100644
--- a/src/3rdparty/masm/wtf/PageBlock.cpp
+++ b/src/3rdparty/masm/wtf/PageBlock.cpp
@@ -64,6 +64,7 @@ inline size_t systemPageSize()
#endif
+inline namespace hidden {
size_t pageSize()
{
if (!s_pageSize)
@@ -78,5 +79,6 @@ size_t pageMask()
s_pageMask = ~(pageSize() - 1);
return s_pageMask;
}
+}
} // namespace WTF
diff --git a/src/3rdparty/masm/wtf/PageBlock.h b/src/3rdparty/masm/wtf/PageBlock.h
index 09e4048239..d85c39cb33 100644
--- a/src/3rdparty/masm/wtf/PageBlock.h
+++ b/src/3rdparty/masm/wtf/PageBlock.h
@@ -28,8 +28,13 @@
namespace WTF {
+// avoid false positive detection by apple
+// by putting the function inside an inline namespace
+// to obtain different name mangling
+inline namespace hidden {
WTF_EXPORT_PRIVATE size_t pageSize();
WTF_EXPORT_PRIVATE size_t pageMask();
+}
inline bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
diff --git a/src/particles/CMakeLists.txt b/src/particles/CMakeLists.txt
index 9ffa6564c2..e801d0b936 100644
--- a/src/particles/CMakeLists.txt
+++ b/src/particles/CMakeLists.txt
@@ -24,7 +24,6 @@ qt_internal_add_module(QuickParticles
qquickparticleaffector.cpp qquickparticleaffector_p.h
qquickparticleemitter.cpp qquickparticleemitter_p.h
qquickparticleextruder.cpp qquickparticleextruder_p.h
- qquickparticleflatset_p.h
qquickparticlegroup.cpp qquickparticlegroup_p.h
qquickparticlepainter.cpp qquickparticlepainter_p.h
qquickparticlesmodule.cpp qquickparticlesmodule_p.h
diff --git a/src/particles/qquickparticleaffector_p.h b/src/particles/qquickparticleaffector_p.h
index 4f60389e04..79446a23a1 100644
--- a/src/particles/qquickparticleaffector_p.h
+++ b/src/particles/qquickparticleaffector_p.h
@@ -55,7 +55,6 @@
#include "qquickparticlesystem_p.h"
#include "qquickparticleextruder_p.h"
#include "qtquickparticlesglobal_p.h"
-#include "qquickparticleflatset_p.h"
QT_BEGIN_NAMESPACE
@@ -197,7 +196,7 @@ protected:
static const qreal simulationCutoff;
QPointF m_offset;
- QtQuickParticlesPrivate::QFlatSet<QPair<int, int>> m_onceOffed;
+ QSet<QPair<int, int>> m_onceOffed;
private:
QSet<int> m_groupIds;
bool m_updateIntSet;
diff --git a/src/particles/qquickparticleflatset_p.h b/src/particles/qquickparticleflatset_p.h
deleted file mode 100644
index 6d0650a12b..0000000000
--- a/src/particles/qquickparticleflatset_p.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKPARTICLEFLATSET_P_H
-#define QQUICKPARTICLEFLATSET_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGlobal>
-
-#include <vector>
-#include <algorithm>
-#include <iterator>
-
-QT_BEGIN_NAMESPACE
-
-// Minimal API, just for the consumption of Qt Quick Particles.
-// For extra safety, it's in a private namespace
-
-namespace QtQuickParticlesPrivate {
-
-template <typename T>
-class QFlatSet
-{
-public:
- using iterator = typename std::vector<T>::iterator;
- using const_iterator = typename std::vector<T>::const_iterator;
- using value_type = typename std::vector<T>::value_type;
- using size_type = int;
-
- iterator find(const T &t)
- {
- return std::find(begin(), end(), t);
- }
-
- const_iterator find(const T &t) const
- {
- return std::find(begin(), end(), t);
- }
-
- bool contains(const T &t) const
- {
- return find(t) != end();
- }
-
- void clear()
- {
- m_data.clear();
- }
-
- void reserve(int capacity)
- {
- m_data.reserve(capacity);
- }
-
- iterator insert(const T &t)
- {
- auto i = find(t);
- if (i != end())
- return i;
- T copy = t;
- m_data.push_back(std::move(copy));
- return std::prev(m_data.end());
- }
-
- iterator insert(T &&t)
- {
- auto i = find(t);
- if (i != end())
- return i;
- m_data.push_back(std::move(t));
- return std::prev(m_data.end());
- }
-
- size_type remove(const T &t)
- {
- auto i = std::find(m_data.begin(), m_data.end(), t);
- if (i != m_data.end()) {
- m_data.erase(i);
- return 1;
- }
- return 0;
- }
-
- iterator operator<<(const T &t)
- {
- return insert(t);
- }
-
- iterator operator<<(T &&t)
- {
- return insert(std::move(t));
- }
-
- iterator begin() { return m_data.begin(); }
- const_iterator begin() const { return m_data.begin(); }
- const_iterator cbegin() const { return m_data.cbegin(); }
-
- iterator end() { return m_data.end(); }
- const_iterator end() const { return m_data.end(); }
- const_iterator cend() const { return m_data.cend(); }
-
-private:
- std::vector<T> m_data;
-};
-
-} // namespace QtQuickParticlesPrivate
-
-QT_END_NAMESPACE
-
-#endif // QQUICKPARTICLEFLATSET_P_H
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index 4eabbde970..5806d7914c 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -214,7 +214,7 @@ QQuickParticleDataHeap::QQuickParticleDataHeap()
void QQuickParticleDataHeap::grow() //###Consider automatic growth vs resize() calls from GroupData
{
- m_data.resize(1 << ++m_size);
+ m_data.resize(qsizetype(1) << ++m_size);
}
void QQuickParticleDataHeap::insert(QQuickParticleData* data)
diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h
index 2f2e10d264..0ae2a5f345 100644
--- a/src/particles/qquickparticlesystem_p.h
+++ b/src/particles/qquickparticlesystem_p.h
@@ -63,7 +63,6 @@
#include <private/qv4global_p.h>
#include <private/qv4staticvalue_p.h>
#include "qtquickparticlesglobal_p.h"
-#include "qquickparticleflatset_p.h"
QT_BEGIN_NAMESPACE
@@ -412,7 +411,7 @@ public:
int systemSync(QQuickParticlePainter* p);
//Data members here for ease of related class and auto-test usage. Not "public" API. TODO: d_ptrize
- QtQuickParticlesPrivate::QFlatSet<QQuickParticleData*> needsReset;
+ QSet<QQuickParticleData*> needsReset;
QVector<QQuickParticleData*> bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
QQuickStochasticEngine* stateEngine;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index ebc9a86a16..f07a5a0513 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -107,6 +107,7 @@ void ScanFunctions::leaveEnvironment()
void ScanFunctions::checkDirectivePrologue(StatementList *ast)
{
+ Q_ASSERT(_context);
for (StatementList *it = ast; it; it = it->next) {
if (ExpressionStatement *expr = cast<ExpressionStatement *>(it->statement)) {
if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
@@ -131,6 +132,7 @@ void ScanFunctions::checkDirectivePrologue(StatementList *ast)
void ScanFunctions::checkName(QStringView name, const QQmlJS::SourceLocation &loc)
{
+ Q_ASSERT(_context);
if (_context->isStrict) {
if (name == QLatin1String("implements")
|| name == QLatin1String("interface")
@@ -161,6 +163,7 @@ void ScanFunctions::endVisit(Program *)
bool ScanFunctions::visit(ESModule *ast)
{
enterEnvironment(ast, defaultProgramType, QStringLiteral("%ModuleCode"));
+ Q_ASSERT(_context);
_context->isStrict = true;
return true;
}
@@ -172,6 +175,7 @@ void ScanFunctions::endVisit(ESModule *)
bool ScanFunctions::visit(ExportDeclaration *declaration)
{
+ Q_ASSERT(_context);
QString module;
if (declaration->fromClause) {
module = declaration->fromClause->moduleSpecifier.toString();
@@ -262,6 +266,7 @@ bool ScanFunctions::visit(ExportDeclaration *declaration)
bool ScanFunctions::visit(ImportDeclaration *declaration)
{
+ Q_ASSERT(_context);
QString module;
if (declaration->fromClause) {
module = declaration->fromClause->moduleSpecifier.toString();
@@ -310,6 +315,7 @@ bool ScanFunctions::visit(ImportDeclaration *declaration)
bool ScanFunctions::visit(CallExpression *ast)
{
+ Q_ASSERT(_context);
if (!_context->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("eval")) {
@@ -324,6 +330,7 @@ bool ScanFunctions::visit(CallExpression *ast)
bool ScanFunctions::visit(PatternElement *ast)
{
+ Q_ASSERT(_context);
if (!ast->isVariableDeclaration())
return true;
@@ -359,6 +366,7 @@ bool ScanFunctions::visit(PatternElement *ast)
bool ScanFunctions::visit(IdentifierExpression *ast)
{
+ Q_ASSERT(_context);
checkName(ast->name, ast->identifierToken);
if (_context->usesArgumentsObject == Context::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments"))
_context->usesArgumentsObject = Context::ArgumentsObjectUsed;
@@ -395,6 +403,7 @@ bool ScanFunctions::visit(FunctionExpression *ast)
bool ScanFunctions::visit(ClassExpression *ast)
{
enterEnvironment(ast, ContextType::Block, QStringLiteral("%Class"));
+ Q_ASSERT(_context);
_context->isStrict = true;
_context->hasNestedFunctions = true;
if (!ast->name.isEmpty())
@@ -409,6 +418,7 @@ void ScanFunctions::endVisit(ClassExpression *)
bool ScanFunctions::visit(ClassDeclaration *ast)
{
+ Q_ASSERT(_context);
if (!ast->name.isEmpty())
_context->addLocalVar(ast->name.toString(), Context::VariableDeclaration, AST::VariableScope::Let);
@@ -459,6 +469,7 @@ bool ScanFunctions::visit(FieldMemberExpression *ast)
_cg->throwSyntaxError(ast->identifierToken, QLatin1String("Expected 'target' after 'new.'."));
return false;
}
+ Q_ASSERT(_context);
Context *c = _context;
bool needContext = false;
while (c->contextType == ContextType::Block || c->isArrowFunction) {
@@ -485,6 +496,7 @@ bool ScanFunctions::visit(ArrayPattern *ast)
bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
{
+ Q_ASSERT(_context);
if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName);
@@ -557,10 +569,13 @@ void ScanFunctions::endVisit(ForStatement *)
leaveEnvironment();
}
-bool ScanFunctions::visit(ForEachStatement *ast) {
+bool ScanFunctions::visit(ForEachStatement *ast)
+{
enterEnvironment(ast, ContextType::Block, QStringLiteral("%Foreach"));
- if (ast->expression)
+ if (ast->expression) {
+ Q_ASSERT(_context);
_context->lastBlockInitializerLocation = ast->expression->lastSourceLocation();
+ }
Node::accept(ast->lhs, this);
Node::accept(ast->expression, this);
@@ -577,6 +592,7 @@ void ScanFunctions::endVisit(ForEachStatement *)
bool ScanFunctions::visit(ThisExpression *)
{
+ Q_ASSERT(_context);
_context->usesThis = true;
return false;
}
@@ -607,6 +623,7 @@ void ScanFunctions::endVisit(CaseBlock *)
bool ScanFunctions::visit(Catch *ast)
{
+ Q_ASSERT(_context);
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
enterEnvironment(ast, ContextType::Block, QStringLiteral("%CatchBlock"));
_context->isCatchBlock = true;
@@ -634,6 +651,7 @@ void ScanFunctions::endVisit(Catch *)
bool ScanFunctions::visit(WithStatement *ast)
{
+ Q_ASSERT(_context);
Node::accept(ast->expression, this);
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _context->isStrict ? false : _allowFuncDecls);
@@ -676,6 +694,7 @@ bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
+ Q_ASSERT(_context);
_context->name = name;
if (formals && formals->containsName(QStringLiteral("arguments")))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
diff --git a/src/qml/doc/snippets/qml/imports/merged-named-imports.qml b/src/qml/doc/snippets/qml/imports/merged-named-imports.qml
index 8fab0436bd..533b22cb93 100644
--- a/src/qml/doc/snippets/qml/imports/merged-named-imports.qml
+++ b/src/qml/doc/snippets/qml/imports/merged-named-imports.qml
@@ -49,8 +49,8 @@
****************************************************************************/
//! [imports]
-import QtQuick 2.0 as Project
-import QtMultimedia 5.0 as Project
+import QtQuick as Project
+import QtMultimedia as Project
Project.Rectangle {
width: 100; height: 50
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 2fdd6edded..aeff2b5776 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -70,6 +70,21 @@ exposed to QML but the type itself should not be instantiable.
For a quick guide to choosing the correct approach to expose C++ types to QML,
see \l {Choosing the Correct Integration Method Between C++ and QML}.
+\section2 Preconditions
+
+All the macros mentioned below are available from the \c qqml.h
+header. You need to add the following code to the files using them in order to
+make the macros available:
+
+\code
+#include <QtQml/qqml.h>
+\endcode
+
+Furthermore, your class declarations have to live in headers reachable via your
+project's include path. The declarations are used to generate registration code
+at compile time, and the registration code needs to include the headers that
+contain the declarations.
+
\section2 Registering an Instantiable Object Type
\b{Any QObject-derived C++ class can be registered as the definition of a
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index f48a5f475b..92d9bdec49 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -730,16 +730,6 @@
*/
/*!
- \fn int qmlRegisterType()
- \relates QQmlEngine
- \overload
- \deprecated
-
- Do not use this function. For anonymous type registrations, use \l qmlRegisterAnonymousType(),
- and make sure to provide a URI and a major version.
-*/
-
-/*!
\fn int qmlRegisterInterface(const char *typeName)
\relates QQmlEngine
diff --git a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc
index fdba452271..7fe678b434 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc
@@ -49,7 +49,7 @@ types and JavaScript resources into a given namespace.
The generic form of a module import is as follows:
\code
-import <ModuleIdentifier> <Version.Number> [as <Qualifier>]
+import <ModuleIdentifier> [<Version.Number>] [as <Qualifier>]
\endcode
\list
@@ -59,7 +59,9 @@ import <ModuleIdentifier> <Version.Number> [as <Qualifier>]
\li The \c <Version.Number> is a version of the form
\c {MajorVersion.MinorVersion} which specifies which definitions of
various object types and JavaScript resources will be made available due
- to the import.
+ to the import. It can be omitted, in which case the latest version of the
+ module is imported. It is also possible to only omit the minor version.
+ Then the latest minor version of the given major version is imported.
\li The \c <Qualifier> is an optional local namespace identifier into which
the object types and JavaScript resources provided by the module will be
installed, if given. If omitted, the object types and JavaScript
@@ -69,7 +71,7 @@ import <ModuleIdentifier> <Version.Number> [as <Qualifier>]
An example of an unqualified module import is as follows:
\code
-import QtQuick 2.0
+import QtQuick
\endcode
This import allows the use of all of the types provided by the \c QtQuick
@@ -77,7 +79,7 @@ module without needing to specify a qualifier. For example, the client code to
create a rectangle is as follows:
\qml
-import QtQuick 2.0
+import QtQuick
Rectangle {
width: 200
@@ -86,9 +88,16 @@ Rectangle {
}
\endqml
+An example of an unqualified import with version would be
+\code
+import QtQuick 2.10
+\endcode
+In that case, any types defined in QtQuick 2.11 and higher or in any higher major
+version, like 6.0, would not be available to the file.
+
An example of a qualified module import is as follows:
\code
-import QtQuick 2.0 as Quick
+import QtQuick as Quick
\endcode
This import allows multiple modules which provide conflicting type names to be
@@ -100,7 +109,7 @@ An example of client code which creates a rectangle after using a qualified
module import is as follows:
\qml
-import QtQuick 2.0 as Quick
+import QtQuick as Quick
Quick.Rectangle {
width: 200
@@ -149,7 +158,7 @@ references to types from the \c QtQuick module must be prefixed with the
\c CoreItems name:
\qml
-import QtQuick 2.0 as CoreItems
+import QtQuick as CoreItems
CoreItems.Rectangle {
width: 100; height: 100
@@ -171,7 +180,7 @@ two modules can be imported into different namespaces to ensure the code is
referring to the correct type:
\qml
-import QtQuick 2.0 as CoreItems
+import QtQuick as CoreItems
import "../textwidgets" as MyModule
CoreItems.Rectangle {
@@ -244,8 +253,8 @@ module by importing the module and using the identifier associated with a
declared resource:
\qml
-import QtQuick 2.0
-import projects.MyQMLProject.MyFunctions 1.0
+import QtQuick
+import projects.MyQMLProject.MyFunctions
Item {
Component.onCompleted: { SystemFunctions.cleanUp(); }
@@ -257,9 +266,9 @@ resource identifiers must be prefixed with the namespace qualifier in order
to be used:
\qml
-import QtQuick 2.0
-import projects.MyQMLProject.MyFunctions 1.0 as MyFuncs
-import org.example.Functions 1.0 as TheirFuncs
+import QtQuick
+import projects.MyQMLProject.MyFunctions as MyFuncs
+import org.example.Functions as TheirFuncs
Item {
Component.onCompleted: {
diff --git a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
index 8cc13e5e9c..4cb438f85d 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
@@ -85,7 +85,9 @@ This type of signal is a \e {property change signal} and signal handlers for
these signals are written in the form \e on<Property>Changed, where
\e <Property> is the name of the property, with the first letter capitalized.
-For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property. To receive a notification whenever this property changes, write a signal handler named \c onPressedChanged:
+For example, the \l MouseArea type has a \l {MouseArea::pressed}{pressed} property.
+To receive a notification whenever this property changes, write a signal handler
+named \c onPressedChanged:
\qml
import QtQuick
@@ -104,6 +106,55 @@ Even though the \l TapHandler documentation does not document a signal handler
named \c onPressedChanged, the signal is implicitly provided by the fact that
the \c pressed property exists.
+\section2 Signal parameters
+
+Signals might have parameters. To access those, you should assign a function to the handler. Both
+arrow functions and anonymous functions work.
+
+For the following examples, consider a Status component with an errorOccurred signal (see
+\l{Adding signals to custom QML types} for more information about how signals can be added to
+QML components).
+
+\qml
+// Status.qml
+import QtQuick
+
+Item {
+ id: myitem
+ signal errorOccurred(message: string, line: int, column: int)
+}
+\endqml
+
+\qml
+Status {
+ onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`)
+}
+\endqml
+
+\note The names of the formal parameters in the function do not have to match those in the
+signal.
+
+If you do not need to handle all parameters, it is possible to omit trailing ones:
+\qml
+Status {
+ onErrorOccurred: function (message) { console.log(message) }
+}
+\endqml
+
+It is not possible to leave out leading parameters you are interested in, however you can use some
+placeholder name to indicate to readers that they are not important:
+\qml
+Status {
+ onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
+}
+\endqml
+
+\note Instead of using a function, it is possible, but discouraged, to use a plain code block. In
+that case all signal parameters get injected into the scope of the block. However, this can make
+code difficult to read as it's unclear where the parameters come from, and results in slower
+lookups in the QML engine. Injecting parameters in this way is deprecated, and will cause runtime
+warnings if the parameter is actually used.
+
\section2 Using the Connections type
In some cases it may be desirable to access a signal outside of the object that
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 37b5306897..b1db348287 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -1076,7 +1076,7 @@ QJSEngine *qjsEngine(const QObject *object)
two different engines will not be valid if one of these engines is deleted. This option is similar
to QScriptEngine::ScriptOwnership.
- Generally an application doesn't need to set an object's ownership explicitly. the JavaScript
+ Generally an application doesn't need to set an object's ownership explicitly. The JavaScript
memory manager uses a heuristic to set the default ownership. By default, an object that is
created by the JavaScript memory manager has JavaScriptOwnership. The exception to this are the
root objects created by calling QQmlComponent::create() or QQmlComponent::beginCreate(), which
@@ -1089,10 +1089,17 @@ QJSEngine *qjsEngine(const QObject *object)
but not to property getter invocations.
Calling setObjectOwnership() overrides the default ownership.
+
+ \sa {Data Ownership}
*/
/*!
Sets the \a ownership of \a object.
+
+ An object with \c JavaScriptOwnership is not garbage collected as long
+ as it still has a parent, even if there are no references to it.
+
+ \sa QJSEngine::ObjectOwnership
*/
void QJSEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
{
@@ -1109,6 +1116,8 @@ void QJSEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
/*!
Returns the ownership of \a object.
+
+ \sa QJSEngine::ObjectOwnership
*/
QJSEngine::ObjectOwnership QJSEngine::objectOwnership(QObject *object)
{
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 21aee81985..1fcdfa8f6f 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1605,7 +1605,9 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
}
asVariant = toVariant(e, arrayValue, valueMetaType.id(), false,
visitedObjects);
- if (valueMetaType.id() != QMetaType::QVariant) {
+ if (valueMetaType == QMetaType::fromType<QVariant>()) {
+ retnAsIterable.metaContainer().addValue(retn.data(), &asVariant);
+ } else {
auto originalType = asVariant.metaType();
bool couldConvert = asVariant.convert(valueMetaType);
if (!couldConvert) {
@@ -1616,8 +1618,8 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
// create default constructed value
asVariant = QVariant(valueMetaType, nullptr);
}
+ retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
}
- retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
}
return retn;
}
diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h
index 10eea5e46b..14368f5416 100644
--- a/src/qml/jsruntime/qv4generatorobject_p.h
+++ b/src/qml/jsruntime/qv4generatorobject_p.h
@@ -87,7 +87,6 @@ struct GeneratorPrototype : FunctionObject {
#define GeneratorObjectMembers(class, Member) \
Member(class, Pointer, ExecutionContext *, context) \
- Member(class, Pointer, GeneratorFunction *, function) \
Member(class, NoMark, GeneratorState, state) \
Member(class, NoMark, CppStackFrame, cppFrame) \
Member(class, Pointer, ArrayObject *, values) \
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
index 616fa9a5a9..9b6b5322bd 100644
--- a/src/qml/jsruntime/qv4stackframe_p.h
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -134,7 +134,9 @@ struct Q_QML_EXPORT CppStackFrame {
argc = nFormals;
jsFrame->setArgc(argc);
- memcpy(jsFrame->args, originalArguments, argc*sizeof(Value));
+ // memcpy requires non-null ptr, even if argc*sizeof(Value) == 0
+ if (originalArguments)
+ memcpy(jsFrame->args, originalArguments, argc*sizeof(Value));
Q_STATIC_ASSERT(Encode::undefined() == 0);
memset(jsFrame->args + argc, 0, (nRegisters - argc)*sizeof(Value));
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index e973226053..a77419d0e0 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -172,7 +172,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRe
: (version.hasMinorVersion()
? QTypeRevision::fromVersion(type.version().majorVersion(),
version.minorVersion())
- : type.version());
+ : QTypeRevision::fromMajorVersion(type.version().majorVersion()));
while (metaObject) {
QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion);
diff --git a/src/qmldebug/qqmlprofilerevent_p.h b/src/qmldebug/qqmlprofilerevent_p.h
index 928cda716e..29c6f86123 100644
--- a/src/qmldebug/qqmlprofilerevent_p.h
+++ b/src/qmldebug/qqmlprofilerevent_p.h
@@ -48,6 +48,7 @@
#include <QtCore/qmetatype.h>
#include <initializer_list>
+#include <limits>
#include <type_traits>
//
diff --git a/src/qmlmodels/qqmllistaccessor.cpp b/src/qmlmodels/qqmllistaccessor.cpp
index 7412dd0146..ea336138ce 100644
--- a/src/qmlmodels/qqmllistaccessor.cpp
+++ b/src/qmlmodels/qqmllistaccessor.cpp
@@ -105,6 +105,7 @@ void QQmlListAccessor::setList(const QVariant &v, QQmlEngine *engine)
m_type = Invalid;
} else {
m_type = Integer;
+ d = i;
}
} else if ((!enginePrivate && QQmlMetaType::isQObject(d.userType())) ||
(enginePrivate && enginePrivate->isQObject(d.userType()))) {
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt
index f158a40210..ffc1298532 100644
--- a/src/quick/CMakeLists.txt
+++ b/src/quick/CMakeLists.txt
@@ -221,66 +221,64 @@ qt_internal_add_module(Quick
# Resources:
set(scenegraph_resource_files
- "shaders_ng/24bittextmask.frag.qsb"
- "shaders_ng/32bitcolortext.frag.qsb"
- "shaders_ng/8bittextmask.frag.qsb"
- "shaders_ng/8bittextmask_a.frag.qsb"
- "shaders_ng/distancefieldoutlinetext.frag.qsb"
- "shaders_ng/distancefieldoutlinetext.vert.qsb"
- "shaders_ng/distancefieldoutlinetext_a.frag.qsb"
- "shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"
- "shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"
- "shaders_ng/distancefieldshiftedtext.frag.qsb"
- "shaders_ng/distancefieldshiftedtext.vert.qsb"
- "shaders_ng/distancefieldshiftedtext_a.frag.qsb"
- "shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"
- "shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"
- "shaders_ng/distancefieldtext.frag.qsb"
- "shaders_ng/distancefieldtext.vert.qsb"
- "shaders_ng/distancefieldtext_a.frag.qsb"
- "shaders_ng/distancefieldtext_a_fwidth.frag.qsb"
- "shaders_ng/distancefieldtext_fwidth.frag.qsb"
- "shaders_ng/flatcolor.frag.qsb"
- "shaders_ng/flatcolor.vert.qsb"
- "shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"
- "shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"
- "shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"
- "shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"
- "shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"
- "shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"
- "shaders_ng/opaquetexture.frag.qsb"
- "shaders_ng/opaquetexture.vert.qsb"
- "shaders_ng/outlinedtext.frag.qsb"
- "shaders_ng/outlinedtext.vert.qsb"
- "shaders_ng/outlinedtext_a.frag.qsb"
- "shaders_ng/shadereffect.frag.qsb"
- "shaders_ng/shadereffect.vert.qsb"
- "shaders_ng/smoothcolor.frag.qsb"
- "shaders_ng/smoothcolor.vert.qsb"
- "shaders_ng/smoothtexture.frag.qsb"
- "shaders_ng/smoothtexture.vert.qsb"
- "shaders_ng/sprite.frag.qsb"
- "shaders_ng/sprite.vert.qsb"
- "shaders_ng/stencilclip.frag.qsb"
- "shaders_ng/stencilclip.vert.qsb"
- "shaders_ng/styledtext.frag.qsb"
- "shaders_ng/styledtext.vert.qsb"
- "shaders_ng/styledtext_a.frag.qsb"
- "shaders_ng/textmask.frag.qsb"
- "shaders_ng/textmask.vert.qsb"
- "shaders_ng/texture.frag.qsb"
- "shaders_ng/texture.vert.qsb"
- "shaders_ng/vertexcolor.frag.qsb"
- "shaders_ng/vertexcolor.vert.qsb"
- "shaders_ng/visualization.frag.qsb"
- "shaders_ng/visualization.vert.qsb"
+ "scenegraph/shaders_ng/24bittextmask.frag.qsb"
+ "scenegraph/shaders_ng/32bitcolortext.frag.qsb"
+ "scenegraph/shaders_ng/8bittextmask.frag.qsb"
+ "scenegraph/shaders_ng/8bittextmask_a.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"
+ "scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"
+ "scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldtext.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldtext.vert.qsb"
+ "scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"
+ "scenegraph/shaders_ng/flatcolor.frag.qsb"
+ "scenegraph/shaders_ng/flatcolor.vert.qsb"
+ "scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"
+ "scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"
+ "scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"
+ "scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"
+ "scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"
+ "scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"
+ "scenegraph/shaders_ng/opaquetexture.frag.qsb"
+ "scenegraph/shaders_ng/opaquetexture.vert.qsb"
+ "scenegraph/shaders_ng/outlinedtext.frag.qsb"
+ "scenegraph/shaders_ng/outlinedtext.vert.qsb"
+ "scenegraph/shaders_ng/outlinedtext_a.frag.qsb"
+ "scenegraph/shaders_ng/shadereffect.frag.qsb"
+ "scenegraph/shaders_ng/shadereffect.vert.qsb"
+ "scenegraph/shaders_ng/smoothcolor.frag.qsb"
+ "scenegraph/shaders_ng/smoothcolor.vert.qsb"
+ "scenegraph/shaders_ng/smoothtexture.frag.qsb"
+ "scenegraph/shaders_ng/smoothtexture.vert.qsb"
+ "scenegraph/shaders_ng/sprite.frag.qsb"
+ "scenegraph/shaders_ng/sprite.vert.qsb"
+ "scenegraph/shaders_ng/stencilclip.frag.qsb"
+ "scenegraph/shaders_ng/stencilclip.vert.qsb"
+ "scenegraph/shaders_ng/styledtext.frag.qsb"
+ "scenegraph/shaders_ng/styledtext.vert.qsb"
+ "scenegraph/shaders_ng/styledtext_a.frag.qsb"
+ "scenegraph/shaders_ng/textmask.frag.qsb"
+ "scenegraph/shaders_ng/textmask.vert.qsb"
+ "scenegraph/shaders_ng/texture.frag.qsb"
+ "scenegraph/shaders_ng/texture.vert.qsb"
+ "scenegraph/shaders_ng/vertexcolor.frag.qsb"
+ "scenegraph/shaders_ng/vertexcolor.vert.qsb"
+ "scenegraph/shaders_ng/visualization.frag.qsb"
+ "scenegraph/shaders_ng/visualization.vert.qsb"
)
qt_internal_add_resource(Quick "scenegraph"
PREFIX
- "/qt-project.org/scenegraph"
- BASE
- "scenegraph"
+ "/qt-project.org"
FILES
${scenegraph_resource_files}
)
@@ -525,4 +523,3 @@ set_target_properties(Quick PROPERTIES
)
qt6_qml_type_registration(Quick)
-
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index bca03b496d..925966d2ef 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -216,6 +216,8 @@ QAccessible::Role QAccessibleQuickItem::role() const
if (role == QAccessible::NoRole) {
if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
role = QAccessible::StaticText;
+ else if (qobject_cast<QQuickTextInput*>(const_cast<QQuickItem *>(item())))
+ role = QAccessible::EditableText;
else
role = QAccessible::Client;
}
diff --git a/src/quick/designer/qquickdesignersupportproperties.cpp b/src/quick/designer/qquickdesignersupportproperties.cpp
index bbbb8a43b4..1254d1ee7a 100644
--- a/src/quick/designer/qquickdesignersupportproperties.cpp
+++ b/src/quick/designer/qquickdesignersupportproperties.cpp
@@ -126,16 +126,15 @@ void QQuickDesignerSupportProperties::getPropertyCache(QObject *object, QQmlEngi
QQmlEnginePrivate::get(engine)->cache(object->metaObject());
}
-QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propertyNameListForWritableProperties(QObject *object,
+static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object,
const QQuickDesignerSupport::PropertyName &baseName,
- QObjectList *inspectedObjects)
+ QObjectList *inspectedObjects,
+ int depth = 0)
{
QQuickDesignerSupport::PropertyNameList propertyNameList;
- QObjectList localObjectList;
-
- if (inspectedObjects == nullptr)
- inspectedObjects = &localObjectList;
+ if (depth > 2)
+ return propertyNameList;
if (!inspectedObjects->contains(object))
inspectedObjects->append(object);
@@ -150,14 +149,16 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propert
if (childObject)
propertyNameList.append(propertyNameListForWritableProperties(childObject,
baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
- + '.', inspectedObjects));
+ + '.', inspectedObjects,
+ depth + 1));
}
} else if (QQmlGadgetPtrWrapper *valueType
= QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.metaType())) {
valueType->setValue(metaProperty.read(object));
propertyNameList.append(propertyNameListForWritableProperties(valueType,
baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
- + '.', inspectedObjects));
+ + '.', inspectedObjects,
+ depth + 1));
}
if (metaProperty.isReadable() && metaProperty.isWritable()) {
@@ -169,6 +170,12 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propert
return propertyNameList;
}
+QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::propertyNameListForWritableProperties(QObject *object)
+{
+ QObjectList localObjectList;
+ return ::propertyNameListForWritableProperties(object, {}, &localObjectList);
+}
+
bool QQuickDesignerSupportProperties::isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName)
{
if (propertyName.contains(".") && propertyName.contains("__"))
@@ -182,7 +189,8 @@ bool QQuickDesignerSupportProperties::isPropertyBlackListed(const QQuickDesigner
QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allPropertyNames(QObject *object,
const QQuickDesignerSupport::PropertyName &baseName,
- QObjectList *inspectedObjects)
+ QObjectList *inspectedObjects,
+ int depth)
{
QQuickDesignerSupport::PropertyNameList propertyNameList;
@@ -191,6 +199,9 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allProp
if (inspectedObjects == nullptr)
inspectedObjects = &localObjectList;
+ if (depth > 2)
+ return propertyNameList;
+
if (!inspectedObjects->contains(object))
inspectedObjects->append(object);
@@ -214,7 +225,8 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allProp
propertyNameList.append(allPropertyNames(childObject,
baseName
+ QQuickDesignerSupport::PropertyName(metaProperty.name())
- + '.', inspectedObjects));
+ + '.', inspectedObjects,
+ depth + 1));
}
} else if (QQmlGadgetPtrWrapper *valueType
= QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.metaType())) {
@@ -223,7 +235,8 @@ QQuickDesignerSupport::PropertyNameList QQuickDesignerSupportProperties::allProp
propertyNameList.append(allPropertyNames(valueType,
baseName
+ QQuickDesignerSupport::PropertyName(metaProperty.name())
- + '.', inspectedObjects));
+ + '.', inspectedObjects,
+ depth + 1));
} else {
addToPropertyNameListIfNotBlackListed(&propertyNameList,
baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
diff --git a/src/quick/designer/qquickdesignersupportproperties_p.h b/src/quick/designer/qquickdesignersupportproperties_p.h
index 02e75ea886..5970eca9f1 100644
--- a/src/quick/designer/qquickdesignersupportproperties_p.h
+++ b/src/quick/designer/qquickdesignersupportproperties_p.h
@@ -90,12 +90,11 @@ public:
static void getPropertyCache(QObject *object, QQmlEngine *engine);
static bool isPropertyBlackListed(const QQuickDesignerSupport::PropertyName &propertyName);
- static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object,
- const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
- QObjectList *inspectedObjects = nullptr);
+ static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProperties(QObject *object);
static QQuickDesignerSupport::PropertyNameList allPropertyNames(QObject *object,
const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
- QObjectList *inspectedObjects = nullptr);
+ QObjectList *inspectedObjects = nullptr,
+ int depth = 0);
static bool hasFullImplementedListInterface(const QQmlListReference &list);
};
diff --git a/src/quick/doc/images/containmentMask-circle.gif b/src/quick/doc/images/containmentMask-circle.gif
new file mode 100644
index 0000000000..80abce625f
--- /dev/null
+++ b/src/quick/doc/images/containmentMask-circle.gif
Binary files differ
diff --git a/src/quick/doc/images/containmentMask-shape.gif b/src/quick/doc/images/containmentMask-shape.gif
new file mode 100644
index 0000000000..e7989352eb
--- /dev/null
+++ b/src/quick/doc/images/containmentMask-shape.gif
Binary files differ
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 12d56a665c..3c19316601 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -62,7 +62,7 @@ depends += \
../../quickwidgets \
../../qmllocalstorage \
../../quicklayouts \
- ../../labs/animation
+ ../../labs
exampledirs += ../../../examples/quick \
snippets
diff --git a/src/quick/doc/snippets/pointerHandlers/hoverTapKeyButton.qml b/src/quick/doc/snippets/pointerHandlers/hoverTapKeyButton.qml
new file mode 100644
index 0000000000..1564aa16b5
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/hoverTapKeyButton.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.12
+
+Rectangle {
+ id: button
+ signal clicked
+
+ width: 150; height: 50; radius: 3
+ color: tapHandler.pressed ? "goldenrod" : hoverHandler.hovered ? "wheat" : "beige"
+ border.color: activeFocus ? "brown" : "transparent"
+ focus: true
+
+ HoverHandler {
+ id: hoverHandler
+ }
+
+ TapHandler {
+ id: tapHandler
+ onTapped: button.clicked()
+ }
+
+ Keys.onEnterPressed: button.clicked()
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/tapHandlerButton.qml b/src/quick/doc/snippets/pointerHandlers/tapHandlerButton.qml
new file mode 100644
index 0000000000..02d0b4213b
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/tapHandlerButton.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick
+
+Rectangle {
+ id: button
+ signal clicked
+ property alias text: buttonLabel.text
+
+ height: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2)
+ width: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3)
+ radius: 3
+ property color dark: Qt.darker(palette.button, 1.3)
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? dark : palette.button }
+ GradientStop { position: 1.0; color: dark }
+ }
+
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.ReleaseWithinBounds
+ onTapped: button.clicked()
+ }
+
+ Text {
+ id: buttonLabel
+ text: "Click Me"
+ color: palette.buttonText
+ anchors.centerIn: parent
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/item/containmentMask-circle-js.qml b/src/quick/doc/snippets/qml/item/containmentMask-circle-js.qml
new file mode 100644
index 0000000000..2d97bcdafa
--- /dev/null
+++ b/src/quick/doc/snippets/qml/item/containmentMask-circle-js.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.12
+import QtQuick 2.12
+
+//![0]
+Rectangle {
+ id: circle
+ width: 100; height: width
+ radius: width / 2
+ color: tapHandler.pressed ? "tomato" : hoverHandler.hovered ? "darkgray" : "lightgray"
+
+ TapHandler { id: tapHandler }
+ HoverHandler { id: hoverHandler }
+
+ containmentMask: QtObject {
+ property alias radius: circle.radius
+ function contains(point: point) : bool {
+ return (Math.pow(point.x - radius, 2) + Math.pow(point.y - radius, 2)) < Math.pow(radius, 2)
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/item/containmentMask-shape.qml b/src/quick/doc/snippets/qml/item/containmentMask-shape.qml
new file mode 100644
index 0000000000..a3da217e73
--- /dev/null
+++ b/src/quick/doc/snippets/qml/item/containmentMask-shape.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Shapes 1.12
+
+//![0]
+Rectangle {
+ width: 90; height: 100
+ color: hoverHandler.hovered ? "wheat" : "lightgray"
+ containmentMask: shape
+
+ HoverHandler { id: hoverHandler }
+
+ Shape {
+ id: shape
+ containsMode: Shape.FillContains
+
+ ShapePath {
+ fillColor: "lightsteelblue"
+ startX: 10; startY: 20
+ PathArc {
+ x: 10; y: 80
+ radiusX: 40; radiusY: 40
+ useLargeArc: true
+ }
+ PathLine {
+ x: 10; y: 20
+ }
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc b/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
index 2ac9860e6f..bf889a9066 100644
--- a/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
+++ b/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -30,20 +30,21 @@
\title Qt Quick Input Handlers
\brief A module with a set of QML elements that handle events from input devices in a user interface.
- Qt Quick Input Handlers are a set of QML types used to handle events from
- keyboard, touch, mouse, and stylus devices in a UI. In contrast to event-handling
- items, such as \l MouseArea and \l Flickable, input handlers are explicitly non-visual,
- require less memory and are intended to be used in greater numbers: one
- handler instance per aspect of interaction. Each input handler instance
- handles certain events on behalf of its \c parent Item. Thus the visual and
+ Qt Quick Input Handlers are a set of QML types used to handle
+ \l {QInputEvent}{events} from keyboard, touch, mouse, and stylus
+ \l {QInputDevice}{devices} in a UI. In contrast to event-handling
+ items, such as \l MouseArea and \l Flickable, input handlers are explicitly
+ non-visual, require less memory and are intended to be used in greater
+ numbers: one handler instance per aspect of interaction. Each input handler
+ instance handles certain events on behalf of its
+ \l {QQuickPointerHandler::parent()}{parent} Item. Thus the visual and
behavioral concerns are better separated, and the behavior is built up by
finer-grained composition.
- In Qt 5.10, these handlers were introduced in a separate Qt.labs.handlers module.
- Now they are included with Qt Quick since 5.12. The pre-existing
- \l Keys attached property is similar in concept, so we refer to the
- pointing-device-oriented handlers plus \c Keys together as the set of Input Handlers.
- We expect to offer more attached-property use cases in future versions of Qt.
+ The pre-existing \l Keys attached property is similar in concept, so we
+ refer to the pointing-device-oriented handlers plus \c Keys together as the
+ set of Input Handlers. We expect to offer more attached-property use cases
+ in future versions of Qt.
\section1 Input Handlers
@@ -60,7 +61,44 @@
\li Each Item can have unlimited Handlers
\endlist
- \omit TODO actual overview with snippets and stuff \endomit
+ \section1 Handlers Manipulating Items
+
+ Some Handlers add interactivity simply by being declared inside an Item:
+
+ \snippet pointerHandlers/dragHandler.qml 0
+
+ \section1 Handler Properties and Signals
+
+ All Handlers have properties that can be used in bindings, and signals that
+ can be handled to react to input:
+
+ \snippet pointerHandlers/hoverTapKeyButton.qml 0
+
+ \section1 Pointer Grab
+
+ An important concept with Pointer Handlers is the type of grabs that they
+ perform. The only kind of grab an Item can take is the exclusive grab: for
+ example if you call \l QPointerEvent::setExclusiveGrabber(), the following
+ mouse moves and mouse release event will be sent only to that object. (As a
+ workaround to this exclusivity, see \l QQuickItem::setFiltersChildMouseEvents()
+ and \l QQuickItem::childMouseEventFilter().) However Pointer Handlers have
+ an additional mechanism available: the
+ \l {QPointerEvent::addPassiveGrabber()} {passive grab}. Mouse and touch
+ \l {QEventPoint::state()}{press} events are delivered by visiting all the
+ Items in top-down Z order: first each Item's child Handlers, and then the
+ \l {QQuickItem::event()}{Item} itself. At the time a press event is
+ delivered, a Handler can take either a passive or an exclusive grab
+ depending on its needs. If it takes a passive grab, it is guaranteed to
+ receive the updates and the release, even if other Items or Handlers in the
+ scene take any kind of grab, passive or exclusve. Some Handlers (such as
+ PointHandler) can work only with passive grabs; others require exclusive
+ grabs; and others can "lurk" with passive grabs until they detect that a
+ gesture is being performed, and then make the transition from passive to
+ exclusive grab.
+
+ When a grab transition is requested, \l PointerHandler::grabPermissions,
+ \l QQuickItem::keepMouseGrab() and \l QQuickItem::keepTouchGrab() control
+ whether the transition will be allowed.
\section1 Related Information
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index 9d79ac862b..b86725f4ad 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -733,6 +733,73 @@ console.log(c + " " + d); // false true
\li Example
\row
+ \li translate(vector3d vector)
+ \li Multiplies \c this matrix4x4 by another that translates coordinates by the components
+ of \c vector
+ \li \code
+var m = Qt.matrix4x4();
+m.translate(Qt.vector3d(1,2,3));
+console.log(m.toString());
+// QMatrix4x4(1, 0, 0, 1, 0, 1, 0, 2, 0, 0, 1, 3, 0, 0, 0, 1)
+ \endcode
+
+ \row
+ \li rotate(real angle, vector3d axis)
+ \li Multiples \c this matrix4x4 by another that rotates coordinates through
+ \c angle degrees about \c axis
+ \li \code
+var m = Qt.matrix4x4();
+m.rotate(180,vector3d(1,0,0));
+console.log(m.toString());
+// QMatrix4x4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)
+ \endcode
+
+ \row
+ \li scale(real factor)
+ \li Multiplies \c this matrix4x4 by another that scales coordinates by the given \c factor
+ \li \code
+var m = Qt.matrix4x4();
+m.scale(2);
+console.log(m.toString());
+// QMatrix4x4(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)
+ \endcode
+
+ \row
+ \li scale(real x, real y, real z)
+ \li Multiplies \c this matrix4x4 by another that scales coordinates by the components
+ \c x, \c y, and \c z
+ \li \code
+var m = Qt.matrix4x4();
+m.scale(1,2,3);
+console.log(m.toString());
+// QMatrix4x4(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1)
+ \endcode
+
+ \row
+ \li scale(vector3d vector)
+ \li Multiplies \c this matrix4x4 by another that scales coordinates by the components
+ of \c vector
+ \li \code
+var m = Qt.matrix4x4();
+m.scale(Qt.vector3d(1,2,3));
+console.log(m.toString());
+// QMatrix4x4(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1)
+ \endcode
+
+ \row
+ \li lookAt(vector3d eye, vector3d center, vector3d up)
+ \li Multiplies \c this matrix4x4 by a viewing matrix derived from an \c eye point.
+ The \c center vector3d indicates the center of the view that the \c eye is looking at.
+ The \c up vector3d indicates which direction should be considered up with respect to
+ the \c eye.
+ \li \code
+var m = Qt.matrix4x4();
+m.lookAt(Qt.vector3d(1,2,3),Qt.vector3d(1,2,0),Qt.vector3d(0,1,0));
+console.log(m.toString());
+// QMatrix4x4(1, 0, 0, -1, 0, 1, 0, -2, 0, 0, 1, -3, 0, 0, 0, 1)
+ \endcode
+
+ \row
\li matrix4x4 times(matrix4x4 other)
\li Returns the matrix4x4 result of multiplying \c this matrix4x4 with
the \c other matrix4x4
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 980481303f..9471ef7660 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -182,7 +182,13 @@ void QQuickDragHandler::onActiveChanged()
bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
{
if (!QQuickMultiPointHandler::wantsPointerEvent(event))
- return false;
+ /* Do handle other events than we would normally care about
+ while we are still doing a drag; otherwise we would suddenly
+ become inactive when a wheel event arrives during dragging.
+ This extra condition needs to be kept in sync with
+ handlePointerEventImpl */
+ if (!active())
+ return false;
#if QT_CONFIG(gestures)
if (event->type() == QEvent::NativeGesture)
@@ -194,6 +200,9 @@ bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
{
+ if (active() && !QQuickMultiPointHandler::wantsPointerEvent(event))
+ return; // see QQuickDragHandler::wantsPointerEvent; we don't want to handle those events
+
QQuickMultiPointHandler::handlePointerEventImpl(event);
event->setAccepted(true);
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index 97cb958aa6..6f66d0e426 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -145,7 +145,7 @@ void QQuickMultiPointHandler::onActiveChanged()
}
}
-void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDevice::GrabTransition transition, QPointerEvent *, QEventPoint &)
+void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
{
Q_D(QQuickMultiPointHandler);
// If another handler or item takes over this set of points, assume it has
@@ -154,6 +154,20 @@ void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QPointingDev
// (e.g. between DragHandler and PinchHandler).
if (transition == QPointingDevice::UngrabExclusive || transition == QPointingDevice::CancelGrabExclusive)
d->currentPoints.clear();
+ if (grabber != this)
+ return;
+ switch (transition) {
+ case QPointingDevice::GrabExclusive:
+ case QPointingDevice::GrabPassive:
+ case QPointingDevice::UngrabPassive:
+ case QPointingDevice::UngrabExclusive:
+ case QPointingDevice::CancelGrabPassive:
+ case QPointingDevice::CancelGrabExclusive:
+ QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
+ break;
+ case QPointingDevice::OverrideGrabPassive:
+ return; // don't emit
+ }
}
QVector<QEventPoint> QQuickMultiPointHandler::eligiblePoints(QPointerEvent *event)
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index fffcc2f848..68b5f2faed 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -85,7 +85,14 @@ Q_LOGGING_CATEGORY(lcPinchHandler, "qt.quick.handler.pinch")
\image touchpoints-pinchhandler.png
- \sa PinchArea
+ \note The pinch begins when the number of fingers pressed is between
+ \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and
+ \l {MultiPointHandler::maximumPointCount}{maximumPointCount}, inclusive.
+ Until then, PinchHandler tracks the positions of any pressed fingers,
+ but if it's a disallowed number, it does not scale or rotate
+ its \l target, and the \l active property remains \c false.
+
+ \sa PinchArea, QPointerEvent::pointCount()
*/
QQuickPinchHandler::QQuickPinchHandler(QQuickItem *parent)
@@ -209,19 +216,12 @@ bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event)
*/
/*!
- \qmlproperty int QtQuick::PinchHandler::minimumTouchPoints
-
- The pinch begins when this number of fingers are pressed.
- Until then, PinchHandler tracks the positions of any pressed fingers,
- but if it's an insufficient number, it does not scale or rotate
- its \l target, and the \l active property will remain false.
-*/
-
-/*!
\qmlproperty bool QtQuick::PinchHandler::active
- This property is true when all the constraints (epecially \l minimumTouchPoints)
- are satisfied and the \l target, if any, is being manipulated.
+ This property is \c true when all the constraints (epecially
+ \l {MultiPointHandler::minimumPointCount}{minimumPointCount} and
+ \l {MultiPointHandler::maximumPointCount}{maximumPointCount}) are satisfied
+ and the \l target, if any, is being manipulated.
*/
void QQuickPinchHandler::onActiveChanged()
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 11c29ee812..12b064a79b 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -302,7 +302,8 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointin
*/
void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab)
{
- qCDebug(lcPointerHandlerGrab) << point << grab;
+ qCDebug(lcPointerHandlerGrab) << this << point << grab << "via"
+ << QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(parentItem());
if (grab) {
event->addPassiveGrabber(point, this);
} else {
@@ -338,8 +339,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
{
Q_D(const QQuickPointerHandler);
bool allowed = false;
+ QObject* existingGrabber = event->exclusiveGrabber(point);
if (proposedGrabber == this) {
- QObject* existingGrabber = event->exclusiveGrabber(point);
allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
if (existingGrabber) {
if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
@@ -350,10 +351,17 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
existingPhGrabber->metaObject()->className() == metaObject()->className())
allowed = true;
} else if ((d->grabPermissions & CanTakeOverFromItems)) {
+ allowed = true;
QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
- if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && QQuickWindowPrivate::isMouseEvent(event)) ||
- (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) {
- allowed = true;
+ auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate()
+ : QQuickDeliveryAgentPrivate::currentEventDeliveryAgent ? static_cast<QQuickDeliveryAgentPrivate *>(
+ QQuickDeliveryAgentPrivate::get(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent)) : nullptr;
+ const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse());
+ if (existingItemGrabber &&
+ ((existingItemGrabber->keepMouseGrab() &&
+ (QQuickWindowPrivate::isMouseEvent(event) || isTouchMouse)) ||
+ (existingItemGrabber->keepTouchGrab() && QQuickWindowPrivate::isTouchEvent(event)))) {
+ allowed = false;
// If the handler wants to steal the exclusive grab from an Item, the Item can usually veto
// by having its keepMouseGrab flag set. But an exception is if that Item is a parent that
// normally filters events (such as a Flickable): it needs to be possible for e.g. a
@@ -362,15 +370,20 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
// at first and then expects to be able to steal the grab later on. It cannot respect
// Flickable's wishes in that case, because then it would never have a chance.
if (existingItemGrabber->keepMouseGrab() &&
- !(existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem()))) {
- auto da = QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate();
+ existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem())) {
Q_ASSERT(da);
- if (da->isDeliveringTouchAsMouse() && point.id() == da->touchMouseId) {
- qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point.id()
- << "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
- allowed = false;
+ if (isTouchMouse && point.id() == da->touchMouseId) {
+ qCDebug(lcPointerHandlerGrab) << this << "steals touchpoint" << point.id()
+ << "despite parent touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
+ allowed = true;
}
}
+ if (!allowed) {
+ qCDebug(lcPointerHandlerGrab) << this << "wants to grab point" << point.id()
+ << "but declines to steal from grabber" << existingItemGrabber
+ << "with keepMouseGrab=" << existingItemGrabber->keepMouseGrab()
+ << "keepTouchGrab=" << existingItemGrabber->keepTouchGrab();
+ }
}
}
}
@@ -394,7 +407,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
}
qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point.id() << "permission" <<
QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
- ':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber;
+ ':' << this << (allowed ? "approved from" : "denied from") <<
+ existingGrabber << "to" << proposedGrabber;
return allowed;
}
@@ -516,8 +530,11 @@ bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
{
if (QQuickItem *par = parentItem()) {
if (par->window()) {
+ QRect windowGeometry = par->window()->geometry();
+ if (!par->window()->isTopLevel())
+ windowGeometry = QRect(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
QPoint screenPosition = par->window()->mapToGlobal(scenePosition.toPoint());
- if (!par->window()->geometry().contains(screenPosition))
+ if (!windowGeometry.contains(screenPosition))
return false;
}
QPointF p = par->mapFromScene(scenePosition);
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 0a7cc7e075..6c6d491f3c 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -77,6 +77,8 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
button in order to cancel the click. For this use case, set the
\l gesturePolicy to \c TapHandler.ReleaseWithinBounds.
+ \snippet pointerHandlers/tapHandlerButton.qml 0
+
For multi-tap gestures (double-tap, triple-tap etc.), the distance moved
must not exceed QStyleHints::mouseDoubleClickDistance() with mouse and
QStyleHints::touchDoubleTapDistance() with touch, and the time between
@@ -214,6 +216,8 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
If the spatial constraint is violated, \l pressed transitions immediately
from true to false, regardless of the time held.
+ The \c gesturePolicy also affects grab behavior as described below.
+
\value TapHandler.DragThreshold
(the default value) The event point must not move significantly.
If the mouse, finger or stylus moves past the system-wide drag
@@ -222,11 +226,13 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
can be useful whenever TapHandler needs to cooperate with other
input handlers (for example \l DragHandler) or event-handling Items
(for example QtQuick Controls), because in this case TapHandler
- will not take the exclusive grab, but merely a passive grab.
+ will not take the exclusive grab, but merely a
+ \l {QPointerEvent::addPassiveGrabber()}{passive grab}.
\value TapHandler.WithinBounds
If the event point leaves the bounds of the \c parent Item, the tap
- gesture is canceled. The TapHandler will take the exclusive grab on
+ gesture is canceled. The TapHandler will take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on
press, but will release the grab as soon as the boundary constraint
is no longer satisfied.
@@ -237,8 +243,9 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
typical behavior for button widgets: you can cancel a click by
dragging outside the button, and you can also change your mind by
dragging back inside the button before release. Note that it's
- necessary for TapHandler take the exclusive grab on press and retain
- it until release in order to detect this gesture.
+ necessary for TapHandler to take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press
+ and retain it until release in order to detect this gesture.
*/
void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gesturePolicy)
{
diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp
index 7045f10d8e..51cb72032b 100644
--- a/src/quick/handlers/qquickwheelhandler.cpp
+++ b/src/quick/handlers/qquickwheelhandler.cpp
@@ -502,7 +502,7 @@ void QQuickWheelHandler::timerEvent(QTimerEvent *event)
}
/*!
- \qmlsignal QtQuick::WheelHandler::wheel(PointerScrollEvent event)
+ \qmlsignal QtQuick::WheelHandler::wheel(WheelEvent event)
This signal is emitted every time this handler receives an \a event
of type \l QWheelEvent: that is, every time the wheel is moved or the
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index e3f8acad00..18bfc66eee 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -371,7 +371,10 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
}
state.lineDash = pattern;
QPen nPen = p->pen();
- nPen.setDashPattern(pattern);
+ if (count > 0)
+ nPen.setDashPattern(pattern);
+ else
+ nPen.setStyle(Qt::SolidLine);
p->setPen(nPen);
break;
}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index e111f908d0..71a5e414f6 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -120,8 +120,15 @@ void QQuickContext2DTexture::setItem(QQuickCanvasItem* item)
bool QQuickContext2DTexture::setCanvasWindow(const QRect& r)
{
- qreal canvasDevicePixelRatio = (m_item && m_item->window()) ?
- m_item->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
+ bool ok = false;
+ static qreal overriddenDevicePixelRatio =
+ !qEnvironmentVariableIsEmpty("QT_CANVAS_OVERRIDE_DEVICEPIXELRATIO") ?
+ qgetenv("QT_CANVAS_OVERRIDE_DEVICEPIXELRATIO").toFloat(&ok) : 0.0;
+ qreal canvasDevicePixelRatio = overriddenDevicePixelRatio;
+ if (overriddenDevicePixelRatio == 0.0) {
+ canvasDevicePixelRatio = (m_item && m_item->window()) ?
+ m_item->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
+ }
if (!qFuzzyCompare(m_canvasDevicePixelRatio, canvasDevicePixelRatio)) {
qCDebug(lcCanvas, "%s device pixel ratio %.1lf -> %.1lf",
(m_item->objectName().isEmpty() ? "Canvas" : qPrintable(m_item->objectName())),
diff --git a/src/quick/items/qquickcolorgroup.cpp b/src/quick/items/qquickcolorgroup.cpp
index e2227e3197..c77207fee0 100644
--- a/src/quick/items/qquickcolorgroup.cpp
+++ b/src/quick/items/qquickcolorgroup.cpp
@@ -47,6 +47,8 @@
QT_BEGIN_NAMESPACE
/*!
+ \internal
+
\class QQuickColorGroup
\brief The QQuickColorGroup class represents a set of colors.
\inmodule QtQuick
diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index f8b4d91bda..7d3db1e7c2 100644
--- a/src/quick/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
@@ -91,6 +91,7 @@ QQuickDropAreaPrivate::~QQuickDropAreaPrivate()
/*!
\qmltype DropArea
\instantiates QQuickDropArea
+ \inherits Item
\inqmlmodule QtQuick
\ingroup qtquick-input
\brief For specifying drag and drop handling in an area.
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index b02840208d..2f511515f9 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1330,7 +1330,7 @@ void QQuickFlickablePrivate::handleMoveEvent(QPointerEvent *event)
{
Q_Q(QQuickFlickable);
if (!interactive || lastPosTime == -1 ||
- (event->isSinglePointEvent() && static_cast<QSinglePointEvent *>(event)->buttons() == Qt::NoButton))
+ (event->isSinglePointEvent() && !static_cast<QSinglePointEvent *>(event)->buttons().testFlag(Qt::LeftButton)))
return;
qint64 currentTimestamp = computeCurrentTime(event);
@@ -2629,8 +2629,18 @@ bool QQuickFlickable::filterPointerEvent(QQuickItem *receiver, QPointerEvent *ev
bool QQuickFlickable::childMouseEventFilter(QQuickItem *i, QEvent *e)
{
Q_D(QQuickFlickable);
+
+ auto wantsPointerEvent_helper = [=]() {
+ QPointerEvent *pe = static_cast<QPointerEvent *>(e);
+ QQuickDeliveryAgentPrivate::localizePointerEvent(pe, this);
+ const bool wants = d->wantsPointerEvent(pe);
+ // re-localize event back to \a i before returning
+ QQuickDeliveryAgentPrivate::localizePointerEvent(pe, i);
+ return wants;
+ };
+
if (!isVisible() || !isEnabled() || !isInteractive() ||
- (e->isPointerEvent() && !d->wantsPointerEvent(static_cast<QPointerEvent *>(e)))) {
+ (e->isPointerEvent() && !wantsPointerEvent_helper())) {
d->cancelInteraction();
return QQuickItem::childMouseEventFilter(i, e);
}
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index d704681d6a..de18df5fda 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -343,9 +343,9 @@ void QQuickImage::setFillMode(FillMode mode)
}
/*!
-
\qmlproperty real QtQuick::Image::paintedWidth
\qmlproperty real QtQuick::Image::paintedHeight
+ \readonly
These properties hold the size of the image that is actually painted.
In most cases it is the same as \c width and \c height, but when using an
@@ -367,6 +367,7 @@ qreal QQuickImage::paintedHeight() const
/*!
\qmlproperty enumeration QtQuick::Image::status
+ \readonly
This property holds the status of image loading. It can be one of:
\list
@@ -404,6 +405,7 @@ qreal QQuickImage::paintedHeight() const
/*!
\qmlproperty real QtQuick::Image::progress
+ \readonly
This property holds the progress of image loading, from 0.0 (nothing loaded)
to 1.0 (finished).
@@ -425,7 +427,7 @@ qreal QQuickImage::paintedHeight() const
*/
/*!
- \qmlproperty QSize QtQuick::Image::sourceSize
+ \qmlproperty size QtQuick::Image::sourceSize
This property holds the scaled width and height of the full-frame image.
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 750b71b25e..64c9d6abcf 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -56,8 +56,8 @@ QT_BEGIN_NAMESPACE
bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio)
{
// QQuickImageProvider and SVG and PDF can generate a high resolution image when
- // sourceSize is set (this function is only called if it's set).
- // If sourceSize is not set then the provider default size will be used, as usual.
+ // sourceSize is set. If sourceSize is not set then the provider default size will
+ // be used, as usual.
bool setDevicePixelRatio = false;
if (url.scheme() == QLatin1String("image")) {
setDevicePixelRatio = true;
@@ -419,10 +419,14 @@ void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value)
Q_D(QQuickImageBase);
// If the screen DPI changed, reload image.
if (change == ItemDevicePixelRatioHasChanged && value.realValue != d->devicePixelRatio) {
+ const auto oldDpr = d->devicePixelRatio;
// ### how can we get here with !qmlEngine(this)? that implies
// itemChange() on an item pending deletion, which seems strange.
if (qmlEngine(this) && isComponentComplete() && d->url.isValid()) {
load();
+ // not changed when loading (sourceSize might not be set)
+ if (d->devicePixelRatio == oldDpr)
+ d->updateDevicePixelRatio(value.realValue);
}
}
QQuickItem::itemChange(change, value);
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 464076cbf8..c7eac920cd 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -403,42 +403,42 @@ void QQuickItemKeyFilter::componentComplete()
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::left
+ \qmlattachedproperty Item QtQuick::KeyNavigation::left
This property holds the item to assign focus to
when the left cursor key is pressed.
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::right
+ \qmlattachedproperty Item QtQuick::KeyNavigation::right
This property holds the item to assign focus to
when the right cursor key is pressed.
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::up
+ \qmlattachedproperty Item QtQuick::KeyNavigation::up
This property holds the item to assign focus to
when the up cursor key is pressed.
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::down
+ \qmlattachedproperty Item QtQuick::KeyNavigation::down
This property holds the item to assign focus to
when the down cursor key is pressed.
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::tab
+ \qmlattachedproperty Item QtQuick::KeyNavigation::tab
This property holds the item to assign focus to
when the Tab key is pressed.
*/
/*!
- \qmlproperty Item QtQuick::KeyNavigation::backtab
+ \qmlattachedproperty Item QtQuick::KeyNavigation::backtab
This property holds the item to assign focus to
when the Shift+Tab key combination (Backtab) is pressed.
@@ -590,7 +590,7 @@ void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
}
/*!
- \qmlproperty enumeration QtQuick::KeyNavigation::priority
+ \qmlattachedproperty enumeration QtQuick::KeyNavigation::priority
This property determines whether the keys are processed before
or after the attached item's own key handling.
@@ -7985,22 +7985,64 @@ bool QQuickItem::contains(const QPointF &point) const
\qmlproperty QObject* QtQuick::Item::containmentMask
\since 5.11
This property holds an optional mask for the Item to be used in the
- QtQuick::Item::contains method.
- QtQuick::Item::contains main use is currently to determine whether
- an input event has landed into the item or not.
+ QtQuick::Item::contains() method. Its main use is currently to determine
+ whether a \l {QPointerEvent}{pointer event} has landed into the item or not.
By default the \l contains method will return true for any point
- within the Item's bounding box. \c containmentMask allows for a
- more fine-grained control. For example, the developer could
- define and use an AnotherItem element as containmentMask,
- which has a specialized contains method, like:
+ within the Item's bounding box. \c containmentMask allows for
+ more fine-grained control. For example, if a custom C++
+ QQuickItem subclass with a specialized contains() method
+ is used as containmentMask:
\code
Item { id: item; containmentMask: AnotherItem { id: anotherItem } }
\endcode
- \e{item}'s contains method would then return true only if
- \e{anotherItem}'s contains implementation returns true.
+ \e{item}'s contains method would then return \c true only if
+ \e{anotherItem}'s contains() implementation returns \c true.
+
+ A \l Shape can be used as a mask, to make an item react to
+ \l {QPointerEvent}{pointer events} only within a non-rectangular region:
+
+ \table
+ \row
+ \li \image containmentMask-shape.gif
+ \li \snippet qml/item/containmentMask-shape.qml 0
+ \endtable
+
+ It is also possible to define the contains method in QML. For example,
+ to create a circular item that only responds to events within its
+ actual bounds:
+
+ \table
+ \row
+ \li \image containmentMask-circle.gif
+ \li \snippet qml/item/containmentMask-circle-js.qml 0
+ \endtable
+
+ \sa {Qt Quick Examples - Shapes}
+*/
+/*!
+ \property QQuickItem::containmentMask
+ \since 5.11
+ This property holds an optional mask to be used in the contains() method,
+ which is mainly used for hit-testing each \l QPointerEvent.
+
+ By default, \l contains() will return \c true for any point
+ within the Item's bounding box. But any QQuickItem, or any QObject
+ that implements a function of the form
+ \code
+ Q_INVOKABLE bool contains(const QPointF &point) const;
+ \endcode
+ can be used as a mask, to defer hit-testing to that object.
+
+ \note contains() is called frequently during event delivery.
+ Deferring hit-testing to another object slows it down somewhat.
+ containmentMask() can cause performance problems if that object's
+ contains() method is not efficient. If you implement a custom
+ QQuickItem subclass, you can alternatively override contains().
+
+ \sa contains()
*/
QObject *QQuickItem::containmentMask() const
{
@@ -8178,6 +8220,12 @@ QPointF QQuickItem::mapFromScene(const QPointF &point) const
treated only as a hint. So, the resulting window position may differ from
what is expected.
+ \note If this item is in a subscene, e.g. mapped onto a 3D
+ \l [QtQuick3D QML] {Model}{Model} object, the UV mapping is incorporated
+ into this transformation, so that it really goes from screen coordinates to
+ this item's coordinates, as long as \a point is actually within this item's bounds.
+ The other mapping functions do not yet work that way.
+
\since 5.7
\sa {Concepts - Visual Coordinates in Qt Quick}
@@ -8185,7 +8233,12 @@ QPointF QQuickItem::mapFromScene(const QPointF &point) const
QPointF QQuickItem::mapFromGlobal(const QPointF &point) const
{
Q_D(const QQuickItem);
- return mapFromScene(d->globalToWindowTransform().map(point));
+ QPointF scenePoint = d->globalToWindowTransform().map(point);
+ if (auto da = QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(this)) {
+ if (auto sceneTransform = da->sceneTransform())
+ scenePoint = sceneTransform->map(scenePoint);
+ }
+ return mapFromScene(scenePoint);
}
/*!
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index caf5a17dc6..a660bd0ca3 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -84,11 +84,15 @@ QT_BEGIN_NAMESPACE
possible in a hardware accelerated manner, unlike the performance-wise limited
alternative of using QQuickWindow::grabWindow()
- When using a QQuickRenderControl, the QQuickWindow does not have to be shown
- or even created at all. This means there will not be an underlying native
- window for it. Instead, the QQuickWindow instance is associated with the
- render control, using the overload of the QQuickWindow constructor, and a
- texture or image object specified via QQuickWindow::setRenderTarget().
+ When using a QQuickRenderControl, the QQuickWindow must not be
+ \l{QWindow::show()}{shown} (it will not be visible on-screen) and there will
+ not be an underlying native window for it. Instead, the QQuickWindow instance
+ is associated with the render control object, using the overload of the
+ QQuickWindow constructor, and a texture or image object specified via
+ QQuickWindow::setRenderTarget(). The QQuickWindow object is still essential,
+ because it represents the Qt Quick scene and provides the bulk of the scene
+ management and event delivery mechanisms. It does not however act as a real
+ on-screen window from the windowing system's perspective.
Management of the graphics devices, contexts, image and texture objects is up
to the application. The device or context that will be used by Qt Quick must
@@ -130,6 +134,12 @@ QT_BEGIN_NAMESPACE
To send events, for example mouse or keyboard events, to the scene, use
QCoreApplication::sendEvent() with the QQuickWindow instance as the receiver.
+ For key events it may be also necessary to set the focus manually on the
+ desired item. In practice this involves calling
+ \l{QQuickItem::forceActiveFocus()}{forceActiveFocus()} on the desired item,
+ for example the scene's root item, once it is associated with the scene (the
+ QQuickWindow).
+
\note In general QQuickRenderControl is supported in combination with all Qt
Quick backends. However, some functionality, in particular grab(), may not be
available in all cases.
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 4f61d61309..b298ed74da 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -344,7 +344,6 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
d->refFromEffectItem(m_hideSource);
d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
- connect(m_sourceItem, SIGNAL(parentChanged(QQuickItem*)), this, SLOT(sourceItemParentChanged(QQuickItem*)));
} else {
qWarning("ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.");
m_sourceItem = nullptr;
@@ -364,13 +363,6 @@ void QQuickShaderEffectSource::sourceItemDestroyed(QObject *item)
}
-void QQuickShaderEffectSource::sourceItemParentChanged(QQuickItem *parent)
-{
- if (!parent && m_texture)
- m_texture->setItem(0);
-}
-
-
/*!
\qmlproperty rect QtQuick::ShaderEffectSource::sourceRect
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 921038e49a..fe419e5959 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -174,7 +174,6 @@ Q_SIGNALS:
private Q_SLOTS:
void sourceItemDestroyed(QObject *item);
void invalidateSceneGraph();
- void sourceItemParentChanged(QQuickItem *parent);
protected:
void releaseResources() override;
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index ddaa1979b6..a832f53e39 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -573,7 +573,7 @@ void QQuickParentChange::rewind()
The AnchorChanges type is used to modify the anchors of an item in a \l State.
AnchorChanges cannot be used to modify the margins on an item. For this, use
- PropertyChanges intead.
+ PropertyChanges instead.
In the following example we change the top and bottom anchors of an item
using AnchorChanges, and the top and bottom anchor margins using
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 63bedb9734..3f06684f25 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1105,43 +1105,61 @@ QQuickTableViewPrivate::RebuildOptions QQuickTableViewPrivate::checkForVisibilit
return RebuildOption::None;
}
- // Go through all columns from first to last, find the columns that used
- // to be hidden and not loaded, and check if they should become visible
- // (and vice versa). If there is a change, we need to rebuild.
RebuildOptions rebuildOptions = RebuildOption::None;
- for (int column = leftColumn(); column <= rightColumn(); ++column) {
- const bool wasVisibleFromBefore = loadedColumns.contains(column);
- const bool isVisibleNow = !qFuzzyIsNull(getColumnWidth(column));
- if (wasVisibleFromBefore == isVisibleNow)
- continue;
-
- // A column changed visibility. This means that it should
- // either be loaded or unloaded. So we need a rebuild.
- qCDebug(lcTableViewDelegateLifecycle) << "Column" << column << "changed visibility to" << isVisibleNow;
+ if (loadedTableOuterRect.x() == origin.x() && leftColumn() != 0) {
+ // Since the left column is at the origin of the viewport, but still not the first
+ // column in the model, we need to calculate a new left column since there might be
+ // columns in front of it that used to be hidden, but should now be visible (QTBUG-93264).
rebuildOptions.setFlag(RebuildOption::ViewportOnly);
- if (column == leftColumn()) {
- // The first loaded column should now be hidden. This means that we
- // need to calculate which column should now be first instead.
- rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftColumn);
+ rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftColumn);
+ } else {
+ // Go through all loaded columns from first to last, find the columns that used
+ // to be hidden and not loaded, and check if they should become visible
+ // (and vice versa). If there is a change, we need to rebuild.
+ for (int column = leftColumn(); column <= rightColumn(); ++column) {
+ const bool wasVisibleFromBefore = loadedColumns.contains(column);
+ const bool isVisibleNow = !qFuzzyIsNull(getColumnWidth(column));
+ if (wasVisibleFromBefore == isVisibleNow)
+ continue;
+
+ // A column changed visibility. This means that it should
+ // either be loaded or unloaded. So we need a rebuild.
+ qCDebug(lcTableViewDelegateLifecycle) << "Column" << column << "changed visibility to" << isVisibleNow;
+ rebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ if (column == leftColumn()) {
+ // The first loaded column should now be hidden. This means that we
+ // need to calculate which column should now be first instead.
+ rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftColumn);
+ }
+ break;
}
- break;
}
- // Go through all rows from first to last, and do the same as above
- for (int row = topRow(); row <= bottomRow(); ++row) {
- const bool wasVisibleFromBefore = loadedRows.contains(row);
- const bool isVisibleNow = !qFuzzyIsNull(getRowHeight(row));
- if (wasVisibleFromBefore == isVisibleNow)
- continue;
-
- // A row changed visibility. This means that it should
- // either be loaded or unloaded. So we need a rebuild.
- qCDebug(lcTableViewDelegateLifecycle) << "Row" << row << "changed visibility to" << isVisibleNow;
+ if (loadedTableOuterRect.y() == origin.y() && topRow() != 0) {
+ // Since the top row is at the origin of the viewport, but still not the first
+ // row in the model, we need to calculate a new top row since there might be
+ // rows in front of it that used to be hidden, but should now be visible (QTBUG-93264).
rebuildOptions.setFlag(RebuildOption::ViewportOnly);
- if (row == topRow())
- rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftRow);
- break;
+ rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftRow);
+ } else {
+ // Go through all loaded rows from first to last, find the rows that used
+ // to be hidden and not loaded, and check if they should become visible
+ // (and vice versa). If there is a change, we need to rebuild.
+ for (int row = topRow(); row <= bottomRow(); ++row) {
+ const bool wasVisibleFromBefore = loadedRows.contains(row);
+ const bool isVisibleNow = !qFuzzyIsNull(getRowHeight(row));
+ if (wasVisibleFromBefore == isVisibleNow)
+ continue;
+
+ // A row changed visibility. This means that it should
+ // either be loaded or unloaded. So we need a rebuild.
+ qCDebug(lcTableViewDelegateLifecycle) << "Row" << row << "changed visibility to" << isVisibleNow;
+ rebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ if (row == topRow())
+ rebuildOptions.setFlag(RebuildOption::CalculateNewTopLeftRow);
+ break;
+ }
}
return rebuildOptions;
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 10399b4e27..efb10bed48 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -2171,7 +2171,7 @@ void QQuickText::resetMaximumLineCount()
<img src="" align="top,middle,bottom" width="" height=""> - inline images
<ol type="">, <ul type=""> and <li> - ordered and unordered lists
<pre></pre> - preformatted
- &gt; &lt; &amp;
+ &gt; &lt; &amp; &quot; &nbsp; &apos;
\endcode
\c Text.StyledText parser is strict, requiring tags to be correctly nested.
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index a0281d1fb2..05343de702 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -819,11 +819,7 @@ void QQuickTextControl::setHtml(const QString &text)
void QQuickTextControlPrivate::keyReleaseEvent(QKeyEvent *e)
{
- if (e->key() == Qt::Key_Back) {
- e->ignore();
- return;
- }
- return;
+ e->ignore();
}
void QQuickTextControlPrivate::keyPressEvent(QKeyEvent *e)
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 0e62898d57..0aee8b2cb1 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -2359,6 +2359,14 @@ void QQuickTextEdit::q_textChanged()
d->determineHorizontalAlignment();
d->updateDefaultTextOption();
updateSize();
+
+ markDirtyNodesForRange(0, d->document->characterCount(), 0);
+ polish();
+ if (isComponentComplete()) {
+ d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
+ update();
+ }
+
emit textChanged();
}
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index ceeed1a839..ba40e8d3c7 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1584,7 +1584,7 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)
d->moveCursor(cursor, mark);
if (d->focusOnPress && !qGuiApp->styleHints()->setFocusOnTouchRelease())
- ensureActiveFocus();
+ ensureActiveFocus(Qt::MouseFocusReason);
event->setAccepted(true);
}
@@ -1636,7 +1636,7 @@ void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
#endif
if (d->focusOnPress && qGuiApp->styleHints()->setFocusOnTouchRelease())
- ensureActiveFocus();
+ ensureActiveFocus(Qt::MouseFocusReason);
if (!event->isAccepted())
QQuickImplicitSizeItem::mouseReleaseEvent(event);
@@ -1871,10 +1871,10 @@ void QQuickTextInput::invalidateFontCaches()
d->m_textLayout.engine()->resetFontEngineCache();
}
-void QQuickTextInput::ensureActiveFocus()
+void QQuickTextInput::ensureActiveFocus(Qt::FocusReason reason)
{
bool hadActiveFocus = hasActiveFocus();
- forceActiveFocus();
+ forceActiveFocus(reason);
#if QT_CONFIG(im)
Q_D(QQuickTextInput);
// re-open input panel on press if already focused
@@ -2104,7 +2104,7 @@ void QQuickTextInput::undo()
{
Q_D(QQuickTextInput);
if (!d->m_readOnly) {
- d->resetInputMethod();
+ d->cancelInput();
d->internalUndo();
d->finishChange(-1, true);
}
@@ -2120,7 +2120,7 @@ void QQuickTextInput::redo()
{
Q_D(QQuickTextInput);
if (!d->m_readOnly) {
- d->resetInputMethod();
+ d->cancelInput();
d->internalRedo();
d->finishChange();
}
@@ -2747,11 +2747,13 @@ void QQuickTextInputPrivate::init()
m_inputControl = new QInputControl(QInputControl::LineEdit, q);
}
-void QQuickTextInputPrivate::resetInputMethod()
+void QQuickTextInputPrivate::cancelInput()
{
+#if QT_CONFIG(im)
Q_Q(QQuickTextInput);
if (!m_readOnly && q->hasActiveFocus() && qGuiApp)
- QGuiApplication::inputMethod()->reset();
+ cancelPreedit();
+#endif // im
}
void QQuickTextInput::updateCursorRectangle(bool scroll)
@@ -4697,7 +4699,7 @@ void QQuickTextInput::ensureVisible(int position)
void QQuickTextInput::clear()
{
Q_D(QQuickTextInput);
- d->resetInputMethod();
+ d->cancelInput();
d->clear();
}
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index ee06eb88e7..031b4780db 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -362,7 +362,7 @@ Q_SIGNALS:
private:
void invalidateFontCaches();
- void ensureActiveFocus();
+ void ensureActiveFocus(Qt::FocusReason reason);
protected:
QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent = nullptr);
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index b4561556aa..1fecd7f9df 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -173,7 +173,7 @@ public:
}
void init();
- void resetInputMethod();
+ void cancelInput();
void startCreatingCursor();
void ensureVisible(int position, int preeditCursor = 0, int preeditLength = 0);
void updateHorizontalScroll();
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index dd666416e8..51bf2ca6be 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -266,11 +266,10 @@ void QQuickTextNodeEngine::processCurrentLine()
Q_ASSERT(sortedIndex < m_currentLineTree.size());
node = m_currentLineTree.data() + sortedIndex;
+ if (i == 0)
+ currentSelectionState = node->selectionState;
}
- if (i == 0)
- currentSelectionState = node->selectionState;
-
// Update decorations
if (currentDecorations != Decoration::NoDecoration) {
decorationRect.setY(m_position.y() + m_currentLine.y());
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 6d602a3810..d9ae003504 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -436,12 +436,13 @@ void QQuickWindow::physicalDpiChanged()
void QQuickWindow::handleScreenChanged(QScreen *screen)
{
Q_D(QQuickWindow);
+ // we connected to the initial screen in QQuickWindowPrivate::init, but the screen changed
disconnect(d->physicalDpiChangedConnection);
if (screen) {
physicalDpiChanged();
// When physical DPI changes on the same screen, either the resolution or the device pixel
// ratio changed. We must check what it is. Device pixel ratio does not have its own
- // ...Changed() signal.
+ // ...Changed() signal. Reconnect, same as in QQuickWindowPrivate::init.
d->physicalDpiChangedConnection = connect(screen, &QScreen::physicalDotsPerInchChanged,
this, &QQuickWindow::physicalDpiChanged);
}
@@ -764,8 +765,13 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
Q_ASSERT(windowManager || renderControl);
- if (QScreen *screen = q->screen())
- devicePixelRatio = screen->devicePixelRatio();
+ if (QScreen *screen = q->screen()) {
+ devicePixelRatio = screen->devicePixelRatio();
+ // if the screen changes, then QQuickWindow::handleScreenChanged disconnects
+ // and connects to the new screen
+ physicalDpiChangedConnection = QObject::connect(screen, &QScreen::physicalDotsPerInchChanged,
+ q, &QQuickWindow::physicalDpiChanged);
+ }
QSGContext *sg;
if (renderControl) {
@@ -869,16 +875,16 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
/*!
\qmltype Window
\instantiates QQuickWindow
- \inqmlmodule QtQuick.Window
+ \inqmlmodule QtQuick
\ingroup qtquick-visual
\brief Creates a new top-level window.
The Window object creates a new top-level window for a Qt Quick scene. It automatically sets up the
- window for use with \c {QtQuick 2.x} graphical types.
+ window for use with \c {QtQuick} graphical types.
To use this type, you will need to import the module with the following line:
\code
- import QtQuick.Window 2.2
+ import QtQuick
\endcode
Omitting this import will allow you to have a QML environment without
@@ -1370,7 +1376,12 @@ bool QQuickWindow::event(QEvent *e)
if (danpit == deliveryAgentsNeedingPoints.end()) {
deliveryAgentsNeedingPoints.insert(ptda, QList<QEventPoint>() << pt);
} else {
- danpit.value().append(pt);
+ auto &ptList = danpit.value();
+ auto ptid = pt.id();
+ auto alreadyThere = std::find_if(ptList.constBegin(), ptList.constEnd(),
+ [ptid] (const QEventPoint &pep) { return pep.id() == ptid; });
+ if (alreadyThere == ptList.constEnd())
+ danpit.value().append(pt);
}
};
@@ -1425,8 +1436,6 @@ bool QQuickWindow::event(QEvent *e)
qCDebug(lcPtr) << daAndPoints.first << "shall now receive" << pe;
ret = daAndPoints.first->event(pe) || ret;
}
- if (pe->isAccepted())
- break;
}
if (ret)
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp
index 2df9c50898..fd448ee3a2 100644
--- a/src/quick/scenegraph/qsgdefaultcontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp
@@ -298,14 +298,11 @@ void *QSGDefaultContext::getResource(QQuickWindow *window, Resource resource) co
QQuickWindowPrivate::get(window)->context);
QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
- switch (resource) {
#if QT_CONFIG(vulkan)
- case VulkanInstanceResource:
+ if (resource == VulkanInstanceResource)
return window->vulkanInstance();
#endif
- default:
- return const_cast<void *>(rhiSupport->rifResource(resource, rc, window));
- }
+ return const_cast<void *>(rhiSupport->rifResource(resource, rc, window));
}
QSGRendererInterface::ShaderType QSGDefaultContext::shaderType() const
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 8ac112b106..5028370bd4 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -43,6 +43,10 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcSgText, "qt.scenegraph.text")
+
+qint64 QSGDistanceFieldGlyphNode::m_totalAllocation = 0;
+
QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGRenderContext *context)
: m_glyphNodeType(RootGlyphNode)
, m_context(context)
@@ -135,6 +139,7 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
const QVector<quint32> glyphIndexes = m_glyphs.glyphIndexes();
for (int i = 0; i < glyphIndexes.count(); ++i)
m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
+ qCDebug(lcSgText, "inserting %lld glyphs, %lld unique", glyphIndexes.count(), m_allGlyphIndexesLookup.count());
}
void QSGDistanceFieldGlyphNode::setStyle(QQuickText::TextStyle style)
@@ -198,8 +203,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
QSGGeometry *g = geometry();
Q_ASSERT(g->indexType() == QSGGeometry::UnsignedShortType);
-
- QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo> glyphsInOtherTextures;
+ m_glyphsInOtherTextures.clear();
const QVector<quint32> indexes = m_glyphs.glyphIndexes();
const QVector<QPointF> positions = m_glyphs.positions();
@@ -208,9 +212,12 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
// The template parameters here are assuming that most strings are short, 64
// characters or less.
QVarLengthArray<QSGGeometry::TexturedPoint2D, 256> vp;
- vp.reserve(indexes.size() * 4);
QVarLengthArray<ushort, 384> ip;
- ip.reserve(indexes.size() * 6);
+ const qsizetype maxIndexCount = (std::numeric_limits<quint16>::max() - 1) / 4; // 16383 (see below: 0xFFFF is not allowed)
+ const qsizetype maxVertexCount = maxIndexCount * 4; // 65532
+ const auto likelyGlyphCount = qMin(indexes.size(), maxIndexCount);
+ vp.reserve(likelyGlyphCount * 4);
+ ip.reserve(likelyGlyphCount * 6);
qreal maxTexMargin = m_glyph_cache->distanceFieldRadius();
qreal fontScale = m_glyph_cache->fontScale(fontPixelSize);
@@ -236,15 +243,20 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
// As we use UNSIGNED_SHORT indexing in the geometry, we overload the
// "glyphsInOtherTextures" concept as overflow for if there are more
- // than 65535 vertices to render which would otherwise exceed the
+ // than 65532 vertices to render, which would otherwise exceed the
// maximum index size. (leave 0xFFFF unused in order not to clash with
- // primitive restart) This will cause sub-nodes to be recursively
- // created to handle any number of glyphs.
- if (m_texture != texture || vp.size() >= 65535) {
- if (texture->texture) {
- GlyphInfo &glyphInfo = glyphsInOtherTextures[texture];
+ // primitive restart) This will cause sub-nodes to be
+ // created to handle any number of glyphs. But only the RootGlyphNode
+ // needs to do this classification; from the perspective of a SubGlyphNode,
+ // it's already done, and m_glyphs contains only pointers to ranges of
+ // indices and positions that the RootGlyphNode is storing.
+ if (m_texture != texture || vp.size() >= maxVertexCount) {
+ if (m_glyphNodeType == RootGlyphNode && texture->texture) {
+ GlyphInfo &glyphInfo = m_glyphsInOtherTextures[texture];
glyphInfo.indexes.append(glyphIndex);
glyphInfo.positions.append(position);
+ } else if (vp.size() >= maxVertexCount && m_glyphNodeType == SubGlyphNode) {
+ break; // out of this loop over indices, because we won't add any more vertices
}
continue;
}
@@ -303,26 +315,40 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
ip.append(o + 0);
}
- QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = glyphsInOtherTextures.constBegin();
- while (ite != glyphsInOtherTextures.constEnd()) {
- QGlyphRun subNodeGlyphRun(m_glyphs);
- subNodeGlyphRun.setGlyphIndexes(ite->indexes);
- subNodeGlyphRun.setPositions(ite->positions);
-
- QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_context);
- subNode->setGlyphNodeType(SubGlyphNode);
- subNode->setColor(m_color);
- subNode->setStyle(m_style);
- subNode->setStyleColor(m_styleColor);
- subNode->setPreferredAntialiasingMode(m_antialiasingMode);
- subNode->setGlyphs(m_originalPosition, subNodeGlyphRun);
- subNode->update();
- subNode->updateGeometry(); // we have to explicitly call this now as preprocess won't be called before it's rendered
- appendChildNode(subNode);
-
- ++ite;
+ int subnodeCount = 0;
+ if (m_glyphNodeType == SubGlyphNode) {
+ Q_ASSERT(m_glyphsInOtherTextures.isEmpty());
+ } else {
+ if (!m_glyphsInOtherTextures.isEmpty())
+ qCDebug(lcSgText, "%lld 'other' textures", m_glyphsInOtherTextures.count());
+ QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = m_glyphsInOtherTextures.constBegin();
+ while (ite != m_glyphsInOtherTextures.constEnd()) {
+ QGlyphRun subNodeGlyphRun(m_glyphs);
+ for (int i = 0; i < ite->indexes.count(); i += maxIndexCount) {
+ int len = qMin(maxIndexCount, ite->indexes.count() - i);
+ subNodeGlyphRun.setRawData(ite->indexes.constData() + i, ite->positions.constData() + i, len);
+ qCDebug(lcSgText) << "subNodeGlyphRun has" << len << "positions:"
+ << *(ite->positions.constData() + i) << "->" << *(ite->positions.constData() + i + len - 1);
+
+ QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_context);
+ subNode->setGlyphNodeType(SubGlyphNode);
+ subNode->setColor(m_color);
+ subNode->setStyle(m_style);
+ subNode->setStyleColor(m_styleColor);
+ subNode->setPreferredAntialiasingMode(m_antialiasingMode);
+ subNode->setGlyphs(m_originalPosition, subNodeGlyphRun);
+ subNode->update();
+ subNode->updateGeometry(); // we have to explicitly call this now as preprocess won't be called before it's rendered
+ appendChildNode(subNode);
+ ++subnodeCount;
+ }
+ ++ite;
+ }
}
+ m_totalAllocation += vp.size() * sizeof(QSGGeometry::TexturedPoint2D) + ip.size() * sizeof(quint16);
+ qCDebug(lcSgText) << "allocating for" << vp.size() << "vtx (reserved" << likelyGlyphCount * 4 << "):" << vp.size() * sizeof(QSGGeometry::TexturedPoint2D)
+ << "bytes;" << ip.size() << "idx:" << ip.size() * sizeof(quint16) << "bytes; total bytes so far" << m_totalAllocation;
g->allocate(vp.size(), ip.size());
memcpy(g->vertexDataAsTexturedPoint2D(), vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
memcpy(g->indexDataAsUShort(), ip.constData(), ip.size() * sizeof(quint16));
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index 2b2975ccb3..e7655f502d 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -115,9 +115,13 @@ private:
QVector<QPointF> positions;
};
QSet<quint32> m_allGlyphIndexesLookup;
+ // m_glyphs holds pointers to the GlyphInfo.indexes and positions arrays, so we need to hold on to them
+ QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo> m_glyphsInOtherTextures;
uint m_dirtyGeometry: 1;
uint m_dirtyMaterial: 1;
+
+ static qint64 m_totalAllocation; // all SG glyph vertices and indices; only for qCDebug metrics
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 077814b1f4..2ee8040448 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -357,10 +357,6 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
rhi->makeThreadLocalNativeContextCurrent();
}
-#if QT_CONFIG(quick_shadereffect)
- QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
-#endif
-
if (d->swapchain) {
if (window->handle()) {
// We get here when exiting via QCoreApplication::quit() instead of
@@ -373,6 +369,11 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
}
d->cleanupNodesOnShutdown();
+
+#if QT_CONFIG(quick_shadereffect)
+ QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
+#endif
+
if (m_windows.size() == 0) {
rc->invalidate();
d->rhi = nullptr;
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 8a0202ede9..3a49002c12 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -525,13 +525,12 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window);
-#if QT_CONFIG(quick_shadereffect)
- QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
-#endif
-
// The canvas nodes must be cleaned up regardless if we are in the destructor..
if (wipeSG) {
dd->cleanupNodesOnShutdown();
+#if QT_CONFIG(quick_shadereffect)
+ QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
+#endif
} else {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent SG, avoiding cleanup");
return;
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
index d97d48c78d..fc1b3aec24 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
@@ -206,13 +206,11 @@ void QSGDefaultPainterNode::updateRenderTarget()
m_image = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied);
m_image.fill(Qt::transparent);
- QSGPainterTexture *texture = new QSGPainterTexture;
- texture->setOwnsTexture(true);
- texture->setTextureSize(m_textureSize);
- if (m_texture)
- delete m_texture;
-
- m_texture = texture;
+ if (!m_texture) {
+ m_texture = new QSGPainterTexture;
+ m_texture->setOwnsTexture(true);
+ }
+ m_texture->setTextureSize(m_textureSize);
}
void QSGDefaultPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target)
diff --git a/src/quick/scenegraph/util/qsgplaintexture.cpp b/src/quick/scenegraph/util/qsgplaintexture.cpp
index 6e59f9e607..ad6bfd450d 100644
--- a/src/quick/scenegraph/util/qsgplaintexture.cpp
+++ b/src/quick/scenegraph/util/qsgplaintexture.cpp
@@ -231,7 +231,12 @@ void QSGPlainTexture::commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch
}
}
- bool needsRebuild = m_texture && m_texture->pixelSize() != m_texture_size;
+ bool needsRebuild = false;
+
+ if (m_texture && m_texture->pixelSize() != m_texture_size) {
+ m_texture->setPixelSize(m_texture_size);
+ needsRebuild = true;
+ }
if (mipmappingChanged) {
QRhiTexture::Flags f = m_texture->flags();
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index a38ac410d4..10ce45e2cf 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -626,6 +626,21 @@ void QQuickDeliveryAgentPrivate::updateFocusItemTransform()
}
/*! \internal
+ If called during event delivery, returns the agent that is delivering the
+ event, without checking whether \a item is reachable from there.
+ Otherwise returns QQuickItemPrivate::deliveryAgent() (the delivery agent for
+ the narrowest subscene containing \a item), or \c null if \a item is \c null.
+*/
+QQuickDeliveryAgent *QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(const QQuickItem *item)
+{
+ if (currentEventDeliveryAgent)
+ return currentEventDeliveryAgent;
+ if (item)
+ return QQuickItemPrivate::get(const_cast<QQuickItem *>(item))->deliveryAgent();
+ return nullptr;
+}
+
+/*! \internal
QQuickDeliveryAgent delivers events to a tree of Qt Quick Items, beginning
with the given root item, which is usually QQuickWindow::rootItem() but
may alternatively be embedded into a Qt Quick 3D scene or something else.
@@ -650,8 +665,20 @@ QQuickItem *QQuickDeliveryAgent::rootItem() const
}
/*! \internal
+ Returns the object that was set in setSceneTransform(): a functor that
+ transforms from scene coordinates in the parent scene to scene coordinates
+ within this DA's subscene, or \c null if none was set.
+*/
+QQuickDeliveryAgent::Transform *QQuickDeliveryAgent::sceneTransform() const
+{
+ Q_D(const QQuickDeliveryAgent);
+ return d->sceneTransform;
+}
+
+/*! \internal
QQuickDeliveryAgent takes ownership of the given \a transform, which
- encapsulates the ability to transform viewport coordinates to rootItem coordinates.
+ encapsulates the ability to transform parent scene coordinates to rootItem
+ (subscene) coordinates.
*/
void QQuickDeliveryAgent::setSceneTransform(QQuickDeliveryAgent::Transform *transform)
{
@@ -904,12 +931,16 @@ bool QQuickDeliveryAgentPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *i
Qt::KeyboardModifiers modifiers, ulong timestamp,
bool accepted)
{
- const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
-
- //create copy of event
+ auto itemPrivate = QQuickItemPrivate::get(item);
+ const QTransform transform = itemPrivate->windowToItemTransform();
QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
hoverEvent.setTimestamp(timestamp);
hoverEvent.setAccepted(accepted);
+ const QTransform transformToGlobal = itemPrivate->windowToGlobalTransform();
+ QMutableEventPoint &point = QMutableEventPoint::from(hoverEvent.point(0));
+ point.setScenePosition(scenePos);
+ point.setGlobalPosition(transformToGlobal.map(scenePos));
+ point.setGlobalLastPosition(transformToGlobal.map(lastScenePos));
hasFiltered.clear();
if (sendFilteredMouseEvent(&hoverEvent, item, item->parentItem()))
@@ -1339,10 +1370,10 @@ void QQuickDeliveryAgentPrivate::handleMouseEvent(QMouseEvent *event)
#if QT_CONFIG(cursor)
QQuickWindowPrivate::get(rootItem->window())->updateCursor(event->scenePosition());
#endif
+ const QPointF last = lastMousePosition.isNull() ? event->scenePosition() : lastMousePosition;
+ lastMousePosition = event->scenePosition();
+ qCDebug(lcHoverTrace) << q << "mouse pos" << last << "->" << lastMousePosition;
if (!event->points().count() || !event->exclusiveGrabber(event->point(0))) {
- QPointF last = lastMousePosition.isNull() ? event->scenePosition() : lastMousePosition;
- lastMousePosition = event->scenePosition();
- qCDebug(lcHoverTrace) << q << "mouse pos" << last << "->" << lastMousePosition << event;
bool accepted = event->isAccepted();
bool delivered = deliverHoverEvent(rootItem, event->scenePosition(), last, event->modifiers(), event->timestamp(), accepted);
if (!delivered) {
@@ -1386,7 +1417,7 @@ void QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents(QQuickWindow *win)
if (frameSynchronousHoverEnabled && !win->mouseGrabberItem() &&
!lastMousePosition.isNull() && QQuickWindowPrivate::get(win)->dirtyItemList) {
bool accepted = false;
- qCDebug(lcHoverTrace) << q << "delivering frame-sync hover to root";
+ qCDebug(lcHoverTrace) << q << "delivering frame-sync hover to root @" << lastMousePosition;
bool delivered = deliverHoverEvent(rootItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
if (!delivered)
clearHover(); // take care of any exits
@@ -1493,10 +1524,12 @@ void QQuickDeliveryAgentPrivate::onGrabChanged(QObject *grabber, QPointingDevice
void QQuickDeliveryAgentPrivate::ensureDeviceConnected(const QPointingDevice *dev)
{
+ Q_Q(QQuickDeliveryAgent);
if (knownPointingDevices.contains(dev))
return;
knownPointingDevices.append(dev);
connect(dev, &QPointingDevice::grabChanged, this, &QQuickDeliveryAgentPrivate::onGrabChanged);
+ QObject::connect(dev, &QObject::destroyed, q, [this, dev] {this->knownPointingDevices.removeAll(dev);});
}
void QQuickDeliveryAgentPrivate::deliverPointerEvent(QPointerEvent *event)
diff --git a/src/quick/util/qquickdeliveryagent_p.h b/src/quick/util/qquickdeliveryagent_p.h
index 9b73d9b9b9..df8c97b368 100644
--- a/src/quick/util/qquickdeliveryagent_p.h
+++ b/src/quick/util/qquickdeliveryagent_p.h
@@ -81,6 +81,7 @@ public:
QQuickItem *rootItem() const;
+ Transform *sceneTransform() const;
void setSceneTransform(Transform *transform);
bool event(QEvent *ev) override;
diff --git a/src/quick/util/qquickdeliveryagent_p_p.h b/src/quick/util/qquickdeliveryagent_p_p.h
index ad1eece36e..f931cfd70b 100644
--- a/src/quick/util/qquickdeliveryagent_p_p.h
+++ b/src/quick/util/qquickdeliveryagent_p_p.h
@@ -121,6 +121,7 @@ public:
static bool subsceneAgentsExist;
// QQuickDeliveryAgent::event() sets this to the one that's currently (trying to) handle the event
static QQuickDeliveryAgent *currentEventDeliveryAgent;
+ static QQuickDeliveryAgent *currentOrItemDeliveryAgent(const QQuickItem *item);
Qt::FocusReason lastFocusReason = Qt::OtherFocusReason;
int pointerEventRecursionGuard = 0;
diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp
index d967721b64..96f5ce4d57 100644
--- a/src/quick/util/qquickstyledtext.cpp
+++ b/src/quick/util/qquickstyledtext.cpp
@@ -46,6 +46,8 @@
#include "qquickstyledtext_p.h"
#include <QQmlContext>
+Q_LOGGING_CATEGORY(lcStyledText, "qt.quick.styledtext")
+
/*
QQuickStyledText supports few tags:
@@ -562,10 +564,14 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI
textOut += QChar(60);
else if (entity == QLatin1String("amp"))
textOut += QChar(38);
+ else if (entity == QLatin1String("apos"))
+ textOut += QChar(39);
else if (entity == QLatin1String("quot"))
textOut += QChar(34);
else if (entity == QLatin1String("nbsp"))
textOut += QChar(QChar::Nbsp);
+ else
+ qCWarning(lcStyledText) << "StyledText doesn't support entity" << entity;
return;
} else if (*ch == QLatin1Char(' ')) {
auto entity = QStringView(textIn).mid(entityStart - 1, entityLength + 1);