VirtualBox

Changeset 97784 in vbox


Ignore:
Timestamp:
Dec 12, 2022 5:54:12 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
154855
Message:

DnD/Main + FE/Qt: Moved the drag'n drop state to where it belongs, namely into the API objects representing it (and not outside within FE/Qt).

Location:
trunk/src/VBox
Files:
6 edited

Legend:

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

    r97718 r97784  
    8383    : m_pSession(pSession)
    8484    , m_pParent(pParent)
    85     , m_enmOpMode(DNDMODE_UNKNOWN)
    86     , m_fIsPending(false)
    8785    , m_fDataRetrieved(false)
    8886#ifndef RT_OS_WINDOWS
     
    107105                                       const QMimeData *pMimeData)
    108106{
    109     LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
    110                  m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
    111 
    112     if (   m_enmOpMode != DNDMODE_UNKNOWN
    113         && m_enmOpMode != DNDMODE_HOSTTOGUEST)
    114         return Qt::IgnoreAction;
     107    LogFlowFunc(("screenID=%RU32, x=%d, y=%d, action=%ld\n", screenID, x, y, toVBoxDnDAction(proposedAction)));
    115108
    116109    /* Ask the guest for starting a DnD event. */
     
    123116    if (m_dndTarget.isOk())
    124117    {
    125         setOpMode(DNDMODE_HOSTTOGUEST);
    126118        return toQtDnDAction(result);
    127119    }
     
    134126                                      const QMimeData *pMimeData)
    135127{
    136     LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
    137                  m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
    138 
    139     if (m_enmOpMode != DNDMODE_HOSTTOGUEST)
     128    LogFlowFunc(("screenID=%RU32, x=%d, y=%d, action=%ld\n", screenID, x, y, toVBoxDnDAction(proposedAction)));
     129
     130    if (!m_dndTarget.isOk()) /* Don't try any further if we got an error before. */
    140131        return Qt::IgnoreAction;
    141132
     
    158149                                      const QMimeData *pMimeData)
    159150{
    160     LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n",
    161                  m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction)));
    162 
    163     if (m_enmOpMode != DNDMODE_HOSTTOGUEST)
     151    LogFlowFunc(("screenID=%RU32, x=%d, y=%d, action=%ld\n", screenID, x, y, toVBoxDnDAction(proposedAction)));
     152
     153    if (!m_dndTarget.isOk()) /* Don't try any further if we got an error before. */
    164154        return Qt::IgnoreAction;
    165155
     
    265255    }
    266256
    267     /*
    268      * Since the mouse button has been release this in any case marks
    269      * the end of the current transfer direction. So reset the current
    270      * mode as well here.
    271      */
    272     setOpMode(DNDMODE_UNKNOWN);
    273 
    274257    return toQtDnDAction(enmResult);
    275258}
     
    277260void UIDnDHandler::dragLeave(ulong screenID)
    278261{
    279     LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32\n", m_enmOpMode, screenID));
    280 
    281     if (m_enmOpMode == DNDMODE_HOSTTOGUEST)
    282     {
    283         m_dndTarget.Leave(screenID);
    284         setOpMode(DNDMODE_UNKNOWN);
    285     }
     262    LogFlowFunc(("screenID=%RU32\n", screenID));
     263
     264    if (!m_dndTarget.isOk()) /* Don't try any further if we got an error before. */
     265        return;
     266
     267    m_dndTarget.Leave(screenID);
     268    return;
    286269}
    287270
     
    323306{
    324307    RT_NOREF(defAction);
     308
    325309    int rc = VINF_SUCCESS;
    326310
     
    454438}
    455439
     440/**
     441 * Checks whether a G->H drag'n drop operation is pending.
     442 *
     443 * @returns VBox status code.
     444 * @retval  VERR_NO_DATA if no operation is pending or an error has occurred.
     445 * @retval  VERR_NOT_SUPPORTED if G->H operations are not supported.
     446 * @param   screenID            Screen ID to check pending status.
     447 */
    456448int UIDnDHandler::dragCheckPending(ulong screenID)
    457449{
    458450    int rc;
    459451#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    460 
    461     LogFlowFunc(("enmOpMode=%RU32, fIsPending=%RTbool, screenID=%RU32\n", m_enmOpMode, m_fIsPending, screenID));
    462 
    463     {
    464         QMutexLocker AutoReadLock(&m_ReadLock);
    465 
    466         if (   m_enmOpMode != DNDMODE_UNKNOWN
    467             && m_enmOpMode != DNDMODE_GUESTTOHOST) /* Wrong mode set? */
    468             return VINF_SUCCESS;
    469 
    470         if (m_fIsPending) /* Pending operation is in progress. */
    471             return VINF_SUCCESS;
    472     }
    473 
    474     QMutexLocker AutoWriteLock(&m_WriteLock);
    475     m_fIsPending = true;
    476     AutoWriteLock.unlock();
     452    LogFlowFunc(("screenID=%RU32\n", screenID));
    477453
    478454    /**
     
    496472    QVector<QString> vecFormats;
    497473    m_dataSource.defaultAction = m_dndSource.DragIsPending(screenID, vecFormats, m_dataSource.vecActions);
     474    if (!m_dndSource.isOk())
     475        return VERR_NO_DATA;
    498476
    499477    LogRelMax3(10, ("DnD: Default action is: 0x%x\n", m_dataSource.defaultAction));
     
    526504        rc = VERR_NO_DATA;
    527505
    528     AutoWriteLock.relock();
    529     m_fIsPending = false;
    530     AutoWriteLock.unlock();
    531 
    532506#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
    533 
    534     NOREF(screenID);
    535 
     507    RT_NOREF(screenID);
    536508    rc = VERR_NOT_SUPPORTED;
    537 
    538509#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    539510
     
    547518#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    548519
    549     NOREF(screenID);
     520    RT_NOREF(screenID);
    550521
    551522    LogFlowFuncEnter();
     
    559530    }
    560531
    561     setOpMode(DNDMODE_GUESTTOHOST);
    562 
    563532    rc = dragStartInternal(m_dataSource.lstFormats,
    564533                           toQtDnDAction(m_dataSource.defaultAction), toQtDnDActions(m_dataSource.vecActions));
    565534
    566535#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
    567 
    568     NOREF(screenID);
    569 
     536    RT_NOREF(screenID);
    570537    rc = VERR_NOT_SUPPORTED;
    571 
    572538#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    573539
     
    578544int UIDnDHandler::dragStop(ulong screenID)
    579545{
     546    RT_NOREF(screenID);
    580547    int rc;
    581548#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    582 
    583     NOREF(screenID);
    584 
    585549    reset();
    586550    rc = VINF_SUCCESS;
    587 
    588551#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
    589 
    590     NOREF(screenID);
    591 
    592552    rc = VERR_NOT_SUPPORTED;
    593 
    594553#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    595 
    596554    LogFlowFuncLeaveRC(rc);
    597555    return rc;
     
    603561
    604562    m_fDataRetrieved = false;
    605     m_fIsPending = false;
    606 
    607     setOpMode(DNDMODE_UNKNOWN);
    608563}
    609564
     
    720675    }
    721676
    722     setOpMode(DNDMODE_UNKNOWN);
    723 
    724677    LogFlowFuncLeaveRC(rc);
    725678    return rc;
    726 }
    727 
    728 /**
    729  * Sets the current DnD operation mode.
    730  *
    731  * Note: Only one mode (guest->host *or* host->guest) can be active at the same time.
    732  *
    733  * @param   enmMode             Current operation mode to set.
    734  */
    735 void UIDnDHandler::setOpMode(DNDOPMODE enmMode)
    736 {
    737     QMutexLocker AutoWriteLock(&m_WriteLock);
    738 
    739     /** @todo r=andy Check for old (current) mode and refuse new mode? */
    740 
    741     m_enmOpMode = enmMode;
    742     LogFunc(("Operation mode is now: %RU32\n", m_enmOpMode));
    743679}
    744680
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h

    r96407 r97784  
    5959    UIDnDHandler(UISession *pSession, QWidget *pParent);
    6060    virtual ~UIDnDHandler(void);
    61 
    62     /**
    63      * Current operation mode.
    64      * Note: The operation mode is independent of the machine's overall
    65      *       drag and drop mode.
    66      */
    67     typedef enum DNDOPMODE
    68     {
    69         /** Unknown mode. */
    70         DNDMODE_UNKNOWN     = 0,
    71         /** Host to guest. */
    72         DNDMODE_HOSTTOGUEST = 1,
    73         /** Guest to host. */
    74         DNDMODE_GUESTTOHOST = 2,
    75         /** @todo Implement guest to guest. */
    76         /** The usual 32-bit type blow up. */
    77         DNDMODE_32BIT_HACK = 0x7fffffff
    78     } DNDOPMODE;
    7961
    8062    /**
     
    141123    int                        dragStartInternal(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions);
    142124    int                        retrieveDataInternal(Qt::DropAction dropAction, const QString &strMIMEType, QVector<uint8_t> &vecData);
    143     void                       setOpMode(DNDOPMODE enmMode);
    144125
    145126protected:
     
    153134    /** Drag and drop target instance. */
    154135    CDnDTarget        m_dndTarget;
    155     /** Current operation mode, indicating the transfer direction.
    156      *  Note: This is independent of the current drag and drop
    157      *        mode being set for this VM! */
    158     DNDOPMODE         m_enmOpMode;
    159136    /** Current data from the source (if any).
    160137     *  At the momenet we only support one source at a time. */
    161138    UIDnDDataSource   m_dataSource;
    162     /** Flag indicating if a drag operation is pending currently. */
    163     bool              m_fIsPending;
    164139    /** Flag indicating whether data has been retrieved from
    165140     *  the guest already or not. */
  • trunk/src/VBox/Main/include/GuestDnDPrivate.h

    r97783 r97784  
    821821public:
    822822
     823    VBOXDNDSTATE get() { return m_enmState; } const
     824    int set(VBOXDNDSTATE enmState) { LogRel3(("DnD: State %s -> %s\n", DnDStateToStr(m_enmState), DnDStateToStr(enmState))); m_enmState = enmState; return 0; }
     825    void lock() { RTCritSectEnter(&m_CritSect); };
     826    void unlock() { RTCritSectLeave(&m_CritSect); };
     827
    823828    /** @name Guest response handling.
    824829     * @{ */
     
    856861    /** Pointer to context this class is tied to. */
    857862    void                 *m_pvCtx;
     863    RTCRITSECT            m_CritSect;
     864    /** The current state we're in. */
     865    VBOXDNDSTATE          m_enmState;
    858866    /** The DnD protocol version to use, depending on the
    859867     *  installed Guest Additions. See DragAndDropSvc.h for
  • trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp

    r97783 r97784  
    301301
    302302GuestDnDState::GuestDnDState(const ComObjPtr<Guest>& pGuest)
    303     : m_uProtocolVersion(0)
     303    : m_enmState(VBOXDNDSTATE_UNKNOWN)
     304    , m_uProtocolVersion(0)
    304305    , m_fGuestFeatures0(VBOX_DND_GF_NONE)
    305306    , m_EventSem(NIL_RTSEMEVENT)
     
    309310    , m_pParent(pGuest)
    310311{
    311     int rc = RTSemEventCreate(&m_EventSem);
     312    int rc = RTCritSectInit(&m_CritSect);
    312313    if (RT_FAILURE(rc))
    313314        throw rc;
     315    rc = RTSemEventCreate(&m_EventSem);
     316    if (RT_FAILURE(rc))
     317        throw rc;
    314318}
    315319
     
    320324    int rc = RTSemEventDestroy(m_EventSem);
    321325    AssertRC(rc);
     326    rc = RTCritSectDelete(&m_CritSect);
     327    AssertRC(rc);
    322328}
    323329
     
    336342
    337343/**
    338  * Resets a GuestDnDResponse object.
     344 * Resets a guest drag'n drop state.
    339345 */
    340346void GuestDnDState::reset(void)
    341347{
    342     LogFlowThisFuncEnter();
    343 
    344     m_dndActionDefault     = 0;
    345     m_dndLstActionsAllowed = 0;
     348    LogRel2(("DnD: Reset\n"));
     349
     350    m_enmState =  VBOXDNDSTATE_UNKNOWN;
     351
     352    m_dndActionDefault     = VBOX_DND_ACTION_IGNORE;
     353    m_dndLstActionsAllowed = VBOX_DND_ACTION_IGNORE;
    346354
    347355    m_lstFormats.clear();
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r97783 r97784  
    286286
    287287    GuestDnDState *pState = GuestDnDInst()->getState();
    288     AssertPtrReturn(pState, E_POINTER);
     288    AssertPtr(pState);
     289
     290    /* Check if any operation is active, and if so, bail out, returning an ignore action (see above). */
     291    if (pState->get() != VBOXDNDSTATE_UNKNOWN)
     292        return S_OK;
     293
     294    pState->set(VBOXDNDSTATE_QUERY_FORMATS);
    289295
    290296    HRESULT hrc = S_OK;
     
    339345    else
    340346        hrc = i_setErrorAndReset(vrc, tr("Sending drag pending event to guest failed"));
     347
     348    pState->set(VBOXDNDSTATE_UNKNOWN);
    341349
    342350    LogFlowFunc(("hr=%Rhrc\n", hrc));
  • trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp

    r97783 r97784  
    350350                LogRel2(("DnD: Host enters the VM window at %RU32,%RU32 (screen %u, default action is '%s') -> guest reported back action '%s'\n",
    351351                         aX, aY, aScreenId, DnDActionToStr(dndActionDefault), DnDActionToStr(resAction)));
     352
     353                pState->set(VBOXDNDSTATE_ENTERED);
    352354            }
    353355            else
     
    455457                LogRel2(("DnD: Host moved to %RU32,%RU32 in VM window (screen %u, default action is '%s') -> guest reported back action '%s'\n",
    456458                         aX, aY, aScreenId, DnDActionToStr(dndActionDefault), DnDActionToStr(resAction)));
     459
     460                pState->set(VBOXDNDSTATE_DRAGGING);
    457461            }
    458462            else
     
    510514    AssertPtrReturn(pState, E_POINTER);
    511515
     516    if (pState->get() == VBOXDNDSTATE_DROP_STARTED)
     517        return S_OK;
     518
    512519    HRESULT hrc = S_OK;
    513520
     
    525532        if (RT_SUCCESS(vrc = pState->waitForGuestResponse(&vrcGuest)))
    526533        {
    527             /* Nothing to do here. */
     534            pState->set(VBOXDNDSTATE_LEFT);
    528535        }
    529536        else
     
    644651                    {
    645652                        resFmt = lstFormats.at(0);
     653
     654                        LogRel2(("DnD: Guest accepted drop in format '%s' (action %#x, %zu format(s))\n",
     655                                 resFmt.c_str(), resAct, lstFormats.size()));
     656
     657                        pState->set(VBOXDNDSTATE_DROP_STARTED);
    646658                    }
    647659                    else
     
    916928    }
    917929
    918     if (RT_FAILURE(vrc))
    919     {
    920         LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc));
     930    GuestDnDState *pState = GuestDnDInst()->getState();
     931    AssertPtrReturn(pState, E_POINTER);
     932
     933    if (RT_SUCCESS(vrc))
     934    {
     935        pState->set(VBOXDNDSTATE_DROP_ENDED);
     936    }
     937    else
     938    {
     939        if (vrc == VERR_CANCELLED)
     940        {
     941            LogRel(("DnD: Sending data to guest cancelled by the user\n"));
     942            pState->set(VBOXDNDSTATE_CANCELLED);
     943        }
     944        else
     945        {
     946            LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc));
     947            pState->set(VBOXDNDSTATE_ERROR);
     948        }
     949
     950        /* Make sure to fire a cancel request to the guest side in any case to prevent any guest side hangs. */
    921951        sendCancel();
    922952    }
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