VirtualBox

Changeset 50265 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Jan 29, 2014 11:12:44 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
91898
Message:

DnD: First working implementation for Windows guest->host support; still work in progress. As for now only pure text data can be dragged over.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp

    r49891 r50265  
    55
    66/*
    7  * Copyright (C) 2011-2013 Oracle Corporation
     7 * Copyright (C) 2011-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    167167class DnDGuestResponse
    168168{
     169
    169170public:
     171
    170172    DnDGuestResponse(const ComObjPtr<Guest>& pGuest);
    171     ~DnDGuestResponse();
    172 
    173     int notifyAboutGuestResponse();
    174     int waitForGuestResponse();
     173
     174    virtual ~DnDGuestResponse(void);
     175
     176public:
     177
     178    int notifyAboutGuestResponse(void);
     179    int waitForGuestResponse(RTMSINTERVAL msTimeout = 500);
    175180
    176181    void setDefAction(uint32_t a) { m_defAction = a; }
    177     uint32_t defAction() const { return m_defAction; }
     182    uint32_t defAction(void) const { return m_defAction; }
    178183
    179184    void setAllActions(uint32_t a) { m_allActions = a; }
     
    181186
    182187    void setFormat(const Utf8Str &strFormat) { m_strFormat = strFormat; }
    183     Utf8Str format() const { return m_strFormat; }
    184 
    185     int addData(void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
    186     void resetData();
    187     void data(void **ppvData, uint32_t *pcbData) const { *ppvData = m_pvData; *pcbData = m_cbData; }
    188     bool hasData() const { return m_pvData != NULL; }
     188    Utf8Str format(void) const { return m_strFormat; }
     189
     190    int dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
     191    void reset(void);
     192    const void *data(void) { return m_pvData; }
     193    size_t size(void) const { return m_cbData; }
    189194
    190195    int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS);
     
    213218        , m_pDnDResponse(new DnDGuestResponse(pGuest))
    214219    {}
    215     ~GuestDnDPrivate() { delete m_pDnDResponse; }
    216 
    217     DnDGuestResponse *response() const { return m_pDnDResponse; }
     220    virtual ~GuestDnDPrivate(void) { delete m_pDnDResponse; }
     221
     222    DnDGuestResponse *response(void) const { return m_pDnDResponse; }
    218223
    219224    void adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
     
    274279DnDGuestResponse::~DnDGuestResponse()
    275280{
    276     resetData();
     281    reset();
    277282    int rc = RTSemEventDestroy(m_EventSem);
    278283    AssertRC(rc);
     
    284289}
    285290
    286 int DnDGuestResponse::waitForGuestResponse()
    287 {
    288     int vrc = RTSemEventWait(m_EventSem, 300);
     291int DnDGuestResponse::waitForGuestResponse(RTMSINTERVAL msTimeout /*= 500 */)
     292{
     293    int vrc = RTSemEventWait(m_EventSem, msTimeout);
    289294#ifdef DEBUG_andy
    290     LogFlowFunc(("rc=%Rrc\n", vrc));
     295    LogFlowFunc(("msTimeout=%RU32, rc=%Rrc\n", msTimeout, vrc));
    291296#endif
    292297    return vrc;
    293298}
    294299
    295 int DnDGuestResponse::addData(void *pvData, uint32_t cbData, uint32_t *pcbCurSize)
     300int DnDGuestResponse::dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize)
    296301{
    297302    int rc = VINF_SUCCESS;
     303
     304    /** @todo Make reallocation scheme a bit smarter here. */
    298305    m_pvData = RTMemRealloc(m_pvData, m_cbData + cbData);
    299306    if (m_pvData)
    300307    {
    301         memcpy(&static_cast<uint8_t*>(m_pvData)[m_cbData], pvData, cbData);
    302         m_cbData    += cbData;
    303         *pcbCurSize  = m_cbData;
     308        memcpy(&static_cast<uint8_t*>(m_pvData)[m_cbData],
     309               pvData, cbData);
     310        m_cbData += cbData;
     311
     312        if (pcbCurSize)
     313            *pcbCurSize = m_cbData;
    304314    }
    305315    else
     
    309319}
    310320
    311 void DnDGuestResponse::resetData()
     321void DnDGuestResponse::reset(void)
    312322{
    313323    if (m_pvData)
     
    316326        m_pvData = NULL;
    317327    }
     328
    318329    m_cbData = 0;
    319330}
     
    747758}
    748759
    749 HRESULT GuestDnD::dragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
     760HRESULT GuestDnD::dragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat,
     761                                ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
    750762{
    751763    DPTR(GuestDnD);
     
    786798}
    787799
    788 # ifdef VBOX_WITH_DRAG_AND_DROP_GH
    789 HRESULT GuestDnD::dragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction)
     800#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     801HRESULT GuestDnD::dragGHPending(ULONG uScreenId,
     802                                ComSafeArrayOut(BSTR, formats),
     803                                ComSafeArrayOut(DragAndDropAction_T, allowedActions),
     804                                DragAndDropAction_T *pDefaultAction)
    790805{
    791806    DPTR(GuestDnD);
     
    821836        /* Convert the action bit field to a vector of actions. */
    822837        d->toMainActions(pDnD->allActions(), ComSafeArrayOutArg(allowedActions));
     838
     839        LogFlowFunc(("*pDefaultAction=0x%x\n", *pDefaultAction));
    823840    }
    824841    catch (HRESULT rc2)
     
    830847}
    831848
    832 HRESULT GuestDnD::dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress)
     849HRESULT GuestDnD::dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action,
     850                                IProgress **ppProgress)
    833851{
    834852    DPTR(GuestDnD);
     
    845863    try
    846864    {
     865        LogFlowFunc(("strFormat=%s, uAction=0x%x\n", strFormat.c_str(), uAction));
     866
    847867        VBOXHGCMSVCPARM paParms[3];
    848868        int i = 0;
     
    853873        DnDGuestResponse *pDnD = d->response();
    854874        /* Reset any old data and the progress status. */
    855         pDnD->resetData();
     875        pDnD->reset();
    856876        pDnD->resetProgress(p);
    857877
     
    879899
    880900    DnDGuestResponse *pDnD = d->response();
    881     /* Is there data at all? */
    882     if (pDnD->hasData())
    883     {
    884         /* Copy the data into an safe array of bytes. */
    885         void     *pvData = 0;
    886         uint32_t  cbData = 0;
    887         pDnD->data(&pvData, &cbData);
    888         com::SafeArray<BYTE> sfaData(cbData);
    889         memcpy(sfaData.raw(), pvData, cbData);
     901    if (pDnD)
     902    {
     903        com::SafeArray<BYTE> sfaData;
     904
     905        uint32_t cbData = pDnD->size();
     906        if (cbData)
     907        {
     908            /* Copy the data into an safe array of bytes. */
     909            const void *pvData = pDnD->data();
     910            if (sfaData.resize(cbData))
     911                memcpy(sfaData.raw(), pvData, cbData);
     912            else
     913                rc = E_OUTOFMEMORY;
     914        }
     915
     916#ifdef DEBUG_andy
     917        LogFlowFunc(("Received %RU32 bytes\n", cbData));
     918#endif
     919        /* Detach in any case, regardless of data size. */
    890920        sfaData.detachTo(ComSafeArrayOutArg(data));
     921
    891922        /* Delete the data. */
    892         pDnD->resetData();
     923        pDnD->reset();
    893924    }
    894925    else
     
    897928    return rc;
    898929}
    899 
    900 # endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     930#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    901931
    902932DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms)
     
    929959            break;
    930960        }
     961
    931962        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
    932963        {
     
    939970            break;
    940971        }
     972
    941973        case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:
    942974        {
     
    948980            break;
    949981        }
     982
    950983#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    951984        case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
     
    961994            break;
    962995        }
     996
    963997        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
    964998        {
     
    9671001            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);
    9681002            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1003
    9691004            uint32_t cbCurSize = 0;
    970             pResp->addData(pCBData->pvData, pCBData->cbData, &cbCurSize);
    971             rc = pResp->setProgress(100.0 / pCBData->cbAllSize * cbCurSize, (pCBData->cbAllSize == cbCurSize ? DragAndDropSvc::DND_PROGRESS_COMPLETE : DragAndDropSvc::DND_PROGRESS_RUNNING));
     1005            rc = pResp->dataAdd(pCBData->pvData, pCBData->cbData, &cbCurSize);
     1006            if (RT_SUCCESS(rc))
     1007            {
     1008                uint32_t cbTotalSize = pCBData->cbAllSize;
     1009                unsigned int cPercentage;
     1010                if (!cbTotalSize) /* Watch out for division by zero. */
     1011                    cPercentage = 100;
     1012                else
     1013                    cPercentage = cbCurSize * 100.0 / cbTotalSize;
     1014
     1015                /** @todo Don't use anonymous enums. */
     1016                uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING;
     1017                if (   pCBData->cbAllSize == cbCurSize
     1018                    /* Empty data? Should not happen, but anyway ... */
     1019                    || !pCBData->cbAllSize)
     1020                {
     1021                    uState = DragAndDropSvc::DND_PROGRESS_COMPLETE;
     1022                }
     1023
     1024                rc = pResp->setProgress(cPercentage, uState);
     1025            }
    9721026            /* Todo: for now we instantly confirm the cancel. Check if the
    9731027             * guest should first clean up stuff itself and than really confirm
     
    9771031            break;
    9781032        }
     1033
    9791034        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
    9801035        {
     
    9831038            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
    9841039            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1040
    9851041            /* Cleanup */
    986             pResp->resetData();
     1042            pResp->reset();
    9871043            rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
    9881044            break;
     
    9901046#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    9911047        default:
    992             AssertMsgFailedReturn(("Function %RU32 not supported\n", u32Function), VERR_NOT_SUPPORTED);
     1048            rc = VERR_NOT_SUPPORTED; /* Tell the guest. */
    9931049            break;
    9941050    }
Note: See TracChangeset for help on using the changeset viewer.

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