specified" popped up when drag and drop over multiple remote apps.
Root cause:
When drag over multiple remote apps, multiple pairs of dragEnter and
dragLeave messages are sending. The DnD state or the dropSource/dataObject
are messed up when handling the 2nd DragEnter with the 1st DragLeave at
the same time.
Solution:
Besides fixing this issue, fixed several other issues also to enhance the
handling for multiple pairs of messages in the same time:
1. In DnDController layer, avoid to reset the DnD state when handling the
message responded from agent for previous sessions.
2. In agent, only set the DnD state to be Ready when the previous
DoDragDrop is really cancelled by OLE.
3. In agent, only response to the button event when the drop is notified.
4. In agent, add a 2s timeout checking for cancelling process to avoid
conflicting with another DnDThread to create dropSrouce.
5. In agent, add a 2s timeout checking for dragBegin process to avoid
conflicting with previous dragBegin processing.
6. Add virtual prefix to the method "GetData".
#include "dndRpcV4.hh"
#include "tracer.hh"
#include "vmGuestDnDMgr.hh"
+#include "vmGuestDnDSrc.hh"
extern "C" {
#include "debug.h"
break;
}
}
+
+
+/**
+ * Got srcDragBegin from rpc with valid data. Create mSrc if the state machine
+ * is ready.
+ *
+ * @param[in] sessionId active DnD session id
+ * @param[in] capability controller capability
+ * @param[in] clip cross-platform clipboard data.
+ */
+
+void
+VMGuestDnDMgr::OnRpcSrcDragBegin(uint32 sessionId,
+ const CPClipboard *clip)
+{
+ TRACE_CALL();
+
+ if (!mDnDAllowed) {
+ g_debug("%s: DnD is not allowed.\n", __FUNCTION__);
+ return;
+ }
+
+ if (GUEST_DND_READY != mDnDState) {
+ g_debug("%s: Bad state: %d, reset\n", __FUNCTION__, mDnDState);
+ ResetDnD();
+ return;
+ }
+
+ if (mSrc) {
+ g_debug("%s: mSrc is not NULL\n", __FUNCTION__);
+ delete mSrc;
+ mSrc = NULL;
+ }
+
+ SetSessionId(sessionId);
+
+ ASSERT(clip);
+
+ mSrc = new VMGuestDnDSrc(this);
+ mSrc->OnRpcDragBegin(clip);
+}
virtual void AddUnityDnDDetTimeoutEvent();
virtual void AddHideDetWndTimerEvent();
virtual void CreateDnDRpcWithVersion(uint32 version);
+ virtual void OnRpcSrcDragBegin(uint32 sessionId,
+ const CPClipboard *clip);
private:
ToolsAppCtx *mToolsAppCtx;
static gboolean DnDUnityDetTimeout(void *clientData);
protected:
- void OnRpcSrcDragBegin(uint32 sessionId,
- const CPClipboard *clip);
+ virtual void OnRpcSrcDragBegin(uint32 sessionId,
+ const CPClipboard *clip) = 0;
void OnRpcQueryExiting(uint32 sessionId, int32 x, int32 y);
void OnRpcUpdateUnityDetWnd(uint32 sessionId,
bool show,
/* Callbacks from rpc for DnD source. */
void OnRpcUpdateMouse(uint32 sessionId, int32 x, int32 y);
void OnRpcDrop(uint32 sessionId, int32 x, int32 y);
- void OnRpcCancel(uint32 sessionId);
+ virtual void OnRpcCancel(uint32 sessionId);
void OnRpcGetFilesDone(uint32 sessionId,
bool success,
const uint8 *stagingDirCP,
#include "guestDnD.hh"
#include "guestDnDCPMgr.hh"
-#ifdef DND_VM
-#include "vmGuestDnDSrc.hh"
-#else
-#include "crtGuestDnDSrc.hh"
-#endif
-
extern "C" {
#include "debug.h"
}
}
-/**
- * Got srcDragBegin from rpc with valid data. Create mSrc if the state machine
- * is ready.
- *
- * @param[in] sessionId active DnD session id
- * @param[in] capability controller capability
- * @param[in] clip cross-platform clipboard data.
- */
-
-void
-GuestDnDMgr::OnRpcSrcDragBegin(uint32 sessionId,
- const CPClipboard *clip)
-{
- TRACE_CALL();
-
- if (!mDnDAllowed) {
- g_debug("%s: DnD is not allowed.\n", __FUNCTION__);
- return;
- }
-
- if (GUEST_DND_READY != mDnDState) {
- g_debug("%s: Bad state: %d, reset\n", __FUNCTION__, mDnDState);
- ResetDnD();
- return;
- }
-
- if (mSrc) {
- g_debug("%s: mSrc is not NULL\n", __FUNCTION__);
- delete mSrc;
- mSrc = NULL;
- }
-
- SetSessionId(sessionId);
-
- ASSERT(clip);
-
-#ifdef DND_VM
- mSrc = new VMGuestDnDSrc(this);
-#else
- mSrc = new CRTGuestDnDSrc(this);
-#endif
-
- mSrc->OnRpcDragBegin(clip);
-}
-
-
/**
* Got queryExiting from rpc. Show the detection window on (x, y) to try to
* detect any pending GH DnD.