VirtualBox

Ignore:
Timestamp:
Apr 1, 2009 6:17:54 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
45519
Message:

GuestHost/SharedClipboard: recommitted x11-clipboard.cpp with more history, take 2

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp

    r18582 r18613  
    22 *
    33 * Shared Clipboard:
    4  * Linux host.
     4 * X11 backend code.
    55 */
    66
     
    2121 */
    2222
    23 #include <string.h>
    24 #include <stdio.h>
    25 #include <stdint.h>
     23/** @todo create a clipboard log group */
     24#define LOG_GROUP LOG_GROUP_HGCM
     25
     26#include <vector>
    2627
    2728#ifdef RT_OS_SOLARIS
    2829#include <tsol/label.h>
    2930#endif
    30 
    31 #include <vector>
    3231
    3332#include <X11/Xlib.h>
     
    3837#include <X11/StringDefs.h>
    3938
    40 #include <iprt/alloc.h>
    41 #include <iprt/asm.h>        /* For atomic operations */
    42 #include <iprt/assert.h>
    4339#include <iprt/env.h>
    4440#include <iprt/mem.h>
    45 #include <iprt/string.h>
     41#include <iprt/semaphore.h>
    4642#include <iprt/thread.h>
    47 #include <iprt/process.h>
    48 #include <iprt/semaphore.h>
    49 
     43
     44#include <VBox/log.h>
     45
     46#include <VBox/GuestHost/SharedClipboard.h>
    5047#include <VBox/GuestHost/clipboard-helper.h>
    5148#include <VBox/HostServices/VBoxClipboardSvc.h>
    52 
    53 #include "VBoxClipboard.h"
    5449
    5550/** Do we want to test Utf16 by disabling other text formats? */
     
    7267};
    7368
    74 /** The X11 clipboard uses several names for the same format.  This structure maps an X11
    75    name to a format. */
     69/** The X11 clipboard uses several names for the same format.  This
     70 * structure maps an X11 name to a format. */
    7671typedef struct {
    7772    Atom atom;
     
    7974    unsigned guestFormat;
    8075} VBOXCLIPBOARDFORMAT;
    81 
    82 /** Does X11 or VBox currently own the clipboard? */
    83 enum g_eOwner { NONE = 0, X11, VB };
    84 
    85 typedef struct {
    86     /** BMP file type marker - must always contain 'BM' */
    87     uint16_t bfType;
    88     /** The size of the BMP file in bytes (the MS docs say that this is not reliable) */
    89     uint32_t bfSize;
    90     /** Reserved, must always be zero */
    91     uint16_t bfReserved1;
    92     /** Reserved, must always be zero */
    93     uint16_t bfReserved2;
    94     /** Offset from the beginning of this header to the actual image bits */
    95 } VBOXBITMAPFILEHEADER;
    96 
    97 /** Global context information used by the host glue for the X11 clipboard
    98  * backend */
    99 struct _VBOXCLIPBOARDCONTEXT
    100 {
    101     /** Since the clipboard data moves asynchronously, we use an event
    102      * semaphore to wait for it.  When a function issues a request for
    103      * clipboard data it must wait for this semaphore, which is triggered
    104      * when the data arrives. */
    105     RTSEMEVENT waitForData;
    106     /** Who (if anyone) is currently waiting for data?  Used for sanity
    107      * checks when data arrives. */
    108     volatile uint32_t waiter;
    109     /** This mutex is grabbed during any critical operations on the clipboard
    110      * which might clash with others. */
    111     RTSEMMUTEX clipboardMutex;
    112 
    113     /** Pointer to the client data structure */
    114     VBOXCLIPBOARDCLIENTDATA *pClient;
    115 };
    11676
    11777/** Global context information used by the X11 clipboard backend */
     
    175135};
    176136
    177 typedef struct _VBOXCLIPBOARDCONTEXTX11 VBOXCLIPBOARDCONTEXTX11;
    178 
    179 /** A structure containing information about where to store a request
    180  * for the X11 clipboard contents. */
    181 struct _VBOXCLIPBOARDREQUEST
    182 {
    183     /** The buffer to write X11 clipboard data to (valid during a request
    184      * for the clipboard contents) */
    185     void *pv;
    186     /** The size of the buffer to write X11 clipboard data to (valid during
    187      * a request for the clipboard contents) */
    188     unsigned cb;
    189     /** The size of the X11 clipboard data written to the buffer (valid
    190      * during a request for the clipboard contents) */
    191     uint32_t *pcbActual;
    192 };
    193 
    194 typedef struct _VBOXCLIPBOARDREQUEST VBOXCLIPBOARDREQUEST;
    195 
    196137/* Only one client is supported. There seems to be no need for more clients.
    197138 */
    198 static VBOXCLIPBOARDCONTEXT g_ctxHost;
    199139static VBOXCLIPBOARDCONTEXTX11 g_ctxX11;
    200140
    201141/* Are we actually connected to the X server? */
    202142static bool g_fHaveX11;
    203 
    204 /** @todo this is a temporary declaration. */
    205 static void vboxClipboardFormatAnnounceBackend (uint32_t u32Formats);
    206 
    207 /**
    208  * Send a request to VBox to transfer the contents of its clipboard to X11.
    209  *
    210  * @param  pCtx      Pointer to the host clipboard structure
    211  * @param  u32Format The format in which the data should be transfered
    212  * @param  ppv       On success and if pcb > 0, this will point to a buffer
    213  *                   to be freed with RTMemFree containing the data read.
    214  * @param  pcb       On success, this contains the number of bytes of data
    215  *                   returned
    216  * @note   Host glue code.
    217  */
    218 static int vboxClipboardReadDataFromVBox (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void **ppv, uint32_t *pcb)
    219 {
    220     volatile VBOXCLIPBOARDCLIENTDATA *pClient = pCtx->pClient;
    221 
    222     LogFlowFunc(("u32Format=%02X\n", u32Format));
    223     if (pClient == NULL)
    224     {
    225         /* This can legitimately happen if we disconnect during a request for
    226          * data from X11. */
    227         LogFunc(("host requested guest clipboard data after guest had disconnected.\n"));
    228         vboxClipboardFormatAnnounceBackend(0);
    229         pCtx->waiter = NONE;
    230         return VERR_TIMEOUT;
    231     }
    232     /* Assert that no other transfer is in process (requests are serialised)
    233      * and that the last transfer cleaned up properly. */
    234     AssertLogRelReturn(   pClient->data.pv == NULL
    235                        && pClient->data.cb == 0
    236                        && pClient->data.u32Format == 0,
    237                        VERR_WRONG_ORDER
    238                       );
    239     /* No one else (X11 or VBox) should currently be waiting.  The first because
    240      * requests from X11 are serialised and the second because VBox previously
    241      * grabbed the clipboard, so it should not be waiting for data from us. */
    242     AssertLogRelReturn (ASMAtomicCmpXchgU32(&pCtx->waiter, X11, NONE), VERR_DEADLOCK);
    243     /* Request data from VBox */
    244     vboxSvcClipboardReportMsg(pCtx->pClient,
    245                               VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
    246                               u32Format);
    247     /* Which will signal us when it is ready.  We use a timeout here because
    248      * we can't be sure that the guest will behave correctly. */
    249     int rc = RTSemEventWait(pCtx->waitForData, CLIPBOARDTIMEOUT);
    250     if (rc == VERR_TIMEOUT)
    251         rc = VINF_SUCCESS;  /* Timeout handling follows. */
    252     /* Now we have a potential race between the HGCM thread delivering the data
    253      * and our setting waiter to NONE to say that we are no longer waiting for
    254      * it.  We solve this as follows: both of these operations are done under
    255      * the clipboard mutex.  The HGCM thread will only deliver the data if we
    256      * are still waiting after it acquires the mutex.  After we release the
    257      * mutex, we finally do our check to see whether the data was delivered. */
    258     RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
    259     pCtx->waiter = NONE;
    260     RTSemMutexRelease(g_ctxHost.clipboardMutex);
    261     AssertLogRelRCSuccess(rc);
    262     if (RT_FAILURE(rc))
    263     {
    264         /* I believe this should not happen.  Wait until the assertions arrive
    265          * to prove the contrary. */
    266         RTMemFree(pClient->data.pv);
    267         g_ctxHost.pClient->data.pv = 0;
    268         g_ctxHost.pClient->data.cb = 0;
    269         g_ctxHost.pClient->data.u32Format = 0;
    270         vboxClipboardFormatAnnounce(NULL, 0);
    271         return rc;
    272     }
    273     if (pClient->data.pv == NULL)
    274         return VERR_TIMEOUT;
    275     LogFlowFunc(("wait completed.  Returning.\n"));
    276     *ppv = pClient->data.pv;
    277     *pcb = pClient->data.cb;
    278     g_ctxHost.pClient->data.pv = 0;
    279     g_ctxHost.pClient->data.cb = 0;
    280     g_ctxHost.pClient->data.u32Format = 0;
    281     return VINF_SUCCESS;
    282 }
    283143
    284144/**
     
    588448
    589449/**
    590  * Report formats available in the X11 clipboard to VBox.
    591  * @param  pCtx        Opaque context pointer for the glue code
    592  * @param  u32Formats  The formats available
    593  * @note  Host glue code
    594  */
    595 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
    596                                       uint32_t u32Formats)
    597 {
    598     vboxSvcClipboardReportMsg(pCtx->pClient,
    599                               VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
    600                               u32Formats);
    601 }
    602 
    603 
    604 /**
    605450 * Notify the host clipboard about the data formats we support, based on the
    606451 * "targets" (available data formats) information obtained from the X11
     
    750595 * @note  X11 backend code.
    751596 */
    752 int vboxClipboardInitX11 (void)
     597static int vboxClipboardInitX11 (void)
    753598{
    754599    /* Create a window and make it a clipboard viewer. */
     
    829674 * @note  X11 backend code
    830675 */
    831 int vboxClipboardInitBackend (VBOXCLIPBOARDCONTEXT *pFrontend)
     676int VBoxX11ClipboardInitX11(VBOXCLIPBOARDCONTEXT *pFrontend,
     677                            VBOXCLIPBOARDCONTEXTX11 **ppBackend)
    832678{
    833679    int rc;
     
    885731
    886732/**
    887  * Initialise the host side of the shared clipboard.
    888  * @note  Host glue code
    889  */
    890 int vboxClipboardInit (void)
    891 {
    892     int rc = VINF_SUCCESS;
    893     LogRel(("Initializing host clipboard service\n"));
    894     RTSemEventCreate(&g_ctxHost.waitForData);
    895     RTSemMutexCreate(&g_ctxHost.clipboardMutex);
    896     rc = vboxClipboardInitBackend(&g_ctxHost);
    897     if (RT_FAILURE(rc))
    898     {
    899         RTSemEventDestroy(g_ctxHost.waitForData);
    900         RTSemMutexDestroy(g_ctxHost.clipboardMutex);
    901         LogRel(("Failed to start the host shared clipboard service.\n"));
    902     }
    903     return rc;
    904 }
    905 
    906 /**
    907733 * Terminate the shared clipboard X11 backend.
    908734 * @note  X11 backend code
    909735 */
    910 int vboxClipboardDestroyBackend (void)
     736int VBoxX11ClipboardTermX11(VBOXCLIPBOARDCONTEXTX11 *pBackend)
    911737{
    912738    int rc, rcThread;
     
    953779
    954780/**
    955  * Terminate the host side of the shared clipboard.
    956  * @note  host glue code
    957  */
    958 void vboxClipboardDestroy (void)
    959 {
    960     int rc = VINF_SUCCESS;
    961     LogRelFunc(("shutting down host clipboard\n"));
    962     /* Drop the reference to the client, in case it is still there.  This
    963      * will cause any outstanding clipboard data requests from X11 to fail
    964      * immediately. */
    965     g_ctxHost.pClient = NULL;
    966     /* The backend may be waiting for data from VBox.  At this point it is no
    967      * longer going to arrive, and we must release it to allow the event
    968      * loop to terminate.  In this case the buffer where VBox would have
    969      * written the clipboard data will still be empty and we will just
    970      * return "no data" to the backend.  Any subsequent attempts to get the
    971      * data from VBox will fail immediately as the client reference is gone.
    972      */
    973     /** @note  This has been made unconditional, as it should do no harm
    974      *         even if we are not waiting. */
    975     RTSemEventSignal(g_ctxHost.waitForData);
    976     rc = vboxClipboardDestroyBackend();
    977     if (RT_SUCCESS(rc))
    978     {
    979         /* We can safely destroy these as the backend has exited
    980          * successfully and no other calls from the host code should be
    981          * forthcoming. */
    982         /** @todo  can the backend fail to exit successfully?  What then? */
    983         RTSemEventDestroy(g_ctxHost.waitForData);
    984         RTSemMutexDestroy(g_ctxHost.clipboardMutex);
    985     }
    986 }
    987 
    988 /**
    989781 * Announce to the X11 backend that we are ready to start.
    990782 * @param  owner who is the initial clipboard owner
    991783 */
    992 int vboxClipboardConnectBackend (enum g_eOwner owner)
     784int VBoxX11ClipboardStartX11(VBOXCLIPBOARDCONTEXTX11 *pBackend,
     785                             enum g_eOwner owner)
    993786{
    994787    LogFlowFunc(("\n"));
     
    1006799        /** @todo Check whether the guest gets a format announcement at
    1007800          *       startup. */
    1008         vboxClipboardFormatAnnounceBackend(0);
     801        VBoxX11ClipboardAnnounceVBoxFormat(pBackend, 0);
    1009802    }
    1010803    return VINF_SUCCESS;
    1011 }
    1012 
    1013 /**
    1014  * Connect a guest to the shared clipboard.
    1015  * @note  host glue code
    1016  * @note  on the host, we assume that some other application already owns
    1017  *        the clipboard and leave ownership to X11.
    1018  */
    1019 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
    1020 {
    1021     int rc = VINF_SUCCESS;
    1022     LogFlowFunc(("\n"));
    1023     /* Only one client is supported for now */
    1024     AssertLogRelReturn(g_ctxHost.pClient == 0, VERR_NOT_SUPPORTED);
    1025     pClient->pCtx = &g_ctxHost;
    1026     pClient->pCtx->pClient = pClient;
    1027     /** The pClient pointer is a dummy anyway, as we only support a single
    1028      * client at a time. */
    1029     rc = vboxClipboardConnectBackend(X11 /* initial owner */);
    1030     return rc;
    1031804}
    1032805
     
    1035808 * @note  X11 backend code
    1036809 */
    1037 void vboxClipboardRequestSync (void)
     810void VBoxX11ClipboardRequestSyncX11(VBOXCLIPBOARDCONTEXTX11 *pBackend)
    1038811{
    1039812    /*
     
    1046819
    1047820/**
    1048  * Synchronise the contents of the host clipboard with the guest, called
    1049  * after a save and restore of the guest.
    1050  * @note  Host glue code
    1051  */
    1052 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
    1053 {
    1054 
    1055     /* On a Linux host, the guest should never synchronise/cache its
    1056      * clipboard contents, as we have no way of reliably telling when the
    1057      * host clipboard data changes.  So instead of synchronising, we tell
    1058      * the guest to empty its clipboard, and we set the cached flag so that
    1059      * we report formats to the guest next time we poll for them. */
    1060     /** @note  This has been changed so that the message is sent even if
    1061      *         X11 is not available. */
    1062     vboxSvcClipboardReportMsg (g_ctxHost.pClient,
    1063                                VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
    1064     vboxClipboardRequestSync();
    1065 
    1066     return VINF_SUCCESS;
    1067 }
    1068 
    1069 /**
    1070821 * Shut down the shared clipboard X11 backend.
    1071822 * @note  X11 backend code
    1072823 */
    1073 void vboxClipboardDisconnectBackend (void)
     824void VBoxX11ClipboardStopX11(VBOXCLIPBOARDCONTEXTX11 *pBackend)
    1074825{
    1075826    /*
     
    1082833    g_ctxX11.X11TextFormat = INVALID;
    1083834    g_ctxX11.X11BitmapFormat = INVALID;
    1084 }
    1085 
    1086 /**
    1087  * Shut down the shared clipboard service and "disconnect" the guest.
    1088  * @note  Host glue code
    1089  */
    1090 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *)
    1091 {
    1092     LogFlow(("vboxClipboardDisconnect\n"));
    1093 
    1094     RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
    1095     g_ctxHost.pClient = NULL;
    1096     vboxClipboardDisconnectBackend();
    1097     RTSemMutexRelease(g_ctxHost.clipboardMutex);
    1098835}
    1099836
     
    1193930
    1194931    LogFlowFunc (("called\n"));
    1195     rc = vboxClipboardReadDataFromVBox(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
     932    rc = VBoxX11ClipboardReadVBoxData(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
    1196933    if ((RT_FAILURE(rc)) || (cbVBox == 0))
    1197934    {
    1198         /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
    1199         LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
     935        /* If VBoxX11ClipboardReadVBoxData fails then pClient may be invalid */
     936        LogRelFunc (("VBoxX11ClipboardReadVBoxData returned %Rrc%s\n", rc,
    1200937                    RT_SUCCESS(rc) ? ", cbVBox == 0" :  ""));
    1201938        RTMemFree(pvVBox);
     
    12781015    LogFlowFunc (("called\n"));
    12791016    /* Read the clipboard data from the guest. */
    1280     rc = vboxClipboardReadDataFromVBox(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
     1017    rc = VBoxX11ClipboardReadVBoxData(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
    12811018    if ((rc != VINF_SUCCESS) || (cbVBox == 0))
    12821019    {
    1283         /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
    1284         LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
     1020        /* If VBoxX11ClipboardReadVBoxData fails then pClient may be invalid */
     1021        LogRelFunc (("VBoxX11ClipboardReadVBoxData returned %Rrc%s\n", rc,
    12851022                     RT_SUCCESS(rc) ? ", cbVBox == 0" :  ""));
    12861023        RTMemFree(pvVBox);
     
    13851122    LogFlowFunc (("called\n"));
    13861123    /* Read the clipboard data from the guest. */
    1387     rc = vboxClipboardReadDataFromVBox(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
     1124    rc = VBoxX11ClipboardReadVBoxData(g_ctxX11.pFrontend, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);
    13881125    if ((rc != VINF_SUCCESS) || (cbVBox == 0))
    13891126    {
    1390         /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */
    1391         LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc,
     1127        /* If VBoxX11ClipboardReadVBoxData fails then pClient may be invalid */
     1128        LogRelFunc (("VBoxX11ClipboardReadVBoxData returned %Rrc%s\n", rc,
    13921129                      RT_SUCCESS(rc) ? ", cbVBox == 0" :  ""));
    13931130        RTMemFree(pvVBox);
     
    15661303 * @note  X11 backend code
    15671304 */
    1568 void vboxClipboardFormatAnnounceBackend (uint32_t u32Formats)
     1305void VBoxX11ClipboardAnnounceVBoxFormat(VBOXCLIPBOARDCONTEXTX11 *pBackend,
     1306                                        uint32_t u32Formats)
    15691307{
    15701308    /*
     
    16101348
    16111349/**
    1612  * VBox is taking possession of the shared clipboard.
    1613  *
    1614  * @param pClient    Context data for the guest system
    1615  * @param u32Formats Clipboard formats the guest is offering
    1616  * @note  Host glue code
    1617  */
    1618 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats)
    1619 {
    1620     vboxClipboardFormatAnnounceBackend (u32Formats);
    1621 }
    1622 
    1623 /**
    16241350 * Called when VBox wants to read the X11 clipboard.
    16251351 *
     
    16311357 * @note   X11 backend code
    16321358 */
    1633 int vboxClipboardReadDataBackend (uint32_t u32Format,
    1634                                   VBOXCLIPBOARDREQUEST *pRequest)
     1359int VBoxX11ClipboardReadX11Data(VBOXCLIPBOARDCONTEXTX11 *pBackend,
     1360                                uint32_t u32Format,
     1361                                VBOXCLIPBOARDREQUEST *pRequest)
    16351362{
    16361363    /*
     
    16801407}
    16811408
    1682 /**
    1683  * Called when VBox wants to read the X11 clipboard.
    1684  *
    1685  * @param  pClient   Context information about the guest VM
    1686  * @param  u32Format The format that the guest would like to receive the data in
    1687  * @param  pv        Where to write the data to
    1688  * @param  cb        The size of the buffer to write the data to
    1689  * @param  pcbActual Where to write the actual size of the written data
    1690  * @note   Host glue code
    1691  */
    1692 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient,
    1693                            uint32_t u32Format, void *pv, uint32_t cb,
    1694                            uint32_t *pcbActual)
    1695 {
    1696     int rc = VINF_SUCCESS;
    1697     VBOXCLIPBOARDREQUEST request;
    1698     /* No one else (VBox or X11) should currently be waiting.  The first
    1699      * because requests from VBox are serialised and the second because X11
    1700      * previously grabbed the clipboard, so it should not be waiting for
    1701      * data from us. */
    1702     AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctxHost.waiter, VB, NONE),
    1703                         VERR_DEADLOCK);
    1704     request.pv = pv;
    1705     request.cb = cb;
    1706     request.pcbActual = pcbActual;
    1707     rc = vboxClipboardReadDataBackend(u32Format, &request);
    1708     g_ctxHost.waiter = NONE;
    1709     return rc;
    1710 }
    1711 
    1712 /**
    1713  * Called when we have requested data from VBox and that data has arrived.
    1714  *
    1715  * @param  pClient   Context information about the guest VM
    1716  * @param  pv        Buffer to which the data was written
    1717  * @param  cb        The size of the data written
    1718  * @param  u32Format The format of the data written
    1719  * @note   Host glue code
    1720  */
    1721 void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format)
    1722 {
    1723     if (!g_fHaveX11)
    1724         return;
    1725 
    1726     LogFlowFunc (("called\n"));
    1727 
    1728     /* Assert that no other transfer is in process (requests are serialised)
    1729      * or has not cleaned up properly. */
    1730     AssertLogRelReturnVoid (   pClient->data.pv == NULL
    1731                             && pClient->data.cb == 0
    1732                             && pClient->data.u32Format == 0);
    1733 
    1734     /* Grab the mutex and check that X11 is still waiting for the data before
    1735      * delivering it.  See the explanation in vboxClipboardReadDataFromVBox. */
    1736     RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT);
    1737     if (g_ctxHost.waiter == X11 && cb > 0)
    1738     {
    1739         pClient->data.pv = RTMemAlloc (cb);
    1740 
    1741         if (pClient->data.pv)
    1742         {
    1743             memcpy (pClient->data.pv, pv, cb);
    1744             pClient->data.cb = cb;
    1745             pClient->data.u32Format = u32Format;
    1746         }
    1747     }
    1748     RTSemMutexRelease(g_ctxHost.clipboardMutex);
    1749 
    1750     RTSemEventSignal(g_ctxHost.waitForData);
    1751 }
    1752 
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette