Fix some problems with MouseDblClick handling

The sequence of events delivered from a double click is:

 [Press,Release,Press,DblClick,Release]

The problem was that a DblClick was delivered just like a press event, so
it would clear the passive grabber that was established because of the
former Press event.
When the Release event then got processed, there was therefore a risk that
the Release event was not delivered to the passive grabber.

The fix is to not deliver DblClick events at all to handlers, and to not
deliver DblClick to items if the former Press event was accepted by a
handler.

Change-Id: I49c0e32ef4e33f7b6014d35dc065da2527b94779
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
Jan Arve Saether 2017-05-22 15:34:18 +02:00 committed by Shawn Rutledge
parent b10e307054
commit 0e3adb65b0
4 changed files with 19 additions and 3 deletions

View File

@ -879,8 +879,9 @@ QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
Qt::TouchPointState state = Qt::TouchPointStationary;
switch (ev->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
m_mousePoint->clearPassiveGrabbers();
Q_FALLTHROUGH();
case QEvent::MouseButtonDblClick:
state = Qt::TouchPointPressed;
break;
case QEvent::MouseButtonRelease:
@ -1055,6 +1056,12 @@ bool QQuickPointerMouseEvent::isPressEvent() const
(me->buttons() & me->button()) == me->buttons());
}
bool QQuickPointerMouseEvent::isDoubleClickEvent() const
{
auto me = static_cast<QMouseEvent*>(m_event);
return (me->type() == QEvent::MouseButtonDblClick);
}
bool QQuickPointerMouseEvent::isUpdateEvent() const
{
auto me = static_cast<QMouseEvent*>(m_event);

View File

@ -407,6 +407,7 @@ public: // helpers for C++ only (during event delivery)
virtual void localize(QQuickItem *target) = 0;
virtual bool isPressEvent() const = 0;
virtual bool isDoubleClickEvent() const { return false; }
virtual bool isUpdateEvent() const = 0;
virtual bool isReleaseEvent() const = 0;
virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; }
@ -451,6 +452,7 @@ public:
QQuickPointerEvent *reset(QEvent *) override;
void localize(QQuickItem *target) override;
bool isPressEvent() const override;
bool isDoubleClickEvent() const override;
bool isUpdateEvent() const override;
bool isReleaseEvent() const override;
QQuickPointerMouseEvent *asPointerMouseEvent() override { return this; }

View File

@ -503,6 +503,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, lastWheelEventAccepted(false)
, componentCompleted(true)
, allowChildEventFiltering(true)
, allowDoubleClick(true)
, lastFocusReason(Qt::OtherFocusReason)
, renderTarget(0)
, renderTargetId(0)
@ -2092,7 +2093,8 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
case QEvent::MouseButtonDblClick:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
event->button(), event->buttons());
deliverPointerEvent(pointerEventInstance(event));
if (allowDoubleClick)
deliverPointerEvent(pointerEventInstance(event));
break;
case QEvent::MouseMove:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
@ -2404,7 +2406,11 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
pointerEvent->localize(item);
// Let the Item's handlers (if any) have the event first.
itemPrivate->handlePointerEvent(pointerEvent);
// However, double click should never be delivered to handlers.
if (!pointerEvent->isDoubleClickEvent()) {
itemPrivate->handlePointerEvent(pointerEvent);
allowDoubleClick = !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted());
}
if (handlersOnly)
return;
if (pointerEvent->allPointsAccepted() && !pointerEvent->isReleaseEvent())

View File

@ -262,6 +262,7 @@ public:
bool componentCompleted : 1;
bool allowChildEventFiltering : 1;
bool allowDoubleClick : 1;
Qt::FocusReason lastFocusReason;