From: Oliver Kurth Date: Tue, 19 Jun 2018 18:07:45 +0000 (-0700) Subject: [Wayland Copy & Paste] Part2: Uses VMBlock notification mechanism for Copy & Paste X-Git-Tag: stable-10.3.0~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7313fdc5b2b14ac83340b2e59752b934494c2ae9;p=thirdparty%2Fopen-vm-tools.git [Wayland Copy & Paste] Part2: Uses VMBlock notification mechanism for Copy & Paste 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, --- diff --git a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp index 01ab1a3cd..d046b8b60 100644 --- a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp +++ b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.cpp @@ -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(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(¶ms->fileBlockMutex); + while (true) { + g_debug("%s: waiting signal\n", __FUNCTION__); + pthread_cond_wait(¶ms->fileBlockCond, ¶ms->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(¶ms->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; +} diff --git a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.h b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.h index b630a31dc..e2cd77443 100644 --- a/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.h +++ b/open-vm-tools/services/plugins/dndcp/copyPasteUIX11.h @@ -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 #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;