VirtualBox

Changeset 56497 in vbox


Ignore:
Timestamp:
Jun 18, 2015 10:50:40 AM (10 years ago)
Author:
vboxsync
Message:

DnD: FE/Qt: Removed a lot of complexity by not having a separate MIME data event filter anymore, miscellaneous state machine fixes, adjusted logging.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/runtime
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp

    r56138 r56497  
    104104                                          pMimeData->formats().toVector());
    105105    if (m_dndTarget.isOk())
    106         m_enmMode = DNDMODE_HOSTTOGUEST;
     106        setMode(DNDMODE_HOSTTOGUEST);
    107107
    108108    /* Set the DnD action returned by the guest. */
     
    201201     * mode as well here.
    202202     */
    203     m_enmMode = DNDMODE_UNKNOWN;
     203    setMode(DNDMODE_UNKNOWN);
    204204
    205205    return toQtDnDAction(result);
     
    213213    {
    214214        m_dndTarget.Leave(screenID);
    215         m_enmMode = DNDMODE_UNKNOWN;
     215        setMode(DNDMODE_UNKNOWN);
    216216    }
    217217}
     
    221221 */
    222222
    223 int UIDnDHandler::dragStart(const QStringList &lstFormats,
    224                             Qt::DropAction defAction, Qt::DropActions actions)
     223int UIDnDHandler::dragStartInternal(const QStringList &lstFormats,
     224                                    Qt::DropAction defAction, Qt::DropActions actions)
    225225{
    226226    int rc = VINF_SUCCESS;
     
    228228#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    229229
    230     m_lstFormats = lstFormats;
    231     m_defAction  = defAction;
    232     m_actions    = actions;
    233 
    234     LogFlowFunc(("m_defAction=0x%x\n", m_defAction));
    235     LogFlowFunc(("Number of formats: %d\n", m_lstFormats.size()));
     230    LogFlowFunc(("defAction=0x%x\n", defAction));
     231    LogFlowFunc(("Number of formats: %d\n", lstFormats.size()));
    236232# ifdef DEBUG
    237     for (int i = 0; i < m_lstFormats.size(); i++)
    238         LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toAscii().constData()));
     233    for (int i = 0; i < lstFormats.size(); i++)
     234        LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toAscii().constData()));
    239235# endif
    240236
     
    244240    if (!pDropSource)
    245241        return VERR_NO_MEMORY;
    246     UIDnDDataObject *pDataObject = new UIDnDDataObject(this, m_lstFormats);
     242    UIDnDDataObject *pDataObject = new UIDnDDataObject(this, lstFormats);
    247243    if (!pDataObject)
    248244        return VERR_NO_MEMORY;
    249245
    250246    DWORD dwOKEffects = DROPEFFECT_NONE;
    251     if (m_actions)
    252     {
    253         if (m_actions & Qt::CopyAction)
     247    if (actions)
     248    {
     249        if (actions & Qt::CopyAction)
    254250            dwOKEffects |= DROPEFFECT_COPY;
    255         if (m_actions & Qt::MoveAction)
     251        if (actions & Qt::MoveAction)
    256252            dwOKEffects |= DROPEFFECT_MOVE;
    257         if (m_actions & Qt::LinkAction)
     253        if (actions & Qt::LinkAction)
    258254            dwOKEffects |= DROPEFFECT_LINK;
    259255    }
     
    276272
    277273    /* Note: pMData is transferred to the QDrag object, so no need for deletion. */
    278     m_pMIMEData = new UIDnDMIMEData(this, m_lstFormats, m_defAction, m_actions);
     274    m_pMIMEData = new UIDnDMIMEData(this, lstFormats, defAction, actions);
    279275    if (!m_pMIMEData)
    280276    {
     
    282278        return VERR_NO_MEMORY;
    283279    }
     280
     281    /* Invoke this handler as data needs to be retrieved. */
     282    connect(m_pMIMEData, SIGNAL(getData(QString, QVariant::Type)),
     283            this, SLOT(sltGetData(QString, QVariant::Type)));
    284284
    285285    /* Inform the MIME data object of any changes in the current action. */
     
    292292     */
    293293    pDrag->setMimeData(m_pMIMEData);
    294     Qt::DropAction dropAction = pDrag->exec(m_actions, m_defAction);
     294    LogFlowFunc(("Executing modal drag'n drop operation ...\n"));
     295    Qt::DropAction dropAction = pDrag->exec(actions, defAction);
    295296    LogRel3(("DnD: Ended with dropAction=%ld\n", UIDnDHandler::toVBoxDnDAction(dropAction)));
    296297
     
    313314}
    314315
    315 int UIDnDHandler::dragIsPending(ulong screenID)
     316int UIDnDHandler::dragCheckPending(ulong screenID)
    316317{
    317318    int rc;
     
    331332    }
    332333
    333     QMutexLocker AutoWriteLock(&m_ReadLock);
     334    QMutexLocker AutoWriteLock(&m_WriteLock);
    334335    m_fIsPending = true;
    335336    AutoWriteLock.unlock();
     
    348349    CGuest guest = m_pSession->guest();
    349350
    350     QVector<QString> vecFmtGuest;
    351     QVector<KDnDAction> vecActions;
    352     KDnDAction defaultAction = m_dndSource.DragIsPending(screenID, vecFmtGuest, vecActions);
    353     LogFlowFunc(("defaultAction=%d, numFormats=%d, numActions=%d\n", defaultAction,
    354                  vecFmtGuest.size(), vecActions.size()));
    355 
    356     QStringList lstFmtNative;
    357     if (defaultAction != KDnDAction_Ignore)
    358     {
    359         LogRel3(("DnD: Number of supported guest actions: %d\n", vecActions.size()));
    360         for (int i = 0; i < vecActions.size(); i++)
    361             LogRel3(("\tAction %d: 0x%x\n", i, vecActions.at(i)));
    362 
    363         /**
    364          * Do guest -> host format conversion, if needed.
    365          * On X11 this already maps to the Xdnd protocol.
    366          ** @todo What about the MacOS Carbon Drag Manager? Needs testing.
    367          *
    368          * See: https://www.iana.org/assignments/media-types/media-types.xhtml
    369          */
    370         LogRel3(("DnD: Number of supported guest formats: %d\n", vecFmtGuest.size()));
    371         for (int i = 0; i < vecFmtGuest.size(); i++)
     351    /* Clear our current data set. */
     352    m_dataSource.lstFormats.clear();
     353    m_dataSource.vecActions.clear();
     354
     355    /* Ask the guest if there is a drag and drop operation pending (on the guest). */
     356    QVector<QString> vecFormats;
     357    m_dataSource.defaultAction = m_dndSource.DragIsPending(screenID, vecFormats, m_dataSource.vecActions);
     358
     359    LogRel3(("DnD: Default action is: 0x%x\n", m_dataSource.defaultAction));
     360    LogRel3(("DnD: Number of supported guest actions: %d\n", m_dataSource.vecActions.size()));
     361        for (int i = 0; i < m_dataSource.vecActions.size(); i++)
     362            LogRel3(("\tAction %d: 0x%x\n", i, m_dataSource.vecActions.at(i)));
     363
     364    LogRel3(("DnD: Number of supported guest formats: %d\n", vecFormats.size()));
     365        for (int i = 0; i < vecFormats.size(); i++)
    372366        {
    373             const QString &strFmtGuest = vecFmtGuest.at(i);
     367            const QString &strFmtGuest = vecFormats.at(i);
    374368            LogRel3(("\tFormat %d: %s\n", i, strFmtGuest.toAscii().constData()));
    375 # ifdef RT_OS_WINDOWS
    376             /* CF_TEXT -> Regular text. */
    377             if (   strFmtGuest.contains("text/plain", Qt::CaseInsensitive)
    378                 && !lstFmtNative.contains("text/plain"))
    379             {
    380                 lstFmtNative << "text/plain";
    381             }
    382             /* CF_HDROP -> URI list. */
    383             else if (   strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)
    384                      && !lstFmtNative.contains("text/uri-list"))
    385             {
    386                 lstFmtNative << "text/uri-list";
    387             }
    388 # else /* RT_OS_WINDOWS */
    389 
    390             /* On non-Windows just do a 1:1 mapping. */
    391             lstFmtNative << strFmtGuest;
    392 #  ifdef RT_OS_MACOS
    393             /** @todo Does the 1:1 format mapping apply on OS X? Needs testing! */
    394 #  endif
    395 
    396 # endif /* !RT_OS_WINDOWS */
    397369        }
    398370
    399         LogRel3(("DnD: Number of supported host formats: %d\n", lstFmtNative.size()));
    400         for (int i = 0; i < lstFmtNative.size(); i++)
    401             LogRel3(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
    402     }
    403 
    404     if (!lstFmtNative.isEmpty())
    405     {
    406         rc = dragStart(lstFmtNative,
    407                        toQtDnDAction(defaultAction), toQtDnDActions(vecActions));
     371    if (   m_dataSource.defaultAction != KDnDAction_Ignore
     372        && vecFormats.size())
     373    {
     374        for (int i = 0; i < vecFormats.size(); i++)
     375        {
     376            const QString &strFormat = vecFormats.at(i);
     377            m_dataSource.lstFormats << strFormat;
     378        }
     379
     380        rc = VINF_SUCCESS; /* There's a valid pending drag and drop operation on the guest. */
    408381    }
    409382    else /* No format data from the guest arrived yet. */
     
    426399}
    427400
    428 /**
    429  * Called by UIDnDMIMEData (Linux, OS X, Solaris) or UIDnDDataObject (Windows)
    430  * to start retrieving the actual data from the guest. This function will block
    431  * and show a modal progress dialog until the data transfer is complete.
    432  *
    433  * @return IPRT return code.
    434  * @param dropAction            Drop action to perform.
    435  * @param strMimeType           MIME data type.
    436  * @param vaType                Qt's variant type of the MIME data.
    437  * @param vaData                The actual MIME data.
    438  * @param pParent               Pointer to parent widget.
    439  */
    440 int UIDnDHandler::retrieveData(      Qt::DropAction  dropAction,
    441                                const QString        &strMimeType,
    442                                      QVariant::Type  vaType,
    443                                      QVariant       &vaData)
     401int UIDnDHandler::dragStart(ulong screenID)
     402{
     403    int rc;
     404#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     405
     406    LogFlowFuncEnter();
     407
     408    /* Sanity checks. */
     409    if (   !m_dataSource.lstFormats.size()
     410        ||  m_dataSource.defaultAction == KDnDAction_Ignore
     411        || !m_dataSource.vecActions.size())
     412    {
     413        return VERR_INVALID_PARAMETER;
     414    }
     415
     416    setMode(DNDMODE_GUESTTOHOST);
     417
     418    rc = dragStartInternal(m_dataSource.lstFormats,
     419                           toQtDnDAction(m_dataSource.defaultAction), toQtDnDActions(m_dataSource.vecActions));
     420
     421#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
     422
     423    NOREF(screenID);
     424
     425    rc = VERR_NOT_SUPPORTED;
     426
     427#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     428
     429    LogFlowFuncLeaveRC(rc);
     430    return rc;
     431}
     432
     433int UIDnDHandler::dragStop(ulong screenID)
     434{
     435    int rc;
     436#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     437
     438    m_fIsPending = false;
     439    rc = VINF_SUCCESS;
     440
     441#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
     442
     443    NOREF(screenID);
     444
     445    rc = VERR_NOT_SUPPORTED;
     446
     447#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     448
     449    LogFlowFuncLeaveRC(rc);
     450    return rc;
     451}
     452
     453int UIDnDHandler::retrieveDataInternal(      Qt::DropAction  dropAction,
     454                                       const QString        &strMimeType,
     455                                             QVariant::Type  vaType,
     456                                             QVariant       &vaData)
    444457{
    445458    LogFlowFunc(("Retrieving data as type=%s (variant type=%ld)\n",
     
    518531    }
    519532
     533    setMode(DNDMODE_UNKNOWN);
     534
    520535    LogFlowFuncLeaveRC(rc);
    521536    return rc;
     537}
     538
     539void UIDnDHandler::setMode(DNDMODE enmMode)
     540{
     541    QMutexLocker AutoWriteLock(&m_WriteLock);
     542    m_enmMode = enmMode;
     543    LogFlowFunc(("Mode is now: %RU32\n", m_enmMode));
     544}
     545
     546/**
     547 * Called by UIDnDMIMEData (Linux, OS X, Solaris) to start retrieving the actual data
     548 * from the guest. This function will block and show a modal progress dialog until
     549 * the data transfer is complete.
     550 *
     551 * @return QVariant with data retrieved, if any.
     552 * @param strMimeType           MIME data type.
     553 * @param vaType                Qt's variant type of the MIME data.
     554 */
     555QVariant UIDnDHandler::sltGetData(const QString        &strMimeType,
     556                                        QVariant::Type  vaType)
     557{
     558    QVariant vaData;
     559    int rc = retrieveDataInternal(Qt::CopyAction, strMimeType, vaType, vaData);
     560    LogFlowFuncLeaveRC(rc);
     561    return vaData;
    522562}
    523563
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h

    r56321 r56497  
    6262    } DNDMODE;
    6363
     64    /**
     65     * Drag and drop data set from the source.
     66     */
     67    typedef struct UIDnDDataSource
     68    {
     69        /** List of formats supported by the source. */
     70        QStringList         lstFormats;
     71        /** List of allowed drop actions from the source. */
     72        QVector<KDnDAction> vecActions;
     73        /** Default drop action from the source. */
     74        KDnDAction          defaultAction;
     75
     76    } UIDnDDataSource;
     77
    6478    /* Frontend -> Target. */
    6579    Qt::DropAction             dragEnter(ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData);
     
    6983
    7084    /* Source -> Frontend. */
    71     int                        dragIsPending(ulong screenId);
    72     int                        dragStart(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
     85    int                        dragCheckPending(ulong screenId);
     86    int                        dragStart(ulong screenId);
     87    int                        dragStop(ulong screenID);
    7388    int                        retrieveData(Qt::DropAction  dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData);
    7489
     
    7994    static Qt::DropAction      toQtDnDAction(KDnDAction action);
    8095    static Qt::DropActions     toQtDnDActions(const QVector<KDnDAction> &vecActions);
     96
     97public slots:
     98
     99    QVariant                   sltGetData(const QString &strMimeType, QVariant::Type vaType);
     100
     101protected:
     102
     103    int                        dragStartInternal(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
     104    int                        retrieveDataInternal(Qt::DropAction dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData);
     105    void                       setMode(DNDMODE enmMode);
    81106
    82107protected:
     
    93118    /** Current transfer direction. */
    94119    DNDMODE           m_enmMode;
     120    /** Current data from the source (if any).
     121     *  At the momenet we only support one source at a time. */
     122    UIDnDDataSource   m_dataSource;
    95123    /** Flag indicating if a drag operation is pending currently. */
    96124    bool              m_fIsPending;
    97125    QMutex            m_ReadLock;
    98126    QMutex            m_WriteLock;
    99 
    100     /** List of formats supported by the source. */
    101     QStringList       m_lstFormats;
    102     /** Default drop action from the source. */
    103     Qt::DropAction    m_defAction;
    104     /** List of allowed drop actions from the source. */
    105     Qt::DropActions   m_actions;
    106127
    107128#ifndef RT_OS_WINDOWS
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp

    r56138 r56497  
    4545    , m_lstFormats(lstFormats)
    4646    , m_defAction(defAction)
     47    , m_curAction(Qt::DropAction::IgnoreAction)
    4748    , m_actions(actions)
    4849    , m_enmState(Dragging)
     
    5657        LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toAscii().constData()));
    5758#endif
    58 
    59      /**
    60      * This is unbelievable hacky, but I didn't find another way. Stupid
    61      * Qt QDrag interface is so less verbose, that we in principle know
    62      * nothing about what happens when the user drag something around. It
    63      * is possible that the target on the host requests data
    64      * (@sa retrieveData) while the mouse button still is pressed. This
    65      * isn't something we should support, because it would mean transferring
    66      * the data from the guest while the mouse is still moving (think of
    67      * transferring a 2GB file from the guest to the host ...). So the idea is
    68      * to detect the mouse release event and only after this happened, allow
    69      * data to be retrieved. Unfortunately the QDrag object eats all events
    70      * while a drag is going on (see QDragManager in the Qt src's).
    71      *
    72      * So what we now are going to do is installing an event filter after the
    73      * QDrag::exec is called, so that this event filter then would be
    74      * the last in the event filter queue and therefore called before the
    75      * one installed by the QDrag object (which then in turn would
    76      * munch all events).
    77      *
    78      ** @todo Test this on all supported platforms (X11 works).
    79      *
    80      * Note: On Windows the above hack is not needed because as soon as Qt calls
    81      *       OLE's DoDragDrop routine internally (via QtDrag::exec), no mouse
    82      *       events will come through anymore. At this point DoDragDrop is modal
    83      *       and will take care of all the input handling. */
    84 #ifndef RT_OS_WINDOWS
    85     /* Install the event filter in a deferred way. */
    86     QTimer::singleShot(0, this, SLOT(sltInstallEventFilter()));
    87 #endif
    8859}
    8960
     
    9566bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const
    9667{
    97     bool fRc = m_lstFormats.contains(strMIMEType);
    98     LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool)\n",
    99                  strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType)));
     68    bool fRc = (m_curAction != Qt::DropAction::IgnoreAction);
     69    LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool, curAction=0x%x)\n",
     70                 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType), m_curAction));
    10071    return fRc;
    10172}
     
    11283QVariant UIDnDMIMEData::retrieveData(const QString &strMIMEType, QVariant::Type vaType) const
    11384{
    114     LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState, strMIMEType.toStdString().c_str(),
    115                  vaType, QVariant::typeToName(vaType)));
     85    LogFlowFunc(("state=%RU32, curAction=0x%x, defAction=0x%x, mimeType=%s, type=%d (%s)\n",
     86                 m_enmState, m_curAction, m_defAction, strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
    11687
    11788    bool fCanDrop = true;
     
    12697     * (see UIDnDMimeData::eventFilter). This filter will update the current
    12798     * operation state for us (based on the mouse buttons). */
    128     if (m_enmState != Dropped)
    129     {
    130         LogFlowFunc(("Not yet in 'dropped' state, so can't drop yet\n"));
     99    if (m_curAction == Qt::DropAction::IgnoreAction)
     100    {
     101        LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction));
    131102        fCanDrop = false;
    132103    }
    133104#endif
    134105
    135     /* Do we support the requested MIME type? */
    136     if (   fCanDrop
    137         && !m_lstFormats.contains(strMIMEType))
    138     {
    139         LogRel3(("DnD: Unsupported MIME type=%s\n", strMIMEType.toStdString().c_str()));
    140         fCanDrop = false;
    141     }
    142 
    143     /* Supported types. See below in the switch statement. */
    144     if (   fCanDrop
    145         && !(
    146              /* Plain text. */
    147                 vaType == QVariant::String
    148              /* Binary data. */
    149              || vaType == QVariant::ByteArray
    150              /* URI list. */
    151              || vaType == QVariant::List))
    152     {
    153         LogRel3(("DnD: Unsupported data type=%d (%s)\n", vaType, QVariant::typeToName(vaType)));
    154         fCanDrop = false;
    155     }
    156 
    157     LogRel3(("DnD: State=%ld, fCanDrop=%RTbool\n", m_enmState, fCanDrop));
     106    if (fCanDrop)
     107    {
     108        /* Do we support the requested MIME type? */
     109        if (!m_lstFormats.contains(strMIMEType))
     110        {
     111            LogRel(("DnD: Unsupported MIME type '%s'\n", strMIMEType.toStdString().c_str()));
     112            fCanDrop = false;
     113        }
     114
     115        /* Supported types. See below in the switch statement. */
     116        if (!(
     117              /* Plain text. */
     118                 vaType == QVariant::String
     119              /* Binary data. */
     120              || vaType == QVariant::ByteArray
     121                 /* URI list. */
     122              || vaType == QVariant::List))
     123        {
     124            LogRel(("DnD: Unsupported data type '%s'\n", QVariant::typeToName(vaType)));
     125            fCanDrop = false;
     126        }
     127    }
     128
     129    LogRel3(("DnD: State=%ld, Action=0x%x, fCanDrop=%RTbool\n", m_enmState, m_curAction, fCanDrop));
    158130
    159131    if (!fCanDrop)
    160132    {
    161133        LogFlowFunc(("Skipping request, state=%RU32 ...\n", m_enmState));
    162         return QMimeData::retrieveData(strMIMEType, vaType);
    163     }
    164 
    165     /* Note: The const_cast is used because this function needs to be const (otherwise
    166      *       Qt won't call it), but we need the stuff in an unconst'ed way. */
    167     int rc = const_cast<UIDnDMIMEData *>(this)->retrieveDataInternal(strMIMEType, vaType);
    168 
    169     LogFlowFunc(("Returning rc=%Rrc, state=%RU32\n", rc, m_enmState));
    170     return m_vaData;
     134        return QVariant(QVariant::Invalid); /* Return a NULL variant. */
     135    }
     136
     137    QVariant vaData = emit getData(strMIMEType, vaType);
     138
     139    LogRel3(("DnD: Returning data of type '%s'\n", vaData.typeName()));
     140    return vaData;
    171141}
    172142
     
    180150        switch (pEvent->type())
    181151        {
    182             case QEvent::MouseMove:
    183             {
    184                 QMouseEvent *pMouseEvent = (QMouseEvent*)(pEvent);
    185                 AssertPtr(pMouseEvent);
    186                 LogFlowFunc(("MouseMove: x=%d, y=%d\n", pMouseEvent->globalX(), pMouseEvent->globalY()));
    187 
    188                 break;
    189             }
    190 
    191152            case QEvent::MouseButtonRelease:
    192153            {
     
    223184    }
    224185
    225     /* Do normal processing by Qt. */
    226     return QObject::eventFilter(pObject, pEvent);
     186    /* Propagate further. */
     187    return false;
    227188}
    228189#endif /* !RT_OS_WINDOWS */
    229190
     191#if 0
    230192int UIDnDMIMEData::setData(const QString &mimeType)
    231193{
     
    278240    return rc;
    279241}
    280 
    281 int UIDnDMIMEData::retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType)
    282 {
    283     LogFlowFunc(("state=%RU32, mimeType=%s, type=%d (%s)\n", m_enmState,
    284                   strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
    285 
    286     AssertPtr(m_pDnDHandler);
    287     int rc = m_pDnDHandler->retrieveData(m_defAction, strMIMEType, vaType, m_vaData);
    288     if (RT_SUCCESS(rc))
    289     {
    290         /* Nothing to do here yet. */
    291     }
    292     else if (rc == VERR_CANCELLED)
    293         m_enmState = Canceled;
    294     else
    295         m_enmState = Error;
    296 
    297     LogFlowFuncLeaveRC(rc);
    298     return rc;
    299 }
     242#endif
    300243
    301244/**
     
    307250{
    308251    LogFlowFunc(("dropAction=0x%x\n", dropAction));
    309     m_defAction = dropAction;
    310 }
    311 
    312 #ifndef RT_OS_WINDOWS
    313 /**
    314  * Issued by ourselves to install the event filter.
    315  */
    316 void UIDnDMIMEData::sltInstallEventFilter(void)
    317 {
    318     LogFlowFunc(("Installing event filter ...\n"));
    319     AssertPtr(qApp);
    320     qApp->installEventFilter(this);
    321 }
    322 #endif
    323 
     252    m_curAction = dropAction;
     253}
     254
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h

    r55821 r56497  
    6363    UIDnDMIMEData(UIDnDHandler *pDnDHandler, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions);
    6464
    65 public:
     65signals:
    6666
    67     int setData(const QString &mimeType);
     67     int getData(const QString &strMIMEType, QVariant::Type vaType) const;
    6868
    6969public slots:
     
    7878    virtual bool hasFormat(const QString &mimeType) const;
    7979
    80     virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
     80    virtual QVariant retrieveData(const QString &strMIMEType, QVariant::Type vaType) const;
    8181
    8282#ifndef RT_OS_WINDOWS
     
    8585    /** @}  */
    8686
    87     int retrieveDataInternal(const QString &strMIMEType, QVariant::Type vaType);
    88 
    89 protected slots:
    90 
    91 #ifndef RT_OS_WINDOWS
    92     void sltInstallEventFilter(void);
    93 #endif
    94 
    9587protected:
    9688
     
    9890
    9991    QStringList       m_lstFormats;
     92    /** Default action on successful drop operation. */
    10093    Qt::DropAction    m_defAction;
     94    /** Current action, based on QDrag's status. */
     95    Qt::DropAction    m_curAction;
    10196    Qt::DropActions   m_actions;
    10297
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r56217 r56497  
    545545    , m_fAccelerate2DVideo(bAccelerate2DVideo)
    546546#endif /* VBOX_WITH_VIDEOHWACCEL */
     547#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     548    , m_fIsDraggingFromGuest(false)
     549#endif
    547550{
    548551    /* Load machine view settings: */
     
    14201423
    14211424#ifdef VBOX_WITH_DRAG_AND_DROP
     1425bool UIMachineView::dragAndDropCanAccept(void) const
     1426{
     1427    bool fAccept =  m_pDnDHandler
     1428#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     1429                 && !m_fIsDraggingFromGuest
     1430#endif
     1431                 && machine().GetDnDMode() != KDnDMode_Disabled;
     1432    LogRelFunc(("fAccept=%RTbool\n", fAccept));
     1433    return fAccept;
     1434}
     1435
    14221436bool UIMachineView::dragAndDropIsActive(void) const
    14231437{
     
    14301444    AssertPtrReturnVoid(pEvent);
    14311445
    1432     if (!dragAndDropIsActive())
     1446    if (!dragAndDropCanAccept())
    14331447        return;
    14341448
     
    14531467    AssertPtrReturnVoid(pEvent);
    14541468
    1455     if (!dragAndDropIsActive())
     1469    if (!dragAndDropCanAccept())
    14561470        return;
    14571471
     
    14761490    AssertPtrReturnVoid(pEvent);
    14771491
     1492    if (!dragAndDropCanAccept())
     1493        return;
     1494
     1495    m_pDnDHandler->dragLeave(screenId());
     1496
     1497    pEvent->accept();
     1498}
     1499
     1500int UIMachineView::dragCheckPending(void)
     1501{
     1502    int rc;
     1503
    14781504    if (!dragAndDropIsActive())
    1479         return;
    1480 
    1481     m_pDnDHandler->dragLeave(screenId());
    1482 
    1483     pEvent->accept();
    1484 }
    1485 
    1486 void UIMachineView::dragIsPending(void)
    1487 {
     1505        rc = VERR_ACCESS_DENIED;
     1506    else if (!m_fIsDraggingFromGuest)
     1507    {
     1508        /** @todo Add guest->guest DnD functionality here by getting
     1509         *        the source of guest B (when copying from B to A). */
     1510        rc = m_pDnDHandler->dragCheckPending(screenId());
     1511        if (RT_SUCCESS(rc))
     1512            m_fIsDraggingFromGuest = true;
     1513    }
     1514    else /* Already dragging, so report success. */
     1515        rc = VINF_SUCCESS;
     1516
     1517    LogRel3(("DnD: dragCheckPending ended with rc=%Rrc\n", rc));
     1518    return rc;
     1519}
     1520
     1521int UIMachineView::dragStart(void)
     1522{
     1523    int rc;
     1524
    14881525    if (!dragAndDropIsActive())
    1489         return;
    1490 
    1491     /** @todo Add guest->guest DnD functionality here by getting
    1492      *        the source of guest B (when copying from B to A). */
    1493     m_pDnDHandler->dragIsPending(screenId());
     1526        rc = VERR_ACCESS_DENIED;
     1527    else if (!m_fIsDraggingFromGuest)
     1528        rc = VERR_WRONG_ORDER;
     1529    else
     1530    {
     1531        /** @todo Add guest->guest DnD functionality here by getting
     1532         *        the source of guest B (when copying from B to A). */
     1533        rc = m_pDnDHandler->dragStart(screenId());
     1534
     1535        m_fIsDraggingFromGuest = false;
     1536    }
     1537
     1538    LogRel3(("DnD: dragStart ended with rc=%Rrc\n", rc));
     1539    return rc;
     1540}
     1541
     1542int UIMachineView::dragStop(void)
     1543{
     1544    int rc;
     1545
     1546    if (!dragAndDropIsActive())
     1547        rc = VERR_ACCESS_DENIED;
     1548    else if (!m_fIsDraggingFromGuest)
     1549        rc = VERR_WRONG_ORDER;
     1550    else
     1551        rc = m_pDnDHandler->dragStop(screenId());
     1552
     1553    LogRel3(("DnD: dragStop ended with rc=%Rrc\n", rc));
     1554    return rc;
    14941555}
    14951556
     
    14981559    AssertPtrReturnVoid(pEvent);
    14991560
    1500     if (!dragAndDropIsActive())
     1561    if (!dragAndDropCanAccept())
    15011562        return;
    15021563
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r56443 r56497  
    263263#ifdef VBOX_WITH_DRAG_AND_DROP
    264264    /**
     265     * Returns @true if the VM window can accept (start is, start) a drag and drop
     266     * operation, @false if not.
     267     */
     268    bool dragAndDropCanAccept(void) const;
     269
     270    /**
    265271     * Returns @true if drag and drop for this machine is active
    266272     * (that is, host->guest, guest->host or bidirectional), @false if not.
     
    298304     *                and (optionally) starts a drag and drop operation on the host.
    299305     */
    300     void dragIsPending(void);
     306    int dragCheckPending(void);
     307
     308    /**
     309     * Guest -> Host: Starts a drag and drop operation from guest to the host. This
     310     *                internally either uses Qt's abstract QDrag methods or some other
     311     *                OS-dependent implementation.
     312     */
     313    int dragStart(void);
     314
     315    /**
     316     * Guest -> Host: Aborts (and resets) the current (pending) guest to host
     317     *                drag and drop operation.
     318     */
     319    int dragStop(void);
    301320
    302321    /**
     
    358377    /** Pointer to drag and drop handler instance. */
    359378    UIDnDHandler *m_pDnDHandler;
     379# ifdef VBOX_WITH_DRAG_AND_DROP_GH
     380    /** Flag indicating whether a guest->host drag currently is in
     381     *  progress or not. */
     382    bool m_fIsDraggingFromGuest;
     383# endif
    360384#endif
    361385
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp

    r55724 r56497  
    957957#ifdef VBOX_WITH_DRAG_AND_DROP
    958958# ifdef VBOX_WITH_DRAG_AND_DROP_GH
     959            QPointer<UIMachineView> pView = m_views[uScreenId];
     960            bool fHandleDnDPending = RT_BOOL(mouseButtons.testFlag(Qt::LeftButton));
     961
     962            /* Mouse pointer outside VM window? */
    959963            if (   cpnt.x() < 0
    960964                || cpnt.x() > iCw - 1
     
    962966                || cpnt.y() > iCh - 1)
    963967            {
    964                 bool fHandleDnDPending
    965                     = RT_BOOL(mouseButtons.testFlag(Qt::LeftButton));
    966968                if (fHandleDnDPending)
    967969                {
    968                     m_views[uScreenId]->dragIsPending();
    969                     return true;
    970                 }
     970                    LogRel2(("DnD: Drag and drop operation from guest to host started\n"));
     971
     972                    int rc = pView->dragCheckPending();
     973                    if (RT_SUCCESS(rc))
     974                    {
     975                        pView->dragStart();
     976                        return true; /* Bail out -- we're done here. */
     977                    }
     978                }
     979            }
     980            else /* Inside VM window? */
     981            {
     982                if (fHandleDnDPending)
     983                    pView->dragStop();
    971984            }
    972985# endif
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