]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Implement capabilities for DnD/CP.
authorVMware, Inc <>
Thu, 24 Feb 2011 22:39:23 +0000 (14:39 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 24 Feb 2011 22:39:23 +0000 (14:39 -0800)
Implement capabilities exchange and add support for new isolation
settings in VMX. The general idea is that each side (host, guest)
transmits to the controller its capabilities (DnD/CP support,
ability to provide certain clipboard types) in a PING request. VMX
file settings can be used to disable a variety of clipboard content,
direction combinations. For example, RTF DnD in the guest to host
direction can be disabled. In the PING response, controller will
provide a requisition to the request, telling the host or guest
what types of DnD/CP content are allowed on the clipboard. When
preparing the clipboard for transmission, the host or guest checks
this requisition and will not supply formats that are not allowed.

The controller will enforce this by removing any clipboard contents
that do not match the published requisition, so in case the guest
or host does not do the right thing, or ignores the requisition in
the ping reply, the controller will catch it. If any of this
processing causes the clipboard received by the controller to be
empty, the DnD or CP operation does not continue.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
26 files changed:
open-vm-tools/lib/include/capsProvider.h [new file with mode: 0644]
open-vm-tools/services/plugins/dndcp/copyPasteDnDImpl.h
open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.cpp
open-vm-tools/services/plugins/dndcp/copyPasteDnDWrapper.h
open-vm-tools/services/plugins/dndcp/copyPasteDnDX11.cpp
open-vm-tools/services/plugins/dndcp/copyPasteDnDX11.h
open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp
open-vm-tools/services/plugins/dndcp/dnd/copyPasteRpc.hh
open-vm-tools/services/plugins/dndcp/dnd/copyPasteRpcV4.hh
open-vm-tools/services/plugins/dndcp/dnd/dndCPMsgV4.h
open-vm-tools/services/plugins/dndcp/dnd/dndClipboard.c
open-vm-tools/services/plugins/dndcp/dnd/dndClipboard.h
open-vm-tools/services/plugins/dndcp/dnd/dndRpc.hh
open-vm-tools/services/plugins/dndcp/dnd/dndRpcV4.hh
open-vm-tools/services/plugins/dndcp/dndGuest/copyPasteRpcV3.cc
open-vm-tools/services/plugins/dndcp/dndGuest/copyPasteRpcV3.hh
open-vm-tools/services/plugins/dndcp/dndGuest/copyPasteRpcV4.cc
open-vm-tools/services/plugins/dndcp/dndGuest/dndRpcV3.hh
open-vm-tools/services/plugins/dndcp/dndGuest/dndRpcV4.cc
open-vm-tools/services/plugins/dndcp/dndGuest/guestCopyPaste.hh
open-vm-tools/services/plugins/dndcp/dndGuest/guestCopyPasteMgr.cc
open-vm-tools/services/plugins/dndcp/dndGuest/guestDnD.hh
open-vm-tools/services/plugins/dndcp/dndGuest/guestDnDCPMgr.cc
open-vm-tools/services/plugins/dndcp/dndGuest/guestDnDCPMgr.hh
open-vm-tools/services/plugins/dndcp/dndGuest/guestDnDMgr.cc
open-vm-tools/services/plugins/dndcp/dndUIX11.cpp

diff --git a/open-vm-tools/lib/include/capsProvider.h b/open-vm-tools/lib/include/capsProvider.h
new file mode 100644 (file)
index 0000000..22f1fdc
--- /dev/null
@@ -0,0 +1,50 @@
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * capsProvider.h --
+ *
+ *      Interface implemented by dnd manager objects to obtain their
+ *      capabilities. Mainly needed by Windows host and guest code.
+ */
+
+#ifndef __CAPS_PROVIDER_H__
+#define __CAPS_PROVIDER_H__
+
+#if defined VMX86_TOOLS || COMPILE_WITHOUT_CUI
+#   ifdef LIB_EXPORT
+#   undef LIB_EXPORT
+#   endif
+#define LIB_EXPORT
+#else
+#include "libExport.hh"
+#endif
+
+#if defined(SWIG)
+class CapsProvider
+#else
+class LIB_EXPORT CapsProvider
+#endif
+{
+public:
+   virtual ~CapsProvider() {};
+   virtual Bool CheckCapability(uint32 caps) = 0;
+};
+
+#endif
+
index dd0d5e01bb37467f908892d289faa6dfb2c91a38..a8a5d242cd31a88f3df5fcf9f5fdb4ed5c8c6ce7 100644 (file)
@@ -46,6 +46,7 @@ public:
    virtual void DnDVersionChanged(const int version) = 0;
    virtual void SetCopyPasteAllowed(bool allowed) = 0;
    virtual void SetDnDAllowed(bool allowed) = 0;
+   virtual uint32 GetCaps() = 0;
 };
 
 #endif // __COPYPASTEDNDIMPL_H__
