diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 55fc3b09fc..614c5a2a04 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -146,6 +146,8 @@ QDragManager::QDragManager() #ifdef Q_WS_X11 xdndMimeTransferedPixmapIndex = 0; #endif + + currentWindow = 0; } diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index cc74889bcb..031ed13608 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -251,6 +251,7 @@ public: void setCurrentTarget(QObject *target, bool dropped = false); QObject *currentTarget(); + QWindow *currentWindow; #ifdef Q_WS_X11 QPixmap xdndMimeTransferedPixmap[2]; diff --git a/src/gui/kernel/qdnd_qpa.cpp b/src/gui/kernel/qdnd_qpa.cpp index e5715bb568..88a98caeaf 100644 --- a/src/gui/kernel/qdnd_qpa.cpp +++ b/src/gui/kernel/qdnd_qpa.cpp @@ -112,7 +112,7 @@ public: // } else { // clearMask(); // } -// resize(pm.width(),pm.height()); + setGeometry(QRect(geometry().topLeft(), pm.size())); } // ### Get it painted again! @@ -181,10 +181,8 @@ void QDragManager::updateCursor() bool QDragManager::eventFilter(QObject *o, QEvent *e) { -#if 0 - // ### - if (beingCancelled) { - if (e->type() == QEvent::KeyRelease && static_cast(e)->key() == Qt::Key_Escape) { + if (beingCancelled) { + if (e->type() == QEvent::KeyRelease && static_cast(e)->key() == Qt::Key_Escape) { qApp->removeEventFilter(this); Q_ASSERT(object == 0); beingCancelled = false; @@ -195,8 +193,8 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) } - - if (!o->isWidgetType()) + QWindow *window = qobject_cast(o); + if (!window) return false; switch(e->type()) { @@ -220,61 +218,57 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) return true; // Eat all key events } + case QEvent::Enter: + { + // don't do anything here, it's the first move event inside the window that + // will be used + break; + } + case QEvent::Leave: + { + currentWindow = 0; + QDragLeaveEvent dle; + QCoreApplication::sendEvent(o, &dle); + break; + } + case QEvent::MouseButtonPress: case QEvent::MouseMove: { - if (!object) { //#### this should not happen - qWarning("QDragManager::eventFilter: No object"); - return true; - } - - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; - if (manager->object) - possible_actions = manager->dragPrivate()->possible_actions; + QMimeData *dropData = object ? dragPrivate()->data : this->dropData; + if (object) + possible_actions = dragPrivate()->possible_actions; else possible_actions = Qt::IgnoreAction; QMouseEvent *me = (QMouseEvent *)e; if (me->buttons()) { Qt::DropAction prevAction = global_accepted_action; - QWidget *cw = QApplication::widgetAt(me->globalPos()); - // Fix for when we move mouse on to the deco widget - if (qt_qws_dnd_deco && cw == qt_qws_dnd_deco) - cw = object->target(); - - while (cw && !cw->acceptDrops() && !cw->isWindow()) - cw = cw->parentWidget(); - - if (object->target() != cw) { - if (object->target()) { + if (currentWindow != window) { + if (currentWindow) { QDragLeaveEvent dle; - QCoreApplication::sendEvent(object->target(), &dle); + QCoreApplication::sendEvent(currentWindow, &dle); willDrop = false; global_accepted_action = Qt::IgnoreAction; updateCursor(); restoreCursor = true; - object->d_func()->target = 0; } - if (cw && cw->acceptDrops()) { - object->d_func()->target = cw; - QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); - QCoreApplication::sendEvent(object->target(), &dee); - willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; - global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; - updateCursor(); - restoreCursor = true; - } - } else if (cw) { - QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); + currentWindow = window; + QDragEnterEvent dee(me->pos(), possible_actions, dropData, me->buttons(), me->modifiers()); + QCoreApplication::sendEvent(currentWindow, &dee); + willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; + global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; + updateCursor(); + restoreCursor = true; + } else { + Q_ASSERT(currentWindow); + QDragMoveEvent dme(me->pos(), possible_actions, dropData, me->buttons(), me->modifiers()); if (global_accepted_action != Qt::IgnoreAction) { dme.setDropAction(global_accepted_action); dme.accept(); } - QCoreApplication::sendEvent(cw, &dme); + QCoreApplication::sendEvent(currentWindow, &dme); willDrop = dme.isAccepted(); global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction; updatePixmap(); @@ -296,15 +290,13 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) #endif restoreCursor = false; } - if (object && object->target()) { + if (currentWindow) { QMouseEvent *me = (QMouseEvent *)e; - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; + QMimeData *dropData = object ? dragPrivate()->data : this->dropData; - QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); - QCoreApplication::sendEvent(object->target(), &de); + QDropEvent de(me->pos(), possible_actions, dropData, me->buttons(), me->modifiers()); + QCoreApplication::sendEvent(currentWindow, &de); if (de.isAccepted()) global_accepted_action = de.dropAction(); else @@ -314,6 +306,7 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) object->deleteLater(); drag_object = object = 0; } + currentWindow = 0; eventLoop->exit(); return true; // Eat all mouse events } @@ -321,7 +314,6 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) default: break; } -#endif return false; } @@ -337,7 +329,8 @@ Qt::DropAction QDragManager::drag(QDrag *o) } object = drag_object = o; - qt_qws_dnd_deco = new QShapedPixmapWindow(); + if (!qt_qws_dnd_deco) + qt_qws_dnd_deco = new QShapedPixmapWindow(); oldstate = Qt::NoModifier; // #### Should use state that caused the drag // drag_mode = mode; diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp index 510614e5e3..6b890fb941 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa.cpp +++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp @@ -44,6 +44,8 @@ #include "private/qwidget_p.h" #include "private/qapplication_p.h" +#include + QT_BEGIN_NAMESPACE QWidget *qt_button_down = 0; // widget got last button-down @@ -94,6 +96,12 @@ bool QWidgetWindow::event(QEvent *event) handleWheelEvent(static_cast(event)); return true; + case QEvent::DragEnter: + case QEvent::DragLeave: + case QEvent::DragMove: + case QEvent::Drop: + handleDragEvent(event); + default: break; } @@ -270,4 +278,63 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QGuiApplication::sendSpontaneousEvent(widget, &translated); } +void QWidgetWindow::handleDragEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::DragEnter: + Q_ASSERT(!m_dragTarget); + // fall through + case QEvent::DragMove: + { + QDragMoveEvent *de = static_cast(event); + QWidget *widget = m_widget->childAt(de->pos()); + if (!widget) + widget = m_widget; + + if (widget != m_dragTarget.data()) { + if (m_dragTarget.data()) { + QDragLeaveEvent le; + QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &le); + } + m_dragTarget = widget; + QPoint mapped = widget->mapFrom(m_widget, de->pos()); + QDragEnterEvent translated(mapped, de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + QGuiApplication::sendSpontaneousEvent(widget, &translated); + if (translated.isAccepted()) + event->accept(); + de->setDropAction(translated.dropAction()); + } else { + Q_ASSERT(event->type() == QEvent::DragMove); + QPoint mapped = widget->mapFrom(m_widget, de->pos()); + QDragMoveEvent translated(mapped, de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + translated.setDropAction(de->dropAction()); + QGuiApplication::sendSpontaneousEvent(widget, &translated); + if (translated.isAccepted()) + event->accept(); + de->setDropAction(translated.dropAction()); + } + break; + } + case QEvent::DragLeave: + if (m_dragTarget) + QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), event); + m_dragTarget = (QWidget *)0; + break; + case QEvent::Drop: + { + QDropEvent *de = static_cast(event); + QPoint mapped = m_dragTarget.data()->mapFrom(m_widget, de->pos()); + QDropEvent translated(mapped, de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &translated); + if (translated.isAccepted()) + event->accept(); + de->setDropAction(translated.dropAction()); + m_dragTarget = (QWidget *)0; + } + default: + break; + } +} + + QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index 9eb1e4f60e..e32a6ed001 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -70,10 +70,12 @@ protected: void handleMoveEvent(QMoveEvent *); void handleResizeEvent(QResizeEvent *); void handleWheelEvent(QWheelEvent *); + void handleDragEvent(QEvent *); private: QWidget *m_widget; QWeakPointer m_implicit_mouse_grabber; + QWeakPointer m_dragTarget; }; QT_END_NAMESPACE