VirtualBox

Ignore:
Timestamp:
May 12, 2015 11:43:14 AM (10 years ago)
Author:
vboxsync
Message:

DnD: FE/Qt: Overhaul of the frontend-specific code, removed unnecessary UIDnDDrag class.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
2 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r55477 r55821  
    55
    66#
    7 # Copyright (C) 2006-2014 Oracle Corporation
     7# Copyright (C) 2006-2015 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    474474 ifdef VBOX_WITH_DRAG_AND_DROP_GH
    475475  VirtualBox_QT_MOCHDRS += \
    476         src/runtime/UIDnDMIMEData.h \
    477         src/runtime/UIDnDDrag.h
     476        src/runtime/UIDnDMIMEData.h
    478477 endif
    479478endif
     
    800799 ifdef VBOX_WITH_DRAG_AND_DROP_GH
    801800  VirtualBox_SOURCES += \
    802         src/runtime/UIDnDMIMEData.cpp \
    803         src/runtime/UIDnDDrag.cpp
     801        src/runtime/UIDnDMIMEData.cpp
    804802  VirtualBox_SOURCES.win += \
    805803        src/runtime/UIDnDDropSource_win.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp

    r52730 r55821  
    3535#include <QStringList>
    3636
     37#include "UIDnDHandler.h"
    3738#include "UIDnDDataObject_win.h"
    3839#include "UIDnDEnumFormat_win.h"
    3940
    4041
    41 UIDnDDataObject::UIDnDDataObject(CSession &session,
    42                                  CDnDSource &dndSource,
    43                                  const QStringList &lstFormats,
    44                                  QWidget *pParent)
    45     : mSession(session),
    46       mDnDSource(dndSource),
    47       mpParent(pParent),
    48       mStatus(Uninitialized),
    49       mRefCount(1),
    50       mcFormats(0),
    51       mpFormatEtc(NULL),
    52       mpStgMedium(NULL),
    53       mpvData(NULL),
    54       mcbData(0)
     42UIDnDDataObject::UIDnDDataObject(UIDnDHandler *pDnDHandler, const QStringList &lstFormats)
     43    : m_pDnDHandler(pDnDHandler)
     44    , mStatus(Uninitialized)
     45    , mRefCount(1)
     46    , mcFormats(0)
     47    , mpFormatEtc(NULL)
     48    , mpStgMedium(NULL)
     49    , mpvData(NULL)
     50    , mcbData(0)
    5551{
    5652    HRESULT hr;
     
    9894        }
    9995
    100         LogFlowFunc(("Total registered native formats: %RU32 (for %d formats from guest)\n",
    101                      cRegisteredFormats, lstFormats.size()));
     96        LogRel3(("DnD: Total registered native formats: %RU32 (for %d formats from guest)\n",
     97                 cRegisteredFormats, lstFormats.size()));
    10298        hr = S_OK;
    10399    }
     
    208204    AssertPtrReturn(pMedium, DV_E_FORMATETC);
    209205
    210 #ifdef VBOX_DND_DEBUG_FORMATS
    211206    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));
    212 #endif
    213207
    214208    ULONG lIndex;
     
    229223    if (mStatus == Dropping)
    230224    {
     225        LogRel3(("DnD: Dropping\n"));
    231226        LogFlowFunc(("Waiting for event ...\n"));
    232227        int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT);
     
    236231    if (mStatus == Dropped)
    237232    {
    238         LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
    239                      pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    240                      pThisFormat->tymed, pThisFormat->dwAspect));
    241         LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n",
    242                      mstrFormat.toAscii().constData(), mpvData, mcbData));
     233        LogRel3(("DnD: Dropped\n"));
     234        LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
     235                 pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
     236                 pThisFormat->tymed, pThisFormat->dwAspect));
     237        LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
     238                 mstrFormat.toAscii().constData(), mpvData, mcbData));
    243239
    244240        QVariant::Type vaType;
     
    286282        }
    287283#endif
    288         LogFlowFunc(("strMIMEType=%s, vaType=%ld\n",
    289                      strMIMEType.toAscii().constData(), vaType));
     284        LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toAscii().constData(), vaType));
    290285
    291286        int rc;
    292287        if (!mVaData.isValid())
    293288        {
    294             rc = UIDnDDrag::RetrieveData(mSession,
    295                                          mDnDSource,
    296                                          /** @todo Support other actions. */
    297                                          Qt::CopyAction,
    298                                          strMIMEType, vaType, mVaData,
    299                                          mpParent);
     289            /* Note:  We're usig Qt::MoveAction because this speed up the whole operation
     290             *        significantly: Instead of copying the data from the temporary location to
     291             *        the final destination we just move it.
     292             *
     293             * Note2: The Qt::MoveAction *only* affects the behavior on the host! The desired
     294             *        action for the guest (e.g. moving a file from guest to host) is not affected
     295             *        by this setting. */
     296            rc = m_pDnDHandler->retrieveData(Qt::MoveAction,
     297                                             strMIMEType, vaType, mVaData);
    300298        }
    301299        else
     
    652650            && pFormatEtc->dwAspect == mpFormatEtc[i].dwAspect)
    653651        {
    654 #ifdef VBOX_DND_DEBUG_FORMATS
    655             LogFlowFunc(("Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
    656                          pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(mpFormatEtc[i].cfFormat),
    657                          pFormatEtc->dwAspect, i));
    658 #endif
     652            LogRel3(("DnD: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n",
     653                     pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(mpFormatEtc[i].cfFormat),
     654                     pFormatEtc->dwAspect, i));
     655
    659656            if (puIndex)
    660657                *puIndex = i;
     
    663660    }
    664661
    665 #ifdef VBOX_DND_DEBUG_FORMATS
    666     LogFlowFunc(("Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
    667                  pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    668                  pFormatEtc->dwAspect));
    669 #endif
     662    LogRel3(("DnD: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
     663             pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
     664             pFormatEtc->dwAspect));
     665
    670666    return false;
    671667}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h

    r52727 r55821  
    3131
    3232/* Forward declarations: */
    33 class UIDnDDrag;
     33class UIDnDHandler;
    3434
    3535class UIDnDDataObject : public IDataObject
     
    4848public:
    4949
    50     UIDnDDataObject(CSession &session, CDnDSource &dndSource, const QStringList &lstFormats, QWidget *pParent);
     50    UIDnDDataObject(UIDnDHandler *pDnDHandler, const QStringList &lstFormats);
    5151    virtual ~UIDnDDataObject(void);
    5252
     
    8484                        LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
    8585
    86     QWidget    *mpParent;
    87     CSession    mSession;
    88     CDnDSource  mDnDSource;
    89     Status      mStatus;
    90     LONG        mRefCount;
    91     /** Number of native formats registered. This
    92      *  can be a different number than supplied with
    93      *  mlstFormats. */
    94     ULONG       mcFormats;
    95     FORMATETC  *mpFormatEtc;
    96     STGMEDIUM  *mpStgMedium;
    97     RTSEMEVENT  mSemEvent;
    98     QStringList mlstFormats;
    99     QString     mstrFormat;
    100     /** The retrieved data as a QVariant. Needed
    101      *  for buffering in case a second format needs
    102      *  the same data, e.g. CF_TEXT and CF_UNICODETEXT. */
    103     QVariant    mVaData;
     86    UIDnDHandler   *m_pDnDHandler;
     87
     88    Status          mStatus;
     89    LONG            mRefCount;
     90    /** Number of native formats registered. This can be a different number than supplied with mlstFormats. */
     91    ULONG           mcFormats;
     92    FORMATETC      *mpFormatEtc;
     93    STGMEDIUM      *mpStgMedium;
     94    RTSEMEVENT      mSemEvent;
     95    QStringList     mlstFormats;
     96    QString         mstrFormat;
     97    /** The retrieved data as a QVariant. Needed for buffering in case a second format needs the same data,
     98     *  e.g. CF_TEXT and CF_UNICODETEXT. */
     99    QVariant        mVaData;
    104100    /** The retrieved data as a raw buffer. */
    105     void       *mpvData;
     101    void           *mpvData;
    106102    /** Raw buffer size (in bytes). */
    107     uint32_t    mcbData;
     103    uint32_t        mcbData;
    108104};
    109105
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDropSource_win.h

    r52727 r55821  
    55
    66/*
    7  * Copyright (C) 2014 Oracle Corporation
     7 * Copyright (C) 2014-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4646protected:
    4747
    48     LONG mRefCount;
    49     QWidget *mpParent;
    50     DWORD mdwCurEffect;
    51     Qt::DropActions muCurAction;
     48    LONG             mRefCount;
     49    QWidget         *mpParent;
     50    DWORD            mdwCurEffect;
     51    Qt::DropActions  muCurAction;
    5252};
    5353
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp

    r55546 r55821  
    2121
    2222/* Qt includes: */
    23 # include <QApplication>
    24 # include <QKeyEvent>
    25 # include <QStringList>
    26 # include <QTimer>
    27 # include <QUrl>
     23#include <QApplication>
     24#include <QKeyEvent>
     25#include <QStringList>
     26#include <QTimer>
     27#include <QUrl>
     28
     29/* VirtualBox interface declarations: */
     30#ifndef VBOX_WITH_XPCOM
     31# include "VirtualBox.h"
     32#else /* !VBOX_WITH_XPCOM */
     33# include "VirtualBox_XPCOM.h"
     34#endif /* VBOX_WITH_XPCOM */
    2835
    2936/* GUI includes: */
     
    3138#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    3239# include "CDnDSource.h"
    33 # include "UIDnDDrag.h"
    34 #endif
    35 # include "UIMessageCenter.h"
     40# ifdef RT_OS_WINDOWS
     41#  include "UIDnDDataObject_win.h"
     42#  include "UIDnDDropSource_win.h"
     43# endif
     44# include "UIDnDMIMEData.h"
     45#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     46#include "UIMessageCenter.h"
     47#include "UISession.h"
    3648
    3749/* COM includes: */
    3850# include "CConsole.h"
    39 # include "CDnDTarget.h"
    4051# include "CGuest.h"
     52# include "CGuestDnDSource.h"
     53# include "CGuestDnDTarget.h"
    4154# include "CSession.h"
    4255
     
    5063
    5164
    52 UIDnDHandler *UIDnDHandler::m_pInstance = NULL;
    53 
    54 UIDnDHandler::UIDnDHandler(void)
     65UIDnDHandler::UIDnDHandler(UISession *pSession, QWidget *pParent)
     66    : m_pSession(pSession)
     67    , m_pParent(pParent)
     68    , m_enmMode(DNDMODE_UNKNOWN)
     69    , m_fIsPending(false)
     70#ifndef RT_OS_WINDOWS
     71    , m_pMIMEData(NULL)
     72#endif
     73{
     74    AssertPtr(pSession);
     75    m_dndSource = static_cast<CDnDSource>(pSession->guest().GetDnDSource());
     76    m_dndTarget = static_cast<CDnDTarget>(pSession->guest().GetDnDTarget());
     77}
     78
     79UIDnDHandler::~UIDnDHandler(void)
    5580{
    5681}
     
    6085 */
    6186
    62 Qt::DropAction UIDnDHandler::dragEnter(CDnDTarget &dndTarget, ulong screenId, int x, int y,
     87Qt::DropAction UIDnDHandler::dragEnter(ulong screenID, int x, int y,
    6388                                       Qt::DropAction proposedAction, Qt::DropActions possibleActions,
    64                                        const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
    65 {
    66     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
    67                  screenId, x, y, toVBoxDnDAction(proposedAction)));
     89                                       const QMimeData *pMimeData)
     90{
     91    LogFlowFunc(("enmMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
     92                 m_enmMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
     93
     94    if (m_enmMode != DNDMODE_UNKNOWN)
     95        return Qt::IgnoreAction;
    6896
    6997    /* Ask the guest for starting a DnD event. */
    70     KDnDAction result = dndTarget.Enter(screenId,
    71                                         x,
    72                                         y,
    73                                         toVBoxDnDAction(proposedAction),
    74                                         toVBoxDnDActions(possibleActions),
    75                                         pMimeData->formats().toVector());
     98    KDnDAction result = m_dndTarget.Enter(screenID,
     99                                          x,
     100                                          y,
     101                                          toVBoxDnDAction(proposedAction),
     102                                          toVBoxDnDActions(possibleActions),
     103                                          pMimeData->formats().toVector());
     104    if (result != KDnDAction_Ignore)
     105        m_enmMode = DNDMODE_HOSTTOGUEST;
    76106
    77107    /* Set the DnD action returned by the guest. */
     
    79109}
    80110
    81 Qt::DropAction UIDnDHandler::dragMove(CDnDTarget &dndTarget, ulong screenId, int x, int y,
     111Qt::DropAction UIDnDHandler::dragMove(ulong screenID, int x, int y,
    82112                                      Qt::DropAction proposedAction, Qt::DropActions possibleActions,
    83                                       const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
    84 {
    85 #ifdef DEBUG_andy
    86     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
    87                  screenId, x, y, toVBoxDnDAction(proposedAction)));
    88 #endif
     113                                      const QMimeData *pMimeData)
     114{
     115    LogFlowFunc(("enmMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
     116                 m_enmMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
     117
     118    if (m_enmMode != DNDMODE_HOSTTOGUEST)
     119        return Qt::IgnoreAction;
    89120
    90121    /* Notify the guest that the mouse has been moved while doing
    91122     * a drag'n drop operation. */
    92     KDnDAction result = dndTarget.Move(screenId,
    93                                        x,
    94                                        y,
    95                                        toVBoxDnDAction(proposedAction),
    96                                        toVBoxDnDActions(possibleActions),
    97                                        pMimeData->formats().toVector());
     123    KDnDAction result = m_dndTarget.Move(screenID,
     124                                         x,
     125                                         y,
     126                                         toVBoxDnDAction(proposedAction),
     127                                         toVBoxDnDActions(possibleActions),
     128                                         pMimeData->formats().toVector());
    98129    /* Set the DnD action returned by the guest. */
    99130    return toQtDnDAction(result);
    100131}
    101132
    102 Qt::DropAction UIDnDHandler::dragDrop(CSession &session, CDnDTarget &dndTarget,
    103                                       ulong screenId, int x, int y,
     133Qt::DropAction UIDnDHandler::dragDrop(ulong screenID, int x, int y,
    104134                                      Qt::DropAction proposedAction, Qt::DropActions possibleActions,
    105                                       const QMimeData *pMimeData, QWidget *pParent /* = NULL */)
    106 {
    107     CGuest guest = session.GetConsole().GetGuest();
    108 
    109     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
    110                  screenId, x, y, toVBoxDnDAction(proposedAction)));
     135                                      const QMimeData *pMimeData)
     136{
     137    LogFlowFunc(("enmMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
     138                 m_enmMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
     139
     140    if (m_enmMode != DNDMODE_HOSTTOGUEST)
     141        return Qt::IgnoreAction;
    111142
    112143    /* The format the guest requests. */
    113144    QString format;
    114145    /* Ask the guest for dropping data. */
    115     KDnDAction result = dndTarget.Drop(screenId,
    116                                        x,
    117                                        y,
    118                                        toVBoxDnDAction(proposedAction),
    119                                        toVBoxDnDActions(possibleActions),
    120                                        pMimeData->formats().toVector(), format);
     146    KDnDAction result = m_dndTarget.Drop(screenID,
     147                                         x,
     148                                         y,
     149                                         toVBoxDnDAction(proposedAction),
     150                                         toVBoxDnDActions(possibleActions),
     151                                         pMimeData->formats().toVector(), format);
    121152    /* Has the guest accepted the drop event? */
    122153    if (result != KDnDAction_Ignore)
     
    132163            memcpy(dv.data(), d.constData(), d.size());
    133164
    134             CProgress progress = dndTarget.SendData(screenId, format, dv);
    135 
    136             if (dndTarget.isOk())
     165            CProgress progress = m_dndTarget.SendData(screenID, format, dv);
     166
     167            if (m_dndTarget.isOk())
    137168            {
    138169                LogFlowFunc(("Transferring data to guest ...\n"));
     
    140171                msgCenter().showModalProgressDialog(progress,
    141172                                                    tr("Dropping data ..."), ":/progress_dnd_hg_90px.png",
    142                                                     pParent);
     173                                                    m_pParent);
    143174
    144175                LogFlowFunc(("Transfer fCompleted=%RTbool, fCanceled=%RTbool, hr=%Rhrc\n",
     
    150181                        ||  progress.GetResultCode() != 0))
    151182                {
    152                     msgCenter().cannotDropDataToGuest(progress, pParent);
     183                    msgCenter().cannotDropDataToGuest(progress, m_pParent);
    153184                    result = KDnDAction_Ignore;
    154185                }
     
    156187            else
    157188            {
    158                 msgCenter().cannotDropDataToGuest(dndTarget, pParent);
     189                msgCenter().cannotDropDataToGuest(m_dndTarget, m_pParent);
    159190                result = KDnDAction_Ignore;
    160191            }
     
    165196}
    166197
    167 void UIDnDHandler::dragLeave(CDnDTarget &dndTarget,
    168                              ulong screenId, QWidget * /* pParent = NULL */)
    169 {
    170     LogFlowFunc(("screenId=%RU32\n", screenId));
    171     dndTarget.Leave(screenId);
     198void UIDnDHandler::dragLeave(ulong screenID)
     199{
     200    LogFlowFunc(("enmMode=%RU32, screenID=%RU32\n", m_enmMode, screenID));
     201    m_dndTarget.Leave(screenID);
     202
     203    if (m_enmMode == DNDMODE_HOSTTOGUEST)
     204        m_enmMode = DNDMODE_UNKNOWN;
    172205}
    173206
     
    176209 */
    177210
    178 int UIDnDHandler::dragIsPending(CSession &session, CDnDSource &dndSource,
    179                                 ulong screenId, QWidget *pParent /* = NULL */)
     211int UIDnDHandler::dragStart(const QStringList &lstFormats,
     212                            Qt::DropAction defAction, Qt::DropActions actions)
     213{
     214    m_lstFormats = lstFormats;
     215    m_defAction  = defAction;
     216    m_actions    = actions;
     217
     218    LogFlowFunc(("m_defAction=0x%x\n", m_defAction));
     219    LogFlowFunc(("Number of formats: %d\n", m_lstFormats.size()));
     220#ifdef DEBUG
     221    for (int i = 0; i < m_lstFormats.size(); i++)
     222        LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toAscii().constData()));
     223#endif
     224
     225    int rc = VINF_SUCCESS;
     226
     227#ifdef RT_OS_WINDOWS
     228
     229    UIDnDDropSource *pDropSource = new UIDnDDropSource(m_pParent);
     230    if (!pDropSource)
     231        return VERR_NO_MEMORY;
     232    UIDnDDataObject *pDataObject = new UIDnDDataObject(this, m_lstFormats);
     233    if (!pDataObject)
     234        return VERR_NO_MEMORY;
     235
     236    DWORD dwOKEffects = DROPEFFECT_NONE;
     237    if (m_actions)
     238    {
     239        if (m_actions & Qt::CopyAction)
     240            dwOKEffects |= DROPEFFECT_COPY;
     241        if (m_actions & Qt::MoveAction)
     242            dwOKEffects |= DROPEFFECT_MOVE;
     243        if (m_actions & Qt::LinkAction)
     244            dwOKEffects |= DROPEFFECT_LINK;
     245    }
     246
     247    DWORD dwEffect;
     248    LogRel3(("DnD: dwOKEffects=0x%x\n", dwOKEffects));
     249    HRESULT hr = ::DoDragDrop(pDataObject, pDropSource, dwOKEffects, &dwEffect);
     250    LogRel3(("DnD: DoDragDrop ended with hr=%Rhrc, dwEffect=%RI32\n", hr, dwEffect));
     251
     252    if (pDropSource)
     253        pDropSource->Release();
     254    if (pDataObject)
     255        pDataObject->Release();
     256
     257#else /* !RT_OS_WINDOWS */
     258
     259    QDrag *pDrag = new QDrag(m_pParent);
     260    if (!pDrag)
     261        return VERR_NO_MEMORY;
     262
     263    /* Note: pMData is transferred to the QDrag object, so no need for deletion. */
     264    m_pMIMEData = new UIDnDMIMEData(this, m_lstFormats, m_defAction, m_actions);
     265    if (!m_pMIMEData)
     266    {
     267        delete pDrag;
     268        return VERR_NO_MEMORY;
     269    }
     270
     271    /* Inform the MIME data object of any changes in the current action. */
     272    connect(pDrag, SIGNAL(actionChanged(Qt::DropAction)),
     273            m_pMIMEData, SLOT(sltDropActionChanged(Qt::DropAction)));
     274
     275    /*
     276     * Set MIME data object and start the (modal) drag'n drop operation on the host.
     277     * This does not block Qt's event loop, however (on Windows it would).
     278     */
     279    pDrag->setMimeData(m_pMIMEData);
     280    Qt::DropAction dropAction = pDrag->exec(m_actions, m_defAction);
     281    LogRel3(("DnD: Ended with dropAction=%ld\n", UIDnDHandler::toVBoxDnDAction(dropAction)));
     282
     283    /* Note: The UIDnDMimeData object will not be not accessible here anymore,
     284     *       since QDrag had its ownership and deleted it after the (blocking)
     285     *       QDrag::exec() call. */
     286
     287    /* pDrag will be cleaned up by Qt automatically. */
     288
     289#endif /* !RT_OS_WINDOWS */
     290
     291    LogFlowFuncLeaveRC(rc);
     292    return rc;
     293}
     294
     295int UIDnDHandler::dragIsPending(ulong screenID)
    180296{
    181297    int rc;
    182298#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    183     /*
     299 
     300    LogFlowFunc(("enmMode=%RU32, m_fIsPending=%RTbool, screenID=%RU32\n", m_enmMode, m_fIsPending, screenID));
     301
     302    {
     303        QMutexLocker AutoReadLock(&m_ReadLock);
     304
     305        if (m_enmMode != DNDMODE_UNKNOWN) /* Wrong mode set? */
     306            return VINF_SUCCESS;
     307
     308        if (m_fIsPending) /* Pendig operation is in progress. */
     309            return VINF_SUCCESS;
     310    }
     311
     312    QMutexLocker AutoWriteLock(&m_ReadLock);
     313    m_fIsPending = true;
     314    AutoWriteLock.unlock();
     315
     316    /**
    184317     * How this works: Source is asking the target if there is any DnD
    185318     * operation pending, when the mouse leaves the guest window. On
     
    187320     * (or defaultAction is KDnDAction_Ignore if not). With
    188321     * this information we create a Qt QDrag object with our own QMimeType
    189      * implementation and call exec. Please note, this *blocks* until the DnD
    190      * operation has finished.
     322     * implementation and call exec.
     323     *
     324     * Note: This function *blocks* until the actual drag'n drop operation
     325     *       has been finished (successfully or not)!
    191326     */
    192     CGuest guest = session.GetConsole().GetGuest();
     327    CGuest guest = m_pSession->guest();
     328
    193329    QVector<QString> vecFmtGuest;
    194330    QVector<KDnDAction> vecActions;
    195     KDnDAction defaultAction = dndSource.DragIsPending(screenId, vecFmtGuest, vecActions);
     331    KDnDAction defaultAction = m_dndSource.DragIsPending(screenID, vecFmtGuest, vecActions);
    196332    LogFlowFunc(("defaultAction=%d, numFormats=%d\n", defaultAction, vecFmtGuest.size()));
    197333
     
    199335    if (defaultAction != KDnDAction_Ignore)
    200336    {
    201         /*
     337        /**
    202338         * Do guest -> host format conversion, if needed.
    203339         * On X11 this already maps to the Xdnd protocol.
     
    206342         * See: https://www.iana.org/assignments/media-types/media-types.xhtml
    207343         */
    208         LogFlowFunc(("Number of guest formats: %d\n", vecFmtGuest.size()));
     344        LogRel3(("DnD: Number of guest formats: %d\n", vecFmtGuest.size()));
    209345        for (int i = 0; i < vecFmtGuest.size(); i++)
    210346        {
    211347            const QString &strFmtGuest = vecFmtGuest.at(i);
    212             LogFlowFunc(("\tFormat %d: %s\n", i,
    213                          strFmtGuest.toAscii().constData()));
     348            LogRel3(("\tFormat %d: %s\n", i, strFmtGuest.toAscii().constData()));
    214349# ifdef RT_OS_WINDOWS
    215             /* CF_TEXT */
     350            /* CF_TEXT -> Regular text. */
    216351            if (   strFmtGuest.contains("text/plain", Qt::CaseInsensitive)
    217352                && !lstFmtNative.contains("text/plain"))
     
    219354                lstFmtNative << "text/plain";
    220355            }
    221             /* CF_HDROP */
     356            /* CF_HDROP -> URI list. */
    222357            else if (   strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)
    223358                     && !lstFmtNative.contains("text/uri-list"))
     
    225360                lstFmtNative << "text/uri-list";
    226361            }
    227 # else
     362# else /* RT_OS_WINDOWS */
     363
    228364            /* On non-Windows just do a 1:1 mapping. */
    229365            lstFmtNative << strFmtGuest;
    230366#  ifdef RT_OS_MACOS
    231             /** @todo Does the mapping apply here? Don't think so ... */
     367            /** @todo Does the 1:1 format mapping apply on OS X? Needs testing! */
    232368#  endif
     369
    233370# endif /* !RT_OS_WINDOWS */
    234371        }
    235372
    236         LogFlowFunc(("Number of native formats: %d\n", lstFmtNative.size()));
    237 # ifdef DEBUG
     373        LogRel3(("DnD: Number of native formats: %d\n", lstFmtNative.size()));
    238374        for (int i = 0; i < lstFmtNative.size(); i++)
    239             LogFlowFunc(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
    240 # endif
     375            LogRel3(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
    241376    }
    242377
    243378    if (!lstFmtNative.isEmpty())
    244379    {
    245         UIDnDDrag *pDrag = new UIDnDDrag(session, dndSource, lstFmtNative,
    246                                          toQtDnDAction(defaultAction),
    247                                          toQtDnDActions(vecActions), pParent);
    248         if (pDrag)
    249         {
    250             rc = pDrag->DoDragDrop();
    251             delete pDrag;
    252         }
    253         else
    254             rc = VERR_NO_MEMORY;
     380        rc = dragStart(lstFmtNative,
     381                       toQtDnDAction(defaultAction), toQtDnDActions(vecActions));         
    255382    }
    256383    else /* No format data from the guest arrived yet. */
    257384        rc = VERR_NO_DATA;
     385
     386    AutoWriteLock.relock();
     387    m_fIsPending = false;
     388    AutoWriteLock.unlock();
     389
    258390#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
    259     NOREF(dndSource);
    260     NOREF(session);
    261     NOREF(screenId);
    262     NOREF(pParent);
     391
     392    NOREF(screenID);
    263393
    264394    rc = VERR_NOT_SUPPORTED;
     395
    265396#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     397
     398    LogFlowFuncLeaveRC(rc);
     399    return rc;
     400}
     401
     402/**
     403 * Called by UIDnDMIMEData (Linux, OS X, Solaris) or UIDnDDataObject (Windows)
     404 * to start retrieving the actual data from the guest. This function will block
     405 * and show a modal progress dialog until the data transfer is complete.
     406 *
     407 * @return IPRT return code.
     408 * @param dropAction            Drop action to perform.
     409 * @param strMimeType           MIME data type.
     410 * @param vaType                Qt's variant type of the MIME data.
     411 * @param vaData                The actual MIME data.
     412 * @param pParent               Pointer to parent widget.
     413 */
     414int UIDnDHandler::retrieveData(      Qt::DropAction  dropAction,
     415                               const QString        &strMimeType,
     416                                     QVariant::Type  vaType,
     417                                     QVariant       &vaData)
     418{
     419    LogFlowFunc(("Retrieving data as type=%s (variant type=%ld)\n",
     420                 strMimeType.toAscii().constData(), vaType));
     421
     422    int rc = VINF_SUCCESS;
     423
     424    /* Start getting the data from the source. Request and transfer data
     425     * from the source and display a modal progress dialog while doing this. */
     426    Assert(!m_dndSource.isNull());
     427    CProgress progress = m_dndSource.Drop(strMimeType,
     428                                          UIDnDHandler::toVBoxDnDAction(dropAction));
     429    if (m_dndSource.isOk())
     430    {
     431        msgCenter().showModalProgressDialog(progress,
     432                                            tr("Retrieving data ..."), ":/progress_dnd_gh_90px.png",
     433                                            m_pParent);
     434
     435        LogFlowFunc(("fCanceled=%RTbool, fCompleted=%RTbool, isOk=%RTbool, hrc=%Rhrc\n",
     436                     progress.GetCanceled(), progress.GetCompleted(), progress.isOk(), progress.GetResultCode()));
     437
     438        if (!progress.GetCanceled())
     439        {
     440            rc =   (   progress.isOk()
     441                    && progress.GetResultCode() == 0)
     442                 ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */
     443
     444            if (RT_SUCCESS(rc))
     445            {
     446                /* After we successfully retrieved data from the source we query it from Main. */
     447                QVector<uint8_t> vecData = m_dndSource.ReceiveData();
     448                if (!vecData.isEmpty())
     449                {
     450                    switch (vaType)
     451                    {
     452                        case QVariant::String:
     453                        {
     454                            vaData = QVariant(QString(reinterpret_cast<const char*>(vecData.constData())));
     455                            break;
     456                        }
     457
     458                        case QVariant::ByteArray:
     459                        {
     460                            QByteArray ba(reinterpret_cast<const char*>(vecData.constData()), vecData.size());
     461                            vaData = QVariant(ba);
     462                            break;
     463                        }
     464
     465                        case QVariant::StringList:
     466                        {
     467                            QString strData = QString(reinterpret_cast<const char*>(vecData.constData()));
     468                            QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts);
     469
     470                            vaData = QVariant(lstString);
     471                            break;
     472                        }
     473
     474                        default:
     475                            rc = VERR_NOT_SUPPORTED;
     476                            break;
     477                    }
     478                }
     479                else
     480                    rc = VERR_NO_DATA;
     481            }
     482            else
     483                msgCenter().cannotDropDataToHost(progress, m_pParent);
     484        }
     485        else /* Don't pop up a message. */
     486            rc = VERR_CANCELLED;
     487    }
     488    else
     489    {
     490        msgCenter().cannotDropDataToHost(m_dndSource, m_pParent);
     491        rc = VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */
     492    }
    266493
    267494    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h

    r52727 r55821  
    55
    66/*
    7  * Copyright (C) 2011-2014 Oracle Corporation
     7 * Copyright (C) 2011-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919#define ___UIDnDHandler_h___
    2020
     21/* Qt includes: */
     22#include <QMimeData>
     23#include <QMutex>
     24#include <QStringList>
     25
    2126/* COM includes: */
    2227#include "COMEnums.h"
     28#include "CDnDTarget.h"
     29#include "CDnDSource.h"
    2330
    2431/* Forward declarations: */
    2532class QMimeData;
    26 class CDnDSource;
    27 class CDnDTarget;
    28 class CGuest;
    29 class CSession;
    30 class UIDnDMimeData;
     33
     34class UIDnDMIMEData;
     35class UISession;
    3136
    3237class UIDnDHandler: public QObject
     
    3641public:
    3742
    38     /* Singleton factory. */
    39     static UIDnDHandler *instance(void)
    40     {
    41         if (!m_pInstance)
    42             m_pInstance = new UIDnDHandler();
    43         return m_pInstance;
    44     }
    45 
    46     static void destroy(void)
    47     {
    48         if (m_pInstance)
    49         {
    50             delete m_pInstance;
    51             m_pInstance = NULL;
    52         }
    53     }
     43    UIDnDHandler(UISession *pSession, QWidget *pParent);
     44    virtual ~UIDnDHandler(void);
    5445
    5546    /**
    5647     * Current operation mode.
    5748     */
    58     enum Direction
     49    typedef enum DNDMODE
    5950    {
    6051        /** Unknown mode. */
    61         Unknown = 0,
     52        DNDMODE_UNKNOWN    = 0,
    6253        /** Host to guest. */
    63         HostToGuest,
     54        DNDMODE_HOSTTOGUEST = 1,
    6455        /** Guest to host. */
    65         GuestToHost
     56        DNDMODE_GUESTTOHOST = 2,
    6657        /** @todo Implement guest to guest. */
    67     };
     58        /** The usual 32-bit type blow up. */
     59        DNDMODE_32BIT_HACK = 0x7fffffff
     60    } DNDMODE;
    6861
    6962    /* Frontend -> Target. */
    70     Qt::DropAction             dragEnter(CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
    71     Qt::DropAction             dragMove (CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
    72     Qt::DropAction             dragDrop (CSession &session, CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
    73     void                       dragLeave(CDnDTarget &dndTarget, ulong screenId, QWidget *pParent = NULL);
     63    Qt::DropAction             dragEnter(ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData);
     64    Qt::DropAction             dragMove (ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData);
     65    Qt::DropAction             dragDrop (ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData);
     66    void                       dragLeave(ulong screenId);
    7467
    7568    /* Source -> Frontend. */
    76     int                        dragIsPending(CSession &session, CDnDSource &dndSource, ulong screenId, QWidget *pParent = NULL);
     69    int                        dragIsPending(ulong screenId);
     70    int                        dragStart(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
     71    int                        retrieveData(Qt::DropAction  dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData);
    7772
    7873public:
     
    8378    static Qt::DropActions     toQtDnDActions(const QVector<KDnDAction> &vecActions);
    8479
    85 private:
     80protected:
    8681
    87     UIDnDHandler(void);
    88     virtual ~UIDnDHandler(void) {}
     82    /** Pointer to UI session. */
     83    UISession        *m_pSession;
     84    /** Pointer to parent widget. */
     85    QWidget          *m_pParent;
    8986
    90 private:
     87    /** Drag and drop source instance. */
     88    CDnDSource        m_dndSource;
     89    /** Drag and drop target instance. */
     90    CDnDTarget        m_dndTarget;
     91    /** Current transfer direction. */
     92    DNDMODE           m_enmMode;
     93    /** Flag indicating if a drag operation is pending currently. */
     94    bool              m_fIsPending;
     95    QMutex            m_ReadLock;
     96    QMutex            m_WriteLock;
    9197
    92     /** Static pointer to singleton instance. */
    93     static UIDnDHandler *m_pInstance;
     98    /** List of formats supported by the source. */
     99    QStringList       m_lstFormats;
     100    /** Default drop action from the source. */
     101    Qt::DropAction    m_defAction;
     102    /** List of allowed drop actions from the source. */
     103    Qt::DropActions   m_actions;
     104
     105#ifndef RT_OS_WINDOWS
     106    /** Pointer to MIMEData instance used for handling
     107     *  own MIME times on non-Windows host OSes. */
     108    UIDnDMIMEData    *m_pMIMEData;
     109    friend class UIDnDMIMEData;
     110#endif
    94111};
    95 
    96 /** Gets the singleton instance of the drag'n drop UI helper class. */
    97 #define DnDHandler() UIDnDHandler::instance()
    98 
    99112#endif /* ___UIDnDHandler_h___ */
    100113
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp

    r55180 r55821  
    55
    66/*
    7  * Copyright (C) 2011-2014 Oracle Corporation
     7 * Copyright (C) 2011-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3131/* GUI includes: */
    3232# include "UIDnDMIMEData.h"
    33 # include "UIDnDDrag.h"
    3433# include "UIMessageCenter.h"
    3534
     
    4140
    4241
    43 UIDnDMimeData::UIDnDMimeData(CSession &session,
    44                              CDnDSource &dndSource,
    45                              QStringList formats,
    46                              Qt::DropAction defAction, Qt::DropActions actions,
    47                              QWidget *pParent)
    48     : m_Session(session)
    49     , m_DnDSource(dndSource)
    50     , m_lstFormats(formats)
     42UIDnDMIMEData::UIDnDMIMEData(UIDnDHandler *pDnDHandler,
     43                             QStringList lstFormats, Qt::DropAction defAction, Qt::DropActions actions)
     44    : m_pDnDHandler(pDnDHandler)
     45    , m_lstFormats(lstFormats)
    5146    , m_defAction(defAction)
    5247    , m_actions(actions)
    53     , m_pParent(pParent)
    5448    , m_enmState(Dragging)
    5549    , m_vaData(QVariant::Invalid)
     
    5751    LogFlowThisFuncEnter();
    5852
    59     /*
     53#ifdef DEBUG
     54    LogFlowFunc(("Number of formats: %d\n", lstFormats.size()));
     55    for (int i = 0; i < lstFormats.size(); i++)
     56        LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toAscii().constData()));
     57#endif
     58
     59     /**
    6060     * This is unbelievable hacky, but I didn't find another way. Stupid
    6161     * Qt QDrag interface is so less verbose, that we in principle know
     
    8383     *       and will take care of all the input handling. */
    8484#ifndef RT_OS_WINDOWS
     85    /* Install the event filter in a deferred way. */
    8586    QTimer::singleShot(0, this, SLOT(sltInstallEventFilter()));
    8687#endif
    87 
    88 #ifdef DEBUG
    89     LogFlowFunc(("Number of formats: %d\n", formats.size()));
    90     for (int i = 0; i < formats.size(); i++)
    91         LogFlowFunc(("\tFormat %d: %s\n", i, formats.at(i).toAscii().constData()));
    92 #endif
    93 }
    94 
    95 void UIDnDMimeData::sltDropActionChanged(Qt::DropAction dropAction)
    96 {
    97     LogFlowFunc(("dropAction=0x%x\n", dropAction));
    98     m_defAction = dropAction;
    99 }
    100 
    101 QStringList UIDnDMimeData::formats(void) const
     88}
     89
     90QStringList UIDnDMIMEData::formats(void) const
    10291{
    10392    return m_lstFormats;
    10493}
    10594
    106 bool UIDnDMimeData::hasFormat(const QString &strMIMEType) const
     95bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const
    10796{
    10897    bool fRc = m_lstFormats.contains(strMIMEType);
    10998    LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool)\n",
    110                  strMIMEType.toStdString().c_str(),
    111                  fRc, QMimeData::hasFormat(strMIMEType)));
     99                 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType)));
    112100    return fRc;
    113101}
    114102
    115 QVariant UIDnDMimeData::retrieveData(const QString &strMIMEType,
    116                                      QVariant::Type vaType)
    117 {
    118     LogFlowFunc(("m_enmState=%d, mimeType=%s, type=%d (%s)\n",
    119                  m_enmState, strMIMEType.toStdString().c_str(),
     103/**
     104 * Called by Qt's drag'n drop operation (QDrag) for retrieving the actual drag'n drop
     105 * data in case of a successful drag'n drop operation.
     106 *
     107 * @param strMIMEType           MIME type string.
     108 * @param vaType                Variant containing the actual data based on the the MIME type.
     109 *
     110 * @return QVariant
     111 */
     112QVariant UIDnDMIMEData::retrieveData(const QString &strMIMEType, QVariant::Type vaType) const
     113{
     114    LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState, strMIMEType.toStdString().c_str(),
    120115                 vaType, QVariant::typeToName(vaType)));
    121116
     
    139134        && !m_lstFormats.contains(strMIMEType))
    140135    {
    141         LogFlowFunc(("Unsupported MIME type=%s\n",
    142                      strMIMEType.toStdString().c_str()));
     136        LogRel3(("DnD: Unsupported MIME type=%s\n", strMIMEType.toStdString().c_str()));
    143137        fCanDrop = false;
    144138    }
     
    154148             || vaType == QVariant::List))
    155149    {
    156         LogFlowFunc(("Unsupported data type=%d (%s)\n",
    157                      vaType, QVariant::typeToName(vaType)));
     150        LogRel3(("DnD: Unsupported data type=%d (%s)\n", vaType, QVariant::typeToName(vaType)));
    158151        fCanDrop = false;
    159152    }
    160153
     154    LogRel3(("DnD: State=%ld, fCanDrop=%RTbool\n", m_enmState, fCanDrop));
     155
    161156    if (!fCanDrop)
    162157    {
    163         LogFlowFunc(("Skipping request, m_enmState=%d ...\n",
    164                      m_enmState));
     158        LogFlowFunc(("Skipping request, state=%RU32 ...\n", m_enmState));
    165159        return QMimeData::retrieveData(strMIMEType, vaType);
    166160    }
    167161
    168     int rc = VINF_SUCCESS;
    169     if (m_enmState == Dropped)
    170     {
    171         rc = UIDnDDrag::RetrieveData(m_Session,
    172                                      m_DnDSource,
    173                                      m_defAction,
    174                                      strMIMEType, vaType, m_vaData,
    175                                      m_pParent);
    176         if (RT_SUCCESS(rc))
    177         {
    178             /* Tell ourselves that data became available. */
    179             emit sigDataAvailable(strMIMEType);
    180         }
    181         else
    182         {
    183             m_enmState = Canceled;
    184         }
    185     }
    186 
    187     LogFlowFunc(("Returning rc=%Rrc, m_enmState=%ld\n",
    188                  rc, m_enmState));
     162    /* Note: The const_cast is used because this function needs to be const (otherwise
     163     *       Qt won't call it), but we need the stuff in an unconst'ed way. */
     164    int rc = const_cast<UIDnDMIMEData *>(this)->retrieveDataInternal(strMIMEType, vaType);
     165
     166    LogFlowFunc(("Returning rc=%Rrc, state=%RU32\n", rc, m_enmState));
    189167    return m_vaData;
    190168}
    191169
    192170#ifndef RT_OS_WINDOWS
    193 bool UIDnDMimeData::eventFilter(QObject *pObject, QEvent *pEvent)
    194 {
     171bool UIDnDMIMEData::eventFilter(QObject *pObject, QEvent *pEvent)
     172{
     173    bool fRemoveFilter = false;
     174
    195175    if (pEvent)
    196176    {
    197177        switch (pEvent->type())
    198178        {
    199 #ifdef DEBUG_andy
    200179            case QEvent::MouseMove:
    201180            {
    202181                QMouseEvent *pMouseEvent = (QMouseEvent*)(pEvent);
    203182                AssertPtr(pMouseEvent);
    204                 LogFlowFunc(("MouseMove: x=%d, y=%d\n",
    205                              pMouseEvent->globalX(), pMouseEvent->globalY()));
    206 
    207                 return true;
    208                 /* Never reached. */
     183                LogFlowFunc(("MouseMove: x=%d, y=%d\n", pMouseEvent->globalX(), pMouseEvent->globalY()));
     184
     185                break;
    209186            }
    210 #endif
     187
    211188            case QEvent::MouseButtonRelease:
    212189            {
     
    214191                m_enmState = Dropped;
    215192
    216                 return true;
    217                 /* Never reached. */
     193                fRemoveFilter = true;
     194                break;
    218195            }
    219196
     
    223200                if (static_cast<QKeyEvent*>(pEvent)->key() == Qt::Key_Escape)
    224201                {
    225                     LogFlowFunc(("ESC pressed, cancelling drag and drop operation\n"));
     202                    LogRel2(("DnD: ESC pressed, cancelling drag and drop operation\n"));
    226203                    m_enmState = Canceled;
     204
     205                    fRemoveFilter = true;
    227206                }
    228 
    229                 return true;
    230                 /* Never reached. */
     207                break;
    231208            }
    232209
     
    236213    }
    237214
     215    if (fRemoveFilter)
     216    {
     217        LogFlowFunc(("Removing event filter ...\n"));
     218        AssertPtr(qApp);
     219        qApp->removeEventFilter(this);
     220    }
     221
     222    /* Do normal processing by Qt. */
    238223    return QObject::eventFilter(pObject, pEvent);
    239224}
    240 
    241 void UIDnDMimeData::sltInstallEventFilter(void)
    242 {
    243     LogFlowFunc(("Installing event filter ...\n"));
    244     AssertPtr(qApp);
    245     qApp->installEventFilter(this);
    246 }
    247 #endif /* RT_OS_WINDOWS */
    248 
    249 int UIDnDMimeData::setData(const QString &mimeType)
     225#endif /* !RT_OS_WINDOWS */
     226
     227int UIDnDMIMEData::setData(const QString &mimeType)
    250228{
    251229    LogFlowFunc(("mimeType=%s, dataType=%s\n",
     
    275253            {
    276254                QFileInfo fileInfo(lstData.at(i).toString());
    277 #ifdef DEBUG
     255
    278256                LogFlowFunc(("\tURL: %s (fExists=%RTbool, fIsDir=%RTbool, cb=%RU64)\n",
    279257                             fileInfo.absoluteFilePath().constData(), fileInfo.exists(),
    280258                             fileInfo.isDir(), fileInfo.size()));
    281 #endif
     259
    282260                lstURL << QUrl::fromLocalFile(fileInfo.absoluteFilePath());
    283261            }
     
    298276}
    299277
     278int UIDnDMIMEData::retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType)
     279{
     280    LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState,
     281                  strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
     282
     283    AssertPtr(m_pDnDHandler);
     284    int rc = m_pDnDHandler->retrieveData(m_defAction, strMIMEType, vaType, m_vaData);
     285    if (RT_SUCCESS(rc))
     286    {
     287        /* Nothing to do here yet. */
     288    }
     289    else if (rc == VERR_CANCELLED)
     290        m_enmState = Canceled;
     291    else
     292        m_enmState = Error;
     293
     294    LogFlowFuncLeaveRC(rc);
     295    return rc;
     296}
     297
     298/**
     299 * Issued by the QDrag object as soon as the current drop action has changed.
     300 *
     301 * @param dropAction            New drop action to use.
     302 */
     303void UIDnDMIMEData::sltDropActionChanged(Qt::DropAction dropAction)
     304{
     305    LogFlowFunc(("dropAction=0x%x\n", dropAction));
     306    m_defAction = dropAction;
     307}
     308
     309#ifndef RT_OS_WINDOWS
     310/**
     311 * Issued by ourselves to install the event filter.
     312 */
     313void UIDnDMIMEData::sltInstallEventFilter(void)
     314{
     315    LogFlowFunc(("Installing event filter ...\n"));
     316    AssertPtr(qApp);
     317    qApp->installEventFilter(this);
     318}
     319#endif
     320
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h

    r52727 r55821  
    55
    66/*
    7  * Copyright (C) 2011-2014 Oracle Corporation
     7 * Copyright (C) 2011-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3131#include "UIDnDHandler.h"
    3232
    33 /* Forward declarations: */
    34 class UIDnDDrag;
    35 
    3633/** @todo Subclass QWindowsMime / QMacPasteboardMime
    3734 *  to register own/more MIME types. */
     
    4138 * handling all guest-to-host transfers.
    4239 */
    43 class UIDnDMimeData: public QMimeData
     40class UIDnDMIMEData: public QMimeData
    4441{
    4542    Q_OBJECT;
     
    5552        Dropped,
    5653        /** The operation has been canceled. */
    57         Canceled
     54        Canceled,
     55        /** An error occurred. */
     56        Error,
     57        /** The usual 32-bit type blow up. */
     58        State_32BIT_Hack = 0x7fffffff
    5859    };
    5960
    6061public:
    6162
    62     UIDnDMimeData(CSession &session, CDnDSource &dndSource, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions, QWidget *pParent);
     63    UIDnDMIMEData(UIDnDHandler *pDnDHandler, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions);
    6364
    6465public:
     
    7778    virtual bool hasFormat(const QString &mimeType) const;
    7879
    79     virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type);
     80    virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
    8081
    8182#ifndef RT_OS_WINDOWS
     
    8485    /** @}  */
    8586
    86 signals:
     87    int retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType);
    8788
    88     void sigDataAvailable(const QString &mimeType) const;
    89 
    90 private slots:
     89protected slots:
    9190
    9291#ifndef RT_OS_WINDOWS
     
    9493#endif
    9594
    96 private:
     95protected:
    9796
    98     CSession          m_Session;
    99     CDnDSource        m_DnDSource;
     97    UIDnDHandler     *m_pDnDHandler;
     98
    10099    QStringList       m_lstFormats;
    101100    Qt::DropAction    m_defAction;
    102101    Qt::DropActions   m_actions;
    103     QWidget          *m_pParent;
     102
    104103    mutable State     m_enmState;
    105104    mutable QVariant  m_vaData;
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r55726 r55821  
    55
    66/*
    7  * Copyright (C) 2010-2012 Oracle Corporation
     7 * Copyright (C) 2010-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    101101
    102102
     103/* static */
    103104UIMachineView* UIMachineView::create(  UIMachineWindow *pMachineWindow
    104105                                     , ulong uScreenId
     
    163164    pMachineView->sltMachineStateChanged();
    164165    /** @todo Can we move the call to sltAdditionsStateChanged() from the
    165      * subclass constructors here too?  It is called for Normal and Seamless,
    166      * but not for Fullscreen and Scale.  However for Scale it is a no op.,
    167      * so it would not hurt.  Would it hurt for Fullscreen? */
     166     *        subclass constructors here too?  It is called for Normal and Seamless,
     167     *        but not for Fullscreen and Scale.  However for Scale it is a no op.,
     168     *        so it would not hurt.  Would it hurt for fullscreen? */
    168169
    169170    /* Set a preliminary maximum size: */
     
    173174}
    174175
     176/* static */
    175177void UIMachineView::destroy(UIMachineView *pMachineView)
    176178{
     179    if (!pMachineView)
     180        return;
     181
     182#ifdef VBOX_WITH_DRAG_AND_DROP
     183    if (pMachineView->m_pDnDHandler)
     184        delete pMachineView->m_pDnDHandler;
     185#endif
    177186    delete pMachineView;
    178187}
     
    675684
    676685#ifdef VBOX_WITH_DRAG_AND_DROP
    677     /* Enable Drag & Drop. */
     686    /* Enable drag & drop. */
    678687    setAcceptDrops(true);
     688
     689    /* Create the drag and drop handler instance.
     690     * At the moment we only support one instance per machine window. */
     691    m_pDnDHandler = new UIDnDHandler(uisession(), this /* pParent */);
    679692#endif /* VBOX_WITH_DRAG_AND_DROP */
    680693}
     
    14021415
    14031416#ifdef VBOX_WITH_DRAG_AND_DROP
     1417/**
     1418 * Host -> Guest: Issued when the host cursor enters the guest (VM) window.
     1419 *                The guest will receive the relative cursor coordinates of the
     1420 *                appropriate screen ID.
     1421 *
     1422 * @param pEvent                Related enter event.
     1423 */
    14041424void UIMachineView::dragEnterEvent(QDragEnterEvent *pEvent)
    14051425{
     
    14091429    const QPoint &cpnt = viewportToContents(pEvent->pos());
    14101430
    1411     CDnDTarget dndTarget = static_cast<CDnDTarget>(guest().GetDnDTarget());
    1412 
    14131431    /* Ask the target for starting a DnD event. */
    1414     Qt::DropAction result = DnDHandler()->dragEnter(dndTarget,
    1415                                                     screenId(),
     1432    Qt::DropAction result = m_pDnDHandler->dragEnter(screenId(),
     1433                                                     frameBuffer()->convertHostXTo(cpnt.x()),
     1434                                                     frameBuffer()->convertHostYTo(cpnt.y()),
     1435                                                     pEvent->proposedAction(),
     1436                                                     pEvent->possibleActions(),
     1437                                                     pEvent->mimeData());
     1438
     1439    /* Set the DnD action returned by the guest. */
     1440    pEvent->setDropAction(result);
     1441    pEvent->accept();
     1442}
     1443
     1444/**
     1445 * Host -> Guest: Issued when the host cursor moves inside (over) the guest (VM) window.
     1446 *                The guest will receive the relative cursor coordinates of the
     1447 *                appropriate screen ID.
     1448 *
     1449 * @param pEvent                Related move event.
     1450 */
     1451void UIMachineView::dragMoveEvent(QDragMoveEvent *pEvent)
     1452{
     1453    AssertPtrReturnVoid(pEvent);
     1454
     1455    /* Get mouse-pointer location. */
     1456    const QPoint &cpnt = viewportToContents(pEvent->pos());
     1457
     1458    /* Ask the guest for moving the drop cursor. */
     1459    Qt::DropAction result = m_pDnDHandler->dragMove(screenId(),
    14161460                                                    frameBuffer()->convertHostXTo(cpnt.x()),
    14171461                                                    frameBuffer()->convertHostYTo(cpnt.y()),
    14181462                                                    pEvent->proposedAction(),
    14191463                                                    pEvent->possibleActions(),
    1420                                                     pEvent->mimeData(), this /* pParent */);
     1464                                                    pEvent->mimeData());
    14211465
    14221466    /* Set the DnD action returned by the guest. */
     
    14251469}
    14261470
    1427 void UIMachineView::dragMoveEvent(QDragMoveEvent *pEvent)
     1471/**
     1472 * Host -> Guest: Issued when the host cursor leaves the guest (VM) window again.
     1473 *                This will ask the guest to stop any further drag'n drop operation.
     1474 *
     1475 * @param pEvent                Related leave event.
     1476 */
     1477void UIMachineView::dragLeaveEvent(QDragLeaveEvent *pEvent)
     1478{
     1479    AssertPtrReturnVoid(pEvent);
     1480
     1481    m_pDnDHandler->dragLeave(screenId());
     1482
     1483    pEvent->accept();
     1484}
     1485
     1486/**
     1487 * Guest -> Host: Checks for a pending drag and drop event within the guest
     1488 *                and (optionally) starts a drag and drop operation on the host.
     1489 */
     1490void UIMachineView::dragIsPending(void)
     1491{
     1492    /** @todo Add guest->guest DnD functionality here by getting
     1493     *        the source of guest B (when copying from B to A). */
     1494    m_pDnDHandler->dragIsPending(screenId());
     1495}
     1496
     1497/**
     1498 * Host -> Guest: Issued when the host drops data into the guest (VM) window.
     1499 *
     1500 * @param pEvent                Related drop event.
     1501 */
     1502void UIMachineView::dropEvent(QDropEvent *pEvent)
    14281503{
    14291504    AssertPtrReturnVoid(pEvent);
     
    14321507    const QPoint &cpnt = viewportToContents(pEvent->pos());
    14331508
    1434     CDnDTarget dndTarget = static_cast<CDnDTarget>(guest().GetDnDTarget());
    1435 
    1436     /* Ask the guest for moving the drop cursor. */
    1437     Qt::DropAction result = DnDHandler()->dragMove(dndTarget,
    1438                                                    screenId(),
    1439                                                    frameBuffer()->convertHostXTo(cpnt.x()),
    1440                                                    frameBuffer()->convertHostYTo(cpnt.y()),
    1441                                                    pEvent->proposedAction(),
    1442                                                    pEvent->possibleActions(),
    1443                                                    pEvent->mimeData(), this /* pParent */);
    1444 
    1445     /* Set the DnD action returned by the guest. */
    1446     pEvent->setDropAction(result);
    1447     pEvent->accept();
    1448 }
    1449 
    1450 void UIMachineView::dragLeaveEvent(QDragLeaveEvent *pEvent)
    1451 {
    1452     AssertPtrReturnVoid(pEvent);
    1453 
    1454     CDnDTarget dndTarget = static_cast<CDnDTarget>(guest().GetDnDTarget());
    1455 
    1456     /* Ask the guest for stopping this DnD event. */
    1457     DnDHandler()->dragLeave(dndTarget,
    1458                             screenId(), this /* pParent */);
    1459     pEvent->accept();
    1460 }
    1461 
    1462 void UIMachineView::dragIsPending(void)
    1463 {
    1464     /** @todo Add guest->guest DnD functionality here by getting
    1465      *        the source of guest B (when copying from B to A). */
    1466     CDnDSource dndSource = static_cast<CDnDSource>(guest().GetDnDSource());
    1467 
    1468     /* Check for a pending DnD event within the guest and if so, handle all the
    1469      * magic. */
    1470     DnDHandler()->dragIsPending(session(), dndSource, screenId(), this /* pParent */);
    1471 }
    1472 
    1473 void UIMachineView::dropEvent(QDropEvent *pEvent)
    1474 {
    1475     AssertPtrReturnVoid(pEvent);
    1476 
    1477     /* Get mouse-pointer location. */
    1478     const QPoint &cpnt = viewportToContents(pEvent->pos());
    1479 
    1480     CDnDTarget dndTarget = static_cast<CDnDTarget>(guest().GetDnDTarget());
    1481 
    14821509    /* Ask the guest for dropping data. */
    1483     Qt::DropAction result = DnDHandler()->dragDrop(session(),
    1484                                                    dndTarget,
    1485                                                    screenId(),
    1486                                                    frameBuffer()->convertHostXTo(cpnt.x()),
    1487                                                    frameBuffer()->convertHostYTo(cpnt.y()),
    1488                                                    pEvent->proposedAction(),
    1489                                                    pEvent->possibleActions(),
    1490                                                    pEvent->mimeData(), this /* pParent */);
     1510    Qt::DropAction result = m_pDnDHandler->dragDrop(screenId(),
     1511                                                    frameBuffer()->convertHostXTo(cpnt.x()),
     1512                                                    frameBuffer()->convertHostYTo(cpnt.y()),
     1513                                                    pEvent->proposedAction(),
     1514                                                    pEvent->possibleActions(),
     1515                                                    pEvent->mimeData());
    14911516
    14921517    /* Set the DnD action returned by the guest. */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r55726 r55821  
    2424
    2525/* GUI includes: */
     26#ifdef VBOX_WITH_DRAG_AND_DROP
     27# include "UIDnDHandler.h"
     28#endif
     29#include "UIExtraDataDefs.h"
    2630#include "UIMachineDefs.h"
    27 #include "UIExtraDataDefs.h"
    2831#ifdef Q_WS_MAC
    2932# include <CoreFoundation/CFBase.h>
     
    309312    QPixmap m_pausePixmapScaled;
    310313
     314#ifdef VBOX_WITH_DRAG_AND_DROP
     315    /** Pointer to drag and drop handler instance. */
     316    UIDnDHandler *m_pDnDHandler;
     317#endif
     318
    311319    /* Friend classes: */
    312320    friend class UIKeyboardHandler;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette