Changeset 46383 in vbox for trunk/src/VBox/GuestHost/SharedClipboard
- Timestamp:
- Jun 4, 2013 1:48:19 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 86203
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r46335 r46383 138 138 * @param widget a valid Xt widget 139 139 */ 140 static CLIPX11FORMAT clipFindX11FormatByAtomText( CLIPBACKEND *pCtx,const char *pcsz)140 static CLIPX11FORMAT clipFindX11FormatByAtomText(const char *pcsz) 141 141 { 142 142 for (unsigned i = 0; i < RT_ELEMENTS(g_aFormats); ++i) … … 291 291 } 292 292 293 static void clipQueueToEventThread(CLIPBACKEND *pCtx, 294 XtTimerCallbackProc proc, 295 XtPointer client_data); 293 #ifdef TESTCASE 294 static void testQueueToEventThread(void (*proc)(void *, void *), 295 void *client_data); 296 #endif 296 297 297 298 /** String written to the wakeup pipe. */ … … 300 301 #define WAKE_UP_STRING_LEN ( sizeof(WAKE_UP_STRING) - 1 ) 301 302 302 #ifndef TESTCASE303 303 /** Schedule a function call to run on the Xt event thread by passing it to 304 304 * the application context as a 0ms timeout and waking up the event loop by 305 305 * writing to the wakeup pipe which it monitors. */ 306 306 void clipQueueToEventThread(CLIPBACKEND *pCtx, 307 XtTimerCallbackProc proc,308 XtPointerclient_data)307 void (*proc)(void *, void *), 308 void *client_data) 309 309 { 310 310 LogRel2(("clipQueueToEventThread: proc=%p, client_data=%p\n", 311 311 proc, client_data)); 312 XtAppAddTimeOut(pCtx->appContext, 0, proc, client_data); 312 #ifndef TESTCASE 313 XtAppAddTimeOut(pCtx->appContext, 0, (XtTimerCallbackProc)proc, 314 (XtPointer)client_data); 313 315 write(pCtx->wakeupPipeWrite, WAKE_UP_STRING, WAKE_UP_STRING_LEN); 314 } 316 #else 317 testQueueToEventThread(proc, client_data); 315 318 #endif 319 } 316 320 317 321 /** … … 380 384 CLIPX11FORMAT targets[2]; 381 385 CLIPX11FORMAT x11Format; 382 targets[0] = clipFindX11FormatByAtomText( pCtx,"text/plain");383 targets[1] = clipFindX11FormatByAtomText( pCtx,"image/bmp");386 targets[0] = clipFindX11FormatByAtomText("text/plain"); 387 targets[1] = clipFindX11FormatByAtomText("image/bmp"); 384 388 x11Format = clipGetTextFormatFromTargets(pCtx, targets, 2); 385 389 if (clipRealFormatForX11Format(x11Format) != TEXT) 386 390 success = false; 387 targets[0] = clipFindX11FormatByAtomText( pCtx,"UTF8_STRING");388 targets[1] = clipFindX11FormatByAtomText( pCtx,"text/plain");391 targets[0] = clipFindX11FormatByAtomText("UTF8_STRING"); 392 targets[1] = clipFindX11FormatByAtomText("text/plain"); 389 393 x11Format = clipGetTextFormatFromTargets(pCtx, targets, 2); 390 394 if (clipRealFormatForX11Format(x11Format) != UTF8) … … 455 459 } 456 460 461 static void clipQueryX11CBFormats(CLIPBACKEND *pCtx); 462 457 463 /** 458 464 * Update the context's information about targets currently supported by X11, … … 465 471 size_t cTargets) 466 472 { 467 LogRel2 (("%s: called\n", __PRETTY_FUNCTION__)); 473 LogRel2 (("%s: called\n", __FUNCTION__)); 474 pCtx->fBusy = false; 475 if (pCtx->fUpdateNeeded) 476 { 477 /* We may already be out of date. */ 478 pCtx->fUpdateNeeded = false; 479 clipQueryX11CBFormats(pCtx); 480 return; 481 } 482 if (pTargets == NULL) { 483 /* No data available */ 484 clipReportEmptyX11CB(pCtx); 485 return; 486 } 468 487 clipGetFormatsFromTargets(pCtx, pTargets, cTargets); 469 488 clipReportFormatsToVBox(pCtx); 470 489 } 471 490 472 static void clipQueryX11CBFormats(CLIPBACKEND *pCtx);473 474 491 /** 475 492 * Notify the VBox clipboard about available data formats, based on the 476 493 * "targets" information obtained from the X11 clipboard. 477 * @note callback for XtGetSelectionValue 494 * @note Callback for XtGetSelectionValue 495 * @note This function is treated as API glue, and as such is not part of any 496 * unit test. So keep it simple, be paranoid and log everything. 478 497 */ 479 498 static void clipConvertX11Targets(Widget widget, XtPointer pClientData, … … 484 503 CLIPBACKEND *pCtx = 485 504 reinterpret_cast<CLIPBACKEND *>(pClientData); 486 LogRel2(("clipConvertX11Targets: pValue=%p, *pcLen=%u, *atomType=%d, XT_CONVERT_FAIL=%d\n", 487 pValue, *pcLen, *atomType, XT_CONVERT_FAIL)); 505 Atom *pAtoms = (Atom *)pValue; 506 unsigned i, j; 507 LogRel2(("%s: pValue=%p, *pcLen=%u, *atomType=%d%s\n", __FUNCTION__, 508 pValue, *pcLen, *atomType, 509 *atomType == XT_CONVERT_FAIL ? " (XT_CONVERT_FAIL)" : "")); 488 510 CLIPX11FORMAT *pFormats = NULL; 489 if (*pcLen) 490 { 511 if (*pcLen && pValue && (*atomType != XT_CONVERT_FAIL /* time out */)) 491 512 pFormats = (CLIPX11FORMAT *)RTMemAllocZ(*pcLen * sizeof(CLIPX11FORMAT)); 492 if (!pFormats) 493 { 494 XtFree((char *)pValue); 495 return; 496 } 497 } 513 #if defined(DEBUG) && !defined(TESTCASE) 498 514 if (pValue) 499 {500 Atom *pAtoms = (Atom *)pValue;501 unsigned i, j;502 #if defined(DEBUG) && !defined(TESTCASE)503 515 for (i = 0; i < *pcLen; ++i) 504 516 if (pAtoms[i]) 505 517 { 506 518 char *pszName = XGetAtomName(XtDisplay(widget), pAtoms[i]); 507 LogRel2(("%s: found target %s\n", __ PRETTY_FUNCTION__,519 LogRel2(("%s: found target %s\n", __FUNCTION__, 508 520 pszName)); 509 521 XFree(pszName); 510 522 } 523 else 524 LogRel2(("%s: found empty target.\n", __FUNCTION__)); 511 525 #endif 526 if (pFormats) 527 { 512 528 for (i = 0; i < *pcLen; ++i) 529 { 513 530 for (j = 0; j < RT_ELEMENTS(g_aFormats); ++j) 514 531 { … … 518 535 pFormats[i] = j; 519 536 } 520 } 521 pCtx->fBusy = false; 522 if (pCtx->fUpdateNeeded) 523 { 524 /* We may already be out of date. */ 525 pCtx->fUpdateNeeded = false; 526 clipQueryX11CBFormats(pCtx); 537 #if defined(DEBUG) && !defined(TESTCASE) 538 LogRel2(("%s: reporting format %d (%s)\n", __FUNCTION__, 539 pFormats[i], g_aFormats[pFormats[i]].pcszAtom)); 540 #endif 541 } 527 542 } 528 543 else 529 { 530 if ( (*atomType == XT_CONVERT_FAIL) /* timeout */ 531 || (pValue == NULL)) /* No data available */ 532 { 533 clipReportEmptyX11CB(pCtx); 534 RTMemFree(pFormats); 535 return; 536 } 537 clipUpdateX11Targets(pCtx, pFormats, *pcLen); 538 } 544 LogRel2(("%s: reporting empty targets (none reported or allocation failure).\n", 545 __FUNCTION__)); 546 clipUpdateX11Targets(pCtx, pFormats, *pcLen); 539 547 RTMemFree(pFormats); 540 548 XtFree(reinterpret_cast<char *>(pValue)); 541 549 } 550 551 #ifdef TESTCASE 552 void testRequestTargets(CLIPBACKEND *pCtx); 553 #endif 542 554 543 555 /** … … 554 566 } 555 567 pCtx->fBusy = true; 568 #ifndef TESTCASE 556 569 XtGetSelectionValue(pCtx->widget, 557 570 clipGetAtom(pCtx, "CLIPBOARD"), … … 559 572 clipConvertX11Targets, pCtx, 560 573 CurrentTime); 574 #else 575 testRequestTargets(pCtx); 576 #endif 561 577 } 562 578 … … 649 665 /** Worker function for stopping the clipboard which runs on the event 650 666 * thread. */ 651 static void clipStopEventThreadWorker( XtPointer pUserData, XtIntervalId *)667 static void clipStopEventThreadWorker(void *pUserData, void *) 652 668 { 653 669 … … 1269 1285 * clipboard context data. Must be freed by the worker. 1270 1286 */ 1271 static void clipNewVBoxFormatsWorker( XtPointerpUserData,1272 XtIntervalId * /* interval */)1287 static void clipNewVBoxFormatsWorker(void *pUserData, 1288 void * /* interval */) 1273 1289 { 1274 1290 CLIPNEWVBOXFORMATS *pFormats = (CLIPNEWVBOXFORMATS *)pUserData; … … 1476 1492 * the X11 clipboard contains a format we understand. 1477 1493 */ 1478 static void clipConvertX11CB(Widget widget, XtPointer pClientData, 1479 Atom * /* selection */, Atom *atomType, 1480 XtPointer pvSrc, long unsigned int *pcLen, 1481 int *piFormat) 1494 static void clipConvertX11CB(void *pClientData, void *pvSrc, unsigned cbSrc) 1482 1495 { 1483 1496 CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *) pClientData; … … 1490 1503 int rc = VINF_SUCCESS; 1491 1504 CLIPBACKEND *pCtx = pReq->mCtx; 1492 unsigned cbSrc = (*pcLen) * (*piFormat) / 8;1493 1505 void *pvDest = NULL; 1494 1506 uint32_t cbDest = 0; … … 1500 1512 /* The clipboard selection may have changed before we could get it. */ 1501 1513 rc = VERR_NO_DATA; 1502 else if (*atomType == XT_CONVERT_FAIL) /* Xt timeout */1503 rc = VERR_TIMEOUT;1504 1514 else if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 1505 1515 { … … 1555 1565 else 1556 1566 rc = VERR_NOT_IMPLEMENTED; 1557 XtFree((char *)pvSrc);1558 1567 ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq, 1559 1568 pvDest, cbDest); … … 1563 1572 } 1564 1573 1574 /** 1575 * Convert the data obtained from the X11 clipboard to the required format, 1576 * place it in the buffer supplied and signal that data has arrived. 1577 * Convert the text obtained UTF-16LE with Windows EOLs. 1578 * Convert full BMP data to DIB format. 1579 * @note X11 backend code, callback for XtGetSelectionValue, for use when 1580 * the X11 clipboard contains a format we understand. 1581 */ 1582 static void cbConvertX11CB(Widget widget, XtPointer pClientData, 1583 Atom * /* selection */, Atom *atomType, 1584 XtPointer pvSrc, long unsigned int *pcLen, 1585 int *piFormat) 1586 { 1587 if (*atomType == XT_CONVERT_FAIL) /* Xt timeout */ 1588 clipConvertX11CB(pClientData, NULL, 0); 1589 else 1590 clipConvertX11CB(pClientData, pvSrc, (*pcLen) * (*piFormat) / 8); 1591 1592 XtFree((char *)pvSrc); 1593 } 1594 1595 #ifdef TESTCASE 1596 static void testRequestData(CLIPBACKEND* pCtx, CLIPX11FORMAT target, 1597 void *closure); 1598 #endif 1599 1600 static void getSelectionValue(CLIPBACKEND *pCtx, CLIPX11FORMAT format, 1601 CLIPREADX11CBREQ *pReq) 1602 { 1603 #ifndef TESTCASE 1604 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx, "CLIPBOARD"), 1605 clipAtomForX11Format(pCtx, format), 1606 cbConvertX11CB, 1607 reinterpret_cast<XtPointer>(pReq), 1608 CurrentTime); 1609 #else 1610 testRequestData(pCtx, format, (void *)pReq); 1611 #endif 1612 } 1613 1565 1614 /** Worker function for ClipRequestDataFromX11 which runs on the event 1566 1615 * thread. */ 1567 static void vboxClipboardReadX11Worker( XtPointerpUserData,1568 XtIntervalId * /* interval */)1616 static void vboxClipboardReadX11Worker(void *pUserData, 1617 void * /* interval */) 1569 1618 { 1570 1619 CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *)pUserData; … … 1590 1639 /* Send out a request for the data to the current clipboard 1591 1640 * owner */ 1592 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx, "CLIPBOARD"), 1593 clipAtomForX11Format(pCtx, pCtx->X11TextFormat), 1594 clipConvertX11CB, 1595 reinterpret_cast<XtPointer>(pReq), 1596 CurrentTime); 1641 getSelectionValue(pCtx, pCtx->X11TextFormat, pReq); 1597 1642 } 1598 1643 else if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_BITMAP) … … 1605 1650 /* Send out a request for the data to the current clipboard 1606 1651 * owner */ 1607 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx, "CLIPBOARD"), 1608 clipAtomForX11Format(pCtx, 1609 pCtx->X11BitmapFormat), 1610 clipConvertX11CB, 1611 reinterpret_cast<XtPointer>(pReq), 1612 CurrentTime); 1652 getSelectionValue(pCtx, pCtx->X11BitmapFormat, pReq); 1613 1653 } 1614 1654 else … … 1677 1717 /* For the purpose of the test case, we just execute the procedure to be 1678 1718 * scheduled, as we are running single threaded. */ 1679 void clipQueueToEventThread(CLIPBACKEND *pCtx, 1680 XtTimerCallbackProc proc, 1681 XtPointer client_data) 1719 void testQueueToEventThread(void (*proc)(void *, void *), 1720 void *client_data) 1682 1721 { 1683 1722 proc(client_data, NULL); … … 1800 1839 } 1801 1840 1841 /* Take a request for the targets we are currently offering. */ 1842 static CLIPX11FORMAT g_selTargets[10] = { 0 }; 1843 static size_t g_cTargets = 0; 1844 1845 void testRequestTargets(CLIPBACKEND* pCtx) 1846 { 1847 clipUpdateX11Targets(pCtx, g_selTargets, g_cTargets); 1848 } 1849 1802 1850 /* The current values of the X selection, which will be returned to the 1803 1851 * XtGetSelectionValue callback. */ 1804 static Atom g_selTarget[1] = { 0 };1805 1852 static Atom g_selType = 0; 1806 1853 static const void *g_pSelData = NULL; 1807 1854 static unsigned long g_cSelData = 0; 1808 1855 static int g_selFormat = 0; 1809 static bool g_fTargetsTimeout = false; 1810 static bool g_fTargetsFailure = false; 1811 1812 void XtGetSelectionValue(Widget widget, Atom selection, Atom target, 1813 XtSelectionCallbackProc callback, 1814 XtPointer closure, Time time) 1856 1857 void testRequestData(CLIPBACKEND* pCtx, CLIPX11FORMAT target, void *closure) 1815 1858 { 1816 1859 unsigned long count = 0; 1817 1860 int format = 0; 1818 Atom type = XA_STRING; 1819 if ( ( selection != XInternAtom(NULL, "PRIMARY", 0) 1820 && selection != XInternAtom(NULL, "CLIPBOARD", 0) 1821 && selection != XInternAtom(NULL, "TARGETS", 0)) 1822 || ( target != g_selTarget[0] 1823 && target != XInternAtom(NULL, "TARGETS", 0))) 1824 { 1825 /* Otherwise this is probably a caller error. */ 1826 Assert(target != g_selTarget[0]); 1827 callback(widget, closure, &selection, &type, NULL, &count, &format); 1828 /* Could not convert to target. */ 1861 if (target != g_selTargets[0]) 1862 { 1863 clipConvertX11CB(closure, NULL, 0); /* Could not convert to target. */ 1829 1864 return; 1830 1865 } 1831 XtPointer pValue = NULL; 1832 if (target == XInternAtom(NULL, "TARGETS", 0)) 1833 { 1834 if (g_fTargetsFailure) 1835 pValue = NULL; 1836 else 1837 pValue = (XtPointer) RTMemDup(&g_selTarget, sizeof(g_selTarget)); 1838 type = g_fTargetsTimeout ? XT_CONVERT_FAIL : XA_ATOM; 1839 count = g_fTargetsFailure ? 0 : RT_ELEMENTS(g_selTarget); 1840 format = 32; 1841 } 1842 else 1843 { 1844 pValue = (XtPointer) g_pSelData ? RTMemDup(g_pSelData, g_cSelData) 1845 : NULL; 1846 type = g_selType; 1847 count = g_pSelData ? g_cSelData : 0; 1848 format = g_selFormat; 1849 } 1866 void *pValue = NULL; 1867 pValue = g_pSelData ? RTMemDup(g_pSelData, g_cSelData) : NULL; 1868 count = g_pSelData ? g_cSelData : 0; 1869 format = g_selFormat; 1850 1870 if (!pValue) 1851 1871 { … … 1853 1873 format = 0; 1854 1874 } 1855 callback(widget, closure, &selection, &type, pValue, 1856 &count, &format); 1875 clipConvertX11CB(closure, pValue, count * format / 8); 1857 1876 } 1858 1877 … … 1940 1959 { 1941 1960 Atom clipAtom = XInternAtom(NULL, "CLIPBOARD", 0); 1942 g_selTarget[0] = XInternAtom(NULL, pcszTarget, 0); 1961 g_selTargets[0] = clipFindX11FormatByAtomText(pcszTarget); 1962 g_cTargets = 1; 1943 1963 g_selType = type; 1944 1964 g_pSelData = data; … … 1948 1968 g_pfnSelLose(TEST_WIDGET, &clipAtom); 1949 1969 g_ownsSel = false; 1950 g_fTargetsTimeout = false;1951 g_fTargetsFailure = false;1952 1970 } 1953 1971 1954 1972 static void clipSendTargetUpdate(CLIPBACKEND *pCtx) 1955 1973 { 1956 CLIPX11FORMAT selTarget[RT_ELEMENTS(g_selTarget)]; 1957 unsigned i, j; 1958 RT_ZERO(selTarget); 1959 for (i = 0; i < RT_ELEMENTS(g_selTarget); ++i) 1960 for (j = 0; j < RT_ELEMENTS(g_aFormats); ++j) 1961 if (XInternAtom(NULL, g_aFormats[j].pcszAtom, 0) == g_selTarget[i]) 1962 selTarget[i] = j; 1963 clipUpdateX11Targets(pCtx, selTarget, RT_ELEMENTS(selTarget)); 1974 clipQueryX11CBFormats(pCtx); 1964 1975 } 1965 1976 1966 1977 /* Configure if and how the X11 TARGETS clipboard target will fail */ 1967 static void clipSetTargetsFailure(bool fTimeout, bool fFailure) 1968 { 1969 g_fTargetsTimeout = fTimeout; 1970 g_fTargetsFailure = fFailure; 1978 static void clipSetTargetsFailure(void) 1979 { 1980 g_cTargets = 0; 1971 1981 } 1972 1982 … … 2320 2330 /*** Timeout from X11 ***/ 2321 2331 RTTestSub(hTest, "X11 timeout"); 2322 clipSetSelectionValues("UTF8_STRING", XT_CONVERT_FAIL, "hello world", 2323 sizeof("hello world"), 8); 2324 testStringFromX11(hTest, pCtx, "hello world", VERR_TIMEOUT); 2332 clipSetSelectionValues("UTF8_STRING", XT_CONVERT_FAIL, NULL,0, 8); 2333 testStringFromX11(hTest, pCtx, "", VERR_NO_DATA); 2325 2334 2326 2335 /*** No data in X11 clipboard ***/ … … 2360 2369 clipSetSelectionValues("UTF8_STRING", XA_STRING, "hello world", 2361 2370 sizeof("hello world"), 8); 2362 clipSetTargetsFailure( false, true);2371 clipSetTargetsFailure(); 2363 2372 Atom atom = XA_STRING; 2364 2373 long unsigned int cLen = 0;
Note:
See TracChangeset
for help on using the changeset viewer.