summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2018-05-11 09:45:12 +0200
committerGatis Paeglis <gatis.paeglis@qt.io>2018-06-25 12:45:54 +0000
commitf8944a7f07112c85dc4f66848cabb490514cd28e (patch)
tree421a8faf42ea55920d5d634927e2e1a0124c3df0 /src
parent7a7c722782a435f7c01b94f48df7a5f4ff4d599e (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp111
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
2 files changed, 67 insertions, 47 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 5603c7cb20..1c73588b7c 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -311,8 +311,10 @@ bool QWidgetWindow::event(QEvent *event)
#if QT_CONFIG(draganddrop)
case QEvent::DragEnter:
+ handleDragEnterEvent(static_cast<QDragEnterEvent *>(event));
+ return true;
case QEvent::DragMove:
- handleDragEnterMoveEvent(static_cast<QDragMoveEvent *>(event));
+ handleDragMoveEvent(static_cast<QDragMoveEvent *>(event));
return true;
case QEvent::DragLeave:
handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
@@ -849,62 +851,80 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
#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).
- QWidget *widget = m_widget->childAt(event->pos());
+ QWidget *widget = parent->childAt(pos);
if (!widget)
- widget = m_widget;
+ widget = parent;
for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ;
if (widget && !widget->acceptDrops())
- widget = 0;
- // Target widget unchanged: DragMove
- if (widget && widget == m_dragTarget.data()) {
- Q_ASSERT(event->type() == QEvent::DragMove);
- 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());
- if (event->isAccepted()) { // Handling 'DragEnter' should suffice for the application.
- translated.accept();
- translated.setDropAction(event->dropAction());
- }
- QGuiApplication::forwardEvent(widget, &translated, event);
- if (translated.isAccepted()) {
- event->accept();
- } else {
- event->ignore();
- }
- event->setDropAction(translated.dropAction());
- 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;
- }
+ widget = nullptr;
+ return widget;
+}
+
+void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget)
+{
+ Q_ASSERT(m_dragTarget == nullptr);
+ if (!widget)
+ widget = findDnDTarget(m_widget, event->pos());
if (!widget) {
- event->ignore();
- return;
+ event->ignore();
+ return;
}
m_dragTarget = widget;
+
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
- QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::forwardEvent(widget, &translated, event);
- if (translated.isAccepted()) {
- event->accept();
- } else {
+ QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
+ event->mouseButtons(), event->keyboardModifiers());
+ translated.setDropAction(event->dropAction());
+ translated.setAccepted(event->isAccepted());
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ event->setAccepted(translated.isAccepted());
+ 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());
}
- event->setDropAction(translated.dropAction());
}
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
{
if (m_dragTarget)
- QGuiApplication::forwardEvent(m_dragTarget.data(), event);
- m_dragTarget = 0;
+ QGuiApplication::forwardEvent(m_dragTarget, event);
+ m_dragTarget = nullptr;
}
void QWidgetWindow::handleDropEvent(QDropEvent *event)
@@ -914,13 +934,12 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
event->ignore();
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());
- QGuiApplication::forwardEvent(m_dragTarget.data(), &translated, event);
- if (translated.isAccepted())
- event->accept();
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());
- m_dragTarget = 0;
+ m_dragTarget = nullptr;
}
#endif // QT_CONFIG(draganddrop)
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index ead099390e..0728135467 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -96,7 +96,8 @@ protected:
void handleWheelEvent(QWheelEvent *);
#endif
#if QT_CONFIG(draganddrop)
- void handleDragEnterMoveEvent(QDragMoveEvent *);
+ void handleDragEnterEvent(QDragEnterEvent *, QWidget *widget = nullptr);
+ void handleDragMoveEvent(QDragMoveEvent *);
void handleDragLeaveEvent(QDragLeaveEvent *);
void handleDropEvent(QDropEvent *);
#endif