Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 56497)
@@ -104,5 +104,5 @@
                                           pMimeData->formats().toVector());
     if (m_dndTarget.isOk())
-        m_enmMode = DNDMODE_HOSTTOGUEST;
+        setMode(DNDMODE_HOSTTOGUEST);
 
     /* Set the DnD action returned by the guest. */
@@ -201,5 +201,5 @@
      * mode as well here.
      */
-    m_enmMode = DNDMODE_UNKNOWN;
+    setMode(DNDMODE_UNKNOWN);
 
     return toQtDnDAction(result);
@@ -213,5 +213,5 @@
     {
         m_dndTarget.Leave(screenID);
-        m_enmMode = DNDMODE_UNKNOWN;
+        setMode(DNDMODE_UNKNOWN);
     }
 }
@@ -221,6 +221,6 @@
  */
 
-int UIDnDHandler::dragStart(const QStringList &lstFormats,
-                            Qt::DropAction defAction, Qt::DropActions actions)
+int UIDnDHandler::dragStartInternal(const QStringList &lstFormats,
+                                    Qt::DropAction defAction, Qt::DropActions actions)
 {
     int rc = VINF_SUCCESS;
@@ -228,13 +228,9 @@
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
 
-    m_lstFormats = lstFormats;
-    m_defAction  = defAction;
-    m_actions    = actions;
-
-    LogFlowFunc(("m_defAction=0x%x\n", m_defAction));
-    LogFlowFunc(("Number of formats: %d\n", m_lstFormats.size()));
+    LogFlowFunc(("defAction=0x%x\n", defAction));
+    LogFlowFunc(("Number of formats: %d\n", lstFormats.size()));
 # ifdef DEBUG
-    for (int i = 0; i < m_lstFormats.size(); i++)
-        LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toAscii().constData()));
+    for (int i = 0; i < lstFormats.size(); i++)
+        LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toAscii().constData()));
 # endif
 
@@ -244,16 +240,16 @@
     if (!pDropSource)
         return VERR_NO_MEMORY;
-    UIDnDDataObject *pDataObject = new UIDnDDataObject(this, m_lstFormats);
+    UIDnDDataObject *pDataObject = new UIDnDDataObject(this, lstFormats);
     if (!pDataObject)
         return VERR_NO_MEMORY;
 
     DWORD dwOKEffects = DROPEFFECT_NONE;
-    if (m_actions)
-    {
-        if (m_actions & Qt::CopyAction)
+    if (actions)
+    {
+        if (actions & Qt::CopyAction)
             dwOKEffects |= DROPEFFECT_COPY;
-        if (m_actions & Qt::MoveAction)
+        if (actions & Qt::MoveAction)
             dwOKEffects |= DROPEFFECT_MOVE;
-        if (m_actions & Qt::LinkAction)
+        if (actions & Qt::LinkAction)
             dwOKEffects |= DROPEFFECT_LINK;
     }
@@ -276,5 +272,5 @@
 
     /* Note: pMData is transferred to the QDrag object, so no need for deletion. */
-    m_pMIMEData = new UIDnDMIMEData(this, m_lstFormats, m_defAction, m_actions);
+    m_pMIMEData = new UIDnDMIMEData(this, lstFormats, defAction, actions);
     if (!m_pMIMEData)
     {
@@ -282,4 +278,8 @@
         return VERR_NO_MEMORY;
     }
+
+    /* Invoke this handler as data needs to be retrieved. */
+    connect(m_pMIMEData, SIGNAL(getData(QString, QVariant::Type)),
+            this, SLOT(sltGetData(QString, QVariant::Type)));
 
     /* Inform the MIME data object of any changes in the current action. */
@@ -292,5 +292,6 @@
      */
     pDrag->setMimeData(m_pMIMEData);
-    Qt::DropAction dropAction = pDrag->exec(m_actions, m_defAction);
+    LogFlowFunc(("Executing modal drag'n drop operation ...\n"));
+    Qt::DropAction dropAction = pDrag->exec(actions, defAction);
     LogRel3(("DnD: Ended with dropAction=%ld\n", UIDnDHandler::toVBoxDnDAction(dropAction)));
 
@@ -313,5 +314,5 @@
 }
 
-int UIDnDHandler::dragIsPending(ulong screenID)
+int UIDnDHandler::dragCheckPending(ulong screenID)
 {
     int rc;
@@ -331,5 +332,5 @@
     }
 
-    QMutexLocker AutoWriteLock(&m_ReadLock);
+    QMutexLocker AutoWriteLock(&m_WriteLock);
     m_fIsPending = true;
     AutoWriteLock.unlock();
@@ -348,62 +349,34 @@
     CGuest guest = m_pSession->guest();
 
-    QVector<QString> vecFmtGuest;
-    QVector<KDnDAction> vecActions;
-    KDnDAction defaultAction = m_dndSource.DragIsPending(screenID, vecFmtGuest, vecActions);
-    LogFlowFunc(("defaultAction=%d, numFormats=%d, numActions=%d\n", defaultAction,
-                 vecFmtGuest.size(), vecActions.size()));
-
-    QStringList lstFmtNative;
-    if (defaultAction != KDnDAction_Ignore)
-    {
-        LogRel3(("DnD: Number of supported guest actions: %d\n", vecActions.size()));
-        for (int i = 0; i < vecActions.size(); i++)
-            LogRel3(("\tAction %d: 0x%x\n", i, vecActions.at(i)));
-
-        /**
-         * Do guest -> host format conversion, if needed.
-         * On X11 this already maps to the Xdnd protocol.
-         ** @todo What about the MacOS Carbon Drag Manager? Needs testing.
-         *
-         * See: https://www.iana.org/assignments/media-types/media-types.xhtml
-         */
-        LogRel3(("DnD: Number of supported guest formats: %d\n", vecFmtGuest.size()));
-        for (int i = 0; i < vecFmtGuest.size(); i++)
+    /* Clear our current data set. */
+    m_dataSource.lstFormats.clear();
+    m_dataSource.vecActions.clear();
+
+    /* Ask the guest if there is a drag and drop operation pending (on the guest). */
+    QVector<QString> vecFormats;
+    m_dataSource.defaultAction = m_dndSource.DragIsPending(screenID, vecFormats, m_dataSource.vecActions);
+
+    LogRel3(("DnD: Default action is: 0x%x\n", m_dataSource.defaultAction));
+    LogRel3(("DnD: Number of supported guest actions: %d\n", m_dataSource.vecActions.size()));
+        for (int i = 0; i < m_dataSource.vecActions.size(); i++)
+            LogRel3(("\tAction %d: 0x%x\n", i, m_dataSource.vecActions.at(i)));
+
+    LogRel3(("DnD: Number of supported guest formats: %d\n", vecFormats.size()));
+        for (int i = 0; i < vecFormats.size(); i++)
         {
-            const QString &strFmtGuest = vecFmtGuest.at(i);
+            const QString &strFmtGuest = vecFormats.at(i);
             LogRel3(("\tFormat %d: %s\n", i, strFmtGuest.toAscii().constData()));
-# ifdef RT_OS_WINDOWS
-            /* CF_TEXT -> Regular text. */
-            if (   strFmtGuest.contains("text/plain", Qt::CaseInsensitive)
-                && !lstFmtNative.contains("text/plain"))
-            {
-                lstFmtNative << "text/plain";
-            }
-            /* CF_HDROP -> URI list. */
-            else if (   strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)
-                     && !lstFmtNative.contains("text/uri-list"))
-            {
-                lstFmtNative << "text/uri-list";
-            }
-# else /* RT_OS_WINDOWS */
-
-            /* On non-Windows just do a 1:1 mapping. */
-            lstFmtNative << strFmtGuest;
-#  ifdef RT_OS_MACOS
-            /** @todo Does the 1:1 format mapping apply on OS X? Needs testing! */
-#  endif
-
-# endif /* !RT_OS_WINDOWS */
         }
 
-        LogRel3(("DnD: Number of supported host formats: %d\n", lstFmtNative.size()));
-        for (int i = 0; i < lstFmtNative.size(); i++)
-            LogRel3(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
-    }
-
-    if (!lstFmtNative.isEmpty())
-    {
-        rc = dragStart(lstFmtNative,
-                       toQtDnDAction(defaultAction), toQtDnDActions(vecActions));
+    if (   m_dataSource.defaultAction != KDnDAction_Ignore
+        && vecFormats.size())
+    {
+        for (int i = 0; i < vecFormats.size(); i++)
+        {
+            const QString &strFormat = vecFormats.at(i);
+            m_dataSource.lstFormats << strFormat;
+        }
+
+        rc = VINF_SUCCESS; /* There's a valid pending drag and drop operation on the guest. */
     }
     else /* No format data from the guest arrived yet. */
@@ -426,20 +399,60 @@
 }
 
