Changeset 18416 in vbox for trunk/src/VBox/HostServices
- Timestamp:
- Mar 27, 2009 5:26:44 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/x11-clipboard.cpp
r18408 r18416 95 95 } VBOXBITMAPFILEHEADER; 96 96 97 /** Global c lipboard context information*/97 /** Global context information used by the host clipboard subsystem */ 98 98 struct _VBOXCLIPBOARDCONTEXT 99 { 100 /** Since the clipboard data moves asynchronously, we use an event 101 * semaphore to wait for it. When a function issues a request for 102 * clipboard data it must wait for this semaphore, which is triggered 103 * when the data arrives. */ 104 RTSEMEVENT waitForData; 105 /** Who (if anyone) is currently waiting for data? Used for sanity 106 * checks when data arrives. */ 107 volatile uint32_t waiter; 108 /** This mutex is grabbed during any critical operations on the clipboard 109 * which might clash with others. */ 110 /** @todo this is still used in X11 backend parts, disentangle it. */ 111 RTSEMMUTEX clipboardMutex; 112 113 /** @todo both the VBox subsystem and the X11 backend need the following 114 * members, so we need to transfer them between the two contexts at 115 * an appropriate time */ 116 /** Format which we are reading from the X11 clipboard (valid during a 117 * request for its contents) */ 118 g_eClipboardFormats requestX11Format; 119 /** The buffer to write X11 clipboard data to (valid during a request 120 * for the clipboard contents) */ 121 void *requestBuffer; 122 /** The size of the buffer to write X11 clipboard data to (valid during 123 * a request for the clipboard contents) */ 124 unsigned requestBufferSize; 125 /** The size of the X11 clipboard data written to the buffer (valid 126 * during a request for the clipboard contents) */ 127 uint32_t *requestActualSize; 128 129 /** Pointer to the client data structure */ 130 VBOXCLIPBOARDCLIENTDATA *pClient; 131 }; 132 133 /** Global context information used by the X11 clipboard backend */ 134 struct _VBOXCLIPBOARDCONTEXTX11 99 135 { 100 136 /** The X Toolkit application context structure */ … … 127 163 std::vector<VBOXCLIPBOARDFORMAT> formatList; 128 164 129 /** Does the host or the guestcurrently own the clipboard? */165 /** Does VBox or X11 currently own the clipboard? */ 130 166 volatile enum g_eOwner eOwner; 131 167 132 /** What is the best text format the host has to offer? INVALID for none. */ 133 g_eClipboardFormats hostTextFormat; 134 /** Atom corresponding to the host text format */ 135 Atom atomHostTextFormat; 136 /** What is the best bitmap format the host has to offer? INVALID for none. */ 137 g_eClipboardFormats hostBitmapFormat; 138 /** Atom corresponding to the host Bitmap format */ 139 Atom atomHostBitmapFormat; 140 /** What formats does the guest have on offer? */ 141 int guestFormats; 142 /** Windows caches the clipboard data it receives. Since we have no way of knowing whether 143 that data is still valid, we always send a "data changed" message after a successful 144 transfer to invalidate the cache. */ 145 bool notifyGuest; 146 147 /** Since the clipboard data moves asynchronously, we use an event semaphore to wait for 148 it. When a function issues a request for clipboard data it must wait for this 149 semaphore, which is triggered when the data arrives. */ 168 /** What is the best text format X11 has to offer? INVALID for none. */ 169 g_eClipboardFormats X11TextFormat; 170 /** Atom corresponding to the X11 text format */ 171 Atom atomX11TextFormat; 172 /** What is the best bitmap format X11 has to offer? INVALID for none. */ 173 g_eClipboardFormats X11BitmapFormat; 174 /** Atom corresponding to the X11 Bitmap format */ 175 Atom atomX11BitmapFormat; 176 /** What formats does VBox have on offer? */ 177 int vboxFormats; 178 /** Windows hosts and guests cache the clipboard data they receive. 179 * Since we have no way of knowing whether their cache is still valid, 180 * we always send a "data changed" message after a successful transfer 181 * to invalidate it. */ 182 bool notifyVBox; 183 184 /** Since the clipboard data moves asynchronously, we use an event 185 * semaphore to wait for it. When a function issues a request for 186 * clipboard data it must wait for this semaphore, which is triggered 187 * when the data arrives. */ 150 188 RTSEMEVENT waitForData; 151 /** Who (if anyone) is currently waiting for data? Used for sanity checks 152 * when data arrives. */ 153 volatile uint32_t waiter; 154 /** This mutex is grabbed during any critical operations on the clipboard 155 * which might clash with others. */ 156 RTSEMMUTEX clipboardMutex; 157 158 /** Format which we are reading from the host clipboard (valid during a request for the 159 host clipboard) */ 160 g_eClipboardFormats requestHostFormat; 161 /** The guest buffer to write host clipboard data to (valid during a request for the host 162 clipboard) */ 189 190 /** Format which we are reading from the X11 clipboard (valid during a 191 * request for its contents) */ 192 g_eClipboardFormats requestX11Format; 193 /** The buffer to write X11 clipboard data to (valid during a request 194 * for the clipboard contents) */ 163 195 void *requestBuffer; 164 /** The size of the guest buffer to write host clipboard data to (valid during a request for165 the host clipboard) */196 /** The size of the buffer to write X11 clipboard data to (valid during 197 * a request for the clipboard contents) */ 166 198 unsigned requestBufferSize; 167 /** The size of the host clipboard data written to the guest buffer (valid during a request168 for the host clipboard) */199 /** The size of the X11 clipboard data written to the buffer (valid 200 * during a request for the clipboard contents) */ 169 201 uint32_t *requestActualSize; 170 171 /** Pointer to the client data structure */172 VBOXCLIPBOARDCLIENTDATA *pClient;173 202 }; 174 203 175 /* Only one client is supported. There seems to be no need for more clients. */ 176 static VBOXCLIPBOARDCONTEXT g_ctx; 177 178 /* Are we actually connected to the X11 servicer? */ 204 typedef struct _VBOXCLIPBOARDCONTEXTX11 VBOXCLIPBOARDCONTEXTX11; 205 206 /* Only one client is supported. There seems to be no need for more clients. 207 */ 208 static VBOXCLIPBOARDCONTEXT g_ctxHost; 209 static VBOXCLIPBOARDCONTEXTX11 g_ctxX11; 210 211 /* Are we actually connected to the X server? */ 179 212 static bool g_fHaveX11; 180 213 … … 200 233 * data from X11. */ 201 234 LogFunc(("host requested guest clipboard data after guest had disconnected.\n")); 202 pCtx->guestFormats = 0; 235 /** @todo call vboxClipboardFormatAnnounce to do this. */ 236 g_ctxX11.vboxFormats = 0; 203 237 pCtx->waiter = NONE; 204 238 return VERR_TIMEOUT; … … 230 264 * are still waiting after it acquires the mutex. After we release the 231 265 * mutex, we finally do our check to see whether the data was delivered. */ 232 RTSemMutexRequest(g_ctx .clipboardMutex, RT_INDEFINITE_WAIT);266 RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT); 233 267 pCtx->waiter = NONE; 234 RTSemMutexRelease(g_ctx .clipboardMutex);268 RTSemMutexRelease(g_ctxHost.clipboardMutex); 235 269 AssertLogRelRCSuccess(rc); 236 270 if (RT_FAILURE(rc)) … … 239 273 * to prove the contrary. */ 240 274 RTMemFree(pClient->data.pv); 241 g_ctx.pClient->data.pv = 0; 242 g_ctx.pClient->data.cb = 0; 243 g_ctx.pClient->data.u32Format = 0; 244 pCtx->guestFormats = 0; 275 g_ctxHost.pClient->data.pv = 0; 276 g_ctxHost.pClient->data.cb = 0; 277 g_ctxHost.pClient->data.u32Format = 0; 278 /** @todo call vboxClipboardFormatAnnounce to do this. */ 279 g_ctxX11.vboxFormats = 0; 245 280 return rc; 246 281 } … … 250 285 *ppv = pClient->data.pv; 251 286 *pcb = pClient->data.cb; 252 g_ctx .pClient->data.pv = 0;253 g_ctx .pClient->data.cb = 0;254 g_ctx .pClient->data.u32Format = 0;287 g_ctxHost.pClient->data.pv = 0; 288 g_ctxHost.pClient->data.cb = 0; 289 g_ctxHost.pClient->data.u32Format = 0; 255 290 return VINF_SUCCESS; 256 291 } … … 298 333 /* We need to do this whether we succeed or fail. */ 299 334 XtFree(reinterpret_cast<char *>(pValue)); 300 RTSemEventSignal(g_ctx .waitForData);335 RTSemEventSignal(g_ctxX11.waitForData); 301 336 LogFlowFunc(("Returning. Status is %Rrc\n", rc)); 302 337 } … … 350 385 XtFree(reinterpret_cast<char *>(pValue)); 351 386 RTUtf16Free(pu16SrcText); 352 RTSemEventSignal(g_ctx .waitForData);387 RTSemEventSignal(g_ctxX11.waitForData); 353 388 LogFlowFunc(("Returning. Status is %Rrc", rc)); 354 389 } … … 384 419 /* First convert the compound text to Utf8 */ 385 420 property.value = reinterpret_cast<unsigned char *>(pValue); 386 property.encoding = g_ctx .atomCText;421 property.encoding = g_ctxX11.atomCText; 387 422 property.format = 8; 388 423 property.nitems = cbSrcLen; 389 424 #ifdef RT_OS_SOLARIS 390 int xrc = XmbTextPropertyToTextList(XtDisplay(g_ctx .widget), &property, &ppu8SrcText, &cProps);425 int xrc = XmbTextPropertyToTextList(XtDisplay(g_ctxX11.widget), &property, &ppu8SrcText, &cProps); 391 426 #else 392 int xrc = Xutf8TextPropertyToTextList(XtDisplay(g_ctx .widget), &property, &ppu8SrcText, &cProps);427 int xrc = Xutf8TextPropertyToTextList(XtDisplay(g_ctxX11.widget), &property, &ppu8SrcText, &cProps); 393 428 #endif 394 429 XtFree(reinterpret_cast<char *>(pValue)); … … 432 467 RTUtf16Free(pu16SrcText); 433 468 LogFlowFunc(("Returning. Status is %Rrc\n", rc)); 434 RTSemEventSignal(g_ctx .waitForData);469 RTSemEventSignal(g_ctxX11.waitForData); 435 470 } 436 471 … … 486 521 } 487 522 XtFree(reinterpret_cast<char *>(pValue)); 488 RTSemEventSignal(g_ctx .waitForData);523 RTSemEventSignal(g_ctxX11.waitForData); 489 524 LogFlowFunc(("Returning. Status is %Rrc\n", rc)); 490 525 } … … 503 538 { 504 539 LogFlowFunc(("pClientData=%p, *pcLen=%lu, *piFormat=%d\n", pClientData, *pcLen, *piFormat)); 505 LogFlowFunc(("g_ctx .requestHostFormat=%d, g_ctx.requestBufferSize=%d\n",506 g_ctx .requestHostFormat, g_ctx.requestBufferSize));540 LogFlowFunc(("g_ctxHost.requestX11Format=%d, g_ctxHost.requestBufferSize=%d\n", 541 g_ctxHost.requestX11Format, g_ctxHost.requestBufferSize)); 507 542 unsigned cTextLen = (*pcLen) * (*piFormat) / 8; 508 543 /* The X Toolkit may have failed to get the clipboard selection for us. */ … … 514 549 /* We grab this mutex whenever an asynchronous clipboard operation completes and while 515 550 disconnecting a client from the clipboard to stop these operations colliding. */ 516 RTSemMutexRequest(g_ctx .clipboardMutex, RT_INDEFINITE_WAIT);517 if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctx .pClient)551 RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT); 552 if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctxHost.pClient) 518 553 { 519 554 /* If the client is no longer connected, just return. */ 520 555 XtFree(reinterpret_cast<char *>(pValue)); 521 556 LogFlowFunc(("client is no longer connected, returning\n")); 522 RTSemMutexRelease(g_ctx .clipboardMutex);557 RTSemMutexRelease(g_ctxHost.clipboardMutex); 523 558 return; 524 559 } 525 560 526 561 /* In which format did we request the clipboard data? */ 527 switch (g_ctx .requestHostFormat)562 switch (g_ctxHost.requestX11Format) 528 563 { 529 564 case UTF16: 530 vboxClipboardGetUtf16(pValue, cTextLen / 2, g_ctx .requestBuffer, g_ctx.requestBufferSize,531 g_ctx .requestActualSize);565 vboxClipboardGetUtf16(pValue, cTextLen / 2, g_ctxHost.requestBuffer, g_ctxHost.requestBufferSize, 566 g_ctxHost.requestActualSize); 532 567 break; 533 568 case CTEXT: 534 vboxClipboardGetCTextFromX11(pValue, cTextLen, g_ctx .requestBuffer, g_ctx.requestBufferSize,535 g_ctx .requestActualSize);569 vboxClipboardGetCTextFromX11(pValue, cTextLen, g_ctxHost.requestBuffer, g_ctxHost.requestBufferSize, 570 g_ctxHost.requestActualSize); 536 571 break; 537 572 case UTF8: … … 541 576 char *pu8SourceText = reinterpret_cast<char *>(pValue); 542 577 543 if ((g_ctx .requestHostFormat == UTF8)578 if ((g_ctxHost.requestX11Format == UTF8) 544 579 && (RTStrUniLenEx(pu8SourceText, *pcLen, &cStringLen) == VINF_SUCCESS)) 545 580 { 546 vboxClipboardGetUtf8FromX11(pValue, cTextLen, g_ctx .requestBuffer, g_ctx.requestBufferSize,547 g_ctx .requestActualSize);581 vboxClipboardGetUtf8FromX11(pValue, cTextLen, g_ctxHost.requestBuffer, g_ctxHost.requestBufferSize, 582 g_ctxHost.requestActualSize); 548 583 break; 549 584 } 550 585 else 551 586 { 552 vboxClipboardGetLatin1FromX11(pValue, cTextLen, g_ctx .requestBuffer, g_ctx.requestBufferSize,553 g_ctx .requestActualSize);587 vboxClipboardGetLatin1FromX11(pValue, cTextLen, g_ctxHost.requestBuffer, g_ctxHost.requestBufferSize, 588 g_ctxHost.requestActualSize); 554 589 break; 555 590 } … … 558 593 LogFunc (("bad target format\n")); 559 594 XtFree(reinterpret_cast<char *>(pValue)); 560 RTSemMutexRelease(g_ctx .clipboardMutex);595 RTSemMutexRelease(g_ctxHost.clipboardMutex); 561 596 return; 562 597 } 563 g_ctx .notifyGuest= true;564 RTSemMutexRelease(g_ctx .clipboardMutex);598 g_ctxX11.notifyVBox = true; 599 RTSemMutexRelease(g_ctxHost.clipboardMutex); 565 600 } 566 601 … … 591 626 /* We grab this mutex whenever an asynchronous clipboard operation completes and while 592 627 disconnecting a client from the clipboard to stop these operations colliding. */ 593 RTSemMutexRequest(g_ctx .clipboardMutex, RT_INDEFINITE_WAIT);594 if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctx .pClient)628 RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT); 629 if (reinterpret_cast<VBOXCLIPBOARDCLIENTDATA *>(pClientData) != g_ctxHost.pClient) 595 630 { 596 631 /* If the client is no longer connected, just return. */ 597 632 LogFlowFunc(("client is no longer connected, returning\n")); 598 RTSemMutexRelease(g_ctx .clipboardMutex);633 RTSemMutexRelease(g_ctxHost.clipboardMutex); 599 634 return; 600 635 } … … 602 637 for (unsigned i = 0; i < cAtoms; ++i) 603 638 { 604 for (unsigned j = 0; j != g_ctx .formatList.size(); ++j)605 if (g_ctx .formatList[j].atom == atomTargets[i])639 for (unsigned j = 0; j != g_ctxX11.formatList.size(); ++j) 640 if (g_ctxX11.formatList[j].atom == atomTargets[i]) 606 641 { 607 if (eBestTarget < g_ctx .formatList[j].format)642 if (eBestTarget < g_ctxX11.formatList[j].format) 608 643 { 609 eBestTarget = g_ctx .formatList[j].format;610 atomBestTarget = g_ctx .formatList[j].atom;644 eBestTarget = g_ctxX11.formatList[j].format; 645 atomBestTarget = g_ctxX11.formatList[j].atom; 611 646 } 612 647 break; … … 614 649 if (g_debugClipboard) 615 650 { 616 char *szAtomName = XGetAtomName(XtDisplay(g_ctx .widget), atomTargets[i]);651 char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomTargets[i]); 617 652 if (szAtomName != 0) 618 653 { … … 623 658 } 624 659 } 625 g_ctx .atomHostTextFormat = atomBestTarget;626 if ((eBestTarget != g_ctx .hostTextFormat) || (g_ctx.notifyGuest== true))660 g_ctxX11.atomX11TextFormat = atomBestTarget; 661 if ((eBestTarget != g_ctxX11.X11TextFormat) || (g_ctxX11.notifyVBox == true)) 627 662 { 628 663 uint32_t u32Formats = 0; … … 631 666 if (atomBestTarget != None) 632 667 { 633 char *szAtomName = XGetAtomName(XtDisplay(g_ctx .widget), atomBestTarget);668 char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomBestTarget); 634 669 Log2 (("%s: switching to host text target %s. Available targets are:\n", 635 670 __PRETTY_FUNCTION__, szAtomName)); … … 641 676 for (unsigned i = 0; i < cAtoms; ++i) 642 677 { 643 char *szAtomName = XGetAtomName(XtDisplay(g_ctx .widget), atomTargets[i]);678 char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomTargets[i]); 644 679 if (szAtomName != 0) 645 680 { … … 649 684 } 650 685 } 651 g_ctx .hostTextFormat = eBestTarget;686 g_ctxX11.X11TextFormat = eBestTarget; 652 687 if (eBestTarget != INVALID) 653 688 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 654 vboxSvcClipboardReportMsg (g_ctx .pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,689 vboxSvcClipboardReportMsg (g_ctxHost.pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 655 690 u32Formats); 656 g_ctx .notifyGuest= false;691 g_ctxX11.notifyVBox = false; 657 692 } 658 693 XtFree(reinterpret_cast<char *>(pValue)); 659 RTSemMutexRelease(g_ctx .clipboardMutex);694 RTSemMutexRelease(g_ctxHost.clipboardMutex); 660 695 } 661 696 … … 670 705 Log3 (("%s: called\n", __PRETTY_FUNCTION__)); 671 706 /* Get the current clipboard contents */ 672 if (g_ctx .eOwner == X11 && g_ctx.pClient != 0)707 if (g_ctxX11.eOwner == X11 && g_ctxHost.pClient != 0) 673 708 { 674 709 Log3 (("%s: requesting the targets that the host clipboard offers\n", 675 710 __PRETTY_FUNCTION__)); 676 XtGetSelectionValue(g_ctx .widget, g_ctx.atomClipboard, g_ctx.atomTargets,677 vboxClipboardGetTargetsFromX11, reinterpret_cast<XtPointer>(g_ctx .pClient),711 XtGetSelectionValue(g_ctxX11.widget, g_ctxX11.atomClipboard, g_ctxX11.atomTargets, 712 vboxClipboardGetTargetsFromX11, reinterpret_cast<XtPointer>(g_ctxHost.pClient), 678 713 CurrentTime); 679 714 } 680 715 /* Re-arm our timer */ 681 XtAppAddTimeOut(g_ctx .appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0);716 XtAppAddTimeOut(g_ctxX11.appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0); 682 717 } 683 718 … … 689 724 VBOXCLIPBOARDFORMAT sFormat; 690 725 /* Get an atom from the X server for that target format */ 691 Atom atomFormat = XInternAtom(XtDisplay(g_ctx .widget), pszName, false);726 Atom atomFormat = XInternAtom(XtDisplay(g_ctxX11.widget), pszName, false); 692 727 sFormat.atom = atomFormat; 693 728 sFormat.format = eFormat; 694 729 sFormat.guestFormat = guestFormat; 695 g_ctx .formatList.push_back(sFormat);730 g_ctxX11.formatList.push_back(sFormat); 696 731 LogFlow (("vboxClipboardAddFormat: added format %s (%d)\n", pszName, eFormat)); 697 732 } … … 706 741 707 742 /* Set up a timer to poll the host clipboard */ 708 XtAppAddTimeOut(g_ctx .appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0);709 710 XtAppMainLoop(g_ctx .appContext);711 g_ctx .formatList.clear();743 XtAppAddTimeOut(g_ctxX11.appContext, 200 /* ms */, vboxClipboardPollX11ForTargets, 0); 744 745 XtAppMainLoop(g_ctxX11.appContext); 746 g_ctxX11.formatList.clear(); 712 747 LogRel(("Shared clipboard: host clipboard thread terminated successfully\n")); 713 748 return VINF_SUCCESS; … … 730 765 can't get an X11 display. */ 731 766 XtToolkitInitialize(); 732 g_ctx .appContext = XtCreateApplicationContext();733 // XtAppSetFallbackResources(g_ctx .appContext, szFallbackResources);734 pDisplay = XtOpenDisplay(g_ctx .appContext, 0, 0, "VBoxClipboard", 0, 0, &cArgc, &pcArgv);767 g_ctxX11.appContext = XtCreateApplicationContext(); 768 // XtAppSetFallbackResources(g_ctxX11.appContext, szFallbackResources); 769 pDisplay = XtOpenDisplay(g_ctxX11.appContext, 0, 0, "VBoxClipboard", 0, 0, &cArgc, &pcArgv); 735 770 if (NULL == pDisplay) 736 771 { … … 740 775 if (RT_SUCCESS(rc)) 741 776 { 742 g_ctx .widget = XtVaAppCreateShell(0, "VBoxClipboard", applicationShellWidgetClass, pDisplay,777 g_ctxX11.widget = XtVaAppCreateShell(0, "VBoxClipboard", applicationShellWidgetClass, pDisplay, 743 778 XtNwidth, 1, XtNheight, 1, NULL); 744 if (NULL == g_ctx .widget)779 if (NULL == g_ctxX11.widget) 745 780 { 746 781 LogRel(("Shared clipboard: failed to construct the X11 window for the host clipboard manager.\n")); … … 750 785 if (RT_SUCCESS(rc)) 751 786 { 752 XtSetMappedWhenManaged(g_ctx .widget, false);753 XtRealizeWidget(g_ctx .widget);787 XtSetMappedWhenManaged(g_ctxX11.widget, false); 788 XtRealizeWidget(g_ctxX11.widget); 754 789 755 790 /* Get hold of the atoms which we need */ 756 g_ctx .atomClipboard = XInternAtom(XtDisplay(g_ctx.widget), "CLIPBOARD", false /* only_if_exists */);757 g_ctx .atomPrimary = XInternAtom(XtDisplay(g_ctx.widget), "PRIMARY", false);758 g_ctx .atomTargets = XInternAtom(XtDisplay(g_ctx.widget), "TARGETS", false);759 g_ctx .atomMultiple = XInternAtom(XtDisplay(g_ctx.widget), "MULTIPLE", false);760 g_ctx .atomTimestamp = XInternAtom(XtDisplay(g_ctx.widget), "TIMESTAMP", false);761 g_ctx .atomUtf16 = XInternAtom(XtDisplay(g_ctx.widget),791 g_ctxX11.atomClipboard = XInternAtom(XtDisplay(g_ctxX11.widget), "CLIPBOARD", false /* only_if_exists */); 792 g_ctxX11.atomPrimary = XInternAtom(XtDisplay(g_ctxX11.widget), "PRIMARY", false); 793 g_ctxX11.atomTargets = XInternAtom(XtDisplay(g_ctxX11.widget), "TARGETS", false); 794 g_ctxX11.atomMultiple = XInternAtom(XtDisplay(g_ctxX11.widget), "MULTIPLE", false); 795 g_ctxX11.atomTimestamp = XInternAtom(XtDisplay(g_ctxX11.widget), "TIMESTAMP", false); 796 g_ctxX11.atomUtf16 = XInternAtom(XtDisplay(g_ctxX11.widget), 762 797 "text/plain;charset=ISO-10646-UCS-2", false); 763 g_ctx .atomUtf8 = XInternAtom(XtDisplay(g_ctx.widget), "UTF_STRING", false);798 g_ctxX11.atomUtf8 = XInternAtom(XtDisplay(g_ctxX11.widget), "UTF_STRING", false); 764 799 /* And build up the vector of supported formats */ 765 g_ctx .atomCText = XInternAtom(XtDisplay(g_ctx.widget), "COMPOUND_TEXT", false);800 g_ctxX11.atomCText = XInternAtom(XtDisplay(g_ctxX11.widget), "COMPOUND_TEXT", false); 766 801 /* And build up the vector of supported formats */ 767 802 if (!g_testUtf8 && !g_testCText) … … 835 870 836 871 LogRel(("Initializing host clipboard service\n")); 837 RTSemEventCreate(&g_ctx.waitForData); 838 RTSemMutexCreate(&g_ctx.clipboardMutex); 872 RTSemEventCreate(&g_ctxHost.waitForData); 873 RTSemEventCreate(&g_ctxX11.waitForData); 874 RTSemMutexCreate(&g_ctxHost.clipboardMutex); 839 875 rc = vboxClipboardInitX11(); 840 876 if (RT_SUCCESS(rc)) 841 877 { 842 rc = RTThreadCreate(&g_ctx .thread, vboxClipboardThread, 0, 0,878 rc = RTThreadCreate(&g_ctxX11.thread, vboxClipboardThread, 0, 0, 843 879 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 844 880 if (RT_FAILURE(rc)) … … 847 883 if (RT_FAILURE(rc)) 848 884 { 849 RTSemEventDestroy(g_ctx.waitForData); 850 RTSemMutexDestroy(g_ctx.clipboardMutex); 885 RTSemEventDestroy(g_ctxHost.waitForData); 886 RTSemEventDestroy(g_ctxX11.waitForData); 887 RTSemMutexDestroy(g_ctxHost.clipboardMutex); 851 888 } 852 889 return rc; … … 875 912 * cause any outstanding clipboard data requests from X11 to fail 876 913 * immediately. */ 877 g_ctx .pClient = NULL;878 if (g_ctx .eOwner == VB)914 g_ctxHost.pClient = NULL; 915 if (g_ctxX11.eOwner == VB) 879 916 /* X11 may be waiting for data from VBox. At this point it is no 880 917 * longer going to arrive, and we must release it to allow the event … … 883 920 * return "no data" to X11. Any subsequent attempts to get the data 884 921 * from VBox will fail immediately as the client reference is gone. */ 885 RTSemEventSignal(g_ctx .waitForData);922 RTSemEventSignal(g_ctxHost.waitForData); 886 923 /* Set the termination flag. This has been observed to block if it was set 887 924 * during a request for clipboard data coming from X11, so only we do it 888 925 * after releasing any such requests. */ 889 XtAppSetExitFlag(g_ctx .appContext);926 XtAppSetExitFlag(g_ctxX11.appContext); 890 927 /* Wake up the event loop */ 891 928 memset(&ev, 0, sizeof(ev)); 892 929 ev.xclient.type = ClientMessage; 893 930 ev.xclient.format = 8; 894 XSendEvent(XtDisplay(g_ctx .widget), XtWindow(g_ctx.widget), false, 0, &ev);895 XFlush(XtDisplay(g_ctx .widget));931 XSendEvent(XtDisplay(g_ctxX11.widget), XtWindow(g_ctxX11.widget), false, 0, &ev); 932 XFlush(XtDisplay(g_ctxX11.widget)); 896 933 do 897 934 { 898 rc = RTThreadWait(g_ctx .thread, 1000, &rcThread);935 rc = RTThreadWait(g_ctxX11.thread, 1000, &rcThread); 899 936 ++count; 900 937 Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5))); … … 910 947 * successfully. 911 948 */ 912 RTSemEventDestroy(g_ctx.waitForData); 913 RTSemMutexDestroy(g_ctx.clipboardMutex); 949 RTSemEventDestroy(g_ctxHost.waitForData); 950 RTSemEventDestroy(g_ctxX11.waitForData); 951 RTSemMutexDestroy(g_ctxHost.clipboardMutex); 914 952 AssertRC(rcThread); 915 953 } 916 954 else 917 955 LogRel(("vboxClipboardDestroy: rc=%Rrc\n", rc)); 918 XtCloseDisplay(XtDisplay(g_ctx .widget));956 XtCloseDisplay(XtDisplay(g_ctxX11.widget)); 919 957 LogFlowFunc(("returning.\n")); 920 958 } … … 939 977 940 978 /* Only one client is supported for now */ 941 AssertLogRelReturn(g_ctx .pClient == 0, VERR_NOT_SUPPORTED);942 943 pClient->pCtx = &g_ctx ;979 AssertLogRelReturn(g_ctxHost.pClient == 0, VERR_NOT_SUPPORTED); 980 981 pClient->pCtx = &g_ctxHost; 944 982 pClient->pCtx->pClient = pClient; 945 g_ctx .eOwner = X11;946 g_ctx .notifyGuest= true;983 g_ctxX11.eOwner = X11; 984 g_ctxX11.notifyVBox = true; 947 985 return VINF_SUCCESS; 948 986 } … … 966 1004 of synchronising, we tell the guest to empty its clipboard, and we set the cached 967 1005 flag so that we report formats to the guest next time we poll for them. */ 968 vboxSvcClipboardReportMsg (g_ctx .pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0);969 g_ctx .notifyGuest= true;1006 vboxSvcClipboardReportMsg (g_ctxHost.pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, 0); 1007 g_ctxX11.notifyVBox = true; 970 1008 971 1009 return VINF_SUCCESS; … … 987 1025 LogFlow(("vboxClipboardDisconnect\n")); 988 1026 989 RTSemMutexRequest(g_ctx .clipboardMutex, RT_INDEFINITE_WAIT);990 g_ctx .pClient = NULL;991 g_ctx .eOwner = NONE;992 g_ctx .hostTextFormat = INVALID;993 g_ctx .hostBitmapFormat = INVALID;994 RTSemMutexRelease(g_ctx .clipboardMutex);1027 RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT); 1028 g_ctxHost.pClient = NULL; 1029 g_ctxX11.eOwner = NONE; 1030 g_ctxX11.X11TextFormat = INVALID; 1031 g_ctxX11.X11BitmapFormat = INVALID; 1032 RTSemMutexRelease(g_ctxHost.clipboardMutex); 995 1033 } 996 1034 … … 1011 1049 unsigned long *pcLenReturn, int *piFormatReturn) 1012 1050 { 1013 unsigned uListSize = g_ctx .formatList.size();1051 unsigned uListSize = g_ctxX11.formatList.size(); 1014 1052 Atom *atomTargets = reinterpret_cast<Atom *>(XtMalloc((uListSize + 3) * sizeof(Atom))); 1015 1053 unsigned cTargets = 0; … … 1018 1056 for (unsigned i = 0; i < uListSize; ++i) 1019 1057 { 1020 if ( ((g_ctx .guestFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) != 0)1021 && (g_ctx .formatList[i].guestFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT))1058 if ( ((g_ctxX11.vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) != 0) 1059 && (g_ctxX11.formatList[i].guestFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)) 1022 1060 { 1023 atomTargets[cTargets] = g_ctx .formatList[i].atom;1061 atomTargets[cTargets] = g_ctxX11.formatList[i].atom; 1024 1062 ++cTargets; 1025 1063 } 1026 1064 } 1027 atomTargets[cTargets] = g_ctx .atomTargets;1028 atomTargets[cTargets + 1] = g_ctx .atomMultiple;1029 atomTargets[cTargets + 2] = g_ctx .atomTimestamp;1065 atomTargets[cTargets] = g_ctxX11.atomTargets; 1066 atomTargets[cTargets + 1] = g_ctxX11.atomMultiple; 1067 atomTargets[cTargets + 2] = g_ctxX11.atomTimestamp; 1030 1068 if (g_debugClipboard) 1031 1069 { 1032 1070 for (unsigned i = 0; i < cTargets + 3; i++) 1033 1071 { 1034 char *szAtomName = XGetAtomName(XtDisplay(g_ctx .widget), atomTargets[i]);1072 char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), atomTargets[i]); 1035 1073 if (szAtomName != 0) 1036 1074 { … … 1054 1092 1055 1093 /** 1056 * Satisfy a request from VBoxto convert the clipboard text to Utf16. We return non-zero1094 * Satisfy a request from X11 to convert the clipboard text to Utf16. We return non-zero 1057 1095 * terminated text. 1058 1096 * … … 1075 1113 1076 1114 LogFlowFunc (("called\n")); 1077 rc = vboxClipboardReadDataFromVBox(&g_ctx , VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);1115 rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox); 1078 1116 if ((RT_FAILURE(rc)) || (cbVBox == 0)) 1079 1117 { … … 1118 1156 LogFlowFunc (("converted string is %.*ls. Returning.\n", cwDestLen, pu16DestText)); 1119 1157 RTMemFree(pvVBox); 1120 *atomTypeReturn = g_ctx .atomUtf16;1158 *atomTypeReturn = g_ctxX11.atomUtf16; 1121 1159 *pValReturn = reinterpret_cast<XtPointer>(pu16DestText); 1122 1160 *pcLenReturn = cwDestLen; … … 1126 1164 1127 1165 /** 1128 * Satisfy a request from the hostto convert the clipboard text to Utf8.1166 * Satisfy a request from X11 to convert the clipboard text to Utf8. 1129 1167 * 1130 1168 * @returns true if we successfully convert the data to the format requested, false otherwise. … … 1152 1190 LogFlowFunc (("called\n")); 1153 1191 /* Read the clipboard data from the guest. */ 1154 rc = vboxClipboardReadDataFromVBox(&g_ctx , VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);1192 rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox); 1155 1193 if ((rc != VINF_SUCCESS) || (cbVBox == 0)) 1156 1194 { … … 1216 1254 LogFlowFunc (("converted string is %.*s. Returning.\n", cbDestLen, pu8DestText)); 1217 1255 RTMemFree(pvVBox); 1218 *atomTypeReturn = g_ctx .atomUtf8;1256 *atomTypeReturn = g_ctxX11.atomUtf8; 1219 1257 *pValReturn = reinterpret_cast<XtPointer>(pu8DestText); 1220 1258 *pcLenReturn = cbDestLen; … … 1224 1262 1225 1263 /** 1226 * Satisfy a request from the hostto convert the clipboard text to COMPOUND_TEXT.1264 * Satisfy a request from X11 to convert the clipboard text to COMPOUND_TEXT. 1227 1265 * 1228 1266 * @returns true if we successfully convert the data to the format requested, false otherwise. … … 1251 1289 LogFlowFunc (("called\n")); 1252 1290 /* Read the clipboard data from the guest. */ 1253 rc = vboxClipboardReadDataFromVBox(&g_ctx , VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox);1291 rc = vboxClipboardReadDataFromVBox(&g_ctxHost, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pvVBox, &cbVBox); 1254 1292 if ((rc != VINF_SUCCESS) || (cbVBox == 0)) 1255 1293 { … … 1303 1341 /* And finally (!) convert the Utf8 text to compound text. */ 1304 1342 #ifdef RT_OS_SOLARIS 1305 rc = XmbTextListToTextProperty(XtDisplay(g_ctx .widget), &pu8DestText, 1,1343 rc = XmbTextListToTextProperty(XtDisplay(g_ctxX11.widget), &pu8DestText, 1, 1306 1344 XCompoundTextStyle, &property); 1307 1345 #else 1308 rc = Xutf8TextListToTextProperty(XtDisplay(g_ctx .widget), &pu8DestText, 1,1346 rc = Xutf8TextListToTextProperty(XtDisplay(g_ctxX11.widget), &pu8DestText, 1, 1309 1347 XCompoundTextStyle, &property); 1310 1348 #endif … … 1358 1396 LogFlowFunc(("\n")); 1359 1397 /* Drop requests that we receive too late. */ 1360 if (g_ctx .eOwner != VB)1361 return false; 1362 if ( (*atomSelection != g_ctx .atomClipboard)1363 && (*atomSelection != g_ctx .atomPrimary)1398 if (g_ctxX11.eOwner != VB) 1399 return false; 1400 if ( (*atomSelection != g_ctxX11.atomClipboard) 1401 && (*atomSelection != g_ctxX11.atomPrimary) 1364 1402 ) 1365 1403 { … … 1369 1407 if (g_debugClipboard) 1370 1408 { 1371 char *szAtomName = XGetAtomName(XtDisplay(g_ctx .widget), *atomTarget);1409 char *szAtomName = XGetAtomName(XtDisplay(g_ctxX11.widget), *atomTarget); 1372 1410 if (szAtomName != 0) 1373 1411 { … … 1380 1418 } 1381 1419 } 1382 if (*atomTarget == g_ctx .atomTargets)1420 if (*atomTarget == g_ctxX11.atomTargets) 1383 1421 { 1384 1422 eFormat = TARGETS; … … 1386 1424 else 1387 1425 { 1388 for (unsigned i = 0; i != g_ctx .formatList.size(); ++i)1426 for (unsigned i = 0; i != g_ctxX11.formatList.size(); ++i) 1389 1427 { 1390 if (g_ctx .formatList[i].atom == *atomTarget)1428 if (g_ctxX11.formatList[i].atom == *atomTarget) 1391 1429 { 1392 eFormat = g_ctx .formatList[i].format;1430 eFormat = g_ctxX11.formatList[i].format; 1393 1431 break; 1394 1432 } … … 1424 1462 { 1425 1463 LogFlowFunc (("called, giving VBox clipboard ownership\n")); 1426 g_ctx .eOwner = X11;1427 g_ctx .notifyGuest= true;1464 g_ctxX11.eOwner = X11; 1465 g_ctxX11.notifyVBox = true; 1428 1466 } 1429 1467 … … 1444 1482 return; 1445 1483 1446 pClient->pCtx->guestFormats = u32Formats;1484 g_ctxX11.vboxFormats = u32Formats; 1447 1485 LogFlowFunc (("u32Formats=%d\n", u32Formats)); 1448 1486 if (u32Formats == 0) … … 1452 1490 return; 1453 1491 } 1454 if (g_ctx .eOwner == VB)1492 if (g_ctxX11.eOwner == VB) 1455 1493 { 1456 1494 /* We already own the clipboard, so no need to grab it, especially as that can lead … … 1461 1499 } 1462 1500 Log2 (("%s: giving the guest clipboard ownership\n", __PRETTY_FUNCTION__)); 1463 g_ctx .eOwner = VB;1464 g_ctx .hostTextFormat = INVALID;1465 g_ctx .hostBitmapFormat = INVALID;1466 if (XtOwnSelection(g_ctx .widget, g_ctx.atomClipboard, CurrentTime, vboxClipboardConvertForX11,1501 g_ctxX11.eOwner = VB; 1502 g_ctxX11.X11TextFormat = INVALID; 1503 g_ctxX11.X11BitmapFormat = INVALID; 1504 if (XtOwnSelection(g_ctxX11.widget, g_ctxX11.atomClipboard, CurrentTime, vboxClipboardConvertForX11, 1467 1505 vboxClipboardReturnToX11, 0) != True) 1468 1506 { … … 1470 1508 /* We set this so that the guest gets notified when we take the clipboard, even if no 1471 1509 guest formats are found which we understand. */ 1472 g_ctx .notifyGuest= true;1473 g_ctx .eOwner = X11;1474 } 1475 XtOwnSelection(g_ctx .widget, g_ctx.atomPrimary, CurrentTime, vboxClipboardConvertForX11,1510 g_ctxX11.notifyVBox = true; 1511 g_ctxX11.eOwner = X11; 1512 } 1513 XtOwnSelection(g_ctxX11.widget, g_ctxX11.atomPrimary, CurrentTime, vboxClipboardConvertForX11, 1476 1514 NULL, 0); 1477 1515 LogFlowFunc(("returning\n")); … … 1510 1548 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 1511 1549 { 1512 if (g_ctx .hostTextFormat == INVALID)1550 if (g_ctxX11.X11TextFormat == INVALID) 1513 1551 { 1514 1552 /* No data available. */ … … 1519 1557 * requests from VBox are serialised and the second because X11 previously 1520 1558 * grabbed the clipboard, so it should not be waiting for data from us. */ 1521 AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctx .waiter, VB, NONE), VERR_DEADLOCK);1522 g_ctx .requestHostFormat = g_ctx.hostTextFormat;1523 g_ctx .requestBuffer = pv;1524 g_ctx .requestBufferSize = cb;1525 g_ctx .requestActualSize = pcbActual;1559 AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctxHost.waiter, VB, NONE), VERR_DEADLOCK); 1560 g_ctxHost.requestX11Format = g_ctxX11.X11TextFormat; 1561 g_ctxHost.requestBuffer = pv; 1562 g_ctxHost.requestBufferSize = cb; 1563 g_ctxHost.requestActualSize = pcbActual; 1526 1564 /* Initially set the size of the data read to zero in case we fail 1527 1565 * somewhere. */ 1528 1566 *pcbActual = 0; 1529 1567 /* Send out a request for the data to the current clipboard owner */ 1530 XtGetSelectionValue(g_ctx .widget, g_ctx.atomClipboard, g_ctx.atomHostTextFormat,1531 vboxClipboardGetDataFromX11, reinterpret_cast<XtPointer>(g_ctx .pClient),1568 XtGetSelectionValue(g_ctxX11.widget, g_ctxX11.atomClipboard, g_ctxX11.atomX11TextFormat, 1569 vboxClipboardGetDataFromX11, reinterpret_cast<XtPointer>(g_ctxHost.pClient), 1532 1570 CurrentTime); 1533 1571 /* When the data arrives, the vboxClipboardGetDataFromX11 callback will be called. The 1534 1572 callback will signal the event semaphore when it has processed the data for us. */ 1535 1573 1536 int rc = RTSemEventWait(g_ctx .waitForData, RT_INDEFINITE_WAIT);1574 int rc = RTSemEventWait(g_ctxX11.waitForData, RT_INDEFINITE_WAIT); 1537 1575 if (RT_FAILURE(rc)) 1538 1576 { 1539 g_ctx .waiter = NONE;1577 g_ctxHost.waiter = NONE; 1540 1578 return rc; 1541 1579 } 1542 g_ctx .waiter = NONE;1580 g_ctxHost.waiter = NONE; 1543 1581 } 1544 1582 else … … 1574 1612 /* Grab the mutex and check that X11 is still waiting for the data before 1575 1613 * delivering it. See the explanation in vboxClipboardReadDataFromVBox. */ 1576 RTSemMutexRequest(g_ctx .clipboardMutex, RT_INDEFINITE_WAIT);1577 if (g_ctx .waiter == X11 && cb > 0)1614 RTSemMutexRequest(g_ctxHost.clipboardMutex, RT_INDEFINITE_WAIT); 1615 if (g_ctxHost.waiter == X11 && cb > 0) 1578 1616 { 1579 1617 pClient->data.pv = RTMemAlloc (cb); … … 1586 1624 } 1587 1625 } 1588 RTSemMutexRelease(g_ctx .clipboardMutex);1589 1590 RTSemEventSignal(g_ctx .waitForData);1591 } 1592 1626 RTSemMutexRelease(g_ctxHost.clipboardMutex); 1627 1628 RTSemEventSignal(g_ctxHost.waitForData); 1629 } 1630
Note:
See TracChangeset
for help on using the changeset viewer.