aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2017-09-22 11:46:36 -0500
committerShawn Rutledge <shawn.rutledge@qt.io>2018-01-25 16:22:51 +0000
commitbf74a908cb0591c2adc024a6f93d566c7348c125 (patch)
tree71e749e71e8dcd4b159303526e7343dcd968e920 /src/quick/items
parentf6222f825831202c084835412a3c217a9420cad7 (diff)
Support masking of QQuickItems
Adding a new property, containsMask, to QQuickItem, that can be set to any QObject defining a Q_INVOKABLE bool contains(const QPointF &point). When this property is set, the mask object contains method is used in place of the item own contains method. [ChangeLog][QtQuick][QQuickItem] Added containsMask property. Task-number: QTBUG-20524 Change-Id: I5b0696e2cddc6ae3e217ce149c5f44980fdb69aa Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickitem.cpp72
-rw-r--r--src/quick/items/qquickitem.h4
-rw-r--r--src/quick/items/qquickitem_p.h7
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickmousearea_p_p.h2
5 files changed, 83 insertions, 3 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f1f6f97356..f4d11e32bd 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -7568,9 +7568,75 @@ void QQuickItem::setKeepTouchGrab(bool keep)
bool QQuickItem::contains(const QPointF &point) const
{
Q_D(const QQuickItem);
- qreal x = point.x();
- qreal y = point.y();
- return x >= 0 && y >= 0 && x <= d->width && y <= d->height;
+ if (d->mask) {
+ bool res = false;
+ d->extra->maskContains.invoke(d->mask,
+ Qt::DirectConnection,
+ Q_RETURN_ARG(bool, res),
+ Q_ARG(QPointF, point));
+ return res;
+ } else {
+ qreal x = point.x();
+ qreal y = point.y();
+ return x >= 0 && y >= 0 && x <= d->width && y <= d->height;
+ }
+}
+
+/*!
+ \qmlproperty QObject * QtQuick::Item::containsMask
+ \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.
+
+ By default the \l contains method will return true for any point
+ within the Item's bounding box. \c containsMask allows for a
+ more fine-grained control. For example, the developer could
+ define and use an AnotherItem element as containsMask,
+ which has a specialized contains method, like:
+
+ \code
+ Item { id: item; containsMask: AnotherItem { id: anotherItem } }
+ \endcode
+
+ \e{item}'s contains method would then return true only if
+ \e{anotherItem}'s contains implementation returns true.
+*/
+QObject *QQuickItem::containsMask() const
+{
+ Q_D(const QQuickItem);
+ return d->mask.data();
+}
+
+void QQuickItem::setContainsMask(QObject *mask)
+{
+ Q_D(QQuickItem);
+ // an Item can't mask itself (to prevent infinite loop in contains())
+ if (d->mask.data() == mask || mask == static_cast<QObject *>(this))
+ return;
+
+ QQuickItem *quickMask = qobject_cast<QQuickItem *>(d->mask);
+ if (quickMask) {
+ QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
+ maskPrivate->registerAsContainsMask(this, false); // removed from use as my mask
+ }
+
+ if (mask) {
+ int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)"));
+ if (methodIndex < 0) {
+ qmlWarning(this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it.");
+ return;
+ }
+ d->extra.value().maskContains = mask->metaObject()->method(methodIndex);
+ }
+ d->mask = mask;
+ quickMask = qobject_cast<QQuickItem *>(mask);
+ if (quickMask) {
+ QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
+ maskPrivate->registerAsContainsMask(this, true); // telling maskPrivate that "this" is using it as mask
+ }
+ emit containsMaskChanged();
}
/*!
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index f6ee54e94d..e38c276b9f 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -144,6 +144,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing)
Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged)
Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged)
+ Q_PROPERTY(QObject *containsMask READ containsMask WRITE setContainsMask NOTIFY containsMaskChanged REVISION 11)
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL)
@@ -320,6 +321,8 @@ public:
QSharedPointer<QQuickItemGrabResult> grabToImage(const QSize &targetSize = QSize());
Q_INVOKABLE virtual bool contains(const QPointF &point) const;
+ QObject *containsMask() const;
+ void setContainsMask(QObject *mask);
QTransform itemTransform(QQuickItem *, bool *) const;
QPointF mapToItem(const QQuickItem *item, const QPointF &point) const;
@@ -390,6 +393,7 @@ Q_SIGNALS:
void zChanged();
void implicitWidthChanged();
void implicitHeightChanged();
+ Q_REVISION(11) void containsMaskChanged();
protected:
bool event(QEvent *) override;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 9ed5286f22..0c02c66ef2 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -368,6 +368,9 @@ public:
QQuickDefaultClipNode *clipNode;
QSGRootNode *rootNode;
+ // Mask contains() method
+ QMetaMethod maskContains;
+
QObjectList resourcesList;
// Although acceptedMouseButtons is inside ExtraData, we actually store
@@ -382,6 +385,10 @@ public:
// 26 bits padding
};
QLazilyAllocated<ExtraData> extra;
+ // Contains mask
+ QPointer<QObject> mask;
+ // If the mask is an Item, inform it that it's being used as a mask (true) or is no longer being used (false)
+ virtual void registerAsContainsMask(QQuickItem * /* maskedItem */, bool /* set */) { }
QQuickAnchors *anchors() const;
mutable QQuickAnchors *_anchors;
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 4839b4dd4f..f03942ecee 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -415,6 +415,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
#if QT_CONFIG(quick_animatedimage)
qmlRegisterType<QQuickAnimatedImage, 11>(uri, 2, 11,"AnimatedImage");
#endif
+ qmlRegisterType<QQuickItem, 11>(uri, 2, 11,"Item");
}
static void initResources()
diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h
index 34cda9e193..0dd2690d43 100644
--- a/src/quick/items/qquickmousearea_p_p.h
+++ b/src/quick/items/qquickmousearea_p_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
class QQuickMouseEvent;
class QQuickMouseArea;
+class QQuickPointerMask;
class QQuickMouseAreaPrivate : public QQuickItemPrivate
{
Q_DECLARE_PUBLIC(QQuickMouseArea)
@@ -99,6 +100,7 @@ public:
#if QT_CONFIG(draganddrop)
QQuickDrag *drag;
#endif
+ QPointer<QQuickPointerMask> mask;
QPointF startScene;
QPointF targetStartPos;
QPointF lastPos;