VirtualBox

Changeset 55820 in vbox for trunk/src/VBox/Additions


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

DnD: VBoxClient: Implemented much smoother and accurate host<->guest drop operations, bugfixes, overhauling various code areas.

File:
1 edited

Legend:

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

    r55707 r55820  
    1717
    1818#include <X11/Xlib.h>
     19#include <X11/Xutil.h>
    1920#include <X11/Xatom.h>
    2021#ifdef VBOX_DND_WITH_XTEST
     
    287288}
    288289
    289 /* Todo: make this iterative */
     290/** todo Make this iterative. */
    290291Window xHelpers::applicationWindowBelowCursor(Window wndParent) const
    291292{
     
    341342#endif
    342343
     344#define VBoxDnDAtomList RTCList<Atom>
     345
    343346/* For now only one DragInstance will exits when the app is running. In the
    344347 * future the support for having more than one drag and drop operation supported at the
     
    353356        Initialized,
    354357        Dragging,
    355         Dropped
     358        Dropped,
     359        State_32BIT_Hack = 0x7fffffff
    356360    };
    357361
     
    360364        Unknown = 0,
    361365        HG,
    362         GH
     366        GH,
     367        Mode_32Bit_Hack = 0x7fffffff
    363368    };
    364369
     
    399404    int proxyWinShow(int *piRootX = NULL, int *piRootY = NULL, bool fMouseMove = false) const;
    400405    int proxyWinHide(void);
    401     void registerForEvents(Window w) const;
    402 
    403     void setActionsWindowProperty(Window wndThis, const RTCList<Atom> &lstActions) const;
    404     void clearActionsWindowProperty(Window wndThis) const;
    405     void setFormatsWindowProperty(Window wndThis, Atom property) const;
    406     void clearFormatsWindowProperty(Window wndThis) const;
    407 
    408     RTCList<Atom>        toAtomList(const RTCList<RTCString> &lstFormats) const;
    409     RTCList<Atom>        toAtomList(void *pvData, uint32_t cbData) const;
    410     static Atom          toX11Action(uint32_t uAction);
    411     static RTCList<Atom> toX11Actions(uint32_t uActions);
    412     static uint32_t      toHGCMAction(Atom atom);
    413     static uint32_t      toHGCMActions(const RTCList<Atom> &actionsList);
     406
     407    void wndXDnDClearActionList(Window wndThis) const;
     408    void wndXDnDClearTypeList(Window wndThis) const;
     409    int wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const;
     410    int wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const;
     411    int wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const;
     412    int wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const;
     413
     414    int                    toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const;
     415    int                    toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const;
     416    static Atom            toAtomAction(uint32_t uAction);
     417    static int             toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms);
     418    static uint32_t        toHGCMAction(Atom atom);
     419    static uint32_t        toHGCMActions(const RTCList<Atom> &actionsList);
    414420
    415421protected:
     
    425431    Window                      m_wndCur;
    426432    long                        m_curVer;
    427     RTCList<Atom>               m_formats;
    428     RTCList<Atom>               m_actions;
     433    VBoxDnDAtomList             m_lstFormats;
     434    VBoxDnDAtomList             m_lstActions;
    429435    /** Deferred host to guest selection event for sending to the
    430436     *  target window as soon as data from the host arrived. */
    431437    XEvent                      m_eventHgSelection;
    432438    /** Current operation mode. */
    433     Mode                        m_mode;
     439    Mode                        m_enmMode;
    434440    /** Current state of operation mode. */
    435     State                       m_state;
     441    State                       m_enmState;
    436442    /** The instance's own X event queue. */
    437443    RTCMTList<XEvent>           m_eventQueue;
     
    467473
    468474private:
     475
    469476    int x11DragAndDropInit(void);
    470477    static int hgcmEventThread(RTTHREAD hThread, void *pvUser);
     
    472479
    473480    void clearEventQueue();
    474 
    475     /* Usually XCheckMaskEvent could be used for querying selected x11 events.
    476      * Unfortunately this doesn't work exactly with the events we need. So we
    477      * use this predicate method below and XCheckIfEvent. */
    478     static bool isDnDRespondEvent(Display * /* pDisplay */, XEvent *pEvent, char *pUser)
    479     {
    480         if (!pEvent)
    481             return false;
    482         if (   pEvent->type == SelectionClear
    483             || pEvent->type == ClientMessage
    484             || pEvent->type == MotionNotify
    485             || pEvent->type == SelectionRequest)
    486 //            || (   pEvent->type == ClientMessage
    487 //                && reinterpret_cast<XClientMessageEvent*>(pEvent)->window == reinterpret_cast<Window>(pUser))
    488 //            || (   pEvent->type == SelectionRequest
    489 //                && reinterpret_cast<XSelectionRequestEvent*>(pEvent)->requestor == reinterpret_cast<Window>(pUser)))
    490             return true;
    491         return false;
    492     }
    493481
    494482    /* Private member vars */
     
    524512    , m_wndCur(0)
    525513    , m_curVer(-1)
    526     , m_mode(Unknown)
    527     , m_state(Uninitialized)
     514    , m_enmMode(Unknown)
     515    , m_enmState(Uninitialized)
    528516{
    529517    uninit();
     
    538526    VbglR3DnDDisconnect(&m_dndCtx);
    539527
    540     m_state    = Uninitialized;
     528    m_enmState    = Uninitialized;
    541529    m_screenId = -1;
    542530    m_pScreen  = 0;
     
    557545        XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), None, CurrentTime);
    558546
    559     /* Clear any other DnD specific data on the proxy win. */
    560     clearFormatsWindowProperty(m_wndProxy);
    561     clearActionsWindowProperty(m_wndProxy);
     547    /* Clear any other DnD specific data on the proxy window. */
     548    wndXDnDClearTypeList(m_wndProxy);
     549    wndXDnDClearActionList(m_wndProxy);
    562550
    563551    /* Reset the internal state. */
    564     m_actions.clear();
    565     m_formats.clear();
    566     m_wndCur = 0;
    567     m_curVer = -1;
    568     m_state  = Initialized;
    569     m_mode   = Unknown;
     552    m_lstActions.clear();
     553    m_lstFormats.clear();
     554    m_wndCur    = 0;
     555    m_curVer    = -1;
     556    m_enmState  = Initialized;
     557    m_enmMode   = Unknown;
    570558    m_eventQueue.clear();
    571559}
     
    599587            break;
    600588        }
     589#if 0
    601590        /* Get the screen number from the x11 server. */
    602 //        pDrag->screen = ScreenOfDisplay(m_pDisplay, u32ScreenId);
    603 //        if (!pDrag->screen)
    604 //        {
    605 //            rc = VERR_GENERAL_FAILURE;
    606 //            break;
    607 //        }
     591        pDrag->screen = ScreenOfDisplay(m_pDisplay, u32ScreenId);
     592        if (!pDrag->screen)
     593        {
     594            rc = VERR_GENERAL_FAILURE;
     595            break;
     596        }
     597#endif
    608598        m_screenId = u32ScreenId;
     599
    609600        /* Now query the corresponding root window of this screen. */
    610601        m_wndRoot = RootWindow(m_pDisplay, m_screenId);
     
    624615        attr.event_mask            =   EnterWindowMask  | LeaveWindowMask
    625616                                     | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
     617        attr.override_redirect     = True;
    626618        attr.do_not_propagate_mask = NoEventMask;
    627         attr.override_redirect     = True;
    628619#ifdef VBOX_DND_DEBUG_WND
    629         attr.background_pixel      = WhitePixel(m_pDisplay, m_screenId);
    630 #endif
     620        attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenId);
     621        attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenId);
     622        m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                     /* Parent */,
     623                                   100, 100,                                 /* Position */
     624                                   100, 100,                                 /* Width + height */
     625                                   2,                                        /* Border width */
     626                                   CopyFromParent,                           /* Depth */
     627                                   InputOutput,                              /* Class */
     628                                   CopyFromParent,                           /* Visual */
     629                                     CWBackPixel
     630                                   | CWBorderPixel
     631                                   | CWOverrideRedirect
     632                                   | CWDontPropagate,                        /* Value mask */
     633                                   &attr);                                   /* Attributes for value mask */       
     634#else
    631635        m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                 /* Parent */,
    632636                                   0, 0,                                 /* Position */
     
    637641                                   CopyFromParent,                       /* Visual */
    638642                                   CWOverrideRedirect | CWDontPropagate, /* Value mask */
    639                                    &attr                                 /* Attributes for value mask */);
     643                                   &attr);                               /* Attributes for value mask */
     644#endif
    640645        if (!m_wndProxy)
    641646        {
     
    645650        }
    646651
    647         LogFlowThisFunc(("Created proxy window 0x%x at m_wndRoot=0x%x ...\n",
    648                          m_wndProxy, m_wndRoot));
     652#ifdef VBOX_DND_DEBUG_WND
     653        XFlush(m_pDisplay);
     654        XMapWindow(m_pDisplay, m_wndProxy);
     655        XRaiseWindow(m_pDisplay, m_wndProxy);
     656        XFlush(m_pDisplay);
     657#endif
     658        LogFlowThisFunc(("Created proxy window 0x%x at m_wndRoot=0x%x ...\n", m_wndProxy, m_wndRoot));
    649659
    650660        /* Set the window's name for easier lookup. */
     
    659669    if (RT_SUCCESS(rc))
    660670    {
    661         m_state = Initialized;
     671        m_enmState = Initialized;
    662672    }
    663673    else
     
    688698    AssertReturn(e.type == ClientMessage, VERR_INVALID_PARAMETER);
    689699
    690     LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
    691     LogFlowThisFunc(("Event wnd=%#x, msg=%s\n",
    692                      e.xclient.window,
    693                      xAtomToString(e.xclient.message_type).c_str()));
     700    LogFlowThisFunc(("mode=%d, state=%d\n", m_enmMode, m_enmState));
     701    LogFlowThisFunc(("Event wnd=%#x, msg=%s\n", e.xclient.window, xAtomToString(e.xclient.message_type).c_str()));
     702
    694703    int rc;
    695704
    696     switch (m_mode)
     705    switch (m_enmMode)
    697706    {
    698707        case HG:
    699708        {
    700             /* Client messages are used to inform us about the status of a XdndAware
    701              * window, in response of some events we send to them. */
     709            /*
     710             * Client messages are used to inform us about the status of a XdndAware
     711             * window, in response of some events we send to them.
     712             */
    702713            if (   e.xclient.message_type == xAtom(XA_XdndStatus)
    703714                && m_wndCur               == static_cast<Window>(e.xclient.data.l[0]))
    704715            {
    705                 /* The XdndStatus message tell us if the window will accept the DnD
     716                /*
     717                 * The XdndStatus message tell us if the window will accept the DnD
    706718                 * event and with which action. We immediately send this info down to
    707                  * the host as a response of a previous DnD message. */
    708                 LogFlowThisFunc(("XA_XdndStatus wnd=%#x, accept=%RTbool, action=%s\n",
     719                 * the host as a response of a previous DnD message.
     720                 */
     721                LogFlowThisFunc(("XA_XdndStatus: wnd=%#x, accept=%RTbool, action=%s\n",
    709722                                 e.xclient.data.l[0],
    710723                                 ASMBitTest(&e.xclient.data.l[1], 0),
     
    722735                rc = VINF_SUCCESS;
    723736
    724                 /* This message is send on a un/successful DnD drop request. */
     737                /* This message is sent on an un/successful DnD drop request. */
    725738                LogFlowThisFunc(("XA_XdndFinished: wnd=%#x, success=%RTbool, action=%s\n",
    726739                                 e.xclient.data.l[0],
    727740                                 ASMBitTest(&e.xclient.data.l[1], 0),
    728741                                 xAtomToString(e.xclient.data.l[2]).c_str()));
    729                 reset();
     742
     743                proxyWinHide();
    730744            }
    731745            else
     
    740754
    741755        case GH:
    742         {
    743             LogFlowThisFunc(("Enqueuing ClientMessage\n"));
    744 
     756        case Unknown: /* Mode not set (yet), just add what we got. */
     757        {
    745758            m_eventQueue.append(e);
    746759            rc = RTSemEventSignal(m_hEventSem);
     760            break;
     761        }
     762       
     763        default:
     764        {
     765            AssertMsgFailed(("Drag and drop mode not implemented: %RU32\n", m_enmMode));
     766            rc = VERR_NOT_IMPLEMENTED;
     767            break;
     768        }
     769    }
     770
     771    LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     772    return rc;
     773}
     774
     775int DragInstance::onX11SelectionNotify(const XEvent &e)
     776{
     777    AssertReturn(e.type == SelectionNotify, VERR_INVALID_PARAMETER);
     778
     779    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_enmMode, m_enmState));
     780
     781    int rc;
     782
     783    switch (m_enmMode)
     784    {
     785        case GH:
     786        {
     787            if (m_enmState == Dropped)
     788            {
     789                m_eventQueue.append(e);
     790                rc = RTSemEventSignal(m_hEventSem);
     791            }
    747792            break;
    748793        }
     
    761806}
    762807
    763 int DragInstance::onX11SelectionNotify(const XEvent &e)
    764 {
    765     AssertReturn(e.type == SelectionNotify, VERR_INVALID_PARAMETER);
    766 
    767     LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
    768 
    769     int rc = VINF_SUCCESS;
    770 
    771     switch (m_mode)
    772     {
    773         case GH:
    774         {
    775             if (m_state == Dropped)
    776             {
    777                 LogFlowThisFunc(("Enqueuing SelectionNotify\n"));
    778 
    779                 m_eventQueue.append(e);
    780                 rc = RTSemEventSignal(m_hEventSem);
    781             }
    782             break;
    783         }
    784 
    785         default:
    786         {
    787             LogFlowThisFunc(("Unhandled: wnd=%#x, msg=%s\n",
    788                              e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str()));
    789             rc = VERR_INVALID_STATE;
    790             break;
    791         }
    792     }
    793 
    794     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
    795     return rc;
    796 }
    797 
    798 
    799808int DragInstance::onX11SelectionRequest(const XEvent &e)
    800809{
    801810    AssertReturn(e.type == SelectionRequest, VERR_INVALID_PARAMETER);
    802811
    803     LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
     812    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_enmMode, m_enmState));
    804813    LogFlowThisFunc(("Event owner=%#x, requestor=%#x, selection=%s, target=%s, prop=%s, time=%u\n",
    805814                     e.xselectionrequest.owner,
     
    811820    int rc;
    812821
    813     switch (m_mode)
     822    bool fSendEvent  = false;
     823    Atom atmTarget   = None;
     824    Atom atmProperty = None;
     825
     826    switch (m_enmMode)
    814827    {
    815828        case HG:
     
    832845                /* If so, set the window property with the formats on the requestor
    833846                 * window. */
    834                 setFormatsWindowProperty(e.xselectionrequest.requestor, e.xselectionrequest.property);
    835 
     847                rc = wndXDnDSetFormatList(e.xselectionrequest.requestor, e.xselectionrequest.property, m_lstFormats);
     848                if (RT_SUCCESS(rc))
     849                {
     850                    atmTarget   = e.xselectionrequest.target;
     851                    atmProperty = e.xselectionrequest.property;
     852
     853                    fSendEvent  = true;
     854                }
     855            }
     856            /* Is the requestor asking for a specific MIME type (we support)? */
     857            else if (m_lstFormats.contains(e.xselectionrequest.target))
     858            {
     859                LogFlowThisFunc(("wnd=%#x asking for data, format=%s\n",
     860                                 e.xselectionrequest.requestor, xAtomToString(e.xselectionrequest.target).c_str()));
     861
     862                /* If so, we need to inform the host about this request. Save the
     863                 * selection request event for later use. */
     864                if (m_enmState != Dropped)
     865                {
     866                    LogFlowThisFunc(("Wrong state (%RU32), refusing request\n", m_enmState));
     867
     868                    atmTarget   = None;
     869                    atmProperty = e.xselectionrequest.property;
     870
     871                    fSendEvent  = true;
     872                }
     873                else
     874                {
     875                    LogFlowThisFunc(("Saving selection notify message\n"));
     876
     877                    memcpy(&m_eventHgSelection, &e, sizeof(XEvent));
     878
     879                    RTCString strFormat = xAtomToString(e.xselectionrequest.target);
     880                    Assert(strFormat.isNotEmpty());
     881
     882                    rc = VbglR3DnDHGRequestData(&m_dndCtx, strFormat.c_str());
     883                    LogFlowThisFunc(("Requested data from host as \"%s\", rc=%Rrc\n", strFormat.c_str(), rc));
     884                }
     885            }
     886            /* Anything else. */
     887            else
     888            {
     889                LogFlowThisFunc(("Refusing unknown command\n"));
     890
     891                /* We don't understand this request message and therefore answer with an
     892                 * refusal messages. */
     893                fSendEvent = true;
     894            }
     895
     896            if (   RT_SUCCESS(rc)
     897                && fSendEvent)
     898            {
    836899                XEvent s;
    837900                RT_ZERO(s);
     
    841904                s.xselection.selection = e.xselectionrequest.selection;
    842905                s.xselection.requestor = e.xselectionrequest.requestor;
    843                 s.xselection.target    = e.xselectionrequest.target;
    844                 s.xselection.property  = e.xselectionrequest.property;
     906                s.xselection.target    = atmTarget;
     907                s.xselection.property  = atmProperty;
    845908
    846909                int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
    847910                if (RT_UNLIKELY(xRc == 0))
    848                     LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
     911                    logError("Error sending SelectionNotify(1) event to wnd=%#x: %s\n", e.xselectionrequest.requestor,
     912                             gX11->xErrorToString(xRc).c_str());
    849913            }
    850             /* Is the requestor asking for a specific MIME type (we support)? */
    851             else if (m_formats.contains(e.xselectionrequest.target))
    852             {
    853                 LogFlowThisFunc(("wnd=%#x asking for data, format=%s\n",
    854                                  e.xselectionrequest.requestor, xAtomToString(e.xselectionrequest.target).c_str()));
    855 
    856                 /* If so, we need to inform the host about this request. Save the
    857                  * selection request event for later use. */
    858                 if (   m_state != Dropped)
    859                     //        || m_curWin != e.xselectionrequest.requestor)
    860                 {
    861                     LogFlowThisFunc(("Wrong state, refusing request\n"));
    862 
    863                     XEvent s;
    864                     RT_ZERO(s);
    865                     s.xselection.type      = SelectionNotify;
    866                     s.xselection.display   = e.xselection.display;
    867                     s.xselection.time      = e.xselectionrequest.time;
    868                     s.xselection.selection = e.xselectionrequest.selection;
    869                     s.xselection.requestor = e.xselectionrequest.requestor;
    870                     s.xselection.target    = None;
    871                     s.xselection.property  = e.xselectionrequest.property;
    872 
    873                     int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
    874                     if (RT_UNLIKELY(xRc == 0))
    875                         LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
    876                 }
    877                 else
    878                 {
    879                     LogFlowThisFunc(("Saving selection notify message\n"));
    880 
    881                     memcpy(&m_eventHgSelection, &e, sizeof(XEvent));
    882 
    883                     RTCString strFormat = xAtomToString(e.xselectionrequest.target);
    884                     Assert(strFormat.isNotEmpty());
    885                     rc = VbglR3DnDHGRequestData(&m_dndCtx, strFormat.c_str());
    886                     LogFlowThisFunc(("Requesting data from host as \"%s\", rc=%Rrc\n",
    887                                      strFormat.c_str(), rc));
    888                 }
    889             }
    890             /* Anything else. */
    891             else
    892             {
    893                 LogFlowThisFunc(("Refusing unknown command\n"));
    894 
    895                 /* We don't understand this request message and therefore answer with an
    896                  * refusal messages. */
    897                 XEvent s;
    898                 RT_ZERO(s);
    899                 s.xselection.type      = SelectionNotify;
    900                 s.xselection.display   = e.xselection.display;
    901                 s.xselection.time      = e.xselectionrequest.time;
    902                 s.xselection.selection = e.xselectionrequest.selection;
    903                 s.xselection.requestor = e.xselectionrequest.requestor;
    904                 s.xselection.target    = None; /* default is refusing */
    905                 s.xselection.property  = None; /* default is refusing */
    906                 int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
    907                 if (RT_UNLIKELY(xRc == 0))
    908                     LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
    909             }
    910914
    911915            break;
     
    914918        default:
    915919        {
    916             LogFlowThisFunc(("Unhandled: wnd=%#x, msg=%s\n",
     920            LogFlowThisFunc(("Unhandled message for wnd=%#x: %s\n",
    917921                             e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str()));
    918922            rc = VERR_INVALID_STATE;
     
    974978
    975979#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    976 bool DragInstance::waitForX11Msg(XEvent &evX, int iType,
    977                                  RTMSINTERVAL uTimeoutMS /* = 100 */)
     980bool DragInstance::waitForX11Msg(XEvent &evX, int iType, RTMSINTERVAL uTimeoutMS /* = 100 */)
    978981{
    979982    LogFlowThisFunc(("iType=%d, uTimeoutMS=%RU32, cEventQueue=%zu\n", iType, uTimeoutMS, m_eventQueue.size()));
     
    10701073    while (RTTimeMilliTS() - uiStart < uTimeoutMS);
    10711074
    1072     LogFlowThisFunc(("Returning fFound=%RTbool, msRuntime=%RU64\n",
    1073                      fFound, RTTimeMilliTS() - uiStart));
     1075    LogFlowThisFunc(("Returning fFound=%RTbool, msRuntime=%RU64\n", fFound, RTTimeMilliTS() - uiStart));
    10741076    return fFound;
    10751077}
     
    10821084int DragInstance::hgEnter(const RTCList<RTCString> &formats, uint32_t uActions)
    10831085{
    1084     if (m_mode != Unknown)
     1086    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
     1087
     1088    if (m_enmMode != Unknown)
    10851089        return VERR_INVALID_STATE;
    10861090
     
    10941098#endif
    10951099
    1096     m_formats = toAtomList(formats);
    1097 
    1098     /* If we have more than 3 formats we have to use the type list extension. */
    1099     if (m_formats.size() > 3)
    1100         setFormatsWindowProperty(m_wndProxy, xAtom(XA_XdndTypeList));
    1101 
    1102     /* Announce the possible actions */
    1103     setActionsWindowProperty(m_wndProxy, toX11Actions(uActions));
    1104 
    1105     /* Set the DnD selection owner to our window. */
    1106     XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy, CurrentTime);
    1107 
    1108     m_mode  = HG;
    1109     m_state = Dragging;
    1110 
    1111     return VINF_SUCCESS;
     1100    int rc;
     1101
     1102    do
     1103    {
     1104        rc = toAtomList(formats, m_lstFormats);
     1105        if (RT_FAILURE(rc))
     1106            break;
     1107
     1108        /* If we have more than 3 formats we have to use the type list extension. */
     1109        if (m_lstFormats.size() > 3)
     1110        {
     1111            rc = wndXDnDSetFormatList(m_wndProxy, xAtom(XA_XdndTypeList), m_lstFormats);
     1112            if (RT_FAILURE(rc))
     1113                break;
     1114        }
     1115
     1116        /* Announce the possible actions. */
     1117        VBoxDnDAtomList lstActions;
     1118        rc = toAtomActions(uActions, lstActions);
     1119        if (RT_FAILURE(rc))
     1120            break;
     1121        rc = wndXDnDSetActionList(m_wndProxy, lstActions);
     1122
     1123        /* Set the DnD selection owner to our window. */
     1124        XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy, CurrentTime);
     1125
     1126        m_enmMode  = HG;
     1127        m_enmState = Dragging;
     1128
     1129    } while (0);
     1130
     1131    LogFlowFuncLeaveRC(rc);
     1132    return rc;
    11121133}
    11131134
    11141135int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
    11151136{
    1116     LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n",
    1117                     u32xPos, u32yPos, uAction));
    1118 
    1119     if (   m_mode  != HG
    1120         || m_state != Dragging)
     1137    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
     1138    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uAction));
     1139
     1140    if (   m_enmMode  != HG
     1141        || m_enmState != Dragging)
    11211142    {
    11221143        return VERR_INVALID_STATE;
     
    11561177            {
    11571178                newVer = reinterpret_cast<long*>(pcData)[0];
    1158                 LogFlowThisFunc(("wndCursor=%#x, XdndAware=%ld\n", wndCursor, newVer));
     1179
     1180                LogFlowThisFunc(("Current: wndCursor=%#x, XdndAware=%ld\n", wndCursor, newVer));               
     1181#ifdef DEBUG
     1182                XTextProperty propName;
     1183                if (XGetWMName(m_pDisplay, wndCursor, &propName))
     1184                {
     1185                    LogFlowThisFunc(("\tTitle: %s\n", propName.value));
     1186                    XFree(propName.value);
     1187                }
     1188#endif
    11591189            }
    11601190
     
    11641194
    11651195    /*
    1166      * Is the window under the cursor another one than our current one?
     1196     * Is the window under the cursor another one than our current one?
     1197     * Cancel the current drop.
    11671198     */
    11681199    if (   wndCursor != m_wndCur
    11691200        && m_curVer  != -1)
    11701201    {
    1171         LogFlowThisFunc(("Leaving window=%#x\n", m_wndCur));
    1172 
    1173         /* We left the current XdndAware window. Announce this to the window. */
     1202        LogFlowThisFunc(("XA_XdndLeave: window=%#x\n", m_wndCur));
     1203
     1204        /* We left the current XdndAware window. Announce this to the current indow. */
    11741205        XClientMessageEvent m;
    11751206        RT_ZERO(m);
     
    11791210        m.message_type = xAtom(XA_XdndLeave);
    11801211        m.format       = 32;
    1181         m.data.l[0]    = m_wndProxy;
     1212        m.data.l[0]    = m_wndProxy;                    /* Source window. */
    11821213
    11831214        xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
    11841215        if (RT_UNLIKELY(xRc == 0))
    1185             logError("DnD: Error sending XA_XdndLeave event to old window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
     1216            logError("Error sending XA_XdndLeave event to old window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
    11861217    }
    11871218
     
    11921223        && newVer    != -1)
    11931224    {
    1194         LogFlowThisFunc(("Entering window=%#x\n", wndCursor));
     1225        LogFlowThisFunc(("XA_XdndEnter: window=%#x\n", wndCursor));
    11951226
    11961227        /*
     
    12071238        m.message_type = xAtom(XA_XdndEnter);
    12081239        m.format       = 32;
    1209         m.data.l[0]    = m_wndProxy;
    1210         m.data.l[1]    = RT_MAKE_U32_FROM_U8(m_formats.size() > 3 ? 1 : 0, 0, 0, RT_MIN(VBOX_XDND_VERSION, newVer));
    1211         m.data.l[2]    = m_formats.value(0, None);
    1212         m.data.l[3]    = m_formats.value(1, None);
    1213         m.data.l[4]    = m_formats.value(2, None);
     1240        m.data.l[0]    = m_wndProxy;                    /* Source window. */
     1241        m.data.l[1]    = RT_MAKE_U32_FROM_U8(
     1242                         /* Bit 0 is set if the source supports more than three data types. */
     1243                         m_lstFormats.size() > 3 ? 1 : 0,
     1244                         /* Reserved for future use. */
     1245                         0, 0,
     1246                         /* Protocol version to use. */
     1247                         RT_MIN(VBOX_XDND_VERSION, newVer));
     1248        m.data.l[2]    = m_lstFormats.value(0, None);   /* First data type to use. */
     1249        m.data.l[3]    = m_lstFormats.value(1, None);   /* Second data type to use. */
     1250        m.data.l[4]    = m_lstFormats.value(2, None);   /* Third data type to use. */
    12141251
    12151252        xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
    12161253        if (RT_UNLIKELY(xRc == 0))
    1217             logError("Error sending XA_XdndEnter event to new window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
     1254            logError("Error sending XA_XdndEnter event to window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
    12181255    }
    12191256
    12201257    if (newVer != -1)
    12211258    {
    1222         LogFlowThisFunc(("Moving window=%#x, xPos=%RU32, yPos=%RU32\n", wndCursor, u32xPos, u32yPos));
     1259        LogFlowThisFunc(("XA_XdndPosition: xPos=%RU32, yPos=%RU32 to window=%#x\n", u32xPos, u32yPos, wndCursor));
    12231260
    12241261        /*
    12251262         * Send a XdndPosition event with the proposed action to the guest.
    12261263         */
    1227         Atom pa = toX11Action(uAction);
     1264        Atom pa = toAtomAction(uAction);
    12281265        LogFlowThisFunc(("strAction=%s\n", xAtomToString(pa).c_str()));
    12291266
     
    12351272        m.message_type = xAtom(XA_XdndPosition);
    12361273        m.format       = 32;
    1237         m.data.l[0]    = m_wndProxy;
    1238         m.data.l[2]    = RT_MAKE_U32(u32yPos, u32xPos);
    1239         m.data.l[3]    = CurrentTime;
    1240         m.data.l[4]    = pa;
     1274        m.data.l[0]    = m_wndProxy;                    /* X window ID of source window. */
     1275        m.data.l[2]    = RT_MAKE_U32(u32yPos, u32xPos); /* Cursor coordinates relative to the root window. */
     1276        m.data.l[3]    = CurrentTime;                   /* Timestamp for retrieving data. */
     1277        m.data.l[4]    = pa;                            /* Actions requested by the user. */
    12411278
    12421279        xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
    12431280        if (RT_UNLIKELY(xRc == 0))
    1244             logError(("Error sending XA_XdndPosition event to current window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str()));
     1281            logError("Error sending XA_XdndPosition event to current window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
    12451282    }
    12461283
     
    12511288        rc = VbglR3DnDHGAcknowledgeOperation(&m_dndCtx, DND_IGNORE_ACTION);
    12521289    }
    1253 
    1254     m_wndCur = wndCursor;
    1255     m_curVer = RT_MIN(VBOX_XDND_VERSION, newVer);
     1290    else
     1291    {
     1292        m_wndCur = wndCursor;
     1293        m_curVer = RT_MIN(VBOX_XDND_VERSION, newVer);
     1294    }
    12561295
    12571296    LogFlowFuncLeaveRC(rc);
     
    12611300int DragInstance::hgDrop(void)
    12621301{
    1263     LogFlowThisFunc(("wndCur=%#x, mMode=%RU32, mState=%RU32\n",
    1264                      m_wndCur, m_mode, m_state));
    1265 
    1266     if (   m_mode  != HG
    1267         || m_state != Dragging)
     1302    LogFlowThisFunc(("wndCur=%#x, wndProxy=%#x, mode=%RU32, state=%RU32\n", m_wndProxy, m_wndCur, m_enmMode, m_enmState));
     1303
     1304    if (   m_enmMode  != HG
     1305        || m_enmState != Dragging)
    12681306    {
    12691307        return VERR_INVALID_STATE;
     
    12721310    int rc = VINF_SUCCESS;
    12731311
    1274     /* Send a drop event to the current window and reset our DnD status. */
     1312    /*
     1313     * Send a drop event to the current window and reset our DnD status.
     1314     */
    12751315    XClientMessageEvent m;
    12761316    RT_ZERO(m);
     
    12801320    m.message_type = xAtom(XA_XdndDrop);
    12811321    m.format       = 32;
    1282     m.data.l[0]    = m_wndProxy;
    1283     m.data.l[2]    = CurrentTime;
     1322    m.data.l[0]    = m_wndProxy;                        /* Source window. */
     1323    m.data.l[2]    = CurrentTime;                       /* Timestamp. */
    12841324
    12851325    int xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
    12861326    if (RT_UNLIKELY(xRc == 0))
    1287         logError(("Error sending XA_XdndDrop event to current window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str()));
     1327        logError("Error sending XA_XdndDrop event to current window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
    12881328
    12891329    m_wndCur = None;
    12901330    m_curVer = -1;
    12911331
    1292     m_state = Dropped;
     1332    m_enmState = Dropped;
    12931333
    12941334    LogFlowFuncLeaveRC(rc);
     
    12981338int DragInstance::hgDataReceived(void *pvData, uint32_t cbData)
    12991339{
    1300     if (   m_mode  != HG
    1301         || m_state != Dropped)
     1340    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
     1341
     1342    if (   m_enmMode  != HG
     1343        || m_enmState != Dropped)
    13021344    {
    13031345        return VERR_INVALID_STATE;
     
    13101352    }
    13111353
    1312     if (RT_UNLIKELY(m_state != Dropped))
    1313         return VERR_INVALID_STATE;
    1314 
    1315     /* Make a copy of the data. The xserver will become the new owner. */
     1354    /* Make a copy of the data. The X server will become the new owner. */
    13161355    void *pvNewData = RTMemAlloc(cbData);
    13171356    if (RT_UNLIKELY(!pvNewData))
     
    13211360
    13221361    /*
    1323      * The host send us the DnD data in the requested mime type. This allows us
     1362     * The host has sent us the DnD data in the requested MIME type. This allows us
    13241363     * to fill the XdndSelection property of the requestor window with the data
    13251364     * and afterwards inform the host about the new status.
     
    13491388    int xRc = XSendEvent(s.xselection.display, s.xselection.requestor, True, 0, &s);
    13501389    if (RT_UNLIKELY(xRc == 0))
    1351     {
    1352         logError(("Error sending SelectionNotify event to window=%#x: %s\n",
    1353                   s.xselection.requestor, gX11->xErrorToString(xRc).c_str()));
    1354     }
     1390        logError("Error sending SelectionNotify(2) event to window=%#x: %s\n",
     1391                 s.xselection.requestor, gX11->xErrorToString(xRc).c_str());
     1392
     1393    /* We're finally done, reset. */
     1394    reset();
    13551395
    13561396    return VINF_SUCCESS;
     
    13601400int DragInstance::ghIsDnDPending(void)
    13611401{
    1362     LogFlowFuncEnter();
    1363 
    1364     if (m_mode == HG)
     1402    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
     1403
     1404    if (m_enmMode == HG)
    13651405        return VERR_INVALID_STATE;
    13661406
     
    13731413        && wndSelection != m_wndProxy)
    13741414    {
    1375         m_mode  = GH;
    1376 
    13771415        /* Map the window on the current cursor position, which should provoke
    13781416         * an XdndEnter event. */
    1379         proxyWinShow();
     1417        proxyWinShow(NULL, NULL, true);
    13801418
    13811419        XEvent e;
    13821420        if (waitForX11Msg(e, ClientMessage))
    13831421        {
     1422            bool fAcceptDrop = false;
     1423
    13841424            int xRc;
    13851425            XClientMessageEvent *pEventClient = reinterpret_cast<XClientMessageEvent*>(&e);
     
    13911431            if (pEventClient->message_type == xAtom(XA_XdndEnter))
    13921432            {
    1393                 Atom type = None;
    1394                 int f;
    1395                 unsigned long n, a;
    1396                 unsigned char *ret = 0;
    1397 
     1433                LogFlowThisFunc(("XA_XdndEnter\n"));
     1434
     1435                /*
     1436                 * Prepare everything for our new window.
     1437                 */
    13981438                reset();
    13991439
    1400                 m_state = Dragging;
    1401                 m_wndCur = wndSelection;
     1440                /*
     1441                 * Update our state and the window handle to process.
     1442                 */
     1443                m_enmMode   = GH;
     1444                m_enmState  = Dragging;
     1445                m_wndCur    = wndSelection;
    14021446                Assert(m_wndCur == (Window)pEventClient->data.l[0]);
    1403 
    1404                 LogFlowThisFunc(("XA_XdndEnter\n"));
    14051447#ifdef DEBUG
    14061448                XWindowAttributes xwa;
     
    14181460                                         gX11->xAtomToString(pEventClient->data.l[i]).c_str()));
    14191461
    1420                         m_formats.append(pEventClient->data.l[i]);
     1462                        m_lstFormats.append(pEventClient->data.l[i]);
    14211463                    }
    14221464                }
    14231465                else
    14241466                {
    1425                     xRc = XGetWindowProperty(m_pDisplay, wndSelection,
    1426                                              xAtom(XA_XdndTypeList),
    1427                                              0, VBOX_MAX_XPROPERTIES,
    1428                                              False, XA_ATOM, &type, &f, &n, &a, &ret);
    1429                     if (   xRc == Success
    1430                         && n > 0
    1431                         && ret)
    1432                     {
    1433                         Atom *data = reinterpret_cast<Atom*>(ret);
    1434                         for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i)
    1435                         {
    1436                             LogFlowThisFunc(("Received format via XdndTypeList: %s\n",
    1437                                              gX11->xAtomToString(data[i]).c_str()));
    1438 
    1439                             m_formats.append(data[i]);
    1440                         }
    1441 
    1442                         XFree(ret);
    1443                     }
     1467                    rc = wndXDnDGetTypeList(wndSelection, m_lstFormats);
    14441468                }
    14451469
    1446                 /* Fetch the possible list of actions, if this property is set. */
    1447                 xRc = XGetWindowProperty(m_pDisplay, wndSelection,
    1448                                          xAtom(XA_XdndActionList),
    1449                                          0, VBOX_MAX_XPROPERTIES,
    1450                                          False, XA_ATOM, &type, &f, &n, &a, &ret);
    1451                 if (   xRc == Success
    1452                     && n > 0
    1453                     && ret)
    1454                 {
    1455                     Atom *data = reinterpret_cast<Atom*>(ret);
    1456                     for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i)
    1457                     {
    1458                         LogFlowThisFunc(("Received action: %s\n",
    1459                                          gX11->xAtomToString(data[i]).c_str()));
    1460 
    1461                         m_actions.append(data[i]);
    1462                     }
    1463 
    1464                     XFree(ret);
    1465                 }
    1466 
    14671470                /*
    1468                  * Acknowledge the event by sending a status message back to the window.
     1471                 * Fetch the actions.
    14691472                 */
    1470                 XClientMessageEvent m;
    1471                 RT_ZERO(m);
    1472                 m.type         = ClientMessage;
    1473                 m.display      = m_pDisplay;
    1474                 m.window       = m_wndCur;
    1475                 m.message_type = xAtom(XA_XdndStatus);
    1476                 m.format       = 32;
    1477                 m.data.l[0]    = m_wndProxy;
    1478                 m.data.l[1]    = RT_BIT(0); /* Accept the drop. */
    1479                 m.data.l[4]    = xAtom(XA_XdndActionCopy); /** @todo Make the accepted action configurable. */
    1480 
    1481                 xRc = XSendEvent(m_pDisplay, m_wndCur,
    1482                                  False, 0, reinterpret_cast<XEvent*>(&m));
    1483                 if (RT_UNLIKELY(xRc == 0))
    1484                 {
    1485                     logError(("Error sending enter XA_XdndStatus event to current window=%#x: %s\n",
    1486                               m_wndCur, gX11->xErrorToString(xRc).c_str()));
    1487                 }
     1473                rc = wndXDnDGetActionList(wndSelection, m_lstActions);
     1474               
     1475                fAcceptDrop = true;
    14881476            }
    14891477            /* Did the source tell us where the cursor currently is? */
     
    14911479            {
    14921480                LogFlowThisFunc(("XA_XdndPosition\n"));
    1493 
     1481                fAcceptDrop = true;
     1482            }
     1483            else if (pEventClient->message_type == xAtom(XA_XdndLeave))
     1484            {
     1485                LogFlowThisFunc(("XA_XdndLeave\n"));
     1486            }
     1487
     1488            if (fAcceptDrop)
     1489            {
    14941490                /* Reply with a XdndStatus message to tell the source whether
    14951491                 * the data can be dropped or not. */
     
    15091505                if (RT_UNLIKELY(xRc == 0))
    15101506                {
    1511                     logError(("Error sending position XA_XdndStatus event to current window=%#x: %s\n",
    1512                               m_wndCur, gX11->xErrorToString(xRc).c_str()));
     1507                    logError("Error sending position XA_XdndStatus event to current window=%#x: %s\n",
     1508                              m_wndCur, gX11->xErrorToString(xRc).c_str());
    15131509                }
    15141510            }
    1515             else if (pEventClient->message_type == xAtom(XA_XdndLeave))
    1516             {
    1517                 LogFlowThisFunc(("XA_XdndLeave\n"));
    1518             }
    15191511        }
    15201512
    15211513        /* Do we need to acknowledge at least one format to the host? */
    1522         if (!m_formats.isEmpty())
    1523         {
    1524             RTCString strFormats = gX11->xAtomListToString(m_formats);
     1514        if (!m_lstFormats.isEmpty())
     1515        {
     1516            RTCString strFormats = gX11->xAtomListToString(m_lstFormats);
    15251517            uint32_t uDefAction = DND_COPY_ACTION; /** @todo Handle default action! */
    1526             uint32_t uAllActions = toHGCMActions(m_actions);
     1518            uint32_t uAllActions = toHGCMActions(m_lstActions);
    15271519
    15281520            rc = VbglR3DnDGHAcknowledgePending(&m_dndCtx, uDefAction, uAllActions, strFormats.c_str());
     
    15381530int DragInstance::ghDropped(const RTCString &strFormat, uint32_t uAction)
    15391531{
    1540     LogFlowThisFunc(("strFormat=%s, uAction=%RU32\n", strFormat.c_str(), uAction));
    1541 
    1542     if (   m_mode  != GH
    1543         || m_state != Dragging)
     1532    LogFlowThisFunc(("mode=%RU32, state=%RU32, strFormat=%s, uAction=%RU32\n",
     1533                     m_enmMode, m_enmState, strFormat.c_str(), uAction));
     1534
     1535    if (   m_enmMode  != GH
     1536        || m_enmState != Dragging)
    15441537    {
    15451538        return VERR_INVALID_STATE;
     
    15481541    int rc = VINF_SUCCESS;
    15491542
    1550     m_state = Dropped;
     1543    m_enmState = Dropped;
    15511544
    15521545    /* Show the proxy window, so that the source will find it. */
     
    15811574    if (fDrop)
    15821575    {
     1576        LogFlowThisFunc(("XA_XdndDrop\n"));
     1577
    15831578        /* Request to convert the selection in the specific format and
    15841579         * place it to our proxy window as property. */
     
    16171612                                             AnyPropertyType,         /* Property type */
    16181613                                             &aPropType, &iPropFormat, &cItems, &cbRemaining, &pcData);
    1619                 if (RT_UNLIKELY(xRc == 0))
     1614                if (RT_UNLIKELY(xRc != Success))
    16201615                    LogFlowThisFunc(("Error getting XA_XdndSelection property of proxy window=%#x: %s\n",
    16211616                                     m_wndProxy, gX11->xErrorToString(xRc).c_str()));
     
    16711666                        m.data.l[0]    = m_wndProxy; /* Target window. */
    16721667                        m.data.l[1]    = 0; /* Don't accept the drop to not make the guest stuck. */
    1673                         m.data.l[2]    = RT_SUCCESS(rc) ? toX11Action(uAction) : None; /* Action used on success */
     1668                        m.data.l[2]    = RT_SUCCESS(rc) ? toAtomAction(uAction) : None; /* Action used on success */
    16741669
    16751670                        xRc = XSendEvent(m_pDisplay, wndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m));
     
    17161711                    if (RT_UNLIKELY(xRc == 0))
    17171712                    {
    1718                         logError(("Error sending XA_XdndFinished event to proxy window=%#x: %s\n",
    1719                                   m_wndProxy, gX11->xErrorToString(xRc).c_str()));
     1713                        logError("Error sending XA_XdndFinished event to proxy window=%#x: %s\n",
     1714                                  m_wndProxy, gX11->xErrorToString(xRc).c_str());
    17201715                    }
    17211716                }
     
    18701865    LogFlowThisFuncEnter();
    18711866
     1867#if 0
     1868    XTestGrabControl(m_pDisplay, False);
     1869#endif
     1870
     1871    /* Get the mouse pointer position and determine if we're on the same screen as the root window
     1872     * and returns the current child window beneath our mouse pointer, if any. */
    18721873    int iRootX, iRootY;
    18731874    int iChildX, iChildY;
    18741875    unsigned int iMask;
    18751876    Window wndRoot, wndChild;
    1876 
    1877 //    XTestGrabControl(m_pDisplay, False);
    1878 
    1879     /* Get the mouse pointer position and determine if we're on the same screen as the root window
    1880      * and returns the current child window beneath our mouse pointer, if any. */
    18811877    Bool fInRootWnd = XQueryPointer(m_pDisplay, m_wndRoot, &wndRoot, &wndChild,
    18821878                                    &iRootX, &iRootY,
     
    18971893    XRaiseWindow(m_pDisplay, m_wndProxy);
    18981894
    1899     /* Resize our proxy window so that it gets displayed right in center of our mouse cursor. */
    1900     const int iProxyX = RT_MAX(0, iRootX - 50);
    1901     const int iProxyY = RT_MAX(0, iRootY - 50);
    1902     LogFlowThisFunc(("iProxyX=%d, iProxyY=%d\n", iProxyX, iProxyY));
    1903     XMoveResizeWindow(m_pDisplay, m_wndProxy, iProxyX, iProxyY, 100, 100);
     1895    /* Spawn our proxy window over the entire screen, making it an easy drop target for the host's cursor. */
     1896    int iScreenID = XDefaultScreen(m_pDisplay);
     1897    XMoveResizeWindow(m_pDisplay, m_wndProxy, 0, 0, XDisplayWidth(m_pDisplay, iScreenID), XDisplayHeight(m_pDisplay, iScreenID));
     1898    /** @todo What about multiple screens? Test this! */
    19041899
    19051900    if (fMouseMove)
     
    19071902
    19081903    XSynchronize(m_pDisplay, False /* Disable sync */);
    1909 //    XTestGrabControl(m_pDisplay, True);
     1904
     1905#if 0
     1906    XTestGrabControl(m_pDisplay, True);
     1907#endif
    19101908
    19111909    return VINF_SUCCESS; /** @todo Add error checking. */
     
    19161914    LogFlowFuncEnter();
    19171915
     1916#ifndef VBOX_DND_DEBUG_WND
    19181917    XUnmapWindow(m_pDisplay, m_wndProxy);
     1918#endif
    19191919    m_eventQueue.clear();
    19201920
     
    19221922}
    19231923
    1924 /* Currently not used. */
    1925 /** @todo Is this function still needed? */
    1926 void DragInstance::registerForEvents(Window wndThis) const
    1927 {
    1928     if (wndThis == m_wndProxy)
    1929         return;
    1930 
    1931     LogFlowThisFunc(("%x\n", wndThis));
    1932 //    XSelectInput(m_pDisplay, w, Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask);//| SubstructureNotifyMask);
    1933 //    XSelectInput(m_pDisplay, w, ButtonMotionMask); //PointerMotionMask);
    1934     XSelectInput(m_pDisplay, wndThis, PointerMotionMask); //PointerMotionMask);
    1935     Window hRealRoot, hParent;
    1936     Window *phChildrenRaw = NULL;
    1937     unsigned cChildren;
    1938     if (XQueryTree(m_pDisplay, wndThis, &hRealRoot, &hParent, &phChildrenRaw, &cChildren))
    1939     {
    1940         for (unsigned i = 0; i < cChildren; ++i)
    1941             registerForEvents(phChildrenRaw[i]);
    1942         XFree(phChildrenRaw);
    1943     }
    1944 }
    1945 
    1946 void DragInstance::setActionsWindowProperty(Window wndThis, const RTCList<Atom> &lstActions) const
     1924void DragInstance::wndXDnDClearActionList(Window wndThis) const
     1925{
     1926    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList));
     1927}
     1928
     1929void DragInstance::wndXDnDClearTypeList(Window wndThis) const
     1930{
     1931    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndTypeList));
     1932}
     1933
     1934int DragInstance::wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const
     1935{
     1936    Atom iActType = None;
     1937    int iActFmt;
     1938    unsigned long cItems, cbData;
     1939    unsigned char *pcbData = NULL;
     1940
     1941    /* Fetch the possible list of actions, if this property is set. */
     1942    int xRc = XGetWindowProperty(m_pDisplay, wndThis,
     1943                                 xAtom(XA_XdndActionList),
     1944                                 0, VBOX_MAX_XPROPERTIES,
     1945                                 False, XA_ATOM, &iActType, &iActFmt, &cItems, &cbData, &pcbData);
     1946    if (xRc != Success)
     1947    {
     1948        LogFlowThisFunc(("Error getting XA_XdndActionList atoms from window=%#x: %s\n",
     1949                         wndThis, gX11->xErrorToString(xRc).c_str()));
     1950        return VERR_NOT_FOUND;
     1951    }
     1952
     1953    if (   cItems > 0
     1954        && pcbData)
     1955    {
     1956        Atom *paData = reinterpret_cast<Atom *>(pcbData);
     1957
     1958        for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, cItems); i++)
     1959        {
     1960            LogFlowThisFunc(("Received action: %s\n",
     1961                             gX11->xAtomToString(paData[i]).c_str()));
     1962
     1963            lstActions.append(paData[i]);
     1964        }
     1965
     1966        XFree(pcbData);
     1967    }
     1968
     1969    return VINF_SUCCESS;
     1970}
     1971
     1972int DragInstance::wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const
     1973{
     1974    Atom iActType = None;
     1975    int iActFmt;
     1976    unsigned long cItems, cbData;
     1977    unsigned char *pcbData = NULL;
     1978
     1979    int xRc = XGetWindowProperty(m_pDisplay, wndThis,
     1980                             xAtom(XA_XdndTypeList),
     1981                             0, VBOX_MAX_XPROPERTIES,
     1982                             False, XA_ATOM, &iActType, &iActFmt, &cItems, &cbData, &pcbData);
     1983    if (xRc != Success)
     1984    {
     1985        LogFlowThisFunc(("Error getting XA_XdndTypeList atoms from window=%#x: %s\n",
     1986                         wndThis, gX11->xErrorToString(xRc).c_str()));
     1987        return VERR_NOT_FOUND;
     1988    }
     1989
     1990    if (   cItems > 0
     1991        && pcbData)
     1992    {
     1993        Atom *paData = reinterpret_cast<Atom*>(pcbData);
     1994
     1995        for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, cItems); i++)
     1996        {
     1997            LogFlowThisFunc(("Received format via XdndTypeList: %s\n",
     1998                             gX11->xAtomToString(paData[i]).c_str()));
     1999
     2000            lstTypes.append(paData[i]);
     2001        }
     2002
     2003        XFree(pcbData);
     2004    }
     2005
     2006    return VINF_SUCCESS;
     2007}
     2008
     2009int DragInstance::wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const
    19472010{
    19482011    if (lstActions.isEmpty())
    1949         return;
     2012        return VINF_SUCCESS;
    19502013
    19512014    XChangeProperty(m_pDisplay, wndThis,
     
    19542017                    reinterpret_cast<const unsigned char*>(lstActions.raw()),
    19552018                    lstActions.size());
    1956 }
    1957 
    1958 void DragInstance::clearActionsWindowProperty(Window wndThis) const
    1959 {
    1960     XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList));
    1961 }
    1962 
    1963 void DragInstance::setFormatsWindowProperty(Window wndThis, Atom property) const
    1964 {
    1965     if (m_formats.isEmpty())
    1966         return;
     2019
     2020    return VINF_SUCCESS;
     2021}
     2022
     2023int DragInstance::wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const
     2024{
     2025    if (lstFormats.isEmpty())
     2026        return VINF_SUCCESS;
    19672027
    19682028    /* We support TARGETS and the data types. */
    1969     RTCList<Atom> targets(m_formats.size() + 1);
    1970     targets.append(xAtom(XA_TARGETS));
    1971     targets.append(m_formats);
     2029    VBoxDnDAtomList lstFormatsExt(lstFormats.size() + 1);
     2030    lstFormatsExt.append(xAtom(XA_TARGETS));
     2031    lstFormatsExt.append(lstFormats);
    19722032
    19732033    /* Add the property with the property data to the window. */
    19742034    XChangeProperty(m_pDisplay, wndThis, property,
    19752035                    XA_ATOM, 32, PropModeReplace,
    1976                     reinterpret_cast<const unsigned char*>(targets.raw()),
    1977                     targets.size());
    1978 }
    1979 
    1980 void DragInstance::clearFormatsWindowProperty(Window wndThis) const
    1981 {
    1982     XDeleteProperty(m_pDisplay, wndThis,
    1983                     xAtom(XA_XdndTypeList));
    1984 }
    1985 
    1986 RTCList<Atom> DragInstance::toAtomList(const RTCList<RTCString> &lstFormats) const
    1987 {
    1988     RTCList<Atom> atomList;
     2036                    reinterpret_cast<const unsigned char*>(lstFormatsExt.raw()),
     2037                    lstFormatsExt.size());
     2038
     2039    return VINF_SUCCESS;
     2040}
     2041
     2042int DragInstance::toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const
     2043{   
    19892044    for (size_t i = 0; i < lstFormats.size(); ++i)
    1990         atomList.append(XInternAtom(m_pDisplay, lstFormats.at(i).c_str(), False));
    1991 
    1992     return atomList;
    1993 }
    1994 
    1995 RTCList<Atom> DragInstance::toAtomList(void *pvData, uint32_t cbData) const
    1996 {
    1997     if (   !pvData
    1998         || !cbData)
    1999         return RTCList<Atom>();
    2000 
    2001     char *pszStr = (char*)pvData;
     2045        lstAtoms.append(XInternAtom(m_pDisplay, lstFormats.at(i).c_str(), False));
     2046
     2047    return VINF_SUCCESS;
     2048}
     2049
     2050int DragInstance::toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const
     2051{
     2052    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     2053    AssertReturn(cbData, VERR_INVALID_PARAMETER);
     2054
     2055    const char *pszStr = (char *)pvData;
    20022056    uint32_t cbStr = cbData;
     2057
     2058    int rc = VINF_SUCCESS;
    20032059
    20042060    RTCList<Atom> lstAtom;
     
    20102066         * even if the data isn't zero terminated. */
    20112067        char *pszTmp = RTStrDupN(pszStr, cbSize);
    2012         LogFlowThisFunc(("f: %s\n", pszTmp));
     2068        if (!pszTmp)
     2069        {
     2070            rc = VERR_NO_MEMORY;
     2071            break;
     2072        }
     2073
    20132074        lstAtom.append(XInternAtom(m_pDisplay, pszTmp, False));
    20142075        RTStrFree(pszTmp);
     2076
    20152077        pszStr  += cbSize + 1;
    20162078        cbStr   -= cbSize + 1;
    20172079    }
    20182080
    2019     return lstAtom;
     2081    return rc;
    20202082}
    20212083
    20222084/* static */
    2023 Atom DragInstance::toX11Action(uint32_t uAction)
     2085Atom DragInstance::toAtomAction(uint32_t uAction)
    20242086{
    20252087    /* Ignore is None. */
     
    20312093
    20322094/* static */
    2033 RTCList<Atom> DragInstance::toX11Actions(uint32_t uActions)
    2034 {
    2035     RTCList<Atom> actionList;
     2095int DragInstance::toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms)
     2096{
    20362097    if (hasDnDCopyAction(uActions))
    2037         actionList.append(xAtom(XA_XdndActionCopy));
     2098        lstAtoms.append(xAtom(XA_XdndActionCopy));
    20382099    if (hasDnDMoveAction(uActions))
    2039         actionList.append(xAtom(XA_XdndActionMove));
     2100        lstAtoms.append(xAtom(XA_XdndActionMove));
    20402101    if (hasDnDLinkAction(uActions))
    2041         actionList.append(xAtom(XA_XdndActionLink));
    2042 
    2043     return actionList;
     2102        lstAtoms.append(xAtom(XA_XdndActionLink));
     2103
     2104    return VINF_SUCCESS;
    20442105}
    20452106
     
    21622223                        if (e.hgcm.cbFormats)
    21632224                        {
    2164                             RTCList<RTCString> lstFormats
    2165                                 = RTCString(e.hgcm.pszFormats, e.hgcm.cbFormats - 1).split("\r\n");
    2166                             m_pCurDnD->hgEnter(lstFormats, e.hgcm.u.a.uAllActions);
    2167 
     2225                            RTCList<RTCString> lstFormats = RTCString(e.hgcm.pszFormats, e.hgcm.cbFormats - 1).split("\r\n");
     2226                            rc = m_pCurDnD->hgEnter(lstFormats, e.hgcm.u.a.uAllActions);
    21682227                            /* Enter is always followed by a move event. */
    21692228                        }
    2170                         else /* Invalid parameter, skip. */
     2229                        else
     2230                        {
     2231                            rc = VERR_INVALID_PARAMETER;
    21712232                            break;
     2233                        }
    21722234                        /* Not breaking unconditionally is intentional. See comment above. */
    21732235                    }
     
    21922254                        break;
    21932255                    }
     2256#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    21942257                    case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
    21952258                    {
    2196 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    21972259                        rc = m_pCurDnD->ghIsDnDPending();
    2198 #endif
    21992260                        break;
    22002261                    }
    22012262                    case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
    22022263                    {
    2203 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    22042264                        rc = m_pCurDnD->ghDropped(e.hgcm.pszFormats, e.hgcm.u.a.uDefAction);
    2205 #endif
    22062265                        break;
    22072266                    }
    2208 
     2267#endif
    22092268                    default:
     2269                    {
    22102270                        LogFlowThisFunc(("Unsupported message: %RU32\n", e.hgcm.uType));
    22112271                        rc = VERR_NOT_SUPPORTED;
    22122272                        break;
     2273                    }
    22132274                }
    22142275
    2215                 LogFlowFunc(("Returning %Rrc\n", rc));
     2276                if (RT_FAILURE(rc))
     2277                {
     2278                    m_pCurDnD->logError("Error: Processing message %RU32 failed with %Rrc\n", e.hgcm.uType, rc);
     2279
     2280                    /* If anything went wrong, do a reset and start over. */
     2281                    m_pCurDnD->reset();
     2282                }
    22162283
    22172284                /* Some messages require cleanup. */
     
    22502317                AssertMsgFailed(("Unknown event queue type %d\n", e.type));
    22512318
    2252             /* Make sure that any X11 requests have actually been sent to the
     2319            /*
     2320             * Make sure that any X11 requests have actually been sent to the
    22532321             * server, since we are waiting for responses using poll() on
    2254              * another thread which will not automatically trigger flushing. */
     2322             * another thread which will not automatically trigger flushing.
     2323             */
    22552324            XFlush(m_pDisplay);
    22562325
     
    22692338    if (RT_FAILURE(rc))
    22702339        VBClFatalError(("Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
     2340
    22712341    /* Connect to the x11 server. */
    22722342    m_pDisplay = XOpenDisplay(NULL);
     
    22922362        rc = RTThreadCreate(&m_hHGCMThread, hgcmEventThread, this,
    22932363                            0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
    2294                             "HGCM-NOTIFY");
     2364                            "dndHGCM");
    22952365        if (RT_FAILURE(rc))
    22962366            break;
     
    22992369        rc = RTThreadCreate(&m_hX11Thread, x11EventThread, this,
    23002370                            0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
    2301                             "X11-NOTIFY");
     2371                            "dndX11");
    23022372    } while (0);
    23032373
     
    23422412        {
    23432413            cMsgSkippedInvalid = 0; /* Reset skipped messages count. */
    2344 
    2345             LogFlowFunc(("Adding new HGCM event ...\n"));
    23462414            pThis->m_eventQueue.append(e);
    23472415
     
    24342502                }
    24352503#endif
    2436                 LogFlowFunc(("Adding new X11 event ...\n"));
    2437 
    24382504                /* At the moment we only have one drag instance. */
    24392505                DragInstance *pInstance = pThis->m_pCurDnD;
    2440 
    24412506                AssertPtr(pInstance);
     2507
    24422508                pInstance->onX11Event(e.x11);
    24432509            }
     
    24632529    struct VBCLSERVICE *pInterface;
    24642530    /** Magic number for sanity checks. */
    2465     uint32_t magic;
     2531    uint32_t uMagic;
    24662532    /** Service object. */
    24672533    DragAndDropService mDragAndDrop;
     
    24772543    struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
    24782544
    2479     if (pSelf->magic != DRAGANDDROPSERVICE_MAGIC)
     2545    if (pSelf->uMagic != DRAGANDDROPSERVICE_MAGIC)
    24802546        VBClFatalError(("Bad display service object!\n"));
    24812547    return pSelf->mDragAndDrop.run(fDaemonised);
     
    24982564};
    24992565
    2500 /* Static factory */
     2566/* Static factory. */
    25012567struct VBCLSERVICE **VBClGetDragAndDropService(void)
    25022568{
     
    25072573        VBClFatalError(("Out of memory\n"));
    25082574    pService->pInterface = &vbclDragAndDropInterface;
    2509     pService->magic = DRAGANDDROPSERVICE_MAGIC;
     2575    pService->uMagic = DRAGANDDROPSERVICE_MAGIC;
    25102576    new(&pService->mDragAndDrop) DragAndDropService();
    25112577    return &pService->pInterface;
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