aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
authorJan Arve Saether <jan-arve.saether@qt.io>2017-05-08 11:25:10 +0200
committerJani Heikkinen <jani.heikkinen@qt.io>2017-05-10 11:31:56 +0000
commite0c30279ec1fad88346ed3fb483bc3c672fdd01b (patch)
treeb4100688b65b66c83249a11f212ebff8c4a56409 /src/quick/items
parent802a5be531a9f2b1396f4ea4715c9a1dc593f778 (diff)
Move pointerEvent instance to QQuickWindow
With two or more windows, if events are being delivered to each, the grabbers can be different in each. We need unique instances of the QQuickPointerEvent objects for each window to avoid losing the grab state in the parent window while delivering a synthesized event to a subwindow, for example. Change-Id: I51da1212d573853969e32ad78f5b219d979a8a5c Task-number: QTBUG-57253 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickevents_p_p.h25
-rw-r--r--src/quick/items/qquickwindow.cpp52
-rw-r--r--src/quick/items/qquickwindow_p.h4
3 files changed, 52 insertions, 29 deletions
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index cf6f83e5b1..3735d68a85 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -332,9 +332,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject
Q_PROPERTY(Qt::MouseButtons buttons READ buttons)
public:
- QQuickPointerEvent(QObject *parent = nullptr)
+ QQuickPointerEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
: QObject(parent)
- , m_device(nullptr)
+ , m_device(device)
, m_event(nullptr)
, m_button(Qt::NoButton)
, m_pressedButtons(Qt::NoButton)
@@ -385,8 +385,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickPointerEvent
{
Q_OBJECT
public:
- QQuickPointerMouseEvent(QObject *parent = nullptr)
- : QQuickPointerEvent(parent), m_mousePoint(new QQuickEventPoint(this)) { }
+ QQuickPointerMouseEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickPointerEvent(parent, device), m_mousePoint(new QQuickEventPoint(this)) { }
QQuickPointerEvent *reset(QEvent *) override;
bool isPressEvent() const override;
@@ -411,8 +411,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent
{
Q_OBJECT
public:
- QQuickPointerTouchEvent(QObject *parent = nullptr)
- : QQuickPointerEvent(parent)
+ QQuickPointerTouchEvent(QObject *parent = nullptr, QQuickPointerDevice *device = nullptr)
+ : QQuickPointerEvent(parent, device)
, m_pointCount(0)
, m_synthMouseEvent(QEvent::MouseMove, QPointF(), Qt::NoButton, Qt::NoButton, Qt::NoModifier)
{ }
@@ -500,18 +500,10 @@ public:
QQuickPointerDevice(DeviceType devType, PointerType pType, Capabilities caps, int maxPoints, int buttonCount, const QString &name, qint64 uniqueId = 0)
: m_deviceType(devType), m_pointerType(pType), m_capabilities(caps)
, m_maximumTouchPoints(maxPoints), m_buttonCount(buttonCount), m_name(name)
- , m_uniqueId(QPointingDeviceUniqueId::fromNumericId(uniqueId)), m_event(nullptr)
+ , m_uniqueId(QPointingDeviceUniqueId::fromNumericId(uniqueId))
{
- if (m_deviceType == Mouse) {
- m_event = new QQuickPointerMouseEvent;
- } else if (m_deviceType == TouchScreen || m_deviceType == TouchPad) {
- m_event = new QQuickPointerTouchEvent;
- } else {
- Q_ASSERT(false);
- }
}
- ~QQuickPointerDevice() { delete m_event; }
DeviceType type() const { return m_deviceType; }
PointerType pointerType() const { return m_pointerType; }
Capabilities capabilities() const { return m_capabilities; }
@@ -520,7 +512,6 @@ public:
int buttonCount() const { return m_buttonCount; }
QString name() const { return m_name; }
QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; }
- QQuickPointerEvent *pointerEvent() const { return m_event; }
static QQuickPointerDevice *touchDevice(QTouchDevice *d);
static QList<QQuickPointerDevice *> touchDevices();
@@ -535,8 +526,6 @@ private:
int m_buttonCount;
QString m_name;
QPointingDeviceUniqueId m_uniqueId;
- // the device-specific event instance which is reused during event delivery
- QQuickPointerEvent *m_event;
Q_DISABLE_COPY(QQuickPointerDevice)
};
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index bdb362e1ff..c441cfc357 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -752,12 +752,12 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
if (grabber && touchMouseId != -1 && touchMouseDevice) {
// update the touch item for mouse touch id to the new grabber
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << touchMouseId << "->" << q->mouseGrabberItem();
- auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId);
+ auto point = pointerEventInstance(touchMouseDevice)->pointById(touchMouseId);
if (point)
point->setGrabber(grabber);
fromTouch = true;
} else {
- QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
+ QQuickPointerEvent *event = pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
Q_ASSERT(event->pointCount() == 1);
event->point(0)->setGrabber(grabber);
}
@@ -784,7 +784,7 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int
continue;
}
if (id == touchMouseId) {
- auto point = touchMouseDevice->pointerEvent()->pointById(id);
+ auto point = pointerEventInstance(touchMouseDevice)->pointById(id);
auto touchMouseGrabber = point->grabber();
if (touchMouseGrabber) {
point->setGrabber(nullptr);
@@ -798,7 +798,7 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int
const auto touchDevices = QQuickPointerDevice::touchDevices();
for (auto device : touchDevices) {
- auto point = device->pointerEvent()->pointById(id);
+ auto point = pointerEventInstance(device)->pointById(id);
if (!point)
continue;
QQuickItem *oldGrabber = point->grabber();
@@ -824,7 +824,7 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
if (Q_LIKELY(touch)) {
const auto touchDevices = QQuickPointerDevice::touchDevices();
for (auto device : touchDevices) {
- auto pointerEvent = device->pointerEvent();
+ auto pointerEvent = pointerEventInstance(device);
for (int i = 0; i < pointerEvent->pointCount(); ++i) {
if (pointerEvent->point(i)->grabber() == grabber) {
pointerEvent->point(i)->setGrabber(nullptr);
@@ -1493,13 +1493,13 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
Q_D(const QQuickWindow);
if (d->touchMouseId != -1 && d->touchMouseDevice) {
- QQuickPointerEvent *event = d->touchMouseDevice->pointerEvent();
+ QQuickPointerEvent *event = d->pointerEventInstance(d->touchMouseDevice);
auto point = event->pointById(d->touchMouseId);
Q_ASSERT(point);
return point->grabber();
}
- QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
+ QQuickPointerEvent *event = d->pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
Q_ASSERT(event->pointCount());
return event->point(0)->grabber();
}
@@ -1883,7 +1883,7 @@ 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();
+ QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::touchDevice(event->device()));
QVector<QQuickItem *> grabbers = pointerEvent->grabbers();
for (QQuickItem *grabber: qAsConst(grabbers)) {
@@ -2113,6 +2113,32 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
}
}
+QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const
+{
+ // the list of devices should be very small so a linear search should be ok
+ for (QQuickPointerEvent *e: pointerEventInstances) {
+ if (e->device() == device)
+ return e;
+ }
+
+ QQuickPointerEvent *ev = nullptr;
+ QQuickWindow *q = const_cast<QQuickWindow*>(q_func());
+ switch (device->type()) {
+ case QQuickPointerDevice::Mouse:
+ ev = new QQuickPointerMouseEvent(q, device);
+ break;
+ case QQuickPointerDevice::TouchPad:
+ case QQuickPointerDevice::TouchScreen:
+ ev = new QQuickPointerTouchEvent(q, device);
+ break;
+ default:
+ // TODO tablet event types
+ break;
+ }
+ pointerEventInstances << ev;
+ return ev;
+}
+
/*!
\internal
Returns a QQuickPointerEvent instance suitable for wrapping and delivering \a event.
@@ -2123,25 +2149,29 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) const
{
QQuickPointerDevice *dev = nullptr;
+ QQuickPointerEvent *ev = nullptr;
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
dev = QQuickPointerDevice::genericMouseDevice();
+ ev = pointerEventInstance(dev);
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
case QEvent::TouchCancel:
dev = QQuickPointerDevice::touchDevice(static_cast<QTouchEvent *>(event)->device());
+ ev = pointerEventInstance(dev);
break;
// TODO tablet event types
default:
break;
}
- Q_ASSERT(dev);
- return dev->pointerEvent()->reset(event);
+
+ Q_ASSERT(ev);
+ return ev->reset(event);
}
void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
@@ -2616,7 +2646,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
if (touchMouseUnset) {
// the point was grabbed as a pure touch point before, now it will be treated as mouse
// but the old receiver still needs to be informed
- if (auto oldGrabber = touchMouseDevice->pointerEvent()->pointById(tp.id())->grabber())
+ if (auto oldGrabber = pointerEventInstance(touchMouseDevice)->pointById(tp.id())->grabber())
oldGrabber->touchUngrabEvent();
}
touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index be915903c6..b3ff5a2b35 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -162,6 +162,10 @@ public:
void flushFrameSynchronousEvents();
void deliverDelayedTouchEvent();
+ // the device-specific event instances which are reused during event delivery
+ mutable QVector<QQuickPointerEvent *> pointerEventInstances;
+ QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device) const;
+
// delivery of pointer events:
QQuickPointerEvent *pointerEventInstance(QEvent *ev) const;
void deliverPointerEvent(QQuickPointerEvent *);