Quick Popup: ignore unhandled events
QQuickPopups event handling code deals with two concepts: the handling of events by the popup (accepting the event and becoming the grabber for the relevant device in case of press events), and the blocking of events to other items. For a plain popup that's ok, but events that aren't blocked by the popup must be ignored by it to that they propagate correctly. QQuickDrawer, which subclasses QQuickPopup and overrides the blocking logik (via QQuickDrawerPrivate::blockInput), conflates those two concepts, which is not ok as QQuickDrawer is interactive and may accept an event even if the event is not modally blocked. Press events that go to the content item of the drawer are never blocked, but must get accepted so that the drawer receives the following mouse moves. Fixes: QTBUG-93649 Pick-to: 6.3 6.2 Change-Id: I254ccd843dc0250d334abb9b1062e7feffb86beb Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
parent
1818d3dfcf
commit
f0b278c4d0
|
@ -430,6 +430,13 @@ bool QQuickDrawerPrivate::grabTouch(QQuickItem *item, QTouchEvent *event)
|
|||
|
||||
static const qreal openCloseVelocityThreshold = 300;
|
||||
|
||||
// Overrides QQuickPopupPrivate::blockInput, which is called by
|
||||
// QQuickPopupPrivate::handlePress/Move/Release, which we call in our own
|
||||
// handlePress/Move/Release overrides.
|
||||
// This implementation conflates two things: should the event going to the item get
|
||||
// modally blocked by us? Or should we accept the event and become the grabber?
|
||||
// Those are two fundamentally different questions for the drawer as a (usually)
|
||||
// interactive control.
|
||||
bool QQuickDrawerPrivate::blockInput(QQuickItem *item, const QPointF &point) const
|
||||
{
|
||||
Q_Q(const QQuickDrawer);
|
||||
|
@ -460,7 +467,7 @@ bool QQuickDrawerPrivate::handlePress(QQuickItem *item, const QPointF &point, ul
|
|||
velocityCalculator.startMeasuring(point, timestamp);
|
||||
|
||||
if (!QQuickPopupPrivate::handlePress(item, point, timestamp))
|
||||
return false;
|
||||
return interactive && popupItem == item;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2550,22 +2550,19 @@ void QQuickPopup::keyReleaseEvent(QKeyEvent *event)
|
|||
void QQuickPopup::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_D(QQuickPopup);
|
||||
d->handleMouseEvent(d->popupItem, event);
|
||||
event->accept();
|
||||
event->setAccepted(d->handleMouseEvent(d->popupItem, event));
|
||||
}
|
||||
|
||||
void QQuickPopup::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_D(QQuickPopup);
|
||||
d->handleMouseEvent(d->popupItem, event);
|
||||
event->accept();
|
||||
event->setAccepted(d->handleMouseEvent(d->popupItem, event));
|
||||
}
|
||||
|
||||
void QQuickPopup::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_D(QQuickPopup);
|
||||
d->handleMouseEvent(d->popupItem, event);
|
||||
event->accept();
|
||||
event->setAccepted(d->handleMouseEvent(d->popupItem, event));
|
||||
}
|
||||
|
||||
void QQuickPopup::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
|
|
|
@ -1441,4 +1441,80 @@ TestCase {
|
|||
compare(shortcutActivatedSpy.count, 2)
|
||||
tryCompare(control, "visible", false)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: mousePropagationComponent
|
||||
ApplicationWindow {
|
||||
id: window
|
||||
width: 360
|
||||
height: 360
|
||||
visible: true
|
||||
|
||||
property alias popup: popup
|
||||
property alias popupTitle: popupTitle
|
||||
|
||||
Popup {
|
||||
id: popup
|
||||
width: 200
|
||||
height: 200
|
||||
|
||||
background: Rectangle {
|
||||
color: "#505050"
|
||||
Rectangle {
|
||||
id: popupTitle
|
||||
width: parent.width
|
||||
height: 30
|
||||
color: "blue"
|
||||
|
||||
property point pressedPosition: Qt.point(0, 0)
|
||||
|
||||
MouseArea {
|
||||
enabled: true
|
||||
propagateComposedEvents: true
|
||||
anchors.fill: parent
|
||||
onPressed: (mouse) => {
|
||||
popupTitle.pressedPosition = Qt.point(mouse.x, mouse.y)
|
||||
}
|
||||
onPositionChanged: (mouse) => {
|
||||
popup.x += mouse.x - popupTitle.pressedPosition.x
|
||||
popup.y += mouse.y - popupTitle.pressedPosition.y
|
||||
}
|
||||
onReleased: (mouse) => {
|
||||
popupTitle.pressedPosition = Qt.point(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
x = parent.width / 2 - width / 2
|
||||
y = parent.height / 2 - height / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test_mousePropagation() {
|
||||
// Tests that Popup ignores mouse events that it doesn't handle itself
|
||||
// so that they propagate correctly.
|
||||
let window = createTemporaryObject(mousePropagationComponent, testCase)
|
||||
window.requestActivate()
|
||||
tryCompare(window, "active", true)
|
||||
|
||||
let popup = window.popup
|
||||
popup.open()
|
||||
let title = window.popupTitle
|
||||
verify(title)
|
||||
|
||||
let pressPoint = Qt.point(title.width / 2, title.height / 2)
|
||||
let oldPos = Qt.point(popup.x, popup.y)
|
||||
mousePress(title, pressPoint.x, pressPoint.y)
|
||||
fuzzyCompare(title.pressedPosition.x, pressPoint.x, 1)
|
||||
fuzzyCompare(title.pressedPosition.y, pressPoint.y, 1)
|
||||
mouseMove(title, pressPoint.x + 5, pressPoint.y + 5)
|
||||
fuzzyCompare(popup.x, oldPos.x + 5, 1)
|
||||
fuzzyCompare(popup.y, oldPos.y + 5, 1)
|
||||
mouseRelease(title, pressPoint.x, pressPoint.y)
|
||||
compare(title.pressedPosition, Qt.point(0, 0))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue