VirtualBox

Changeset 19842 in vbox


Ignore:
Timestamp:
May 19, 2009 9:40:24 PM (15 years ago)
Author:
vboxsync
Message:

SharedClipboard/GuestHost and HostServices/x11: use asynchronous host clipboard reads, plus numerous small cleanups and some more tests

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/SharedClipboard.h

    r19552 r19842  
    3737enum {
    3838    /** The number of milliseconds before the clipboard times out. */
     39#ifndef TESTCASE
    3940    CLIPBOARD_TIMEOUT = 5000
     41#else
     42    CLIPBOARD_TIMEOUT = 1
     43#endif
    4044};
    4145
     
    4852typedef struct _CLIPBACKEND CLIPBACKEND;
    4953
     54/** Opaque data structure used for asynchronously completing requests by VBox
     55 * to read the X11 clipboard data. */
     56struct _CLIPREADX11CBCONTEXT;
     57typedef struct _CLIPREADX11CBCONTEXT CLIPREADX11CBCONTEXT;
     58
    5059/* APIs exported by the X11 backend */
    51 extern CLIPBACKEND *VBoxX11ClipboardConstructX11
    52                                         (VBOXCLIPBOARDCONTEXT *pFrontend);
    53 extern void VBoxX11ClipboardDestructX11(CLIPBACKEND *pBackend);
    54 extern int VBoxX11ClipboardStartX11(CLIPBACKEND *pBackend);
    55 extern int VBoxX11ClipboardStopX11(CLIPBACKEND *pBackend);
    56 extern void VBoxX11ClipboardAnnounceVBoxFormat(CLIPBACKEND
    57                                                *pBackend, uint32_t u32Formats);
    58 extern int VBoxX11ClipboardReadX11Data(CLIPBACKEND *pBackend,
    59                                        uint32_t u32Format,
    60                                        void *pv, uint32_t cb,
    61                                        uint32_t *pcbActual);
     60extern CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend);
     61extern void ClipDestructX11(CLIPBACKEND *pBackend);
     62extern int ClipStartX11(CLIPBACKEND *pBackend);
     63extern int ClipStopX11(CLIPBACKEND *pBackend);
     64extern void ClipAnnounceFormatToX11(CLIPBACKEND *pBackend,
     65                                    uint32_t u32Formats);
     66extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, uint32_t u32Format,
     67                                  void *pv, uint32_t cb,
     68                                  CLIPREADX11CBCONTEXT *pCtx);
    6269
    6370/* APIs exported by the X11/VBox frontend */
    64 extern int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,
     71extern int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx,
    6572                                        uint32_t u32Format, void **ppv,
    6673                                        uint32_t *pcb);
    67 extern void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
     74extern void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
    6875                                             uint32_t u32Formats);
     76extern void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc,
     77                                           uint32_t cbActual);
    6978#endif  /* ___GUESTHOST_VBOXCLIPBOARD__H */
  • trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp

    r19754 r19842  
    297297{
    298298    uint32_t u32VBoxFormats = clipVBoxFormatForX11Format(pCtx->X11TextFormat);
    299     VBoxX11ClipboardReportX11Formats(pCtx->pFrontend, u32VBoxFormats);
     299    ClipReportX11Formats(pCtx->pFrontend, u32VBoxFormats);
    300300}
    301301
     
    381381        /* VBox raced us and we lost.  So we don't want to report anything. */
    382382        changed = false;
    383     else if (*atomType == XT_CONVERT_FAIL)  /* timeout */
     383    else if (   (*atomType == XT_CONVERT_FAIL)  /* timeout */
     384             || !pTargets  /* Conversion failed */)
    384385        clipResetX11Formats(pCtx);
    385386    else
     
    558559 * @note  X11 backend code
    559560 */
    560 CLIPBACKEND *VBoxX11ClipboardConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend)
     561CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend)
    561562{
    562563    int rc;
     
    589590 * @note  X11 backend code
    590591 */
    591 void VBoxX11ClipboardDestructX11(CLIPBACKEND *pCtx)
     592void ClipDestructX11(CLIPBACKEND *pCtx)
    592593{
    593594    /*
     
    606607 * Announce to the X11 backend that we are ready to start.
    607608 */
    608 int VBoxX11ClipboardStartX11(CLIPBACKEND *pCtx)
     609int ClipStartX11(CLIPBACKEND *pCtx)
    609610{
    610611    int rc = VINF_SUCCESS;
     
    647648 *        to return and will not be able to terminate.
    648649 */
    649 int VBoxX11ClipboardStopX11(CLIPBACKEND *pCtx)
     650int ClipStopX11(CLIPBACKEND *pCtx)
    650651{
    651652    int rc, rcThread;
     
    719720}
    720721
    721 /** This is a wrapper around VBoxX11ClipboardReadVBoxData that will cache the
    722  * data returned.  This is unfortunately necessary, because if the other side
    723  * of the shared clipboard is also an X11 system, it may send a format
    724  * announcement message every time its clipboard is read, for reasons that
    725  * are explained elsewhere.  Unfortunately, some applications on our side
    726  * like to read the clipboard several times in short succession in different
    727  * formats.  This can fail if it collides with a format announcement message.
    728  * @todo any ideas about how to do this better are welcome.
     722/** This is a wrapper around ClipRequestDataForX11 that will cache the
     723 * data returned.
    729724 */
    730725static int clipReadVBoxClipboard(CLIPBACKEND *pCtx, uint32_t u32Format,
     
    737732    {
    738733        if (pCtx->pvUnicodeCache == NULL)
    739             rc = VBoxX11ClipboardReadVBoxData(pCtx->pFrontend, u32Format,
     734            rc = ClipRequestDataForX11(pCtx->pFrontend, u32Format,
    740735                                              &pCtx->pvUnicodeCache,
    741736                                              &pCtx->cbUnicodeCache);
     
    749744    }
    750745    else
    751         rc = VBoxX11ClipboardReadVBoxData(pCtx->pFrontend, u32Format,
     746        rc = ClipRequestDataForX11(pCtx->pFrontend, u32Format,
    752747                                          ppv, pcb);
    753748    LogFlowFunc(("returning %Rrc\n", rc));
     
    964959                                                      *atomTarget);
    965960    CLIPFORMAT format = clipRealFormatForX11Format(x11Format);
    966     if ((format == UTF8) || (format == CTEXT))
     961    if (   ((format == UTF8) || (format == CTEXT))
     962        && (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT))
    967963    {
    968964        void *pv = NULL;
     
    10841080
    10851081/**
    1086  * Worker function for VBoxX11ClipboardAnnounceVBoxFormat which runs on the
     1082 * Worker function for ClipAnnounceFormatToX11 which runs on the
    10871083 * event thread.
    10881084 * @param pUserData  Pointer to a CLIPNEWVBOXFORMATS structure containing
     
    11131109 * @note  X11 backend code
    11141110 */
    1115 void VBoxX11ClipboardAnnounceVBoxFormat(CLIPBACKEND *pCtx,
     1111void ClipAnnounceFormatToX11(CLIPBACKEND *pCtx,
    11161112                                        uint32_t u32Formats)
    11171113{
     
    13571353     * a request for the clipboard contents) */
    13581354    unsigned mSize;
    1359     /** The size of the X11 clipboard data written to the buffer (valid
    1360      * during a request for the clipboard contents) */
    1361     uint32_t *mActual;
     1355    /** The opaque context structure for completing the request */
     1356    CLIPREADX11CBCONTEXT *mReadCtx;
    13621357    /** The format VBox would like the data in */
    13631358    uint32_t mFormat;
    13641359    /** The text format we requested from X11 if we requested text */
    13651360    CLIPX11FORMAT mTextFormat;
    1366     /** Return code for the request processing code */
    1367     int mRC;
    1368     /** Semaphore which is signalled when the request is completed */
    1369     RTSEMEVENT mSem;
    13701361    /** The clipboard context this request is associated with */
    13711362    CLIPBACKEND *mCtx;
     
    13951386    CLIPBACKEND *pCtx = pReq->mCtx;
    13961387    unsigned cbSrc = (*pcLen) * (*piFormat) / 8;
     1388    uint32_t cbActual = 0;
    13971389
    13981390    if (pvSrc == NULL)
     
    14091401                rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc,
    14101402                                       pReq->mBuffer, pReq->mSize,
    1411                                        pReq->mActual);
     1403                                       &cbActual);
    14121404                break;
    14131405            case UTF8:
     
    14191411                    rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc,
    14201412                                          pReq->mBuffer, pReq->mSize,
    1421                                           pReq->mActual);
     1413                                          &cbActual);
    14221414                else
    14231415                    rc = clipLatin1ToWinTxt((char *) pvSrc, cbSrc,
    14241416                                            pReq->mBuffer, pReq->mSize,
    1425                                             pReq->mActual);
     1417                                            &cbActual);
    14261418                break;
    14271419            }
     
    14331425        rc = VERR_NOT_IMPLEMENTED;
    14341426    XtFree((char *)pvSrc);
    1435     pReq->mRC = rc;
    1436     RTSemEventSignal(pReq->mSem);
    1437     /* Don't try to call VBox until after we have released the inbound call
    1438      * from VBox! */
    1439     /** @todo make this safer */
     1427    ClipCompleteDataRequestFromX11(pReq->mReadCtx, rc, cbActual);
     1428    RTMemFree(pReq);
    14401429    if (RT_SUCCESS(rc))
    14411430        /* The other end may want to cache the data, so pretend we have new
     
    14481437}
    14491438
    1450 /** Worker function for VBoxX11ClipboardReadX11Data which runs on the event
     1439/** Worker function for ClipRequestDataFromX11 which runs on the event
    14511440 * thread. */
    14521441static void vboxClipboardReadX11Worker(XtPointer pUserData,
     
    14591448
    14601449    int rc = VINF_SUCCESS;
    1461     /* Set this to start with, just in case */
    1462     *pReq->mActual = 0;
    14631450    /* Do not continue if we already own the clipboard */
    14641451    if (pCtx->fOwnsClipboard == true)
    1465         rc = VERR_NO_DATA;  /** @todo should this be VINF? */
     1452        rc = VERR_TIMEOUT;
    14661453    else
    14671454    {
     
    14901477    if (RT_FAILURE(rc))
    14911478    {
    1492         pReq->mRC = rc;
    14931479        /* The clipboard callback was never scheduled, so we must signal
    1494          * that the request processing is finished ourselves. */
    1495         RTSemEventSignal(pReq->mSem);
     1480         * that the request processing is finished and clean up ourselves. */
     1481        ClipCompleteDataRequestFromX11(pReq->mReadCtx, rc, 0);
     1482        RTMemFree(pReq);
    14961483    }
    14971484    LogFlowFunc(("status %Rrc\n", rc));
     
    15011488 * Called when VBox wants to read the X11 clipboard.
    15021489 *
     1490 * @returns iprt status code
    15031491 * @param  pCtx      Context data for the clipboard backend
    15041492 * @param  u32Format The format that the VBox would like to receive the data
     
    15071495 * @param  cb        The size of the buffer to write the data to
    15081496 * @param  pcbActual Where to write the actual size of the written data
    1509  * @note   X11 backend code
    1510  */
    1511 int VBoxX11ClipboardReadX11Data(CLIPBACKEND *pCtx,
    1512                                 uint32_t u32Format, void *pv, uint32_t cb,
    1513                                 uint32_t *pcbActual)
    1514 {
    1515     /* Initially set the size of the data read to zero in case we fail
    1516      * somewhere or X11 is not available. */
    1517     *pcbActual = 0;
    1518 
     1497 * @note   We allocate a request structure which must be freed by the worker
     1498 */
     1499int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format, void *pv,
     1500                           uint32_t cb, CLIPREADX11CBCONTEXT *pReadCtx)
     1501{
    15191502    /*
    15201503     * Immediately return if we are not connected to the X server.
    15211504     */
    15221505    if (!pCtx->fHaveX11)
    1523         return VINF_SUCCESS;
    1524 
    1525     CLIPREADX11CBREQ req = { 0 };
    1526     req.mRC = VERR_WRONG_ORDER;
    1527     req.mBuffer = pv;
    1528     req.mSize = cb;
    1529     req.mActual = pcbActual;
    1530     req.mFormat = u32Format;
    1531     req.mCtx = pCtx;
    1532     /* The worker function will signal this when it has finished. */
    1533     int rc = RTSemEventCreate(&req.mSem);
    1534     if (RT_SUCCESS(rc))
    1535     {
     1506        return VERR_NO_DATA;
     1507    int rc = VINF_SUCCESS;
     1508    CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *)RTMemAllocZ(sizeof(*pReq));
     1509    if (!pReq)
     1510        rc = VERR_NO_MEMORY;
     1511    else
     1512    {
     1513        pReq->mBuffer = pv;
     1514        pReq->mSize = cb;
     1515        pReq->mReadCtx = pReadCtx;
     1516        pReq->mFormat = u32Format;
     1517        pReq->mCtx = pCtx;
    15361518        /* We use this to schedule a worker function on the event thread. */
    15371519        clipQueueToEventThread(pCtx->appContext, vboxClipboardReadX11Worker,
    1538                                (XtPointer) &req);
    1539         rc = RTSemEventWait(req.mSem, RT_INDEFINITE_WAIT);
    1540         if (RT_SUCCESS(rc))
    1541             rc = req.mRC;
    1542         RTSemEventDestroy(req.mSem);
     1520                               (XtPointer) pReq);
    15431521    }
    15441522    return rc;
     
    16001578    g_vboxDatapv = NULL;
    16011579    g_vboxDatacb = 0;
    1602     VBoxX11ClipboardAnnounceVBoxFormat(pCtx, 0);
     1580    ClipAnnounceFormatToX11(pCtx, 0);
    16031581}
    16041582
     
    16221600    g_vboxDatapv = pv;
    16231601    g_vboxDatacb = cb;
    1624     VBoxX11ClipboardAnnounceVBoxFormat(pCtx,
     1602    ClipAnnounceFormatToX11(pCtx,
    16251603                                       VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
    16261604    return VINF_SUCCESS;
     
    16281606
    16291607/* Return the data in the simulated VBox clipboard. */
    1630 int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,
     1608int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx,
    16311609                                 uint32_t u32Format, void **ppv,
    16321610                                 uint32_t *pcb)
     
    17921770static unsigned long g_cSelData = 0;
    17931771static int g_selFormat = 0;
     1772static bool g_fTargetsTimeout = false;
     1773static bool g_fTargetsFailure = false;
    17941774
    17951775void XtGetSelectionValue(Widget widget, Atom selection, Atom target,
     
    18151795    if (target == clipGetAtom(NULL, "TARGETS"))
    18161796    {
    1817         pValue = (XtPointer) RTMemDup(&g_selTarget, sizeof(g_selTarget));
    1818         type = XA_ATOM;
    1819         count = 1;
     1797        if (g_fTargetsFailure)
     1798            pValue = NULL;
     1799        else
     1800            pValue = (XtPointer) RTMemDup(&g_selTarget, sizeof(g_selTarget));
     1801        type = g_fTargetsTimeout ? XT_CONVERT_FAIL : XA_ATOM;
     1802        count = g_fTargetsFailure ? 0 : 1;
    18201803        format = 32;
    18211804    }
     
    18401823static uint32_t g_fX11Formats = 0;
    18411824
    1842 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT* pCtx,
     1825void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT* pCtx,
    18431826                                      uint32_t u32Formats)
    18441827{
     
    19231906        g_pfnSelLose(TEST_WIDGET, &clipAtom);
    19241907    g_ownsSel = false;
     1908    g_fTargetsTimeout = false;
     1909    g_fTargetsFailure = false;
     1910}
     1911
     1912/* Configure if and how the X11 TARGETS clipboard target will fail */
     1913static void clipSetTargetsFailure(bool fTimeout, bool fFailure)
     1914{
     1915    g_fTargetsTimeout = fTimeout;
     1916    g_fTargetsFailure = fFailure;
    19251917}
    19261918
     
    19591951        RTMemFree(*list);
    19601952    RTMemFree(list);
     1953}
     1954
     1955struct _CLIPREADX11CBCONTEXT
     1956{
     1957    int rc;
     1958    uint32_t cbActual;
     1959};
     1960
     1961void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc,
     1962                                    uint32_t cbActual)
     1963{
     1964    pCtx->rc = rc;
     1965    pCtx->cbActual = cbActual;
    19611966}
    19621967
     
    19791984    {
    19801985        char pc[MAX_BUF_SIZE];
    1981         uint32_t cbActual;
    1982         int rc = VBoxX11ClipboardReadX11Data(pCtx,
    1983                                      VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    1984                                      (void *) pc, cbBuf, &cbActual);
     1986        CLIPREADX11CBCONTEXT readCtx;
     1987        uint32_t cbActual = 0;
     1988        ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     1989                               (void *) pc, cbBuf, &readCtx);
     1990        int rc = readCtx.rc;
     1991        cbActual = readCtx.cbActual;
    19851992        if (rc != rcExp)
    19861993            RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp,
     
    20352042    {
    20362043        char pc[MAX_BUF_SIZE];
    2037         uint32_t cbActual;
    2038         int rc = VBoxX11ClipboardReadX11Data(pCtx,
    2039                                      VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    2040                                      (void *) pc, cbBuf, &cbActual);
     2044        CLIPREADX11CBCONTEXT readCtx;
     2045        uint32_t cbActual = 0;
     2046        ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     2047                               (void *) pc, cbBuf, &readCtx);
     2048        int rc = readCtx.rc;
     2049        cbActual = readCtx.cbActual;
    20412050        if (rc != rcExp)
    20422051            RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp,
     
    21332142{
    21342143    RTR3Init();
    2135     CLIPBACKEND *pCtx = VBoxX11ClipboardConstructX11(NULL);
     2144    CLIPBACKEND *pCtx = ClipConstructX11(NULL);
    21362145    unsigned cErrs = 0;
    21372146    char pc[MAX_BUF_SIZE];
    21382147    uint32_t cbActual;
    2139     int rc = VBoxX11ClipboardStartX11(pCtx);
     2148    int rc = ClipStartX11(pCtx);
    21402149    AssertRCReturn(rc, 1);
    21412150
     
    22632272    clipSetSelectionValues("UTF8_STRING", XA_STRING, NULL,
    22642273                           0, 8);
    2265     rc = VBoxX11ClipboardReadX11Data(pCtx,
    2266                                      VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    2267                                      (void *) pc, sizeof(pc), &cbActual);
     2274    CLIPREADX11CBCONTEXT readCtx;
     2275    ClipRequestDataFromX11(pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     2276                           (void *) pc, sizeof(pc), &readCtx);
     2277    rc = readCtx.rc;
     2278    cbActual = readCtx.cbActual;
    22682279    if (rc != VERR_NO_DATA)
    22692280    {
     
    22742285    /*** request for an invalid VBox format from X11 ***/
    22752286    RTPrintf(TEST_NAME ": TESTING a request for an invalid VBox format from X11\n");
    2276     rc = VBoxX11ClipboardReadX11Data(pCtx, 0xffff, (void *) pc,
    2277                                      sizeof(pc), &cbActual);
     2287    ClipRequestDataFromX11(pCtx, 0xffff, (void *) pc, sizeof(pc), &readCtx);
     2288    rc = readCtx.rc;
     2289    cbActual = readCtx.cbActual;
    22782290    if (rc != VERR_NOT_IMPLEMENTED)
    22792291    {
    22802292        RTPrintf("Returned %Rrc instead of VERR_NOT_IMPLEMENTED\n", rc);
     2293        ++cErrs;
     2294    }
     2295
     2296    /*** Targets timeout from X11 ***/
     2297    RTPrintf(TEST_NAME ": TESTING X11 targets timeout\n");
     2298    clipSetSelectionValues("UTF8_STRING", XA_STRING, "hello world",
     2299                           sizeof("hello world"), 8);
     2300    clipSetTargetsFailure(true, false);
     2301    if (!clipPollTargets())
     2302    {
     2303        RTPrintf("Failed to poll for targets\n");
     2304        ++cErrs;
     2305    }
     2306    else if (clipQueryFormats() != 0)
     2307    {
     2308        RTPrintf("Wrong targets reported: %02X\n", clipQueryFormats());
     2309        ++cErrs;
     2310    }
     2311
     2312    /*** Targets failure from X11 ***/
     2313    RTPrintf(TEST_NAME ": TESTING X11 targets conversion failure\n");
     2314    clipSetSelectionValues("UTF8_STRING", XA_STRING, "hello world",
     2315                           sizeof("hello world"), 8);
     2316    clipSetTargetsFailure(false, true);
     2317    if (!clipPollTargets())
     2318    {
     2319        RTPrintf("Failed to poll for targets\n");
     2320        ++cErrs;
     2321    }
     2322    else if (clipQueryFormats() != 0)
     2323    {
     2324        RTPrintf("Wrong targets reported: %02X\n", clipQueryFormats());
    22812325        ++cErrs;
    22822326    }
     
    23602404    if (!testStringFromVBoxFailed(pCtx, "UTF8_STRING"))
    23612405        ++cErrs;
     2406
     2407    /*** An unknown VBox format ***/
     2408    RTPrintf(TEST_NAME ": TESTING reading an unknown VBox format\n");
     2409    clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "", 2);
     2410    ClipAnnounceFormatToX11(pCtx, 0xa0000);
     2411    if (!testStringFromVBoxFailed(pCtx, "UTF8_STRING"))
     2412        ++cErrs;
     2413
    23622414    if (cErrs > 0)
    23632415        RTPrintf("Failed with %u error(s)\n", cErrs);
     
    23792431#define TEST_NAME "tstClipboardX11Smoke"
    23802432
    2381 int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,
     2433int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx,
    23822434                                 uint32_t u32Format, void **ppv,
    23832435                                 uint32_t *pcb)
     
    23862438}
    23872439
    2388 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
     2440void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
    23892441                                      uint32_t u32Formats)
     2442{}
     2443
     2444void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc,
     2445                                    uint32_t cbActual)
    23902446{}
    23912447
     
    24022458    }
    24032459    RTPrintf(TEST_NAME ": TESTING\n");
    2404     CLIPBACKEND *pCtx = VBoxX11ClipboardConstructX11(NULL);
     2460    CLIPBACKEND *pCtx = ClipConstructX11(NULL);
    24052461    AssertReturn(pCtx, 1);
    2406     rc = VBoxX11ClipboardStartX11(pCtx);
     2462    rc = ClipStartX11(pCtx);
    24072463    AssertRCReturn(rc, 1);
    24082464    /* Give the clipboard time to synchronise. */
    24092465    RTThreadSleep(500);
    2410     rc = VBoxX11ClipboardStopX11(pCtx);
     2466    rc = ClipStopX11(pCtx);
    24112467    AssertRCReturn(rc, 1);
    2412     VBoxX11ClipboardDestructX11(pCtx);
     2468    ClipDestructX11(pCtx);
    24132469    return 0;
    24142470}
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r19282 r19842  
    6969        -framework ApplicationServices -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxSharedClipboard.dylib
    7070
     71ifdef VBOX_WITH_TESTCASES
     72 ifndef VBOX_ONLY_ADDITIONS
     73#
     74# Case conversion testcase.
     75#
     76  if1of ($(KBUILD_TARGET),freebsd linux netbsd openbsd solaris)
     77   PROGRAMS += tstClipboardX11-2
     78   tstClipboardX11-2_TEMPLATE = VBOXR3TSTEXE
     79   tstClipboardX11-2_DEFS     = VBOX_WITH_HGCM TESTCASE
     80   tstClipboardX11-2_SOURCES  = x11-clipboard.cpp
     81   tstClipboardX11-2_LIBS     = $(LIB_RUNTIME)
     82
     83# Set this in LocalConfig.kmk if you are working on the X11 clipboard service
     84# to automatically run the testcase at build time.
     85   ifdef VBOX_RUN_X11_CLIPBOARD_TEST
     86    ifndef VBOX_ONLY_SDK
     87     TESTING  += $(PATH_tstClipboardX11-2)/tstClipboardX11-2.run
     88     OTHERS += $(PATH_tstClipboardX11-2)/tstClipboardX11-2.run
     89$$(PATH_tstClipboardX11-2)/tstClipboardX11-2.run: \
     90        $$(INSTARGET_tstClipboardX11-2)
     91        export VBOX_LOG_DEST=nofile; $(INSTARGET_tstClipboardX11-2) quiet
     92        $(QUIET)$(APPEND) -t "$@" "done"
     93    endif
     94   endif
     95
     96  endif # 1of ($(KBUILD_TARGET),freebsd linux netbsd openbsd solaris)
     97 endif # ! VBOX_ONLY_ADDITIONS
     98endif # VBOX_WITH_TESTCASES
     99
    71100include $(KBUILD_PATH)/subfooter.kmk
    72 
  • trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp

    r19536 r19842  
    3535#include "VBoxClipboard.h"
    3636
    37 /** A request for clipboard data from VBox */
    38 typedef struct _VBOXCLIPBOARDREQFROMVBOX
    39 {
    40     /** Data received */
    41     void *pv;
    42     /** The size of the data */
    43     uint32_t cb;
    44     /** Format of the data */
    45     uint32_t format;
    46     /** A semaphore for waiting for the data */
    47     RTSEMEVENT finished;
    48 } VBOXCLIPBOARDREQFROMVBOX;
     37struct _VBOXCLIPBOARDREQFROMVBOX;
     38typedef struct _VBOXCLIPBOARDREQFROMVBOX VBOXCLIPBOARDREQFROMVBOX;
    4939
    5040/** Global context information used by the host glue for the X11 clipboard
     
    7363};
    7464
    75 static int vboxClipboardWaitForReq(VBOXCLIPBOARDCONTEXT *pCtx,
     65/**
     66 * Report formats available in the X11 clipboard to VBox.
     67 * @param  pCtx        Opaque context pointer for the glue code
     68 * @param  u32Formats  The formats available
     69 * @note  Host glue code
     70 */
     71void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
     72                                      uint32_t u32Formats)
     73{
     74    LogFlowFunc(("called.  pCtx=%p, u32Formats=%02X\n", pCtx, u32Formats));
     75    vboxSvcClipboardReportMsg(pCtx->pClient,
     76                              VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
     77                              u32Formats);
     78}
     79
     80/**
     81 * Initialise the host side of the shared clipboard.
     82 * @note  Host glue code
     83 */
     84int vboxClipboardInit (void)
     85{
     86    return VINF_SUCCESS;
     87}
     88
     89/**
     90 * Terminate the host side of the shared clipboard.
     91 * @note  host glue code
     92 */
     93void vboxClipboardDestroy (void)
     94{
     95
     96}
     97
     98/**
     99 * Connect a guest to the shared clipboard.
     100 * @note  host glue code
     101 * @note  on the host, we assume that some other application already owns
     102 *        the clipboard and leave ownership to X11.
     103 */
     104int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
     105{
     106    int rc = VINF_SUCCESS;
     107    CLIPBACKEND *pBackend = NULL;
     108
     109    LogRel(("Starting host clipboard service\n"));
     110    VBOXCLIPBOARDCONTEXT *pCtx =
     111        (VBOXCLIPBOARDCONTEXT *) RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT));
     112    if (!pCtx)
     113        rc = VERR_NO_MEMORY;
     114    else
     115    {
     116        RTCritSectInit(&pCtx->clipboardMutex);
     117        pBackend = ClipConstructX11(pCtx);
     118        if (pBackend == NULL)
     119            rc = VERR_NO_MEMORY;
     120        else
     121        {
     122            pCtx->pBackend = pBackend;
     123            pClient->pCtx = pCtx;
     124            pCtx->pClient = pClient;
     125            rc = ClipStartX11(pBackend);
     126        }
     127        if (RT_FAILURE(rc) && pBackend)
     128            ClipStopX11(pCtx->pBackend);
     129        if (RT_FAILURE(rc))
     130            RTCritSectDelete(&pCtx->clipboardMutex);
     131    }
     132    if (RT_FAILURE(rc))
     133    {
     134        RTMemFree(pCtx);
     135        LogRel(("Failed to initialise the shared clipboard\n"));
     136    }
     137    LogFlowFunc(("returning %Rrc\n", rc));
     138    return rc;
     139}
     140
     141/**
     142 * Synchronise the contents of the host clipboard with the guest, called
     143 * after a save and restore of the guest.
     144 * @note  Host glue code
     145 */
     146int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
     147{
     148    /* Tell the guest we have no data in case X11 is not available.  If
     149     * there is data in the host clipboard it will automatically be sent to
     150     * the guest when the clipboard starts up. */
     151    vboxSvcClipboardReportMsg (pClient,
     152                               VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
     153    return VINF_SUCCESS;
     154}
     155
     156/**
     157 * Shut down the shared clipboard service and "disconnect" the guest.
     158 * @note  Host glue code
     159 */
     160void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
     161{
     162    LogFlow(("vboxClipboardDisconnect\n"));
     163
     164    LogRel(("Stopping the host clipboard service\n"));
     165    VBOXCLIPBOARDCONTEXT *pCtx = pClient->pCtx;
     166    /* Drop the reference to the client, in case it is still there.  This
     167     * will cause any outstanding clipboard data requests from X11 to fail
     168     * immediately. */
     169    pCtx->fShuttingDown = true;
     170    /* If there is a currently pending request, release it immediately. */
     171    vboxClipboardWriteData(pClient, NULL, 0, 0);
     172    int rc = ClipStopX11(pCtx->pBackend);
     173    /** @todo handle this slightly more reasonably, or be really sure
     174     *        it won't go wrong. */
     175    AssertRC(rc);
     176    if (RT_SUCCESS(rc))  /* And if not? */
     177    {
     178        ClipDestructX11(pCtx->pBackend);
     179        RTCritSectDelete(&pCtx->clipboardMutex);
     180        RTMemFree(pCtx);
     181    }
     182}
     183
     184/**
     185 * VBox is taking possession of the shared clipboard.
     186 *
     187 * @param pClient    Context data for the guest system
     188 * @param u32Formats Clipboard formats the guest is offering
     189 * @note  Host glue code
     190 */
     191void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient,
     192                                  uint32_t u32Formats)
     193{
     194    LogFlowFunc(("called.  pClient=%p, u32Formats=%02X\n", pClient,
     195                 u32Formats));
     196    ClipAnnounceFormatToX11 (pClient->pCtx->pBackend, u32Formats);
     197}
     198
     199struct _CLIPREADX11CBCONTEXT
     200{
     201    /** HGCM call data */
     202    VBOXHGCMCALLHANDLE callHandle;
     203    /** HGCM call parameters */
     204    VBOXHGCMSVCPARM *paParms;
     205};
     206
     207/**
     208 * Called when VBox wants to read the X11 clipboard.
     209 *
     210 * @returns VINF_SUCCESS on successful completion
     211 * @returns VINF_HGCM_ASYNC_EXECUTE if the operation will complete
     212 *          asynchronously
     213 * @returns iprt status code on failure
     214 * @param  pClient   Context information about the guest VM
     215 * @param  u32Format The format that the guest would like to receive the data in
     216 * @param  pv        Where to write the data to
     217 * @param  cb        The size of the buffer to write the data to
     218 * @param  pcbActual Where to write the actual size of the written data
     219 * @note   We always fail or complete asynchronously
     220 * @note   On success allocates a CLIPREADX11CBCONTEXT structure which must be
     221 *         freed in ClipCompleteDataRequestFromX11 when it is called back from
     222 *         the backend code.
     223 *         
     224 */
     225int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient,
     226                           uint32_t u32Format, void *pv, uint32_t cb,
     227                           uint32_t *pcbActual)
     228{
     229    LogFlowFunc(("pClient=%p, u32Format=%02X, pv=%p, cb=%u, pcbActual=%p",
     230                 pClient, u32Format, pv, cb, pcbActual));
     231   
     232    int rc = VINF_SUCCESS;
     233    CLIPREADX11CBCONTEXT *pCtx
     234            = (CLIPREADX11CBCONTEXT *)RTMemAlloc(sizeof(*pCtx));
     235    if (!pCtx)
     236        rc = VERR_NO_MEMORY;
     237    if (RT_SUCCESS(rc))
     238    {
     239        pCtx->callHandle = pClient->asyncRead.callHandle;
     240        pCtx->paParms = pClient->asyncRead.paParms;
     241        rc = ClipRequestDataFromX11(pClient->pCtx->pBackend, u32Format, pv,
     242                                    cb, pCtx);
     243        if (RT_SUCCESS(rc))
     244            rc = VINF_HGCM_ASYNC_EXECUTE;
     245    }
     246    LogFlowFunc(("returning %Rrc\n", rc));
     247    return rc;
     248}
     249
     250/**
     251 * Complete a request from VBox for the X11 clipboard data.  The data should
     252 * be written to the buffer provided in the initial request.
     253 * @param  pCtx  request context information
     254 * @param  rc    the completion status of the request
     255 * @param  cbActual  on successful completion, the number of bytes of data
     256 *                   actually written, on buffer overflow the size of the
     257 *                   buffer needed, ignored otherwise
     258 * @todo   change this to deal with the buffer issues rather than offloading
     259 *         them onto the caller
     260 */
     261void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc,
     262                                    uint32_t cbActual)
     263{
     264    vboxSvcClipboardCompleteReadData(pCtx->callHandle, pCtx->paParms, rc,
     265                                 cbActual);
     266    RTMemFree(pCtx);
     267}
     268
     269/** A request for clipboard data from VBox */
     270struct _VBOXCLIPBOARDREQFROMVBOX
     271{
     272    /** Data received */
     273    void *pv;
     274    /** The size of the data */
     275    uint32_t cb;
     276    /** Format of the data */
     277    uint32_t format;
     278    /** A semaphore for waiting for the data */
     279    RTSEMEVENT finished;
     280};
     281
     282/** Wait for clipboard data requested from VBox to arrive. */
     283static int clipWaitForDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx,
    76284                                   VBOXCLIPBOARDREQFROMVBOX *pReq,
    77285                                   uint32_t u32Format)
     
    104312/** Post a request for clipboard data to VBox/the guest and wait for it to be
    105313 * completed. */
    106 static int vboxClipboardPostAndWaitForReq(VBOXCLIPBOARDCONTEXT *pCtx,
     314static int clipRequestDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx,
    107315                                          VBOXCLIPBOARDREQFROMVBOX *pReq,
    108316                                          uint32_t u32Format)
     
    125333    RTCritSectLeave(&pCtx->clipboardMutex);
    126334    if (RT_SUCCESS(rc))
    127         rc = vboxClipboardWaitForReq(pCtx, pReq, u32Format);
     335        rc = clipWaitForDataFromVBox(pCtx, pReq, u32Format);
    128336    LogFlowFunc(("returning %Rrc\n", rc));
    129337    return rc;
     
    141349 * @note   Host glue code.
    142350 */
    143 int VBoxX11ClipboardReadVBoxData (VBOXCLIPBOARDCONTEXT *pCtx,
     351int ClipRequestDataForX11 (VBOXCLIPBOARDCONTEXT *pCtx,
    144352                                   uint32_t u32Format, void **ppv,
    145353                                   uint32_t *pcb)
     
    158366    if (RT_SUCCESS(rc))
    159367    {
    160         rc = vboxClipboardPostAndWaitForReq(pCtx, &request,
    161                                             u32Format);
     368        rc = clipRequestDataFromVBox(pCtx, &request, u32Format);
    162369        RTSemEventDestroy(request.finished);
    163370    }
     
    170377    if (RT_SUCCESS(rc))
    171378        LogFlowFunc(("*ppv=%.*ls, *pcb=%u\n", *pcb / 2, *ppv, *pcb));
    172     return rc;
    173 }
    174 
    175 /**
    176  * Report formats available in the X11 clipboard to VBox.
    177  * @param  pCtx        Opaque context pointer for the glue code
    178  * @param  u32Formats  The formats available
    179  * @note  Host glue code
    180  */
    181 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,
    182                                       uint32_t u32Formats)
    183 {
    184     LogFlowFunc(("called.  pCtx=%p, u32Formats=%02X\n", pCtx, u32Formats));
    185     vboxSvcClipboardReportMsg(pCtx->pClient,
    186                               VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
    187                               u32Formats);
    188 }
    189 
    190 /**
    191  * Initialise the host side of the shared clipboard.
    192  * @note  Host glue code
    193  */
    194 int vboxClipboardInit (void)
    195 {
    196     return VINF_SUCCESS;
    197 }
    198 
    199 /**
    200  * Terminate the host side of the shared clipboard.
    201  * @note  host glue code
    202  */
    203 void vboxClipboardDestroy (void)
    204 {
    205 
    206 }
    207 
    208 /**
    209  * Connect a guest to the shared clipboard.
    210  * @note  host glue code
    211  * @note  on the host, we assume that some other application already owns
    212  *        the clipboard and leave ownership to X11.
    213  */
    214 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient)
    215 {
    216     int rc = VINF_SUCCESS;
    217     CLIPBACKEND *pBackend = NULL;
    218 
    219     LogRel(("Starting host clipboard service\n"));
    220     VBOXCLIPBOARDCONTEXT *pCtx =
    221         (VBOXCLIPBOARDCONTEXT *) RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT));
    222     if (!pCtx)
    223         rc = VERR_NO_MEMORY;
    224     else
    225     {
    226         RTCritSectInit(&pCtx->clipboardMutex);
    227         pBackend = VBoxX11ClipboardConstructX11(pCtx);
    228         if (pBackend == NULL)
    229             rc = VERR_NO_MEMORY;
    230         else
    231         {
    232             pCtx->pBackend = pBackend;
    233             pClient->pCtx = pCtx;
    234             pCtx->pClient = pClient;
    235             rc = VBoxX11ClipboardStartX11(pBackend);
    236         }
    237         if (RT_FAILURE(rc) && pBackend)
    238             VBoxX11ClipboardStopX11(pCtx->pBackend);
    239         if (RT_FAILURE(rc))
    240             RTCritSectDelete(&pCtx->clipboardMutex);
    241     }
    242     if (RT_FAILURE(rc))
    243     {
    244         RTMemFree(pCtx);
    245         LogRel(("Failed to initialise the shared clipboard\n"));
    246     }
    247     LogFlowFunc(("returning %Rrc\n", rc));
    248     return rc;
    249 }
    250 
    251 /**
    252  * Synchronise the contents of the host clipboard with the guest, called
    253  * after a save and restore of the guest.
    254  * @note  Host glue code
    255  */
    256 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
    257 {
    258     /* Tell the guest we have no data in case X11 is not available.  If
    259      * there is data in the host clipboard it will automatically be sent to
    260      * the guest when the clipboard starts up. */
    261     vboxSvcClipboardReportMsg (pClient,
    262                                VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);
    263     return VINF_SUCCESS;
    264 }
    265 
    266 /**
    267  * Shut down the shared clipboard service and "disconnect" the guest.
    268  * @note  Host glue code
    269  */
    270 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
    271 {
    272     LogFlow(("vboxClipboardDisconnect\n"));
    273 
    274     LogRel(("Stopping the host clipboard service\n"));
    275     VBOXCLIPBOARDCONTEXT *pCtx = pClient->pCtx;
    276     /* Drop the reference to the client, in case it is still there.  This
    277      * will cause any outstanding clipboard data requests from X11 to fail
    278      * immediately. */
    279     pCtx->fShuttingDown = true;
    280     /* If there is a currently pending request, release it immediately. */
    281     vboxClipboardWriteData(pClient, NULL, 0, 0);
    282     int rc = VBoxX11ClipboardStopX11(pCtx->pBackend);
    283     /** @todo handle this slightly more reasonably, or be really sure
    284      *        it won't go wrong. */
    285     AssertRC(rc);
    286     if (RT_SUCCESS(rc))  /* And if not? */
    287     {
    288         VBoxX11ClipboardDestructX11(pCtx->pBackend);
    289         RTCritSectDelete(&pCtx->clipboardMutex);
    290         RTMemFree(pCtx);
    291     }
    292 }
    293 
    294 /**
    295  * VBox is taking possession of the shared clipboard.
    296  *
    297  * @param pClient    Context data for the guest system
    298  * @param u32Formats Clipboard formats the guest is offering
    299  * @note  Host glue code
    300  */
    301 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient,
    302                                   uint32_t u32Formats)
    303 {
    304     LogFlowFunc(("called.  pClient=%p, u32Formats=%02X\n", pClient,
    305                  u32Formats));
    306     VBoxX11ClipboardAnnounceVBoxFormat (pClient->pCtx->pBackend, u32Formats);
    307 }
    308 
    309 /**
    310  * Called when VBox wants to read the X11 clipboard.
    311  *
    312  * @param  pClient   Context information about the guest VM
    313  * @param  u32Format The format that the guest would like to receive the data in
    314  * @param  pv        Where to write the data to
    315  * @param  cb        The size of the buffer to write the data to
    316  * @param  pcbActual Where to write the actual size of the written data
    317  * @note   Host glue code
    318  */
    319 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient,
    320                            uint32_t u32Format, void *pv, uint32_t cb,
    321                            uint32_t *pcbActual)
    322 {
    323     LogFlowFunc(("pClient=%p, u32Format=%02X, pv=%p, cb=%u, pcbActual=%p",
    324                  pClient, u32Format, pv, cb, pcbActual));
    325     int rc = VBoxX11ClipboardReadX11Data(pClient->pCtx->pBackend, u32Format,
    326                                          pv, cb, pcbActual);
    327     LogFlowFunc(("returning %Rrc\n", rc));
    328     if (RT_SUCCESS(rc))
    329         LogFlowFunc(("*pv=%.*ls, *pcbActual=%u\n", *pcbActual / 2, pv,
    330                      *pcbActual));
    331379    return rc;
    332380}
     
    365413        /* Signal that the request has been completed. */
    366414        RTSemEventSignal(pReq->finished);
    367     }
    368     pCtx->pReq = NULL;
     415        pCtx->pReq = NULL;
     416    }
    369417    RTCritSectLeave(&pCtx->clipboardMutex);
    370418}
     419
     420#ifdef TESTCASE
     421#include <iprt/initterm.h>
     422#include <iprt/stream.h>
     423
     424#define TEST_NAME "tstClipboardX11-2"
     425
     426struct _CLIPBACKEND
     427{
     428    uint32_t formats;
     429    struct _READDATA
     430    {
     431        uint32_t format;
     432        void *pv;
     433        uint32_t cb;
     434        CLIPREADX11CBCONTEXT *pCtx;
     435        int rc;
     436    } readData;
     437    struct _COMPLETEREAD
     438    {
     439        int rc;
     440        uint32_t cbActual;
     441    } completeRead;
     442    struct _WRITEDATA
     443    {
     444        void *pv;
     445        uint32_t cb;
     446        uint32_t format;
     447        bool timeout;
     448    } writeData;
     449    struct _REPORTDATA
     450    {
     451        uint32_t format;
     452    } reportData;
     453};
     454
     455void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats)
     456{
     457    CLIPBACKEND *pBackend = pClient->pCtx->pBackend;
     458    if (   (u32Msg == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA)
     459        && !pBackend->writeData.timeout)
     460        vboxClipboardWriteData(pClient, pBackend->writeData.pv,
     461                               pBackend->writeData.cb,
     462                               pBackend->writeData.format);
     463    else
     464        return;
     465}
     466
     467void vboxSvcClipboardCompleteReadData(VBOXHGCMCALLHANDLE callHandle, VBOXHGCMSVCPARM *paParms, int rc, uint32_t cbActual)
     468{
     469    CLIPBACKEND *pBackend = (CLIPBACKEND *)callHandle;
     470    pBackend->completeRead.rc = rc;
     471    pBackend->completeRead.cbActual = cbActual;
     472}
     473
     474CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend)
     475{
     476    return (CLIPBACKEND *)RTMemAllocZ(sizeof(CLIPBACKEND));
     477}
     478
     479void ClipDestructX11(CLIPBACKEND *pBackend)
     480{
     481    RTMemFree(pBackend);
     482}
     483
     484int ClipStartX11(CLIPBACKEND *pBackend)
     485{
     486    return VINF_SUCCESS;
     487}
     488
     489int ClipStopX11(CLIPBACKEND *pBackend)
     490{
     491    return VINF_SUCCESS;
     492}
     493
     494void ClipAnnounceFormatToX11(CLIPBACKEND *pBackend,
     495                                    uint32_t u32Formats)
     496{
     497    pBackend->formats = u32Formats;
     498}
     499
     500extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, uint32_t u32Format,
     501                                  void *pv, uint32_t cb,
     502                                  CLIPREADX11CBCONTEXT *pCtx)
     503{
     504    pBackend->readData.format = u32Format;
     505    pBackend->readData.pv = pv;
     506    pBackend->readData.cb = cb;
     507    pBackend->readData.pCtx = pCtx;
     508    return pBackend->readData.rc;
     509}
     510
     511int main()
     512{
     513    VBOXCLIPBOARDCLIENTDATA client;
     514    unsigned cErrors = 0;
     515    int rc = RTR3Init();
     516    RTPrintf(TEST_NAME ": TESTING\n");
     517    AssertRCReturn(rc, 1);
     518    rc = vboxClipboardConnect(&client);
     519    CLIPBACKEND *pBackend = client.pCtx->pBackend;
     520    AssertRCReturn(rc, 1);
     521    vboxClipboardFormatAnnounce(&client,
     522                                VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     523    if (pBackend->formats != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     524    {
     525        RTPrintf(TEST_NAME ": vboxClipboardFormatAnnounce failed with VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n");
     526        ++cErrors;
     527    }
     528    pBackend->readData.rc = VINF_SUCCESS;
     529    client.asyncRead.callHandle = (VBOXHGCMCALLHANDLE)pBackend;
     530    client.asyncRead.paParms = (VBOXHGCMSVCPARM *)&client;
     531    uint32_t u32Dummy;
     532    rc = vboxClipboardReadData(&client, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     533                               &u32Dummy, 42, &u32Dummy);
     534    if (rc != VINF_HGCM_ASYNC_EXECUTE)
     535    {
     536        RTPrintf(TEST_NAME ": vboxClipboardReadData returned %Rrc\n", rc);
     537        ++cErrors;
     538    }
     539    else
     540    {
     541        if (   pBackend->readData.format !=
     542                       VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT
     543            || pBackend->readData.pv != &u32Dummy
     544            || pBackend->readData.cb != 42)
     545        {
     546            RTPrintf(TEST_NAME ": format=%u, pv=%p, cb=%u\n",
     547                     pBackend->readData.format, pBackend->readData.pv,
     548                     pBackend->readData.cb);
     549            ++cErrors;
     550        }
     551        else
     552        {
     553            ClipCompleteDataRequestFromX11(pBackend->readData.pCtx,
     554                                           VERR_NO_DATA, 43);
     555            if (   pBackend->completeRead.rc != VERR_NO_DATA
     556                || pBackend->completeRead.cbActual != 43)
     557            {
     558                RTPrintf(TEST_NAME ": rc=%Rrc, cbActual=%u\n",
     559                         pBackend->completeRead.rc,
     560                         pBackend->completeRead.cbActual);
     561                ++cErrors;
     562            }
     563        }
     564    }
     565    void *pv;
     566    uint32_t cb;
     567    pBackend->writeData.pv = (void *)"testing";
     568    pBackend->writeData.cb = sizeof("testing");
     569    pBackend->writeData.format = 1234;
     570    pBackend->reportData.format = 4321;  /* XX this should be handled! */
     571    rc = ClipRequestDataForX11(client.pCtx, 23, &pv, &cb);
     572    if (   rc != VINF_SUCCESS
     573        || strcmp((const char *)pv, "testing") != 0
     574        || cb != sizeof("testing"))
     575    {
     576        RTPrintf("rc=%Rrc, pv=%p, cb=%u\n", rc, pv, cb);
     577        ++cErrors;
     578    }
     579    else
     580        RTMemFree(pv);
     581    pBackend->writeData.timeout = true;
     582    rc = ClipRequestDataForX11(client.pCtx, 23, &pv, &cb);
     583    if (rc != VERR_TIMEOUT)
     584    {
     585        RTPrintf("rc=%Rrc\n", rc);
     586        ++cErrors;
     587    }
     588    /* Data arriving after a timeout should *not* cause any segfaults or
     589     * memory leaks.  Check with Valgrind! */
     590    vboxClipboardWriteData(&client, (void *)"tested", sizeof("tested"), 999);
     591    vboxClipboardDisconnect(&client);
     592    if (cErrors > 0)
     593        RTPrintf(TEST_NAME ": errors: %u\n", cErrors);
     594    return cErrors > 0 ? 1 : 0;
     595}
     596#endif  /* TESTCASE */
Note: See TracChangeset for help on using the changeset viewer.

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