From: Martin Jones Date: Tue, 10 Jul 2012 06:40:06 +0000 (+1000) Subject: pressed and pressedButtons don't work when multiple buttons are pressed X-Git-Tag: upstream/5.2.1~1458 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd0caf5ad611311621696177adcaf87c33f88a03;p=platform%2Fupstream%2Fqtdeclarative.git pressed and pressedButtons don't work when multiple buttons are pressed The pressed property would react to any mouse event, regardless of whether it was in acceptedButtons, or there were other buttons still pressed. It will now remain true while any button in acceptedButtons is pressed. The pressedButtons property could contain buttons not in the acceptedButtons mask. It will now only contain buttons that are in the acceptedButtons mask. Task-number: QTBUG-26458 Change-Id: I6b25cc36a58c113de062d530761dc179d7ef4a5a Reviewed-by: Michael Brasser --- diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 2de8fd5..e7134c1 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -1187,7 +1187,7 @@ bool QQuickCanvasPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouse event->setAccepted(me->isAccepted()); if (me->isAccepted()) return true; - if (mouseGrabberItem) + if (mouseGrabberItem && !event->buttons()) mouseGrabberItem->ungrabMouse(); } } @@ -1229,7 +1229,7 @@ void QQuickCanvas::mousePressEvent(QMouseEvent *event) { Q_D(QQuickCanvas); #ifdef MOUSE_DEBUG - qWarning() << "QQuickCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons(); + qWarning() << "QQuickCanvas::mousePressEvent()" << event->localPos() << event->button() << event->buttons(); #endif d->deliverMouseEvent(event); @@ -1240,7 +1240,7 @@ void QQuickCanvas::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickCanvas); #ifdef MOUSE_DEBUG - qWarning() << "QQuickCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons(); + qWarning() << "QQuickCanvas::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons(); #endif if (!d->mouseGrabberItem) { @@ -1249,7 +1249,7 @@ void QQuickCanvas::mouseReleaseEvent(QMouseEvent *event) } d->deliverMouseEvent(event); - if (d->mouseGrabberItem) + if (d->mouseGrabberItem && !event->buttons()) d->mouseGrabberItem->ungrabMouse(); } @@ -1258,7 +1258,7 @@ void QQuickCanvas::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(QQuickCanvas); #ifdef MOUSE_DEBUG - qWarning() << "QQuickCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons(); + qWarning() << "QQuickCanvas::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons(); #endif if (!d->mouseGrabberItem && (event->buttons() & event->button()) == event->buttons()) { @@ -1293,7 +1293,7 @@ void QQuickCanvas::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickCanvas); #ifdef MOUSE_DEBUG - qWarning() << "QQuickCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons(); + qWarning() << "QQuickCanvas::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons(); #endif if (!d->mouseGrabberItem) { @@ -1423,7 +1423,7 @@ void QQuickCanvas::wheelEvent(QWheelEvent *event) { Q_D(QQuickCanvas); #ifdef MOUSE_DEBUG - qWarning() << "QQuickCanvas::wheelEvent()" << event->pos() << event->pixelDelta() << event->angleDelta(); + qWarning() << "QQuickCanvas::wheelEvent()" << event->pixelDelta() << event->angleDelta(); #endif //if the actual wheel event was accepted, accept the compatability wheel event and return early diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index a2522a4..a26c7c9 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -193,9 +193,9 @@ QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj) #endif // QT_NO_DRAGANDDROP QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() -: enabled(true), hovered(false), pressed(false), longPress(false), +: enabled(true), hovered(false), longPress(false), moved(false), dragX(true), dragY(true), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false) + propagateComposedEvents(false), pressed(0) #ifndef QT_NO_DRAGANDDROP , drag(0) #endif @@ -693,12 +693,14 @@ void QQuickMouseArea::setPropagateComposedEvents(bool prevent) \snippet qml/mousearea/mousearea.qml mousebuttons + \note this property only handles buttons specified in \l acceptedButtons. + \sa acceptedButtons */ Qt::MouseButtons QQuickMouseArea::pressedButtons() const { Q_D(const QQuickMouseArea); - return d->lastButtons; + return d->pressed; } void QQuickMouseArea::mousePressEvent(QMouseEvent *event) @@ -706,9 +708,9 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) Q_D(QQuickMouseArea); d->moved = false; d->stealMouse = d->preventStealing; - if (!d->enabled) + if (!d->enabled || !(event->button() & acceptedMouseButtons())) { QQuickItem::mousePressEvent(event); - else { + } else { d->longPress = false; d->saveEvent(event); #ifndef QT_NO_DRAGANDDROP @@ -719,7 +721,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) d->startScene = event->windowPos(); d->pressAndHoldTimer.start(PressAndHoldDelay, this); setKeepMouseGrab(d->stealMouse); - event->setAccepted(setPressed(true)); + event->setAccepted(setPressed(event->button(), true)); #ifndef QT_NO_DRAGANDDROP if (d->drag) { @@ -827,19 +829,21 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event) QQuickItem::mouseReleaseEvent(event); } else { d->saveEvent(event); - setPressed(false); + setPressed(event->button(), false); + if (!d->pressed) { + // no other buttons are pressed #ifndef QT_NO_DRAGANDDROP - if (d->drag) - d->drag->setActive(false); + if (d->drag) + d->drag->setActive(false); #endif - // If we don't accept hover, we need to reset containsMouse. - if (!acceptHoverEvents()) - setHovered(false); - QQuickCanvas *c = canvas(); - if (c && c->mouseGrabberItem() == this) - ungrabMouse(); - setKeepMouseGrab(false); - + // If we don't accept hover, we need to reset containsMouse. + if (!acceptHoverEvents()) + setHovered(false); + QQuickCanvas *c = canvas(); + if (c && c->mouseGrabberItem() == this) + ungrabMouse(); + setKeepMouseGrab(false); + } } d->doubleClick = false; } @@ -924,11 +928,12 @@ void QQuickMouseArea::ungrabMouse() if (d->pressed) { // if our mouse grab has been removed (probably by Flickable), fix our // state - d->pressed = false; + d->pressed = 0; d->stealMouse = false; setKeepMouseGrab(false); emit canceled(); emit pressedChanged(); + emit pressedButtonsChanged(); if (d->hovered) { d->hovered = false; emit hoveredChanged(); @@ -975,15 +980,19 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event) } if (event->type() == QEvent::MouseButtonRelease) { if (d->pressed) { - d->pressed = false; - d->stealMouse = false; - if (c && c->mouseGrabberItem() == this) - ungrabMouse(); - emit canceled(); - emit pressedChanged(); - if (d->hovered) { - d->hovered = false; - emit hoveredChanged(); + d->pressed &= ~event->button(); + emit pressedButtonsChanged(); + if (!d->pressed) { + // no other buttons are pressed + d->stealMouse = false; + if (c && c->mouseGrabberItem() == this) + ungrabMouse(); + emit canceled(); + emit pressedChanged(); + if (d->hovered) { + d->hovered = false; + emit hoveredChanged(); + } } } } @@ -1116,7 +1125,7 @@ bool QQuickMouseArea::hovered() const /*! \qmlproperty bool QtQuick2::MouseArea::pressed - This property holds whether the mouse area is currently pressed. + This property holds whether any of the \l acceptedButtons are currently pressed. */ bool QQuickMouseArea::pressed() const { @@ -1176,31 +1185,39 @@ void QQuickMouseArea::setAcceptedButtons(Qt::MouseButtons buttons) } } -bool QQuickMouseArea::setPressed(bool p) +bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p) { Q_D(QQuickMouseArea); + #ifndef QT_NO_DRAGANDDROP bool dragged = d->drag && d->drag->active(); #else bool dragged = false; #endif - bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true; + bool wasPressed = d->pressed & button; + bool isclick = wasPressed && p == false && dragged == false && d->hovered == true; + Qt::MouseButtons oldPressed = d->pressed; - if (d->pressed != p) { - d->pressed = p; + if (wasPressed != p) { QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress); - if (d->pressed) { + if (p) { + d->pressed |= button; if (!d->doubleClick) emit pressed(&me); me.setPosition(d->lastPos); emit mouseXChanged(&me); me.setPosition(d->lastPos); emit mouseYChanged(&me); - emit pressedChanged(); + if (!oldPressed) + emit pressedChanged(); + emit pressedButtonsChanged(); } else { + d->pressed &= ~button; emit released(&me); me.setPosition(d->lastPos); - emit pressedChanged(); + if (!d->pressed) + emit pressedChanged(); + emit pressedButtonsChanged(); if (isclick && !d->longPress && !d->doubleClick){ me.setAccepted(d->isClickConnected()); emit clicked(&me); diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index 14b74f4..8a8de3b 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -135,7 +135,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged) Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedChanged) + Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedButtonsChanged) Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged) Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged) #ifndef QT_NO_DRAGANDDROP @@ -187,6 +187,7 @@ Q_SIGNALS: void hoveredChanged(); void pressedChanged(); void enabledChanged(); + void pressedButtonsChanged(); void acceptedButtonsChanged(); void hoverEnabledChanged(); #ifndef QT_NO_CURSOR @@ -210,7 +211,7 @@ Q_SIGNALS: protected: void setHovered(bool); - bool setPressed(bool); + bool setPressed(Qt::MouseButton button, bool); bool sendMouseEvent(QMouseEvent *event); virtual void mousePressEvent(QMouseEvent *event); diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 39a0616..aa28da8 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -87,7 +87,6 @@ public: bool enabled : 1; bool hovered : 1; - bool pressed : 1; bool longPress : 1; bool moved : 1; bool dragX : 1; @@ -96,6 +95,7 @@ public: bool doubleClick : 1; bool preventStealing : 1; bool propagateComposedEvents : 1; + Qt::MouseButtons pressed; #ifndef QT_NO_DRAGANDDROP QQuickDrag *drag; #endif diff --git a/tests/auto/quick/qquickmousearea/data/simple.qml b/tests/auto/quick/qquickmousearea/data/simple.qml new file mode 100644 index 0000000..56d561e --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/simple.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 + +Rectangle { + id: whiteRect + width: 200 + height: 200 + color: "white" + MouseArea { + objectName: "mousearea" + anchors.fill: parent + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 686c057..7d42eb2 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -82,6 +82,8 @@ private slots: void onWheel(); void transformedMouseArea_data(); void transformedMouseArea(); + void pressedMultipleButtons_data(); + void pressedMultipleButtons(); private: void acceptedButton_data(); @@ -1175,6 +1177,132 @@ void tst_QQuickMouseArea::transformedMouseArea() delete canvas; } +void tst_QQuickMouseArea::pressedMultipleButtons_data() +{ + QTest::addColumn("accepted"); + QTest::addColumn >("buttons"); + QTest::addColumn >("pressed"); + QTest::addColumn >("pressedButtons"); + QTest::addColumn("changeCount"); + + QList buttons; + QList pressed; + QList pressedButtons; + buttons << Qt::LeftButton + << (Qt::LeftButton | Qt::RightButton) + << Qt::LeftButton + << 0; + pressed << true + << true + << true + << false; + pressedButtons << Qt::LeftButton + << Qt::LeftButton + << Qt::LeftButton + << 0; + QTest::newRow("Accept Left - Press left, Press Right, Release Right") + << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2; + + buttons.clear(); + pressed.clear(); + pressedButtons.clear(); + buttons << Qt::LeftButton + << (Qt::LeftButton | Qt::RightButton) + << Qt::RightButton + << 0; + pressed << true + << true + << false + << false; + pressedButtons << Qt::LeftButton + << Qt::LeftButton + << 0 + << 0; + QTest::newRow("Accept Left - Press left, Press Right, Release Left") + << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2; + + buttons.clear(); + pressed.clear(); + pressedButtons.clear(); + buttons << Qt::LeftButton + << (Qt::LeftButton | Qt::RightButton) + << Qt::LeftButton + << 0; + pressed << true + << true + << true + << false; + pressedButtons << Qt::LeftButton + << (Qt::LeftButton | Qt::RightButton) + << Qt::LeftButton + << 0; + QTest::newRow("Accept Left|Right - Press left, Press Right, Release Right") + << (Qt::LeftButton | Qt::RightButton) << buttons << pressed << pressedButtons << 4; + + buttons.clear(); + pressed.clear(); + pressedButtons.clear(); + buttons << Qt::RightButton + << (Qt::LeftButton | Qt::RightButton) + << Qt::LeftButton + << 0; + pressed << true + << true + << false + << false; + pressedButtons << Qt::RightButton + << Qt::RightButton + << 0 + << 0; + QTest::newRow("Accept Right - Press Right, Press Left, Release Right") + << Qt::MouseButtons(Qt::RightButton) << buttons << pressed << pressedButtons << 2; +} + +void tst_QQuickMouseArea::pressedMultipleButtons() +{ + QFETCH(Qt::MouseButtons, accepted); + QFETCH(QList, buttons); + QFETCH(QList, pressed); + QFETCH(QList, pressedButtons); + QFETCH(int, changeCount); + + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("simple.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickMouseArea *mouseArea = canvas->rootObject()->findChild("mousearea"); + QVERIFY(mouseArea != 0); + + QSignalSpy pressedSpy(mouseArea, SIGNAL(pressedChanged())); + QSignalSpy pressedButtonsSpy(mouseArea, SIGNAL(pressedButtonsChanged())); + mouseArea->setAcceptedMouseButtons(accepted); + + QPoint point(10,10); + + int prevButtons = 0; + for (int i = 0; i < buttons.count(); ++i) { + int btns = buttons.at(i); + + // The windowsysteminterface takes care of sending releases + QTest::mousePress(canvas, (Qt::MouseButton)btns, 0, point); + + QCOMPARE(mouseArea->pressed(), pressed.at(i)); + QCOMPARE(mouseArea->pressedButtons(), pressedButtons.at(i)); + + prevButtons = buttons.at(i); + } + + QTest::mousePress(canvas, Qt::NoButton, 0, point); + QCOMPARE(mouseArea->pressed(), false); + + QCOMPARE(pressedSpy.count(), 2); + QCOMPARE(pressedButtonsSpy.count(), changeCount); + + delete canvas; +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc"