clipboard.cpp revision b72771e8c6ba3b3d9ebdd7977730325131ae0f98
45565249f149f7562fc6ee85be7ca3a3706e32e6vboxsync * Guest Additions - X11 Shared Clipboard.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Copyright (C) 2007 Sun Microsystems, Inc.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * available from http://www.virtualbox.org. This file is free software;
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * General Public License (GPL) as published by the Free Software
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * additional information or have any questions.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync/*******************************************************************************
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync* Header Files *
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync*******************************************************************************/
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync/** The formats which we support in the guest. These can be deactivated in order to test specific code paths. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync/*******************************************************************************
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync* Global Variables *
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync*******************************************************************************/
cea5568645ca17479265436cfd5ba010ddd106d9vboxsync/** The different clipboard formats which we support. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync/** The X11 clipboard uses several names for the same format. This structure maps an X11 name to a format. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsynctypedef struct
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync/** Does the host or the guest currently own the clipboard? */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Global clipboard context information.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsynctypedef struct
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /** The Xt application context structure */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** We have a separate thread to wait for Window and Clipboard events */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** The Xt widget which we use as our clipboard client. It is never made visible. */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /** X11 atom refering to the clipboard: CLIPBOARD */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** X11 atom refering to the selection: PRIMARY */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** X11 atom refering to the clipboard: TARGETS */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** X11 atom refering to the clipboard: MULTIPLE */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** X11 atom refering to the clipboard: TIMESTAMP */
8d7d0a641afd3eb2aacf2b3ba428e6d8894a6a5fvboxsync /** X11 atom refering to the clipboard utf16 text format: text/plain;charset=ISO-10646-UCS-2 */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /** X11 atom refering to the clipboard utf8 text format: UTF8_STRING */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** X11 atom refering to the native X11 clipboard text format: COMPOUND_TEXT */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** A list of the X11 formats which we support, mapped to our identifier for them, in the order
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync we prefer to have them in. */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /** Does the host or the guest currently own the clipboard? */
a93da6c0946d71f517dc6d64a633704cb99068b8vboxsync /** What is the best text format the guest has to offer? INVALID for none. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Atom corresponding to the guest text format */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /** What is the best bitmap format the guest has to offer? INVALID for none. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Atom corresponding to the guest Bitmap format */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** What formats does the host have on offer? */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Windows caches the clipboard data it receives. Since we have no way of knowing whether
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync that data is still valid, we always send a "data changed" message after a successful
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync transfer to invalidate the cache. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Since the clipboard data moves asynchronously, we use an event semaphore to wait for it. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Format which we are reading from the guest clipboard (valid during a request for the
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync guest clipboard) */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** The guest buffer to write guest clipboard data to (valid during a request for the host
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync clipboard) */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** The size of the host buffer to write guest clipboard data to (valid during a request for
cf0b951d0e7a93540b3931ca506ed97c1dc300ccvboxsync the guest clipboard) */
cf0b951d0e7a93540b3931ca506ed97c1dc300ccvboxsync /** The size of the guest clipboard data written to the host buffer (valid during a request
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync for the guest clipboard) */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /** Client ID for the clipboard subsystem */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync/** Only one client is supported. There seems to be no need for more clients. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Transfer clipboard data from the guest to the host.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * @returns VBox result code
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * @param u32Format The format of the data being sent
a93da6c0946d71f517dc6d64a633704cb99068b8vboxsync * @param pv Pointer to the data being sent
b47847090b3c99e4fdf905536053595e75845265vboxsync * @param cb Size of the data being sent in bytes
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsyncstatic int vboxClipboardSendData(uint32_t u32Format, void *pv, uint32_t cb)
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync LogFlowFunc(("u32Format=%d, pv=%p, cb=%d\n", u32Format, pv, cb));
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync rc = VbglR3ClipboardWriteData(g_ctx.client, u32Format, pv, cb);
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * Get clipboard data from the host.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * @returns VBox result code
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param u32Format The format of the data being requested
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * @retval ppv On success and if pcb > 0, this will point to a buffer
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * to be freed with RTMemFree containing the data read.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @retval pcb On success, this contains the number of bytes of data
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsyncstatic int vboxClipboardReadHostData(uint32_t u32Format, void **ppv, uint32_t *pcb)
4b30f6c72b07654509606857da385afcc09aaae3vboxsync rc = VbglR3ClipboardReadData(g_ctx.client, u32Format, pv, cb, pcb);
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW))
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync /* A return value of VINF_BUFFER_OVERFLOW tells us to try again with a
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * larger buffer. The size of the buffer needed is placed in *pcb.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * So we start all over again. */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync rc = VbglR3ClipboardReadData(g_ctx.client, u32Format, pv, cb, pcb);
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW))
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Catch other errors. This also catches the case in which the buffer was
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * too small a second time, possibly because the clipboard contents
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * changed half-way through the operation. Since we can't say whether or
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync * not this is actually an error, we just return size 0.
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync if (RT_FAILURE(rc) || (VINF_BUFFER_OVERFLOW == rc))
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * Convert a Utf16 text with Linux EOLs to zero-terminated Utf16-LE with Windows EOLs, allocating
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * memory for the converted text. Does no checking for validity.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @returns VBox status code
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param pu16Src Source Utf16 text to convert
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param cwSrc Size of the source text in 16 bit words
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @retval ppu16Dest Where to store the pointer to the converted text. Only valid on success
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * and if pcwDest is greater than 0.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @retval pcwDest Size of the converted text in 16 bit words, including the trailing null
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * if present
84eeabfd29e718854e00e795879dab6ce61469e5vboxsyncstatic int vboxClipboardUtf16LinToWin(PRTUTF16 pu16Src, size_t cwSrc, PRTUTF16 *ppu16Dest,
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u\n", cwSrc, pu16Src, cwSrc));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("*ppu16Dest=0, *pcwDest=0, rc=VINF_SUCCESS\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertReturn(VALID_PTR(pu16Src), VERR_INVALID_PARAMETER);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync if (pu16Src[i] == 0)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Leave space for a trailing null */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync pu16Dest = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDest * 2));
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync for (i = (pu16Src[0] == 0xfeff ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync if (pu16Src[i] == 0)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* The trailing null */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("*ppu16Dest=%p, *pcwDest=%d, rc=VINF_SUCCESS\n", pu16Dest, cwDest));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * Convert the UTF-16 text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * and send it to the host.
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync * @param pValue Source UTF-16 text
13e885122ee503a6b52b157f8d779f8a9a8dd716vboxsync * @param cwSourceLen Length in 16-bit words of the source text
13e885122ee503a6b52b157f8d779f8a9a8dd716vboxsyncstatic void vboxClipboardGetUtf16(XtPointer pValue, size_t cwSourceLen)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync PRTUTF16 pu16SourceText = reinterpret_cast<PRTUTF16>(pValue);
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync LogFlowFunc(("converting Utf-16 to Utf-16LE. Original is %.*ls\n",
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = vboxClipboardUtf16LinToWin(pu16SourceText, cwSourceLen, &pu16DestText, &cwDestLen);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlow(("vboxClipboardGetUtf16: converted string is %.*ls\n", cwDestLen, pu16DestText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync vboxClipboardSendData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync reinterpret_cast<void *>(pu16DestText), cwDestLen * 2);
b47847090b3c99e4fdf905536053595e75845265vboxsync * Convert the UTF-8 text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
a93da6c0946d71f517dc6d64a633704cb99068b8vboxsync * and send it to the host.
b47847090b3c99e4fdf905536053595e75845265vboxsync * @param pValue Source UTF-8 text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsyncstatic void vboxClipboardGetUtf8(XtPointer pValue, size_t cbSourceLen)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlow(("vboxClipboardGetUtf8: converting Utf-8 to Utf-16LE. Original is %.*s\n", cbSourceLen,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* First convert the UTF8 to UTF16 */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = RTStrToUtf16Ex(pu8SourceText, cbSourceLen, &pu16SourceText, 0, &cwSourceLen);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
13e885122ee503a6b52b157f8d779f8a9a8dd716vboxsync rc = vboxClipboardUtf16LinToWin(pu16SourceText, cwSourceLen, &pu16DestText, &cwDestLen);
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync RTMemFree(reinterpret_cast<void *>(pu16SourceText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlow(("vboxClipboardGetUtf8: converted string is %.*ls\n", cwDestLen, pu16DestText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync vboxClipboardSendData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync reinterpret_cast<void *>(pu16DestText), cwDestLen * 2);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync RTMemFree(reinterpret_cast<void *>(pu16SourceText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * Convert the compound text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * and send it to the host.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param pValue Source compound text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsyncstatic void vboxClipboardGetCText(XtPointer pValue, size_t cbSourceLen)
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync LogFlow(("vboxClipboardGetCText: converting compound text to Utf-16LE. Original is %.*s\n",
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* First convert the compound text to Utf8 */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync property.value = reinterpret_cast<unsigned char *>(pValue);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = XmbTextPropertyToTextList(XtDisplay(g_ctx.widget), &property, &ppu8SourceText, &cProps);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = Xutf8TextPropertyToTextList(XtDisplay(g_ctx.widget), &property, &ppu8SourceText, &cProps);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync const char *pcReason;
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogRel(("vboxClipboardGetCText: Xutf8TextPropertyToTextList failed. Reason: %s\n", pcReason));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Next convert the UTF8 to UTF16 */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = RTStrToUtf16Ex(*ppu8SourceText, cbSourceLen, &pu16SourceText, 0, &cwSourceLen);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync rc = vboxClipboardUtf16LinToWin(pu16SourceText, cwSourceLen, &pu16DestText, &cwDestLen);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync RTMemFree(reinterpret_cast<void *>(pu16SourceText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlow(("vboxClipboardGetCText: converted string is %.*ls\n", cwDestLen, pu16DestText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync vboxClipboardSendData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync reinterpret_cast<void *>(pu16DestText), cwDestLen * 2);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * Convert the Latin1 text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * and send it to the host.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param pValue Source Latin1 text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
84eeabfd29e718854e00e795879dab6ce61469e5vboxsyncstatic void vboxClipboardGetLatin1(XtPointer pValue, size_t cbSourceLen)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Leave space for an additional null character at the end of the destination text. */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("converting Latin1 to Utf-16LE. Original is %.*s\n", cbSourceLen,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Find the size of the destination text */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync pu16DestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDestLen * 2));
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync LogFlow(("vboxClipboardGetLatin1: failed to allocate %d bytes!\n", cwDestLen * 2));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* Copy the original X clipboard string to the destination, replacing Linux EOLs with
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync Windows ones */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync for (size_t i = 0; i < cbSourceLen; ++i, ++cwDestPos)
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* latin1 < utf-16LE */
36ebaddfec017eee7e82ee466c25de002cdc4231vboxsync LogFlow(("vboxClipboardGetLatin1: converted text is %.*ls\n", cwDestPos, pu16DestText));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync vboxClipboardSendData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync reinterpret_cast<void *>(pu16DestText), cwDestPos * 2);
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync/** Convert the clipboard text from the current format to Utf-16 with Windows line breaks.
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync We are reading the guest clipboard to make it available to the host. */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsyncstatic void vboxClipboardGetProc(Widget, XtPointer /* pClientData */, Atom * /* selection */,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync Atom *atomType, XtPointer pValue, long unsigned int *pcLen,
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* The X Toolkit may have failed to get the clipboard selection for us. */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("*pcLen=%lu, *piFormat=%d, requested target format: %d, g_ctx.requestBufferSize=%d\n",
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync *pcLen, *piFormat, g_ctx.requestGuestFormat, g_ctx.requestBufferSize));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("Xt failed to convert the data. Sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync LogFlowFunc(("The clipboard contents changed while we were requesting them. Sending empty data and returning\n"));
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* In which format did we request the clipboard data? */
84eeabfd29e718854e00e795879dab6ce61469e5vboxsync /* If we are given broken Utf-8, we treat it as Latin1. Is this acceptable? */
bb73206f5ad484c56a70984ee9897e9ffee18b8bvboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync if (RTStrUniLenEx(pu8SourceText, *pcLen, &cStringLen) == VINF_SUCCESS)
3393c62e395aa8388303d99f765a219efc289158vboxsync Log(("vboxClipboardGetProc: bad target format\n"));
3393c62e395aa8388303d99f765a219efc289158vboxsync LogFlowFunc(("sending empty data and returning\n"));
3393c62e395aa8388303d99f765a219efc289158vboxsync * Tell the host that new clipboard formats are available.
cea5568645ca17479265436cfd5ba010ddd106d9vboxsync * @returns VBox status code.
3393c62e395aa8388303d99f765a219efc289158vboxsync * @param u32Formats The formats to advertise
3393c62e395aa8388303d99f765a219efc289158vboxsyncstatic int vboxClipboardReportFormats(uint32_t u32Formats)
3393c62e395aa8388303d99f765a219efc289158vboxsync rc = VbglR3ClipboardReportFormats(g_ctx.client, u32Formats);
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync/** Callback to handle a reply to a request for the targets the current clipboard holder can
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync handle. We are reading the guest clipboard to make it available to the host. */
0a769a6be37f526faeabe88f77422ee6291afa37vboxsyncstatic void vboxClipboardTargetsProc(Widget, XtPointer, Atom * /* selection */, Atom *atomType,
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync XtPointer pValue, long unsigned int *pcLen, int *piFormat)
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync static int cCalls = 0;
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync Atom *atomTargets = reinterpret_cast<Atom *>(pValue);
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync /* The number of format atoms the clipboard holder is offering us */
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync /* The best clipboard format we have found so far */
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync /* The atom corresponding to our best clipboard format found */
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync Log3(("vboxClipboardTargetsProc called, cAtoms=%d\n", cAtoms));
71b548af8b5b8adb865702432045250bc56ad7e5vboxsync Log(("vboxClipboardTargetsProc: reading clipboard from guest, X toolkit failed to convert the selection\n"));
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync /* Run through the atoms offered to us to see if we recognise them. If we find the atom for
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync a "better" format than the best we have found so far, we remember it as our new "best"
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync for (unsigned i = 0; i < cAtoms; ++i)
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync for (unsigned j = 0; j != g_ctx.formatList.size(); ++j)
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomTargets[i]);
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync Log3(("vboxClipboardTargetsProc: the guest offers target %s\n", szAtomName));
c5019986bed37ec649721e6f7bc2117386fa5ac3vboxsync Log3(("vboxClipboardTargetsProc: the guest returned a bad atom: %d\n",
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync /* If the available formats as seen by the host have changed, or if we suspect that
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync the host has cached the clipboard data (which can change without our noticing it),
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync then tell the host that new clipboard contents are available. */
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync if ((eBestTarget != g_ctx.guestTextFormat) || (g_ctx.notifyHost == true))
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomBestTarget);
0a769a6be37f526faeabe88f77422ee6291afa37vboxsync LogFlow(("vboxClipboardTargetsProc: switching to guest text target %s. Available targets are:\n", szAtomName));
LogFlow(("vboxClipboardTargetsProc: no supported host text target found. Available targets are:\n"));
for (unsigned i = 0; i < cAtoms; ++i)
if (szAtomName != 0)
++cCalls;
static int cCalls = 0;
++cCalls;
unsigned cTargets = 0;
for (unsigned i = 0; i < uListSize; ++i)
++cTargets;
#ifdef DEBUG
if (szAtomName != 0)
if (cwSrc == 0)
cwDest = 0;
if (pu16Src[i] == 0)
++cwDest;
if (cwSrc == 0)
if (cwDest != 0)
pu16Dest[0] = 0;
return VINF_SUCCESS;
cwDestPos = 0;
if (cwDest == 0)
return VERR_BUFFER_OVERFLOW;
return VERR_BUFFER_OVERFLOW;
if (pu16Src[i] == 0)
return VERR_BUFFER_OVERFLOW;
return VINF_SUCCESS;
int rc;
LogFlow(("vboxClipboardConvertUtf16: vboxClipboardReadHostData returned %Rrc, %d bytes of data\n", rc, cbHostText));
if (pu16GuestText == 0)
LogFlow(("vboxClipboardConvertUtf16: returning Unicode, original text is %.*ls\n", cwHostText, pu16HostText));
LogFlow(("vboxClipboardConvertUtf16: converted text is %.*ls\n", cwGuestText - 1, pu16GuestText + 1));
char *pcGuestText;
int rc;
LogFlow(("vboxClipboardConvertUtf16: vboxClipboardReadHostData returned %Rrc, %d bytes of data\n", rc, cbHostText));
if (pu16GuestText == 0)
if (pcGuestText == 0)
cbGuestTextActual = 0;
rc = RTUtf16ToUtf8Ex(pu16GuestText + 1, cwGuestText - 1, &pcGuestText, cbGuestTextBuffer, &cbGuestTextActual);
char *pcUtf8Text;
int rc;
LogFlow(("vboxClipboardConvertCText: vboxClipboardReadHostData returned %Rrc, %d bytes of data\n", rc, cbHostText));
if (pu16GuestText == 0)
if (pcUtf8Text == 0)
#ifdef RT_OS_SOLARIS
if (rc < 0)
const char *pcReason;
switch(rc)
case XNoMemory:
case XLocaleNotSupported:
case XConverterNotFound:
pcReason));
int rc;
#ifdef DEBUG
if (szAtomName != 0)
switch (eFormat)
case TARGETS:
return rc;
case UTF16:
return rc;
case UTF8:
return rc;
case CTEXT:
return rc;
if (u32Formats == 0)
NULL, 0);
return VINF_SUCCESS;
return VERR_NOT_IMPLEMENTED;
return VINF_SUCCESS;
void vboxClipboardDestroy (void)
int rc;
switch (Msg)
return rc;
void vboxClipboardDisconnect(void)
int vboxClipboardConnect(void)
int rc;
return rc;
return VERR_NOT_SUPPORTED;
return rc;
static void vboxClipboardAddFormat(const char *pszName, g_eClipboardFormat eFormat, unsigned hostFormat)
if (atomFormat == 0)
static int vboxClipboardCreateWindow(void)
int cArgc = 0;
char *pcArgv = 0;
g_ctx.atomClipboard = XInternAtom(XtDisplay(g_ctx.widget), "CLIPBOARD", false /* only_if_exists */);
#ifdef USE_UTF16
vboxClipboardAddFormat("text/plain;charset=ISO-10646-UCS-2", UTF16, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
#ifdef USE_UTF8
#ifdef USE_CTEXT
return VINF_SUCCESS;
int vboxClipboardMain(void)
int rc;
return rc;
return rc;