Skip to content

Commit

Permalink
Merge pull request #81 from adenexter/jb32349
Browse files Browse the repository at this point in the history
Don't send delayed mouse presses to ancestors of the replaying Flickable.
  • Loading branch information
Chris Adams committed Oct 16, 2015
2 parents 4d85d43 + 4eb5dee commit 69670fb
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 10 deletions.
6 changes: 1 addition & 5 deletions src/quick/items/qquickflickable.cpp
Expand Up @@ -301,7 +301,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate()
, vData(this, &QQuickFlickablePrivate::setViewportY)
, hMoved(false), vMoved(false)
, stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
, pixelAligned(false), replayingPressEvent(false)
, pixelAligned(false)
, lastPosTime(-1)
, lastPressTime(0)
, deceleration(FlickDefaultDeceleration)
Expand Down Expand Up @@ -2129,10 +2129,6 @@ bool QQuickFlickable::sendMouseEvent(QQuickItem *item, QMouseEvent *event)
d->handleMouseMoveEvent(mouseEvent.data());
break;
case QEvent::MouseButtonPress:
// Don't process a replayed event during replay
if (d->replayingPressEvent)
return false;

d->handleMousePressEvent(mouseEvent.data());
d->captureDelayedPress(item, event);
stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
Expand Down
1 change: 0 additions & 1 deletion src/quick/items/qquickflickable_p_p.h
Expand Up @@ -214,7 +214,6 @@ class Q_AUTOTEST_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate, publi
bool interactive : 1;
bool calcVelocity : 1;
bool pixelAligned : 1;
bool replayingPressEvent : 1;
QElapsedTimer timer;
qint64 lastPosTime;
qint64 lastPressTime;
Expand Down
1 change: 1 addition & 0 deletions src/quick/items/qquickitem.cpp
Expand Up @@ -2775,6 +2775,7 @@ QQuickItemPrivate::QQuickItemPrivate()
, hasCursor(false)
, hasCursorInChild(false)
, activeFocusOnTab(false)
, replayingPressEvent(false)
, dirtyAttributes(0)
, nextDirtyItem(0)
, prevDirtyItem(0)
Expand Down
1 change: 1 addition & 0 deletions src/quick/items/qquickitem_p.h
Expand Up @@ -425,6 +425,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickItemPrivate : public QObjectPrivate
// Bit 32
bool hasCursorInChild:1;
bool activeFocusOnTab:1;
bool replayingPressEvent:1;

enum DirtyType {
TransformOrigin = 0x00000001,
Expand Down
6 changes: 4 additions & 2 deletions src/quick/items/qquickwindow.cpp
Expand Up @@ -2330,9 +2330,11 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem
if (!target)
return false;

bool filtered = false;

QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->replayingPressEvent)
return false;

bool filtered = false;
if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
hasFiltered->insert(target);
if (target->childMouseEventFilter(item, event))
Expand Down
10 changes: 8 additions & 2 deletions tests/auto/quick/qquickflickable/data/nestedPressDelay.qml
Expand Up @@ -8,12 +8,18 @@ Flickable {
contentHeight: 320
flickableDirection: Flickable.HorizontalFlick
pressDelay: 10000
Rectangle {
MouseArea {
objectName: "filteringMouseArea"
x: 20
y: 20
width: 400
height: 300
color: "yellow"
drag.filterChildren: true
Rectangle {
id: rectangle
color: "yellow"
anchors.fill: parent
}
Flickable {
objectName: "innerFlickable"
anchors.fill: parent
Expand Down
43 changes: 43 additions & 0 deletions tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
Expand Up @@ -75,6 +75,7 @@ private slots:
void flickDeceleration();
void pressDelay();
void nestedPressDelay();
void filterReplayedPress();
void nestedClickThenFlick();
void flickableDirection();
void resizeContent();
Expand Down Expand Up @@ -514,6 +515,48 @@ void tst_qquickflickable::nestedPressDelay()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150));
}

void tst_qquickflickable::filterReplayedPress()
{
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("nestedPressDelay.qml"));
QTRY_COMPARE(window->status(), QQuickView::Ready);
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QVERIFY(window->rootObject() != 0);

QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(outer != 0);

QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
QVERIFY(inner != 0);

QQuickItem *filteringMouseArea = outer->findChild<QQuickItem *>("filteringMouseArea");
QVERIFY(filteringMouseArea);

moveAndPress(window.data(), QPoint(150, 150));
// the MouseArea filtering the Flickable is pressed immediately.
QCOMPARE(filteringMouseArea->property("pressed").toBool(), true);

// Some event causes the mouse area to set keepMouseGrab.
filteringMouseArea->setKeepMouseGrab(true);
QCOMPARE(filteringMouseArea->keepMouseGrab(), true);

// The inner pressDelay will prevail (50ms, vs. 10sec)
// QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
QTRY_VERIFY(outer->property("pressed").toBool());

// The replayed press event isn't delivered to parent items of the
// flickable with the press delay, and the state of the parent mouse
// area is therefore unaffected.
QCOMPARE(filteringMouseArea->property("pressed").toBool(), true);
QCOMPARE(filteringMouseArea->keepMouseGrab(), true);

QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
}


// QTBUG-37316
void tst_qquickflickable::nestedClickThenFlick()
{
Expand Down

0 comments on commit 69670fb

Please sign in to comment.