-/**
- * Called by UIDnDMIMEData (Linux, OS X, Solaris) or UIDnDDataObject (Windows)
- * to start retrieving the actual data from the guest. This function will block
- * and show a modal progress dialog until the data transfer is complete.
- *
- * @return IPRT return code.
- * @param dropAction            Drop action to perform.
- * @param strMimeType           MIME data type.
- * @param vaType                Qt's variant type of the MIME data.
- * @param vaData                The actual MIME data.
- * @param pParent               Pointer to parent widget.
- */
-int UIDnDHandler::retrieveData(      Qt::DropAction  dropAction,
-                               const QString        &strMimeType,
-                                     QVariant::Type  vaType,
-                                     QVariant       &vaData)
+int UIDnDHandler::dragStart(ulong screenID)
+{
+    int rc;
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+
+    LogFlowFuncEnter();
+
+    /* Sanity checks. */
+    if (   !m_dataSource.lstFormats.size()
+        ||  m_dataSource.defaultAction == KDnDAction_Ignore
+        || !m_dataSource.vecActions.size())
+    {
+        return VERR_INVALID_PARAMETER;
+    }
+
+    setMode(DNDMODE_GUESTTOHOST);
+
+    rc = dragStartInternal(m_dataSource.lstFormats,
+                           toQtDnDAction(m_dataSource.defaultAction), toQtDnDActions(m_dataSource.vecActions));
+
+#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
+
+    NOREF(screenID);
+
+    rc = VERR_NOT_SUPPORTED;
+
+#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int UIDnDHandler::dragStop(ulong screenID)
+{
+    int rc;
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+
+    m_fIsPending = false;
+    rc = VINF_SUCCESS;
+
+#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
+
+    NOREF(screenID);
+
+    rc = VERR_NOT_SUPPORTED;
+
+#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int UIDnDHandler::retrieveDataInternal(      Qt::DropAction  dropAction,
+                                       const QString        &strMimeType,
+                                             QVariant::Type  vaType,
+                                             QVariant       &vaData)
 {
     LogFlowFunc(("Retrieving data as type=%s (variant type=%ld)\n",
@@ -518,6 +531,33 @@
     }
 
+    setMode(DNDMODE_UNKNOWN);
+
     LogFlowFuncLeaveRC(rc);
     return rc;
+}
+
+void UIDnDHandler::setMode(DNDMODE enmMode)
+{
+    QMutexLocker AutoWriteLock(&m_WriteLock);
+    m_enmMode = enmMode;
+    LogFlowFunc(("Mode is now: %RU32\n", m_enmMode));
+}
+
+/**
+ * Called by UIDnDMIMEData (Linux, OS X, Solaris) to start retrieving the actual data
+ * from the guest. This function will block and show a modal progress dialog until
+ * the data transfer is complete.
+ *
+ * @return QVariant with data retrieved, if any.
+ * @param strMimeType           MIME data type.
+ * @param vaType                Qt's variant type of the MIME data.
+ */
+QVariant UIDnDHandler::sltGetData(const QString        &strMimeType,
+                                        QVariant::Type  vaType)
+{
+    QVariant vaData;
+    int rc = retrieveDataInternal(Qt::CopyAction, strMimeType, vaType, vaData);
+    LogFlowFuncLeaveRC(rc);
+    return vaData;
 }
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h	(revision 56497)
@@ -62,4 +62,18 @@
     } DNDMODE;
 
+    /**
+     * Drag and drop data set from the source.
+     */
+    typedef struct UIDnDDataSource
+    {
+        /** List of formats supported by the source. */
+        QStringList         lstFormats;
+        /** List of allowed drop actions from the source. */
+        QVector<KDnDAction> vecActions;
+        /** Default drop action from the source. */
+        KDnDAction          defaultAction;
+
+    } UIDnDDataSource;
+
     /* Frontend -> Target. */
     Qt::DropAction             dragEnter(ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData);
@@ -69,6 +83,7 @@
 
     /* Source -> Frontend. */
-    int                        dragIsPending(ulong screenId);
-    int                        dragStart(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
+    int                        dragCheckPending(ulong screenId);
+    int                        dragStart(ulong screenId);
+    int                        dragStop(ulong screenID);
     int                        retrieveData(Qt::DropAction  dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData);
 
@@ -79,4 +94,14 @@
     static Qt::DropAction      toQtDnDAction(KDnDAction action);
     static Qt::DropActions     toQtDnDActions(const QVector<KDnDAction> &vecActions);
+
+public slots:
+
+    QVariant                   sltGetData(const QString &strMimeType, QVariant::Type vaType);
+
+protected:
+
+    int                        dragStartInternal(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
+    int                        retrieveDataInternal(Qt::DropAction dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData);
+    void                       setMode(DNDMODE enmMode);
 
 protected:
@@ -93,15 +118,11 @@
     /** Current transfer direction. */
     DNDMODE           m_enmMode;
+    /** Current data from the source (if any).
+     *  At the momenet we only support one source at a time. */
+    UIDnDDataSource   m_dataSource;
     /** Flag indicating if a drag operation is pending currently. */
     bool              m_fIsPending;
     QMutex            m_ReadLock;
     QMutex            m_WriteLock;
-
-    /** List of formats supported by the source. */
-    QStringList       m_lstFormats;
-    /** Default drop action from the source. */
-    Qt::DropAction    m_defAction;
-    /** List of allowed drop actions from the source. */
-    Qt::DropActions   m_actions;
 
 #ifndef RT_OS_WINDOWS
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp	(revision 56497)
@@ -45,4 +45,5 @@
     , m_lstFormats(lstFormats)
     , m_defAction(defAction)
+    , m_curAction(Qt::DropAction::IgnoreAction)
     , m_actions(actions)
     , m_enmState(Dragging)
@@ -56,34 +57,4 @@
         LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toAscii().constData()));
 #endif
-
-     /**
-     * This is unbelievable hacky, but I didn't find another way. Stupid
-     * Qt QDrag interface is so less verbose, that we in principle know
-     * nothing about what happens when the user drag something around. It
-     * is possible that the target on the host requests data
-     * (@sa retrieveData) while the mouse button still is pressed. This
-     * isn't something we should support, because it would mean transferring
-     * the data from the guest while the mouse is still moving (think of
-     * transferring a 2GB file from the guest to the host ...). So the idea is
-     * to detect the mouse release event and only after this happened, allow
-     * data to be retrieved. Unfortunately the QDrag object eats all events
-     * while a drag is going on (see QDragManager in the Qt src's).
-     *
-     * So what we now are going to do is installing an event filter after the
-     * QDrag::exec is called, so that this event filter then would be
-     * the last in the event filter queue and therefore called before the
-     * one installed by the QDrag object (which then in turn would
-     * munch all events).
-     *
-     ** @todo Test this on all supported platforms (X11 works).
-     *
-     * Note: On Windows the above hack is not needed because as soon as Qt calls
-     *       OLE's DoDragDrop routine internally (via QtDrag::exec), no mouse
-     *       events will come through anymore. At this point DoDragDrop is modal
-     *       and will take care of all the input handling. */
-#ifndef RT_OS_WINDOWS
-    /* Install the event filter in a deferred way. */
-    QTimer::singleShot(0, this, SLOT(sltInstallEventFilter()));
-#endif
 }
 
