diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp')
-rw-r--r-- | src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp b/src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp new file mode 100644 index 00000000..896e5eb2 --- /dev/null +++ b/src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp @@ -0,0 +1,330 @@ +/** $Id: VBoxClientClipboard.cpp $ */ +/** @file + * VBoxClient - Shared Slipboard Dispatcher, Darwin. + */ + +/* + * Copyright (C) 2007-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 * +*********************************************************************************************************************************/ +#include <Carbon/Carbon.h> + +#include <iprt/asm.h> +#include <iprt/stream.h> +#include <iprt/thread.h> +#include <iprt/critsect.h> +#include <VBox/VBoxGuestLib.h> +#include <VBox/HostServices/VBoxClipboardSvc.h> +#include <VBox/GuestHost/clipboard-helper.h> +#include "VBoxClientInternal.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ + +/** Host clipboard connection client ID */ +static uint32_t g_u32ClientId; +/* Guest clipboard reference */ +static PasteboardRef g_PasteboardRef; +/* Dispatcher tharead handle */ +RTTHREAD g_DispatcherThread; +/* Pasteboard polling tharead handle */ +RTTHREAD g_GuestPasteboardThread; +/* Flag that indicates whether or not dispatcher and Pasteboard polling threada should stop */ +static bool volatile g_fShouldStop; +/* Barrier for Pasteboard */ +static RTCRITSECT g_critsect; + + +/********************************************************************************************************************************* +* Local Macros * +*********************************************************************************************************************************/ + +#define VBOXCLIENT_SERVICE_NAME "clipboard" + + +/********************************************************************************************************************************* +* Local Function Prototypes * +*********************************************************************************************************************************/ +static int vbclClipboardStop(void); + + +/** + * Clipboard dispatcher function. + * + * Forwards cliproard content between host and guest. + * + * @param ThreadSelf Unused parameter. + * @param pvUser Unused parameter. + * + * @return IPRT status code. + */ +static DECLCALLBACK(int) vbclClipboardDispatcher(RTTHREAD ThreadSelf, void *pvUser) +{ + bool fQuit = false; + NOREF(ThreadSelf); + NOREF(pvUser); + + VBoxClientVerbose(2, "starting host clipboard polling thread\n"); + + /* + * Block all signals for this thread. Only the main thread will handle signals. + */ + sigset_t signalMask; + sigfillset(&signalMask); + pthread_sigmask(SIG_BLOCK, &signalMask, NULL); + + while (!fQuit && !ASMAtomicReadBool(&g_fShouldStop)) + { + int rc; + uint32_t Msg; + uint32_t fFormats; + + VBoxClientVerbose(2, "waiting for new host request\n"); + + rc = VbglR3ClipboardGetHostMsg(g_u32ClientId, &Msg, &fFormats); + if (RT_SUCCESS(rc)) + { + RTCritSectEnter(&g_critsect); + switch (Msg) + { + /* The host is terminating */ + case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT: + VBoxClientVerbose(2, "host requested quit\n"); + fQuit = true; + break; + + /* The host needs data in the specified format */ + case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA: + VBoxClientVerbose(2, "host requested guest's clipboard read\n"); + rc = vbclClipboardForwardToHost(g_u32ClientId, g_PasteboardRef, fFormats); + AssertMsg(RT_SUCCESS(rc), ("paste to host failed\n")); + break; + + /* The host has announced available clipboard formats */ + case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS: + VBoxClientVerbose(2, "host requested guest's clipboard write\n"); + rc = vbclClipboardForwardToGuest(g_u32ClientId, g_PasteboardRef, fFormats); + AssertMsg(RT_SUCCESS(rc), ("paste to guest failed\n")); + break; + + default: + VBoxClientVerbose(2, "received unknow command from host service\n"); + RTThreadSleep(1000); + } + + RTCritSectLeave(&g_critsect); + } + else + { + RTThreadSleep(1000); + } + } + + VBoxClientVerbose(2, "host clipboard polling thread stopped\n"); + + return VINF_SUCCESS; +} + + +/** + * Clipboard dispatcher function. + * + * Forwards cliproard content between host and guest. + * + * @param hThreadSelf Unused parameter. + * @param pvUser Unused parameter. + * + * @return IPRT status code. + */ +static DECLCALLBACK(int) vbclGuestPasteboardPoll(RTTHREAD hThreadSelf, void *pvUser) +{ + RT_NOREF(hThreadSelf, pvUser); + + /* + * Block all signals for this thread. Only the main thread will handle signals. + */ + sigset_t signalMask; + sigfillset(&signalMask); + pthread_sigmask(SIG_BLOCK, &signalMask, NULL); + + VBoxClientVerbose(2, "starting guest clipboard polling thread\n"); + + while (!ASMAtomicReadBool(&g_fShouldStop)) + { + PasteboardSyncFlags fSyncFlags; + uint32_t fFormats; + int rc; + + RTCritSectEnter(&g_critsect); + + fSyncFlags = PasteboardSynchronize(g_PasteboardRef); + if (fSyncFlags & kPasteboardModified) + { + fFormats = vbclClipboardGetAvailableFormats(g_PasteboardRef); + rc = VbglR3ClipboardReportFormats(g_u32ClientId, fFormats); + if (RT_FAILURE(rc)) + { + VBoxClientVerbose(2, "failed to report pasteboard update (%Rrc)\n", rc); + } + else + { + VBoxClientVerbose(2, "guest clipboard update reported: %d\n", (int)fFormats); + } + } + + RTCritSectLeave(&g_critsect); + + /* Check pasteboard every 200 ms */ + RTThreadSleep(200); + } + + VBoxClientVerbose(2, "guest clipboard polling thread stopped\n"); + + return VINF_SUCCESS; +} + + +/** + * Initialize host and guest clipboards, start clipboard dispatcher loop. + * + * @return IPRT status code. + */ +static int vbclClipboardStart(void) +{ + int rc; + + VBoxClientVerbose(2, "starting clipboard\n"); + + rc = RTCritSectInit(&g_critsect); + if (RT_FAILURE(rc)) + return VERR_GENERAL_FAILURE; + + rc = VbglR3ClipboardConnect(&g_u32ClientId); + if (RT_SUCCESS(rc)) + { + rc = PasteboardCreate(kPasteboardClipboard, &g_PasteboardRef); + if (rc == noErr) + { + /* Start dispatcher loop */ + ASMAtomicWriteBool(&g_fShouldStop, false); + rc = RTThreadCreate(&g_DispatcherThread, + vbclClipboardDispatcher, + (void *)NULL, + 0, + RTTHREADTYPE_DEFAULT, + RTTHREADFLAGS_WAITABLE, + VBOXCLIENT_SERVICE_NAME); + if (RT_SUCCESS(rc)) + { + /* Start dispatcher loop */ + ASMAtomicWriteBool(&g_fShouldStop, false); + rc = RTThreadCreate(&g_GuestPasteboardThread, + vbclGuestPasteboardPoll, + (void *)NULL, + 0, + RTTHREADTYPE_DEFAULT, + RTTHREADFLAGS_WAITABLE, + VBOXCLIENT_SERVICE_NAME); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + + /* Stop dispatcher thread */ + ASMAtomicWriteBool(&g_fShouldStop, true); + RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL); + + } + VBoxClientVerbose(2, "unable create dispatcher thread\n"); + CFRelease(g_PasteboardRef); + g_PasteboardRef = NULL; + + } + else + { + rc = VERR_GENERAL_FAILURE; + VBoxClientVerbose(2, "unable access guest clipboard\n"); + } + + vbclClipboardStop(); + + } + else + { + VBoxClientVerbose(2, "unable to establish connection to clipboard service: %Rrc\n", rc); + } + + RTCritSectDelete(&g_critsect); + + return rc; +} + + +/** + * Release host and guest clipboards, stop clipboard dispatcher loop. + * + * @return IPRT status code. + */ +static int vbclClipboardStop(void) +{ + int rc; + + VBoxClientVerbose(2, "stopping clipboard\n"); + + AssertReturn(g_u32ClientId != 0, VERR_GENERAL_FAILURE); + + VbglR3ClipboardReportFormats(g_u32ClientId, 0); + + rc = VbglR3ClipboardDisconnect(g_u32ClientId); + if (RT_SUCCESS(rc)) + g_u32ClientId = 0; + else + VBoxClientVerbose(2, "unable to close clipboard service connection: %Rrc\n", rc); + + if (g_PasteboardRef) + { + CFRelease(g_PasteboardRef); + g_PasteboardRef = NULL; + } + + /* Stop dispatcher thread */ + ASMAtomicWriteBool(&g_fShouldStop, true); + rc = RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL); + if (RT_FAILURE(rc)) + VBoxClientVerbose(2, "failed to stop dispatcher thread"); + + /* Stop Pasteboard polling thread */ + rc = RTThreadWait(g_GuestPasteboardThread, 10 * 1000 /* Wait 10 seconds */, NULL); + if (RT_FAILURE(rc)) + VBoxClientVerbose(2, "failed to stop pasteboard polling thread"); + + RTCritSectDelete(&g_critsect); + + return rc; +} + + +/* Clipboard service struct */ +VBOXCLIENTSERVICE g_ClipboardService = +{ + /* pszName */ + VBOXCLIENT_SERVICE_NAME, + + /* pfnStart */ + vbclClipboardStart, + + /* pfnStop */ + vbclClipboardStop, +}; |