Index: /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 97733)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 97734)
@@ -50,13 +50,9 @@
 #include <VBox/log.h>
 #include <VBox/VBoxGuestLib.h>
+#include <VBox/version.h>
 
 #include "VBox/HostServices/DragAndDropSvc.h"
 #include "VBoxClient.h"
 
-/* Enable this define to see the proxy window(s) when debugging
- * their behavior. Don't have this enabled in release builds! */
-#ifdef DEBUG
-//# define VBOX_DND_DEBUG_WND
-#endif
 
 /* Enable this to handle drag'n drop "promises".
@@ -131,4 +127,7 @@
 /** How many X properties our proxy window can hold. */
 #define VBOX_MAX_XPROPERTIES (LONG_MAX-1)
+
+/** The notification header text for VBClShowNotify(). */
+#define VBOX_DND_SHOWNOTIFY_HEADER              VBOX_PRODUCT " Drag'n Drop"
 
 /**
@@ -199,5 +198,5 @@
 
 /**
- * Xdnd message value indexes, sorted by message type.
+ * Xdnd message value indices, sorted by message type.
  */
 typedef enum XdndMsg
@@ -251,6 +250,6 @@
     /** XdndFinished. */
     XdndFinishedWindow = 0,         /* Target window (sender). */
-    XdndFinishedFlags,              /* Version 5: Bit 0 is set if the current target accepted the drop. */
-    XdndFinishedAction              /* Version 5: Contains the action performed by the target. */
+    XdndFinishedFlags,              /* Since version 5: Bit 0 is set if the current target accepted the drop. */
+    XdndFinishedAction              /* Since version 5: Contains the action performed by the target. */
 
 } XdndMsg;
@@ -628,10 +627,9 @@
     /** Current source/target window handle. */
     Window                      m_wndCur;
-    /** The XDnD protocol version the current
-     *  source/target window is using. */
+    /** The XDnD protocol version the current source/target window is using. */
     long                        m_curVer;
-    /** List of (Atom) formats the source window supports. */
+    /** List of (Atom) formats the current source/target window supports. */
     VBoxDnDAtomList             m_lstAtomFormats;
-    /** List of (Atom) actions the source window supports. */
+    /** List of (Atom) actions the current source/target window supports. */
     VBoxDnDAtomList             m_lstAtomActions;
     /** Buffer for answering the target window's selection request. */
@@ -645,9 +643,7 @@
     /** The instance's own X event queue. */
     RTCMTList<WrappedXEvent>    m_eventQueueList;
-    /** Critical section for providing serialized access to list
-     *  event queue's contents. */
+    /** Critical section for providing serialized access to list event queue's contents. */
     RTCRITSECT                  m_eventQueueCS;
-    /** Event for notifying this instance in case of a new
-     *  event. */
+    /** Event for notifying this instance in case of a new event. */
     RTSEMEVENT                  m_eventQueueEvent;
     /** Critical section for data access. */
@@ -824,4 +820,6 @@
         RTCritSectLeave(&m_dataCS);
     }
+
+    LogFlowFuncLeave();
 }
 
@@ -838,4 +836,10 @@
     if (rc != VINF_SUCCESS)
         return rc;
+
+    if (g_cVerbosity)
+    {
+        RTCString strBody = RTCStringFmt("Connected (screen %RU32, verbosity %u)", uScreenID, g_cVerbosity);
+        VBClShowNotify(VBOX_DND_SHOWNOTIFY_HEADER, strBody.c_str());
+    }
 
     do
@@ -891,30 +895,33 @@
         attr.override_redirect     = True;
         attr.do_not_propagate_mask = NoEventMask;
-#ifdef VBOX_DND_DEBUG_WND
-        attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenID);
-        attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenID);
-        m_wndProxy.hWnd = 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.hWnd = XCreateWindow(m_pDisplay, m_wndRoot            /* Parent */,
-                                   0, 0,                                 /* Position */
-                                   1, 1,                                 /* Width + height */
-                                   0,                                    /* Border width */
-                                   CopyFromParent,                       /* Depth */
-                                   InputOnly,                            /* Class */
-                                   CopyFromParent,                       /* Visual */
-                                   CWOverrideRedirect | CWDontPropagate, /* Value mask */
-                                   &attr);                               /* Attributes for value mask */
-#endif
+
+        if (g_cVerbosity >= 3)
+        {
+            attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenID);
+            attr.border_pixel          = XBlackPixel(m_pDisplay, m_screenID);
+            m_wndProxy.hWnd = 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 */
+        }
+
+        m_wndProxy.hWnd = XCreateWindow(m_pDisplay, m_wndRoot                   /* Parent */,
+                                        0, 0,                                   /* Position */
+                                        1, 1,                                   /* Width + height */
+                                        0,                                      /* Border width */
+                                        CopyFromParent,                         /* Depth */
+                                        InputOnly,                              /* Class */
+                                        CopyFromParent,                         /* Visual */
+                                        CWOverrideRedirect | CWDontPropagate,   /* Value mask */
+                                        &attr);                                 /* Attributes for value mask */
+
         if (!m_wndProxy.hWnd)
         {
@@ -931,11 +938,14 @@
         }
 
-#ifdef VBOX_DND_DEBUG_WND
-        XFlush(m_pDisplay);
-        XMapWindow(m_pDisplay, m_wndProxy.hWnd);
-        XRaiseWindow(m_pDisplay, m_wndProxy.hWnd);
-        XFlush(m_pDisplay);
-#endif
-        VBClLogInfo("Proxy window=%RU32, root window=%RU32 ...\n", m_wndProxy.hWnd, m_wndRoot);
+        if (g_cVerbosity >= 3) /* Make debug window visible. */
+        {
+            XFlush(m_pDisplay);
+            XMapWindow(m_pDisplay, m_wndProxy.hWnd);
+            XRaiseWindow(m_pDisplay, m_wndProxy.hWnd);
+            XFlush(m_pDisplay);
+        }
+
+        VBClLogInfo("Proxy window=%#x (debug mode: %RTbool), root window=%#x ...\n",
+                    m_wndProxy.hWnd, RT_BOOL(g_cVerbosity >= 3), m_wndRoot);
 
         /* Set the window's name for easier lookup. */
@@ -974,4 +984,7 @@
     int rc = VINF_SUCCESS;
 
+    char *pszWndCurName = wndX11GetNameA(m_wndCur);
+    AssertPtrReturn(pszWndCurName, VERR_NO_MEMORY);
+
     switch (m_enmMode)
     {
@@ -982,7 +995,12 @@
              * window, in response of some events we send to them.
              */
+
+            /* The target window informs us of the current Xdnd status. */
             if (e.xclient.message_type == xAtom(XA_XdndStatus))
             {
-                Window wndTarget = static_cast<Window>(e.xclient.data.l[XdndStatusWindow]);
+                Window wndTgt = static_cast<Window>(e.xclient.data.l[XdndStatusWindow]);
+
+                char *pszWndTgtName = wndX11GetNameA(wndTgt);
+                AssertPtrBreakStmt(pszWndTgtName, VERR_NO_MEMORY);
 
                 /* Does the target accept the drop? */
@@ -991,7 +1009,4 @@
                 const bool fWantsPosition = e.xclient.data.l[XdndStatusFlags] & VBOX_XDND_STATUS_FLAG_WANTS_POS;
                 RT_NOREF(fWantsPosition);
-
-                char *pszWndName = wndX11GetNameA(m_wndCur);
-                AssertPtr(pszWndName);
 
                 /*
@@ -1002,20 +1017,21 @@
                 RTCString strActions = xAtomToString(e.xclient.data.l[XdndStatusAction]);
 
-                VBClLogInfo("Target window %#x ('%s') %s accept data with actions '%s'\n",
-                            wndTarget, pszWndName, fAcceptDrop ? "does" : "does not", strActions.c_str());
-
-                const uint16_t x  = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]);
-                const uint16_t y  = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]);
-                const uint16_t cx = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]);
-                const uint16_t cy = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]);
+                VBClLogInfo("Target window %#x ('%s')\n", wndTgt, pszWndTgtName);
+                VBClLogInfo("    - %s accept data (actions '%s')\n", fAcceptDrop ? "does" : "does not", strActions.c_str());
+                VBClLogInfo("    - %s want position messages\n", fWantsPosition ? "does" : "does not");
+
+                uint16_t const x  = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]);
+                uint16_t const y  = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]);
+                uint16_t const cx = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]);
+                uint16_t const cy = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]);
 
                 if (cx && cy)
                 {
                     VBClLogInfo("Target window %#x ('%s') reported dead area at %RU16,%RU16 (%RU16 x %RU16)\n",
-                                wndTarget, pszWndName, x, y, cx, cy);
+                                wndTgt, pszWndTgtName, x, y, cx, cy);
                     /** @todo Save dead area and don't send XdndPosition messages anymore into it. */
                 }
 
-                if (m_wndCur == wndTarget)
+                if (m_wndCur == wndTgt)
                 {
                     VBOXDNDACTION dndAction = VBOX_DND_ACTION_IGNORE; /* Default is ignoring. */
@@ -1027,27 +1043,29 @@
                 }
                 else
-                    VBClLogInfo("Target window %#x ('%s') is not our current window, skipping\n", wndTarget, pszWndName);
-
-                RTStrFree(pszWndName);
+                    VBClLogInfo("Target window %#x ('%s') is not our current window, skipping\n", wndTgt, pszWndTgtName);
+
+                RTStrFree(pszWndTgtName);
             }
+            /* The target window informs us that it finished the Xdnd operation and that we may free all data. */
             else if (e.xclient.message_type == xAtom(XA_XdndFinished))
             {
                 Window wndTarget = static_cast<Window>(e.xclient.data.l[XdndFinishedWindow]);
 
-                const bool fSucceeded = e.xclient.data.l[XdndFinishedFlags] & VBOX_XDND_FINISHED_FLAG_SUCCEEDED;
-
-                char *pszWndName = wndX11GetNameA(wndTarget);
-                AssertPtr(pszWndName);
-
-                const char *pcszAction = xAtomToString(e.xclient.data.l[XdndFinishedAction]).c_str();
-
-                /* This message is sent on an un/successful DnD drop request. */
-                LogFlowThisFunc(("XA_XdndFinished: wnd=%#x ('%s'), success=%RTbool, action=%s\n",
-                                 wndTarget, pszWndName, fSucceeded, pcszAction));
-
-                VBClLogInfo("Target window %#x ('%s') has %s the data with action '%s'\n",
-                            wndTarget, pszWndName, fSucceeded ? "accepted" : "rejected", pcszAction ? "<None>" : pcszAction);
-
-                RTStrFree(pszWndName);
+                char *pszWndTgtName = wndX11GetNameA(wndTarget);
+                AssertPtrBreakStmt(pszWndTgtName, VERR_NO_MEMORY);
+
+                if (m_curVer >= 5)
+                {
+                    const bool  fSucceeded = e.xclient.data.l[XdndFinishedFlags] & VBOX_XDND_FINISHED_FLAG_SUCCEEDED;
+            #if 0 /** @todo Returns garbage -- investigate this! */
+                    //const char *pcszAction = fSucceeded ? xAtomToString(e.xclient.data.l[XdndFinishedAction]).c_str() : NULL;
+            #endif
+                    VBClLogInfo("Target window %#x ('%s') has %s the data\n",
+                                wndTarget, pszWndTgtName, fSucceeded ? "accepted" : "rejected");
+                }
+                else /* Xdnd < version 5 did not have the XdndFinishedFlags / XdndFinishedAction properties. */
+                    VBClLogInfo("Target window %#x ('%s') has accepted the data\n", wndTarget, pszWndTgtName);
+
+                RTStrFree(pszWndTgtName);
 
                 reset();
@@ -1063,4 +1081,5 @@
 
         case Unknown: /* Mode not set (yet). */
+            RT_FALL_THROUGH();
         case GH:
         {
@@ -1071,16 +1090,11 @@
             if (e.xclient.message_type == xAtom(XA_XdndEnter))
             {
-                LogFlowFunc(("XA_XdndEnter\n"));
-
                 /*
                  * Get the window which currently has the XA_XdndSelection
                  * bit set.
                  */
-                Window wndSelection = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
-
-                char *pszWndName = wndX11GetNameA(wndSelection);
-                AssertPtr(pszWndName);
-                LogFlowThisFunc(("wndSelection=%RU32 ('%s'), wndProxy=%RU32\n", wndSelection, pszWndName, m_wndProxy.hWnd));
-                RTStrFree(pszWndName);
+                Window wndSel = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
+                char *pszWndSelName = wndX11GetNameA(wndSel);
+                AssertPtrBreakStmt(pszWndSelName, VERR_NO_MEMORY);
 
                 mouseButtonSet(m_wndProxy.hWnd, -1, -1, 1, true /* fPress */);
@@ -1089,10 +1103,10 @@
                  * Update our state and the window handle to process.
                  */
-                int rc2 = RTCritSectEnter(&m_dataCS);
-                if (RT_SUCCESS(rc2))
+                rc = RTCritSectEnter(&m_dataCS);
+                if (RT_SUCCESS(rc))
                 {
-                    m_wndCur = wndSelection;
-                    m_curVer = e.xclient.data.l[XdndEnterFlags] >> XdndEnterVersionRShift;
-                    Assert(m_wndCur == (Window)e.xclient.data.l[XdndEnterWindow]); /* Source window. */
+                    long const xdndVer = e.xclient.data.l[XdndEnterFlags] >> XdndEnterVersionRShift;
+
+                    VBClLogInfo("Entered new source window %#x ('%s'), supports Xdnd version %ld\n", wndSel, pszWndSelName, xdndVer);
 #ifdef DEBUG
                     XWindowAttributes xwa;
@@ -1107,5 +1121,4 @@
                      * to fetch the XdndTypeList property from the window. */
                     bool fMoreTypes = e.xclient.data.l[XdndEnterFlags] & XdndEnterMoreTypesFlag;
-                    LogFlowThisFunc(("XdndVer=%d, fMoreTypes=%RTbool\n", m_curVer, fMoreTypes));
                     if (!fMoreTypes)
                     {
@@ -1121,5 +1134,11 @@
                     {
                         /* More than 3 format types supported. */
-                        rc = wndXDnDGetFormatList(wndSelection, m_lstAtomFormats);
+                        rc = wndXDnDGetFormatList(wndSel, m_lstAtomFormats);
+                    }
+
+                    if (RT_FAILURE(rc))
+                    {
+                        VBClLogError("Error retrieving supported formats, rc=%Rrc\n", rc);
+                        break;
                     }
 
@@ -1127,22 +1146,47 @@
                      * Retrieve supported actions.
                      */
-                    if (RT_SUCCESS(rc))
+                    if (xdndVer >= 2) /* More than one action allowed since protocol version 2. */
                     {
-                        if (m_curVer >= 2) /* More than one action allowed since protocol version 2. */
-                        {
-                            rc = wndXDnDGetActionList(wndSelection, m_lstAtomActions);
-                        }
-                        else /* Only "copy" action allowed on legacy applications. */
-                            m_lstAtomActions.append(XA_XdndActionCopy);
+                        rc = wndXDnDGetActionList(wndSel, m_lstAtomActions);
                     }
-
-                    if (RT_SUCCESS(rc))
+                    else /* Only "copy" action allowed on legacy applications. */
+                        m_lstAtomActions.append(XA_XdndActionCopy);
+
+                    if (RT_FAILURE(rc))
                     {
-                        m_enmMode  = GH;
-                        m_enmState = Dragging;
+                        VBClLogError("Error retrieving supported actions, rc=%Rrc\n", rc);
+                        break;
                     }
+
+                    VBClLogInfo("Source window %#x ('%s')\n", wndSel, pszWndSelName);
+                    VBClLogInfo("    - supports the formats ");
+                    for (size_t i = 0; i < m_lstAtomFormats.size(); i++)
+                    {
+                        if (i > 0)
+                            VBClLogInfo(", ");
+                        VBClLogInfo("%s", gX11->xAtomToString(m_lstAtomFormats[i]).c_str());
+                    }
+                    VBClLogInfo("\n");
+                    VBClLogInfo("    - supports the actions ");
+                    for (size_t i = 0; i < m_lstAtomActions.size(); i++)
+                    {
+                        if (i > 0)
+                            VBClLogInfo(", ");
+                        VBClLogInfo("%s", gX11->xAtomToString(m_lstAtomActions[i]).c_str());
+                    }
+                    VBClLogInfo("\n");
+
+                    AssertBreakStmt(wndSel == (Window)e.xclient.data.l[XdndEnterWindow],
+                                    rc = VERR_INVALID_PARAMETER); /* Source window. */
+
+                    m_wndCur   = wndSel;
+                    m_curVer   = xdndVer;
+                    m_enmMode  = GH;
+                    m_enmState = Dragging;
 
                     RTCritSectLeave(&m_dataCS);
                 }
+
+                RTStrFree(pszWndSelName);
             }
             else if (   e.xclient.message_type == xAtom(XA_XdndPosition)
@@ -1158,9 +1202,8 @@
                 Atom    atmAction = m_curVer >= 2 /* Actions other than "copy" or only supported since protocol version 2. */
                                   ? e.xclient.data.l[XdndPositionAction] : xAtom(XA_XdndActionCopy);
-                LogFlowThisFunc(("XA_XdndPosition: wndProxy=%RU32, wndCur=%RU32, x=%RI32, y=%RI32, strAction=%s\n",
+                LogFlowThisFunc(("XA_XdndPosition: wndProxy=%#x, wndCur=%#x, x=%RI32, y=%RI32, strAction=%s\n",
                                  m_wndProxy.hWnd, m_wndCur, RT_HIWORD(iPos), RT_LOWORD(iPos),
                                  xAtomToString(atmAction).c_str()));
 #endif
-
                 bool fAcceptDrop = true;
 
@@ -1188,6 +1231,6 @@
                                      False /* Propagate */, NoEventMask, reinterpret_cast<XEvent *>(&m));
                 if (xRc == 0)
-                    VBClLogError("Error sending position XA_XdndStatus event to current window=%#x: %s\n",
-                                 m_wndCur, gX11->xErrorToString(xRc).c_str());
+                    VBClLogError("Error sending position status event to current window %#x ('%s'): %s\n",
+                                 m_wndCur, pszWndCurName, gX11->xErrorToString(xRc).c_str());
             }
             else if (   e.xclient.message_type == xAtom(XA_XdndLeave)
@@ -1241,4 +1284,6 @@
         }
     }
+
+    RTStrFree(pszWndCurName);
 
     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
@@ -1327,12 +1372,24 @@
     const XSelectionRequestEvent *pEvReq = &evReq.xselectionrequest;
 
+    char *pszWndSrcName = wndX11GetNameA(pEvReq->owner);
+    AssertPtrReturn(pszWndSrcName, VERR_INVALID_POINTER);
+    char *pszWndTgtName = wndX11GetNameA(pEvReq->requestor);
+    AssertPtrReturn(pszWndTgtName, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
-    LogFlowThisFunc(("Event owner=%#x, requestor=%#x, selection=%s, target=%s, prop=%s, time=%u\n",
-                     pEvReq->owner,
-                     pEvReq->requestor,
+    LogFlowThisFunc(("Event owner=%#x ('%s'), requestor=%#x ('%s'), selection=%s, target=%s, prop=%s, time=%u\n",
+                     pEvReq->owner, pszWndSrcName,
+                     pEvReq->requestor, pszWndTgtName,
                      xAtomToString(pEvReq->selection).c_str(),
                      xAtomToString(pEvReq->target).c_str(),
                      xAtomToString(pEvReq->property).c_str(),
                      pEvReq->time));
+
+    VBClLogInfo("Window '%s' is asking '%s' for '%s' / '%s'\n",
+                pszWndTgtName, pszWndSrcName, xAtomToString(pEvReq->selection).c_str(), xAtomToString(pEvReq->property).c_str());
+
+    RTStrFree(pszWndSrcName);
+    /* Note: pszWndTgtName will be free'd below. */
+
     int rc;
 
@@ -1342,7 +1399,4 @@
         {
             rc = VINF_SUCCESS;
-
-            char *pszWndName = wndX11GetNameA(pEvReq->requestor);
-            AssertPtr(pszWndName);
 
             /*
@@ -1364,13 +1418,15 @@
             pEvResp->time      = pEvReq->time;
 
-#ifdef DEBUG
-            LogFlowFunc(("Supported formats:\n"));
-            for (size_t i = 0; i < m_lstAtomFormats.size(); i++)
-                LogFlowFunc(("\t%s\n", xAtomToString(m_lstAtomFormats.at(i)).c_str()));
-#endif
+            if (g_cVerbosity)
+            {
+                VBClLogVerbose(1, "Supported formats by VBoxClient:\n");
+                for (size_t i = 0; i < m_lstAtomFormats.size(); i++)
+                    VBClLogVerbose(1, "\t%s\n", xAtomToString(m_lstAtomFormats.at(i)).c_str());
+            }
+
             /* Is the requestor asking for the possible MIME types? */
             if (pEvReq->target == xAtom(XA_TARGETS))
             {
-                VBClLogInfo("Target window %#x ('%s') asking for target list\n", pEvReq->requestor, pszWndName);
+                VBClLogInfo("Target window %#x ('%s') asking for target list\n", pEvReq->requestor, pszWndTgtName);
 
                 /* If so, set the window property with the formats on the requestor
@@ -1384,5 +1440,5 @@
             {
                 VBClLogInfo("Target window %#x ('%s') is asking for data as '%s'\n",
-                            pEvReq->requestor, pszWndName, xAtomToString(pEvReq->target).c_str());
+                            pEvReq->requestor, pszWndTgtName, xAtomToString(pEvReq->target).c_str());
 
 #ifdef VBOX_WITH_DRAG_AND_DROP_PROMISES
@@ -1400,14 +1456,16 @@
 #endif /* VBOX_WITH_DRAG_AND_DROP_PROMISES */
                     /* Get the data format the requestor wants from us. */
-                    RTCString strFormat = xAtomToString(pEvReq->target);
-                    Assert(strFormat.isNotEmpty());
-                    VBClLogInfo("Target window=%#x requested data from host as '%s', rc=%Rrc\n",
-                                pEvReq->requestor, strFormat.c_str(), rc);
+                    VBClLogInfo("Target window %#x ('%s') requested data from host as '%s', rc=%Rrc\n",
+                                pEvReq->requestor, pszWndTgtName, xAtomToString(pEvReq->target).c_str(), rc);
 
                     /* Make a copy of the MIME data to be passed back. The X server will be become
                      * the new owner of that data, so no deletion needed. */
                     /** @todo Do we need to do some more conversion here? XConvertSelection? */
-                    void *pvData = RTMemDup(m_pvSelReqData, m_cbSelReqData);
-                    uint32_t cbData = m_cbSelReqData;
+                    AssertMsgBreakStmt(m_pvSelReqData != NULL, ("Selection request data is NULL\n"),   rc = VERR_INVALID_PARAMETER);
+                    AssertMsgBreakStmt(m_cbSelReqData  > 0,    ("Selection request data size is 0\n"), rc = VERR_INVALID_PARAMETER);
+
+                    void    const *pvData = RTMemDup(m_pvSelReqData, m_cbSelReqData);
+                    AssertMsgBreakStmt(pvData != NULL, ("Duplicating selection request failed\n"), rc = VERR_NO_MEMORY);
+                    uint32_t const cbData = m_cbSelReqData;
 
                     /* Always return the requested property. */
@@ -1419,8 +1477,8 @@
                                               reinterpret_cast<const unsigned char*>(pvData), cbData);
 
-                    LogFlowFunc(("Changing property '%s' (target '%s') of window=%RU32: %s\n",
+                    LogFlowFunc(("Changing property '%s' (of type '%s') of window %#x ('%s'): %s\n",
                                  xAtomToString(pEvReq->property).c_str(),
                                  xAtomToString(pEvReq->target).c_str(),
-                                 pEvReq->requestor,
+                                 pEvReq->requestor, pszWndTgtName,
                                  gX11->xErrorToString(xRc).c_str()));
                     RT_NOREF(xRc);
@@ -1433,20 +1491,18 @@
             {
                 VBClLogError("Refusing unknown command/format '%s' of wnd=%#x ('%s')\n",
-                             xAtomToString(pEvReq->target).c_str(), pEvReq->requestor, pszWndName);
+                             xAtomToString(pEvReq->target).c_str(), pEvReq->requestor, pszWndTgtName);
                 rc = VERR_NOT_SUPPORTED;
             }
 
-            LogFlowThisFunc(("Offering type '%s', property '%s' to wnd=%#x ...\n",
-                             xAtomToString(pEvReq->target).c_str(),
-                             xAtomToString(pEvReq->property).c_str(), pEvReq->requestor));
+            VBClLogVerbose(1, "Offering type '%s', property '%s' to window %#x ('%s') ...\n",
+                           xAtomToString(pEvReq->target).c_str(),
+                           xAtomToString(pEvReq->property).c_str(), pEvReq->requestor, pszWndTgtName);
 
             int xRc = XSendEvent(pEvReq->display, pEvReq->requestor, True /* Propagate */, 0, &evResp);
             if (xRc == 0)
-                VBClLogError("Error sending SelectionNotify(1) event to wnd=%#x: %s\n",
-                             pEvReq->requestor, gX11->xErrorToString(xRc).c_str());
+                VBClLogError("Error sending SelectionNotify(1) event to window %#x ('%s'): %s\n",
+                             pEvReq->requestor, pszWndTgtName, gX11->xErrorToString(xRc).c_str());
+
             XFlush(pEvReq->display);
-
-            if (pszWndName)
-                RTStrFree(pszWndName);
             break;
         }
@@ -1456,4 +1512,7 @@
             break;
     }
+
+    RTStrFree(pszWndTgtName);
+    pszWndTgtName = NULL;
 
     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
@@ -1726,4 +1785,19 @@
         XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy.hWnd, CurrentTime);
 
+        if (g_cVerbosity)
+        {
+            RTCString strMsg("Enter: Host -> Guest\n\n");
+            strMsg += RTCStringFmt("Allowed actions: %#x\n", dndListActionsAllowed);
+            strMsg += "Formats:\n";
+            for (size_t i = 0; i < lstActions.size(); i++)
+            {
+                if (i > 0)
+                    strMsg += "\n";
+                strMsg += lstActions.at(i);
+            }
+
+            VBClShowNotify(VBOX_DND_SHOWNOTIFY_HEADER, strMsg.c_str());
+        }
+
         m_enmMode  = HG;
         m_enmState = Dragging;
@@ -1741,4 +1815,7 @@
 int DragInstance::hgLeave(void)
 {
+    if (g_cVerbosity)
+        VBClShowNotify(VBOX_DND_SHOWNOTIFY_HEADER, "Leave: Host -> Guest");
+
     if (m_enmMode == HG) /* Only reset if in the right operation mode. */
         reset();
@@ -1774,9 +1851,12 @@
     mouseCursorMove(uPosX, uPosY);
 
+    /* Search for the application window below the cursor. */
+    Window wndBelowCursor       = gX11->applicationWindowBelowCursor(m_wndRoot);
+    char *pszWndBelowCursorName = wndX11GetNameA(wndBelowCursor);
+    AssertPtrReturn(pszWndBelowCursorName, VERR_NO_MEMORY);
+
     long newVer = -1; /* This means the current window is _not_ XdndAware. */
 
-    /* Search for the application window below the cursor. */
-    Window wndCursor = gX11->applicationWindowBelowCursor(m_wndRoot);
-    if (wndCursor != None)
+    if (wndBelowCursor != None)
     {
         /* Temp stuff for the XGetWindowProperty call. */
@@ -1788,10 +1868,10 @@
         /* Query the XdndAware property from the window. We are interested in
          * the version and if it is XdndAware at all. */
-        xRc = XGetWindowProperty(m_pDisplay, wndCursor, xAtom(XA_XdndAware),
+        xRc = XGetWindowProperty(m_pDisplay, wndBelowCursor, xAtom(XA_XdndAware),
                                  0, 2, False, AnyPropertyType,
                                  &atmTmp, &fmt, &cItems, &cbRemaining, &pcData);
         if (xRc != Success)
         {
-            VBClLogError("Error getting properties of cursor window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
+            VBClLogError("Error getting properties of cursor window=%#x: %s\n", wndBelowCursor, gX11->xErrorToString(xRc).c_str());
         }
         else
@@ -1801,5 +1881,5 @@
                 /** @todo Do we need to deal with this? */
                 VBClLogError("Wrong window properties for window %#x: pcData=%#x, iFmt=%d, cItems=%ul\n",
-                             wndCursor, pcData, fmt, cItems);
+                             wndBelowCursor, pcData, fmt, cItems);
             }
             else
@@ -1813,26 +1893,14 @@
     }
 
-#ifdef DEBUG
-    char *pszNameCursor = wndX11GetNameA(wndCursor);
-    AssertPtr(pszNameCursor);
-    char *pszNameCur = wndX11GetNameA(m_wndCur);
-    AssertPtr(pszNameCur);
+    char *pszWndCurName = wndX11GetNameA(m_wndCur);
+    AssertPtrReturn(pszWndCurName, VERR_NO_MEMORY);
 
     LogFlowThisFunc(("wndCursor=%x ('%s', Xdnd version %ld), wndCur=%x ('%s', Xdnd version %ld)\n",
-                     wndCursor, pszNameCursor, newVer, m_wndCur, pszNameCur, m_curVer));
-
-    RTStrFree(pszNameCursor);
-    RTStrFree(pszNameCur);
-#endif
-
-    if (   wndCursor != m_wndCur
-        && m_curVer  != -1)
-    {
-        LogFlowThisFunc(("XA_XdndLeave: window=%#x\n", m_wndCur));
-
-        char *pszWndName = wndX11GetNameA(m_wndCur);
-        AssertPtr(pszWndName);
-        VBClLogInfo("Left old window %#x ('%s'), Xdnd version=%ld\n", m_wndCur, pszWndName, newVer);
-        RTStrFree(pszWndName);
+                     wndBelowCursor, pszWndBelowCursorName, newVer, m_wndCur, pszWndCurName, m_curVer));
+
+    if (   wndBelowCursor != m_wndCur
+        && m_curVer       != -1)
+    {
+        VBClLogInfo("Left old window %#x ('%s'), supported Xdnd version %ld\n", m_wndCur, pszWndCurName, m_curVer);
 
         /* We left the current XdndAware window. Announce this to the current indow. */
@@ -1848,5 +1916,5 @@
         xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (xRc == 0)
-            VBClLogError("Error sending XA_XdndLeave event to old window=%#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
+            VBClLogError("Error sending leave event to old window %#x: %s\n", m_wndCur, gX11->xErrorToString(xRc).c_str());
 
         /* Reset our current window. */
@@ -1858,13 +1926,8 @@
      * Do we have a new Xdnd-aware window which now is under the cursor?
      */
-    if (   wndCursor != m_wndCur
-        && newVer    != -1)
-    {
-        LogFlowThisFunc(("XA_XdndEnter: window=%#x\n", wndCursor));
-
-        char *pszWndName = wndX11GetNameA(wndCursor);
-        AssertPtr(pszWndName);
-        VBClLogInfo("Entered new window %#x ('%s'), supports Xdnd version=%ld\n", wndCursor, pszWndName, newVer);
-        RTStrFree(pszWndName);
+    if (   wndBelowCursor != m_wndCur
+        && newVer         != -1)
+    {
+        VBClLogInfo("Entered new window %#x ('%s'), supports Xdnd version=%ld\n", wndBelowCursor, pszWndBelowCursorName, newVer);
 
         /*
@@ -1878,5 +1941,5 @@
         m.type         = ClientMessage;
         m.display      = m_pDisplay;
-        m.window       = wndCursor;
+        m.window       = wndBelowCursor;
         m.message_type = xAtom(XA_XdndEnter);
         m.format       = 32;
@@ -1893,26 +1956,27 @@
         m.data.l[XdndEnterType3]  = m_lstAtomFormats.value(2, None); /* Third data type to use. */
 
-        xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
+        xRc = XSendEvent(m_pDisplay, wndBelowCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (xRc == 0)
-            VBClLogError("Error sending XA_XdndEnter event to window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
+            VBClLogError("Error sending enter event to window %#x: %s\n", wndBelowCursor, gX11->xErrorToString(xRc).c_str());
     }
 
     if (newVer != -1)
     {
-        Assert(wndCursor != None);
-
-        LogFlowThisFunc(("XA_XdndPosition: xPos=%RU32, yPos=%RU32 to window=%#x\n", uPosX, uPosY, wndCursor));
+        Assert(wndBelowCursor != None);
+
+        Atom atmAction = toAtomAction(dndActionDefault);
+        LogFlowThisFunc(("strAction=%s\n", xAtomToString(atmAction).c_str()));
+
+        VBClLogInfo("Sent position event (%RU32 x %RU32) to window %#x ('%s') with actions '%s'\n",
+                    uPosX, uPosY, wndBelowCursor, pszWndBelowCursorName, xAtomToString(atmAction).c_str());
 
         /*
          * Send a XdndPosition event with the proposed action to the guest.
          */
-        Atom atmAction = toAtomAction(dndActionDefault);
-        LogFlowThisFunc(("strAction=%s\n", xAtomToString(atmAction).c_str()));
-
         XClientMessageEvent m;
         RT_ZERO(m);
         m.type         = ClientMessage;
         m.display      = m_pDisplay;
-        m.window       = wndCursor;
+        m.window       = wndBelowCursor;
         m.message_type = xAtom(XA_XdndPosition);
         m.format       = 32;
@@ -1923,7 +1987,7 @@
         m.data.l[XdndPositionAction]    = atmAction;                     /* Actions requested by the user. */
 
-        xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
+        xRc = XSendEvent(m_pDisplay, wndBelowCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
         if (xRc == 0)
-            VBClLogError("Error sending XA_XdndPosition event to current window=%#x: %s\n", wndCursor, gX11->xErrorToString(xRc).c_str());
+            VBClLogError("Error sending position event to current window %#x: %s\n", wndBelowCursor, gX11->xErrorToString(xRc).c_str());
     }
 
@@ -1935,9 +1999,12 @@
     else
     {
-        Assert(wndCursor != None);
-
-        m_wndCur = wndCursor;
+        Assert(wndBelowCursor != None);
+
+        m_wndCur = wndBelowCursor;
         m_curVer = newVer;
     }
+
+    RTStrFree(pszWndBelowCursorName);
+    RTStrFree(pszWndCurName);
 
     LogFlowFuncLeaveRC(rc);
@@ -1979,4 +2046,7 @@
     int rc = VbglR3DnDHGSendReqData(&m_dndCtx, szFormat);
     VBClLogInfo("Drop event from host resulted in: %Rrc\n", rc);
+
+    if (g_cVerbosity)
+        VBClShowNotify(VBOX_DND_SHOWNOTIFY_HEADER, "Drop: Host -> Guest");
 
     LogFlowFuncLeaveRC(rc);
@@ -2160,15 +2230,15 @@
 
         /* Determine the current window which currently has the XdndSelection set. */
-        Window wndSelection = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
-        LogFlowThisFunc(("wndSelection=%#x, wndProxy=%#x, wndCur=%#x\n", wndSelection, m_wndProxy.hWnd, m_wndCur));
+        Window wndSel = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
+        LogFlowThisFunc(("wndSel=%#x, wndProxy=%#x, wndCur=%#x\n", wndSel, m_wndProxy.hWnd, m_wndCur));
 
         /* Is this another window which has a Xdnd selection and not our proxy window? */
         if (   RT_SUCCESS(rc)
-            && wndSelection
-            && wndSelection != m_wndCur)
-        {
-            char *pszWndName = wndX11GetNameA(wndSelection);
-            AssertPtr(pszWndName);
-            VBClLogInfo("New guest source window %#x ('%s')\n", wndSelection, pszWndName);
+            && wndSel
+            && wndSel != m_wndCur)
+        {
+            char *pszWndSelName = wndX11GetNameA(wndSel);
+            AssertPtrReturn(pszWndSelName, VERR_NO_MEMORY);
+            VBClLogInfo("New guest source window %#x ('%s')\n", wndSel, pszWndSelName);
 
             /* Start over. */
@@ -2215,5 +2285,5 @@
                     {
                         VBClLogError("Error mapping proxy window to guest source window %#x ('%s'), rc=%Rrc\n",
-                                     wndSelection, pszWndName, rc);
+                                     wndSel, pszWndSelName, rc);
 
                         /* Reset the counter in any case. */
@@ -2223,5 +2293,5 @@
             }
 
-            RTStrFree(pszWndName);
+            RTStrFree(pszWndSelName);
         }
         else
@@ -2255,4 +2325,20 @@
     if (RT_FAILURE(rc2))
     {
+        switch (rc2)
+        {
+            case VERR_ACCESS_DENIED:
+            {
+                rc = VBClShowNotify(VBOX_DND_SHOWNOTIFY_HEADER,
+                                    "Drag and drop to the host either is not supported or disabled. "
+                                    "Please enable Guest to Host or Bidirectional drag and drop mode "
+                                    "or re-install the VirtualBox Guest Additions.");
+                AssertRC(rc);
+                break;
+            }
+
+            default:
+                break;
+        }
+
         VBClLogError("Error reporting pending drag and drop operation status to host: %Rrc\n", rc2);
         if (RT_SUCCESS(rc))
@@ -3088,5 +3174,5 @@
     if (xRc == 0)
     {
-        VBClLogError("Error sending XA_XdndFinished event to source window=%#x: %s\n",
+        VBClLogError("Error sending finished event to source window=%#x: %s\n",
                       hWndSource, gX11->xErrorToString(xRc).c_str());
 
