x11-clipboard.cpp revision 355e8f335c21967a66a2151d4b8571c0ba3b35ec
af062818b47340eef15700d2f0211576ba3506eevboxsync * Shared Clipboard:
af062818b47340eef15700d2f0211576ba3506eevboxsync * Linux host.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
af062818b47340eef15700d2f0211576ba3506eevboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
af062818b47340eef15700d2f0211576ba3506eevboxsync * additional information or have any questions.
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Do we want to test Utf16 by disabling other text formats? */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic bool g_testUtf16 = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Do we want to test Utf8 by disabling other text formats? */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic bool g_testUtf8 = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Do we want to test compount text by disabling other text formats? */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic bool g_testCText = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Are we currently debugging the clipboard code? */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic bool g_debugClipboard = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync/** The different clipboard formats which we support. */
af062818b47340eef15700d2f0211576ba3506eevboxsync/** The X11 clipboard uses several names for the same format. This structure maps an X11
af062818b47340eef15700d2f0211576ba3506eevboxsync name to a format. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsynctypedef struct {
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Does X11 or VBox currently own the clipboard? */
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct {
af062818b47340eef15700d2f0211576ba3506eevboxsync /** BMP file type marker - must always contain 'BM' */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The size of the BMP file in bytes (the MS docs say that this is not reliable) */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Reserved, must always be zero */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Reserved, must always be zero */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** Offset from the beginning of this header to the actual image bits */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/** Global context information used by the host glue for the X11 clipboard
af062818b47340eef15700d2f0211576ba3506eevboxsync * backend */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Since the clipboard data moves asynchronously, we use an event
af062818b47340eef15700d2f0211576ba3506eevboxsync * semaphore to wait for it. When a function issues a request for
af062818b47340eef15700d2f0211576ba3506eevboxsync * clipboard data it must wait for this semaphore, which is triggered
af062818b47340eef15700d2f0211576ba3506eevboxsync * when the data arrives. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** Who (if anyone) is currently waiting for data? Used for sanity
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * checks when data arrives. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** This mutex is grabbed during any critical operations on the clipboard
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * which might clash with others. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** Pointer to the client data structure */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/** Global context information used by the X11 clipboard backend */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The X Toolkit application context structure */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** We have a separate thread to wait for Window and Clipboard events */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The X Toolkit widget which we use as our clipboard client. It is never made visible. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** X11 atom refering to the clipboard: CLIPBOARD */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** X11 atom refering to the selection: PRIMARY */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** X11 atom refering to the clipboard targets: TARGETS */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** X11 atom refering to the clipboard multiple target: MULTIPLE */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** X11 atom refering to the clipboard timestamp target: TIMESTAMP */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** X11 atom refering to the clipboard utf16 text format: text/plain;charset=ISO-10646-UCS-2 */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** X11 atom refering to the clipboard utf8 text format: UTF8_STRING */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** X11 atom refering to the clipboard compound text format: COMPOUND_TEXT */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** A list of the X11 formats which we support, mapped to our identifier for them, in the
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync order we prefer to have them in. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Does VBox or X11 currently own the clipboard? */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** What is the best text format X11 has to offer? INVALID for none. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** Atom corresponding to the X11 text format */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** What is the best bitmap format X11 has to offer? INVALID for none. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** Atom corresponding to the X11 Bitmap format */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /** What formats does VBox have on offer? */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Windows hosts and guests cache the clipboard data they receive.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Since we have no way of knowing whether their cache is still valid,
af062818b47340eef15700d2f0211576ba3506eevboxsync * we always send a "data changed" message after a successful transfer
af062818b47340eef15700d2f0211576ba3506eevboxsync * to invalidate it. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** Since the clipboard data moves asynchronously, we use an event
af062818b47340eef15700d2f0211576ba3506eevboxsync * semaphore to wait for it. When a function issues a request for
af062818b47340eef15700d2f0211576ba3506eevboxsync * clipboard data it must wait for this semaphore, which is triggered
af062818b47340eef15700d2f0211576ba3506eevboxsync * when the data arrives. */
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct _VBOXCLIPBOARDCONTEXTX11 VBOXCLIPBOARDCONTEXTX11;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/** A structure containing information about where to store a request
af062818b47340eef15700d2f0211576ba3506eevboxsync * for the X11 clipboard contents. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The buffer to write X11 clipboard data to (valid during a request
af062818b47340eef15700d2f0211576ba3506eevboxsync * for the clipboard contents) */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The size of the buffer to write X11 clipboard data to (valid during
af062818b47340eef15700d2f0211576ba3506eevboxsync * a request for the clipboard contents) */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** The size of the X11 clipboard data written to the buffer (valid
af062818b47340eef15700d2f0211576ba3506eevboxsync * during a request for the clipboard contents) */
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct _VBOXCLIPBOARDREQUEST VBOXCLIPBOARDREQUEST;
af062818b47340eef15700d2f0211576ba3506eevboxsync/* Only one client is supported. There seems to be no need for more clients.
af062818b47340eef15700d2f0211576ba3506eevboxsync/* Are we actually connected to the X server? */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Send a request to VBox to transfer the contents of its clipboard to X11.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCtx Pointer to the host clipboard structure
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param u32Format The format in which the data should be transfered
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param ppv On success and if pcb > 0, this will point to a buffer
af062818b47340eef15700d2f0211576ba3506eevboxsync * to be freed with RTMemFree containing the data read.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pcb On success, this contains the number of bytes of data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note Host glue code.
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic int vboxClipboardReadDataFromVBox (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void **ppv, uint32_t *pcb)
af062818b47340eef15700d2f0211576ba3506eevboxsync volatile VBOXCLIPBOARDCLIENTDATA *pClient = pCtx->pClient;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* This can legitimately happen if we disconnect during a request for
af062818b47340eef15700d2f0211576ba3506eevboxsync * data from X11. */
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFunc(("host requested guest clipboard data after guest had disconnected.\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Assert that no other transfer is in process (requests are serialised)
af062818b47340eef15700d2f0211576ba3506eevboxsync * and that the last transfer cleaned up properly. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* No one else (X11 or VBox) should currently be waiting. The first because
af062818b47340eef15700d2f0211576ba3506eevboxsync * requests from X11 are serialised and the second because VBox previously
af062818b47340eef15700d2f0211576ba3506eevboxsync * grabbed the clipboard, so it should not be waiting for data from us. */
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertLogRelReturn (ASMAtomicCmpXchgU32(&pCtx->waiter, X11, NONE), VERR_DEADLOCK);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Request data from VBox */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Which will signal us when it is ready. We use a timeout here because
af062818b47340eef15700d2f0211576ba3506eevboxsync * we can't be sure that the guest will behave correctly. */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = RTSemEventWait(pCtx->waitForData, CLIPBOARDTIMEOUT);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Now we have a potential race between the HGCM thread delivering the data
af062818b47340eef15700d2f0211576ba3506eevboxsync * and our setting waiter to NONE to say that we are no longer waiting for
af062818b47340eef15700d2f0211576ba3506eevboxsync * it. We solve this as follows: both of these operations are done under
af062818b47340eef15700d2f0211576ba3506eevboxsync * the clipboard mutex. The HGCM thread will only deliver the data if we
af062818b47340eef15700d2f0211576ba3506eevboxsync * are still waiting after it acquires the mutex. After we release the
af062818b47340eef15700d2f0211576ba3506eevboxsync * mutex, we finally do our check to see whether the data was delivered. */
af062818b47340eef15700d2f0211576ba3506eevboxsync RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* I believe this should not happen. Wait until the assertions arrive
af062818b47340eef15700d2f0211576ba3506eevboxsync * to prove the contrary. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Convert the UTF-16 text obtained from the X11 clipboard to UTF-16LE with
af062818b47340eef15700d2f0211576ba3506eevboxsync * Windows EOLs, place it in the buffer supplied and signal that data has
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pValue Source UTF-16 text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cwSourceLen Length in 16-bit words of the source text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pv Where to store the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cb Length in bytes of the buffer pointed to by cb
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pcbActual Where to store the size of the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pClient Pointer to the client context structure
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @note X11 backend code, called from the Xt callback when we wish to read
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * the X11 clipboard.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncstatic void vboxClipboardGetUtf16(XtPointer pValue, unsigned cwSrcLen,
af062818b47340eef15700d2f0211576ba3506eevboxsync PRTUTF16 pu16SrcText = reinterpret_cast<PRTUTF16>(pValue);
af062818b47340eef15700d2f0211576ba3506eevboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("converting Utf-16 to Utf-16LE. cwSrcLen=%d, cb=%d, pu16SrcText+1=%.*ls\n",
af062818b47340eef15700d2f0211576ba3506eevboxsync *pcbActual = 0; /* Only set this to the right value on success. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* How long will the converted text be? */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Not enough buffer space provided - report the amount needed. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Convert the text. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("converted string is %.*ls\n", cwDestLen, pu16DestText));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* We need to do this whether we succeed or fail. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Convert the UTF-8 text obtained from the X11 clipboard to UTF-16LE with
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Windows EOLs, place it in the buffer supplied and signal that data has
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pValue Source UTF-8 text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pv Where to store the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cb Length in bytes of the buffer pointed to by pv
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pcbActual Where to store the size of the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pClient Pointer to the client context structure
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note X11 backend code, called from the Xt callback when we wish to read
af062818b47340eef15700d2f0211576ba3506eevboxsync * the X11 clipboard.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncstatic void vboxClipboardGetUtf8FromX11(XtPointer pValue, unsigned cbSrcLen,
af062818b47340eef15700d2f0211576ba3506eevboxsync char *pu8SrcText = reinterpret_cast<char *>(pValue);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("converting Utf-8 to Utf-16LE. cbSrcLen=%d, cb=%d, pu8SrcText=%.*s\n",
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *pcbActual = 0; /* Only set this to the right value on success. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* First convert the UTF8 to UTF16 */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync int rc = RTStrToUtf16Ex(pu8SrcText, cbSrcLen, &pu16SrcText, 0, &cwSrcLen);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Check how much longer will the converted text will be. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Not enough buffer space provided - report the amount needed. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Convert the text. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("converted string is %.*ls.\n", cwDestLen, pu16DestText));
af062818b47340eef15700d2f0211576ba3506eevboxsync * Convert the COMPOUND_TEXT obtained from the X11 clipboard to UTF-16LE with
af062818b47340eef15700d2f0211576ba3506eevboxsync * Windows EOLs, place it in the buffer supplied and signal that data has
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pValue Source COMPOUND_TEXT
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pv Where to store the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cb Length in bytes of the buffer pointed to by pv
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pcbActual Where to store the size of the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pClient Pointer to the client context structure
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note X11 backend code, called from the Xt callback when we wish to read
af062818b47340eef15700d2f0211576ba3506eevboxsync * the X11 clipboard.
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic void vboxClipboardGetCTextFromX11(XtPointer pValue, unsigned cbSrcLen,
af062818b47340eef15700d2f0211576ba3506eevboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("converting COMPOUND TEXT to Utf-16LE. cbSrcLen=%d, cb=%d, pu8SrcText=%.*s\n",
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync cbSrcLen, cb, cbSrcLen, reinterpret_cast<char *>(pValue)));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *pcbActual = 0; /* Only set this to the right value on success. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* First convert the compound text to Utf8 */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync property.value = reinterpret_cast<unsigned char *>(pValue);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync int xrc = XmbTextPropertyToTextList(XtDisplay(g_ctxX11.widget), &property, &ppu8SrcText, &cProps);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync int xrc = Xutf8TextPropertyToTextList(XtDisplay(g_ctxX11.widget), &property, &ppu8SrcText, &cProps);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Now convert the UTF8 to UTF16 */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTStrToUtf16Ex(*ppu8SrcText, cbSrcLen, &pu16SrcText, 0, &cwSrcLen);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Check how much longer will the converted text will be. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = vboxClipboardUtf16GetWinSize(pu16SrcText, cwSrcLen, &cwDestLen);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Not enough buffer space provided - report the amount needed. */
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("guest buffer too small: size %d bytes, needed %d. Returning.\n",
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Convert the text. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = vboxClipboardUtf16LinToWin(pu16SrcText, cwSrcLen, pu16DestText, cb / 2);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("converted string is %.*ls\n", cwDestLen, pu16DestText));
af062818b47340eef15700d2f0211576ba3506eevboxsync * Convert the Latin1 text obtained from the X11 clipboard to UTF-16LE with
af062818b47340eef15700d2f0211576ba3506eevboxsync * Windows EOLs, place it in the buffer supplied and signal that data has
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pValue Source Latin1 text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cbSourceLen Length in 8-bit bytes of the source text
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pv Where to store the converted data
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cb Length in bytes of the buffer pointed to by cb
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pcbActual Where to store the size of the converted data
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pClient Pointer to the client context structure
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note X11 backend code, called from the Xt callback when we wish to read
af062818b47340eef15700d2f0211576ba3506eevboxsync * the X11 clipboard.
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic void vboxClipboardGetLatin1FromX11(XtPointer pValue,
af062818b47340eef15700d2f0211576ba3506eevboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
af062818b47340eef15700d2f0211576ba3506eevboxsync PRTUTF16 pu16DestText = reinterpret_cast<PRTUTF16>(pv);
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("converting Latin1 to Utf-16LE. Original is %.*s\n",
af062818b47340eef15700d2f0211576ba3506eevboxsync *pcbActual = 0; /* Only set this to the right value on success. */
af062818b47340eef15700d2f0211576ba3506eevboxsync for (unsigned i = 0; i < cbSourceLen; i++)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Not enough buffer space provided - report the amount needed. */
af062818b47340eef15700d2f0211576ba3506eevboxsync LogFlowFunc (("guest buffer too small: size %d bytes\n", cb));
af062818b47340eef15700d2f0211576ba3506eevboxsync for (unsigned i = 0, j = 0; i < cbSourceLen; ++i, ++j)
af062818b47340eef15700d2f0211576ba3506eevboxsync pu16DestText[j] = pu8SourceText[i]; /* latin1 < utf-16LE */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc (("converted text is %.*ls\n", cwDestLen, pu16DestText));
af062818b47340eef15700d2f0211576ba3506eevboxsync * Convert the text obtained from the X11 clipboard to UTF-16LE with Windows
af062818b47340eef15700d2f0211576ba3506eevboxsync * EOLs, place it in the buffer supplied and signal that data has arrived.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note X11 backend code, callback for XtGetSelectionValue, for use when
af062818b47340eef15700d2f0211576ba3506eevboxsync * the X11 clipboard contains a text format we understand.
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic void vboxClipboardGetDataFromX11(Widget, XtPointer pClientData,
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync long unsigned int *pcLen,
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync = reinterpret_cast<VBOXCLIPBOARDREQUEST *>(pClientData);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc(("pClientData=%p, *pcLen=%lu, *piFormat=%d\n", pClientData,
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFlowFunc(("g_ctxX11.X11TextFormat=%d, pRequest->cb=%d\n",
af062818b47340eef15700d2f0211576ba3506eevboxsync /* The X Toolkit may have failed to get the clipboard selection for us. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* The clipboard selection may have changed before we could get it. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* In which format is the clipboard data? */
af062818b47340eef15700d2f0211576ba3506eevboxsync vboxClipboardGetUtf16(pValue, cTextLen / 2, pRequest->pv,
af062818b47340eef15700d2f0211576ba3506eevboxsync vboxClipboardGetCTextFromX11(pValue, cTextLen, pRequest->pv,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* If we are given broken Utf-8, we treat it as Latin1. Is this acceptable? */
af062818b47340eef15700d2f0211576ba3506eevboxsync char *pu8SourceText = reinterpret_cast<char *>(pValue);
af062818b47340eef15700d2f0211576ba3506eevboxsync && (RTStrUniLenEx(pu8SourceText, *pcLen, &cStringLen) == VINF_SUCCESS))
af062818b47340eef15700d2f0211576ba3506eevboxsync vboxClipboardGetUtf8FromX11(pValue, cTextLen, pRequest->pv,
af062818b47340eef15700d2f0211576ba3506eevboxsync vboxClipboardGetLatin1FromX11(pValue, cTextLen, pRequest->pv,
af062818b47340eef15700d2f0211576ba3506eevboxsync * Notify the host clipboard about the data formats we support, based on the
af062818b47340eef15700d2f0211576ba3506eevboxsync * "targets" (available data formats) information obtained from the X11
af062818b47340eef15700d2f0211576ba3506eevboxsync * clipboard.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note X11 backend code, callback for XtGetSelectionValue, called when we
af062818b47340eef15700d2f0211576ba3506eevboxsync * poll for available targets.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @todo This function still references host-specific data and calls host
af062818b47340eef15700d2f0211576ba3506eevboxsync * frontend APIs. Fix.
af062818b47340eef15700d2f0211576ba3506eevboxsync long unsigned int *pcLen,
af062818b47340eef15700d2f0211576ba3506eevboxsync Atom *atomTargets = reinterpret_cast<Atom *>(pValue);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync LogFunc (("reading clipboard from host, X toolkit failed to convert the selection\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync for (unsigned i = 0; i < cAtoms; ++i)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync for (unsigned j = 0; j != g_ctxX11.formatList.size(); ++j)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomTargets[i]);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log2 (("%s: the host offers target %s\n", __PRETTY_FUNCTION__,
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if ((eBestTarget != g_ctxX11.X11TextFormat) || (g_ctxX11.notifyVBox == true))
af062818b47340eef15700d2f0211576ba3506eevboxsync char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomBestTarget);
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2 (("%s: switching to host text target %s. Available targets are:\n",
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("%s: no supported host text target found. Available targets are:\n",
for (unsigned i = 0; i < cAtoms; ++i)
if (szAtomName != 0)
static void vboxClipboardPollX11ForTargets(XtPointer /* pUserData */, XtIntervalId * /* hTimerId */)
unsigned guestFormat)
return VINF_SUCCESS;
int vboxClipboardInitX11 (void)
int cArgc = 0;
char *pcArgv = 0;
LogRel(("Shared clipboard: failed to connect to the host clipboard - the window system may not be running.\n"));
g_ctxX11.atomClipboard = XInternAtom(XtDisplay(g_ctxX11.widget), "CLIPBOARD", false /* only_if_exists */);
return rc;
int vboxClipboardInitBackend (void)
int rc;
g_fHaveX11 = false;
return VINF_SUCCESS;
g_testUtf16 = true;
g_testUtf8 = true;
g_testCText = true;
g_debugClipboard = true;
g_fHaveX11 = true;
return rc;
int vboxClipboardInit (void)
return rc;
int vboxClipboardDestroyBackend (void)
unsigned count = 0;
if (!g_fHaveX11)
return VINF_SUCCESS;
++count;
return rc;
void vboxClipboardDestroy (void)
if (!g_fHaveX11)
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
void vboxClipboardRequestSync (void)
if (!g_fHaveX11)
/* On a Linux host, the guest should never synchronise/cache its
return VINF_SUCCESS;
void vboxClipboardDisconnectBackend (void)
if (!g_fHaveX11)
unsigned long *pcLenReturn,
int *piFormatReturn)
unsigned cTargets = 0;
for (unsigned i = 0; i < uListSize; ++i)
++cTargets;
if (g_debugClipboard)
if (szAtomName != 0)
szAtomName));
atomTargets[i]));
unsigned long *pcLenReturn,
int *piFormatReturn)
void *pvVBox;
int rc;
rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16WinToLin returned %Rrc. Abandoning.\n", rc));
unsigned long *pcLenReturn,
int *piFormatReturn)
char *pu8DestText;
void *pvVBox;
int rc;
rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
if (pu8DestText == 0)
&cbDestLen);
unsigned long *pcLenReturn,
int *piFormatReturn)
void *pvVBox;
char *pu8DestText = 0;
int rc;
rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRelFunc (("clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
#ifdef RT_OS_SOLARIS
if (rc < 0)
const char *pcReason;
switch(rc)
case XNoMemory:
case XLocaleNotSupported:
case XConverterNotFound:
pcReason));
unsigned long *pcLenReturn,
int *piFormatReturn)
if (g_debugClipboard)
if (szAtomName != 0)
switch (eFormat)
case TARGETS:
case UTF16:
case UTF8:
case CTEXT:
if (!g_fHaveX11)
if (u32Formats == 0)
if (XtOwnSelection(g_ctxX11.widget, g_ctxX11.atomClipboard, CurrentTime, vboxClipboardConvertForX11,
NULL, 0);
if (!g_fHaveX11)
return VINF_SUCCESS;
return rc;
return VERR_NOT_IMPLEMENTED;
return VINF_SUCCESS;
return rc;
void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format)
if (!g_fHaveX11)