diff options
Diffstat (limited to 'src/gui/kernel')
-rw-r--r-- | src/gui/kernel/kernel.pri | 1 | ||||
-rw-r--r-- | src/gui/kernel/qdnd.cpp | 402 | ||||
-rw-r--r-- | src/gui/kernel/qdnd_p.h | 87 | ||||
-rw-r--r-- | src/gui/kernel/qdrag.cpp | 89 | ||||
-rw-r--r-- | src/gui/kernel/qdrag.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 5 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 57 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qplatformdrag_qpa.cpp | 187 | ||||
-rw-r--r-- | src/gui/kernel/qplatformdrag_qpa.h | 49 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_qpa.cpp | 9 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_qpa.h | 6 |
12 files changed, 399 insertions, 504 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 9c5f3b10da..2656d8ffdb 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -66,6 +66,7 @@ SOURCES += \ kernel/qwindowsysteminterface_qpa.cpp \ kernel/qplatforminputcontext_qpa.cpp \ kernel/qplatformintegration_qpa.cpp \ + kernel/qplatformdrag_qpa.cpp \ kernel/qplatformscreen_qpa.cpp \ kernel/qplatformintegrationfactory_qpa.cpp \ kernel/qplatformintegrationplugin_qpa.cpp \ diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 2fb250cf18..1ed4a96192 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -125,417 +125,79 @@ QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies) #endif // the universe's only drag manager -QDragManager *QDragManager::instance = 0; +QDragManager *QDragManager::m_instance = 0; QDragManager::QDragManager() - : QObject(qApp) + : QObject(qApp), m_platformDropData(0), m_currentDropTarget(0), + m_platformDrag(QGuiApplicationPrivate::platformIntegration()->drag()), + m_object(0) { - Q_ASSERT(!instance); + Q_ASSERT(!m_instance); - object = 0; - beingCancelled = false; - restoreCursor = false; - willDrop = false; - eventLoop = 0; - currentDropTarget = 0; - shapedPixmapWindow = 0; - - possible_actions = Qt::IgnoreAction; - - QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); - platformDrag = pi->drag(); - - platformDropData = 0; - if (platformDrag) - platformDropData = platformDrag->platformDropData(); + if (m_platformDrag) + m_platformDropData = m_platformDrag->platformDropData(); } QDragManager::~QDragManager() { -#ifndef QT_NO_CURSOR - if (restoreCursor) - QGuiApplication::restoreOverrideCursor(); -#endif - instance = 0; + m_instance = 0; } QDragManager *QDragManager::self() { - if (!instance && !QGuiApplication::closingDown()) - instance = new QDragManager; - return instance; + if (!m_instance && !QGuiApplication::closingDown()) + m_instance = new QDragManager; + return m_instance; } -QPixmap QDragManager::dragCursor(Qt::DropAction action) const +QObject *QDragManager::source() const { - typedef QMap<Qt::DropAction, QPixmap>::const_iterator Iterator; - - if (const QDragPrivate *d = dragPrivate()) { - const Iterator it = d->customCursors.constFind(action); - if (it != d->customCursors.constEnd()) - return it.value(); - } - - Qt::CursorShape shape = Qt::ForbiddenCursor; - switch (action) { - case Qt::MoveAction: - shape = Qt::DragMoveCursor; - break; - case Qt::CopyAction: - shape = Qt::DragCopyCursor; - break; - case Qt::LinkAction: - shape = Qt::DragLinkCursor; - break; - default: - shape = Qt::ForbiddenCursor; - } - return QGuiApplicationPrivate::instance()->getPixmapCursor(shape); -} - -Qt::DropAction QDragManager::defaultAction(Qt::DropActions possibleActions, - Qt::KeyboardModifiers modifiers) const -{ -#ifdef QDND_DEBUG - qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)"); - qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1()); -#endif - - QDragPrivate *d = dragPrivate(); - Qt::DropAction defaultAction = d ? d->defaultDropAction : Qt::IgnoreAction; - - if (defaultAction == Qt::IgnoreAction) { - //This means that the drag was initiated by QDrag::start and we need to - //preserve the old behavior - defaultAction = Qt::CopyAction; - } - - if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) - defaultAction = Qt::LinkAction; - else if (modifiers & Qt::ControlModifier) - defaultAction = Qt::CopyAction; - else if (modifiers & Qt::ShiftModifier) - defaultAction = Qt::MoveAction; - else if (modifiers & Qt::AltModifier) - defaultAction = Qt::LinkAction; - -#ifdef QDND_DEBUG - qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1()); -#endif - - // Check if the action determined is allowed - if (!(possibleActions & defaultAction)) { - if (possibleActions & Qt::CopyAction) - defaultAction = Qt::CopyAction; - else if (possibleActions & Qt::MoveAction) - defaultAction = Qt::MoveAction; - else if (possibleActions & Qt::LinkAction) - defaultAction = Qt::LinkAction; - else - defaultAction = Qt::IgnoreAction; - } - -#ifdef QDND_DEBUG - qDebug("default action : %s", dragActionsToString(defaultAction).latin1()); -#endif - - return defaultAction; + if (m_object) + return m_object->source(); + return 0; } void QDragManager::setCurrentTarget(QObject *target, bool dropped) { - if (currentDropTarget == target) + if (m_currentDropTarget == target) return; - currentDropTarget = target; - if (!dropped && object) { - object->d_func()->target = target; - emit object->targetChanged(target); + m_currentDropTarget = target; + if (!dropped && m_object) { + m_object->d_func()->target = target; + emit m_object->targetChanged(target); } - } -QObject *QDragManager::currentTarget() +QObject *QDragManager::currentTarget() const { - return currentDropTarget; -} - - -static const int default_pm_hotx = -2; -static const int default_pm_hoty = -16; -static const char *const default_pm[] = { -"13 9 3 1", -". c None", -" c #000000", -"X c #FFFFFF", -"X X X X X X X", -" X X X X X X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X X X X X X ", -"X X X X X X X", -}; - - -QShapedPixmapWindow::QShapedPixmapWindow() - : QWindow() -{ - setSurfaceType(RasterSurface); - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | - Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput); - create(); - backingStore = new QBackingStore(this); -} - -void QShapedPixmapWindow::render() -{ - QRect rect(QPoint(), geometry().size()); - backingStore->resize(rect.size()); - - backingStore->beginPaint(rect); - - QPaintDevice *device = backingStore->paintDevice(); - - { - QPainter p(device); - p.drawPixmap(0, 0, pixmap); - } - - backingStore->endPaint(); - backingStore->flush(rect); -} - - - - -static Qt::KeyboardModifiers oldstate; - -void QDragManager::updatePixmap() -{ - if (shapedPixmapWindow) { - shapedPixmapWindow->pixmap = QPixmap(); - shapedPixmapWindow->hotSpot = QPoint(default_pm_hotx,default_pm_hoty); - if (object) { - shapedPixmapWindow->pixmap = object->pixmap(); - if (!shapedPixmapWindow->pixmap.isNull()) - shapedPixmapWindow->hotSpot = object->hotSpot(); - } - if (shapedPixmapWindow->pixmap.isNull()) - shapedPixmapWindow->pixmap = QPixmap(default_pm); - shapedPixmapWindow->setGeometry(QRect(QCursor::pos() - shapedPixmapWindow->hotSpot, shapedPixmapWindow->pixmap.size())); - shapedPixmapWindow->show(); - shapedPixmapWindow->render(); - } -} - -void QDragManager::updateCursor() -{ - if (shapedPixmapWindow) { - shapedPixmapWindow->render(); // ### Hack - shapedPixmapWindow->move(QCursor::pos() - shapedPixmapWindow->hotSpot); - } - - Qt::CursorShape cursorShape = Qt::ForbiddenCursor; - if (willDrop) { - if (global_accepted_action == Qt::CopyAction) { - cursorShape = Qt::DragCopyCursor; - } else if (global_accepted_action == Qt::LinkAction) { - cursorShape = Qt::DragLinkCursor; - } else { - cursorShape = Qt::DragMoveCursor; - } - } - QCursor *cursor = qApp->overrideCursor(); - if (cursor && cursorShape != cursor->shape()) - qApp->changeOverrideCursor(QCursor(cursorShape)); -} - - -bool QDragManager::eventFilter(QObject *o, QEvent *e) -{ - if (beingCancelled) { - if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) { - qApp->removeEventFilter(this); - Q_ASSERT(object == 0); - beingCancelled = false; - eventLoop->exit(); - return true; // block the key release - } - return false; - } - - Q_ASSERT(object != 0); - - if (!qobject_cast<QWindow *>(o)) - return false; - - switch(e->type()) { - case QEvent::ShortcutOverride: - // prevent accelerators from firing while dragging - e->accept(); - return true; - - case QEvent::KeyPress: - case QEvent::KeyRelease: - { - QKeyEvent *ke = static_cast<QKeyEvent *>(e); - if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - eventLoop->exit(); - } else { - // ### x11 forces move! - updateCursor(); - } - return true; // Eat all key events - } - - case QEvent::MouseMove: - move(static_cast<QMouseEvent *>(e)); - return true; // Eat all mouse events - - case QEvent::MouseButtonRelease: - qApp->removeEventFilter(this); - if (willDrop) - drop(static_cast<QMouseEvent *>(e)); - else - cancel(); - beingCancelled = false; - eventLoop->exit(); - return true; // Eat all mouse events - - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - case QEvent::Wheel: - return true; - default: - break; - } - return false; + return m_currentDropTarget; } Qt::DropAction QDragManager::drag(QDrag *o) { - if (!o || object == o) + if (!o || m_object == o) return Qt::IgnoreAction; - if (!platformDrag || !o->source()) { + if (!m_platformDrag || !o->source()) { o->deleteLater(); return Qt::IgnoreAction; } - if (object) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - } - - object = o; - if (!shapedPixmapWindow) - shapedPixmapWindow = new QShapedPixmapWindow(); - oldstate = Qt::NoModifier; // #### Should use state that caused the drag -// drag_mode = mode; - - possible_actions = dragPrivate()->possible_actions; - - willDrop = false; - object->d_func()->target = 0; - qApp->installEventFilter(this); - - global_accepted_action = Qt::CopyAction; -#ifndef QT_NO_CURSOR - qApp->setOverrideCursor(Qt::DragCopyCursor); - restoreCursor = true; - updateCursor(); -#endif - updatePixmap(); - - platformDrag->startDrag(); - - eventLoop = new QEventLoop; - (void) eventLoop->exec(); - delete eventLoop; - eventLoop = 0; - - delete shapedPixmapWindow; - shapedPixmapWindow = 0; - - return global_accepted_action; -} - -void QDragManager::move(const QMouseEvent *me) -{ - if (!platformDrag) - return; - - platformDrag->move(me); -} - -void QDragManager::drop(const QMouseEvent *me) -{ - if (!platformDrag) - return; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QGuiApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif - willDrop = false; - - platformDrag->drop(me); - - if (object) - object->deleteLater(); - object = 0; -} - -void QDragManager::cancel(bool deleteSource) -{ - if (!platformDrag) - return; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QGuiApplication::restoreOverrideCursor(); - restoreCursor = false; + if (m_object) { + qWarning("QDragManager::drag in possibly invalid state"); + return Qt::IgnoreAction; } -#endif - - beingCancelled = true; - platformDrag->cancel(); + m_object = o; - if (object && deleteSource) - object->deleteLater(); - object = 0; + m_object->d_func()->target = 0; - global_accepted_action = Qt::IgnoreAction; -} - -/*! - Called from startDrag() in QPlatformDrag implementations that do not need - the desktop-oriented stuff provided by the event filter (e.g. because their - drag is not based on mouse events). Instead, they will manage everything on - their own, will not rely on move/drop/cancel, and will call stopDrag() to stop - the event loop when the drag is over. - */ -void QDragManager::unmanageEvents() -{ - qApp->removeEventFilter(this); -} - -void QDragManager::stopDrag() -{ - if (eventLoop) - eventLoop->exit(); + const Qt::DropAction result = m_platformDrag->drag(m_object); + m_object = 0; + return result; } #endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 857be34d10..764b73c06f 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -98,100 +98,45 @@ protected: class QDragPrivate : public QObjectPrivate { public: + QDragPrivate() + : source(0) + , target(0) + , data(0) + { } QObject *source; QObject *target; QMimeData *data; QPixmap pixmap; QPoint hotspot; - Qt::DropActions possible_actions; Qt::DropAction executed_action; + Qt::DropActions supported_actions; + Qt::DropAction default_action; QMap<Qt::DropAction, QPixmap> customCursors; - Qt::DropAction defaultDropAction; }; -class QShapedPixmapWindow : public QWindow -{ -public: - QShapedPixmapWindow(); - - void exposeEvent(QExposeEvent *) - { - render(); - } - - void render(); - - QBackingStore *backingStore; - QPixmap pixmap; - QPoint hotSpot; -}; - - class Q_GUI_EXPORT QDragManager : public QObject { Q_OBJECT - // only friend classes can use QDragManager. - friend class QDrag; - friend class QDragMoveEvent; - friend class QDropEvent; - friend class QApplication; - - bool eventFilter(QObject *, QEvent *); - public: QDragManager(); ~QDragManager(); static QDragManager *self(); - virtual Qt::DropAction drag(QDrag *); - - virtual void cancel(bool deleteSource = true); - virtual void move(const QMouseEvent *me); - virtual void drop(const QMouseEvent *me); - - void updatePixmap(); - void updateCursor(); - - Qt::DropAction defaultAction(Qt::DropActions possibleActions, - Qt::KeyboardModifiers modifiers) const; - - QPixmap dragCursor(Qt::DropAction action) const; - - QDragPrivate *dragPrivate() const { return object ? object->d_func() : 0; } - - inline QMimeData *dropData() - { return object ? dragPrivate()->data : platformDropData; } - - void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); } + Qt::DropAction drag(QDrag *); void setCurrentTarget(QObject *target, bool dropped = false); - QObject *currentTarget(); + QObject *currentTarget() const; - QDrag *object; - - bool beingCancelled; - bool restoreCursor; - bool willDrop; - QEventLoop *eventLoop; - - Qt::DropActions possible_actions; - // Shift/Ctrl handling, and final drop status - Qt::DropAction global_accepted_action; - - QShapedPixmapWindow *shapedPixmapWindow; - - void unmanageEvents(); - void stopDrag(); + QDrag *object() const { return m_object; } + QObject *source() const; private: - QMimeData *platformDropData; - - Qt::DropAction currentActionForOverrideCursor; - QObject *currentDropTarget; - - QPlatformDrag *platformDrag; + QMimeData *m_platformDropData; + QObject *m_currentDropTarget; + QPlatformDrag *m_platformDrag; + QDrag *m_object; - static QDragManager *instance; + static QDragManager *m_instance; Q_DISABLE_COPY(QDragManager) }; diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp index 694b12a180..ead0805bd1 100644 --- a/src/gui/kernel/qdrag.cpp +++ b/src/gui/kernel/qdrag.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <qdrag.h> +#include "private/qguiapplication_p.h" #include <qpixmap.h> #include <qpoint.h> #include "qdnd_p.h" @@ -114,9 +115,9 @@ QDrag::QDrag(QObject *dragSource) d->target = 0; d->data = 0; d->hotspot = QPoint(-10, -10); - d->possible_actions = Qt::CopyAction; d->executed_action = Qt::IgnoreAction; - d->defaultDropAction = Qt::IgnoreAction; + d->supported_actions = Qt::IgnoreAction; + d->default_action = Qt::IgnoreAction; } /*! @@ -126,9 +127,6 @@ QDrag::~QDrag() { Q_D(QDrag); delete d->data; - QDragManager *manager = QDragManager::self(); - if (manager && manager->object == this) - manager->cancel(false); } /*! @@ -264,24 +262,22 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defa qWarning("QDrag: No mimedata set before starting the drag"); return d->executed_action; } - QDragManager *manager = QDragManager::self(); - d->defaultDropAction = Qt::IgnoreAction; - d->possible_actions = supportedActions; - - if (manager) { - if (defaultDropAction == Qt::IgnoreAction) { - if (supportedActions & Qt::MoveAction) { - d->defaultDropAction = Qt::MoveAction; - } else if (supportedActions & Qt::CopyAction) { - d->defaultDropAction = Qt::CopyAction; - } else if (supportedActions & Qt::LinkAction) { - d->defaultDropAction = Qt::LinkAction; - } - } else { - d->defaultDropAction = defaultDropAction; + Qt::DropAction transformedDefaultDropAction = Qt::IgnoreAction; + + if (defaultDropAction == Qt::IgnoreAction) { + if (supportedActions & Qt::MoveAction) { + transformedDefaultDropAction = Qt::MoveAction; + } else if (supportedActions & Qt::CopyAction) { + transformedDefaultDropAction = Qt::CopyAction; + } else if (supportedActions & Qt::LinkAction) { + transformedDefaultDropAction = Qt::LinkAction; } - d->executed_action = manager->drag(this); + } else { + transformedDefaultDropAction = defaultDropAction; } + d->supported_actions = supportedActions; + d->default_action = transformedDefaultDropAction; + d->executed_action = QDragManager::self()->drag(this); return d->executed_action; } @@ -308,11 +304,9 @@ Qt::DropAction QDrag::start(Qt::DropActions request) qWarning("QDrag: No mimedata set before starting the drag"); return d->executed_action; } - QDragManager *manager = QDragManager::self(); - d->defaultDropAction = Qt::IgnoreAction; - d->possible_actions = request | Qt::CopyAction; - if (manager) - d->executed_action = manager->drag(this); + d->supported_actions = request | Qt::CopyAction; + d->default_action = Qt::IgnoreAction; + d->executed_action = QDragManager::self()->drag(this); return d->executed_action; } @@ -336,6 +330,49 @@ void QDrag::setDragCursor(const QPixmap &cursor, Qt::DropAction action) } /*! + Returns the drag cursor for the \a action. + + \since 5.0 +*/ + +QPixmap QDrag::dragCursor(Qt::DropAction action) const +{ + typedef QMap<Qt::DropAction, QPixmap>::const_iterator Iterator; + + Q_D(const QDrag); + const Iterator it = d->customCursors.constFind(action); + if (it != d->customCursors.constEnd()) + return it.value(); + + Qt::CursorShape shape = Qt::ForbiddenCursor; + switch (action) { + case Qt::MoveAction: + shape = Qt::DragMoveCursor; + break; + case Qt::CopyAction: + shape = Qt::DragCopyCursor; + break; + case Qt::LinkAction: + shape = Qt::DragLinkCursor; + break; + default: + shape = Qt::ForbiddenCursor; + } + return QGuiApplicationPrivate::instance()->getPixmapCursor(shape); +} + +Qt::DropActions QDrag::supportedActions() const +{ + Q_D(const QDrag); + return d->supported_actions; +} + +Qt::DropAction QDrag::defaultAction() const +{ + Q_D(const QDrag); + return d->default_action; +} +/*! \fn void QDrag::actionChanged(Qt::DropAction action) This signal is emitted when the \a action associated with the diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h index 0a1ddff2d9..de84b6588b 100644 --- a/src/gui/kernel/qdrag.h +++ b/src/gui/kernel/qdrag.h @@ -56,6 +56,7 @@ class QPixmap; class QPoint; class QDragManager; + class Q_GUI_EXPORT QDrag : public QObject { Q_OBJECT @@ -81,6 +82,10 @@ public: Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction); void setDragCursor(const QPixmap &cursor, Qt::DropAction action); + QPixmap dragCursor(Qt::DropAction action) const; + + Qt::DropActions supportedActions() const; + Qt::DropAction defaultAction() const; Q_SIGNALS: void actionChanged(Qt::DropAction action); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 281d4f61bc..ee121f2071 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2295,8 +2295,9 @@ QDropEvent::~QDropEvent() */ QObject* QDropEvent::source() const { - QDragManager *manager = QDragManager::self(); - return (manager && manager->object) ? manager->object->source() : 0; + if (const QDragManager *manager = QDragManager::self()) + return manager->source(); + return 0; } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 1cd448a6bb..09d4e98c3c 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -73,8 +73,11 @@ #include "private/qwindowsysteminterface_qpa_p.h" #include "private/qwindow_p.h" #include "private/qcursor_p.h" + #include "private/qdnd_p.h" #include <private/qplatformthemefactory_qpa_p.h> +#include "qplatformdrag_qpa.h" + #ifndef QT_NO_CURSOR #include "qplatformcursor_qpa.h" #endif @@ -326,8 +329,7 @@ QGuiApplication::QGuiApplication(int &argc, char **argv, int flags) QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p) : QCoreApplication(p) { - d_func()->init(); -} + d_func()->init(); } /*! Destructs the application. @@ -1547,49 +1549,62 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E QCoreApplication::sendSpontaneousEvent(window, &exposeEvent); } -Qt::DropAction QGuiApplicationPrivate::processDrag(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { static QPointer<QWindow> currentDragWindow; - QDragManager *manager = QDragManager::self(); + static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; + QPlatformDrag *platformDrag = platformIntegration()->drag(); + if (!platformDrag) { + lastAcceptedDropAction = Qt::IgnoreAction; + return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); + } + if (!dropData) { if (currentDragWindow.data() == w) currentDragWindow = 0; QDragLeaveEvent e; QGuiApplication::sendEvent(w, &e); - manager->global_accepted_action = Qt::IgnoreAction; - return Qt::IgnoreAction; + lastAcceptedDropAction = Qt::IgnoreAction; + return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } - QDragMoveEvent me(p, manager->possible_actions, dropData, + QDragMoveEvent me(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + if (w != currentDragWindow) { + lastAcceptedDropAction = Qt::IgnoreAction; if (currentDragWindow) { QDragLeaveEvent e; QGuiApplication::sendEvent(currentDragWindow, &e); - manager->global_accepted_action = Qt::IgnoreAction; } currentDragWindow = w; - QDragEnterEvent e(p, manager->possible_actions, dropData, + QDragEnterEvent e(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); QGuiApplication::sendEvent(w, &e); - manager->global_accepted_action = e.isAccepted() ? e.dropAction() : Qt::IgnoreAction; - if (manager->global_accepted_action != Qt::IgnoreAction) { - me.setDropAction(manager->global_accepted_action); - me.accept(); - } + if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction) + lastAcceptedDropAction = e.dropAction(); + } + + // Handling 'DragEnter' should suffice for the application. + if (lastAcceptedDropAction != Qt::IgnoreAction + && (supportedActions & lastAcceptedDropAction)) { + me.setDropAction(lastAcceptedDropAction); + me.accept(); } QGuiApplication::sendEvent(w, &me); - manager->global_accepted_action = me.isAccepted() ? me.dropAction() : Qt::IgnoreAction; - return manager->global_accepted_action; + lastAcceptedDropAction = me.isAccepted() ? + me.dropAction() : Qt::IgnoreAction; + return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect()); } -Qt::DropAction QGuiApplicationPrivate::processDrop(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - QDragManager *manager = QDragManager::self(); - QDropEvent de(p, manager->possible_actions, dropData, + QDropEvent de(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); QGuiApplication::sendEvent(w, &de); - manager->global_accepted_action = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; - return manager->global_accepted_action; + + Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; + QPlatformDropQtResponse response(de.isAccepted(),acceptedAction); + return response; } #ifndef QT_NO_CLIPBOARD diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 68546ce0cf..d9477a3e9e 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -53,6 +53,8 @@ #include "private/qwindowsysteminterface_qpa_p.h" #include "private/qshortcutmap_p.h" +#include "qplatformdrag_qpa.h" + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -121,8 +123,8 @@ public: static void processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e); - static Qt::DropAction processDrag(QWindow *w, QMimeData *dropData, const QPoint &p); - static Qt::DropAction processDrop(QWindow *w, QMimeData *dropData, const QPoint &p); + static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); + static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); diff --git a/src/gui/kernel/qplatformdrag_qpa.cpp b/src/gui/kernel/qplatformdrag_qpa.cpp new file mode 100644 index 0000000000..832b91db7e --- /dev/null +++ b/src/gui/kernel/qplatformdrag_qpa.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdrag_qpa.h" + +#include <QtGui/private/qdnd_p.h> +#include <QtGui/QKeyEvent> +#include <QtGui/QGuiApplication> +#include <QtCore/QEventLoop> + +QT_BEGIN_NAMESPACE + +QPlatformDropQtResponse::QPlatformDropQtResponse(bool accepted, Qt::DropAction acceptedAction) + : m_accepted(accepted) + , m_accepted_action(acceptedAction) +{ +} + +bool QPlatformDropQtResponse::isAccepted() const +{ + return m_accepted; +} + +Qt::DropAction QPlatformDropQtResponse::acceptedAction() const +{ + return m_accepted_action; +} + +QPlatformDragQtResponse::QPlatformDragQtResponse(bool accepted, Qt::DropAction acceptedAction, QRect answerRect) + : QPlatformDropQtResponse(accepted,acceptedAction) + , m_answer_rect(answerRect) +{ +} + +QRect QPlatformDragQtResponse::answerRect() const +{ + return m_answer_rect; +} + +class QPlatformDragPrivate { +public: + QPlatformDragPrivate() : cursor_drop_action(Qt::IgnoreAction) {} + + Qt::DropAction cursor_drop_action; +}; + +QPlatformDrag::QPlatformDrag() : d_ptr(new QPlatformDragPrivate) +{ +} + +QPlatformDrag::~QPlatformDrag() +{ +} + +QDrag *QPlatformDrag::currentDrag() const +{ + return QDragManager::self()->object(); +} + +Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, + Qt::KeyboardModifiers modifiers) const +{ +#ifdef QDND_DEBUG + qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)"); + qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1()); +#endif + + Qt::DropAction default_action = Qt::IgnoreAction; + + if (currentDrag()) { + default_action = currentDrag()->defaultAction(); + } + + + if (default_action == Qt::IgnoreAction) { + //This means that the drag was initiated by QDrag::start and we need to + //preserve the old behavior + default_action = Qt::CopyAction; + } + + if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) + default_action = Qt::LinkAction; + else if (modifiers & Qt::ControlModifier) + default_action = Qt::CopyAction; + else if (modifiers & Qt::ShiftModifier) + default_action = Qt::MoveAction; + else if (modifiers & Qt::AltModifier) + default_action = Qt::LinkAction; + +#ifdef QDND_DEBUG + qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1()); +#endif + + // Check if the action determined is allowed + if (!(possibleActions & default_action)) { + if (possibleActions & Qt::CopyAction) + default_action = Qt::CopyAction; + else if (possibleActions & Qt::MoveAction) + default_action = Qt::MoveAction; + else if (possibleActions & Qt::LinkAction) + default_action = Qt::LinkAction; + else + default_action = Qt::IgnoreAction; + } + +#ifdef QDND_DEBUG + qDebug("default action : %s", dragActionsToString(defaultAction).latin1()); +#endif + + return default_action; +} + +/*! + \brief Called to notify QDrag about changes of the current action. + */ + +void QPlatformDrag::updateAction(Qt::DropAction action) +{ + Q_D(QPlatformDrag); + if (d->cursor_drop_action != action) { + d->cursor_drop_action = action; + emit currentDrag()->actionChanged(action); + } +} + +static const char *const default_pm[] = { +"13 9 3 1", +". c None", +" c #000000", +"X c #FFFFFF", +"X X X X X X X", +" X X X X X X ", +"X ......... X", +" X.........X ", +"X ......... X", +" X.........X ", +"X ......... X", +" X X X X X X ", +"X X X X X X X", +}; + +Q_GLOBAL_STATIC_WITH_ARGS(QPixmap,qt_drag_default_pixmap,(default_pm)) + +QPixmap QPlatformDrag::defaultPixmap() +{ + return *qt_drag_default_pixmap(); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformdrag_qpa.h b/src/gui/kernel/qplatformdrag_qpa.h index 0c215071d3..7d22c69947 100644 --- a/src/gui/kernel/qplatformdrag_qpa.h +++ b/src/gui/kernel/qplatformdrag_qpa.h @@ -43,6 +43,7 @@ #define QPLATFORMDRAG_H #include <QtCore/qglobal.h> +#include <QtGui/QPixmap> QT_BEGIN_HEADER @@ -51,18 +52,54 @@ QT_BEGIN_NAMESPACE class QMimeData; class QMouseEvent; +class QDrag; +class QObject; +class QEvent; +class QPlatformDragPrivate; -class QPlatformDrag +class Q_GUI_EXPORT QPlatformDropQtResponse { public: - virtual ~QPlatformDrag() {} + QPlatformDropQtResponse(bool accepted, Qt::DropAction acceptedAction); + bool isAccepted() const; + Qt::DropAction acceptedAction() const; +private: + bool m_accepted; + Qt::DropAction m_accepted_action; + +}; + +class Q_GUI_EXPORT QPlatformDragQtResponse : public QPlatformDropQtResponse +{ +public: + QPlatformDragQtResponse(bool accepted, Qt::DropAction acceptedAction, QRect answerRect); + + QRect answerRect() const; + +private: + QRect m_answer_rect; +}; + +class Q_GUI_EXPORT QPlatformDrag +{ + Q_DECLARE_PRIVATE(QPlatformDrag) +public: + QPlatformDrag(); + virtual ~QPlatformDrag(); + + QDrag *currentDrag() const; virtual QMimeData *platformDropData() = 0; - virtual void startDrag() {} - virtual void move(const QMouseEvent *me) = 0; - virtual void drop(const QMouseEvent *me) = 0; - virtual void cancel() = 0; + virtual Qt::DropAction drag(QDrag *m_drag) = 0; + void updateAction(Qt::DropAction action); + + Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const; + + static QPixmap defaultPixmap(); + +private: + QPlatformDragPrivate *d_ptr; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 40a4ec07a6..5b77d97950 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -43,6 +43,7 @@ #include "private/qguiapplication_p.h" #include "private/qtouchdevice_p.h" #include <QAbstractEventDispatcher> +#include <QPlatformDrag> #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -447,14 +448,14 @@ int QWindowSystemInterface::windowSystemEventsQueued() return QWindowSystemInterfacePrivate::windowSystemEventsQueued(); } -Qt::DropAction QWindowSystemInterface::handleDrag(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - return QGuiApplicationPrivate::processDrag(w, dropData, p); + return QGuiApplicationPrivate::processDrag(w, dropData, p,supportedActions); } -Qt::DropAction QWindowSystemInterface::handleDrop(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - return QGuiApplicationPrivate::processDrop(w, dropData, p); + return QGuiApplicationPrivate::processDrop(w, dropData, p,supportedActions); } /*! diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h index 836fb40bd7..6dae11ea81 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE class QMimeData; class QTouchDevice; +class QPlatformDragQtResponse; +class QPlatformDropQtResponse; class Q_GUI_EXPORT QWindowSystemInterface @@ -122,8 +124,8 @@ public: static void handleSynchronousExposeEvent(QWindow *tlw, const QRegion ®ion); // Drag and drop. These events are sent immediately. - static Qt::DropAction handleDrag(QWindow *w, QMimeData *dropData, const QPoint &p); - static Qt::DropAction handleDrop(QWindow *w, QMimeData *dropData, const QPoint &p); + static QPlatformDragQtResponse handleDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); + static QPlatformDropQtResponse handleDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); |