]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
[Wayland Copy & Paste] Part2: Uses VMBlock notification mechanism for Copy & Paste
authorOliver Kurth <okurth@vmware.com>
Tue, 5 Jun 2018 22:45:05 +0000 (15:45 -0700)
committerOliver Kurth <okurth@vmware.com>
Tue, 5 Jun 2018 22:45:05 +0000 (15:45 -0700)
This patch is part of the new feature for Workstation 15: \[P0\] Wayland
support in Linux guest - Copy & Paste.

In the first patch, the notification mechanism is added to the VMBlock module.
In this patch, the notification mechanism is used,

open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp
open-vm-tools/services/plugins/dndcp/copyPasteUIX11.h

index 01ab1a3cda6b53c142f8deb750bbcef358fd5910..d046b8b609cfb2c2149ba2f837a395b3d90aefd7 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 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
@@ -74,6 +74,7 @@
 #include "guestDnDCPMgr.hh"
 #include "tracer.hh"
 #include "vmblock.h"
+#include "fcntl.h"
 #include "file.h"
 #include "dnd.h"
 #include "dndMsg.h"
@@ -128,6 +129,7 @@ CopyPasteUIX11::CopyPasteUIX11()
    mClipTime(0),
    mPrimTime(0),
    mLastTimestamp(0),
+   mThread(0),
    mHGGetFileStatus(DND_FILE_TRANSFER_NOT_STARTED),
    mBlockAdded(false),
    mBlockCtrl(0),
@@ -135,10 +137,24 @@ CopyPasteUIX11::CopyPasteUIX11()
    mTotalFileSize(0),
    mGetTimestampOnly(false)
 {
+   TRACE_CALL();
    GuestDnDCPMgr *p = GuestDnDCPMgr::GetInstance();
    ASSERT(p);
    mCP = p->GetCopyPasteMgr();
    ASSERT(mCP);
+
+   mThreadParams.fileBlockCondExit = false;
+   pthread_mutex_init(&mThreadParams.fileBlockMutex, NULL);
+   pthread_cond_init(&mThreadParams.fileBlockCond, NULL);
+   mThreadParams.cp = this;
+   int ret = pthread_create(&mThread,
+                            NULL,
+                            FileBlockMonitorThread,
+                            (void *)&(this->mThreadParams));
+   if (ret != 0) {
+      Warning("%s: Create thread failed, errno:%d.\n", __FUNCTION__, ret);
+      mThread = 0;
+   }
 }
 
 
@@ -164,6 +180,7 @@ CopyPasteUIX11::Init()
 {
    TRACE_CALL();
    if (mInited) {
+      g_debug("%s: mInited is true\n", __FUNCTION__);
       return true;
    }
 
@@ -231,6 +248,10 @@ CopyPasteUIX11::~CopyPasteUIX11()
       }
       mBlockAdded = false;
    }
+
+   TerminateThread();
+   pthread_mutex_destroy(&mThreadParams.fileBlockMutex);
+   pthread_cond_destroy(&mThreadParams.fileBlockCond);
 }
 
 