index 43c3d9849fcc123214cee71873381314436dbfde..d2f81d23c07fea17f7ca3d4b48d2f2b265f6bc72 100644 (file)
@@ -141,9 +141,9 @@ CopyPasteDnDWrapper::Init(ToolsAppCtx *ctx)
    /*
     * We only support DnD/CP V3 and greater.
     */
+   GuestDnDCPMgr *p = GuestDnDCPMgr::GetInstance();
+   ASSERT(p);
    if (GetDnDVersion() >= 3 && GetCPVersion() >= 3 || GetCPVersion() == 1) {
-      GuestDnDCPMgr *p = GuestDnDCPMgr::GetInstance();
-      ASSERT(p);
       p->Init(ctx);
    }
 
@@ -159,6 +159,10 @@ CopyPasteDnDWrapper::Init(ToolsAppCtx *ctx)
 #endif
       if (m_pimpl) {
          m_pimpl->Init(ctx);
+         /*
+          * Tell the Guest DnD Manager what capabilities we support.
+          */
+         p->SetCaps(m_pimpl->GetCaps());
       }
    }
 }
@@ -671,3 +675,18 @@ CopyPasteDnDWrapper::OnSetOption(const char *option, const char *value)
 
    return ret;
 }
+
+
+/**
+ * Get capabilities by calling platform implementation.
+ *
+ * @return 32-bit mask of DnD/CP capabilities.
+ */
+
+uint32
+CopyPasteDnDWrapper::GetCaps()
+{
+   ASSERT(m_pimpl);
+
+   return m_pimpl->GetCaps();
+}
index ced5d66f2918b665ba27d3fd8d9496fb5b688bd0..3f1e8c4938145327d745bf785e83a526f939d2ce 100644 (file)
@@ -59,6 +59,7 @@ public:
    void Init(ToolsAppCtx *ctx);
    void PointerInit(void);
    ToolsAppCtx *GetToolsAppCtx() {return m_ctx;};
+   uint32 GetCaps();
 private:
    /*
     * We're a singleton, so it is a compile time error to call these.
index 0c5ec5ff1d2781b92e200b7a8df5fed703c7dabd..f377ce724af726f252d491ab79d97adcf17f5a6b 100644 (file)
@@ -523,3 +523,21 @@ CopyPasteDnDX11::PointerInit()
 
    Pointer_Init(ctx);
 }
+
+
+/**
+ * Return platform DnD/CP caps.
+ *
+ * @return 32-bit caps vector.
+ */
+
+uint32
+CopyPasteDnDX11::GetCaps()
+{
+   return DND_CP_CAP_VALID |
+          DND_CP_CAP_DND |
+          DND_CP_CAP_CP |
+          DND_CP_CAP_FORMATS_ALL |
+          DND_CP_CAP_ACTIVE_CP |
+          DND_CP_CAP_BIG_BUFFER;
+}
index bdb9221eb285e1b6cf5221bf40070c98e8834957..a8b6e2566c1a921cf5b1f4c849d122d20d018a5e 100644 (file)
@@ -54,6 +54,7 @@ public:
    virtual void UnregisterDnD();
    virtual void DnDVersionChanged(int version);
    virtual void CopyPasteVersionChanged(int version);
+   virtual uint32 GetCaps();
    void SetUnityMode(Bool mode) {m_dndUI->SetUnityMode(mode);};
    void SetDnDAllowed(bool allowed);
    void SetCopyPasteAllowed(bool allowed);
index 095450dfd06bed7d8f4e415e2f39f47ab3d3eebf..e45d72c5218475b9d7a2e2fe1209bdbc382cdd4a 100644 (file)
@@ -631,10 +631,10 @@ again:
    /* First check for URIs. This must always be done first */
    bool haveURIs = false;
    std::string format;
