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 <shawn.rutledge@qt.io>
This commit is contained in:
Alexander Volkov 2020-04-30 15:15:12 +03:00
parent 45ed28a9d3
commit af3caa2271
3 changed files with 30 additions and 5 deletions

View File

@ -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<QMouseEvent *>(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();
}

View File

@ -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

View File

@ -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