@@ -95,7 +66,7 @@
 bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const
 {
-    bool fRc = m_lstFormats.contains(strMIMEType);
-    LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool)\n",
-                 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType)));
+    bool fRc = (m_curAction != Qt::DropAction::IgnoreAction);
+    LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool, curAction=0x%x)\n",
+                 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType), m_curAction));
     return fRc;
 }
@@ -112,6 +83,6 @@
 QVariant UIDnDMIMEData::retrieveData(const QString &strMIMEType, QVariant::Type vaType) const
 {
-    LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState, strMIMEType.toStdString().c_str(),
-                 vaType, QVariant::typeToName(vaType)));
+    LogFlowFunc(("state=%RU32, curAction=0x%x, defAction=0x%x, mimeType=%s, type=%d (%s)\n",
+                 m_enmState, m_curAction, m_defAction, strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
 
     bool fCanDrop = true;
@@ -126,47 +97,46 @@
      * (see UIDnDMimeData::eventFilter). This filter will update the current
      * operation state for us (based on the mouse buttons). */
-    if (m_enmState != Dropped)
-    {
-        LogFlowFunc(("Not yet in 'dropped' state, so can't drop yet\n"));
+    if (m_curAction == Qt::DropAction::IgnoreAction)
+    {
+        LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction));
         fCanDrop = false;
     }
 #endif
 
-    /* Do we support the requested MIME type? */
-    if (   fCanDrop
-        && !m_lstFormats.contains(strMIMEType))
-    {
-        LogRel3(("DnD: Unsupported MIME type=%s\n", strMIMEType.toStdString().c_str()));
-        fCanDrop = false;
-    }
-
-    /* Supported types. See below in the switch statement. */
-    if (   fCanDrop
-        && !(
-             /* Plain text. */
-                vaType == QVariant::String
-             /* Binary data. */
-             || vaType == QVariant::ByteArray
-             /* URI list. */
-             || vaType == QVariant::List))
-    {
-        LogRel3(("DnD: Unsupported data type=%d (%s)\n", vaType, QVariant::typeToName(vaType)));
-        fCanDrop = false;
-    }
-
-    LogRel3(("DnD: State=%ld, fCanDrop=%RTbool\n", m_enmState, fCanDrop));
+    if (fCanDrop)
+    {
+        /* Do we support the requested MIME type? */
+        if (!m_lstFormats.contains(strMIMEType))
+        {
+            LogRel(("DnD: Unsupported MIME type '%s'\n", strMIMEType.toStdString().c_str()));
+            fCanDrop = false;
+        }
+
+        /* Supported types. See below in the switch statement. */
+        if (!(
+              /* Plain text. */
+                 vaType == QVariant::String
+              /* Binary data. */
+              || vaType == QVariant::ByteArray
+                 /* URI list. */
+              || vaType == QVariant::List))
+        {
+            LogRel(("DnD: Unsupported data type '%s'\n", QVariant::typeToName(vaType)));
+            fCanDrop = false;
+        }
+    }
+
+    LogRel3(("DnD: State=%ld, Action=0x%x, fCanDrop=%RTbool\n", m_enmState, m_curAction, fCanDrop));
 
     if (!fCanDrop)
     {
         LogFlowFunc(("Skipping request, state=%RU32 ...\n", m_enmState));
-        return QMimeData::retrieveData(strMIMEType, vaType);
-    }
-
-    /* Note: The const_cast is used because this function needs to be const (otherwise
-     *       Qt won't call it), but we need the stuff in an unconst'ed way. */
-    int rc = const_cast<UIDnDMIMEData *>(this)->retrieveDataInternal(strMIMEType, vaType);
-
-    LogFlowFunc(("Returning rc=%Rrc, state=%RU32\n", rc, m_enmState));
-    return m_vaData;
+        return QVariant(QVariant::Invalid); /* Return a NULL variant. */
+    }
+
+    QVariant vaData = emit getData(strMIMEType, vaType);
+
+    LogRel3(("DnD: Returning data of type '%s'\n", vaData.typeName()));
+    return vaData;
 }
 
@@ -180,13 +150,4 @@
         switch (pEvent->type())
         {
-            case QEvent::MouseMove:
-            {
-                QMouseEvent *pMouseEvent = (QMouseEvent*)(pEvent);
-                AssertPtr(pMouseEvent);
-                LogFlowFunc(("MouseMove: x=%d, y=%d\n", pMouseEvent->globalX(), pMouseEvent->globalY()));
-
-                break;
-            }
-
             case QEvent::MouseButtonRelease:
             {
@@ -223,9 +184,10 @@
     }
 
-    /* Do normal processing by Qt. */
-    return QObject::eventFilter(pObject, pEvent);
+    /* Propagate further. */
+    return false;
 }
 #endif /* !RT_OS_WINDOWS */
 
+#if 0
 int UIDnDMIMEData::setData(const QString &mimeType)
 {
@@ -278,24 +240,5 @@
     return rc;
 }
-
-int UIDnDMIMEData::retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType)
-{
-    LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState,
-                  strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
-
-    AssertPtr(m_pDnDHandler);
-    int rc = m_pDnDHandler->retrieveData(m_defAction, strMIMEType, vaType, m_vaData);
-    if (RT_SUCCESS(rc))
-    {
-        /* Nothing to do here yet. */
-    }
-    else if (rc == VERR_CANCELLED)
-        m_enmState = Canceled;
-    else
-        m_enmState = Error;
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
+#endif
 
 /**
@@ -307,17 +250,5 @@
 {
     LogFlowFunc(("dropAction=0x%x\n", dropAction));
-    m_defAction = dropAction;
-}
-
-#ifndef RT_OS_WINDOWS
-/**
- * Issued by ourselves to install the event filter.
- */
-void UIDnDMIMEData::sltInstallEventFilter(void)
-{
-    LogFlowFunc(("Installing event filter ...\n"));
-    AssertPtr(qApp);
-    qApp->installEventFilter(this);
-}
-#endif
-
+    m_curAction = dropAction;
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h	(revision 56497)
@@ -63,7 +63,7 @@
     UIDnDMIMEData(UIDnDHandler *pDnDHandler, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions);
 
-public:
+signals:
 
-    int setData(const QString &mimeType);
+     int getData(const QString &strMIMEType, QVariant::Type vaType) const;
 
 public slots:
@@ -78,5 +78,5 @@
     virtual bool hasFormat(const QString &mimeType) const;
 
-    virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+    virtual QVariant retrieveData(const QString &strMIMEType, QVariant::Type vaType) const;
 
 #ifndef RT_OS_WINDOWS
@@ -85,12 +85,4 @@
     /** @}  */
 
-    int retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType);
-
-protected slots:
-
-#ifndef RT_OS_WINDOWS
-    void sltInstallEventFilter(void);
-#endif
-
 protected:
 