-   if (refClipboard->wait_is_target_available(FCP_TARGET_NAME_GNOME_COPIED_FILES)) {
+   if (mCP->CheckCapability(DND_CP_CAP_FILE_CP) && refClipboard->wait_is_target_available(FCP_TARGET_NAME_GNOME_COPIED_FILES)) {
       format = FCP_TARGET_NAME_GNOME_COPIED_FILES;
       haveURIs = true;
-   } else if (refClipboard->wait_is_target_available(FCP_TARGET_NAME_URI_LIST)) {
+   } else if (mCP->CheckCapability(DND_CP_CAP_FILE_CP) && refClipboard->wait_is_target_available(FCP_TARGET_NAME_URI_LIST)) {
       format = FCP_TARGET_NAME_URI_LIST;
       haveURIs = true;
    }
@@ -649,7 +649,7 @@ again:
    /* Try to get image data from clipboard. */
    Glib::RefPtr<Gdk::Pixbuf> img = refClipboard->wait_for_image();
    gsize bufSize;
-   if (img) {
+   if (mCP->CheckCapability(DND_CP_CAP_IMAGE_CP) && img) {
       gchar *buf = NULL;
 
       img->save_to_buffer(buf, bufSize, Glib::ustring("png"));
@@ -678,7 +678,7 @@ again:
       haveRTF = true;
    }
 
-   if (haveRTF) {
+   if (mCP->CheckCapability(DND_CP_CAP_RTF_CP) && haveRTF) {
       /*
        * There is a function for waiting for rtf data, but that was leading
        * to crashes. It's use required we instantiate a class that implements
@@ -701,7 +701,8 @@ again:
    }
 
    /* Try to get Text data from clipboard. */
-   if (refClipboard->wait_is_text_available()) {
+   if (mCP->CheckCapability(DND_CP_CAP_PLAIN_TEXT_CP) &&
+       refClipboard->wait_is_text_available()) {
       g_debug("%s: ask for text\n", __FUNCTION__);
       Glib::ustring str = refClipboard->wait_for_text();
       bufSize = str.bytes();
@@ -763,6 +764,12 @@ CopyPasteUIX11::LocalReceivedFileListCB(const Gtk::SelectionData& sd)        //
    g_debug("%s: enter", __FUNCTION__);
    const utf::string target = sd.get_target().c_str();
 
+   if (!mCP->CheckCapability(DND_CP_CAP_FILE_CP)) {
+      /*
+       * Disallowed based on caps settings, return.
+       */
+      return;
+   }
    if (target == FCP_TARGET_NAME_GNOME_COPIED_FILES ||
        target == FCP_TARGET_NAME_URI_LIST) {
       LocalGetSelectionFileList(sd);
@@ -799,6 +806,13 @@ CopyPasteUIX11::LocalGetFileContentsRequestCB(Gtk::SelectionData& sd, // IN
    utf::string pre;
    utf::string post;
 
+   if (!mCP->CheckCapability(DND_CP_CAP_FILE_CONTENT_CP)) {
+      /*
+       * Disallowed based on caps settings, return.
+       */
+      return;
+   }
+
    sd.set(sd.get_target().c_str(), "");
 
    /* Provide URIs for each path in the guest's file list. */
index 8ce3d2650cb8c03cd241f458885a986f18460325..33c452ffe93e9c4f7d6bde3fa1e70b0ea99e17d0 100644 (file)
@@ -44,10 +44,17 @@ public:
    sigc::signal<void, uint32, const uint8 *, uint32> requestFilesChanged;
    sigc::signal<void, uint32, bool, const uint8 *, uint32> getFilesDoneChanged;
 
-   /* sigc signals for CopyPaste destination callback. */
+   /* sigc signal for CopyPaste destination callback. */
    sigc::signal<void, uint32, bool> destRequestClipChanged;
 
+   /* sigc signal for ping reply callback. */
+   sigc::signal<void, uint32> pingReplyChanged;
+
+   /* sigc signal for rpc command reply received. */
+   sigc::signal<void, uint32, uint32> cmdReplyChanged;
+
    virtual void Init(void) = 0;
+   virtual void SendPing(uint32 caps) = 0;
 
    /* CopyPaste Rpc functions. */
    virtual bool SrcRequestClip(uint32 sessionId,
index 6c64671c865ea7208ccfa11b70e98e9f764909fc..cd911c1e0f3dc6c850f447bde43268e6324974db 100644 (file)
@@ -42,8 +42,8 @@ class LIB_EXPORT CopyPasteRpcV4
 {
 public:
    CopyPasteRpcV4(DnDCPTransport *transport);
-
    virtual void Init(void);
+   virtual void SendPing(uint32 caps);
 
    /* CopyPaste Rpc functions. */
    virtual bool SrcRequestClip(uint32 sessionId,
index bea29dcd09a625c9c05b151ada167c256ad33b7c..235c5d8e8b3fc9617d650ce7c82e8d7d9c4eeec0 100644 (file)
@@ -174,6 +174,21 @@ typedef enum DnDCPMsgPacketType {
 #define DND_CP_CAP_GUEST_PROGRESS   (1 << 14)
 #define DND_CP_CAP_BIG_BUFFER       (1 << 15)
 
+#define DND_CP_CAP_FORMATS_CP       (DND_CP_CAP_PLAIN_TEXT_CP   | \
+                                     DND_CP_CAP_RTF_CP          | \
+                                     DND_CP_CAP_IMAGE_CP        | \
+                                     DND_CP_CAP_FILE_CP         | \
+                                     DND_CP_CAP_FILE_CONTENT_CP)
+
+#define DND_CP_CAP_FORMATS_DND      (DND_CP_CAP_PLAIN_TEXT_DND  | \
+                                     DND_CP_CAP_RTF_DND         | \
+                                     DND_CP_CAP_IMAGE_DND       | \
+                                     DND_CP_CAP_FILE_DND        | \
+                                     DND_CP_CAP_FILE_CONTENT_DND)
+
+#define DND_CP_CAP_FORMATS_ALL      (DND_CP_CAP_FORMATS_CP      | \
+                                     DND_CP_CAP_FORMATS_DND)
+
 /*
  * Header definition for DnD version 4 packet. Any DnD version 4 packet has 2
  * parts: fixed header and payload. payload is optional.
index 1da6ab65a0fced510c113fe91a0e9f8368a7d3e3..113ceb64e5d2d2ff4e6c5e386d1396c412e5fcb0 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "dndClipboard.h"
 #include "dndInt.h"
+#include "dndCPMsgV4.h"
 
 
 #define CPFormatToIndex(x) ((unsigned int)(x) - 1)
@@ -690,3 +691,51 @@ error:
    CPClipboard_Destroy(clip);
    return FALSE;
 }
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * CPClipboard_Strip --
+ *
+ *      Remove clipboard items based on the passed in capabilities mask.
+ *      Introduced in DnDV4.
+ *
+ *      XXX This function assumes that the bits in mask are such that if the
+ *      check is being made for copy paste, that the corresponding bit for
+ *      DnD is set to zero. Otherwise, the format cleared by copy paste will
+ *      not be removed. Similar for the other case. A way to make this clearer
+ *      would be to pass a flag to this function that tells it which bits
+ *      to check, with no dependencies on the other bits being in proper
+ *      state.
+ *
+ * Results:
+ *      TRUE if clipboard is empty as a result, else FALSE.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+CPClipboard_Strip(CPClipboard *clip,    // IN/OUT: the clipboard
+                  uint32 mask)          // IN: if TRUE, DnD.
+{
+   if (!(mask & DND_CP_CAP_PLAIN_TEXT_DND) &&
+       !(mask & DND_CP_CAP_PLAIN_TEXT_CP)) {
+      CPClipboard_ClearItem(clip, CPFORMAT_TEXT);
+   }
+   if (!(mask & DND_CP_CAP_RTF_DND) && !(mask & DND_CP_CAP_RTF_CP)) {
+      CPClipboard_ClearItem(clip, CPFORMAT_RTF);
+   }
+   if (!(mask & DND_CP_CAP_IMAGE_DND) && !(mask & DND_CP_CAP_IMAGE_CP)) {
+      CPClipboard_ClearItem(clip, CPFORMAT_IMG_PNG);
+   }
+   if (!(mask & DND_CP_CAP_FILE_DND) && !(mask & DND_CP_CAP_FILE_CP)) {
+      CPClipboard_ClearItem(clip, CPFORMAT_FILELIST);
+      CPClipboard_ClearItem(clip, CPFORMAT_FILELIST_URI);
+   }
+   if (!(mask & DND_CP_CAP_FILE_CONTENT_DND) &&
+       !(mask & DND_CP_CAP_FILE_CONTENT_CP)) {
+      CPClipboard_ClearItem(clip, CPFORMAT_FILECONTENTS);
+   }
+   return CPClipboard_IsEmpty(clip);
+}
index f6f10c0dbec8fcf044ae90bac3170abc07dfe6a1..e9210b01f00b648793a922443a0cb80f02f0114b 100644 (file)
@@ -133,5 +133,6 @@ size_t CPClipboard_GetTotalSize(const CPClipboard *clip);
 Bool CPClipboard_Copy(CPClipboard *dest, const CPClipboard *src);
 Bool CPClipboard_Serialize(const CPClipboard *clip, DynBuf *buf);
 Bool CPClipboard_Unserialize(CPClipboard *clip, const void *buf, size_t len);
+Bool CPClipboard_Strip(CPClipboard *clip, uint32 caps);
 
 #endif // _DND_CLIPBOARD_H_
index 9747ddc58fc452df4ee9ca33d091465351993f47..486cd21c540f4deac15b08dfceff3ddb6d821e2d 100644 (file)
@@ -60,6 +60,12 @@ public:
    sigc::signal<void, uint32, const uint8 *, uint32> requestFileChanged;
    sigc::signal<void, uint32, bool, const uint8 *, uint32> getFilesDoneChanged;
 
+   /* sigc signal for responding to ping reply */
+   sigc::signal<void, uint32> pingReplyChanged;
+
+   /* sigc signal for rpc cmd reply received. */
+   sigc::signal<void, uint32, uint32> cmdReplyChanged;
+
    /* DnD source. */
    virtual bool SrcDragBeginDone(uint32 sessionId) = 0;
    virtual bool SrcDrop(uint32 sessionId, int32 x, int32 y) = 0;
@@ -83,6 +89,7 @@ public:
 
    /* Common. */
    virtual void Init(void) = 0;
+   virtual void SendPing(uint32 caps) = 0;
    virtual bool UpdateFeedback(uint32 sessionId, DND_DROPEFFECT feedback) = 0;
    virtual bool MoveMouse(uint32 sessionId,
                           int32 x,
index b5e5594297e02bbc97a456b983d98beb8247b7f4..b420f92dfbaba94355dec7a45dd445990e5cc892 100644 (file)
@@ -44,6 +44,7 @@ public:
    DnDRpcV4(DnDCPTransport *transport);
 
    virtual void Init(void);
+   virtual void SendPing(uint32 caps);
 
    /* DnD source. */
    virtual bool SrcDragBeginDone(uint32 sessionId);
index 0a5374ae1f075b0659b46f078e9d9c93a3b4a050..268501ce2c4412acb1050e3bc29c9e3f8e31ba8c 100644 (file)
@@ -69,6 +69,19 @@ CopyPasteRpcV3::Init(void)
 }
 
 
+/**
+ * Not needed for version 3.
+ *
+ * @param[ignored] caps capabilities mask
+ */
+
+void
+CopyPasteRpcV3::SendPing(uint32 caps)
+{
+   Debug("%s: entering.\n", __FUNCTION__);
+}
+
+
 /**
  * Not needed for version 3.
  *
index f73729d80202069587603524e8f580ea3b0fbb59..411f748c4ed1c5847cefd4fe4eab7fa82254cfc5 100644 (file)
@@ -45,6 +45,7 @@ public:
    virtual ~CopyPasteRpcV3(void);
 
    virtual void Init(void);
+   virtual void SendPing(uint32 caps);
 
    /* CopyPaste Rpc functions. */
    virtual bool SrcRequestClip(uint32 sessionId,
index caad812b11bdc7396456834fef756c0fdc27d67b..8bf1426f0dad3000827573d3b9b2113b5be6b390 100644 (file)
@@ -67,11 +67,23 @@ CopyPasteRpcV4::CopyPasteRpcV4(DnDCPTransport *transport)
  */
 
 void
-CopyPasteRpcV4::Init(void)
+CopyPasteRpcV4::Init()
 {
    ASSERT(mTransport);
    mTransport->RegisterRpc(this, mTransportInterface);
-   mUtil.SendPingMsg(DEFAULT_CONNECTION_ID, 0);
+}
+
+
+/**
+ * Send Ping message to controller.
+ *
+ * @param[in] caps capabilities value.
+ */
+
+void
+CopyPasteRpcV4::SendPing(uint32 caps)
+{
+   mUtil.SendPingMsg(DEFAULT_CONNECTION_ID, caps);
 }
 
 
@@ -283,6 +295,13 @@ CopyPasteRpcV4::HandleMsg(RpcParams *params,
                                binary,
                                binarySize);
       break;
+   case DNDCP_CMD_PING_REPLY:
+      pingReplyChanged.emit(params->optional.version.capability);
+      break;
+   case DNDCP_CMP_REPLY:
+      LOG(0, ("%s: Got cmp reply command %d.\n", __FUNCTION__, params->cmd));
+      cmdReplyChanged.emit(params->cmd, params->status);
+      break;
    default:
       LOG(0, ("%s: Got unknown command %d.\n", __FUNCTION__, params->cmd));
       break;
index 3f76985e74df8865289be557a7d34f93bf80936d..6673a12e11869c0cac9d2f3460c2ec4f9c1bc3d1 100644 (file)
@@ -45,6 +45,7 @@ public:
    virtual ~DnDRpcV3(void);
 
    virtual void Init(void);
+   virtual void SendPing(uint32 caps) {};
 
    /* DnD source. */
    virtual bool SrcDragBeginDone(uint32 sessionId);
index c8ecc93a60c79b9235ef0a38f5db63a360c78b90..6a300631d239bb8102b7bbba258b28c727aa0528 100644 (file)
@@ -68,11 +68,23 @@ DnDRpcV4::DnDRpcV4(DnDCPTransport *transport)
  */
 
 void
-DnDRpcV4::Init(void)
+DnDRpcV4::Init()
 {
    ASSERT(mTransport);
    mTransport->RegisterRpc(this, mTransportInterface);
-   mUtil.SendPingMsg(DEFAULT_CONNECTION_ID, 0);
+}
+
+
+/**
+ * Send Ping message to controller.
+ *
+ * @param[in] caps capabilities value.
+ */
+
+void
+DnDRpcV4::SendPing(uint32 caps)
+{
+   mUtil.SendPingMsg(DEFAULT_CONNECTION_ID, caps);
 }
 
 
@@ -718,6 +730,7 @@ DnDRpcV4::HandleMsg(RpcParams *params,
                                binarySize);
       break;
    case DNDCP_CMD_PING_REPLY:
+      pingReplyChanged.emit(params->optional.version.capability);
       break;
    case DNDCP_CMD_TEST_BIG_BINARY:
    {
@@ -744,6 +757,10 @@ DnDRpcV4::HandleMsg(RpcParams *params,
 
       break;
    }
+   case DNDCP_CMP_REPLY:
+      LOG(0, ("%s: Got cmp reply command %d.\n", __FUNCTION__, params->cmd));
+      cmdReplyChanged.emit(params->cmd, params->status);
+      break;
    default:
       LOG(0, ("%s: Got unknown command %d.\n", __FUNCTION__, params->cmd));
       break;
index 45fb1b2f86d3f7b9103e44dcf24eb1259b28820b..6eebdbf881cfd761a9c181d7e887d5080a2df717 100644 (file)
@@ -71,13 +71,14 @@ public:
    void SetCopyPasteAllowed(bool isCopyPasteAllowed)
    { mCopyPasteAllowed = isCopyPasteAllowed; }
    void VmxCopyPasteVersionChanged(uint32 version);
-
+   Bool CheckCapability(uint32 capsRequest);
 private:
    void OnRpcSrcRecvClip(uint32 sessionId,
                          bool isActive,
                          const CPClipboard *clip);
    void OnRpcDestRequestClip(uint32 sessionId,
                              bool isActive);
+   void OnPingReply(uint32 capabilities);
    GuestCopyPasteSrc *mSrc;
    GuestCopyPasteDest *mDest;
    CopyPasteRpc *mRpc;
@@ -85,6 +86,7 @@ private:
    DnDCPTransport *mTransport;
    uint32 mSessionId;
    bool mCopyPasteAllowed;
+   uint32 mResolvedCaps;       // caps as returned in ping reply, or default.
 };
 
 
index c3925d78edd17fcc75bc35d52e29de297724db2a..52a04c59baebeb51e94e06a35836fe62fb8b1d9c 100644 (file)
@@ -25,6 +25,7 @@
 #include "guestCopyPaste.hh"
 #include "copyPasteRpcV3.hh"
 #include "copyPasteRpcV4.hh"
+#include "guestDnDCPMgr.hh"
 
 extern "C" {
    #include "debug.h"
@@ -44,7 +45,8 @@ GuestCopyPasteMgr::GuestCopyPasteMgr(DnDCPTransport *transport)
    mCPState(GUEST_CP_READY),
    mTransport(transport),
    mSessionId(0),
-   mCopyPasteAllowed(false)
+   mCopyPasteAllowed(false),
+   mResolvedCaps(0xffffffff)
 {
    ASSERT(transport);
 }
@@ -235,12 +237,53 @@ GuestCopyPasteMgr::VmxCopyPasteVersionChanged(uint32 version)
       break;
    }
    if (mRpc) {
-      mRpc->Init();
+      Debug("GuestCopyPasteMgr::%s: register ping reply changed %d\n",
+            __FUNCTION__, version);
+      mRpc->pingReplyChanged.connect(
+         sigc::mem_fun(this, &GuestCopyPasteMgr::OnPingReply));
       mRpc->srcRecvClipChanged.connect(
          sigc::mem_fun(this, &GuestCopyPasteMgr::OnRpcSrcRecvClip));
       mRpc->destRequestClipChanged.connect(
          sigc::mem_fun(this, &GuestCopyPasteMgr::OnRpcDestRequestClip));
+      mRpc->Init();
+      mRpc->SendPing(GuestDnDCPMgr::GetInstance()->GetCaps() &
+                     (DND_CP_CAP_CP | DND_CP_CAP_FORMATS_CP | DND_CP_CAP_VALID));
    }
 
    ResetCopyPaste();
 }
+
+
+/**
+ * Check if a request is allowed based on resolved capabilities.
+ *
+ * @param[in] capsRequest requested capabilities.
+ *
+ * @return TRUE if allowed, FALSE otherwise.
+ */
+
+Bool
+GuestCopyPasteMgr::CheckCapability(uint32 capsRequest)
+{
+   Bool allowed = FALSE;
+
+   if ((mResolvedCaps & capsRequest) == capsRequest) {
+      allowed = TRUE;
+   }
+   return allowed;
+}
+
+
+/**
+ * Got pingReplyChanged message. Update capabilities.
+ *
+ * @param[in] capability modified capabilities from VMX controller.
+ */
+
+void
+GuestCopyPasteMgr::OnPingReply(uint32 capabilities)
+{
+   Debug("%s: copypaste ping reply caps are %x\n", __FUNCTION__, capabilities);
+   mResolvedCaps = capabilities;
+}
+
index 07d3fac63251dab6a18187a71595e23b9efbf1ff..d96adc65af2eb4fbbdc77851e788adb15e3d46a6 100644 (file)
@@ -29,6 +29,8 @@
 #include "dndRpcV4.hh"
 #include "guestFileTransfer.hh"
 
+#include "capsProvider.h"
+
 #include <string>
 
 extern "C" {
@@ -54,7 +56,7 @@ class GuestDnDSrc;
 class GuestDnDDest;
 
 class GuestDnDMgr
-   : public sigc::trackable
+   : public sigc::trackable, public CapsProvider
 {
 public:
    GuestDnDMgr(DnDCPTransport *transport,
@@ -103,7 +105,7 @@ public:
    { mDnDAllowed = isDnDAllowed;}
    void VmxDnDVersionChanged(uint32 version);
    bool IsDragEnterAllowed(void);
-
+   Bool CheckCapability(uint32 capsRequest);
 private:
    void OnRpcSrcDragBegin(uint32 sessionId,
                           const CPClipboard *clip);
@@ -114,6 +116,8 @@ private:
    void OnRpcMoveMouse(uint32 sessionId,
                        int32 x,
                        int32 y);
+   void OnPingReply(uint32 capabilities);
+
    GuestDnDSrc *mSrc;
    GuestDnDDest *mDest;
    DnDRpc *mRpc;
@@ -127,6 +131,7 @@ private:
    bool mDnDAllowed;
    uint32 mVmxDnDVersion;
    DnDCPTransport *mDnDTransport;
+   uint32 mCapabilities;
 };
 
 
index e86aa76a1464b37d6cc59e030c62b767e5260312..2172b136bbf66426c2e6cf39e5a9fbce4408ef52 100644 (file)
@@ -47,7 +47,8 @@ GuestDnDCPMgr::GuestDnDCPMgr()
      mCPMgr(NULL),
      mFileTransfer(NULL),
      mTransport(NULL),
-     mToolsAppCtx(NULL)
+     mToolsAppCtx(NULL),
+     mLocalCaps(0xffffffff)
 {
 }
 
@@ -233,4 +234,3 @@ GuestDnDCPMgr::EndLoop()
       mTransport->EndLoop();
    }
 }
-
index 25b90e457ab6b5669fd038e86352ddf250148e39..de56149c69e1738975cd09ca739dbcc5902d6dd1 100644 (file)
@@ -49,7 +49,8 @@ public:
    void EndLoop();
    void IterateLoop();
    void Init(ToolsAppCtx *ctx);
-
+   void SetCaps(uint32 caps) {mLocalCaps = caps;};
+   uint32 GetCaps() {return mLocalCaps;};
 private:
    /* We're a singleton, so it is a compile time error to call these. */
    GuestDnDCPMgr(void);
@@ -62,6 +63,7 @@ private:
    GuestFileTransfer *mFileTransfer;
    DnDCPTransport *mTransport;
    ToolsAppCtx *mToolsAppCtx;
+   uint32 mLocalCaps;
 };
 
 #endif // GUEST_DND_CP_HH
index eb934812a7b13e959c94ff09912aec02e376d14d..aec94b58b831a15aaa274f72f7bb9c6e0b7a99d5 100644 (file)
@@ -25,6 +25,7 @@
 #include "guestDnD.hh"
 #include "dndRpcV4.hh"
 #include "dndRpcV3.hh"
+#include "guestDnDCPMgr.hh"
 
 extern "C" {
    #include "debug.h"
@@ -117,7 +118,8 @@ GuestDnDMgr::GuestDnDMgr(DnDCPTransport *transport,
    mUngrabTimeout(NULL),
    mToolsAppCtx(ctx),
    mDnDAllowed(false),
-   mDnDTransport(transport)
+   mDnDTransport(transport),
+   mCapabilities(0xffffffff)
 {
    ASSERT(transport);
    ASSERT(mToolsAppCtx);
@@ -610,7 +612,8 @@ GuestDnDMgr::VmxDnDVersionChanged(uint32 version)
       break;
    }
    if (mRpc) {
-      mRpc->Init();
+      mRpc->pingReplyChanged.connect(
+         sigc::mem_fun(this, &GuestDnDMgr::OnPingReply));
       mRpc->srcDragBeginChanged.connect(
          sigc::mem_fun(this, &GuestDnDMgr::OnRpcSrcDragBegin));
       mRpc->queryExitingChanged.connect(
@@ -619,7 +622,46 @@ GuestDnDMgr::VmxDnDVersionChanged(uint32 version)
          sigc::mem_fun(this, &GuestDnDMgr::OnRpcUpdateUnityDetWnd));
       mRpc->moveMouseChanged.connect(
          sigc::mem_fun(this, &GuestDnDMgr::OnRpcMoveMouse));
+      mRpc->Init();
+      mRpc->SendPing(GuestDnDCPMgr::GetInstance()->GetCaps() &
+                     (DND_CP_CAP_DND | DND_CP_CAP_FORMATS_DND |
+                      DND_CP_CAP_VALID));
    }
 
    ResetDnD();
 }
+
+
+/**
+ * Check if a request is allowed based on resolved capabilities.
+ *
+ * @param[in] capsRequest requested capabilities.
+ *
+ * @return TRUE if allowed, FALSE otherwise.
+ */
+
+Bool
+GuestDnDMgr::CheckCapability(uint32 capsRequest)
+{
+   Bool allowed = FALSE;
+
+   if ((mCapabilities & capsRequest) == capsRequest) {
+      allowed = TRUE;
+   }
+   return allowed;
+}
+
+
+/**
+ * Got pingReplyChanged message. Update capabilities.
+ *
+ * @param[in] capability modified capabilities from VMX controller.
+ */
+
+void
+GuestDnDMgr::OnPingReply(uint32 capabilities)
+{
+   Debug("%s: dnd ping reply caps are %x\n", __FUNCTION__, capabilities);
+   mCapabilities = capabilities;
+}
+
index a83312619ceb89affd4859681a158a2302db283d..0dff137ce450220718b5923440f3965710a7b887 100644 (file)
@@ -1152,7 +1152,7 @@ DnDUIX11::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
    const utf::string target = sd.get_target().c_str();
 
    /* Try to get file list. */
-   if (target == DRAG_TARGET_NAME_URI_LIST) {
+   if (m_DnD->CheckCapability(DND_CP_CAP_FILE_DND) && target == DRAG_TARGET_NAME_URI_LIST) {
       /*
        * Turn the uri list into two \0  delimited lists. One for full paths and
        * one for just the last path component.
@@ -1229,10 +1229,11 @@ DnDUIX11::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
    }
 
    /* Try to get plain text. */
-   if (target == TARGET_NAME_STRING ||
+   if (m_DnD->CheckCapability(DND_CP_CAP_PLAIN_TEXT_DND) && (
+       target == TARGET_NAME_STRING ||
        target == TARGET_NAME_TEXT_PLAIN ||
        target == TARGET_NAME_UTF8_STRING ||
-       target == TARGET_NAME_COMPOUND_TEXT) {
+       target == TARGET_NAME_COMPOUND_TEXT)) {
       utf::string source = sd.get_data_as_string().c_str();
       if (source.bytes() > 0 &&
           source.bytes() < DNDMSG_MAX_ARGSZ &&
@@ -1247,8 +1248,9 @@ DnDUIX11::SetCPClipboardFromGtk(const Gtk::SelectionData& sd) // IN
    }
 
    /* Try to get RTF string. */
-   if (target == TARGET_NAME_APPLICATION_RTF ||
-       target == TARGET_NAME_TEXT_RICHTEXT) {
+   if (m_DnD->CheckCapability(DND_CP_CAP_RTF_DND) && (
+       target == TARGET_NAME_APPLICATION_RTF ||
+       target == TARGET_NAME_TEXT_RICHTEXT)) {
       utf::string source = sd.get_data_as_string().c_str();
       if (source.bytes() > 0 &&
           source.bytes() < DNDMSG_MAX_ARGSZ &&
@@ -2096,7 +2098,7 @@ DnDUIX11::GetTimeInMillis(void)
 
 
 /**
- * Update version information in mDnD.
+ * Update version information in m_DnD.
  *
  * @param[ignored] chan RpcChannel pointer
  * @param[in] version the version negotiated with host.