aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2012-07-10 16:40:06 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-11 17:37:55 +0200
commitdd0caf5ad611311621696177adcaf87c33f88a03 (patch)
treeebc46c8e894a68a6a1fb9e9a6a9ba9da81e48f3e
parentb5eb3d69b40c4b750a1bbece7be2acbe7cf918e3 (diff)
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 <michael.brasser@nokia.com>
-rw-r--r--src/quick/items/qquickcanvas.cpp14
-rw-r--r--src/quick/items/qquickmousearea.cpp87
-rw-r--r--src/quick/items/qquickmousearea_p.h5
-rw-r--r--src/quick/items/qquickmousearea_p_p.h2
-rw-r--r--tests/auto/quick/qquickmousearea/data/simple.qml12
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp128
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"