@@ -361,20 +382,6 @@ CopyPasteUIX11::LocalGetFileRequestCB(Gtk::SelectionData& sd,        // IN:
                                       guint info)                    // IN:
 {
    g_debug("%s: enter.\n", __FUNCTION__);
-   VmTimeType curTime;
-
-   curTime = GetCurrentTime();
-
-   /*
-    * Some applications may ask for clipboard contents right after clipboard
-    * owner changed. So HG FCP will return nothing for some time after switch
-    * from guest OS to host OS.
-    */
-   if ((curTime - mHGGetListTime) < FCP_COPY_DELAY) {
-      g_debug("%s: time delta less than FCP_COPY_DELAY, returning.\n",
-            __FUNCTION__);
-      return;
-   }
 
    if (!mIsClipboardOwner || !mCP->IsCopyPasteAllowed()) {
       g_debug("%s: not clipboard ownder, or copy paste not allowed, returning.\n",
@@ -403,7 +410,7 @@ CopyPasteUIX11::LocalGetFileRequestCB(Gtk::SelectionData& sd,        // IN:
       utf::string post;
       size_t index = 0;
 
-      hgStagingDir = static_cast<utf::string>(mCP->SrcUIRequestFiles());
+      hgStagingDir = utf::CopyAndFree(DnD_CreateStagingDirectory());
       g_debug("%s: Getting files. Staging dir: %s", __FUNCTION__,
             hgStagingDir.c_str());
 
@@ -419,6 +426,13 @@ CopyPasteUIX11::LocalGetFileRequestCB(Gtk::SelectionData& sd,        // IN:
          g_debug("%s: add block for %s.\n",
                __FUNCTION__, hgStagingDir.c_str());
          mBlockAdded = true;
+         pthread_mutex_lock(&mThreadParams.fileBlockMutex);
+         mThreadParams.fileBlockCondExit = false;
+         mThreadParams.fileBlockName = VMBLOCK_FUSE_NOTIFY_ROOT;
+         mThreadParams.fileBlockName += DIRSEPS;
+         mThreadParams.fileBlockName += GetLastDirName(hgStagingDir);
+         pthread_cond_signal(&mThreadParams.fileBlockCond);
+         pthread_mutex_unlock(&mThreadParams.fileBlockMutex);
       } else {
          g_debug("%s: unable to add block for %s.\n",
                __FUNCTION__, hgStagingDir.c_str());
@@ -1183,6 +1197,13 @@ CopyPasteUIX11::GetRemoteClipboardCB(const CPClipboard *clip) // IN
       return;
    }
 
+   if (mBlockAdded) {
+      if (DnD_BlockIsReady(mBlockCtrl)) {
+         mBlockCtrl->RemoveBlock(mBlockCtrl->fd, mHGStagingDir.c_str());
+         mBlockAdded = false;
+      }
+   }
+
    /* Clear the clipboard contents if we are the owner. */
    if (mIsClipboardOwner) {
       refClipboard->clear();
@@ -1602,3 +1623,109 @@ CopyPasteUIX11::Reset(void)
    TRACE_CALL();
    /* Cancel any pending file transfer. */
 }
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CopyPasteUIX11::FileBlockMonitorThread --
+ *
+ *    This thread monitors the access to the files in the clipboard which owns
+ *    by VMTools by using the notification mechanism of VMBlock.
+ *    If any access to the file is detected, then this thread requests the file
+ *    transfer from host to guest.
+ *
+ * Results:
+ *    Always return NULL
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void*
+CopyPasteUIX11::FileBlockMonitorThread(void *arg)   // IN
+{
+   TRACE_CALL();
+   ThreadParams *params = (ThreadParams *)arg;
+   pthread_mutex_lock(&params->fileBlockMutex);
+   while (true) {
+      g_debug("%s: waiting signal\n", __FUNCTION__);
+      pthread_cond_wait(&params->fileBlockCond, &params->fileBlockMutex);
+      g_debug("%s: received signal. Exit:%d\n",
+              __FUNCTION__,
+              params->fileBlockCondExit);
+      if (params->fileBlockCondExit) {
+         break;
+      }
+      if (params->fileBlockName.bytes() == 0) {
+        continue;
+      }
+
+      int fd = open(params->fileBlockName.c_str(), O_RDONLY);
+      if (fd <= 0) {
+         g_debug("%s: Failed to open %s\n",
+                 __FUNCTION__,
+                 params->fileBlockName.c_str());
+         continue;
+      }
+
+      char buf[sizeof(VMBLOCK_FUSE_READ_RESPONSE)];
+      ssize_t size;
+      size = read(fd, buf, sizeof(VMBLOCK_FUSE_READ_RESPONSE));
+      /*
+       * The current thread will block in read function until
+       * any other application accesses the file params->fileBlockName
+       * or the block on the file params->fileBlockName is removed.
+       * Currently we don't need to check the response in buf, so
+       * just ignore it.
+       */
+
+      if (params->cp->IsBlockAdded()) {
+         g_debug("%s: Request files\n", __FUNCTION__);
+         params->cp->RequestFiles();
+      } else {
+         g_debug("%s: Block is not added\n", __FUNCTION__);
+      }
+   }
+   pthread_mutex_unlock(&params->fileBlockMutex);
+   return NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CopyPasteUIX11::TerminateThread --
+ *
+ *    This is called when the monitor thread is asked to exit.
+ *    Sets the global state and signals the monitor thread to exit and wait
+ *    for the monitor thread to exit.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+CopyPasteUIX11::TerminateThread()
+{
+   TRACE_CALL();
+   if (mThread == 0) {
+      return;
+   }
+
+   pthread_mutex_lock(&mThreadParams.fileBlockMutex);
+   mThreadParams.fileBlockCondExit = true;
+   pthread_cond_signal(&mThreadParams.fileBlockCond);
+   pthread_mutex_unlock(&mThreadParams.fileBlockMutex);
+
+   pthread_join(mThread, NULL);
+
+   mThread = 0;
+}
index b630a31dcd4f459c43572def0b70f409499e0d8a..e2cd77443a03db6be351ebdc6c3dff36737272b8 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 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
@@ -64,6 +64,17 @@ extern "C" {
 #include <gdk/gdkx.h>
 #include "vmware/guestrpc/tclodefs.h"
 
+class CopyPasteUIX11;
+
+struct ThreadParams
+{
+   pthread_mutex_t fileBlockMutex;
+   pthread_cond_t fileBlockCond;
+   bool fileBlockCondExit;
+   CopyPasteUIX11 *cp;
+   utf::string fileBlockName;
+};
+
 class CopyPasteUIX11 : public sigc::trackable
 {
 public:
@@ -78,6 +89,10 @@ public:
    void SetBlockControl(DnDBlockControl *blockCtrl)
       { Debug("Setting mBlockCtrl to %p\n", blockCtrl);
         mBlockCtrl = blockCtrl; }
+   bool IsBlockAdded() const
+   { return mBlockAdded; }
+   void RequestFiles()
+   { mCP->SrcUIRequestFiles(); }
 
 private:
 
@@ -105,6 +120,9 @@ private:
 
    VmTimeType GetCurrentTime(void);
 
+   static void* FileBlockMonitorThread(void *arg);
+   void TerminateThread();
+
    // Member variables
    GuestCopyPasteMgr *mCP;
    bool mClipboardEmpty;
@@ -116,6 +134,8 @@ private:
    uint64 mLastTimestamp;
    GdkAtom mGHSelection;
    CPClipboard mClipboard;
+   ThreadParams mThreadParams;
+   pthread_t mThread;
 
    /* File vars. */
    VmTimeType mHGGetListTime;