summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostServices/SharedClipboard/darwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/SharedClipboard/darwin.cpp')
-rw-r--r--src/VBox/HostServices/SharedClipboard/darwin.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/VBox/HostServices/SharedClipboard/darwin.cpp b/src/VBox/HostServices/SharedClipboard/darwin.cpp
new file mode 100644
index 00000000..3dbafbd3
--- /dev/null
+++ b/src/VBox/HostServices/SharedClipboard/darwin.cpp
@@ -0,0 +1,274 @@
+/* $Id: darwin.cpp $ */
+/** @file
+ * Shared Clipboard Service - Mac OS X host.
+ */
+
+/*
+ * Copyright (C) 2008-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
+#include <VBox/HostServices/VBoxClipboardSvc.h>
+
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/thread.h>
+
+#include "VBoxClipboard.h"
+#include "darwin-pasteboard.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/** Global clipboard context information */
+struct _VBOXCLIPBOARDCONTEXT
+{
+ /** We have a separate thread to poll for new clipboard content */
+ RTTHREAD thread;
+ bool volatile fTerminate;
+
+ /** The reference to the current pasteboard */
+ PasteboardRef pasteboard;
+
+ VBOXCLIPBOARDCLIENTDATA *pClient;
+};
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Only one client is supported. There seems to be no need for more clients. */
+static VBOXCLIPBOARDCONTEXT g_ctx;
+
+
+/**
+ * Checks if something is present on the clipboard and calls vboxSvcClipboardReportMsg.
+ *
+ * @returns IPRT status code (ignored).
+ * @param pCtx The context.
+ */
+static int vboxClipboardChanged (VBOXCLIPBOARDCONTEXT *pCtx)
+{
+ if (pCtx->pClient == NULL)
+ return VINF_SUCCESS;
+
+ uint32_t fFormats = 0;
+ bool fChanged = false;
+ /* Retrieve the formats currently in the clipboard and supported by vbox */
+ int rc = queryNewPasteboardFormats (pCtx->pasteboard, &fFormats, &fChanged);
+ if (RT_SUCCESS (rc) && fChanged)
+ {
+ vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, fFormats);
+ Log (("vboxClipboardChanged fFormats %02X\n", fFormats));
+ }
+
+ return rc;
+}
+
+
+/**
+ * The poller thread.
+ *
+ * This thread will check for the arrival of new data on the clipboard.
+ *
+ * @returns VINF_SUCCESS (not used).
+ * @param ThreadSelf Our thread handle.
+ * @param pvUser Pointer to the VBOXCLIPBOARDCONTEXT structure.
+ *
+ */
+static int vboxClipboardThread (RTTHREAD ThreadSelf, void *pvUser)
+{
+ Log (("vboxClipboardThread: starting clipboard thread\n"));
+
+ AssertPtrReturn (pvUser, VERR_INVALID_PARAMETER);
+ VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *) pvUser;
+
+ while (!pCtx->fTerminate)
+ {
+ /* call this behind the lock because we don't know if the api is
+ thread safe and in any case we're calling several methods. */
+ vboxSvcClipboardLock();
+ vboxClipboardChanged (pCtx);
+ vboxSvcClipboardUnlock();
+
+ /* Sleep for 200 msecs before next poll */
+ RTThreadUserWait (ThreadSelf, 200);
+ }
+
+ Log (("vboxClipboardThread: clipboard thread terminated successfully with return code %Rrc\n", VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+/*
+ * Public platform dependent functions.
+ */
+
+/** Initialise the host side of the shared clipboard - called by the hgcm layer. */
+int vboxClipboardInit (void)
+{
+ Log (("vboxClipboardInit\n"));
+
+ g_ctx.fTerminate = false;
+
+ int rc = initPasteboard (&g_ctx.pasteboard);
+ AssertRCReturn (rc, rc);
+
+ rc = RTThreadCreate (&g_ctx.thread, vboxClipboardThread, &g_ctx, 0,
+ RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
+ if (RT_FAILURE (rc))
+ {
+ g_ctx.thread = NIL_RTTHREAD;
+ destroyPasteboard (&g_ctx.pasteboard);
+ }
+
+ return rc;
+}
+
+/** Terminate the host side of the shared clipboard - called by the hgcm layer. */
+void vboxClipboardDestroy (void)
+{
+ Log (("vboxClipboardDestroy\n"));
+
+ /*
+ * Signal the termination of the polling thread and wait for it to respond.
+ */
+ ASMAtomicWriteBool (&g_ctx.fTerminate, true);
+ int rc = RTThreadUserSignal (g_ctx.thread);
+ AssertRC (rc);
+ rc = RTThreadWait (g_ctx.thread, RT_INDEFINITE_WAIT, NULL);
+ AssertRC (rc);
+
+ /*
+ * Destroy the pasteboard and uninitialize the global context record.
+ */
+ destroyPasteboard (&g_ctx.pasteboard);
+ g_ctx.thread = NIL_RTTHREAD;
+ g_ctx.pClient = NULL;
+}
+
+/**
+ * Enable the shared clipboard - called by the hgcm clipboard subsystem.
+ *
+ * @param pClient Structure containing context information about the guest system
+ * @param fHeadless Whether headless.
+ * @returns RT status code
+ */
+int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless)
+{
+ NOREF(fHeadless);
+ if (g_ctx.pClient != NULL)
+ {
+ /* One client only. */
+ return VERR_NOT_SUPPORTED;
+ }
+
+ vboxSvcClipboardLock();
+
+ pClient->pCtx = &g_ctx;
+ pClient->pCtx->pClient = pClient;
+
+ /* Initially sync the host clipboard content with the client. */
+ int rc = vboxClipboardSync (pClient);
+
+ vboxSvcClipboardUnlock();
+ return rc;
+}
+
+/**
+ * Synchronise the contents of the host clipboard with the guest, called by the HGCM layer
+ * after a save and restore of the guest.
+ */
+int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
+{
+ /* Sync the host clipboard content with the client. */
+ vboxSvcClipboardLock();
+ int rc = vboxClipboardChanged (pClient->pCtx);
+ vboxSvcClipboardUnlock();
+
+ return rc;
+}
+
+/**
+ * Shut down the shared clipboard subsystem and "disconnect" the guest.
+ */
+void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
+{
+ Log (("vboxClipboardDisconnect\n"));
+
+ vboxSvcClipboardLock();
+ pClient->pCtx->pClient = NULL;
+ vboxSvcClipboardUnlock();
+}
+
+/**
+ * The guest is taking possession of the shared clipboard. Called by the HGCM clipboard
+ * subsystem.
+ *
+ * @param pClient Context data for the guest system
+ * @param u32Formats Clipboard formats the guest is offering
+ */
+void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats)
+{
+ Log (("vboxClipboardFormatAnnounce u32Formats %02X\n", u32Formats));
+ if (u32Formats == 0)
+ {
+ /* This is just an automatism, not a genuine announcement */
+ return;
+ }
+
+ vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
+ u32Formats);
+}
+
+/**
+ * Called by the HGCM clipboard subsystem when the guest wants to read the host clipboard.
+ *
+ * @param pClient Context information about the guest VM
+ * @param u32Format The format that the guest would like to receive the data in
+ * @param pv Where to write the data to
+ * @param cb The size of the buffer to write the data to
+ * @param pcbActual Where to write the actual size of the written data
+ */
+int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format,
+ void *pv, uint32_t cb, uint32_t * pcbActual)
+{
+ vboxSvcClipboardLock();
+
+ /* Default to no data available. */
+ *pcbActual = 0;
+ int rc = readFromPasteboard (pClient->pCtx->pasteboard, u32Format, pv, cb, pcbActual);
+
+ vboxSvcClipboardUnlock();
+ return rc;
+}
+
+/**
+ * Called by the HGCM clipboard subsystem when we have requested data and that data arrives.
+ *
+ * @param pClient Context information about the guest VM
+ * @param pv Buffer to which the data was written
+ * @param cb The size of the data written
+ * @param u32Format The format of the data written
+ */
+void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv,
+ uint32_t cb, uint32_t u32Format)
+{
+ vboxSvcClipboardLock();
+
+ writeToPasteboard (pClient->pCtx->pasteboard, pv, cb, u32Format);
+
+ vboxSvcClipboardUnlock();
+}