@@ -98,5 +90,8 @@
 
     QStringList       m_lstFormats;
+    /** Default action on successful drop operation. */
     Qt::DropAction    m_defAction;
+    /** Current action, based on QDrag's status. */
+    Qt::DropAction    m_curAction;
     Qt::DropActions   m_actions;
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 56497)
@@ -545,4 +545,7 @@
     , m_fAccelerate2DVideo(bAccelerate2DVideo)
 #endif /* VBOX_WITH_VIDEOHWACCEL */
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+    , m_fIsDraggingFromGuest(false)
+#endif
 {
     /* Load machine view settings: */
@@ -1420,4 +1423,15 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP
+bool UIMachineView::dragAndDropCanAccept(void) const
+{
+    bool fAccept =  m_pDnDHandler
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+                 && !m_fIsDraggingFromGuest
+#endif
+                 && machine().GetDnDMode() != KDnDMode_Disabled;
+    LogRelFunc(("fAccept=%RTbool\n", fAccept));
+    return fAccept;
+}
+
 bool UIMachineView::dragAndDropIsActive(void) const
 {
@@ -1430,5 +1444,5 @@
     AssertPtrReturnVoid(pEvent);
 
-    if (!dragAndDropIsActive())
+    if (!dragAndDropCanAccept())
         return;
 
@@ -1453,5 +1467,5 @@
     AssertPtrReturnVoid(pEvent);
 
-    if (!dragAndDropIsActive())
+    if (!dragAndDropCanAccept())
         return;
 
@@ -1476,20 +1490,67 @@
     AssertPtrReturnVoid(pEvent);
 
+    if (!dragAndDropCanAccept())
+        return;
+
+    m_pDnDHandler->dragLeave(screenId());
+
+    pEvent->accept();
+}
+
+int UIMachineView::dragCheckPending(void)
+{
+    int rc;
+
     if (!dragAndDropIsActive())
-        return;
-
-    m_pDnDHandler->dragLeave(screenId());
-
-    pEvent->accept();
-}
-
-void UIMachineView::dragIsPending(void)
-{
+        rc = VERR_ACCESS_DENIED;
+    else if (!m_fIsDraggingFromGuest)
+    {
+        /** @todo Add guest->guest DnD functionality here by getting
+         *        the source of guest B (when copying from B to A). */
+        rc = m_pDnDHandler->dragCheckPending(screenId());
+        if (RT_SUCCESS(rc))
+            m_fIsDraggingFromGuest = true;
+    }
+    else /* Already dragging, so report success. */
+        rc = VINF_SUCCESS;
+
+    LogRel3(("DnD: dragCheckPending ended with rc=%Rrc\n", rc));
+    return rc;
+}
+
+int UIMachineView::dragStart(void)
+{
+    int rc;
+
     if (!dragAndDropIsActive())
-        return;
-
-    /** @todo Add guest->guest DnD functionality here by getting
-     *        the source of guest B (when copying from B to A). */
-    m_pDnDHandler->dragIsPending(screenId());
+        rc = VERR_ACCESS_DENIED;
+    else if (!m_fIsDraggingFromGuest)
+        rc = VERR_WRONG_ORDER;
+    else
+    {
+        /** @todo Add guest->guest DnD functionality here by getting
+         *        the source of guest B (when copying from B to A). */
+        rc = m_pDnDHandler->dragStart(screenId());
+
+        m_fIsDraggingFromGuest = false;
+    }
+
+    LogRel3(("DnD: dragStart ended with rc=%Rrc\n", rc));
+    return rc;
+}
+
+int UIMachineView::dragStop(void)
+{
+    int rc;
+
+    if (!dragAndDropIsActive())
+        rc = VERR_ACCESS_DENIED;
+    else if (!m_fIsDraggingFromGuest)
+        rc = VERR_WRONG_ORDER;
+    else
+        rc = m_pDnDHandler->dragStop(screenId());
+
+    LogRel3(("DnD: dragStop ended with rc=%Rrc\n", rc));
+    return rc;
 }
 
@@ -1498,5 +1559,5 @@
     AssertPtrReturnVoid(pEvent);
 
-    if (!dragAndDropIsActive())
+    if (!dragAndDropCanAccept())
         return;
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 56497)
@@ -263,4 +263,10 @@
 #ifdef VBOX_WITH_DRAG_AND_DROP
     /**
+     * Returns @true if the VM window can accept (start is, start) a drag and drop
+     * operation, @false if not.
+     */
+    bool dragAndDropCanAccept(void) const;
+
+    /**
      * Returns @true if drag and drop for this machine is active
      * (that is, host->guest, guest->host or bidirectional), @false if not.
@@ -298,5 +304,18 @@
      *                and (optionally) starts a drag and drop operation on the host.
      */
-    void dragIsPending(void);
+    int dragCheckPending(void);
+
+    /**
+     * Guest -> Host: Starts a drag and drop operation from guest to the host. This
+     *                internally either uses Qt's abstract QDrag methods or some other
+     *                OS-dependent implementation.
+     */
+    int dragStart(void);
+
+    /**
+     * Guest -> Host: Aborts (and resets) the current (pending) guest to host
+     *                drag and drop operation.
+     */
+    int dragStop(void);
 
     /**
@@ -358,4 +377,9 @@
     /** Pointer to drag and drop handler instance. */
     UIDnDHandler *m_pDnDHandler;
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+    /** Flag indicating whether a guest->host drag currently is in
+     *  progress or not. */
+    bool m_fIsDraggingFromGuest;
+# endif
 #endif
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 56496)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 56497)
@@ -957,4 +957,8 @@
 #ifdef VBOX_WITH_DRAG_AND_DROP
 # ifdef VBOX_WITH_DRAG_AND_DROP_GH
+            QPointer<UIMachineView> pView = m_views[uScreenId];
+            bool fHandleDnDPending = RT_BOOL(mouseButtons.testFlag(Qt::LeftButton));
+
+            /* Mouse pointer outside VM window? */
             if (   cpnt.x() < 0
                 || cpnt.x() > iCw - 1
@@ -962,11 +966,20 @@
                 || cpnt.y() > iCh - 1)
             {
-                bool fHandleDnDPending
-                    = RT_BOOL(mouseButtons.testFlag(Qt::LeftButton));
                 if (fHandleDnDPending)
                 {
-                    m_views[uScreenId]->dragIsPending();
-                    return true;
-                }
+                    LogRel2(("DnD: Drag and drop operation from guest to host started\n"));
+
+                    int rc = pView->dragCheckPending();
+                    if (RT_SUCCESS(rc))
+                    {
+                        pView->dragStart();
+                        return true; /* Bail out -- we're done here. */
+                    }
+                }
+            }
+            else /* Inside VM window? */
+            {
+                if (fHandleDnDPending)
+                    pView->dragStop();
             }
 # endif
