aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2016-08-08 17:09:15 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2016-08-23 20:49:05 +0000
commit8a06075f48ad352acfc70111682e7decf8fedb33 (patch)
tree1d241486b9eced82f0a7c15cd815fc6e10674dbf /src
parenta0cb20c08db13003f7b8adc2f02fdcadf96fb8d1 (diff)
QQuickEventPoint::grabber: allow grabbing either an item or a handler
QQuickPointerHandler and QQuickItem have only QObject in common. Change-Id: I8fb68cc1779f42049db1e0eb5ff60019a1c674d3 Reviewed-by: Jan Arve Sæther <jan-arve.saether@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp7
-rw-r--r--src/quick/items/qquickevents.cpp56
-rw-r--r--src/quick/items/qquickevents_p_p.h24
-rw-r--r--src/quick/items/qquickwindow.cpp69
-rw-r--r--src/quick/items/qquickwindow_p.h2
5 files changed, 101 insertions, 57 deletions
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 293eae914e..038e7f2571 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -64,11 +64,10 @@ QQuickPointerHandler::QQuickPointerHandler(QObject *parent)
void QQuickPointerHandler::setGrab(QQuickEventPoint *point, bool grab)
{
- // TODO eventually the handler itself should be the grabber, instead of the target Item
if (grab)
- point->setGrabber(m_target);
- else if (point->grabber() == m_target)
- point->setGrabber(nullptr);
+ point->setPointerHandlerGrabber(this);
+ else if (point->pointerHandlerGrabber() == this)
+ point->setPointerHandlerGrabber(nullptr);
}
QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 7e84d27836..e8f333f953 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -40,12 +40,14 @@
#include "qquickevents_p_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickwindow_p.h>
#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events")
+Q_DECLARE_LOGGING_CATEGORY(lcPointerHandlerDispatch)
/*!
\qmltype KeyEvent
@@ -525,14 +527,40 @@ void QQuickEventPoint::reset(Qt::TouchPointState state, QPointF scenePos, quint6
m_velocity = velocity;
}
-QQuickItem *QQuickEventPoint::grabber() const
+QObject *QQuickEventPoint::grabber() const
{
return m_grabber.data();
}
-void QQuickEventPoint::setGrabber(QQuickItem *grabber)
+void QQuickEventPoint::setGrabber(QObject *grabber)
{
- m_grabber = QPointer<QQuickItem>(grabber);
+ qCDebug(lcPointerHandlerDispatch) << this << grabber;
+ m_grabber = QPointer<QObject>(grabber);
+ m_grabberIsHandler = (qmlobject_cast<QQuickPointerHandler *>(grabber) != nullptr);
+}
+
+QQuickItem *QQuickEventPoint::itemGrabber() const
+{
+ return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_grabber.data()));
+}
+
+void QQuickEventPoint::setItemGrabber(QQuickItem *grabber)
+{
+ qCDebug(lcPointerHandlerDispatch) << this << grabber;
+ m_grabber = QPointer<QObject>(grabber);
+ m_grabberIsHandler = false;
+}
+
+QQuickPointerHandler *QQuickEventPoint::pointerHandlerGrabber() const
+{
+ return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_grabber.data()) : nullptr);
+}
+
+void QQuickEventPoint::setPointerHandlerGrabber(QQuickPointerHandler *grabber)
+{
+ qCDebug(lcPointerHandlerDispatch) << this << grabber;
+ m_grabber = QPointer<QObject>(grabber);
+ m_grabberIsHandler = true;
}
void QQuickEventPoint::setAccepted(bool accepted)
@@ -620,11 +648,11 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
m_touchPoints.insert(i, new QQuickEventTouchPoint(this));
// Make sure the grabbers are right from one event to the next
- QVector<QQuickItem*> grabbers;
+ QVector<QObject*> grabbers;
// Copy all grabbers, because the order of points might have changed in the event.
// The ID is all that we can rely on (release might remove the first point etc).
for (int i = 0; i < newPointCount; ++i) {
- QQuickItem *grabber = nullptr;
+ QObject *grabber = nullptr;
if (auto point = pointById(tps.at(i).id()))
grabber = point->grabber();
grabbers.append(grabber);
@@ -636,7 +664,7 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
if (point->state() == QQuickEventPoint::Pressed) {
if (grabbers.at(i))
qWarning() << "TouchPointPressed without previous release event" << point;
- point->setGrabber(nullptr);
+ point->setItemGrabber(nullptr);
} else {
point->setGrabber(grabbers.at(i));
}
@@ -659,7 +687,7 @@ QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const {
QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
: QObject(parent), m_pointId(0), m_grabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
- m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false)
+ m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false), m_grabberIsHandler(false)
{
Q_UNUSED(m_reserved);
}
@@ -680,16 +708,16 @@ QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) cons
return event;
}
-QVector<QQuickItem *> QQuickPointerMouseEvent::grabbers() const
+QVector<QObject *> QQuickPointerMouseEvent::grabbers() const
{
- QVector<QQuickItem *> result;
- if (QQuickItem *grabber = m_mousePoint->grabber())
+ QVector<QObject *> result;
+ if (QObject *grabber = m_mousePoint->grabber())
result << grabber;
return result;
}
void QQuickPointerMouseEvent::clearGrabbers() const {
- m_mousePoint->setGrabber(nullptr);
+ m_mousePoint->setItemGrabber(nullptr);
}
bool QQuickPointerMouseEvent::isPressEvent() const
@@ -707,12 +735,12 @@ bool QQuickPointerTouchEvent::allPointsAccepted() const {
return true;
}
-QVector<QQuickItem *> QQuickPointerTouchEvent::grabbers() const
+QVector<QObject *> QQuickPointerTouchEvent::grabbers() const
{
- QVector<QQuickItem *> result;
+ QVector<QObject *> result;
for (int i = 0; i < m_pointCount; ++i) {
auto point = m_touchPoints.at(i);
- if (QQuickItem *grabber = point->grabber()) {
+ if (QObject *grabber = point->grabber()) {
if (!result.contains(grabber))
result << grabber;
}
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index c64478e856..b954c8a4ec 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -68,6 +68,7 @@ class QQuickPointerEvent;
class QQuickPointerMouseEvent;
class QQuickPointerTabletEvent;
class QQuickPointerTouchEvent;
+class QQuickPointerHandler;
class QQuickKeyEvent : public QObject
{
@@ -255,7 +256,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject
Q_PROPERTY(quint64 pointId READ pointId)
Q_PROPERTY(qreal timeHeld READ timeHeld)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
- Q_PROPERTY(QQuickItem *grabber READ grabber WRITE setGrabber)
+ Q_PROPERTY(QObject *grabber READ grabber WRITE setGrabber)
public:
enum State {
@@ -282,20 +283,27 @@ public:
qreal timeHeld() const { return (m_timestamp - m_pressTimestamp) / 1000.0; }
bool isAccepted() const { return m_accept; }
void setAccepted(bool accepted = true);
- QQuickItem *grabber() const;
- void setGrabber(QQuickItem *grabber);
+ QObject *grabber() const;
+ void setGrabber(QObject *grabber);
+
+ QQuickItem *itemGrabber() const;
+ void setItemGrabber(QQuickItem *grabber);
+
+ QQuickPointerHandler *pointerHandlerGrabber() const;
+ void setPointerHandlerGrabber(QQuickPointerHandler *grabber);
private:
QPointF m_scenePos;
QVector2D m_velocity;
quint64 m_pointId;
- QPointer<QQuickItem> m_grabber;
+ QPointer<QObject> m_grabber;
ulong m_timestamp;
ulong m_pressTimestamp;
State m_state;
bool m_valid : 1;
bool m_accept : 1;
- int m_reserved : 30;
+ bool m_grabberIsHandler : 1;
+ int m_reserved : 29;
Q_DISABLE_COPY(QQuickEventPoint)
};
@@ -368,7 +376,7 @@ public: // helpers for C++ only (during event delivery)
virtual int pointCount() const = 0;
virtual QQuickEventPoint *point(int i) const = 0;
virtual QQuickEventPoint *pointById(quint64 pointId) const = 0;
- virtual QVector<QQuickItem *> grabbers() const = 0;
+ virtual QVector<QObject *> grabbers() const = 0;
virtual void clearGrabbers() const = 0;
ulong timestamp() const { return m_event->timestamp(); }
@@ -397,7 +405,7 @@ public:
QQuickEventPoint *point(int i) const override;
QQuickEventPoint *pointById(quint64 pointId) const override;
bool allPointsAccepted() const override;
- QVector<QQuickItem *> grabbers() const override;
+ QVector<QObject *> grabbers() const override;
void clearGrabbers() const override;
QMouseEvent *asMouseEvent(const QPointF& localPos) const;
@@ -427,7 +435,7 @@ public:
QQuickEventPoint *pointById(quint64 pointId) const override;
const QTouchEvent::TouchPoint *touchPointById(int pointId) const;
bool allPointsAccepted() const override;
- QVector<QQuickItem *> grabbers() const override;
+ QVector<QObject *> grabbers() const override;
void clearGrabbers() const override;
QMouseEvent *syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index fc6bfc43a4..b2727f113e 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -46,6 +46,7 @@
#include "qquickevents_p_p.h"
#include <private/qquickdrag_p.h>
+#include <private/qquickpointerhandler_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
@@ -656,7 +657,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
if (!q->mouseGrabberItem())
item->grabMouse();
auto pointerEventPoint = pointerEvent->pointById(p.id());
- pointerEventPoint->setGrabber(item);
+ pointerEventPoint->setItemGrabber(item);
if (checkIfDoubleClicked(event->timestamp())) {
QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item, false));
@@ -740,14 +741,14 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
Q_ASSERT(event->pointCount() == 1);
- event->point(0)->setGrabber(grabber);
+ event->point(0)->setItemGrabber(grabber);
if (grabber && touchMouseId != -1 && touchMouseDevice) {
// update the touch item for mouse touch id to the new grabber
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << q->mouseGrabberItem();
auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId);
if (point)
- point->setGrabber(grabber);
+ point->setItemGrabber(grabber);
}
if (oldGrabber) {
@@ -758,10 +759,10 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
}
}
-void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids)
+void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids)
{
Q_Q(QQuickWindow);
- QSet<QQuickItem*> ungrab;
+ QSet<QObject*> ungrab;
for (int i = 0; i < ids.count(); ++i) {
// FIXME: deprecate this function, we need a device
const auto touchDevices = QQuickPointerDevice::touchDevices();
@@ -769,7 +770,7 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int
auto point = device->pointerEvent()->pointById(ids.at(i));
if (!point)
continue;
- QQuickItem *oldGrabber = point->grabber();
+ QObject *oldGrabber = point->grabber();
if (oldGrabber == grabber)
continue;
@@ -784,8 +785,10 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int
setMouseGrabber(nullptr);
}
}
- for (QQuickItem *oldGrabber : qAsConst(ungrab))
- oldGrabber->touchUngrabEvent();
+ for (QObject *oldGrabber : qAsConst(ungrab))
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(oldGrabber))
+ item->touchUngrabEvent();
+ // TODO else if the old grabber was a PointerHandler, notify it somehow?
}
void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch)
@@ -797,7 +800,7 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
auto pointerEvent = device->pointerEvent();
for (int i = 0; i < pointerEvent->pointCount(); ++i) {
if (pointerEvent->point(i)->grabber() == grabber) {
- pointerEvent->point(i)->setGrabber(nullptr);
+ pointerEvent->point(i)->setItemGrabber(nullptr);
// FIXME send ungrab event only once
grabber->touchUngrabEvent();
}
@@ -1466,7 +1469,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
{
QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
Q_ASSERT(event->pointCount());
- return event->point(0)->grabber();
+ return event->point(0)->itemGrabber();
}
@@ -1609,7 +1612,13 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
Q_Q(QQuickWindow);
auto point = pointerEvent->point(0);
lastMousePosition = point->scenePos();
- QQuickItem *grabber = point->grabber();
+
+ if (point->pointerHandlerGrabber()) {
+ point->pointerHandlerGrabber()->handlePointerEvent(pointerEvent);
+ return;
+ }
+
+ QQuickItem *grabber = point->itemGrabber();
if (grabber) {
// if the update consists of changing button state, then don't accept it
// unless the button is one in which the item is interested
@@ -1620,12 +1629,6 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
return;
}
- // Let the Item's handlers (if any) have the event first.
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(grabber);
- itemPrivate->handlePointerEvent(pointerEvent);
- if (pointerEvent->allPointsAccepted())
- return;
-
// send update
QPointF localPos = grabber->mapFromScene(lastMousePosition);
auto me = pointerEvent->asMouseEvent(localPos);
@@ -1845,10 +1848,14 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
// A TouchCancel event will typically not contain any points.
// Deliver it to all items that have active touches.
QQuickPointerEvent *pointerEvent = QQuickPointerDevice::touchDevice(event->device())->pointerEvent();
- QVector<QQuickItem *> grabbers = pointerEvent->grabbers();
-
- for (QQuickItem *grabber: qAsConst(grabbers)) {
- q->sendEvent(grabber, event);
+ QVector<QObject *> grabbers = pointerEvent->grabbers();
+
+ for (QObject *grabber: qAsConst(grabbers)) {
+ if (QQuickItem *grabberItem = qmlobject_cast<QQuickItem *>(grabber))
+ q->sendEvent(grabberItem, event);
+ else //if (QQuickPointerHandler *grabberHandler = qmlobject_cast<QQuickPointerHandler *>(grabber))
+// grabberHandler->handlePointerEvent()
+ qWarning("unexpected: can't deliver touch cancel to a PointerHandler (yet?)");
}
touchMouseId = -1;
touchMouseDevice = nullptr;
@@ -1986,8 +1993,6 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
{
- Q_Q(QQuickWindow);
-
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
return;
@@ -2020,7 +2025,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
updateCursor(event->windowPos());
#endif
- if (!q->mouseGrabberItem()) {
+ if (!QQuickPointerDevice::genericMouseDevice()->pointerEvent()->point(0)->grabber()) {
QPointF last = lastMousePosition.isNull() ? event->windowPos() : lastMousePosition;
lastMousePosition = event->windowPos();
@@ -2188,7 +2193,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
if (point->state() == QQuickEventPoint::Released) {
int id = point->pointId();
qCDebug(DBG_TOUCH_TARGET) << "TP" << id << "released";
- point->setGrabber(nullptr);
+ point->setItemGrabber(nullptr);
if (id == touchMouseId) {
touchMouseId = -1;
touchMouseDevice = nullptr;
@@ -2208,8 +2213,12 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
bool QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event, QSet<QQuickItem *> *hasFiltered)
{
const auto grabbers = event->grabbers();
- for (auto grabber : grabbers)
- deliverMatchingPointsToItem(grabber, event, hasFiltered);
+ for (auto grabber : grabbers) {
+ if (QQuickItem *grabberItem = qmlobject_cast<QQuickItem *>(grabber))
+ deliverMatchingPointsToItem(grabberItem, event, hasFiltered);
+ else if (QQuickPointerHandler *grabberHandler = qmlobject_cast<QQuickPointerHandler *>(grabber))
+ deliverMatchingPointsToItem(grabberHandler->target(), event, hasFiltered);
+ }
return false;
}
@@ -2310,7 +2319,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
auto pointerEventPoint = event->pointById(point.id());
pointerEventPoint->setAccepted();
if (point.state() == Qt::TouchPointPressed)
- pointerEventPoint->setGrabber(item);
+ pointerEventPoint->setItemGrabber(item);
}
} else {
// But if the event was not accepted then we know this item
@@ -2319,7 +2328,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
if (point.state() == Qt::TouchPointPressed) {
if (event->pointById(point.id())->grabber() == item) {
qCDebug(DBG_TOUCH_TARGET) << "TP" << point.id() << "disassociated";
- event->pointById(point.id())->setGrabber(nullptr);
+ event->pointById(point.id())->setItemGrabber(nullptr);
}
}
}
@@ -2558,7 +2567,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
qCDebug(DBG_TOUCH_TARGET) << "TP" << tp.id() << "->" << target;
touchMouseId = tp.id();
touchMouseDevice = event->device();
- touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabber(target);
+ touchMouseDevice->pointerEvent()->pointById(tp.id())->setItemGrabber(target);
target->grabMouse();
}
filtered = true;
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 3328eb65c4..a2a53fd2ce 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -141,7 +141,7 @@ public:
bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
void translateTouchEvent(QTouchEvent *touchEvent);
void setMouseGrabber(QQuickItem *grabber);
- void grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids);
+ void grabTouchPoints(QObject *grabber, const QVector<int> &ids);
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);