VirtualBox

Ignore:
Timestamp:
May 18, 2015 5:49:27 PM (10 years ago)
Author:
vboxsync
Message:

Documentation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp

    r55846 r55918  
    11/* $Id$ */
    22/** @file
    3  * X11 guest client - Drag and Drop.
     3 * X11 guest client - Drag and drop implementation.
    44 */
    55
     
    5050#endif
    5151
    52 /* For X11 guest xDnD is used. See http://www.acc.umu.se/~vatten/XDND.html for
     52/**
     53 * For X11 guest xDnD is used. See http://www.acc.umu.se/~vatten/XDND.html for
    5354 * a walk trough.
    5455 *
    55  * H->G:
    56  * For X11 this means mainly forwarding all the events from HGCM to the
    57  * appropriate X11 events. There exists a proxy window, which is invisible and
    58  * used for all the X11 communication. On a HGCM Enter event, we set our proxy
    59  * window as XdndSelection owner with the given mime-types. On every HGCM move
    60  * event, we move the X11 mouse cursor to the new position and query for the
    61  * window below that position. Depending on if it is XdndAware, a new window or
    62  * a known window, we send the appropriate X11 messages to it. On HGCM drop, we
    63  * send a XdndDrop message to the current window and wait for a X11
    64  * SelectionMessage from the target window. Because we didn't have the data in
    65  * the requested mime-type, yet, we save that message and ask the host for the
    66  * data. When the data is successfully received from the host, we put the data
    67  * as a property to the window and send a X11 SelectionNotify event to the
    68  * target window.
    69  *
    70  * G->H:
    71  * This is a lot more trickery than H->G. When a pending event from HGCM
    72  * arrives, we ask if there currently is an owner of the XdndSelection
    73  * property. If so, our proxy window is shown (1x1, but without backing store)
    74  * and some mouse event is triggered. This should be followed by an XdndEnter
    75  * event send to the proxy window. From this event we can fetch the necessary
    76  * info of the MIME types and allowed actions and send this back to the host.
    77  * On a drop request from the host, we query for the selection and should get
    78  * the data in the specified mime-type. This data is send back to the host.
    79  * After that we send a XdndLeave event to the source window.
    80  *
    81  * To-do:
    82  * - Cancelling (e.g. with ESC key) doesn't work.
    83  *
    84  * To-do:
    85  * - INCR (incremental transfers) support.
    86  * - Make this much more robust for crashes of the other party.
    87  * - Really check for the Xdnd version and the supported features.
     56 * Host -> Guest:
     57 *     For X11 this means mainly forwarding all the events from HGCM to the
     58 *     appropriate X11 events. There exists a proxy window, which is invisible and
     59 *     used for all the X11 communication. On a HGCM Enter event, we set our proxy
     60 *     window as XdndSelection owner with the given mime-types. On every HGCM move
     61 *     event, we move the X11 mouse cursor to the new position and query for the
     62 *     window below that position. Depending on if it is XdndAware, a new window or
     63 *     a known window, we send the appropriate X11 messages to it. On HGCM drop, we
     64 *     send a XdndDrop message to the current window and wait for a X11
     65 *     SelectionMessage from the target window. Because we didn't have the data in
     66 *     the requested mime-type, yet, we save that message and ask the host for the
     67 *     data. When the data is successfully received from the host, we put the data
     68 *     as a property to the window and send a X11 SelectionNotify event to the
     69 *     target window.
     70 *
     71 * Guest -> Host:
     72 *     This is a lot more trickery than H->G. When a pending event from HGCM
     73 *     arrives, we ask if there currently is an owner of the XdndSelection
     74 *     property. If so, our proxy window is shown (1x1, but without backing store)
     75 *     and some mouse event is triggered. This should be followed by an XdndEnter
     76 *     event send to the proxy window. From this event we can fetch the necessary
     77 *     info of the MIME types and allowed actions and send this back to the host.
     78 *     On a drop request from the host, we query for the selection and should get
     79 *     the data in the specified mime-type. This data is send back to the host.
     80 *     After that we send a XdndLeave event to the source window.
     81 *
     82 ** @todo Cancelling (e.g. with ESC key) doesn't work.
     83 ** @todo INCR (incremental transfers) support.
     84 ** @todo Really check for the Xdnd version and the supported features.
     85 ** @todo Either get rid of the xHelpers class or properly unify the code with the drag instance class.
    8886 */
    8987
     
    9189#define VBOX_MAX_XPROPERTIES (LONG_MAX-1)
    9290
    93 /* Shared struct used for adding new X11 events and HGCM messages to a single
    94  * event queue. */
     91/**
     92 * Structure for storing new X11 events and HGCM messages
     93 * into a single vent queue.
     94 */
    9595struct DnDEvent
    9696{
     
    147147class DragAndDropService;
    148148
     149/** List of Atoms. */
     150#define VBoxDnDAtomList RTCList<Atom>
     151
    149152/*******************************************************************************
    150153 *
     
    186189    }
    187190
    188     inline RTCString xAtomListToString(const RTCList<Atom> &formatList)
     191    inline RTCString xAtomListToString(const VBoxDnDAtomList &formatList)
    189192    {
    190193        RTCString format;
     
    198201
    199202private:
     203
    200204    xHelpers(Display *pDisplay)
    201205      : m_pDisplay(pDisplay)
     
    225229 ******************************************************************************/
    226230
    227 xHelpers *xHelpers::m_pInstance = 0;
     231xHelpers *xHelpers::m_pInstance = NULL;
     232
    228233/* Has to be in sync with the XA_Type enum. */
    229234const char *xHelpers::m_xAtomNames[] =
     
    337342
    338343#ifdef DEBUG
    339 # define VBOX_DND_FN_DECL_LOG(x) inline x
     344# define VBOX_DND_FN_DECL_LOG(x) inline x /* For LogFlowXXX logging. */
    340345#else
    341346# define VBOX_DND_FN_DECL_LOG(x) x
    342347#endif
    343348
    344 #define VBoxDnDAtomList RTCList<Atom>
    345 
    346 /* For now only one DragInstance will exits when the app is running. In the
    347  * future the support for having more than one drag and drop operation supported at the
    348  * time will be necessary. */
     349/**
     350 * Class for handling a single drag and drop operation, that is,
     351 * one source and one target at a time.
     352 *
     353 * For now only one DragInstance will exits when the app is running.
     354 */
    349355class DragInstance
    350356{
     
    387393    bool waitForX11ClientMsg(XClientMessageEvent &evMsg, Atom aType, RTMSINTERVAL uTimeoutMS = 100);
    388394
    389     /* H->G */
    390     int  hgEnter(const RTCList<RTCString> &formats, uint32_t actions);
    391     int  hgLeave(void);
    392     int  hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t action);
    393     int  hgDrop();
    394     int  hgDataReceived(void *pvData, uint32_t cData);
     395    /* Host -> Guest handling. */
     396    int hgEnter(const RTCList<RTCString> &formats, uint32_t actions);
     397    int hgLeave(void);
     398    int hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t action);
     399    int hgDrop(void);
     400    int hgDataReceived(const void *pvData, uint32_t cData);
    395401
    396402#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    397     /* G->H */
    398     int  ghIsDnDPending();
    399     int  ghDropped(const RTCString &strFormat, uint32_t action);
     403    /* Guest -> Host handling. */
     404    int ghIsDnDPending(void);
     405    int ghDropped(const RTCString &strFormat, uint32_t action);
    400406#endif
    401407
     
    407413
    408414    void wndXDnDClearActionList(Window wndThis) const;
    409     void wndXDnDClearTypeList(Window wndThis) const;
     415    void wndXDnDClearFormatList(Window wndThis) const;
    410416    int wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const;
    411     int wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const;
     417    int wndXDnDGetFormatList(Window wndThis, VBoxDnDAtomList &lstTypes) const;
    412418    int wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const;
    413     int wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const;
    414 
    415     int                    toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const;
    416     int                    toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const;
    417     static Atom            toAtomAction(uint32_t uAction);
    418     static int             toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms);
    419     static uint32_t        toHGCMAction(Atom atom);
    420     static uint32_t        toHGCMActions(const RTCList<Atom> &actionsList);
     419    int wndXDnDSetFormatList(Window wndThis, Atom atmProp, const VBoxDnDAtomList &lstFormats) const;
     420
     421    int             toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const;
     422    int             toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const;
     423    static Atom     toAtomAction(uint32_t uAction);
     424    static int      toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms);
     425    static uint32_t toHGCMAction(Atom atom);
     426    static uint32_t toHGCMActions(const VBoxDnDAtomList &actionsList);
    421427
    422428protected:
     
    424430    /** The instance's own DnD context. */
    425431    VBGLR3GUESTDNDCMDCTX        m_dndCtx;
     432    /** Pointer to service instance. */
    426433    DragAndDropService         *m_pParent;
     434    /** Pointer to X display operating on. */
    427435    Display                    *m_pDisplay;
     436    /** X screen ID to operate on. */
    428437    int                         m_screenId;
     438    /** Pointer to X screen operating on. */
    429439    Screen                     *m_pScreen;
     440    /** Root window handle. */
    430441    Window                      m_wndRoot;
     442    /** Proxy window handle. */
    431443    Window                      m_wndProxy;
     444    /** Current source/target window handle. */
    432445    Window                      m_wndCur;
     446    /** The XDnD protocol version the current
     447     *  source/target window is using. */
    433448    long                        m_curVer;
     449    /** List of (Atom) formats the source window supports. */
    434450    VBoxDnDAtomList             m_lstFormats;
     451    /** List of (Atom) actions the source window supports. */
    435452    VBoxDnDAtomList             m_lstActions;
    436453    /** Deferred host to guest selection event for sending to the
     
    475492private:
    476493
    477     int x11DragAndDropInit(void);
     494    int dragAndDropInit(void);
    478495    static int hgcmEventThread(RTTHREAD hThread, void *pvUser);
    479496    static int x11EventThread(RTTHREAD hThread, void *pvUser);
    480 
    481     void clearEventQueue();
    482497
    483498    /* Private member vars */
     
    519534}
    520535
     536/**
     537 * Unitializes (destroys) this drag instance.
     538 */
    521539void DragInstance::uninit(void)
    522540{
     
    534552}
    535553
     554/**
     555 * Resets this drag instance.
     556 */
    536557void DragInstance::reset(void)
    537558{
     
    547568
    548569    /* Clear any other DnD specific data on the proxy window. */
    549     wndXDnDClearTypeList(m_wndProxy);
     570    wndXDnDClearFormatList(m_wndProxy);
    550571    wndXDnDClearActionList(m_wndProxy);
    551572
     
    560581}
    561582
    562 int DragInstance::init(uint32_t u32ScreenId)
     583/**
     584 * Initializes this drag instance.
     585 *
     586 * @return  IPRT status code.
     587 * @param   u32ScreenID             X' screen ID to use.
     588 */
     589int DragInstance::init(uint32_t u32ScreenID)
    563590{
    564591    int rc;
     
    583610         * Enough screens configured in the x11 server?
    584611         */
    585         if ((int)u32ScreenId > ScreenCount(m_pDisplay))
     612        if ((int)u32ScreenID > ScreenCount(m_pDisplay))
    586613        {
    587614            rc = VERR_INVALID_PARAMETER;
     
    597624        }
    598625#endif
    599         m_screenId = u32ScreenId;
     626        m_screenId = u32ScreenID;
    600627
    601628        /* Now query the corresponding root window of this screen. */
     
    620647#ifdef VBOX_DND_DEBUG_WND
    621648        attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenId);
    622         attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenId); 
     649        attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenId);
    623650        m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                     /* Parent */,
    624651                                   100, 100,                                 /* Position */
     
    628655                                   InputOutput,                              /* Class */
    629656                                   CopyFromParent,                           /* Visual */
    630                                      CWBackPixel 
     657                                     CWBackPixel
    631658                                   | CWBorderPixel
    632659                                   | CWOverrideRedirect
    633660                                   | CWDontPropagate,                        /* Value mask */
    634                                    &attr);                                   /* Attributes for value mask */       
     661                                   &attr);                                   /* Attributes for value mask */
    635662#else
    636663        m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                 /* Parent */,
     
    674701    else
    675702        LogRel(("DnD: Initializing drag instance for screen %RU32 failed with rc=%Rrc\n",
    676                 u32ScreenId, rc));
     703                u32ScreenID, rc));
    677704
    678705    LogFlowFuncLeaveRC(rc);
     
    680707}
    681708
     709/**
     710 * Logs an error message to the (release) logging instance.
     711 *
     712 * @param   pszFormat               Format string to log.
     713 */
    682714VBOX_DND_FN_DECL_LOG(void) DragInstance::logError(const char *pszFormat, ...)
    683715{
     
    695727}
    696728
     729/**
     730 * Callback handler for a generic client message from a window.
     731 *
     732 * @return  IPRT status code.
     733 * @param   e                       X11 event to handle.
     734 */
    697735int DragInstance::onX11ClientMessage(const XEvent &e)
    698736{
     
    708746        case HG:
    709747        {
    710             /* 
     748            /*
    711749             * Client messages are used to inform us about the status of a XdndAware
    712              * window, in response of some events we send to them. 
    713              */ 
     750             * window, in response of some events we send to them.
     751             */
    714752            if (   e.xclient.message_type == xAtom(XA_XdndStatus)
    715753                && m_wndCur               == static_cast<Window>(e.xclient.data.l[0]))
    716754            {
    717                 /* 
     755                /*
    718756                 * The XdndStatus message tell us if the window will accept the DnD
    719757                 * event and with which action. We immediately send this info down to
    720                  * the host as a response of a previous DnD message. 
    721                  */ 
     758                 * the host as a response of a previous DnD message.
     759                 */
    722760                LogFlowThisFunc(("XA_XdndStatus: wnd=%#x, accept=%RTbool, action=%s\n",
    723761                                 e.xclient.data.l[0],
     
    761799            break;
    762800        }
    763        
     801
    764802        default:
    765803        {
     
    774812}
    775813
     814/**
     815 * Callback handler for a XDnD selection notify from a window. This is needed
     816 * to let the us know if a certain window has drag'n drop data to share with us,
     817 * e.g. our proxy window.
     818 *
     819 * @return  IPRT status code.
     820 * @param   e                       X11 event to handle.
     821 */
    776822int DragInstance::onX11SelectionNotify(const XEvent &e)
    777823{
     
    807853}
    808854
     855/**
     856 * Callback handler for a XDnD selection request from a window. This is needed
     857 * to retrieve the data required to complete the actual drag'n drop operation.
     858 *
     859 * @returns IPRT status code.
     860 * @param   e                       X11 event to handle.
     861 */
    809862int DragInstance::onX11SelectionRequest(const XEvent &e)
    810863{
     
    846899            if (e.xselectionrequest.target == xAtom(XA_TARGETS))
    847900            {
    848                 LogFlowThisFunc(("wnd=%#x '%s' asking for target list\n", 
     901                LogFlowThisFunc(("wnd=%#x '%s' asking for target list\n",
    849902                                 e.xselectionrequest.requestor, propName.value));
    850903
     
    852905                 * window. */
    853906                rc = wndXDnDSetFormatList(e.xselectionrequest.requestor, e.xselectionrequest.property, m_lstFormats);
    854                 if (RT_SUCCESS(rc)) 
     907                if (RT_SUCCESS(rc))
    855908                {
    856909                    atmTarget   = e.xselectionrequest.target;
     
    864917            {
    865918                LogFlowThisFunc(("wnd=%#x '%s' asking for data, format=%s\n",
    866                                  e.xselectionrequest.requestor, propName.value, 
     919                                 e.xselectionrequest.requestor, propName.value,
    867920                                 xAtomToString(e.xselectionrequest.target).c_str()));
    868921
     
    880933                else
    881934                {
    882                     LogFlowThisFunc(("Saving selection notify message of wnd=%#x '%s'\n", 
     935                    LogFlowThisFunc(("Saving selection notify message of wnd=%#x '%s'\n",
    883936                                     e.xselectionrequest.requestor, propName.value));
    884937
     
    941994}
    942995
     996/**
     997 * Handles X11 events, called by x11EventThread.
     998 *
     999 * @returns IPRT status code.
     1000 * @param   e                       X11 event to handle.
     1001 */
    9431002int DragInstance::onX11Event(const XEvent &e)
    9441003{
     
    9901049
    9911050#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     1051/**
     1052 * Waits for an X11 event of a specific type.
     1053 *
     1054 * @returns IPRT status code.
     1055 * @param   evX                     Reference where to store the event into.
     1056 * @param   iType                   Event type to wait for.
     1057 * @param   uTimeoutMS              Timeout (in ms) to wait for the event.
     1058 */
    9921059bool DragInstance::waitForX11Msg(XEvent &evX, int iType, RTMSINTERVAL uTimeoutMS /* = 100 */)
    9931060{
     
    10391106}
    10401107
     1108/**
     1109 * Waits for an X11 client message of a specific type.
     1110 *
     1111 * @returns IPRT status code.
     1112 * @param   evMsg                   Reference where to store the event into.
     1113 * @param   aType                   Event type to wait for.
     1114 * @param   uTimeoutMS              Timeout (in ms) to wait for the event.
     1115 */
    10411116bool DragInstance::waitForX11ClientMsg(XClientMessageEvent &evMsg, Atom aType,
    10421117                                       RTMSINTERVAL uTimeoutMS /*= 100 */)
     
    10581133                if (e.type == ClientMessage)
    10591134                {
     1135                    /** @todo Check is aType matches the event's type! */
     1136
    10601137                    m_eventQueue.removeAt(i);
    10611138                    evMsg = e.xclient;
     
    10941171 */
    10951172
    1096 int DragInstance::hgEnter(const RTCList<RTCString> &formats, uint32_t uActions)
     1173/**
     1174 * Host -> Guest: Event signalling that the host's (mouse) cursor just entered the VM's (guest's) display
     1175 *                area.
     1176 *
     1177 * @returns IPRT status code.
     1178 * @param   lstFormats              List of supported formats from the host.
     1179 * @param   uActions                (ORed) List of supported actions from the host.
     1180 */
     1181int DragInstance::hgEnter(const RTCList<RTCString> &lstFormats, uint32_t uActions)
    10971182{
    10981183    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
    10991184
    1100     if (m_enmMode != Unknown) 
     1185    if (m_enmMode != Unknown)
    11011186        return VERR_INVALID_STATE;
    11021187
     
    11041189
    11051190#ifdef DEBUG
    1106     LogFlowThisFunc(("uActions=0x%x, lstFormats=%zu: ", uActions, formats.size()));
    1107     for (size_t i = 0; i < formats.size(); ++i)
    1108         LogFlow(("'%s' ", formats.at(i).c_str()));
     1191    LogFlowThisFunc(("uActions=0x%x, lstFormats=%zu: ", uActions, lstFormats.size()));
     1192    for (size_t i = 0; i < lstFormats.size(); ++i)
     1193        LogFlow(("'%s' ", lstFormats.at(i).c_str()));
    11091194    LogFlow(("\n"));
    11101195#endif
     
    11141199    do
    11151200    {
    1116         rc = toAtomList(formats, m_lstFormats);
     1201        rc = toAtomList(lstFormats, m_lstFormats);
    11171202        if (RT_FAILURE(rc))
    11181203            break;
     
    11451230}
    11461231
     1232/**
     1233 * Host -> Guest: Event signalling that the host's (mouse) cursor has left the VM's (guest's)
     1234 *                display area.
     1235 */
    11471236int DragInstance::hgLeave(void)
    11481237{
    1149     if (m_enmMode == HG)
     1238    if (m_enmMode == HG) /* Only reset if in the right operation mode. */
    11501239        reset();
    11511240
     
    11531242}
    11541243
    1155 int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
     1244/**
     1245 * Host -> Guest: Event signalling that the host's (mouse) cursor has been moved within the VM's
     1246 *                (guest's) display area.
     1247 *
     1248 * @returns IPRT status code.
     1249 * @param   u32xPos                 Relative X position within the guest's display area.
     1250 * @param   u32yPos                 Relative Y position within the guest's display area.
     1251 * @param   uDefaultAction          Default action the host wants to perform on the guest
     1252 *                                  as soon as the operation successfully finishes.
     1253 */
     1254int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uDefaultAction)
    11561255{
    11571256    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
    1158     LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uAction));
     1257    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uDefaultAction));
    11591258
    11601259    if (   m_enmMode  != HG
     
    12121311
    12131312    /*
    1214      * Is the window under the cursor another one than our current one? 
    1215      * Cancel the current drop. 
     1313     * Is the window under the cursor another one than our current one?
     1314     * Cancel the current drop.
    12161315     */
    12171316    if (   wndCursor != m_wndCur
     
    12801379         * Send a XdndPosition event with the proposed action to the guest.
    12811380         */
    1282         Atom pa = toAtomAction(uAction);
     1381        Atom pa = toAtomAction(uDefaultAction);
    12831382        LogFlowThisFunc(("strAction=%s\n", xAtomToString(pa).c_str()));
    12841383
     
    13161415}
    13171416
     1417/**
     1418 * Host -> Guest: Event signalling that the host has dropped the data over the VM (guest) window.
     1419 *
     1420 * @returns IPRT status code.
     1421 */
    13181422int DragInstance::hgDrop(void)
    13191423{
     
    13281432    int rc = VINF_SUCCESS;
    13291433
    1330     /* 
     1434    /*
    13311435     * Send a drop event to the current window and reset our DnD status.
    13321436     */
     
    13541458}
    13551459
    1356 int DragInstance::hgDataReceived(void *pvData, uint32_t cbData)
     1460/**
     1461 * Host -> Guest: Event signalling that the host has sent drag'n drop (MIME) data
     1462 *                to the guest for further processing.
     1463 *
     1464 * @returns IPRT status code.
     1465 * @param   pvData                  Pointer to (MIME) data from host.
     1466 * @param   cbData                  Size (in bytes) of data from host.
     1467 */
     1468int DragInstance::hgDataReceived(const void *pvData, uint32_t cbData)
    13571469{
    13581470    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
     
    14161528
    14171529#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     1530/**
     1531 * Guest -> Host: Event signalling that the host is asking whether there is a pending
     1532 *                drag event on the guest (to the host).
     1533 *
     1534 * @returns IPRT status code.
     1535 */
    14181536int DragInstance::ghIsDnDPending(void)
    14191537{
     
    14831601                else
    14841602                {
    1485                     rc = wndXDnDGetTypeList(wndSelection, m_lstFormats);
     1603                    rc = wndXDnDGetFormatList(wndSelection, m_lstFormats);
    14861604                }
    14871605
     
    14901608                 */
    14911609                rc = wndXDnDGetActionList(wndSelection, m_lstActions);
    1492                
     1610
    14931611                fAcceptDrop = true;
    14941612            }
     
    15461664}
    15471665
     1666/**
     1667 * Guest -> Host: Event signalling that the host has dropped the item(s) on the
     1668 *                host side.
     1669 *
     1670 * @returns IPRT status code.
     1671 * @param   strFormat               Requested format to send to the host.
     1672 * @param   uAction                 Requested action to perform on the guest.
     1673 */
    15481674int DragInstance::ghDropped(const RTCString &strFormat, uint32_t uAction)
    15491675{
    1550     LogFlowThisFunc(("mode=%RU32, state=%RU32, strFormat=%s, uAction=%RU32\n", 
     1676    LogFlowThisFunc(("mode=%RU32, state=%RU32, strFormat=%s, uAction=%RU32\n",
    15511677                     m_enmMode, m_enmState, strFormat.c_str(), uAction));
    15521678
     
    15771703                   1 /* Button */, false /* fPress */);
    15781704
    1579     /** 
     1705    /**
    15801706     * The fake button release event above should lead to a XdndDrop event from the
    15811707     * source. Because of showing our proxy window, other Xdnd events can
    15821708     * occur before, e.g. a XdndPosition event. We are not interested
    1583      * in those, so just try to get the right one. 
    1584      */ 
     1709     * in those, so just try to get the right one.
     1710     */
    15851711
    15861712    XClientMessageEvent evDnDDrop;
     
    16271753                                             &aPropType, &iPropFormat, &cItems, &cbRemaining, &pcData);
    16281754                if (RT_UNLIKELY(xRc != Success))
    1629                     LogFlowThisFunc(("Error getting XA_XdndSelection property of proxy window=%#x: %s\n", 
     1755                    LogFlowThisFunc(("Error getting XA_XdndSelection property of proxy window=%#x: %s\n",
    16301756                                     m_wndProxy, gX11->xErrorToString(xRc).c_str()));
    16311757
     
    16801806                        m.data.l[0]    = m_wndProxy;                   /* Target window. */
    16811807                        m.data.l[1]    = 0;                            /* Don't accept the drop to not make the guest stuck. */
    1682                         m.data.l[2]    = RT_SUCCESS(rc) 
     1808                        m.data.l[2]    = RT_SUCCESS(rc)
    16831809                                       ? toAtomAction(uAction) : None; /* Action used on success */
    16841810
    16851811                        xRc = XSendEvent(m_pDisplay, wndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m));
    16861812                        if (RT_UNLIKELY(xRc == 0))
    1687                             LogFlowThisFunc(("Error sending XA_XdndFinished event to proxy window=%#x: %s\n", 
     1813                            LogFlowThisFunc(("Error sending XA_XdndFinished event to proxy window=%#x: %s\n",
    16881814                                             m_wndProxy, gX11->xErrorToString(xRc).c_str()));
    16891815                    }
     
    17631889 */
    17641890
     1891/**
     1892 * Moves the mouse pointer to a specific position.
     1893 *
     1894 * @returns IPRT status code.
     1895 * @param   iPosX                   Absolute X coordinate.
     1896 * @param   iPosY                   Absolute Y coordinate.
     1897 */
    17651898int DragInstance::mouseCursorMove(int iPosX, int iPosY) const
    17661899{
     
    17821915}
    17831916
     1917/**
     1918 * Sends a mouse button event to a specific window.
     1919 *
     1920 * @param   wndDest                 Window to send the mouse button event to.
     1921 * @param   rx                      X coordinate relative to the root window's origin.
     1922 * @param   ry                      Y coordinate relative to the root window's origin.
     1923 * @param   iButton                 Mouse button to press/release.
     1924 * @param   fPress                  Whether to press or release the mouse button.
     1925 */
    17841926void DragInstance::mouseButtonSet(Window wndDest, int rx, int ry, int iButton, bool fPress)
    17851927{
     
    18491991}
    18501992
     1993/**
     1994 * Shows the (invisible) proxy window. The proxy window is needed for intercepting
     1995 * drags from the host to the guest or from the guest to the host. It acts as a proxy
     1996 * between the host and the actual (UI) element on the guest OS.
     1997 *
     1998 * To not make it miss any actions this window gets spawned across the entire guest
     1999 * screen (think of an umbrella) to (hopefully) capture everything. A proxy window
     2000 * which follows the cursor would be far too slow here.
     2001 *
     2002 * @returns IPRT status code.
     2003 * @param   piRootX                 X coordinate relative to the root window's origin. Optional.
     2004 * @param   piRootY                 Y coordinate relative to the root window's origin. Optional.
     2005 * @param   fMouseMove              Whether to move the mouse cursor to the root window's origin or not.
     2006 */
    18512007int DragInstance::proxyWinShow(int *piRootX /*= NULL*/,
    18522008                               int *piRootY /*= NULL*/,
     
    18602016    int rc = VINF_SUCCESS;
    18612017
    1862 #if 0 
     2018#if 0
    18632019    XTestGrabControl(m_pDisplay, False);
    18642020#endif
     
    18982054    XSynchronize(m_pDisplay, False /* Disable sync */);
    18992055
    1900 #if 0 
     2056#if 0
    19012057    XTestGrabControl(m_pDisplay, True);
    19022058#endif
     
    19052061}
    19062062
     2063/**
     2064 * Hides the (invisible) proxy window.
     2065 */
    19072066int DragInstance::proxyWinHide(void)
    19082067{
     
    19172076}
    19182077
     2078/**
     2079 * Clear a window's supported/accepted actions list.
     2080 *
     2081 * @param   wndThis                 Window to clear the list for.
     2082 */
    19192083void DragInstance::wndXDnDClearActionList(Window wndThis) const
    19202084{
     
    19222086}
    19232087
    1924 void DragInstance::wndXDnDClearTypeList(Window wndThis) const
     2088/**
     2089 * Clear a window's supported/accepted formats list.
     2090 *
     2091 * @param   wndThis                 Window to clear the list for.
     2092 */
     2093void DragInstance::wndXDnDClearFormatList(Window wndThis) const
    19252094{
    19262095    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndTypeList));
    19272096}
    19282097
     2098/**
     2099 * Retrieves a window's supported/accepted XDnD actions.
     2100 *
     2101 * @returns IPRT status code.
     2102 * @param   wndThis                 Window to retrieve the XDnD actions for.
     2103 * @param   lstActions              Reference to VBoxDnDAtomList to store the action into.
     2104 */
    19292105int DragInstance::wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const
    19302106{
     
    19412117    if (xRc != Success)
    19422118    {
    1943         LogFlowThisFunc(("Error getting XA_XdndActionList atoms from window=%#x: %s\n", 
     2119        LogFlowThisFunc(("Error getting XA_XdndActionList atoms from window=%#x: %s\n",
    19442120                         wndThis, gX11->xErrorToString(xRc).c_str()));
    19452121        return VERR_NOT_FOUND;
    19462122    }
    19472123
    1948     if (   cItems > 0 
     2124    if (   cItems > 0
    19492125        && pcbData)
    19502126    {
     
    19652141}
    19662142
    1967 int DragInstance::wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const
     2143/**
     2144 * Retrieves a window's supported/accepted XDnD formats.
     2145 *
     2146 * @returns IPRT status code.
     2147 * @param   wndThis                 Window to retrieve the XDnD formats for.
     2148 * @param   lstTypes                Reference to VBoxDnDAtomList to store the formats into.
     2149 */
     2150int DragInstance::wndXDnDGetFormatList(Window wndThis, VBoxDnDAtomList &lstTypes) const
    19682151{
    19692152    Atom iActType = None;
     
    19782161    if (xRc != Success)
    19792162    {
    1980         LogFlowThisFunc(("Error getting XA_XdndTypeList atoms from window=%#x: %s\n", 
     2163        LogFlowThisFunc(("Error getting XA_XdndTypeList atoms from window=%#x: %s\n",
    19812164                         wndThis, gX11->xErrorToString(xRc).c_str()));
    19822165        return VERR_NOT_FOUND;
    19832166    }
    19842167
    1985     if (   cItems > 0 
     2168    if (   cItems > 0
    19862169        && pcbData)
    19872170    {
     
    20022185}
    20032186
     2187/**
     2188 * Sets (replaces) a window's XDnD accepted/allowed actions.
     2189 *
     2190 * @returns IPRT status code.
     2191 * @param   wndThis                 Window to set the format list for.
     2192 * @param   lstActions              Reference to list of XDnD actions to set.
     2193 *
     2194 * @remark
     2195 */
    20042196int DragInstance::wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const
    20052197{
     
    20162208}
    20172209
    2018 int DragInstance::wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const
     2210/**
     2211 * Sets (replaces) a window's XDnD accepted format list.
     2212 *
     2213 * @returns IPRT status code.
     2214 * @param   wndThis                 Window to set the format list for.
     2215 * @param   atmProp                 Property to set.
     2216 * @param   lstFormats              Reference to list of XDnD formats to set.
     2217 */
     2218int DragInstance::wndXDnDSetFormatList(Window wndThis, Atom atmProp, const VBoxDnDAtomList &lstFormats) const
    20192219{
    20202220    if (lstFormats.isEmpty())
     
    20272227
    20282228    /* Add the property with the property data to the window. */
    2029     XChangeProperty(m_pDisplay, wndThis, property,
     2229    XChangeProperty(m_pDisplay, wndThis, atmProp,
    20302230                    XA_ATOM, 32, PropModeReplace,
    20312231                    reinterpret_cast<const unsigned char*>(lstFormatsExt.raw()),
     
    20352235}
    20362236
     2237/**
     2238 * Converts a RTCString list to VBoxDnDAtomList list.
     2239 *
     2240 * @returns IPRT status code.
     2241 * @param   lstFormats              Reference to RTCString list to convert.
     2242 * @param   lstAtoms                Reference to VBoxDnDAtomList list to store results in.
     2243 */
    20372244int DragInstance::toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const
    2038 {   
     2245{
    20392246    for (size_t i = 0; i < lstFormats.size(); ++i)
    20402247        lstAtoms.append(XInternAtom(m_pDisplay, lstFormats.at(i).c_str(), False));
     
    20432250}
    20442251
     2252/**
     2253 * Converts a raw-data string list to VBoxDnDAtomList list.
     2254 *
     2255 * @returns IPRT status code.
     2256 * @param   pvData                  Pointer to string data to convert.
     2257 * @param   cbData                  Size (in bytes) to convert.
     2258 * @param   lstAtoms                Reference to VBoxDnDAtomList list to store results in.
     2259 */
    20452260int DragInstance::toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const
    20462261{
     
    20532268    int rc = VINF_SUCCESS;
    20542269
    2055     RTCList<Atom> lstAtom;
     2270    VBoxDnDAtomList lstAtom;
    20562271    while (cbStr)
    20572272    {
     
    20772292}
    20782293
     2294/**
     2295 * Converts a HGCM-based drag'n drop action to a Atom-based drag'n drop action.
     2296 *
     2297 * @returns Converted Atom-based drag'n drop action.
     2298 * @param   uActions                HGCM drag'n drop actions to convert.
     2299 */
    20792300/* static */
    20802301Atom DragInstance::toAtomAction(uint32_t uAction)
     
    20872308}
    20882309
     2310/**
     2311 * Converts HGCM-based drag'n drop actions to a VBoxDnDAtomList list.
     2312 *
     2313 * @returns IPRT status code.
     2314 * @param   uActions                HGCM drag'n drop actions to convert.
     2315 * @param   lstAtoms                Reference to VBoxDnDAtomList to store actions in.
     2316 */
    20892317/* static */
    20902318int DragInstance::toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms)
     
    21002328}
    21012329
     2330/**
     2331 * Converts an Atom-based drag'n drop action to a HGCM drag'n drop action.
     2332 *
     2333 * @returns HGCM drag'n drop action.
     2334 * @param   atom                    Atom-based drag'n drop action to convert.
     2335 */
    21022336/* static */
    21032337uint32_t DragInstance::toHGCMAction(Atom atom)
     
    21152349}
    21162350
     2351/**
     2352 * Converts an VBoxDnDAtomList list to an HGCM action list.
     2353 *
     2354 * @returns ORed HGCM action list.
     2355 * @param   actionsList             List of Atom-based actions to convert.
     2356 */
    21172357/* static */
    2118 uint32_t DragInstance::toHGCMActions(const RTCList<Atom> &actionsList)
     2358uint32_t DragInstance::toHGCMActions(const VBoxDnDAtomList &lstActions)
    21192359{
    21202360    uint32_t uActions = DND_IGNORE_ACTION;
    21212361
    2122     for (size_t i = 0; i < actionsList.size(); ++i)
    2123         uActions |= toHGCMAction(actionsList.at(i));
     2362    for (size_t i = 0; i < lstActions.size(); ++i)
     2363        uActions |= toHGCMAction(lstActions.at(i));
    21242364
    21252365    return uActions;
    2126 }
    2127 
    2128 /** @todo Replace by DnDURIList?  */
    2129 RTCList<RTCString> toStringList(const void *pvData, uint32_t cbData)
    2130 {
    2131     if (   !pvData
    2132         || !cbData)
    2133         return RTCList<RTCString>();
    2134 
    2135     const char *pszStr = (char*)pvData;
    2136     uint32_t cbStr = cbData;
    2137 
    2138     RTCList<RTCString> lstString;
    2139     while (cbStr > 0)
    2140     {
    2141         size_t cbSize = RTStrNLen(pszStr, cbStr);
    2142 
    2143         /* Create a copy with max N chars, so that we are on the save side,
    2144          * even if the data isn't zero terminated. */
    2145         char *pszTmp = RTStrDupN(pszStr, cbSize);
    2146         lstString.append(pszTmp);
    2147         RTStrFree(pszTmp);
    2148         pszStr  += cbSize + 1;
    2149         cbStr   -= cbSize + 1;
    2150     }
    2151 
    2152     return lstString;
    2153 }
    2154 
    2155 /** @todo Is this function really needed?  */
    2156 void DragAndDropService::clearEventQueue(void)
    2157 {
    2158     LogFlowThisFuncEnter();
    2159     m_eventQueue.clear();
    21602366}
    21612367
     
    21642370 ******************************************************************************/
    21652371
     2372/**
     2373 * Main loop for the drag and drop service which does the HGCM message
     2374 * processing and routing to the according drag and drop instance(s).
     2375 *
     2376 * @returns IPRT status code.
     2377 * @param   fDaemonised             Whether to run in daemonized or not. Does not
     2378 *                                  apply for this service.
     2379 */
    21662380int DragAndDropService::run(bool fDaemonised /* = false */)
    21672381{
     
    21712385    do
    21722386    {
    2173         /* Initialize X11 DnD. */
    2174         rc = x11DragAndDropInit();
     2387        /* Initialize drag and drop. */
     2388        rc = dragAndDropInit();
    21752389        if (RT_FAILURE(rc))
    21762390            break;
     
    22712485                LogFlowFunc(("Message %RU32 processed with %Rrc\n", e.hgcm.uType, rc));
    22722486                if (   RT_FAILURE(rc)
    2273                     /* 
    2274                      * Note: The hgXXX and ghXXX functions of the DnD instance above may return 
     2487                    /*
     2488                     * Note: The hgXXX and ghXXX functions of the DnD instance above may return
    22752489                     *       VERR_INVALID_STATE in case we're not in the expected state they want
    22762490                     *       to operate in. As the user might drag content back and forth to/from
     
    23242538             * Make sure that any X11 requests have actually been sent to the
    23252539             * server, since we are waiting for responses using poll() on
    2326              * another thread which will not automatically trigger flushing. 
    2327              */ 
     2540             * another thread which will not automatically trigger flushing.
     2541             */
    23282542            XFlush(m_pDisplay);
    23292543
     
    23362550}
    23372551
    2338 int DragAndDropService::x11DragAndDropInit(void)
     2552/**
     2553 * Initializes the drag and drop instance.
     2554 *
     2555 * @returns IPRT status code.
     2556 */
     2557int DragAndDropService::dragAndDropInit(void)
    23392558{
    23402559    /* Initialise the guest library. */
    23412560    int rc = VbglR3InitUser();
    23422561    if (RT_FAILURE(rc))
    2343         VBClFatalError(("Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
     2562        VBClFatalError(("DnD: Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
    23442563
    23452564    /* Connect to the x11 server. */
     
    23842603}
    23852604
     2605/**
     2606 * Static callback function for HGCM message processing thread. An internal
     2607 * message queue will be filled which then will be processed by the according
     2608 * drag'n drop instance.
     2609 *
     2610 * @returns IPRT status code.
     2611 * @param   hThread                 Thread handle to use.
     2612 * @param   pvUser                  Pointer to DragAndDropService instance to use.
     2613 */
    23862614/* static */
    23872615int DragAndDropService::hgcmEventThread(RTTHREAD hThread, void *pvUser)
     
    24462674}
    24472675
     2676/**
     2677 * Static callback function for X11 message processing thread. All X11 messages
     2678 * will be directly routed to the according drag'n drop instance.
     2679 *
     2680 * @returns IPRT status code.
     2681 * @param   hThread                 Thread handle to use.
     2682 * @param   pvUser                  Pointer to DragAndDropService instance to use.
     2683 */
    24482684/* static */
    24492685int DragAndDropService::x11EventThread(RTTHREAD hThread, void *pvUser)
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