diff options
-rw-r--r-- | src/quick/items/qquickcanvas.cpp | 14 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 87 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea_p.h | 5 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/data/simple.qml | 12 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp | 128 |
6 files changed, 203 insertions, 45 deletions
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 2de8fd5030..e7134c1230 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 a2522a4f47..a26c7c97f9 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 14b74f45d0..8a8de3bdc3 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 39a06161b7..aa28da88bc 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 0000000000..56d561e5af --- /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 686c05719d..7d42eb2261 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<Qt::MouseButtons>("accepted"); + QTest::addColumn<QList<Qt::MouseButtons> >("buttons"); + QTest::addColumn<QList<bool> >("pressed"); + QTest::addColumn<QList<Qt::MouseButtons> >("pressedButtons"); + QTest::addColumn<int>("changeCount"); + + QList<Qt::MouseButtons> buttons; + QList<bool> pressed; + QList<Qt::MouseButtons> 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<Qt::MouseButtons>, buttons); + QFETCH(QList<bool>, pressed); + QFETCH(QList<Qt::MouseButtons>, 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<QQuickMouseArea *>("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" |