From af3caa2271f47ddf48da46a0cc5932aaa442eb39 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 30 Apr 2020 15:15:12 +0300 Subject: QBasicDrag: Send QDragMoveEvent when modifiers change ... without moving the mouse. This allows to update drop action and cursor. Task-number: QTBUG-56218 Task-number: QTBUG-82934 Pick-to: 5.15 Change-Id: I8b0ac2a008a9dbcc4c2d6abce282e6f169c2f542 Reviewed-by: Shawn Rutledge --- src/gui/kernel/qsimpledrag.cpp | 7 ++++-- src/gui/kernel/qsimpledrag_p.h | 1 + .../kernel/qwidget_window/tst_qwidget_window.cpp | 27 +++++++++++++++++++--- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index dec3cc399d..55e92d2a5d 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -145,15 +145,17 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) disableEventFilter(); exitDndEventLoop(); + } else if (ke->modifiers() != QGuiApplication::keyboardModifiers()) { + move(m_lastPos, QGuiApplication::mouseButtons(), ke->modifiers()); } return true; // Eat all key events } case QEvent::MouseMove: { - QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); + m_lastPos = getNativeMousePos(e, m_drag_icon_window); auto mouseMove = static_cast(e); - move(nativePosition, mouseMove->buttons(), mouseMove->modifiers()); + move(m_lastPos, mouseMove->buttons(), mouseMove->modifiers()); return true; // Eat all mouse move events } case QEvent::MouseButtonRelease: @@ -230,6 +232,7 @@ void QBasicDrag::startDrag() pos = QPoint(); } #endif + m_lastPos = pos; recreateShapedPixmapWindow(m_screen, pos); enableEventFilter(); } diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index 8638b05155..4409deb1da 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -126,6 +126,7 @@ private: QShapedPixmapWindow *m_drag_icon_window = nullptr; bool m_useCompositing = true; QScreen *m_screen = nullptr; + QPoint m_lastPos; }; class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 12d60a33c2..72fa32a1b1 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -725,7 +725,7 @@ protected: { e->accept(); _dndEvents.append(QStringLiteral("DragMove ")); - emit releaseMouseButton(); + emit dragMoveReceived(); } void dragLeaveEvent(QDragLeaveEvent *e) { @@ -739,7 +739,7 @@ protected: } signals: - void releaseMouseButton(); + void dragMoveReceived(); }; void tst_QWidget_window::tst_dnd_events() @@ -774,7 +774,7 @@ void tst_QWidget_window::tst_dnd_events() // Some dnd implementation rely on running internal event loops, so we have to use // the following queued signal hack to simulate mouse clicks in the widget. - QObject::connect(&dndWidget, &DnDEventRecorder::releaseMouseButton, this, [=]() { + QObject::connect(&dndWidget, &DnDEventRecorder::dragMoveReceived, this, [=]() { QTest::mouseRelease(window, Qt::LeftButton); }, Qt::QueuedConnection); @@ -783,6 +783,27 @@ void tst_QWidget_window::tst_dnd_events() QTest::mousePress(window, Qt::LeftButton); QCOMPARE(dndWidget._dndEvents, expectedDndEvents); + + dndWidget._dndEvents.clear(); + dndWidget.disconnect(); + int step = 0; + QObject::connect(&dndWidget, &DnDEventRecorder::dragMoveReceived, this, [window, &step]() { + switch (step++) { + case 0: + QTest::keyPress(window, Qt::Key_Shift, Qt::ShiftModifier); + break; + case 1: + QTest::keyRelease(window, Qt::Key_Shift, Qt::NoModifier); + break; + default: + QTest::mouseRelease(window, Qt::LeftButton); + break; + } + }, Qt::QueuedConnection); + + QTest::mousePress(window, Qt::LeftButton); + const QString expectedDndWithModsEvents = "DragEnter DragMove DragMove DragMove DropEvent "; + QCOMPARE(dndWidget._dndEvents, expectedDndWithModsEvents); } class DropTarget : public QWidget -- cgit v1.2.3