Changeset 19842 in vbox
- Timestamp:
- May 19, 2009 9:40:24 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
include/VBox/GuestHost/SharedClipboard.h (modified) (2 diffs)
-
src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp (modified) (39 diffs)
-
src/VBox/HostServices/SharedClipboard/Makefile.kmk (modified) (1 diff)
-
src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/SharedClipboard.h
r19552 r19842 37 37 enum { 38 38 /** The number of milliseconds before the clipboard times out. */ 39 #ifndef TESTCASE 39 40 CLIPBOARD_TIMEOUT = 5000 41 #else 42 CLIPBOARD_TIMEOUT = 1 43 #endif 40 44 }; 41 45 … … 48 52 typedef struct _CLIPBACKEND CLIPBACKEND; 49 53 54 /** Opaque data structure used for asynchronously completing requests by VBox 55 * to read the X11 clipboard data. */ 56 struct _CLIPREADX11CBCONTEXT; 57 typedef struct _CLIPREADX11CBCONTEXT CLIPREADX11CBCONTEXT; 58 50 59 /* 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); 60 extern CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend); 61 extern void ClipDestructX11(CLIPBACKEND *pBackend); 62 extern int ClipStartX11(CLIPBACKEND *pBackend); 63 extern int ClipStopX11(CLIPBACKEND *pBackend); 64 extern void ClipAnnounceFormatToX11(CLIPBACKEND *pBackend, 65 uint32_t u32Formats); 66 extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, uint32_t u32Format, 67 void *pv, uint32_t cb, 68 CLIPREADX11CBCONTEXT *pCtx); 62 69 63 70 /* APIs exported by the X11/VBox frontend */ 64 extern int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,71 extern int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, 65 72 uint32_t u32Format, void **ppv, 66 73 uint32_t *pcb); 67 extern void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,74 extern void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx, 68 75 uint32_t u32Formats); 76 extern void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc, 77 uint32_t cbActual); 69 78 #endif /* ___GUESTHOST_VBOXCLIPBOARD__H */ -
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r19754 r19842 297 297 { 298 298 uint32_t u32VBoxFormats = clipVBoxFormatForX11Format(pCtx->X11TextFormat); 299 VBoxX11ClipboardReportX11Formats(pCtx->pFrontend, u32VBoxFormats);299 ClipReportX11Formats(pCtx->pFrontend, u32VBoxFormats); 300 300 } 301 301 … … 381 381 /* VBox raced us and we lost. So we don't want to report anything. */ 382 382 changed = false; 383 else if (*atomType == XT_CONVERT_FAIL) /* timeout */ 383 else if ( (*atomType == XT_CONVERT_FAIL) /* timeout */ 384 || !pTargets /* Conversion failed */) 384 385 clipResetX11Formats(pCtx); 385 386 else … … 558 559 * @note X11 backend code 559 560 */ 560 CLIPBACKEND * VBoxX11ClipboardConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend)561 CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend) 561 562 { 562 563 int rc; … … 589 590 * @note X11 backend code 590 591 */ 591 void VBoxX11ClipboardDestructX11(CLIPBACKEND *pCtx)592 void ClipDestructX11(CLIPBACKEND *pCtx) 592 593 { 593 594 /* … … 606 607 * Announce to the X11 backend that we are ready to start. 607 608 */ 608 int VBoxX11ClipboardStartX11(CLIPBACKEND *pCtx)609 int ClipStartX11(CLIPBACKEND *pCtx) 609 610 { 610 611 int rc = VINF_SUCCESS; … … 647 648 * to return and will not be able to terminate. 648 649 */ 649 int VBoxX11ClipboardStopX11(CLIPBACKEND *pCtx)650 int ClipStopX11(CLIPBACKEND *pCtx) 650 651 { 651 652 int rc, rcThread; … … 719 720 } 720 721 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. 729 724 */ 730 725 static int clipReadVBoxClipboard(CLIPBACKEND *pCtx, uint32_t u32Format, … … 737 732 { 738 733 if (pCtx->pvUnicodeCache == NULL) 739 rc = VBoxX11ClipboardReadVBoxData(pCtx->pFrontend, u32Format,734 rc = ClipRequestDataForX11(pCtx->pFrontend, u32Format, 740 735 &pCtx->pvUnicodeCache, 741 736 &pCtx->cbUnicodeCache); … … 749 744 } 750 745 else 751 rc = VBoxX11ClipboardReadVBoxData(pCtx->pFrontend, u32Format,746 rc = ClipRequestDataForX11(pCtx->pFrontend, u32Format, 752 747 ppv, pcb); 753 748 LogFlowFunc(("returning %Rrc\n", rc)); … … 964 959 *atomTarget); 965 960 CLIPFORMAT format = clipRealFormatForX11Format(x11Format); 966 if ((format == UTF8) || (format == CTEXT)) 961 if ( ((format == UTF8) || (format == CTEXT)) 962 && (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)) 967 963 { 968 964 void *pv = NULL; … … 1084 1080 1085 1081 /** 1086 * Worker function for VBoxX11ClipboardAnnounceVBoxFormatwhich runs on the1082 * Worker function for ClipAnnounceFormatToX11 which runs on the 1087 1083 * event thread. 1088 1084 * @param pUserData Pointer to a CLIPNEWVBOXFORMATS structure containing … … 1113 1109 * @note X11 backend code 1114 1110 */ 1115 void VBoxX11ClipboardAnnounceVBoxFormat(CLIPBACKEND *pCtx,1111 void ClipAnnounceFormatToX11(CLIPBACKEND *pCtx, 1116 1112 uint32_t u32Formats) 1117 1113 { … … 1357 1353 * a request for the clipboard contents) */ 1358 1354 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; 1362 1357 /** The format VBox would like the data in */ 1363 1358 uint32_t mFormat; 1364 1359 /** The text format we requested from X11 if we requested text */ 1365 1360 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;1370 1361 /** The clipboard context this request is associated with */ 1371 1362 CLIPBACKEND *mCtx; … … 1395 1386 CLIPBACKEND *pCtx = pReq->mCtx; 1396 1387 unsigned cbSrc = (*pcLen) * (*piFormat) / 8; 1388 uint32_t cbActual = 0; 1397 1389 1398 1390 if (pvSrc == NULL) … … 1409 1401 rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc, 1410 1402 pReq->mBuffer, pReq->mSize, 1411 pReq->mActual);1403 &cbActual); 1412 1404 break; 1413 1405 case UTF8: … … 1419 1411 rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc, 1420 1412 pReq->mBuffer, pReq->mSize, 1421 pReq->mActual);1413 &cbActual); 1422 1414 else 1423 1415 rc = clipLatin1ToWinTxt((char *) pvSrc, cbSrc, 1424 1416 pReq->mBuffer, pReq->mSize, 1425 pReq->mActual);1417 &cbActual); 1426 1418 break; 1427 1419 } … … 1433 1425 rc = VERR_NOT_IMPLEMENTED; 1434 1426 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); 1440 1429 if (RT_SUCCESS(rc)) 1441 1430 /* The other end may want to cache the data, so pretend we have new … … 1448 1437 } 1449 1438 1450 /** Worker function for VBoxX11ClipboardReadX11Datawhich runs on the event1439 /** Worker function for ClipRequestDataFromX11 which runs on the event 1451 1440 * thread. */ 1452 1441 static void vboxClipboardReadX11Worker(XtPointer pUserData, … … 1459 1448 1460 1449 int rc = VINF_SUCCESS; 1461 /* Set this to start with, just in case */1462 *pReq->mActual = 0;1463 1450 /* Do not continue if we already own the clipboard */ 1464 1451 if (pCtx->fOwnsClipboard == true) 1465 rc = VERR_ NO_DATA; /** @todo should this be VINF? */1452 rc = VERR_TIMEOUT; 1466 1453 else 1467 1454 { … … 1490 1477 if (RT_FAILURE(rc)) 1491 1478 { 1492 pReq->mRC = rc;1493 1479 /* 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); 1496 1483 } 1497 1484 LogFlowFunc(("status %Rrc\n", rc)); … … 1501 1488 * Called when VBox wants to read the X11 clipboard. 1502 1489 * 1490 * @returns iprt status code 1503 1491 * @param pCtx Context data for the clipboard backend 1504 1492 * @param u32Format The format that the VBox would like to receive the data … … 1507 1495 * @param cb The size of the buffer to write the data to 1508 1496 * @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 */ 1499 int ClipRequestDataFromX11(CLIPBACKEND *pCtx, uint32_t u32Format, void *pv, 1500 uint32_t cb, CLIPREADX11CBCONTEXT *pReadCtx) 1501 { 1519 1502 /* 1520 1503 * Immediately return if we are not connected to the X server. 1521 1504 */ 1522 1505 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; 1536 1518 /* We use this to schedule a worker function on the event thread. */ 1537 1519 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); 1543 1521 } 1544 1522 return rc; … … 1600 1578 g_vboxDatapv = NULL; 1601 1579 g_vboxDatacb = 0; 1602 VBoxX11ClipboardAnnounceVBoxFormat(pCtx, 0);1580 ClipAnnounceFormatToX11(pCtx, 0); 1603 1581 } 1604 1582 … … 1622 1600 g_vboxDatapv = pv; 1623 1601 g_vboxDatacb = cb; 1624 VBoxX11ClipboardAnnounceVBoxFormat(pCtx,1602 ClipAnnounceFormatToX11(pCtx, 1625 1603 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT); 1626 1604 return VINF_SUCCESS; … … 1628 1606 1629 1607 /* Return the data in the simulated VBox clipboard. */ 1630 int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,1608 int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, 1631 1609 uint32_t u32Format, void **ppv, 1632 1610 uint32_t *pcb) … … 1792 1770 static unsigned long g_cSelData = 0; 1793 1771 static int g_selFormat = 0; 1772 static bool g_fTargetsTimeout = false; 1773 static bool g_fTargetsFailure = false; 1794 1774 1795 1775 void XtGetSelectionValue(Widget widget, Atom selection, Atom target, … … 1815 1795 if (target == clipGetAtom(NULL, "TARGETS")) 1816 1796 { 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; 1820 1803 format = 32; 1821 1804 } … … 1840 1823 static uint32_t g_fX11Formats = 0; 1841 1824 1842 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT* pCtx,1825 void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT* pCtx, 1843 1826 uint32_t u32Formats) 1844 1827 { … … 1923 1906 g_pfnSelLose(TEST_WIDGET, &clipAtom); 1924 1907 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 */ 1913 static void clipSetTargetsFailure(bool fTimeout, bool fFailure) 1914 { 1915 g_fTargetsTimeout = fTimeout; 1916 g_fTargetsFailure = fFailure; 1925 1917 } 1926 1918 … … 1959 1951 RTMemFree(*list); 1960 1952 RTMemFree(list); 1953 } 1954 1955 struct _CLIPREADX11CBCONTEXT 1956 { 1957 int rc; 1958 uint32_t cbActual; 1959 }; 1960 1961 void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc, 1962 uint32_t cbActual) 1963 { 1964 pCtx->rc = rc; 1965 pCtx->cbActual = cbActual; 1961 1966 } 1962 1967 … … 1979 1984 { 1980 1985 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; 1985 1992 if (rc != rcExp) 1986 1993 RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp, … … 2035 2042 { 2036 2043 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; 2041 2050 if (rc != rcExp) 2042 2051 RTPrintf("Wrong return code, expected %Rrc, got %Rrc\n", rcExp, … … 2133 2142 { 2134 2143 RTR3Init(); 2135 CLIPBACKEND *pCtx = VBoxX11ClipboardConstructX11(NULL);2144 CLIPBACKEND *pCtx = ClipConstructX11(NULL); 2136 2145 unsigned cErrs = 0; 2137 2146 char pc[MAX_BUF_SIZE]; 2138 2147 uint32_t cbActual; 2139 int rc = VBoxX11ClipboardStartX11(pCtx);2148 int rc = ClipStartX11(pCtx); 2140 2149 AssertRCReturn(rc, 1); 2141 2150 … … 2263 2272 clipSetSelectionValues("UTF8_STRING", XA_STRING, NULL, 2264 2273 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; 2268 2279 if (rc != VERR_NO_DATA) 2269 2280 { … … 2274 2285 /*** request for an invalid VBox format from X11 ***/ 2275 2286 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; 2278 2290 if (rc != VERR_NOT_IMPLEMENTED) 2279 2291 { 2280 2292 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()); 2281 2325 ++cErrs; 2282 2326 } … … 2360 2404 if (!testStringFromVBoxFailed(pCtx, "UTF8_STRING")) 2361 2405 ++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 2362 2414 if (cErrs > 0) 2363 2415 RTPrintf("Failed with %u error(s)\n", cErrs); … … 2379 2431 #define TEST_NAME "tstClipboardX11Smoke" 2380 2432 2381 int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,2433 int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, 2382 2434 uint32_t u32Format, void **ppv, 2383 2435 uint32_t *pcb) … … 2386 2438 } 2387 2439 2388 void VBoxX11ClipboardReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx,2440 void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx, 2389 2441 uint32_t u32Formats) 2442 {} 2443 2444 void ClipCompleteDataRequestFromX11(CLIPREADX11CBCONTEXT *pCtx, int rc, 2445 uint32_t cbActual) 2390 2446 {} 2391 2447 … … 2402 2458 } 2403 2459 RTPrintf(TEST_NAME ": TESTING\n"); 2404 CLIPBACKEND *pCtx = VBoxX11ClipboardConstructX11(NULL);2460 CLIPBACKEND *pCtx = ClipConstructX11(NULL); 2405 2461 AssertReturn(pCtx, 1); 2406 rc = VBoxX11ClipboardStartX11(pCtx);2462 rc = ClipStartX11(pCtx); 2407 2463 AssertRCReturn(rc, 1); 2408 2464 /* Give the clipboard time to synchronise. */ 2409 2465 RTThreadSleep(500); 2410 rc = VBoxX11ClipboardStopX11(pCtx);2466 rc = ClipStopX11(pCtx); 2411 2467 AssertRCReturn(rc, 1); 2412 VBoxX11ClipboardDestructX11(pCtx);2468 ClipDestructX11(pCtx); 2413 2469 return 0; 2414 2470 } -
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r19282 r19842 69 69 -framework ApplicationServices -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxSharedClipboard.dylib 70 70 71 ifdef 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 98 endif # VBOX_WITH_TESTCASES 99 71 100 include $(KBUILD_PATH)/subfooter.kmk 72 -
trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp
r19536 r19842 35 35 #include "VBoxClipboard.h" 36 36 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; 37 struct _VBOXCLIPBOARDREQFROMVBOX; 38 typedef struct _VBOXCLIPBOARDREQFROMVBOX VBOXCLIPBOARDREQFROMVBOX; 49 39 50 40 /** Global context information used by the host glue for the X11 clipboard … … 73 63 }; 74 64 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 */ 71 void 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 */ 84 int 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 */ 93 void 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 */ 104 int 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 */ 146 int 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 */ 160 void 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 */ 191 void 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 199 struct _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 */ 225 int 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 */ 261 void 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 */ 270 struct _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. */ 283 static int clipWaitForDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx, 76 284 VBOXCLIPBOARDREQFROMVBOX *pReq, 77 285 uint32_t u32Format) … … 104 312 /** Post a request for clipboard data to VBox/the guest and wait for it to be 105 313 * completed. */ 106 static int vboxClipboardPostAndWaitForReq(VBOXCLIPBOARDCONTEXT *pCtx,314 static int clipRequestDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx, 107 315 VBOXCLIPBOARDREQFROMVBOX *pReq, 108 316 uint32_t u32Format) … … 125 333 RTCritSectLeave(&pCtx->clipboardMutex); 126 334 if (RT_SUCCESS(rc)) 127 rc = vboxClipboardWaitForReq(pCtx, pReq, u32Format);335 rc = clipWaitForDataFromVBox(pCtx, pReq, u32Format); 128 336 LogFlowFunc(("returning %Rrc\n", rc)); 129 337 return rc; … … 141 349 * @note Host glue code. 142 350 */ 143 int VBoxX11ClipboardReadVBoxData(VBOXCLIPBOARDCONTEXT *pCtx,351 int ClipRequestDataForX11 (VBOXCLIPBOARDCONTEXT *pCtx, 144 352 uint32_t u32Format, void **ppv, 145 353 uint32_t *pcb) … … 158 366 if (RT_SUCCESS(rc)) 159 367 { 160 rc = vboxClipboardPostAndWaitForReq(pCtx, &request, 161 u32Format); 368 rc = clipRequestDataFromVBox(pCtx, &request, u32Format); 162 369 RTSemEventDestroy(request.finished); 163 370 } … … 170 377 if (RT_SUCCESS(rc)) 171 378 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 code178 * @param u32Formats The formats available179 * @note Host glue code180 */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 code193 */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 code202 */203 void vboxClipboardDestroy (void)204 {205 206 }207 208 /**209 * Connect a guest to the shared clipboard.210 * @note host glue code211 * @note on the host, we assume that some other application already owns212 * 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 else225 {226 RTCritSectInit(&pCtx->clipboardMutex);227 pBackend = VBoxX11ClipboardConstructX11(pCtx);228 if (pBackend == NULL)229 rc = VERR_NO_MEMORY;230 else231 {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, called253 * after a save and restore of the guest.254 * @note Host glue code255 */256 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)257 {258 /* Tell the guest we have no data in case X11 is not available. If259 * there is data in the host clipboard it will automatically be sent to260 * 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 code269 */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. This277 * will cause any outstanding clipboard data requests from X11 to fail278 * 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 sure284 * 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 system298 * @param u32Formats Clipboard formats the guest is offering299 * @note Host glue code300 */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 VM313 * @param u32Format The format that the guest would like to receive the data in314 * @param pv Where to write the data to315 * @param cb The size of the buffer to write the data to316 * @param pcbActual Where to write the actual size of the written data317 * @note Host glue code318 */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));331 379 return rc; 332 380 } … … 365 413 /* Signal that the request has been completed. */ 366 414 RTSemEventSignal(pReq->finished); 367 }368 pCtx->pReq = NULL;415 pCtx->pReq = NULL; 416 } 369 417 RTCritSectLeave(&pCtx->clipboardMutex); 370 418 } 419 420 #ifdef TESTCASE 421 #include <iprt/initterm.h> 422 #include <iprt/stream.h> 423 424 #define TEST_NAME "tstClipboardX11-2" 425 426 struct _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 455 void 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 467 void 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 474 CLIPBACKEND *ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend) 475 { 476 return (CLIPBACKEND *)RTMemAllocZ(sizeof(CLIPBACKEND)); 477 } 478 479 void ClipDestructX11(CLIPBACKEND *pBackend) 480 { 481 RTMemFree(pBackend); 482 } 483 484 int ClipStartX11(CLIPBACKEND *pBackend) 485 { 486 return VINF_SUCCESS; 487 } 488 489 int ClipStopX11(CLIPBACKEND *pBackend) 490 { 491 return VINF_SUCCESS; 492 } 493 494 void ClipAnnounceFormatToX11(CLIPBACKEND *pBackend, 495 uint32_t u32Formats) 496 { 497 pBackend->formats = u32Formats; 498 } 499 500 extern 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 511 int 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.

