Changeset 19219 in vbox for trunk/src/VBox
- Timestamp:
- Apr 27, 2009 3:53:25 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r19169 r19219 24 24 25 25 #include <errno.h> 26 #include <vector>27 26 28 27 #include <unistd.h> … … 58 57 59 58 /** The different clipboard formats which we support. */ 60 enum g_eClipboardFormats59 enum CLIPFORMAT 61 60 { 62 61 INVALID = 0, … … 66 65 }; 67 66 68 /** The X11 clipboard uses several names for the same format. This 69 * structure maps an X11 name to a format. */ 70 typedef struct { 71 Atom atom; 72 g_eClipboardFormats format; 73 unsigned guestFormat; 74 } VBOXCLIPBOARDFORMAT; 67 /** The table mapping X11 names to data formats and to the corresponding 68 * VBox clipboard formats (currently only Unicode) */ 69 static struct _CLIPFORMATTABLE 70 { 71 /** The X11 atom name of the format (several names can match one format) 72 */ 73 const char *pcszAtom; 74 /** The format corresponding to the name */ 75 CLIPFORMAT enmFormat; 76 /** The corresponding VBox clipboard format */ 77 uint32_t u32VBoxFormat; 78 } g_aFormats[] = 79 { 80 { "UTF8_STRING", UTF8, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 81 { "text/plain;charset=UTF-8", UTF8, 82 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 83 { "text/plain;charset=utf-8", UTF8, 84 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 85 { "STRING", UTF8, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 86 { "TEXT", UTF8, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 87 { "text/plain", UTF8, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 88 { "COMPOUND_TEXT", CTEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT } 89 }; 75 90 76 91 /** Global context information used by the X11 clipboard backend */ … … 87 102 Widget widget; 88 103 89 /** X11 atom refering to the clipboard: CLIPBOARD */90 Atom atomClipboard;91 /** X11 atom refering to the selection: PRIMARY */92 Atom atomPrimary;93 /** X11 atom refering to the clipboard targets: TARGETS */94 Atom atomTargets;95 /** X11 atom refering to the clipboard multiple target: MULTIPLE */96 Atom atomMultiple;97 /** X11 atom refering to the clipboard timestamp target: TIMESTAMP */98 Atom atomTimestamp;99 /** X11 atom refering to the clipboard utf8 text format: UTF8_STRING */100 Atom atomUtf8;101 /** X11 atom refering to the clipboard compound text format: COMPOUND_TEXT */102 Atom atomCText;103 104 /** A list of the X11 formats which we support, mapped to our identifier for them, in the105 order we prefer to have them in. */106 std::vector<VBOXCLIPBOARDFORMAT> formatList;107 108 104 /** Does VBox currently own the clipboard? If so, we don't need to poll 109 105 * X11 for supported formats. */ … … 111 107 112 108 /** What is the best text format X11 has to offer? INVALID for none. */ 113 g_eClipboardFormatsX11TextFormat;109 CLIPFORMAT X11TextFormat; 114 110 /** Atom corresponding to the X11 text format */ 115 111 Atom atomX11TextFormat; 116 112 /** What is the best bitmap format X11 has to offer? INVALID for none. 117 113 */ 118 g_eClipboardFormatsX11BitmapFormat;114 CLIPFORMAT X11BitmapFormat; 119 115 /** Atom corresponding to the X11 Bitmap format */ 120 116 Atom atomX11BitmapFormat; … … 210 206 } 211 207 208 /** Convert an atom name string to an X11 atom, looking it up in a cache 209 * before asking the server */ 210 static Atom clipGetAtom(Widget widget, const char *pszName) 211 { 212 AssertPtrReturn(pszName, None); 213 Atom retval = None; 214 XrmValue nameVal, atomVal; 215 nameVal.addr = (char *) pszName; 216 nameVal.size = strlen(pszName); 217 atomVal.size = sizeof(Atom); 218 atomVal.addr = (char *) &retval; 219 XtConvertAndStore(widget, XtRString, &nameVal, XtRAtom, &atomVal); 220 return retval; 221 } 222 212 223 /* Are we actually connected to the X server? */ 213 224 static bool g_fHaveX11; … … 311 322 /* First convert the compound text to Utf8 */ 312 323 property.value = reinterpret_cast<unsigned char *>(pValue); 313 property.encoding = pCtx->atomCText;324 property.encoding = clipGetAtom(pCtx->widget, "COMPOUND_TEXT"); 314 325 property.format = 8; 315 326 property.nitems = cbSrcLen; … … 515 526 Atom *atomTargets = reinterpret_cast<Atom *>(pValue); 516 527 unsigned cAtoms = *pcLen; 517 g_eClipboardFormats eBestTarget = INVALID; 528 CLIPFORMAT enmBestTarget = INVALID; 529 CLIPFORMAT enmRequiredTarget = INVALID; 518 530 Atom atomBestTarget = None; 519 531 … … 529 541 } 530 542 543 /* Debugging stuff */ 544 if (g_testUtf8) 545 enmRequiredTarget = UTF8; 546 else if (g_testCText) 547 enmRequiredTarget = CTEXT; 548 531 549 for (unsigned i = 0; i < cAtoms; ++i) 532 550 { 533 for (unsigned j = 0; j != pCtx->formatList.size(); ++j) 534 if (pCtx->formatList[j].atom == atomTargets[i]) 551 for (unsigned j = 0; j < RT_ELEMENTS(g_aFormats); ++j) 552 { 553 Atom formatAtom = clipGetAtom(pCtx->widget, 554 g_aFormats[j].pcszAtom); 555 if (atomTargets[i] == formatAtom) 535 556 { 536 if (eBestTarget < pCtx->formatList[j].format) 557 if ( enmBestTarget < g_aFormats[j].enmFormat 558 /* debugging stuff */ 559 && ( enmRequiredTarget == INVALID 560 || enmRequiredTarget == g_aFormats[j].enmFormat)) 537 561 { 538 e BestTarget = pCtx->formatList[j].format;539 atomBestTarget = pCtx->formatList[j].atom;562 enmBestTarget = g_aFormats[j].enmFormat; 563 atomBestTarget = formatAtom; 540 564 } 541 565 break; 542 566 } 567 } 543 568 if (g_debugClipboard) 544 569 { … … 554 579 } 555 580 pCtx->atomX11TextFormat = atomBestTarget; 556 if ((e BestTarget != pCtx->X11TextFormat) || (pCtx->notifyVBox == true))581 if ((enmBestTarget != pCtx->X11TextFormat) || (pCtx->notifyVBox == true)) 557 582 { 558 583 uint32_t u32Formats = 0; … … 581 606 } 582 607 } 583 pCtx->X11TextFormat = e BestTarget;584 if (e BestTarget != INVALID)608 pCtx->X11TextFormat = enmBestTarget; 609 if (enmBestTarget != INVALID) 585 610 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 586 611 VBoxX11ClipboardReportX11Formats(pCtx->pFrontend, u32Formats); … … 609 634 Log3 (("%s: requesting the targets that the host clipboard offers\n", 610 635 __PRETTY_FUNCTION__)); 611 XtGetSelectionValue(pCtx->widget, pCtx->atomClipboard,612 pCtx->atomTargets,636 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), 637 clipGetAtom(pCtx->widget, "TARGETS"), 613 638 vboxClipboardGetTargetsFromX11, pCtx, 614 639 CurrentTime); … … 617 642 XtAppAddTimeOut(pCtx->appContext, 200 /* ms */, 618 643 vboxClipboardPollX11ForTargets, pCtx); 619 }620 621 /** We store information about the target formats we can handle in a global622 * vector for internal use.623 * @note X11 backend code.624 */625 static void vboxClipboardAddFormat(VBOXCLIPBOARDCONTEXTX11 *pCtx,626 const char *pszName,627 g_eClipboardFormats eFormat,628 unsigned guestFormat)629 {630 VBOXCLIPBOARDFORMAT sFormat;631 /* Get an atom from the X server for that target format */632 Atom atomFormat = XInternAtom(XtDisplay(pCtx->widget), pszName, false);633 sFormat.atom = atomFormat;634 sFormat.format = eFormat;635 sFormat.guestFormat = guestFormat;636 pCtx->formatList.push_back(sFormat);637 LogFlow (("vboxClipboardAddFormat: added format %s (%d)\n", pszName, eFormat));638 644 } 639 645 … … 654 660 while (XtAppGetExitFlag(pCtx->appContext) == FALSE) 655 661 XtAppProcessEvent(pCtx->appContext, XtIMAll); 656 pCtx->formatList.clear();657 662 LogRel(("Shared clipboard: host clipboard thread terminated successfully\n")); 658 663 return VINF_SUCCESS; … … 744 749 XtSetMappedWhenManaged(pCtx->widget, false); 745 750 XtRealizeWidget(pCtx->widget); 746 747 /* Get hold of the atoms which we need */748 pCtx->atomClipboard = XInternAtom(XtDisplay(pCtx->widget), "CLIPBOARD", false /* only_if_exists */);749 pCtx->atomPrimary = XInternAtom(XtDisplay(pCtx->widget), "PRIMARY", false);750 pCtx->atomTargets = XInternAtom(XtDisplay(pCtx->widget), "TARGETS", false);751 pCtx->atomMultiple = XInternAtom(XtDisplay(pCtx->widget), "MULTIPLE", false);752 pCtx->atomTimestamp = XInternAtom(XtDisplay(pCtx->widget), "TIMESTAMP", false);753 pCtx->atomUtf8 = XInternAtom(XtDisplay(pCtx->widget), "UTF_STRING", false);754 /* And build up the vector of supported formats */755 pCtx->atomCText = XInternAtom(XtDisplay(pCtx->widget), "COMPOUND_TEXT", false);756 /* And build up the vector of supported formats */757 if (!g_testCText)758 {759 vboxClipboardAddFormat(pCtx, "UTF8_STRING", UTF8,760 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);761 vboxClipboardAddFormat(pCtx, "text/plain;charset=UTF-8", UTF8,762 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);763 vboxClipboardAddFormat(pCtx, "text/plain;charset=utf-8", UTF8,764 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);765 vboxClipboardAddFormat(pCtx, "STRING", UTF8,766 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);767 vboxClipboardAddFormat(pCtx, "TEXT", UTF8,768 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);769 vboxClipboardAddFormat(pCtx, "text/plain", UTF8,770 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);771 }772 if (!g_testUtf8)773 vboxClipboardAddFormat(pCtx, "COMPOUND_TEXT", CTEXT,774 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);775 751 } 776 752 /* Create the pipes */ … … 949 925 int *piFormatReturn) 950 926 { 951 unsigned uListSize = pCtx->formatList.size();927 unsigned uListSize = RT_ELEMENTS(g_aFormats); 952 928 Atom *atomTargets = reinterpret_cast<Atom *>(XtMalloc((uListSize + 3) * sizeof(Atom))); 953 929 unsigned cTargets = 0; … … 956 932 for (unsigned i = 0; i < uListSize; ++i) 957 933 { 958 if ( ( (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) != 0)959 && ( pCtx->formatList[i].guestFormat934 if ( (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 935 && ( g_aFormats[i].u32VBoxFormat 960 936 == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)) 961 937 { 962 atomTargets[cTargets] = pCtx->formatList[i].atom; 938 atomTargets[cTargets] = clipGetAtom(pCtx->widget, 939 g_aFormats[i].pcszAtom); 963 940 ++cTargets; 964 941 } 965 942 } 966 atomTargets[cTargets] = pCtx->atomTargets;967 atomTargets[cTargets + 1] = pCtx->atomMultiple;968 atomTargets[cTargets + 2] = pCtx->atomTimestamp;943 atomTargets[cTargets] = clipGetAtom(pCtx->widget, "TARGETS"); 944 atomTargets[cTargets + 1] = clipGetAtom(pCtx->widget, "MULTIPLE"); 945 atomTargets[cTargets + 2] = clipGetAtom(pCtx->widget, "TIMESTAMP"); 969 946 if (g_debugClipboard) 970 947 { … … 1134 1111 LogFlowFunc (("converted string is %.*s. Returning.\n", cbDestLen, pu8DestText)); 1135 1112 RTMemFree(pvVBox); 1136 *atomTypeReturn = pCtx->atomUtf8;1113 *atomTypeReturn = clipGetAtom(pCtx->widget, "UTF8_STRING"); 1137 1114 *pValReturn = reinterpret_cast<XtPointer>(pu8DestText); 1138 1115 *pcLenReturn = cbDestLen; … … 1282 1259 int *piFormatReturn) 1283 1260 { 1284 g_eClipboardFormats eFormat = INVALID;1261 CLIPFORMAT enmFormat = INVALID; 1285 1262 VBOXCLIPBOARDCONTEXTX11 *pCtx = vboxClipboardFindContext(widget); 1286 1263 … … 1289 1266 if (!pCtx->fOwnsClipboard) 1290 1267 return false; 1291 if ( (*atomSelection != pCtx->atomClipboard)1292 && (*atomSelection != pCtx->atomPrimary)1268 if ( (*atomSelection != clipGetAtom(pCtx->widget, "CLIPBOARD")) 1269 && (*atomSelection != clipGetAtom(pCtx->widget, "PRIMARY")) 1293 1270 ) 1294 1271 { … … 1309 1286 } 1310 1287 } 1311 if (*atomTarget == pCtx->atomTargets)1312 { 1313 e Format = TARGETS;1288 if (*atomTarget == clipGetAtom(pCtx->widget, "TARGETS")) 1289 { 1290 enmFormat = TARGETS; 1314 1291 } 1315 1292 else 1316 1293 { 1317 for (unsigned i = 0; i != pCtx->formatList.size(); ++i) 1318 { 1319 if (pCtx->formatList[i].atom == *atomTarget) 1294 for (unsigned i = 0; i < RT_ELEMENTS(g_aFormats); ++i) 1295 { 1296 if (*atomTarget == clipGetAtom(pCtx->widget, 1297 g_aFormats[i].pcszAtom)) 1320 1298 { 1321 e Format = pCtx->formatList[i].format;1299 enmFormat = g_aFormats[i].enmFormat; 1322 1300 break; 1323 1301 } 1324 1302 } 1325 1303 } 1326 switch (e Format)1304 switch (enmFormat) 1327 1305 { 1328 1306 case TARGETS: … … 1391 1369 { 1392 1370 /* This is just an automatism, not a genuine anouncement */ 1393 XtDisownSelection(pCtx->widget, pCtx->atomClipboard, CurrentTime);1371 XtDisownSelection(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), CurrentTime); 1394 1372 pCtx->fOwnsClipboard = false; 1395 1373 LogFlowFunc(("returning\n")); … … 1397 1375 } 1398 1376 Log2 (("%s: giving the guest clipboard ownership\n", __PRETTY_FUNCTION__)); 1399 if (XtOwnSelection(pCtx->widget, pCtx->atomClipboard, CurrentTime,1377 if (XtOwnSelection(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), CurrentTime, 1400 1378 vboxClipboardConvertForX11, vboxClipboardReturnToX11, 1401 1379 0) == True) … … 1403 1381 pCtx->fOwnsClipboard = true; 1404 1382 /* Grab the middle-button paste selection too. */ 1405 XtOwnSelection(pCtx->widget, pCtx->atomPrimary, CurrentTime,1383 XtOwnSelection(pCtx->widget, clipGetAtom(pCtx->widget, "PRIMARY"), CurrentTime, 1406 1384 vboxClipboardConvertForX11, NULL, 0); 1407 1385 } … … 1475 1453 /* Send out a request for the data to the current clipboard 1476 1454 * owner */ 1477 XtGetSelectionValue(pCtx->widget, pCtx->atomClipboard,1455 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), 1478 1456 pCtx->atomX11TextFormat, 1479 1457 vboxClipboardGetDataFromX11, … … 1742 1720 int rc = VINF_SUCCESS; 1743 1721 int status = 0; 1722 g_debugClipboard = true; 1744 1723 /* We can't test anything without an X session, so just return success 1745 1724 * in that case. */
Note:
See TracChangeset
for help on using the changeset viewer.