aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2011-08-01 16:20:26 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-02 06:42:28 +0200
commit1b65161042108ee46ca42331dacc2b66b63c6b4e (patch)
tree86827961301d01d59bbe72b944373293d8409984
parent9dfd621aec9a031297c50dd7df5ca90c771f46a3 (diff)
Allow descendant chains to simultaneously be hovered.
Matches GV behaviour. Also fixes a bug in QSGMouseArea, which we aren't fixing for QtQuick 1. Task-number: QTBUG-18175 Change-Id: I4ecac7b908504f28de830732c731281407d7b0bc Reviewed-on: http://codereview.qt.nokia.com/2422 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
-rw-r--r--src/declarative/items/qsgcanvas.cpp62
-rw-r--r--src/declarative/items/qsgcanvas_p.h4
-rw-r--r--src/declarative/items/qsgitem.cpp19
-rw-r--r--src/declarative/items/qsgmousearea.cpp2
-rw-r--r--tests/auto/declarative/qsgmousearea/data/hoverPropagation.qml54
-rw-r--r--tests/auto/declarative/qsgmousearea/tst_qsgmousearea.cpp26
6 files changed, 140 insertions, 27 deletions
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index ecb4e2b524..2efdd50c73 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -422,7 +422,6 @@ QSGCanvasPrivate::QSGCanvasPrivate()
: rootItem(0)
, activeFocusItem(0)
, mouseGrabberItem(0)
- , hoverItem(0)
, dirtyItemList(0)
, context(0)
, contextFailed(false)
@@ -955,17 +954,19 @@ QSGItem *QSGCanvas::mouseGrabberItem() const
}
-void QSGCanvasPrivate::clearHover()
+bool QSGCanvasPrivate::clearHover()
{
Q_Q(QSGCanvas);
- if (!hoverItem)
- return;
+ if (hoverItems.isEmpty())
+ return false;
QPointF pos = q->mapFromGlobal(QCursor::pos());
- QSGItem *item = hoverItem;
- hoverItem = 0;
- sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QApplication::keyboardModifiers(), true);
+ bool accepted = false;
+ foreach (QSGItem* item, hoverItems)
+ accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QApplication::keyboardModifiers(), true) || accepted;
+ hoverItems.clear();
+ return accepted;
}
@@ -1205,11 +1206,7 @@ void QSGCanvas::mouseMoveEvent(QMouseEvent *event)
bool delivered = d->deliverHoverEvent(d->rootItem, event->pos(), last, event->modifiers(), accepted);
if (!delivered) {
//take care of any exits
- if (d->hoverItem) {
- QSGItem *item = d->hoverItem;
- d->hoverItem = 0;
- accepted = d->sendHoverEvent(QEvent::HoverLeave, item, event->pos(), last, event->modifiers(), accepted);
- }
+ accepted = d->clearHover();
}
event->setAccepted(accepted);
return;
@@ -1247,20 +1244,43 @@ bool QSGCanvasPrivate::deliverHoverEvent(QSGItem *item, const QPointF &scenePos,
if (itemPrivate->hoverEnabled) {
QPointF p = item->mapFromScene(scenePos);
if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- if (hoverItem == item) {
+ if (!hoverItems.isEmpty() && hoverItems[0] == item) {
//move
accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
} else {
- //exit from previous
- if (hoverItem) {
- QSGItem *item = hoverItem;
- hoverItem = 0;
- accepted = sendHoverEvent(QEvent::HoverLeave, item, scenePos, lastScenePos, modifiers, accepted);
+ QList<QSGItem*> parents;
+ QSGItem* parent = item;
+ parents << item;
+ while ((parent = parent->parentItem()))
+ parents << parent;
+
+ //exit from previous (excepting ancestors)
+ while (!hoverItems.isEmpty() && !parents.contains(hoverItems[0])){
+ sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
+ hoverItems.removeFirst();
}
- //enter new item
- hoverItem = item;
- accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, accepted);
+ if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ } else {
+ //enter any ancestors that also wish to be hovered and aren't
+ int startIdx = -1;
+ if (!hoverItems.isEmpty())
+ startIdx = parents.indexOf(hoverItems[0]);
+ if (startIdx == -1)
+ startIdx = parents.count() - 1;
+
+ for (int i = startIdx; i >= 0; i--) {
+ if (QSGItemPrivate::get(parents[i])->hoverEnabled) {
+ hoverItems.prepend(parents[i]);
+ sendHoverEvent(QEvent::HoverEnter, parents[i], scenePos, lastScenePos, modifiers, accepted);
+ }
+ }
+
+ //enter new item
+ hoverItems.prepend(item);
+ accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, accepted);
+ }
}
return true;
}
diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h
index 20fc332e1b..d26b311e59 100644
--- a/src/declarative/items/qsgcanvas_p.h
+++ b/src/declarative/items/qsgcanvas_p.h
@@ -117,11 +117,11 @@ public:
bool deliverHoverEvent(QSGItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool sendHoverEvent(QEvent::Type, QSGItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, bool accepted);
- void clearHover();
+ bool clearHover();
void deliverDragEvent(QSGDragEvent *);
bool deliverDragEvent(QSGItem *item, QSGDragEvent *);
- QDeclarativeGuard<QSGItem> hoverItem;
+ QList<QSGItem*> hoverItems;
enum FocusOption {
DontChangeFocusProperty = 0x01,
};
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index 043c568a82..ef77bfda02 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -1161,6 +1161,8 @@ void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
c->itemsToPolish.remove(q);
if (c->mouseGrabberItem == q)
c->mouseGrabberItem = 0;
+ if ( hoverEnabled )
+ c->hoverItems.removeAll(q);
}
canvas = c;
@@ -3021,8 +3023,21 @@ void QSGItem::setAcceptHoverEvents(bool enabled)
Q_D(QSGItem);
d->hoverEnabled = enabled;
- if (d->canvas && d->hoverEnabled && !d->canvas->hasMouseTracking())
- d->canvas->setMouseTracking(true);
+ if (d->canvas){
+ QSGCanvasPrivate *c = QSGCanvasPrivate::get(d->canvas);
+ if (d->hoverEnabled){
+ if (!d->canvas->hasMouseTracking())
+ d->canvas->setMouseTracking(true);
+ if (isUnderMouse())
+ c->hoverItems.prepend(this);
+ c->sendHoverEvent(QEvent::HoverEnter, this, c->lastMousePosition, c->lastMousePosition,
+ QApplication::keyboardModifiers(), true);
+ } else {
+ c->hoverItems.removeAll(this);
+ c->sendHoverEvent(QEvent::HoverLeave, this, c->lastMousePosition, c->lastMousePosition,
+ QApplication::keyboardModifiers(), true);
+ }
+ }
}
void QSGItem::grabMouse()
diff --git a/src/declarative/items/qsgmousearea.cpp b/src/declarative/items/qsgmousearea.cpp
index ac577a4810..88a617fd71 100644
--- a/src/declarative/items/qsgmousearea.cpp
+++ b/src/declarative/items/qsgmousearea.cpp
@@ -834,8 +834,6 @@ void QSGMouseArea::setHoverEnabled(bool h)
setAcceptHoverEvents(h);
emit hoverEnabledChanged();
- if (d->hovered != isUnderMouse())
- setHovered(!d->hovered);
}
bool QSGMouseArea::hovered() const
diff --git a/tests/auto/declarative/qsgmousearea/data/hoverPropagation.qml b/tests/auto/declarative/qsgmousearea/data/hoverPropagation.qml
new file mode 100644
index 0000000000..c47c794132
--- /dev/null
+++ b/tests/auto/declarative/qsgmousearea/data/hoverPropagation.qml
@@ -0,0 +1,54 @@
+import QtQuick 2.0
+
+Item{
+ width: 400
+ height: 200
+ property bool point1: ma2.containsMouse && !ma1.containsMouse
+ property bool point2: ma3.containsMouse && ma4.containsMouse
+ Rectangle{
+ width: 200
+ height: 200
+ color: ma1.containsMouse ? "red" : "white"
+ MouseArea{
+ id: ma1
+ hoverEnabled: true
+ anchors.fill: parent
+ }
+ Rectangle{
+ width: 100
+ height: 100
+ color: ma2.containsMouse ? "blue" : "white"
+ MouseArea{
+ id: ma2
+ hoverEnabled: true
+ anchors.fill: parent
+ }
+ }
+ }
+
+ Item{
+ x:200
+ Rectangle{
+ width: 200
+ height: 200
+ color: ma3.containsMouse ? "yellow" : "white"
+ Rectangle{
+ width: 100
+ height: 100
+ color: ma4.containsMouse ? "green" : "white"
+ }
+ }
+ MouseArea{
+ id: ma3
+ hoverEnabled: true
+ width: 200
+ height: 200
+ MouseArea{
+ id: ma4
+ width: 100
+ height: 100
+ hoverEnabled: true
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgmousearea/tst_qsgmousearea.cpp b/tests/auto/declarative/qsgmousearea/tst_qsgmousearea.cpp
index 8e711e6ceb..e9788cd147 100644
--- a/tests/auto/declarative/qsgmousearea/tst_qsgmousearea.cpp
+++ b/tests/auto/declarative/qsgmousearea/tst_qsgmousearea.cpp
@@ -75,6 +75,7 @@ private slots:
void testQtQuick11Attributes();
void testQtQuick11Attributes_data();
void hoverPosition();
+ void hoverPropagation();
private:
QSGView *createView();
@@ -741,6 +742,31 @@ void tst_QSGMouseArea::hoverPosition()
delete canvas;
}
+void tst_QSGMouseArea::hoverPropagation()
+{
+ //QTBUG-18175, to behave like GV did.
+ QSGView *canvas = createView();
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/hoverPropagation.qml"));
+
+ QSGItem *root = canvas->rootObject();
+ QVERIFY(root != 0);
+
+ QCOMPARE(root->property("point1").toBool(), false);
+ QCOMPARE(root->property("point2").toBool(), false);
+
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+ QCOMPARE(root->property("point1").toBool(), true);
+ QCOMPARE(root->property("point2").toBool(), false);
+
+ QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent2);
+ QCOMPARE(root->property("point1").toBool(), false);
+ QCOMPARE(root->property("point2").toBool(), true);
+
+ delete canvas;
+}
+
QTEST_MAIN(tst_QSGMouseArea)
#include "tst_qsgmousearea.moc"