x11.cpp revision 68e0f2909a5fe490fd5c33346b911815ca5b02a5
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Shared Clipboard:
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Linux host.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * available from http://www.virtualbox.org. This file is free software;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * General Public License (GPL) as published by the Free Software
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * additional information or have any questions.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Do we want to test Utf16 by disabling other text formats? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic bool g_testUtf16 = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Do we want to test Utf8 by disabling other text formats? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic bool g_testUtf8 = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Do we want to test compount text by disabling other text formats? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic bool g_testCText = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Are we currently debugging the clipboard code? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic bool g_debugClipboard = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** The different clipboard formats which we support. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** The X11 clipboard uses several names for the same format. This structure maps an X11
6ef855ecf2121f708685307839f1262e0db1a024vboxsync name to a format. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsynctypedef struct {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Does the host or the guest currently own the clipboard? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsynctypedef struct {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** BMP file type marker - must always contain 'BM' */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The size of the BMP file in bytes (the MS docs say that this is not reliable) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Reserved, must always be zero */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Reserved, must always be zero */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Offset from the beginning of this header to the actual image bits */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** Global clipboard context information */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The X Toolkit application context structure */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** We have a separate thread to wait for Window and Clipboard events */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The X Toolkit widget which we use as our clipboard client. It is never made visible. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard: CLIPBOARD */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the selection: PRIMARY */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard targets: TARGETS */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard multiple target: MULTIPLE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard timestamp target: TIMESTAMP */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard utf16 text format: text/plain;charset=ISO-10646-UCS-2 */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard utf8 text format: UTF8_STRING */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** X11 atom refering to the clipboard compound text format: COMPOUND_TEXT */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** A list of the X11 formats which we support, mapped to our identifier for them, in the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync order we prefer to have them in. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Does the host or the guest currently own the clipboard? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** What is the best text format the host has to offer? INVALID for none. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Atom corresponding to the host text format */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** What is the best bitmap format the host has to offer? INVALID for none. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Atom corresponding to the host Bitmap format */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** What formats does the guest have on offer? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Windows caches the clipboard data it receives. Since we have no way of knowing whether
6ef855ecf2121f708685307839f1262e0db1a024vboxsync that data is still valid, we always send a "data changed" message after a successful
6ef855ecf2121f708685307839f1262e0db1a024vboxsync transfer to invalidate the cache. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Since the clipboard data moves asynchronously, we use an event semaphore to wait for
6ef855ecf2121f708685307839f1262e0db1a024vboxsync it. When a function issues a request for clipboard data it must wait for this
6ef855ecf2121f708685307839f1262e0db1a024vboxsync semaphore, which is triggered when the data arrives. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** And because it would not do for the guest to be waiting for the host while the host
6ef855ecf2121f708685307839f1262e0db1a024vboxsync is waiting for the guest, we set a flag and assert horribly if we spot a deadlock. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** This mutex is held while an asynchronous operation completes (i.e. the host clipboard is
6ef855ecf2121f708685307839f1262e0db1a024vboxsync being queried) to make sure that the clipboard is not disconnected during that time. It
6ef855ecf2121f708685307839f1262e0db1a024vboxsync is also grabbed when the clipboard client disconnects. When an asynchronous operation
6ef855ecf2121f708685307839f1262e0db1a024vboxsync starts completing, it checks that the same client is still connected immediately after
6ef855ecf2121f708685307839f1262e0db1a024vboxsync grabbing the mutex. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Format which we are reading from the host clipboard (valid during a request for the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync host clipboard) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The guest buffer to write host clipboard data to (valid during a request for the host
6ef855ecf2121f708685307839f1262e0db1a024vboxsync clipboard) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The size of the guest buffer to write host clipboard data to (valid during a request for
6ef855ecf2121f708685307839f1262e0db1a024vboxsync the host clipboard) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** The size of the host clipboard data written to the guest buffer (valid during a request
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for the host clipboard) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** Pointer to the client data structure */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/* Only one client is supported. There seems to be no need for more clients. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/* Are we actually connected to the X11 servicer? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Send a request to VBox to transfer the contents of its clipboard to X11.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pCtx Pointer to the host clipboard structure
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param u32Format The format in which the data should be transfered
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardConvert*
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic int vboxClipboardReadDataFromVBox (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Assert that no other transfer is in process (requests are serialised)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * and that the last transfer cleaned up properly. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* No one else (X11 or VBox) should currently be waiting. The first because
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * requests from X11 are serialised and the second because VBox previously
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * grabbed the clipboard, so it should not be waiting for data from us. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertLogRelReturn (ASMAtomicCmpXchgU32(&pCtx->waiter, 1, 0), VERR_DEADLOCK);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* This can legitimately happen if we disconnect during a request for
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * data from X11. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFunc(("host requested guest clipboard data after guest had disconnected.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Request data from the guest */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Which will signal us when it is ready. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int rc = RTSemEventWait(pCtx->waitForData, RT_INDEFINITE_WAIT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* I believe this should not happen. Wait until the assertions arrive
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * to prove the contrary. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Convert the UTF-16 text returned from the X11 clipboard to UTF-16LE with Windows EOLs
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * and place it in the global g_pcClipboardText variable. We are reading the host clipboard to
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * make it available to the guest.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValue Source UTF-16 text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cwSourceLen Length in 16-bit words of the source text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Where to store the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb Length in bytes of the buffer pointed to by cb
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcbActual Where to store the size of the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Pointer to the client context structure
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetUtf16(XtPointer pValue, unsigned cwSrcLen, void *pv, unsigned cb,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync PRTUTF16 pu16SrcText = reinterpret_cast<PRTUTF16>(pValue);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converting Utf-16 to Utf-16LE. cwSrcLen=%d, cb=%d, pu16SrcText+1=%.*ls\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pcbActual = 0; /* Only set this to the right value on success. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* How long will the converted text be? */
441579693f771e49eb05f2bd20c316232155675bvboxsync int rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Not enough buffer space provided - report the amount needed. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %.*ls\n", cwDestLen, pu16DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We need to do this whether we succeed or fail. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Convert the UTF-8 text returned from the X11 clipboard to UTF-16LE with Windows EOLS.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * We are reading the X11 clipboard to make it available to VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValue Source UTF-8 text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Where to store the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb Length in bytes of the buffer pointed to by pv
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcbActual Where to store the size of the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Pointer to the client context structure
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardGetDataFromX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetUtf8FromX11(XtPointer pValue, unsigned cbSrcLen,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *pu8SrcText = reinterpret_cast<char *>(pValue);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converting Utf-8 to Utf-16LE. cbSrcLen=%d, cb=%d, pu8SrcText=%.*s\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pcbActual = 0; /* Only set this to the right value on success. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* First convert the UTF8 to UTF16 */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int rc = RTStrToUtf16Ex(pu8SrcText, cbSrcLen, &pu16SrcText, 0, &cwSrcLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Check how much longer will the converted text will be. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Not enough buffer space provided - report the amount needed. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %.*ls.\n", cwDestLen, pu16DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Convert the COMPOUND_TEXT text returned from the X11 clipboard to UTF-16LE with Windows
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * EOLS. We are reading the X11 clipboard to make it available to VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValue Source COMPOUND_TEXT text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Where to store the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb Length in bytes of the buffer pointed to by pv
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcbActual Where to store the size of the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Pointer to the client context structure
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardGetDataFromX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetCTextFromX11(XtPointer pValue, unsigned cbSrcLen,
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync LogFlowFunc (("converting COMPOUND TEXT to Utf-16LE. cbSrcLen=%d, cb=%d, pu8SrcText=%.*s\n",
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync cbSrcLen, cb, cbSrcLen, reinterpret_cast<char *>(pValue)));
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync *pcbActual = 0; /* Only set this to the right value on success. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* First convert the compound text to Utf8 */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync property.value = reinterpret_cast<unsigned char *>(pValue);
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync int xrc = XmbTextPropertyToTextList(XtDisplay(g_ctx.widget), &property, &ppu8SrcText, &cProps);
58015215080abff9c3a752cb331b6efe29fe8933vboxsync int xrc = Xutf8TextPropertyToTextList(XtDisplay(g_ctx.widget), &property, &ppu8SrcText, &cProps);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Now convert the UTF8 to UTF16 */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = RTStrToUtf16Ex(*ppu8SrcText, cbSrcLen, &pu16SrcText, 0, &cwSrcLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Check how much longer will the converted text will be. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Not enough buffer space provided - report the amount needed. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %.*ls\n", cwDestLen, pu16DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Convert the Latin1 text returned from the X11 clipboard to UTF-16LE with Windows EOLS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * and place it in the global g_pcClipboardText variable. We are reading the X11 clipboard to
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * make it available to VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValue Source Latin1 text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Where to store the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb Length in bytes of the buffer pointed to by cb
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcbActual Where to store the size of the converted data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Pointer to the client context structure
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardGetDataFromX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetLatin1FromX11(XtPointer pValue, unsigned cbSourceLen, void *pv, unsigned cb,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converting Latin1 to Utf-16LE. Original is %.*s\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pcbActual = 0; /* Only set this to the right value on success. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0; i < cbSourceLen; i++)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Not enough buffer space provided - report the amount needed. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("guest buffer too small: size %d bytes\n", cb));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0, j = 0; i < cbSourceLen; ++i, ++j)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16DestText[j] = pu8SourceText[i]; /* latin1 < utf-16LE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted text is %.*ls\n", cwDestLen, pu16DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Convert the clipboard text from the current format to Utf-16 with Windows line breaks.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * We are reading the X11 clipboard to make it available to VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Callback for XtGetSelectionValue, called from vboxClipboardReadData
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetDataFromX11(Widget, XtPointer pClientData,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync long unsigned int *pcLen,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("pClientData=%p, *pcLen=%lu, *piFormat=%d\n", pClientData, *pcLen, *piFormat));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("g_ctx.requestHostFormat=%d, g_ctx.requestBufferSize=%d\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.requestHostFormat, g_ctx.requestBufferSize));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* The X Toolkit may have failed to get the clipboard selection for us. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* The clipboard selection may have changed before we could get it. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We grab this mutex whenever an asynchronous clipboard operation completes and while
6ef855ecf2121f708685307839f1262e0db1a024vboxsync disconnecting a client from the clipboard to stop these operations colliding. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTSemMutexRequest(g_ctx.asyncMutex, RT_INDEFINITE_WAIT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctx.pClient)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If the client is no longer connected, just return. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("client is no longer connected, returning\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* In which format did we request the clipboard data? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetUtf16(pValue, cTextLen / 2, g_ctx.requestBuffer, g_ctx.requestBufferSize,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetCTextFromX11(pValue, cTextLen, g_ctx.requestBuffer, g_ctx.requestBufferSize,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If we are given broken Utf-8, we treat it as Latin1. Is this acceptable? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync && (RTStrUniLenEx(pu8SourceText, *pcLen, &cStringLen) == VINF_SUCCESS))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetUtf8FromX11(pValue, cTextLen, g_ctx.requestBuffer, g_ctx.requestBufferSize,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetLatin1FromX11(pValue, cTextLen, g_ctx.requestBuffer, g_ctx.requestBufferSize,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Find out what targets the current X11 clipboard holder can handle. We are
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * reading the X11 clipboard to make it available to VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Callback for XtGetSelectionValue, called from vboxClipboardPollX11ForTargets
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardGetTargetsFromX11(Widget, XtPointer pClientData,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync long unsigned int *pcLen,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Atom *atomTargets = reinterpret_cast<Atom *>(pValue);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFunc (("reading clipboard from host, X toolkit failed to convert the selection\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We grab this mutex whenever an asynchronous clipboard operation completes and while
6ef855ecf2121f708685307839f1262e0db1a024vboxsync disconnecting a client from the clipboard to stop these operations colliding. */
30dced101cb78acf27e752f25c88c1f637539a1evboxsync RTSemMutexRequest(g_ctx.asyncMutex, RT_INDEFINITE_WAIT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctx.pClient)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If the client is no longer connected, just return. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("client is no longer connected, returning\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0; i < cAtoms; ++i)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned j = 0; j != g_ctx.formatList.size(); ++j)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomTargets[i]);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: the host offers target %s\n", __PRETTY_FUNCTION__,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((eBestTarget != g_ctx.hostTextFormat) || (g_ctx.notifyGuest == true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomBestTarget);
441579693f771e49eb05f2bd20c316232155675bvboxsync Log2 (("%s: switching to host text target %s. Available targets are:\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2(("%s: no supported host text target found. Available targets are:\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0; i < cAtoms; ++i)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomTargets[i]);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: %s\n", __PRETTY_FUNCTION__, szAtomName));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxSvcClipboardReportMsg (g_ctx.pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * This callback is called every 200ms to check the contents of the X11 clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
441579693f771e49eb05f2bd20c316232155675bvboxsync * @note Callback for XtAppAddTimeOut, called from vboxClipboardThread and
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * recursively retriggered
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardPollX11ForTargets(XtPointer /* pUserData */, XtIntervalId * /* hTimerId */)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Get the current clipboard contents */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log3 (("%s: requesting the targets that the host clipboard offers\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync XtGetSelectionValue(g_ctx.widget, g_ctx.atomClipboard, g_ctx.atomTargets,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetTargetsFromX11, reinterpret_cast<XtPointer>(g_ctx.pClient),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Re-arm our timer */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync XtAppAddTimeOut(g_ctx.appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** We store information about the target formats we can handle in a global vector for internal
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardAddFormat(const char *pszName, g_eClipboardFormats eFormat,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Get an atom from the X server for that target format */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Atom atomFormat = XInternAtom(XtDisplay(g_ctx.widget), pszName, false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlow (("vboxClipboardAddFormat: added format %s (%d)\n", pszName, eFormat));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * The main loop of our clipboard reader.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic int vboxClipboardThread(RTTHREAD self, void * /* pvUser */)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Shared clipboard: starting host clipboard thread\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Set up a timer to poll the host clipboard */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync XtAppAddTimeOut(g_ctx.appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Shared clipboard: host clipboard thread terminated successfully\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** X11 specific initialisation for the shared clipboard. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Create a window and make it a clipboard viewer. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // static String szFallbackResources[] = { (char*)"*.width: 1", (char*)"*.height: 1", NULL };
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Make sure we are thread safe */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Set up the Clipbard application context and main window. We call all these functions
6ef855ecf2121f708685307839f1262e0db1a024vboxsync directly instead of calling XtOpenApplication() so that we can fail gracefully if we
6ef855ecf2121f708685307839f1262e0db1a024vboxsync can't get an X11 display. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // XtAppSetFallbackResources(g_ctx.appContext, szFallbackResources);
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync pDisplay = XtOpenDisplay(g_ctx.appContext, 0, 0, "VBoxClipboard", 0, 0, &cArgc, &pcArgv);
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync LogRel(("Shared clipboard: failed to connect to the host clipboard - the window system may not be running.\n"));
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync g_ctx.widget = XtVaAppCreateShell(0, "VBoxClipboard", applicationShellWidgetClass, pDisplay,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Shared clipboard: failed to construct the X11 window for the host clipboard manager.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Get hold of the atoms which we need */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomClipboard = XInternAtom(XtDisplay(g_ctx.widget), "CLIPBOARD", false /* only_if_exists */);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomPrimary = XInternAtom(XtDisplay(g_ctx.widget), "PRIMARY", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomTargets = XInternAtom(XtDisplay(g_ctx.widget), "TARGETS", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomMultiple = XInternAtom(XtDisplay(g_ctx.widget), "MULTIPLE", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomTimestamp = XInternAtom(XtDisplay(g_ctx.widget), "TIMESTAMP", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomUtf16 = XInternAtom(XtDisplay(g_ctx.widget),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "text/plain;charset=ISO-10646-UCS-2", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomUtf8 = XInternAtom(XtDisplay(g_ctx.widget), "UTF_STRING", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* And build up the vector of supported formats */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync g_ctx.atomCText = XInternAtom(XtDisplay(g_ctx.widget), "COMPOUND_TEXT", false);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* And build up the vector of supported formats */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardAddFormat("text/plain;charset=ISO-10646-UCS-2", UTF16,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardAddFormat("text/plain;charset=UTF-8", UTF8,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardAddFormat("text/plain;charset=utf-8", UTF8,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Initialise the host side of the shared clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * If we don't find the DISPLAY environment variable we assume that we are not
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * connected to an X11 server. Don't actually try to do this then, just fail
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * silently and report success on every call. This is important for VBoxHeadless.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc(("no X11 detected -- host clipboard disabled\n"));
441579693f771e49eb05f2bd20c316232155675bvboxsync LogRel(("Host clipboard: testing compound text\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host clipboard: enabling additional debugging output\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = RTThreadCreate(&g_ctx.thread, vboxClipboardThread, 0, 0,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Failed to start the host shared clipboard thread.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Terminate the host side of the shared clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync unsigned count = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("vboxClipboardDestroy: shutting down host clipboard\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Drop the reference to the client, in case it is still there. This will
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * cause any outstanding clipboard data requests from X11 to fail
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * immediately. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Set the termination flag. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Wake up the event loop */
441579693f771e49eb05f2bd20c316232155675bvboxsync XSendEvent(XtDisplay(g_ctx.widget), XtWindow(g_ctx.widget), false, 0, &ev);
441579693f771e49eb05f2bd20c316232155675bvboxsync /* X11 may be waiting for data from VBox. At this point it is no
441579693f771e49eb05f2bd20c316232155675bvboxsync * longer going to arrive, and we must release it to allow the event
441579693f771e49eb05f2bd20c316232155675bvboxsync * loop to terminate. In this case the buffer where VBox would have
441579693f771e49eb05f2bd20c316232155675bvboxsync * written the clipboard data will still be empty and we will just
441579693f771e49eb05f2bd20c316232155675bvboxsync * return "no data" to X11. Any subsequent attempts to get the data
441579693f771e49eb05f2bd20c316232155675bvboxsync * from VBox will fail immediately as the client reference is gone. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5)));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * No one should be waiting on this by now. Justification:
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * - Case 1: VBox is waiting for data from X11:
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Not possible, as it would be waiting on this thread.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * - Case 2: X11 is waiting for data from VBox:
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Not possible, as we checked that the X11 event thread exited
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * successfully.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Connect a guest the shared clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Structure containing context information about the guest system
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns RT status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
441579693f771e49eb05f2bd20c316232155675bvboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncint vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Only one client is supported for now */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertLogRelReturn(g_ctx.pClient == 0, VERR_NOT_SUPPORTED);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Synchronise the contents of the host clipboard with the guest, called
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * after a save and restore of the guest.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncint vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* On a Linux host, the guest should never synchronise/cache its clipboard contents, as
6ef855ecf2121f708685307839f1262e0db1a024vboxsync we have no way of reliably telling when the host clipboard data changes. So instead
6ef855ecf2121f708685307839f1262e0db1a024vboxsync of synchronising, we tell the guest to empty its clipboard, and we set the cached
6ef855ecf2121f708685307839f1262e0db1a024vboxsync flag so that we report formats to the guest next time we poll for them. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxSvcClipboardReportMsg (g_ctx.pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Shut down the shared clipboard service and "disconnect" the guest.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTSemMutexRequest(g_ctx.asyncMutex, RT_INDEFINITE_WAIT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Satisfy a request from X11 for clipboard targets supported by VBox.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if we successfully convert the data to the format requested, false otherwise.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param atomTypeReturn The type of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValReturn A pointer to the data we are returning. This should be to memory
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * allocated by XtMalloc, which will be freed by the toolkit later
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync * @param pcLenReturn The length of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param piFormatReturn The format (8bit, 16bit, 32bit) of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync * @note called by vboxClipboardConvertForX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic Boolean vboxClipboardConvertTargetsForX11(Atom *atomTypeReturn, XtPointer *pValReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Atom *atomTargets = reinterpret_cast<Atom *>(XtMalloc((uListSize + 3) * sizeof(Atom)));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync unsigned cTargets = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0; i < uListSize; ++i)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ( ((g_ctx.guestFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync && (g_ctx.formatList[i].guestFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), atomTargets[i]);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: returning target %s\n", __PRETTY_FUNCTION__,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log(("%s: invalid atom %d in the list!\n", __PRETTY_FUNCTION__,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pValReturn = reinterpret_cast<XtPointer>(atomTargets);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Reset the contents of the buffer used to pass clipboard data from VBox to X11.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * This must be done after every clipboard transfer.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Satisfy a request from the host to convert the clipboard text to Utf16. We return non-zero
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * terminated text.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if we successfully convert the data to the format requested, false otherwise.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval atomTypeReturn The type of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval pValReturn A pointer to the data we are returning. This should be to memory
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * allocated by XtMalloc, which will be freed by the toolkit later
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval pcLenReturn The length of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval piFormatReturn The format (8bit, 16bit, 32bit) of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic Boolean vboxClipboardConvertUtf16(Atom *atomTypeReturn, XtPointer *pValReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardReadDataFromVBox(&g_ctx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((RT_FAILURE(rc)) || (g_ctx.pClient->data.cb == 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RT_SUCCESS(rc) ? ", g_ctx.pClient->data.cb == 0" : ""));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16SrcText = reinterpret_cast<PRTUTF16>(g_ctx.pClient->data.pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* How long will the converted text be? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16GetLinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("received empty clipboard data from the guest, returning false.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16DestText = reinterpret_cast<PRTUTF16>(XtMalloc(cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("vboxClipboardConvertUtf16: failed to allocate %d bytes\n", cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16WinToLin(pu16SrcText, cwSrcLen, pu16DestText, cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16WinToLin returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %.*ls. Returning.\n", cwDestLen, pu16DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pValReturn = reinterpret_cast<XtPointer>(pu16DestText);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Satisfy a request from the host to convert the clipboard text to Utf8.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if we successfully convert the data to the format requested, false otherwise.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param atomTypeReturn The type of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValReturn A pointer to the data we are returning. This should be to memory
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * allocated by XtMalloc, which will be freed by the toolkit later
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcLenReturn The length of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param piFormatReturn The format (8bit, 16bit, 32bit) of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardConvertForX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic Boolean vboxClipboardConvertToUtf8ForX11(Atom *atomTypeReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync unsigned long *pcLenReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Read the clipboard data from the guest. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardReadDataFromVBox(&g_ctx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((rc != VINF_SUCCESS) || (g_ctx.pClient->data.cb == 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RT_SUCCESS(rc) ? ", g_ctx.pClient->data.cb == 0" : ""));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16SrcText = reinterpret_cast<PRTUTF16>(g_ctx.pClient->data.pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* How long will the converted text be? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16GetLinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("received empty clipboard data from the guest, returning false.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16DestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16WinToLin(pu16SrcText, cwSrcLen, pu16DestText, cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Allocate enough space, as RTUtf16ToUtf8Ex may fail if the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync space is too tightly calculated. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 4));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the Utf16 string to Utf8. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = RTUtf16ToUtf8Ex(pu16DestText + 1, cwDestLen - 1, &pu8DestText, cwDestLen * 4,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. RTUtf16ToUtf8Ex() returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %.*s. Returning.\n", cbDestLen, pu8DestText));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pValReturn = reinterpret_cast<XtPointer>(pu8DestText);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Satisfy a request from the host to convert the clipboard text to COMPOUND_TEXT.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if we successfully convert the data to the format requested, false otherwise.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param atomTypeReturn The type of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pValReturn A pointer to the data we are returning. This should be to memory
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * allocated by XtMalloc, which will be freed by the toolkit later
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcLenReturn The length of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param piFormatReturn The format (8bit, 16bit, 32bit) of the data we are returning
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note called by vboxClipboardConvertForX11
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic Boolean vboxClipboardConvertToCTextForX11(Atom *atomTypeReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync unsigned long *pcLenReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Read the clipboard data from the guest. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardReadDataFromVBox(&g_ctx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((rc != VINF_SUCCESS) || (g_ctx.pClient->data.cb == 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RT_SUCCESS(rc) ? ", g_ctx.pClient->data.cb == 0" : ""));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16SrcText = reinterpret_cast<PRTUTF16>(g_ctx.pClient->data.pv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* How long will the converted text be? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16GetLinSize(pu16SrcText, cwSrcLen, &cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc(("received empty clipboard data from the guest, returning false.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync pu16DestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 2));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = vboxClipboardUtf16WinToLin(pu16SrcText, cwSrcLen, pu16DestText, cwDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Convert the Utf16 string to Utf8. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = RTUtf16ToUtf8Ex(pu16DestText + 1, cwDestLen - 1, &pu8DestText, 0, &cbDestLen);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("clipboard conversion failed. RTUtf16ToUtf8Ex() returned %Rrc. Abandoning.\n", rc));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* And finally (!) convert the Utf8 text to compound text. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = XmbTextListToTextProperty(XtDisplay(g_ctx.widget), &pu8DestText, 1,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = Xutf8TextListToTextProperty(XtDisplay(g_ctx.widget), &pu8DestText, 1,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync const char *pcReason;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRelFunc (("Xutf8TextListToTextProperty failed. Reason: %s\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("converted string is %s. Returning.\n", property.value));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *pValReturn = reinterpret_cast<XtPointer>(property.value);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Callback to request VBox's clipboard data for an X11 client. Called by the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * X Toolkit.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note callback for XtOwnSelection, called by vboxClipboardFormatAnnounce
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic Boolean vboxClipboardConvertForX11(Widget, Atom *atomSelection,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync unsigned long *pcLenReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Drop requests that we receive too late. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctx.widget), *atomTarget);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: request for format %s\n", __PRETTY_FUNCTION__, szAtomName));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFunc (("request for invalid target atom %d!\n", *atomTarget));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (unsigned i = 0; i != g_ctx.formatList.size(); ++i)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return vboxClipboardConvertTargetsForX11(atomTypeReturn, pValReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return vboxClipboardConvertUtf16(atomTypeReturn, pValReturn, pcLenReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return vboxClipboardConvertToUtf8ForX11(atomTypeReturn, pValReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return vboxClipboardConvertToCTextForX11(atomTypeReturn, pValReturn,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * This is called by the X toolkit intrinsics to let us know that another
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * X11 client has taken the clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note callback for XtOwnSelection, called from vboxClipboardFormatAnnounce
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread clipboard X11 event thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic void vboxClipboardReturnToX11(Widget, Atom *)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("called, giving VBox clipboard ownership\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * VBox is taking possession of the shared clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Context data for the guest system
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param u32Formats Clipboard formats the guest is offering
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* This is just an automatism, not a genuine anouncement */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We already own the clipboard, so no need to grab it, especially as that can lead
6ef855ecf2121f708685307839f1262e0db1a024vboxsync to races due to the asynchronous nature of the X11 clipboard. This event may also
6ef855ecf2121f708685307839f1262e0db1a024vboxsync have been sent out by the guest to invalidate the Windows clipboard cache. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: giving the guest clipboard ownership\n", __PRETTY_FUNCTION__));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (XtOwnSelection(g_ctx.widget, g_ctx.atomClipboard, CurrentTime, vboxClipboardConvertForX11,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Log2 (("%s: returning clipboard ownership to the host\n", __PRETTY_FUNCTION__));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We set this so that the guest gets notified when we take the clipboard, even if no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync guest formats are found which we understand. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync XtOwnSelection(g_ctx.widget, g_ctx.atomPrimary, CurrentTime, vboxClipboardConvertForX11,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called when VBox wants to read the X11 clipboard.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Context information about the guest VM
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param u32Format The format that the guest would like to receive the data in
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Where to write the data to
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb The size of the buffer to write the data to
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pcbActual Where to write the actual size of the written data
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncint vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Immediately return if we are not connected to the host X server.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* no data available */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("u32Format = %d, cb = %d\n", u32Format, cb));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * The guest wants to read data in the given format.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* No data available. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return VERR_NO_DATA; /* The guest thinks we have data and we don't */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* No one else (VBox or X11) should currently be waiting. The first because
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * requests from VBox are serialised and the second because X11 previously
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * grabbed the clipboard, so it should not be waiting for data from us. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctx.waiter, 1, 0), VERR_DEADLOCK);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Initially set the size of the data read to zero in case we fail
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * somewhere. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Send out a request for the data to the current clipboard owner */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync XtGetSelectionValue(g_ctx.widget, g_ctx.atomClipboard, g_ctx.atomHostTextFormat,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vboxClipboardGetDataFromX11, reinterpret_cast<XtPointer>(g_ctx.pClient),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* When the data arrives, the vboxClipboardGetDataFromX11 callback will be called. The
6ef855ecf2121f708685307839f1262e0db1a024vboxsync callback will signal the event semaphore when it has processed the data for us. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int rc = RTSemEventWait(g_ctx.waitForData, RT_INDEFINITE_WAIT);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called when we have requested data from VBox and that data has arrived.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pClient Context information about the guest VM
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param pv Buffer to which the data was written
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param cb The size of the data written
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param u32Format The format of the data written
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Called by the HGCM clipboard service
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @thread HGCM clipboard service thread
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Assert that no other transfer is in process (requests are serialised)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * or has not cleaned up properly. */