Index: /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 55819)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 55820)
@@ -17,4 +17,5 @@
 
 #include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #include <X11/Xatom.h>
 #ifdef VBOX_DND_WITH_XTEST
@@ -287,5 +288,5 @@
 }
 
-/* Todo: make this iterative */
+/** todo Make this iterative. */
 Window xHelpers::applicationWindowBelowCursor(Window wndParent) const
 {
@@ -341,4 +342,6 @@
 #endif
 
+#define VBoxDnDAtomList RTCList<Atom> 
+
 /* For now only one DragInstance will exits when the app is running. In the
  * future the support for having more than one drag and drop operation supported at the
@@ -353,5 +356,6 @@
         Initialized,
         Dragging,
-        Dropped
+        Dropped,
+        State_32BIT_Hack = 0x7fffffff
     };
 
@@ -360,5 +364,6 @@
         Unknown = 0,
         HG,
-        GH
+        GH,
+        Mode_32Bit_Hack = 0x7fffffff
     };
 
@@ -399,17 +404,18 @@
     int proxyWinShow(int *piRootX = NULL, int *piRootY = NULL, bool fMouseMove = false) const;
     int proxyWinHide(void);
-    void registerForEvents(Window w) const;
-
-    void setActionsWindowProperty(Window wndThis, const RTCList<Atom> &lstActions) const;
-    void clearActionsWindowProperty(Window wndThis) const;
-    void setFormatsWindowProperty(Window wndThis, Atom property) const;
-    void clearFormatsWindowProperty(Window wndThis) const;
-
-    RTCList<Atom>        toAtomList(const RTCList<RTCString> &lstFormats) const;
-    RTCList<Atom>        toAtomList(void *pvData, uint32_t cbData) const;
-    static Atom          toX11Action(uint32_t uAction);
-    static RTCList<Atom> toX11Actions(uint32_t uActions);
-    static uint32_t      toHGCMAction(Atom atom);
-    static uint32_t      toHGCMActions(const RTCList<Atom> &actionsList);
+
+    void wndXDnDClearActionList(Window wndThis) const;
+    void wndXDnDClearTypeList(Window wndThis) const;
+    int wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const;
+    int wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const;
+    int wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const;
+    int wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const;
+
+    int                    toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const;
+    int                    toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const;
+    static Atom            toAtomAction(uint32_t uAction);
+    static int             toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms);
+    static uint32_t        toHGCMAction(Atom atom);
+    static uint32_t        toHGCMActions(const RTCList<Atom> &actionsList);
 
 protected:
@@ -425,13 +431,13 @@
     Window                      m_wndCur;
     long                        m_curVer;
-    RTCList<Atom>               m_formats;
-    RTCList<Atom>               m_actions;
+    VBoxDnDAtomList             m_lstFormats;
+    VBoxDnDAtomList             m_lstActions;
     /** Deferred host to guest selection event for sending to the
      *  target window as soon as data from the host arrived. */
     XEvent                      m_eventHgSelection;
     /** Current operation mode. */
-    Mode                        m_mode;
+    Mode                        m_enmMode;
     /** Current state of operation mode. */
-    State                       m_state;
+    State                       m_enmState;
     /** The instance's own X event queue. */
     RTCMTList<XEvent>           m_eventQueue;
@@ -467,4 +473,5 @@
 
 private:
+
     int x11DragAndDropInit(void);
     static int hgcmEventThread(RTTHREAD hThread, void *pvUser);
@@ -472,23 +479,4 @@
 
     void clearEventQueue();
-
-    /* Usually XCheckMaskEvent could be used for querying selected x11 events.
-     * Unfortunately this doesn't work exactly with the events we need. So we
-     * use this predicate method below and XCheckIfEvent. */
-    static bool isDnDRespondEvent(Display * /* pDisplay */, XEvent *pEvent, char *pUser)
-    {
-        if (!pEvent)
-            return false;
-        if (   pEvent->type == SelectionClear
-            || pEvent->type == ClientMessage
-            || pEvent->type == MotionNotify
-            || pEvent->type == SelectionRequest)
-//            || (   pEvent->type == ClientMessage
-//                && reinterpret_cast<XClientMessageEvent*>(pEvent)->window == reinterpret_cast<Window>(pUser))
-//            || (   pEvent->type == SelectionRequest
-//                && reinterpret_cast<XSelectionRequestEvent*>(pEvent)->requestor == reinterpret_cast<Window>(pUser)))
-            return true;
-        return false;
-    }
 
     /* Private member vars */
@@ -524,6 +512,6 @@
     , m_wndCur(0)
     , m_curVer(-1)
-    , m_mode(Unknown)
-    , m_state(Uninitialized)
+    , m_enmMode(Unknown)
+    , m_enmState(Uninitialized)
 {
     uninit();
@@ -538,5 +526,5 @@
     VbglR3DnDDisconnect(&m_dndCtx);
 
-    m_state    = Uninitialized;
+    m_enmState    = Uninitialized;
     m_screenId = -1;
     m_pScreen  = 0;
@@ -557,15 +545,15 @@
         XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), None, CurrentTime);
 
-    /* Clear any other DnD specific data on the proxy win. */
-    clearFormatsWindowProperty(m_wndProxy);
-    clearActionsWindowProperty(m_wndProxy);
+    /* Clear any other DnD specific data on the proxy window. */
+    wndXDnDClearTypeList(m_wndProxy);
+    wndXDnDClearActionList(m_wndProxy);
 
     /* Reset the internal state. */
-    m_actions.clear();
-    m_formats.clear();
-    m_wndCur = 0;
-    m_curVer = -1;
-    m_state  = Initialized;
-    m_mode   = Unknown;
+    m_lstActions.clear();
+    m_lstFormats.clear();
+    m_wndCur    = 0;
+    m_curVer    = -1;
+    m_enmState  = Initialized;
+    m_enmMode   = Unknown;
     m_eventQueue.clear();
 }
@@ -599,12 +587,15 @@
             break;
         }
+#if 0
         /* Get the screen number from the x11 server. */
-//        pDrag->screen = ScreenOfDisplay(m_pDisplay, u32ScreenId);
-//        if (!pDrag->screen)
-//        {
-//            rc = VERR_GENERAL_FAILURE;
-//            break;
-//        }
+        pDrag->screen = ScreenOfDisplay(m_pDisplay, u32ScreenId);
+        if (!pDrag->screen)
+        {
+            rc = VERR_GENERAL_FAILURE;
+            break;
+        }
+#endif
         m_screenId = u32ScreenId;
+
         /* Now query the corresponding root window of this screen. */
         m_wndRoot = RootWindow(m_pDisplay, m_screenId);
@@ -624,9 +615,22 @@
         attr.event_mask            =   EnterWindowMask  | LeaveWindowMask
                                      | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
+        attr.override_redirect     = True;
         attr.do_not_propagate_mask = NoEventMask;
-        attr.override_redirect     = True;
 #ifdef VBOX_DND_DEBUG_WND
-        attr.background_pixel      = WhitePixel(m_pDisplay, m_screenId);
-#endif
+        attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenId);
+        attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenId); 
+        m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                     /* Parent */,
+                                   100, 100,                                 /* Position */
+                                   100, 100,                                 /* Width + height */
+                                   2,                                        /* Border width */
+                                   CopyFromParent,                           /* Depth */
+                                   InputOutput,                              /* Class */
+                                   CopyFromParent,                           /* Visual */
+                                     CWBackPixel 
+                                   | CWBorderPixel
+                                   | CWOverrideRedirect
+                                   | CWDontPropagate,                        /* Value mask */
+                                   &attr);                                   /* Attributes for value mask */       
+#else
         m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                 /* Parent */,
                                    0, 0,                                 /* Position */
@@ -637,5 +641,6 @@
                                    CopyFromParent,                       /* Visual */
                                    CWOverrideRedirect | CWDontPropagate, /* Value mask */
-                                   &attr                                 /* Attributes for value mask */);
+                                   &attr);                               /* Attributes for value mask */
+#endif
         if (!m_wndProxy)
         {
@@ -645,6 +650,11 @@
         }
 
-        LogFlowThisFunc(("Created proxy window 0x%x at m_wndRoot=0x%x ...\n",
-                         m_wndProxy, m_wndRoot));
+#ifdef VBOX_DND_DEBUG_WND
+        XFlush(m_pDisplay);
+        XMapWindow(m_pDisplay, m_wndProxy);
+        XRaiseWindow(m_pDisplay, m_wndProxy);
+        XFlush(m_pDisplay);
+#endif
+        LogFlowThisFunc(("Created proxy window 0x%x at m_wndRoot=0x%x ...\n", m_wndProxy, m_wndRoot));
 
         /* Set the window's name for easier lookup. */
@@ -659,5 +669,5 @@
     if (RT_SUCCESS(rc))
     {
-        m_state = Initialized;
+        m_enmState = Initialized;
     }
     else
@@ -688,23 +698,26 @@
     AssertReturn(e.type == ClientMessage, VERR_INVALID_PARAMETER);
 
-    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
-    LogFlowThisFunc(("Event wnd=%#x, msg=%s\n",
-                     e.xclient.window,
-                     xAtomToString(e.xclient.message_type).c_str()));
+    LogFlowThisFunc(("mode=%d, state=%d\n", m_enmMode, m_enmState));
+    LogFlowThisFunc(("Event wnd=%#x, msg=%s\n", e.xclient.window, xAtomToString(e.xclient.message_type).c_str()));
+
     int rc;
 
-    switch (m_mode)
+    switch (m_enmMode)
     {
         case HG:
         {
-            /* Client messages are used to inform us about the status of a XdndAware
-             * window, in response of some events we send to them. */
+            /* 
+             * Client messages are used to inform us about the status of a XdndAware
+             * window, in response of some events we send to them. 
+             */ 
             if (   e.xclient.message_type == xAtom(XA_XdndStatus)
                 && m_wndCur               == static_cast<Window>(e.xclient.data.l[0]))
             {
-                /* The XdndStatus message tell us if the window will accept the DnD
+                /* 
+                 * The XdndStatus message tell us if the window will accept the DnD
                  * event and with which action. We immediately send this info down to
-                 * the host as a response of a previous DnD message. */
-                LogFlowThisFunc(("XA_XdndStatus wnd=%#x, accept=%RTbool, action=%s\n",
+                 * the host as a response of a previous DnD message. 
+                 */ 
+                LogFlowThisFunc(("XA_XdndStatus: wnd=%#x, accept=%RTbool, action=%s\n",
                                  e.xclient.data.l[0],
                                  ASMBitTest(&e.xclient.data.l[1], 0),
@@ -722,10 +735,11 @@
                 rc = VINF_SUCCESS;
 
-                /* This message is send on a un/successful DnD drop request. */
+                /* This message is sent on an un/successful DnD drop request. */
                 LogFlowThisFunc(("XA_XdndFinished: wnd=%#x, success=%RTbool, action=%s\n",
                                  e.xclient.data.l[0],
                                  ASMBitTest(&e.xclient.data.l[1], 0),
                                  xAtomToString(e.xclient.data.l[2]).c_str()));
-                reset();
+
+                proxyWinHide();
             }
             else
@@ -740,9 +754,40 @@
 
         case GH:
-        {
-            LogFlowThisFunc(("Enqueuing ClientMessage\n"));
-
+        case Unknown: /* Mode not set (yet), just add what we got. */
+        {
             m_eventQueue.append(e);
             rc = RTSemEventSignal(m_hEventSem);
+            break;
+        }
+       
+        default:
+        {
+            AssertMsgFailed(("Drag and drop mode not implemented: %RU32\n", m_enmMode));
+            rc = VERR_NOT_IMPLEMENTED;
+            break;
+        }
+    }
+
+    LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
+    return rc;
+}
+
+int DragInstance::onX11SelectionNotify(const XEvent &e)
+{
+    AssertReturn(e.type == SelectionNotify, VERR_INVALID_PARAMETER);
+
+    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_enmMode, m_enmState));
+
+    int rc;
+
+    switch (m_enmMode)
+    {
+        case GH:
+        {
+            if (m_enmState == Dropped)
+            {
+                m_eventQueue.append(e);
+                rc = RTSemEventSignal(m_hEventSem);
+            }
             break;
         }
@@ -761,45 +806,9 @@
 }
 
-int DragInstance::onX11SelectionNotify(const XEvent &e)
-{
-    AssertReturn(e.type == SelectionNotify, VERR_INVALID_PARAMETER);
-
-    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
-
-    int rc = VINF_SUCCESS;
-
-    switch (m_mode)
-    {
-        case GH:
-        {
-            if (m_state == Dropped)
-            {
-                LogFlowThisFunc(("Enqueuing SelectionNotify\n"));
-
-                m_eventQueue.append(e);
-                rc = RTSemEventSignal(m_hEventSem);
-            }
-            break;
-        }
-
-        default:
-        {
-            LogFlowThisFunc(("Unhandled: wnd=%#x, msg=%s\n",
-                             e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str()));
-            rc = VERR_INVALID_STATE;
-            break;
-        }
-    }
-
-    LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
-    return rc;
-}
-
-
 int DragInstance::onX11SelectionRequest(const XEvent &e)
 {
     AssertReturn(e.type == SelectionRequest, VERR_INVALID_PARAMETER);
 
-    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_mode, m_state));
+    LogFlowThisFunc(("m_mode=%d, m_state=%d\n", m_enmMode, m_enmState));
     LogFlowThisFunc(("Event owner=%#x, requestor=%#x, selection=%s, target=%s, prop=%s, time=%u\n",
                      e.xselectionrequest.owner,
@@ -811,5 +820,9 @@
     int rc;
 
-    switch (m_mode)
+    bool fSendEvent  = false;
+    Atom atmTarget   = None;
+    Atom atmProperty = None;
+
+    switch (m_enmMode)
     {
         case HG:
@@ -832,6 +845,56 @@
                 /* If so, set the window property with the formats on the requestor
                  * window. */
-                setFormatsWindowProperty(e.xselectionrequest.requestor, e.xselectionrequest.property);
-
+                rc = wndXDnDSetFormatList(e.xselectionrequest.requestor, e.xselectionrequest.property, m_lstFormats);
+                if (RT_SUCCESS(rc)) 
+                {
+                    atmTarget   = e.xselectionrequest.target;
+                    atmProperty = e.xselectionrequest.property;
+
+                    fSendEvent  = true;
+                }
+            }
+            /* Is the requestor asking for a specific MIME type (we support)? */
+            else if (m_lstFormats.contains(e.xselectionrequest.target))
+            {
+                LogFlowThisFunc(("wnd=%#x asking for data, format=%s\n",
+                                 e.xselectionrequest.requestor, xAtomToString(e.xselectionrequest.target).c_str()));
+
+                /* If so, we need to inform the host about this request. Save the
+                 * selection request event for later use. */
+                if (m_enmState != Dropped)
+                {
+                    LogFlowThisFunc(("Wrong state (%RU32), refusing request\n", m_enmState));
+
+                    atmTarget   = None;
+                    atmProperty = e.xselectionrequest.property;
+
+                    fSendEvent  = true;
+                }
+                else
+                {
+                    LogFlowThisFunc(("Saving selection notify message\n"));
+
+                    memcpy(&m_eventHgSelection, &e, sizeof(XEvent));
+
+                    RTCString strFormat = xAtomToString(e.xselectionrequest.target);
+                    Assert(strFormat.isNotEmpty());
+
+                    rc = VbglR3DnDHGRequestData(&m_dndCtx, strFormat.c_str());
+                    LogFlowThisFunc(("Requested data from host as \"%s\", rc=%Rrc\n", strFormat.c_str(), rc));
+                }
+            }
+            /* Anything else. */
+            else
+            {
+                LogFlowThisFunc(("Refusing unknown command\n"));
+
+                /* We don't understand this request message and therefore answer with an
+                 * refusal messages. */
+                fSendEvent = true;
+            }
+
+            if (   RT_SUCCESS(rc)
+                && fSendEvent)
+            {
                 XEvent s;
                 RT_ZERO(s);
@@ -841,71 +904,12 @@
                 s.xselection.selection = e.xselectionrequest.selection;
                 s.xselection.requestor = e.xselectionrequest.requestor;
-                s.xselection.target    = e.xselectionrequest.target;
-                s.xselection.property  = e.xselectionrequest.property;
+                s.xselection.target    = atmTarget;
+                s.xselection.property  = atmProperty;
 
                 int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
                 if (RT_UNLIKELY(xRc == 0))
-                    LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
+                    logError("Error sending SelectionNotify(1) event to wnd=%#x: %s\n", e.xselectionrequest.requestor,
+                             gX11->xErrorToString(xRc).c_str());
             }
-            /* Is the requestor asking for a specific MIME type (we support)? */
-            else if (m_formats.contains(e.xselectionrequest.target))
-            {
-                LogFlowThisFunc(("wnd=%#x asking for data, format=%s\n",
-                                 e.xselectionrequest.requestor, xAtomToString(e.xselectionrequest.target).c_str()));
-
-                /* If so, we need to inform the host about this request. Save the
-                 * selection request event for later use. */
-                if (   m_state != Dropped)
-                    //        || m_curWin != e.xselectionrequest.requestor)
-                {
-                    LogFlowThisFunc(("Wrong state, refusing request\n"));
-
-                    XEvent s;
-                    RT_ZERO(s);
-                    s.xselection.type      = SelectionNotify;
-                    s.xselection.display   = e.xselection.display;
-                    s.xselection.time      = e.xselectionrequest.time;
-                    s.xselection.selection = e.xselectionrequest.selection;
-                    s.xselection.requestor = e.xselectionrequest.requestor;
-                    s.xselection.target    = None;
-                    s.xselection.property  = e.xselectionrequest.property;
-
-                    int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
-                    if (RT_UNLIKELY(xRc == 0))
-                        LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
-                }
-                else
-                {
-                    LogFlowThisFunc(("Saving selection notify message\n"));
-
-                    memcpy(&m_eventHgSelection, &e, sizeof(XEvent));
-
-                    RTCString strFormat = xAtomToString(e.xselectionrequest.target);
-                    Assert(strFormat.isNotEmpty());
-                    rc = VbglR3DnDHGRequestData(&m_dndCtx, strFormat.c_str());
-                    LogFlowThisFunc(("Requesting data from host as \"%s\", rc=%Rrc\n",
-                                     strFormat.c_str(), rc));
-                }
-            }
-            /* Anything else. */
-            else
-            {
-                LogFlowThisFunc(("Refusing unknown command\n"));
-
-                /* We don't understand this request message and therefore answer with an
-                 * refusal messages. */
-                XEvent s;
-                RT_ZERO(s);
-                s.xselection.type      = SelectionNotify;
-                s.xselection.display   = e.xselection.display;
-                s.xselection.time      = e.xselectionrequest.time;
-                s.xselection.selection = e.xselectionrequest.selection;
-                s.xselection.requestor = e.xselectionrequest.requestor;
-                s.xselection.target    = None; /* default is refusing */
-                s.xselection.property  = None; /* default is refusing */
-                int xRc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s);
-                if (RT_UNLIKELY(xRc == 0))
-                    LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor));
-            }
 
             break;
@@ -914,5 +918,5 @@
         default:
         {
-            LogFlowThisFunc(("Unhandled: wnd=%#x, msg=%s\n",
+            LogFlowThisFunc(("Unhandled message for wnd=%#x: %s\n",
                              e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str()));
             rc = VERR_INVALID_STATE;
@@ -974,6 +978,5 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
-bool DragInstance::waitForX11Msg(XEvent &evX, int iType,
-                                 RTMSINTERVAL uTimeoutMS /* = 100 */)
+bool DragInstance::waitForX11Msg(XEvent &evX, int iType, RTMSINTERVAL uTimeoutMS /* = 100 */)
 {
     LogFlowThisFunc(("iType=%d, uTimeoutMS=%RU32, cEventQueue=%zu\n", iType, uTimeoutMS, m_eventQueue.size()));
@@ -1070,6 +1073,5 @@
     while (RTTimeMilliTS() - uiStart < uTimeoutMS);
 
-    LogFlowThisFunc(("Returning fFound=%RTbool, msRuntime=%RU64\n",
-                     fFound, RTTimeMilliTS() - uiStart));
+    LogFlowThisFunc(("Returning fFound=%RTbool, msRuntime=%RU64\n", fFound, RTTimeMilliTS() - uiStart));
     return fFound;
 }
@@ -1082,5 +1084,7 @@
 int DragInstance::hgEnter(const RTCList<RTCString> &formats, uint32_t uActions)
 {
-    if (m_mode != Unknown) 
+    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
+
+    if (m_enmMode != Unknown) 
         return VERR_INVALID_STATE;
 
@@ -1094,29 +1098,46 @@
 #endif
 
-    m_formats = toAtomList(formats);
-
-    /* If we have more than 3 formats we have to use the type list extension. */
-    if (m_formats.size() > 3)
-        setFormatsWindowProperty(m_wndProxy, xAtom(XA_XdndTypeList));
-
-    /* Announce the possible actions */
-    setActionsWindowProperty(m_wndProxy, toX11Actions(uActions));
-
-    /* Set the DnD selection owner to our window. */
-    XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy, CurrentTime);
-
-    m_mode  = HG;
-    m_state = Dragging;
-
-    return VINF_SUCCESS;
+    int rc;
+
+    do
+    {
+        rc = toAtomList(formats, m_lstFormats);
+        if (RT_FAILURE(rc))
+            break;
+
+        /* If we have more than 3 formats we have to use the type list extension. */
+        if (m_lstFormats.size() > 3)
+        {
+            rc = wndXDnDSetFormatList(m_wndProxy, xAtom(XA_XdndTypeList), m_lstFormats);
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        /* Announce the possible actions. */
+        VBoxDnDAtomList lstActions;
+        rc = toAtomActions(uActions, lstActions);
+        if (RT_FAILURE(rc))
+            break;
+        rc = wndXDnDSetActionList(m_wndProxy, lstActions);
+
+        /* Set the DnD selection owner to our window. */
+        XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy, CurrentTime);
+
+        m_enmMode  = HG;
+        m_enmState = Dragging;
+
+    } while (0);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
 int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
 {
-    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n",
-                     u32xPos, u32yPos, uAction));
-
-    if (   m_mode  != HG
-        || m_state != Dragging)
+    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
+    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uAction));
+
+    if (   m_enmMode  != HG
+        || m_enmState != Dragging)
     {
         return VERR_INVALID_STATE;
@@ -1156,5 +1177,14 @@
             {
                 newVer = reinterpret_cast<long*>(pcData)[0];
-                LogFlowThisFunc(("wndCursor=%#x, XdndAware=%ld\n", wndCursor, newVer));
+
+                LogFlowThisFunc(("Current: wndCursor=%#x, XdndAware=%ld\n", wndCursor, newVer));               
+#ifdef DEBUG
+                XTextProperty propName;
+                if (XGetWMName(m_pDisplay, wndCursor, &propName))
+                {
+                    LogFlowThisFunc(("\tTitle: %s\n", propName.value));
+                    XFree(propName.value);
+                }
+#endif
             }
 
@@ -1164,12 +1194,13 @@
 
     /*
-     * Is the window under the cursor another one than our current one?
+     * Is the window under the cursor another one than our current one? 
+     * Cancel the current drop. 
      */
     if (   wndCursor != m_wndCur
         && m_curVer  != -1)
     {
-        LogFlowThisFunc(("Leaving window=%#x\n", m_wndCur));
-
-        /* We left the current XdndAware window. Announce this to the window. */
+        LogFlowThisFunc(("XA_XdndLeave: window=%#x\n", m_wndCur));
+
+        /* We left the current XdndAware window. Announce this to the current indow. */
         XClientMessageEvent m;
         RT_ZERO(m);
@@ -1179,9 +1210,9 @@
         m.message_type = xAtom(XA_XdndLeave);
         m.format       = 32;
-        m.data.l[0]    = m_wndProxy;
+        m.data.l[0]    = m_wndProxy;                    /* Source window. */
 
         xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (RT_UNLIKELY(xRc == 0))
-            logError("DnD: Error sending XA_XdndLeave event to old window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
+            logError("Error sending XA_XdndLeave event to old window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
     }
 
@@ -1192,5 +1223,5 @@
         && newVer    != -1)
     {
-        LogFlowThisFunc(("Entering window=%#x\n", wndCursor));
+        LogFlowThisFunc(("XA_XdndEnter: window=%#x\n", wndCursor));
 
         /*
@@ -1207,23 +1238,29 @@
         m.message_type = xAtom(XA_XdndEnter);
         m.format       = 32;
-        m.data.l[0]    = m_wndProxy;
-        m.data.l[1]    = RT_MAKE_U32_FROM_U8(m_formats.size() > 3 ? 1 : 0, 0, 0, RT_MIN(VBOX_XDND_VERSION, newVer));
-        m.data.l[2]    = m_formats.value(0, None);
-        m.data.l[3]    = m_formats.value(1, None);
-        m.data.l[4]    = m_formats.value(2, None);
+        m.data.l[0]    = m_wndProxy;                    /* Source window. */
+        m.data.l[1]    = RT_MAKE_U32_FROM_U8(
+                         /* Bit 0 is set if the source supports more than three data types. */
+                         m_lstFormats.size() > 3 ? 1 : 0,
+                         /* Reserved for future use. */
+                         0, 0,
+                         /* Protocol version to use. */
+                         RT_MIN(VBOX_XDND_VERSION, newVer));
+        m.data.l[2]    = m_lstFormats.value(0, None);   /* First data type to use. */
+        m.data.l[3]    = m_lstFormats.value(1, None);   /* Second data type to use. */
+        m.data.l[4]    = m_lstFormats.value(2, None);   /* Third data type to use. */
 
         xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (RT_UNLIKELY(xRc == 0))
-            logError("Error sending XA_XdndEnter event to new window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
+            logError("Error sending XA_XdndEnter event to window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
     }
 
     if (newVer != -1)
     {
-        LogFlowThisFunc(("Moving window=%#x, xPos=%RU32, yPos=%RU32\n", wndCursor, u32xPos, u32yPos));
+        LogFlowThisFunc(("XA_XdndPosition: xPos=%RU32, yPos=%RU32 to window=%#x\n", u32xPos, u32yPos, wndCursor));
 
         /*
          * Send a XdndPosition event with the proposed action to the guest.
          */
-        Atom pa = toX11Action(uAction);
+        Atom pa = toAtomAction(uAction);
         LogFlowThisFunc(("strAction=%s\n", xAtomToString(pa).c_str()));
 
@@ -1235,12 +1272,12 @@
         m.message_type = xAtom(XA_XdndPosition);
         m.format       = 32;
-        m.data.l[0]    = m_wndProxy;
-        m.data.l[2]    = RT_MAKE_U32(u32yPos, u32xPos);
-        m.data.l[3]    = CurrentTime;
-        m.data.l[4]    = pa;
+        m.data.l[0]    = m_wndProxy;                    /* X window ID of source window. */
+        m.data.l[2]    = RT_MAKE_U32(u32yPos, u32xPos); /* Cursor coordinates relative to the root window. */
+        m.data.l[3]    = CurrentTime;                   /* Timestamp for retrieving data. */
+        m.data.l[4]    = pa;                            /* Actions requested by the user. */
 
         xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (RT_UNLIKELY(xRc == 0))
-            logError(("Error sending XA_XdndPosition event to current window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str()));
+            logError("Error sending XA_XdndPosition event to current window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
     }
 
@@ -1251,7 +1288,9 @@
         rc = VbglR3DnDHGAcknowledgeOperation(&m_dndCtx, DND_IGNORE_ACTION);
     }
-
-    m_wndCur = wndCursor;
-    m_curVer = RT_MIN(VBOX_XDND_VERSION, newVer);
+    else
+    {
+        m_wndCur = wndCursor;
+        m_curVer = RT_MIN(VBOX_XDND_VERSION, newVer);
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -1261,9 +1300,8 @@
 int DragInstance::hgDrop(void)
 {
-    LogFlowThisFunc(("wndCur=%#x, mMode=%RU32, mState=%RU32\n",
-                     m_wndCur, m_mode, m_state));
-
-    if (   m_mode  != HG
-        || m_state != Dragging)
+    LogFlowThisFunc(("wndCur=%#x, wndProxy=%#x, mode=%RU32, state=%RU32\n", m_wndProxy, m_wndCur, m_enmMode, m_enmState));
+
+    if (   m_enmMode  != HG
+        || m_enmState != Dragging)
     {
         return VERR_INVALID_STATE;
@@ -1272,5 +1310,7 @@
     int rc = VINF_SUCCESS;
 
-    /* Send a drop event to the current window and reset our DnD status. */
+    /* 
+     * Send a drop event to the current window and reset our DnD status.
+     */
     XClientMessageEvent m;
     RT_ZERO(m);
@@ -1280,15 +1320,15 @@
     m.message_type = xAtom(XA_XdndDrop);
     m.format       = 32;
-    m.data.l[0]    = m_wndProxy;
-    m.data.l[2]    = CurrentTime;
+    m.data.l[0]    = m_wndProxy;                        /* Source window. */
+    m.data.l[2]    = CurrentTime;                       /* Timestamp. */
 
     int xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
     if (RT_UNLIKELY(xRc == 0))
-        logError(("Error sending XA_XdndDrop event to current window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str()));
+        logError("Error sending XA_XdndDrop event to current window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
 
     m_wndCur = None;
     m_curVer = -1;
 
-    m_state = Dropped;
+    m_enmState = Dropped;
 
     LogFlowFuncLeaveRC(rc);
@@ -1298,6 +1338,8 @@
 int DragInstance::hgDataReceived(void *pvData, uint32_t cbData)
 {
-    if (   m_mode  != HG
-        || m_state != Dropped)
+    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
+
+    if (   m_enmMode  != HG
+        || m_enmState != Dropped)
     {
         return VERR_INVALID_STATE;
@@ -1310,8 +1352,5 @@
     }
 
-    if (RT_UNLIKELY(m_state != Dropped))
-        return VERR_INVALID_STATE;
-
-    /* Make a copy of the data. The xserver will become the new owner. */
+    /* Make a copy of the data. The X server will become the new owner. */
     void *pvNewData = RTMemAlloc(cbData);
     if (RT_UNLIKELY(!pvNewData))
@@ -1321,5 +1360,5 @@
 
     /*
-     * The host send us the DnD data in the requested mime type. This allows us
+     * The host has sent us the DnD data in the requested MIME type. This allows us
      * to fill the XdndSelection property of the requestor window with the data
      * and afterwards inform the host about the new status.
@@ -1349,8 +1388,9 @@
     int xRc = XSendEvent(s.xselection.display, s.xselection.requestor, True, 0, &s);
     if (RT_UNLIKELY(xRc == 0))
-    {
-        logError(("Error sending SelectionNotify event to window=%#x: %s\n",
-                  s.xselection.requestor, gX11->xErrorToString(xRc).c_str()));
-    }
+        logError("Error sending SelectionNotify(2) event to window=%#x: %s\n",
+                 s.xselection.requestor, gX11->xErrorToString(xRc).c_str());
+
+    /* We're finally done, reset. */
+    reset();
 
     return VINF_SUCCESS;
@@ -1360,7 +1400,7 @@
 int DragInstance::ghIsDnDPending(void)
 {
-    LogFlowFuncEnter();
-
-    if (m_mode == HG)
+    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
+
+    if (m_enmMode == HG)
         return VERR_INVALID_STATE;
 
@@ -1373,13 +1413,13 @@
         && wndSelection != m_wndProxy)
     {
-        m_mode  = GH;
-
         /* Map the window on the current cursor position, which should provoke
          * an XdndEnter event. */
-        proxyWinShow();
+        proxyWinShow(NULL, NULL, true);
 
         XEvent e;
         if (waitForX11Msg(e, ClientMessage))
         {
+            bool fAcceptDrop = false;
+
             int xRc;
             XClientMessageEvent *pEventClient = reinterpret_cast<XClientMessageEvent*>(&e);
@@ -1391,16 +1431,18 @@
             if (pEventClient->message_type == xAtom(XA_XdndEnter))
             {
-                Atom type = None;
-                int f;
-                unsigned long n, a;
-                unsigned char *ret = 0;
-
+                LogFlowThisFunc(("XA_XdndEnter\n"));
+
+                /*
+                 * Prepare everything for our new window.
+                 */
                 reset();
 
-                m_state = Dragging;
-                m_wndCur = wndSelection;
+                /*
+                 * Update our state and the window handle to process.
+                 */
+                m_enmMode   = GH;
+                m_enmState  = Dragging;
+                m_wndCur    = wndSelection;
                 Assert(m_wndCur == (Window)pEventClient->data.l[0]);
-
-                LogFlowThisFunc(("XA_XdndEnter\n"));
 #ifdef DEBUG
                 XWindowAttributes xwa;
@@ -1418,72 +1460,18 @@
                                          gX11->xAtomToString(pEventClient->data.l[i]).c_str()));
 
-                        m_formats.append(pEventClient->data.l[i]);
+                        m_lstFormats.append(pEventClient->data.l[i]);
                     }
                 }
                 else
                 {
-                    xRc = XGetWindowProperty(m_pDisplay, wndSelection,
-                                             xAtom(XA_XdndTypeList),
-                                             0, VBOX_MAX_XPROPERTIES,
-                                             False, XA_ATOM, &type, &f, &n, &a, &ret);
-                    if (   xRc == Success
-                        && n > 0
-                        && ret)
-                    {
-                        Atom *data = reinterpret_cast<Atom*>(ret);
-                        for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i)
-                        {
-                            LogFlowThisFunc(("Received format via XdndTypeList: %s\n",
-                                             gX11->xAtomToString(data[i]).c_str()));
-
-                            m_formats.append(data[i]);
-                        }
-
-                        XFree(ret);
-                    }
+                    rc = wndXDnDGetTypeList(wndSelection, m_lstFormats);
                 }
 
-                /* Fetch the possible list of actions, if this property is set. */
-                xRc = XGetWindowProperty(m_pDisplay, wndSelection,
-                                         xAtom(XA_XdndActionList),
-                                         0, VBOX_MAX_XPROPERTIES,
-                                         False, XA_ATOM, &type, &f, &n, &a, &ret);
-                if (   xRc == Success
-                    && n > 0
-                    && ret)
-                {
-                    Atom *data = reinterpret_cast<Atom*>(ret);
-                    for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i)
-                    {
-                        LogFlowThisFunc(("Received action: %s\n",
-                                         gX11->xAtomToString(data[i]).c_str()));
-
-                        m_actions.append(data[i]);
-                    }
-
-                    XFree(ret);
-                }
-
                 /*
-                 * Acknowledge the event by sending a status message back to the window.
+                 * Fetch the actions.
                  */
-                XClientMessageEvent m;
-                RT_ZERO(m);
-                m.type         = ClientMessage;
-                m.display      = m_pDisplay;
-                m.window       = m_wndCur;
-                m.message_type = xAtom(XA_XdndStatus);
-                m.format       = 32;
-                m.data.l[0]    = m_wndProxy;
-                m.data.l[1]    = RT_BIT(0); /* Accept the drop. */
-                m.data.l[4]    = xAtom(XA_XdndActionCopy); /** @todo Make the accepted action configurable. */
-
-                xRc = XSendEvent(m_pDisplay, m_wndCur,
-                                 False, 0, reinterpret_cast<XEvent*>(&m));
-                if (RT_UNLIKELY(xRc == 0))
-                {
-                    logError(("Error sending enter XA_XdndStatus event to current window=%#x: %s\n",
-                              m_wndCur, gX11->xErrorToString(xRc).c_str()));
-                }
+                rc = wndXDnDGetActionList(wndSelection, m_lstActions);
+               
+                fAcceptDrop = true;
             }
             /* Did the source tell us where the cursor currently is? */
@@ -1491,5 +1479,13 @@
             {
                 LogFlowThisFunc(("XA_XdndPosition\n"));
-
+                fAcceptDrop = true;
+            }
+            else if (pEventClient->message_type == xAtom(XA_XdndLeave))
+            {
+                LogFlowThisFunc(("XA_XdndLeave\n"));
+            }
+
+            if (fAcceptDrop)
+            {
                 /* Reply with a XdndStatus message to tell the source whether
                  * the data can be dropped or not. */
@@ -1509,20 +1505,16 @@
                 if (RT_UNLIKELY(xRc == 0))
                 {
-                    logError(("Error sending position XA_XdndStatus event to current window=%#x: %s\n",
-                              m_wndCur, gX11->xErrorToString(xRc).c_str()));
+                    logError("Error sending position XA_XdndStatus event to current window=%#x: %s\n",
+                              m_wndCur, gX11->xErrorToString(xRc).c_str());
                 }
             }
-            else if (pEventClient->message_type == xAtom(XA_XdndLeave))
-            {
-                LogFlowThisFunc(("XA_XdndLeave\n"));
-            }
         }
 
         /* Do we need to acknowledge at least one format to the host? */
-        if (!m_formats.isEmpty())
-        {
-            RTCString strFormats = gX11->xAtomListToString(m_formats);
+        if (!m_lstFormats.isEmpty())
+        {
+            RTCString strFormats = gX11->xAtomListToString(m_lstFormats);
             uint32_t uDefAction = DND_COPY_ACTION; /** @todo Handle default action! */
-            uint32_t uAllActions = toHGCMActions(m_actions);
+            uint32_t uAllActions = toHGCMActions(m_lstActions);
 
             rc = VbglR3DnDGHAcknowledgePending(&m_dndCtx, uDefAction, uAllActions, strFormats.c_str());
@@ -1538,8 +1530,9 @@
 int DragInstance::ghDropped(const RTCString &strFormat, uint32_t uAction)
 {
-    LogFlowThisFunc(("strFormat=%s, uAction=%RU32\n", strFormat.c_str(), uAction));
-
-    if (   m_mode  != GH
-        || m_state != Dragging)
+    LogFlowThisFunc(("mode=%RU32, state=%RU32, strFormat=%s, uAction=%RU32\n", 
+                     m_enmMode, m_enmState, strFormat.c_str(), uAction));
+
+    if (   m_enmMode  != GH
+        || m_enmState != Dragging)
     {
         return VERR_INVALID_STATE;
@@ -1548,5 +1541,5 @@
     int rc = VINF_SUCCESS;
 
-    m_state = Dropped;
+    m_enmState = Dropped;
 
     /* Show the proxy window, so that the source will find it. */
@@ -1581,4 +1574,6 @@
     if (fDrop)
     {
+        LogFlowThisFunc(("XA_XdndDrop\n"));
+
         /* Request to convert the selection in the specific format and
          * place it to our proxy window as property. */
@@ -1617,5 +1612,5 @@
                                              AnyPropertyType,         /* Property type */
                                              &aPropType, &iPropFormat, &cItems, &cbRemaining, &pcData);
-                if (RT_UNLIKELY(xRc == 0))
+                if (RT_UNLIKELY(xRc != Success))
                     LogFlowThisFunc(("Error getting XA_XdndSelection property of proxy window=%#x: %s\n", 
                                      m_wndProxy, gX11->xErrorToString(xRc).c_str()));
@@ -1671,5 +1666,5 @@
                         m.data.l[0]    = m_wndProxy; /* Target window. */
                         m.data.l[1]    = 0; /* Don't accept the drop to not make the guest stuck. */
-                        m.data.l[2]    = RT_SUCCESS(rc) ? toX11Action(uAction) : None; /* Action used on success */
+                        m.data.l[2]    = RT_SUCCESS(rc) ? toAtomAction(uAction) : None; /* Action used on success */
 
                         xRc = XSendEvent(m_pDisplay, wndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m));
@@ -1716,6 +1711,6 @@
                     if (RT_UNLIKELY(xRc == 0))
                     {
-                        logError(("Error sending XA_XdndFinished event to proxy window=%#x: %s\n",
-                                  m_wndProxy, gX11->xErrorToString(xRc).c_str()));
+                        logError("Error sending XA_XdndFinished event to proxy window=%#x: %s\n",
+                                  m_wndProxy, gX11->xErrorToString(xRc).c_str());
                     }
                 }
@@ -1870,13 +1865,14 @@
     LogFlowThisFuncEnter();
 
+#if 0 
+    XTestGrabControl(m_pDisplay, False);
+#endif
+
+    /* Get the mouse pointer position and determine if we're on the same screen as the root window
+     * and returns the current child window beneath our mouse pointer, if any. */
     int iRootX, iRootY;
     int iChildX, iChildY;
     unsigned int iMask;
     Window wndRoot, wndChild;
-
-//    XTestGrabControl(m_pDisplay, False);
-
-    /* Get the mouse pointer position and determine if we're on the same screen as the root window
-     * and returns the current child window beneath our mouse pointer, if any. */
     Bool fInRootWnd = XQueryPointer(m_pDisplay, m_wndRoot, &wndRoot, &wndChild,
                                     &iRootX, &iRootY,
@@ -1897,9 +1893,8 @@
     XRaiseWindow(m_pDisplay, m_wndProxy);
 
-    /* Resize our proxy window so that it gets displayed right in center of our mouse cursor. */
-    const int iProxyX = RT_MAX(0, iRootX - 50);
-    const int iProxyY = RT_MAX(0, iRootY - 50);
-    LogFlowThisFunc(("iProxyX=%d, iProxyY=%d\n", iProxyX, iProxyY));
-    XMoveResizeWindow(m_pDisplay, m_wndProxy, iProxyX, iProxyY, 100, 100);
+    /* Spawn our proxy window over the entire screen, making it an easy drop target for the host's cursor. */
+    int iScreenID = XDefaultScreen(m_pDisplay);
+    XMoveResizeWindow(m_pDisplay, m_wndProxy, 0, 0, XDisplayWidth(m_pDisplay, iScreenID), XDisplayHeight(m_pDisplay, iScreenID));
+    /** @todo What about multiple screens? Test this! */
 
     if (fMouseMove)
@@ -1907,5 +1902,8 @@
 
     XSynchronize(m_pDisplay, False /* Disable sync */);
-//    XTestGrabControl(m_pDisplay, True);
+
+#if 0 
+    XTestGrabControl(m_pDisplay, True);
+#endif
 
     return VINF_SUCCESS; /** @todo Add error checking. */
@@ -1916,5 +1914,7 @@
     LogFlowFuncEnter();
 
+#ifndef VBOX_DND_DEBUG_WND
     XUnmapWindow(m_pDisplay, m_wndProxy);
+#endif
     m_eventQueue.clear();
 
@@ -1922,30 +1922,93 @@
 }
 
-/* Currently not used. */
-/** @todo Is this function still needed? */
-void DragInstance::registerForEvents(Window wndThis) const
-{
-    if (wndThis == m_wndProxy)
-        return;
-
-    LogFlowThisFunc(("%x\n", wndThis));
-//    XSelectInput(m_pDisplay, w, Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask);//| SubstructureNotifyMask);
-//    XSelectInput(m_pDisplay, w, ButtonMotionMask); //PointerMotionMask);
-    XSelectInput(m_pDisplay, wndThis, PointerMotionMask); //PointerMotionMask);
-    Window hRealRoot, hParent;
-    Window *phChildrenRaw = NULL;
-    unsigned cChildren;
-    if (XQueryTree(m_pDisplay, wndThis, &hRealRoot, &hParent, &phChildrenRaw, &cChildren))
-    {
-        for (unsigned i = 0; i < cChildren; ++i)
-            registerForEvents(phChildrenRaw[i]);
-        XFree(phChildrenRaw);
-    }
-}
-
-void DragInstance::setActionsWindowProperty(Window wndThis, const RTCList<Atom> &lstActions) const
+void DragInstance::wndXDnDClearActionList(Window wndThis) const
+{
+    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList));
+}
+
+void DragInstance::wndXDnDClearTypeList(Window wndThis) const
+{
+    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndTypeList));
+}
+
+int DragInstance::wndXDnDGetActionList(Window wndThis, VBoxDnDAtomList &lstActions) const
+{
+    Atom iActType = None;
+    int iActFmt;
+    unsigned long cItems, cbData;
+    unsigned char *pcbData = NULL;
+
+    /* Fetch the possible list of actions, if this property is set. */
+    int xRc = XGetWindowProperty(m_pDisplay, wndThis,
+                                 xAtom(XA_XdndActionList),
+                                 0, VBOX_MAX_XPROPERTIES,
+                                 False, XA_ATOM, &iActType, &iActFmt, &cItems, &cbData, &pcbData);
+    if (xRc != Success)
+    {
+        LogFlowThisFunc(("Error getting XA_XdndActionList atoms from window=%#x: %s\n", 
+                         wndThis, gX11->xErrorToString(xRc).c_str()));
+        return VERR_NOT_FOUND;
+    }
+
+    if (   cItems > 0 
+        && pcbData)
+    {
+        Atom *paData = reinterpret_cast<Atom *>(pcbData);
+
+        for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, cItems); i++)
+        {
+            LogFlowThisFunc(("Received action: %s\n",
+                             gX11->xAtomToString(paData[i]).c_str()));
+
+            lstActions.append(paData[i]);
+        }
+
+        XFree(pcbData);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int DragInstance::wndXDnDGetTypeList(Window wndThis, VBoxDnDAtomList &lstTypes) const
+{
+    Atom iActType = None;
+    int iActFmt;
+    unsigned long cItems, cbData;
+    unsigned char *pcbData = NULL;
+
+    int xRc = XGetWindowProperty(m_pDisplay, wndThis,
+                             xAtom(XA_XdndTypeList),
+                             0, VBOX_MAX_XPROPERTIES,
+                             False, XA_ATOM, &iActType, &iActFmt, &cItems, &cbData, &pcbData);
+    if (xRc != Success)
+    {
+        LogFlowThisFunc(("Error getting XA_XdndTypeList atoms from window=%#x: %s\n", 
+                         wndThis, gX11->xErrorToString(xRc).c_str()));
+        return VERR_NOT_FOUND;
+    }
+
+    if (   cItems > 0 
+        && pcbData)
+    {
+        Atom *paData = reinterpret_cast<Atom*>(pcbData);
+
+        for (unsigned i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, cItems); i++)
+        {
+            LogFlowThisFunc(("Received format via XdndTypeList: %s\n",
+                             gX11->xAtomToString(paData[i]).c_str()));
+
+            lstTypes.append(paData[i]);
+        }
+
+        XFree(pcbData);
+    }
+
+    return VINF_SUCCESS;
+}
+
+int DragInstance::wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const
 {
     if (lstActions.isEmpty())
-        return;
+        return VINF_SUCCESS;
 
     XChangeProperty(m_pDisplay, wndThis,
@@ -1954,51 +2017,44 @@
                     reinterpret_cast<const unsigned char*>(lstActions.raw()),
                     lstActions.size());
-}
-
-void DragInstance::clearActionsWindowProperty(Window wndThis) const
-{
-    XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList));
-}
-
-void DragInstance::setFormatsWindowProperty(Window wndThis, Atom property) const
-{
-    if (m_formats.isEmpty())
-        return;
+
+    return VINF_SUCCESS;
+}
+
+int DragInstance::wndXDnDSetFormatList(Window wndThis, Atom property, const VBoxDnDAtomList &lstFormats) const
+{
+    if (lstFormats.isEmpty())
+        return VINF_SUCCESS;
 
     /* We support TARGETS and the data types. */
-    RTCList<Atom> targets(m_formats.size() + 1);
-    targets.append(xAtom(XA_TARGETS));
-    targets.append(m_formats);
+    VBoxDnDAtomList lstFormatsExt(lstFormats.size() + 1);
+    lstFormatsExt.append(xAtom(XA_TARGETS));
+    lstFormatsExt.append(lstFormats);
 
     /* Add the property with the property data to the window. */
     XChangeProperty(m_pDisplay, wndThis, property,
                     XA_ATOM, 32, PropModeReplace,
-                    reinterpret_cast<const unsigned char*>(targets.raw()),
-                    targets.size());
-}
-
-void DragInstance::clearFormatsWindowProperty(Window wndThis) const
-{
-    XDeleteProperty(m_pDisplay, wndThis,
-                    xAtom(XA_XdndTypeList));
-}
-
-RTCList<Atom> DragInstance::toAtomList(const RTCList<RTCString> &lstFormats) const
-{
-    RTCList<Atom> atomList;
+                    reinterpret_cast<const unsigned char*>(lstFormatsExt.raw()),
+                    lstFormatsExt.size());
+
+    return VINF_SUCCESS;
+}
+
+int DragInstance::toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const
+{    
     for (size_t i = 0; i < lstFormats.size(); ++i)
-        atomList.append(XInternAtom(m_pDisplay, lstFormats.at(i).c_str(), False));
-
-    return atomList;
-}
-
-RTCList<Atom> DragInstance::toAtomList(void *pvData, uint32_t cbData) const
-{
-    if (   !pvData
-        || !cbData)
-        return RTCList<Atom>();
-
-    char *pszStr = (char*)pvData;
+        lstAtoms.append(XInternAtom(m_pDisplay, lstFormats.at(i).c_str(), False));
+
+    return VINF_SUCCESS;
+}
+
+int DragInstance::toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const
+{
+    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+    AssertReturn(cbData, VERR_INVALID_PARAMETER);
+
+    const char *pszStr = (char *)pvData;
     uint32_t cbStr = cbData;
+
+    int rc = VINF_SUCCESS;
 
     RTCList<Atom> lstAtom;
@@ -2010,16 +2066,22 @@
          * even if the data isn't zero terminated. */
         char *pszTmp = RTStrDupN(pszStr, cbSize);
-        LogFlowThisFunc(("f: %s\n", pszTmp));
+        if (!pszTmp)
+        {
+            rc = VERR_NO_MEMORY;
+            break;
+        }
+
         lstAtom.append(XInternAtom(m_pDisplay, pszTmp, False));
         RTStrFree(pszTmp);
+
         pszStr  += cbSize + 1;
         cbStr   -= cbSize + 1;
     }
 
-    return lstAtom;
+    return rc;
 }
 
 /* static */
-Atom DragInstance::toX11Action(uint32_t uAction)
+Atom DragInstance::toAtomAction(uint32_t uAction)
 {
     /* Ignore is None. */
@@ -2031,15 +2093,14 @@
 
 /* static */
-RTCList<Atom> DragInstance::toX11Actions(uint32_t uActions)
-{
-    RTCList<Atom> actionList;
+int DragInstance::toAtomActions(uint32_t uActions, VBoxDnDAtomList &lstAtoms)
+{
     if (hasDnDCopyAction(uActions))
-        actionList.append(xAtom(XA_XdndActionCopy));
+        lstAtoms.append(xAtom(XA_XdndActionCopy));
     if (hasDnDMoveAction(uActions))
-        actionList.append(xAtom(XA_XdndActionMove));
+        lstAtoms.append(xAtom(XA_XdndActionMove));
     if (hasDnDLinkAction(uActions))
-        actionList.append(xAtom(XA_XdndActionLink));
-
-    return actionList;
+        lstAtoms.append(xAtom(XA_XdndActionLink));
+
+    return VINF_SUCCESS;
 }
 
@@ -2162,12 +2223,13 @@
                         if (e.hgcm.cbFormats)
                         {
-                            RTCList<RTCString> lstFormats
-                                = RTCString(e.hgcm.pszFormats, e.hgcm.cbFormats - 1).split("\r\n");
-                            m_pCurDnD->hgEnter(lstFormats, e.hgcm.u.a.uAllActions);
-
+                            RTCList<RTCString> lstFormats = RTCString(e.hgcm.pszFormats, e.hgcm.cbFormats - 1).split("\r\n");
+                            rc = m_pCurDnD->hgEnter(lstFormats, e.hgcm.u.a.uAllActions);
                             /* Enter is always followed by a move event. */
                         }
-                        else /* Invalid parameter, skip. */
+                        else
+                        {
+                            rc = VERR_INVALID_PARAMETER;
                             break;
+                        }
                         /* Not breaking unconditionally is intentional. See comment above. */
                     }
@@ -2192,26 +2254,31 @@
                         break;
                     }
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
                     case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
                     {
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
                         rc = m_pCurDnD->ghIsDnDPending();
-#endif
                         break;
                     }
                     case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
                     {
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
                         rc = m_pCurDnD->ghDropped(e.hgcm.pszFormats, e.hgcm.u.a.uDefAction);
-#endif
                         break;
                     }
-
+#endif
                     default:
+                    {
                         LogFlowThisFunc(("Unsupported message: %RU32\n", e.hgcm.uType));
                         rc = VERR_NOT_SUPPORTED;
                         break;
+                    }
                 }
 
-                LogFlowFunc(("Returning %Rrc\n", rc));
+                if (RT_FAILURE(rc))
+                {
+                    m_pCurDnD->logError("Error: Processing message %RU32 failed with %Rrc\n", e.hgcm.uType, rc);
+
+                    /* If anything went wrong, do a reset and start over. */
+                    m_pCurDnD->reset();
+                }
 
                 /* Some messages require cleanup. */
@@ -2250,7 +2317,9 @@
                 AssertMsgFailed(("Unknown event queue type %d\n", e.type));
 
-            /* Make sure that any X11 requests have actually been sent to the
+            /*
+             * Make sure that any X11 requests have actually been sent to the
              * server, since we are waiting for responses using poll() on
-             * another thread which will not automatically trigger flushing. */
+             * another thread which will not automatically trigger flushing. 
+             */ 
             XFlush(m_pDisplay);
 
@@ -2269,4 +2338,5 @@
     if (RT_FAILURE(rc))
         VBClFatalError(("Failed to connect to the VirtualBox kernel service, rc=%Rrc\n", rc));
+
     /* Connect to the x11 server. */
     m_pDisplay = XOpenDisplay(NULL);
@@ -2292,5 +2362,5 @@
         rc = RTThreadCreate(&m_hHGCMThread, hgcmEventThread, this,
                             0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
-                            "HGCM-NOTIFY");
+                            "dndHGCM");
         if (RT_FAILURE(rc))
             break;
@@ -2299,5 +2369,5 @@
         rc = RTThreadCreate(&m_hX11Thread, x11EventThread, this,
                             0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
-                            "X11-NOTIFY");
+                            "dndX11");
     } while (0);
 
@@ -2342,6 +2412,4 @@
         {
             cMsgSkippedInvalid = 0; /* Reset skipped messages count. */
-
-            LogFlowFunc(("Adding new HGCM event ...\n"));
             pThis->m_eventQueue.append(e);
 
@@ -2434,10 +2502,8 @@
                 }
 #endif
-                LogFlowFunc(("Adding new X11 event ...\n"));
-
                 /* At the moment we only have one drag instance. */
                 DragInstance *pInstance = pThis->m_pCurDnD;
-
                 AssertPtr(pInstance);
+
                 pInstance->onX11Event(e.x11);
             }
@@ -2463,5 +2529,5 @@
     struct VBCLSERVICE *pInterface;
     /** Magic number for sanity checks. */
-    uint32_t magic;
+    uint32_t uMagic;
     /** Service object. */
     DragAndDropService mDragAndDrop;
@@ -2477,5 +2543,5 @@
     struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
 
-    if (pSelf->magic != DRAGANDDROPSERVICE_MAGIC)
+    if (pSelf->uMagic != DRAGANDDROPSERVICE_MAGIC)
         VBClFatalError(("Bad display service object!\n"));
     return pSelf->mDragAndDrop.run(fDaemonised);
@@ -2498,5 +2564,5 @@
 };
 
-/* Static factory */
+/* Static factory. */
 struct VBCLSERVICE **VBClGetDragAndDropService(void)
 {
@@ -2507,5 +2573,5 @@
         VBClFatalError(("Out of memory\n"));
     pService->pInterface = &vbclDragAndDropInterface;
-    pService->magic = DRAGANDDROPSERVICE_MAGIC;
+    pService->uMagic = DRAGANDDROPSERVICE_MAGIC;
     new(&pService->mDragAndDrop) DragAndDropService();
     return &pService->pInterface;
