Fix drag and drop with native widgets
authorjian liang <jianliang79@gmail.com>
Tue, 25 Sep 2012 13:33:55 +0000 (21:33 +0800)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 27 Sep 2012 21:51:30 +0000 (23:51 +0200)
Task-number: QTBUG-27336

Don't check 'widget != m_widget' in
QWidgetWindow::handleDragEnterMoveEvent() since the current window's
parent widget may be the actual drop target. I replace it with a check
'!widget->isWindow()' to prevent we pass through a top level window.
I also change 'widget->mapFrom(m_widget, event->pos())' to
'widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()))' since m_widget
may not be widget's parent.

Change-Id: Ia4f10f85ccdf1e27223ddc51afabd98b5d16f2fb
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
src/widgets/kernel/qwidgetwindow.cpp
tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp

index ad4b9c9..10ec4d3 100644 (file)
@@ -443,13 +443,13 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
     QWidget *widget = m_widget->childAt(event->pos());
     if (!widget)
         widget = m_widget;
-    for ( ; widget && widget != m_widget && !widget->acceptDrops(); widget = widget->parentWidget()) ;
+    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->mapFrom(m_widget, event->pos());
+        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());
         QGuiApplication::sendSpontaneousEvent(widget, &translated);
@@ -472,7 +472,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
          return;
     }
     m_dragTarget = widget;
-    const QPoint mapped = widget->mapFrom(m_widget, event->pos());
+    const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
     QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
     QGuiApplication::sendSpontaneousEvent(widget, &translated);
     if (translated.isAccepted()) {
@@ -492,7 +492,7 @@ void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
 
 void QWidgetWindow::handleDropEvent(QDropEvent *event)
 {
-    const QPoint mapped = m_dragTarget.data()->mapFrom(m_widget, event->pos());
+    const QPoint mapped = m_dragTarget.data()->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
     QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
     QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &translated);
     if (translated.isAccepted())
index 65284bf..230fceb 100644 (file)
@@ -409,7 +409,13 @@ static const char *expectedLogC[] = {
     "acceptingDropsWidget2::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
     "Event at 11,241 accepted",
     "acceptingDropsWidget2::dropEvent at 1,51 action=1 MIME_DATA_ADDRESS 'testmimetext'",
-    "Event at 11,261 accepted"
+    "Event at 11,261 accepted",
+    "acceptingDropsWidget1::dragEnterEvent at 10,10 action=1 MIME_DATA_ADDRESS 'testmimetext'",
+    "Event at 0,0 accepted",
+    "acceptingDropsWidget1::dragMoveEvent at 11,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
+    "Event at 1,1 accepted",
+    "acceptingDropsWidget1::dropEvent at 12,12 action=1 MIME_DATA_ADDRESS 'testmimetext'",
+    "Event at 2,2 accepted"
 };
 
 // A widget that logs the DnD events it receives into a QStringList.
@@ -497,6 +503,12 @@ void tst_QWidget_window::tst_dnd()
     dropsAcceptingWidget1->resize(180, 80);
     dropsAcceptingWidget1->move(10, 110);
 
+    // Create a native widget on top of dropsAcceptingWidget1 to check QTBUG-27336
+    QWidget *nativeWidget = new QWidget(dropsAcceptingWidget1);
+    nativeWidget->resize(160, 60);
+    nativeWidget->move(10, 10);
+    nativeWidget->winId();
+
     QWidget *dropsAcceptingWidget2 = new DnDEventLoggerWidget(&log, &dndTestWidget);
     dropsAcceptingWidget2->setAcceptDrops(true);
     dropsAcceptingWidget2->setObjectName(QLatin1String("acceptingDropsWidget2"));
@@ -535,6 +547,19 @@ void tst_QWidget_window::tst_dnd()
         }
     }
 
+    window = nativeWidget->windowHandle();
+    QDragEnterEvent enterEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier);
+    qApp->sendEvent(window, &enterEvent);
+    log.push_back(msgEventAccepted(enterEvent));
+
+    QDragMoveEvent moveEvent(QPoint(1, 1), Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier);
+    qApp->sendEvent(window, &moveEvent);
+    log.push_back(msgEventAccepted(moveEvent));
+
+    QDropEvent dropEvent(QPoint(2, 2), Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier);
+    qApp->sendEvent(window, &dropEvent);
+    log.push_back(msgEventAccepted(dropEvent));
+
     // Compare logs.
     QStringList expectedLog;
     const int expectedLogSize = int(sizeof(expectedLogC) / sizeof(expectedLogC[0]));