diff options
4 files changed, 114 insertions, 0 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index d4e7f7b..6633256 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -660,6 +660,32 @@ void QDeclarativeMouseArea::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) setHovered(false); } +#ifndef QT_NO_CONTEXTMENU +void QDeclarativeMouseArea::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + bool acceptsContextMenuButton; +#if defined(Q_OS_SYMBIAN) + // In Symbian a Long Tap on the screen will trigger. See QSymbianControl::HandleLongTapEventL(). + acceptsContextMenuButton = acceptedButtons() & Qt::LeftButton; +#elif defined(Q_WS_WINCE) + // ### WinCE can trigger context menu event with a gesture in the left button or a + // click with the right button. Since we have no way here to differentiate them when + // event happens, accepting either of the them will block the event. + acceptsContextMenuButton = acceptedButtons() & (Qt::LeftButton | Qt::RightButton); +#else + acceptsContextMenuButton = acceptedButtons() & Qt::RightButton; +#endif + + if (isEnabled() && event->reason() == QGraphicsSceneContextMenuEvent::Mouse + && acceptsContextMenuButton) { + // Do not let the context menu event propagate to items behind. + return; + } + + QDeclarativeItem::contextMenuEvent(event); +} +#endif // QT_NO_CONTEXTMENU + bool QDeclarativeMouseArea::sceneEvent(QEvent *event) { bool rv = QDeclarativeItem::sceneEvent(event); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index 351d4de..0fe8c6a 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -190,6 +190,9 @@ protected: void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverMoveEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); +#ifndef QT_NO_CONTEXTMENU + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); +#endif // QT_NO_CONTEXTMENU bool sceneEvent(QEvent *); bool sendMouseEvent(QGraphicsSceneMouseEvent *event); bool sceneEventFilter(QGraphicsItem *i, QEvent *e); diff --git a/tests/auto/declarative/qdeclarativemousearea/data/preventContextMenu.qml b/tests/auto/declarative/qdeclarativemousearea/data/preventContextMenu.qml new file mode 100644 index 0000000..dcbb5d7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemousearea/data/preventContextMenu.qml @@ -0,0 +1,22 @@ +import QtQuick 1.1 +import Test 1.0 + +Item { + width: 200 + height: 200 + + property alias mouseAreaEnabled: mouseArea.enabled + property alias eventsReceived: receiver.eventCount + + ContextMenuEventReceiver { + id: receiver + anchors.fill: parent + } + + MouseArea { + id: mouseArea + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton + enabled: true + } +} diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index e1c34fc..fea7865 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -47,6 +47,7 @@ #include <QtDeclarative/qdeclarativeview.h> #include <QtDeclarative/qdeclarativecontext.h> #include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativeproperty.h> #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -70,6 +71,9 @@ private slots: void preventStealing(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); +#ifndef QT_NO_CONTEXTMENU + void preventContextMenu(); +#endif // QT_NO_CONTEXTMENU private: QDeclarativeView *createView(); @@ -637,6 +641,65 @@ void tst_QDeclarativeMouseArea::testQtQuick11Attributes_data() << ":1 \"MouseArea.preventStealing\" is not available in QtQuick 1.0.\n"; } +#ifndef QT_NO_CONTEXTMENU +class ContextMenuEventReceiver : public QDeclarativeItem +{ + Q_OBJECT + Q_PROPERTY(int eventCount READ eventCount NOTIFY eventCountChanged); +public: + ContextMenuEventReceiver(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent), m_eventCount(0) { } + int eventCount() const { return m_eventCount; } +signals: + void eventCountChanged(int); +protected: + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + if (event->reason() == QGraphicsSceneContextMenuEvent::Mouse) { + m_eventCount++; + emit eventCountChanged(m_eventCount); + } + } +private: + int m_eventCount; +}; + +void tst_QDeclarativeMouseArea::preventContextMenu() +{ + // A MouseArea accepting Left, Middle and Right buttons should prevent context menu + // events with "Mouse" reason to hit the Item below. + + qmlRegisterType<ContextMenuEventReceiver>("Test", 1, 0, "ContextMenuEventReceiver"); + + QDeclarativeView *view = createView(); + view->setSource(QUrl::fromLocalFile(SRCDIR "/data/preventContextMenu.qml")); + view->show(); + QVERIFY(view->rootObject() != 0); + + QDeclarativeProperty mouseAreaEnabled(view->rootObject(), "mouseAreaEnabled"); + QVERIFY(mouseAreaEnabled.read().toBool()); + + QDeclarativeProperty eventsReceived(view->rootObject(), "eventsReceived"); + QCOMPARE(eventsReceived.read().toInt(), 0); + + QPoint targetPoint = view->mapFromScene(QPoint(80, 80)); + + QContextMenuEvent fakeEvent1(QContextMenuEvent::Mouse, targetPoint); + QApplication::sendEvent(view->viewport(), &fakeEvent1); + QCOMPARE(eventsReceived.read().toInt(), 0); + + mouseAreaEnabled.write(false); + QVERIFY(!mouseAreaEnabled.read().toBool()); + QContextMenuEvent fakeEvent2(QContextMenuEvent::Mouse, targetPoint); + QApplication::sendEvent(view->viewport(), &fakeEvent2); + QCOMPARE(eventsReceived.read().toInt(), 1); + + mouseAreaEnabled.write(true); + QVERIFY(mouseAreaEnabled.read().toBool()); + QContextMenuEvent fakeEvent3(QContextMenuEvent::Mouse, targetPoint); + QApplication::sendEvent(view->viewport(), &fakeEvent3); + QCOMPARE(eventsReceived.read().toInt(), 1); +} +#endif // QT_NO_CONTEXTMENU + QTEST_MAIN(tst_QDeclarativeMouseArea) #include "tst_qdeclarativemousearea.moc" |