MouseArea: don't get stuck in pressed state when disabling in press
In 8ace780b5a
we fixed the case when
MouseArea hides itself on press. This time, the concern is when it
becomes _effectively_ disabled by disabling its parent on press.
(As explained in a comment on QTBUG-38364, the MouseArea.enabled state
is independent, but we can nevertheless also find out when the effective
enabled state changes.)
[ChangeLog][QtQuick][MouseArea] When a MouseArea becomes effectively
disabled due to a parent's enabled property being set false while the
mouse is pressed, the press will now be canceled.
Fixes: QTBUG-39806
Fixes: QTBUG-103788
Change-Id: I8d69b535b6e1b5d51ad1e030f52217de9ab541f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
51ddad5ffd
commit
61a9612f5b
|
@ -1038,6 +1038,12 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
|
|||
{
|
||||
Q_D(QQuickMouseArea);
|
||||
switch (change) {
|
||||
case ItemEnabledHasChanged:
|
||||
// If MouseArea becomes effectively disabled by disabling a parent
|
||||
// (for example, onPressed: parent.enabled = false), cancel the pressed state.
|
||||
if (d->pressed && !d->effectiveEnable)
|
||||
ungrabMouse();
|
||||
break;
|
||||
case ItemVisibleHasChanged:
|
||||
if (d->effectiveEnable && d->enabled && hoverEnabled() && d->hovered != (isVisible() && isUnderMouse())) {
|
||||
if (!d->hovered) {
|
||||
|
@ -1048,7 +1054,7 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
|
|||
setHovered(!d->hovered);
|
||||
}
|
||||
if (d->pressed && (!isVisible())) {
|
||||
// This happens when the mouse area sets itself disabled or hidden
|
||||
// This happens when the mouse area hides itself
|
||||
// inside the press handler. In that case we should not keep the internal
|
||||
// state as pressed, since we never became the mouse grabber.
|
||||
ungrabMouse();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import QtQuick
|
||||
|
||||
Rectangle {
|
||||
id: whiteRect
|
||||
width: 200
|
||||
height: 200
|
||||
color: ma.pressed ? "lightsteelblue" : "white"
|
||||
MouseArea {
|
||||
id: ma
|
||||
objectName: "mousearea"
|
||||
anchors.fill: parent
|
||||
onPressed: parent.enabled = false
|
||||
}
|
||||
}
|
|
@ -110,6 +110,8 @@ private slots:
|
|||
void subtreeHoverEnabled();
|
||||
void hoverWhenDisabled();
|
||||
void disableAfterPress();
|
||||
void disableParentOnPress_data();
|
||||
void disableParentOnPress();
|
||||
void onWheel();
|
||||
void transformedMouseArea_data();
|
||||
void transformedMouseArea();
|
||||
|
@ -1532,6 +1534,53 @@ void tst_QQuickMouseArea::disableAfterPress()
|
|||
QCOMPARE(mouseReleaseSpy.size(), 0);
|
||||
}
|
||||
|
||||
void tst_QQuickMouseArea::disableParentOnPress_data()
|
||||
{
|
||||
QTest::addColumn<const QPointingDevice *>("device");
|
||||
|
||||
QTest::newRow("core pointer") << QPointingDevice::primaryPointingDevice();
|
||||
QTest::newRow("touch") << device;
|
||||
}
|
||||
|
||||
void tst_QQuickMouseArea::disableParentOnPress() // QTBUG-39806 and QTBUG-103788
|
||||
{
|
||||
QFETCH(const QPointingDevice *, device);
|
||||
|
||||
QQuickView window;
|
||||
QVERIFY(QQuickTest::showView(window, testFileUrl("disableParentOnPress.qml")));
|
||||
QQuickItem *root = window.rootObject();
|
||||
QVERIFY(root);
|
||||
QQuickMouseArea *mouseArea = root->findChild<QQuickMouseArea*>();
|
||||
QVERIFY(mouseArea);
|
||||
|
||||
QSignalSpy pressedChangedSpy(mouseArea, &QQuickMouseArea::pressedChanged);
|
||||
QSignalSpy canceledSpy(mouseArea, &QQuickMouseArea::canceled);
|
||||
QSignalSpy enabledSpy(mouseArea, &QQuickMouseArea::enabledChanged);
|
||||
QSignalSpy parentEnabledSpy(root, &QQuickItem::enabledChanged);
|
||||
const QPoint p(100, 100);
|
||||
|
||||
QQuickTest::pointerPress(device, &window, 0, p);
|
||||
QTRY_COMPARE(parentEnabledSpy.size(), 1);
|
||||
QCOMPARE(root->isEnabled(), false);
|
||||
QCOMPARE(mouseArea->isEnabled(), true); // enabled is independent, unfortunately (inverse of QTBUG-38364)
|
||||
QCOMPARE(QQuickItemPrivate::get(mouseArea)->effectiveEnable, false);
|
||||
// bug fix: it knows it got effectively disabled, so now it's no longer pressed
|
||||
QCOMPARE(mouseArea->pressed(), false);
|
||||
QCOMPARE(canceledSpy.size(), 1); // ...because the press was canceled
|
||||
QCOMPARE(pressedChangedSpy.size(), 2); // kerchunk
|
||||
QQuickTest::pointerRelease(device, &window, 0, p);
|
||||
|
||||
// now re-enable it and try again
|
||||
root->setEnabled(true);
|
||||
QQuickTest::pointerPress(device, &window, 0, p);
|
||||
QTRY_COMPARE(root->isEnabled(), false);
|
||||
QCOMPARE(QQuickItemPrivate::get(mouseArea)->effectiveEnable, false);
|
||||
QCOMPARE(mouseArea->pressed(), false);
|
||||
QCOMPARE(canceledSpy.size(), 2);
|
||||
QCOMPARE(pressedChangedSpy.size(), 4);
|
||||
QQuickTest::pointerRelease(device, &window, 0, p);
|
||||
}
|
||||
|
||||
void tst_QQuickMouseArea::onWheel()
|
||||
{
|
||||
QQuickView window;
|
||||
|
|
Loading…
Reference in New Issue