widgetwindow: send DragMove for every DragEnter
... as specified in the documentation. This was a regression from Qt4 and can cause mouse cursor flickering durig dragging on e.g. custom widget where some areas of the widget do not accept drag-and-drop. Task-number: QTBUG-67155 Change-Id: Iaa6f9407181931ed8e3d6a8fec13fd59d3c8625d Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
7a7c722782
commit
f8944a7f07
@ -311,8 +311,10 @@ bool QWidgetWindow::event(QEvent *event)
|
|||||||
|
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
case QEvent::DragEnter:
|
case QEvent::DragEnter:
|
||||||
|
handleDragEnterEvent(static_cast<QDragEnterEvent *>(event));
|
||||||
|
return true;
|
||||||
case QEvent::DragMove:
|
case QEvent::DragMove:
|
||||||
handleDragEnterMoveEvent(static_cast<QDragMoveEvent *>(event));
|
handleDragMoveEvent(static_cast<QDragMoveEvent *>(event));
|
||||||
return true;
|
return true;
|
||||||
case QEvent::DragLeave:
|
case QEvent::DragLeave:
|
||||||
handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
|
handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
|
||||||
@ -849,62 +851,80 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
|
|||||||
|
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
|
|
||||||
void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
|
static QWidget *findDnDTarget(QWidget *parent, const QPoint &pos)
|
||||||
{
|
{
|
||||||
Q_ASSERT(event->type() ==QEvent::DragMove || !m_dragTarget);
|
|
||||||
// Find a target widget under mouse that accepts drops (QTBUG-22987).
|
// Find a target widget under mouse that accepts drops (QTBUG-22987).
|
||||||
QWidget *widget = m_widget->childAt(event->pos());
|
QWidget *widget = parent->childAt(pos);
|
||||||
if (!widget)
|
if (!widget)
|
||||||
widget = m_widget;
|
widget = parent;
|
||||||
for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ;
|
for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ;
|
||||||
if (widget && !widget->acceptDrops())
|
if (widget && !widget->acceptDrops())
|
||||||
widget = 0;
|
widget = nullptr;
|
||||||
// Target widget unchanged: DragMove
|
return widget;
|
||||||
if (widget && widget == m_dragTarget.data()) {
|
}
|
||||||
Q_ASSERT(event->type() == QEvent::DragMove);
|
|
||||||
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget)
|
||||||
QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
|
{
|
||||||
translated.setDropAction(event->dropAction());
|
Q_ASSERT(m_dragTarget == nullptr);
|
||||||
if (event->isAccepted()) { // Handling 'DragEnter' should suffice for the application.
|
if (!widget)
|
||||||
translated.accept();
|
widget = findDnDTarget(m_widget, event->pos());
|
||||||
translated.setDropAction(event->dropAction());
|
if (!widget) {
|
||||||
}
|
event->ignore();
|
||||||
QGuiApplication::forwardEvent(widget, &translated, event);
|
|
||||||
if (translated.isAccepted()) {
|
|
||||||
event->accept();
|
|
||||||
} else {
|
|
||||||
event->ignore();
|
|
||||||
}
|
|
||||||
event->setDropAction(translated.dropAction());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Target widget changed: Send DragLeave to previous, DragEnter to new if there is any
|
|
||||||
if (m_dragTarget.data()) {
|
|
||||||
QDragLeaveEvent le;
|
|
||||||
QGuiApplication::forwardEvent(m_dragTarget.data(), &le, event);
|
|
||||||
m_dragTarget = 0;
|
|
||||||
}
|
|
||||||
if (!widget) {
|
|
||||||
event->ignore();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_dragTarget = widget;
|
m_dragTarget = widget;
|
||||||
|
|
||||||
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
||||||
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
|
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
|
||||||
QGuiApplication::forwardEvent(widget, &translated, event);
|
event->mouseButtons(), event->keyboardModifiers());
|
||||||
if (translated.isAccepted()) {
|
translated.setDropAction(event->dropAction());
|
||||||
event->accept();
|
translated.setAccepted(event->isAccepted());
|
||||||
} else {
|
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
|
||||||
event->ignore();
|
event->setAccepted(translated.isAccepted());
|
||||||
}
|
|
||||||
event->setDropAction(translated.dropAction());
|
event->setDropAction(translated.dropAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
|
||||||
|
{
|
||||||
|
auto *widget = findDnDTarget(m_widget, event->pos());
|
||||||
|
if (!widget) {
|
||||||
|
event->ignore();
|
||||||
|
if (m_dragTarget) { // Send DragLeave to previous
|
||||||
|
QDragLeaveEvent leaveEvent;
|
||||||
|
QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
|
||||||
|
m_dragTarget = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
||||||
|
QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(),
|
||||||
|
event->mouseButtons(), event->keyboardModifiers());
|
||||||
|
translated.setDropAction(event->dropAction());
|
||||||
|
translated.setAccepted(event->isAccepted());
|
||||||
|
|
||||||
|
if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove
|
||||||
|
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
|
||||||
|
} else {
|
||||||
|
if (m_dragTarget) { // Send DragLeave to previous
|
||||||
|
QDragLeaveEvent leaveEvent;
|
||||||
|
QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
|
||||||
|
m_dragTarget = nullptr;
|
||||||
|
}
|
||||||
|
// Send DragEnter to new widget.
|
||||||
|
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
|
||||||
|
// The drag enter event is always immediately followed by a drag move event,
|
||||||
|
// see QDragEnterEvent documentation.
|
||||||
|
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
|
||||||
|
}
|
||||||
|
event->setAccepted(translated.isAccepted());
|
||||||
|
event->setDropAction(translated.dropAction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
|
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
|
||||||
{
|
{
|
||||||
if (m_dragTarget)
|
if (m_dragTarget)
|
||||||
QGuiApplication::forwardEvent(m_dragTarget.data(), event);
|
QGuiApplication::forwardEvent(m_dragTarget, event);
|
||||||
m_dragTarget = 0;
|
m_dragTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWidgetWindow::handleDropEvent(QDropEvent *event)
|
void QWidgetWindow::handleDropEvent(QDropEvent *event)
|
||||||
@ -914,13 +934,12 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
|
|||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const QPoint mapped = m_dragTarget.data()->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
const QPoint mapped = m_dragTarget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
|
||||||
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
|
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
|
||||||
QGuiApplication::forwardEvent(m_dragTarget.data(), &translated, event);
|
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
|
||||||
if (translated.isAccepted())
|
event->setAccepted(translated.isAccepted());
|
||||||
event->accept();
|
|
||||||
event->setDropAction(translated.dropAction());
|
event->setDropAction(translated.dropAction());
|
||||||
m_dragTarget = 0;
|
m_dragTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QT_CONFIG(draganddrop)
|
#endif // QT_CONFIG(draganddrop)
|
||||||
|
@ -96,7 +96,8 @@ protected:
|
|||||||
void handleWheelEvent(QWheelEvent *);
|
void handleWheelEvent(QWheelEvent *);
|
||||||
#endif
|
#endif
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
void handleDragEnterMoveEvent(QDragMoveEvent *);
|
void handleDragEnterEvent(QDragEnterEvent *, QWidget *widget = nullptr);
|
||||||
|
void handleDragMoveEvent(QDragMoveEvent *);
|
||||||
void handleDragLeaveEvent(QDragLeaveEvent *);
|
void handleDragLeaveEvent(QDragLeaveEvent *);
|
||||||
void handleDropEvent(QDropEvent *);
|
void handleDropEvent(QDropEvent *);
|
||||||
#endif
|
#endif
|
||||||
|
@ -423,6 +423,7 @@ static const char *expectedLogC[] = {
|
|||||||
"Event at 11,81 ignored",
|
"Event at 11,81 ignored",
|
||||||
"Event at 11,101 ignored",
|
"Event at 11,101 ignored",
|
||||||
"acceptingDropsWidget1::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
"acceptingDropsWidget1::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
|
"acceptingDropsWidget1::dragMoveEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
"Event at 11,121 accepted",
|
"Event at 11,121 accepted",
|
||||||
"acceptingDropsWidget1::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
"acceptingDropsWidget1::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
"Event at 11,141 accepted",
|
"Event at 11,141 accepted",
|
||||||
@ -433,6 +434,7 @@ static const char *expectedLogC[] = {
|
|||||||
"acceptingDropsWidget1::dragLeaveEvent QDragLeaveEvent",
|
"acceptingDropsWidget1::dragLeaveEvent QDragLeaveEvent",
|
||||||
"Event at 11,201 ignored",
|
"Event at 11,201 ignored",
|
||||||
"acceptingDropsWidget2::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
"acceptingDropsWidget2::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
|
"acceptingDropsWidget2::dragMoveEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
"Event at 11,221 accepted",
|
"Event at 11,221 accepted",
|
||||||
"acceptingDropsWidget2::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
"acceptingDropsWidget2::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
|
||||||
"Event at 11,241 accepted",
|
"Event at 11,241 accepted",
|
||||||
|
Loading…
Reference in New Issue
Block a user