VirtualBox

Changeset 19704 in vbox for trunk


Ignore:
Timestamp:
May 14, 2009 4:05:11 PM (16 years ago)
Author:
vboxsync
Message:

GuestHost/SharedClipboard/x11: more clean-ups

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp

    r19553 r19704  
    5555#include <VBox/HostServices/VBoxClipboardSvc.h>
    5656
     57static Atom clipGetAtom(Widget widget, const char *pszName);
     58
    5759/** The different clipboard formats which we support. */
    5860enum CLIPFORMAT
     
    7779} g_aFormats[] =
    7880{
     81    { "INVALID", INVALID, 0 },
    7982    { "UTF8_STRING", UTF8, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT },
    8083    { "text/plain;charset=UTF-8", UTF8,
     
    8891};
    8992
     93typedef unsigned CLIPX11FORMAT;
     94
     95enum
     96{
     97    NIL_CLIPX11FORMAT = 0,
     98    MAX_CLIP_X11_FORMATS = RT_ELEMENTS(g_aFormats)
     99};
     100
     101/** Return the atom corresponding to a supported X11 format.
     102 * @param widget a valid Xt widget
     103 */
     104static Atom clipAtomForX11Format(Widget widget, CLIPX11FORMAT format)
     105{
     106    return clipGetAtom(widget, g_aFormats[format].pcszAtom);
     107}
     108
     109/** Return the CLIPFORMAT corresponding to a supported X11 format. */
     110static CLIPFORMAT clipRealFormatForX11Format(CLIPX11FORMAT format)
     111{
     112    return g_aFormats[format].enmFormat;
     113}
     114
     115/** Return the atom corresponding to a supported X11 format. */
     116static uint32_t clipVBoxFormatForX11Format(CLIPX11FORMAT format)
     117{
     118    return g_aFormats[format].u32VBoxFormat;
     119}
     120
     121/** Lookup the X11 format matching a given X11 atom.
     122 * @returns the format on success, NIL_CLIPX11FORMAT on failure
     123 * @param   widget a valid Xt widget
     124 */
     125static CLIPX11FORMAT clipFindX11FormatByAtom(Widget widget, Atom atomFormat)
     126{
     127    for (unsigned i = 0; i < RT_ELEMENTS(g_aFormats); ++i)
     128        if (clipAtomForX11Format(widget, i) == atomFormat)
     129            return i;
     130    return NIL_CLIPX11FORMAT;
     131}
     132
     133/**
     134 * Enumerates supported X11 clipboard formats corresponding to a given VBox
     135 * format.
     136 * @returns the next matching X11 format in the list, or NIL_CLIPX11FORMAT if
     137 *          there are no more
     138 * @param lastFormat  The value returned from the last call of this function.
     139 *                    Use NIL_CLIPX11FORMAT to start the enumeration.
     140 */
     141static CLIPX11FORMAT clipNextX11Format(uint32_t u32VBoxFormat,
     142                                       CLIPX11FORMAT lastFormat)
     143{
     144    for (unsigned i = lastFormat + 1; i < RT_ELEMENTS(g_aFormats); ++i)
     145        if (clipVBoxFormatForX11Format(i) == u32VBoxFormat)
     146            return i;
     147    return NIL_CLIPX11FORMAT;
     148}
     149
    90150/** Global context information used by the X11 clipboard backend */
    91151struct _CLIPBACKEND
     
    93153    /** Opaque data structure describing the front-end. */
    94154    VBOXCLIPBOARDCONTEXT *pFrontend;
     155    /** Is an X server actually available? */
     156    bool fHaveX11;
    95157    /** The X Toolkit application context structure */
    96158    XtAppContext appContext;
     
    105167    bool fOwnsClipboard;
    106168
    107     /** What is the best text format X11 has to offer?  INVALID for none. */
    108     CLIPFORMAT X11TextFormat;
    109     /** Atom corresponding to the X11 text format */
    110     Atom atomX11TextFormat;
    111     /** What is the best bitmap format X11 has to offer?  INVALID for none.
    112      */
    113     CLIPFORMAT X11BitmapFormat;
    114     /** Atom corresponding to the X11 Bitmap format */
    115     Atom atomX11BitmapFormat;
     169    /** The best text format X11 has to offer, as an index into the formats
     170     * table */
     171    CLIPX11FORMAT X11TextFormat;
     172    /** The best bitmap format X11 has to offer, as an index into the formats
     173     * table */
     174    CLIPX11FORMAT X11BitmapFormat;
    116175    /** What formats does VBox have on offer? */
    117176    uint32_t vboxFormats;
     
    220279}
    221280
    222 /* Are we actually connected to the X server? */
    223 static bool g_fHaveX11;
     281/**
     282 * Send a message to VBox that new data is available to prevent the other
     283 * side of the shared clipboard from caching the data we send to it.  We need
     284 * to do this because we can't always tell ourselves when the clipboard
     285 * contents change on our side.
     286 */
     287static void clipInvalidateVBoxCache(CLIPBACKEND *pCtx)
     288{
     289    pCtx->notifyVBox = true;
     290}
     291
     292/**
     293 * Forget any information about valid data in the X11 clipboard.  To be used
     294 * when the X11 clipboard contents go away, or if an error occurs accessing
     295 * them.
     296 */
     297static void clipInvalidateX11Contents(CLIPBACKEND *pCtx)
     298{
     299        pCtx->X11TextFormat = 0;
     300        pCtx->X11BitmapFormat = 0;
     301}
    224302
    225303/**
     
    443521    /** The buffer to write X11 clipboard data to (valid during a request
    444522     * for the clipboard contents) */
    445     void *pv;
     523    void *mBuffer;
    446524    /** The size of the buffer to write X11 clipboard data to (valid during
    447525     * a request for the clipboard contents) */
    448     unsigned cb;
     526    unsigned mSize;
    449527    /** The size of the X11 clipboard data written to the buffer (valid
    450528     * during a request for the clipboard contents) */
    451     uint32_t *pcbActual;
     529    uint32_t *mActual;
    452530    /** The format VBox would like the data in */
    453     uint32_t format;
     531    uint32_t mFormat;
     532    /** The text format we requested from X11 if we requested text */
     533    CLIPX11FORMAT mTextFormat;
    454534    /** Return code for the request processing code */
    455     int rc;
     535    int mRC;
    456536    /** Semaphore which is signalled when the request is completed */
    457     RTSEMEVENT finished;
     537    RTSEMEVENT mSem;
    458538    /** The clipboard context this request is associated with */
    459     CLIPBACKEND *pCtx;
     539    CLIPBACKEND *mCtx;
    460540};
    461541
     
    474554{
    475555    CLIPX11CLIPBOARDREQ *pReq = (CLIPX11CLIPBOARDREQ *) pClientData;
    476     LogFlowFunc(("pReq->pv=%p, pReq->cb=%u, pReq->format=%02X, pReq->pCtx=%p\n",
    477                  pReq->pv, pReq->cb, pReq->format, pReq->pCtx));
    478     AssertPtr(pReq->pv);    /* We can't really return either... */
    479     AssertPtr(pReq->pCtx);
    480     Assert(pReq->format != 0);  /* sanity */
     556    LogFlowFunc(("pReq->mBuffer=%p, pReq->mSize=%u, pReq->mFormat=%02X, pReq->mTextFormat=%u, pReq->mCtx=%p\n",
     557                 pReq->mBuffer, pReq->mSize, pReq->mFormat,
     558                 pReq->mTextFormat, pReq->mCtx));
     559    AssertPtr(pReq->mBuffer);    /* We can't really return either... */
     560    AssertPtr(pReq->mCtx);
     561    Assert(pReq->mFormat != 0);  /* sanity */
    481562    int rc = VINF_SUCCESS;
    482     CLIPBACKEND *pCtx = pReq->pCtx;
     563    CLIPBACKEND *pCtx = pReq->mCtx;
    483564    unsigned cbSrc = (*pcLen) * (*piFormat) / 8;
    484565
    485     if (   pCtx->fOwnsClipboard
    486         /* We don't want to request data from ourselves! */
    487         || (pvSrc == NULL)
     566    if (pvSrc == NULL)
    488567        /* The clipboard selection may have changed before we could get it. */
    489        )
    490568        rc = VERR_NO_DATA;
    491569    else if (*atomType == XT_CONVERT_FAIL) /* Xt timeout */
    492570        rc = VERR_TIMEOUT;
    493     else
     571    else if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    494572    {
    495573        /* In which format is the clipboard data? */
    496         switch (pCtx->X11TextFormat)
     574        switch (clipRealFormatForX11Format(pReq->mTextFormat))
    497575        {
    498576            case CTEXT:
    499577                rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc,
    500                                        pReq->pv, pReq->cb, pReq->pcbActual);
     578                                       pReq->mBuffer, pReq->mSize,
     579                                       pReq->mActual);
    501580                break;
    502581            case UTF8:
     
    504583                /* If we are given broken Utf-8, we treat it as Latin1.  Is
    505584                 * this acceptable? */
    506                 if (RT_SUCCESS(RTStrValidateEncoding((char *)pvSrc)))
     585                if (RT_SUCCESS(RTStrValidateEncodingEx((char *)pvSrc, cbSrc,
     586                                                       0)))
    507587                    rc = clipUtf8ToWinTxt((const char *)pvSrc, cbSrc,
    508                                           pReq->pv, pReq->cb,
    509                                           pReq->pcbActual);
     588                                          pReq->mBuffer, pReq->mSize,
     589                                          pReq->mActual);
    510590                else
    511591                    rc = clipLatin1ToWinTxt((char *) pvSrc, cbSrc,
    512                                             pReq->pv, pReq->cb,
    513                                             pReq->pcbActual);
     592                                            pReq->mBuffer, pReq->mSize,
     593                                            pReq->mActual);
    514594                break;
    515595            }
     
    518598        }
    519599    }
     600    else
     601        rc = VERR_NOT_IMPLEMENTED;
    520602    if (RT_SUCCESS(rc))
    521603        /* The other end may cache the data, so invalidate it again. */
    522         pCtx->notifyVBox = true;
     604        clipInvalidateVBoxCache(pCtx);
    523605    else
    524     {
    525         pCtx->X11TextFormat = INVALID;
    526         pCtx->X11BitmapFormat = INVALID;
    527     }
     606        /* We failed to retrieve the X11 clipboard contents, mark them as
     607         * invalid. */
     608        clipInvalidateX11Contents(pCtx);
    528609    XtFree((char *)pvSrc);
    529     pReq->rc = rc;
    530     RTSemEventSignal(pReq->finished);
     610    pReq->mRC = rc;
     611    RTSemEventSignal(pReq->mSem);
    531612    LogFlowFunc(("rc=%Rrc\n", rc));
    532613}
     
    539620 *        poll for available targets.
    540621 */
    541 static void vboxClipboardGetTargetsFromX11(Widget,
    542                                            XtPointer pClientData,
    543                                            Atom * /* selection */,
    544                                            Atom *atomType,
    545                                            XtPointer pValue,
    546                                            long unsigned int *pcLen,
    547                                            int *piFormat)
     622static void clipConvertX11Targets(Widget, XtPointer pClientData,
     623                                  Atom * /* selection */, Atom *atomType,
     624                                  XtPointer pValue, long unsigned int *pcLen,
     625                                  int *piFormat)
    548626{
    549627    CLIPBACKEND *pCtx =
     
    552630    unsigned cAtoms = *pcLen;
    553631    CLIPFORMAT enmBestTarget = INVALID;
    554     Atom atomBestTarget = None;
     632    CLIPX11FORMAT bestFormat = NIL_CLIPX11FORMAT;
    555633
    556634    Log3 (("%s: called\n", __PRETTY_FUNCTION__));
     
    560638       )
    561639    {
    562         pCtx->atomX11TextFormat = None;
    563         pCtx->X11TextFormat = INVALID;
     640        clipInvalidateX11Contents(pCtx);
    564641        return;
    565642    }
     
    567644    for (unsigned i = 0; i < cAtoms; ++i)
    568645    {
    569         for (unsigned j = 0; j < RT_ELEMENTS(g_aFormats); ++j)
     646        CLIPX11FORMAT format = clipFindX11FormatByAtom(pCtx->widget,
     647                                                       atomTargets[i]);
     648        if (format != NIL_CLIPX11FORMAT)
    570649        {
    571             Atom formatAtom = clipGetAtom(pCtx->widget,
    572                                           g_aFormats[j].pcszAtom);
    573             if (atomTargets[i] == formatAtom)
     650            if (enmBestTarget < clipRealFormatForX11Format(format))
    574651            {
    575                 if (   enmBestTarget < g_aFormats[j].enmFormat)
    576                 {
    577                     enmBestTarget = g_aFormats[j].enmFormat;
    578                     atomBestTarget = formatAtom;
    579                 }
    580                 break;
     652                enmBestTarget = clipRealFormatForX11Format(format);
     653                bestFormat = format;
    581654            }
    582655        }
    583656    }
    584     pCtx->atomX11TextFormat = atomBestTarget;
    585     if ((enmBestTarget != pCtx->X11TextFormat) || (pCtx->notifyVBox == true))
    586     {
    587         uint32_t u32Formats = 0;
    588         pCtx->X11TextFormat = enmBestTarget;
    589         if (enmBestTarget != INVALID)
    590             u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    591         VBoxX11ClipboardReportX11Formats(pCtx->pFrontend, u32Formats);
     657    uint32_t u32VBoxFormat = clipVBoxFormatForX11Format(bestFormat);
     658    uint32_t u32OldVBoxFormat
     659            = clipVBoxFormatForX11Format(pCtx->X11TextFormat);
     660    /* Notify VBox if something has changed or if a forced notification was
     661     * scheduled. */
     662    if ((u32VBoxFormat != u32OldVBoxFormat) || (pCtx->notifyVBox))
     663    {
     664        VBoxX11ClipboardReportX11Formats(pCtx->pFrontend, u32VBoxFormat);
    592665        pCtx->notifyVBox = false;
    593666    }
     667    pCtx->X11TextFormat = bestFormat;
    594668    XtFree(reinterpret_cast<char *>(pValue));
    595669}
     
    597671enum { TIMER_FREQ = 200 /* ms */ };
    598672
    599 static void vboxClipboardPollX11ForTargets(XtPointer pUserData,
    600                                            XtIntervalId * /* hTimerId */);
     673static void clipPollX11CBFormats(XtPointer pUserData,
     674                                 XtIntervalId * /* hTimerId */);
    601675static void clipSchedulePoller(CLIPBACKEND *pCtx,
    602676                               XtTimerCallbackProc proc);
     
    618692 *        available.
    619693 */
    620 void vboxClipboardPollX11ForTargets(XtPointer pUserData,
    621                                     XtIntervalId * /* hTimerId */)
    622 {
    623     CLIPBACKEND *pCtx =
    624             reinterpret_cast<CLIPBACKEND *>(pUserData);
     694void clipPollX11CBFormats(XtPointer pUserData, XtIntervalId * /* hTimerId */)
     695{
     696    CLIPBACKEND *pCtx = (CLIPBACKEND *)pUserData;
    625697    Log3 (("%s: called\n", __PRETTY_FUNCTION__));
    626698    /* Get the current clipboard contents if we don't own it ourselves */
     
    629701        Log3 (("%s: requesting the targets that the host clipboard offers\n",
    630702               __PRETTY_FUNCTION__));
    631         XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"),
     703        XtGetSelectionValue(pCtx->widget,
     704                            clipGetAtom(pCtx->widget, "CLIPBOARD"),
    632705                            clipGetAtom(pCtx->widget, "TARGETS"),
    633                             vboxClipboardGetTargetsFromX11, pCtx,
     706                            clipConvertX11Targets, pCtx,
    634707                            CurrentTime);
    635708    }
    636709    /* Re-arm our timer */
    637     clipSchedulePoller(pCtx, vboxClipboardPollX11ForTargets);
     710    clipSchedulePoller(pCtx, clipPollX11CBFormats);
    638711}
    639712
     
    643716 * @note  X11 backend code.
    644717 */
    645 static int vboxClipboardThread(RTTHREAD self, void *pvUser)
     718static int clipEventThread(RTTHREAD self, void *pvUser)
    646719{
    647720    LogRel(("Shared clipboard: starting host clipboard thread\n"));
    648721
    649     CLIPBACKEND *pCtx =
    650             reinterpret_cast<CLIPBACKEND *>(pvUser);
     722    CLIPBACKEND *pCtx = (CLIPBACKEND *)pvUser;
    651723    while (XtAppGetExitFlag(pCtx->appContext) == FALSE)
    652724        XtAppProcessEvent(pCtx->appContext, XtIMAll);
     
    659731 * @note  X11 backend code.
    660732 */
    661 static void vboxClipboardUninitX11(CLIPBACKEND *pCtx)
     733static void clipUninit(CLIPBACKEND *pCtx)
    662734{
    663735    AssertPtrReturnVoid(pCtx);
     
    683755/** Worker function for stopping the clipboard which runs on the event
    684756 * thread. */
    685 static void vboxClipboardStopWorker(XtPointer pUserData, int * /* source */,
    686                                     XtInputId * /* id */)
     757static void clipStopEventThreadWorker(XtPointer pUserData, int * /* source */,
     758                                      XtInputId * /* id */)
    687759{
    688760   
     
    697769    XtAppSetExitFlag(pCtx->appContext);
    698770    pCtx->fOwnsClipboard = false;
    699     pCtx->X11TextFormat = INVALID;
    700     pCtx->X11BitmapFormat = INVALID;
     771    clipInvalidateX11Contents(pCtx);
    701772}
    702773
     
    704775 * @note  X11 backend code.
    705776 */
    706 static int vboxClipboardInitX11 (CLIPBACKEND *pCtx)
     777static int clipInit(CLIPBACKEND *pCtx)
    707778{
    708779    /* Create a window and make it a clipboard viewer. */
     
    714785    /* Make sure we are thread safe */
    715786    XtToolkitThreadInitialize();
    716     /* Set up the Clipbard application context and main window.  We call all these functions
    717        directly instead of calling XtOpenApplication() so that we can fail gracefully if we
    718        can't get an X11 display. */
     787    /* Set up the Clipbard application context and main window.  We call all
     788     * these functions directly instead of calling XtOpenApplication() so
     789     * that we can fail gracefully if we can't get an X11 display. */
    719790    XtToolkitInitialize();
    720791    pCtx->appContext = XtCreateApplicationContext();
     
    727798    if (RT_SUCCESS(rc))
    728799    {
    729         pCtx->widget = XtVaAppCreateShell(0, "VBoxClipboard", applicationShellWidgetClass, pDisplay,
    730                                           XtNwidth, 1, XtNheight, 1, NULL);
     800        pCtx->widget = XtVaAppCreateShell(0, "VBoxClipboard",
     801                                          applicationShellWidgetClass,
     802                                          pDisplay, XtNwidth, 1, XtNheight,
     803                                          1, NULL);
    731804        if (NULL == pCtx->widget)
    732805        {
     
    742815        XtRealizeWidget(pCtx->widget);
    743816        /* Set up a timer to poll the host clipboard */
    744         clipSchedulePoller(pCtx, vboxClipboardPollX11ForTargets);
     817        clipSchedulePoller(pCtx, clipPollX11CBFormats);
    745818    }
    746819    /* Create the pipes */
     
    752825        if (!XtAppAddInput(pCtx->appContext, pCtx->wakeupPipeRead,
    753826                           (XtPointer) XtInputReadMask,
    754                            vboxClipboardStopWorker, (XtPointer) pCtx))
     827                           clipStopEventThreadWorker, (XtPointer) pCtx))
    755828            rc = VERR_NO_MEMORY;  /* What failure means is not doc'ed. */
    756829    }
     
    758831        rc = RTErrConvertFromErrno(errno);
    759832    if (RT_FAILURE(rc))
    760         vboxClipboardUninitX11(pCtx);
     833        clipUninit(pCtx);
    761834    return rc;
    762835}
     
    766839 * @note  X11 backend code
    767840 */
    768 CLIPBACKEND *VBoxX11ClipboardConstructX11
    769                                  (VBOXCLIPBOARDCONTEXT *pFrontend)
     841CLIPBACKEND *VBoxX11ClipboardConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend)
    770842{
    771843    int rc;
     
    782854         */
    783855        LogRelFunc(("X11 DISPLAY variable not set -- disabling shared clipboard\n"));
    784         g_fHaveX11 = false;
     856        pCtx->fHaveX11 = false;
    785857        return pCtx;
    786858    }
    787859
    788     g_fHaveX11 = true;
     860    pCtx->fHaveX11 = true;
    789861
    790862    LogRel(("Initializing X11 clipboard backend\n"));
     
    803875     * Immediately return if we are not connected to the host X server.
    804876     */
    805     if (!g_fHaveX11)
     877    if (!pCtx->fHaveX11)
    806878        return;
    807879
     
    822894     * Immediately return if we are not connected to the host X server.
    823895     */
    824     if (!g_fHaveX11)
     896    if (!pCtx->fHaveX11)
    825897        return VINF_SUCCESS;
    826898
    827     rc = vboxClipboardInitX11(pCtx);
     899    rc = clipInit(pCtx);
    828900#ifndef TESTCASE
    829901    if (RT_SUCCESS(rc))
    830902    {
    831         rc = RTThreadCreate(&pCtx->thread, vboxClipboardThread, pCtx, 0,
     903        rc = RTThreadCreate(&pCtx->thread, clipEventThread, pCtx, 0,
    832904                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
    833905        if (RT_FAILURE(rc))
     
    838910    {
    839911        pCtx->fOwnsClipboard = false;
    840         pCtx->notifyVBox = true;
     912        clipInvalidateVBoxCache(pCtx);
    841913    }
    842914    return rc;
     
    863935     * Immediately return if we are not connected to the host X server.
    864936     */
    865     if (!g_fHaveX11)
     937    if (!pCtx->fHaveX11)
    866938        return VINF_SUCCESS;
    867939
     
    879951    else
    880952        LogRelFunc(("rc=%Rrc\n", rc));
    881     vboxClipboardUninitX11(pCtx);
     953    clipUninit(pCtx);
    882954    LogFlowFunc(("returning %Rrc.\n", rc));
    883955    return rc;
     
    899971 * @note  X11 backend code, called by the XtOwnSelection callback.
    900972 */
    901 static Boolean vboxClipboardConvertTargetsForX11(CLIPBACKEND
    902                                                                       *pCtx,
    903                                                  Atom *atomTypeReturn,
    904                                                  XtPointer *pValReturn,
    905                                                  unsigned long *pcLenReturn,
    906                                                  int *piFormatReturn)
    907 {
    908     unsigned uListSize = RT_ELEMENTS(g_aFormats);
    909     Atom *atomTargets = reinterpret_cast<Atom *>(XtMalloc((uListSize + 3) * sizeof(Atom)));
     973static Boolean clipCreateX11Targets(CLIPBACKEND *pCtx, Atom *atomTypeReturn,
     974                                    XtPointer *pValReturn,
     975                                    unsigned long *pcLenReturn,
     976                                    int *piFormatReturn)
     977{
     978    Atom *atomTargets = (Atom *)XtMalloc(  (MAX_CLIP_X11_FORMATS + 3)
     979                                         * sizeof(Atom));
    910980    unsigned cTargets = 0;
    911 
    912981    LogFlowFunc (("called\n"));
    913     for (unsigned i = 0; i < uListSize; ++i)
    914     {
    915         if (   (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    916             && (   g_aFormats[i].u32VBoxFormat
    917                 == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT))
     982    CLIPX11FORMAT format = NIL_CLIPX11FORMAT;
     983    do
     984    {
     985        format = clipNextX11Format(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     986                                   format);
     987        if (format != NIL_CLIPX11FORMAT)
    918988        {
    919             atomTargets[cTargets] = clipGetAtom(pCtx->widget,
    920                                                 g_aFormats[i].pcszAtom);
     989            atomTargets[cTargets] = clipAtomForX11Format(pCtx->widget,
     990                                                          format);
    921991            ++cTargets;
    922992        }
    923     }
     993    } while (format != NIL_CLIPX11FORMAT);
     994    /* We always offer these */
    924995    atomTargets[cTargets] = clipGetAtom(pCtx->widget, "TARGETS");
    925996    atomTargets[cTargets + 1] = clipGetAtom(pCtx->widget, "MULTIPLE");
    926997    atomTargets[cTargets + 2] = clipGetAtom(pCtx->widget, "TIMESTAMP");
    927998    *atomTypeReturn = XA_ATOM;
    928     *pValReturn = reinterpret_cast<XtPointer>(atomTargets);
     999    *pValReturn = (XtPointer)atomTargets;
    9291000    *pcLenReturn = cTargets + 3;
    9301001    *piFormatReturn = 32;
     
    9411012 * @todo any ideas about how to do this better are welcome.
    9421013 */
    943 static int vboxClipboardReadVBoxData (CLIPBACKEND *pCtx,
    944                                uint32_t u32Format, void **ppv,
    945                                uint32_t *pcb)
     1014static int clipReadVBoxClipboard(CLIPBACKEND *pCtx, uint32_t u32Format,
     1015                                 void **ppv, uint32_t *pcb)
    9461016{
    9471017    int rc = VINF_SUCCESS;
     
    9711041}
    9721042
     1043
    9731044/**
    974  * Satisfy a request from X11 to convert the clipboard text to Utf8.  We
    975  * return non-zero terminated text.
    976  * @todo that works, but it is bad.  Change it to return zero-terminated
    977  *       text.
     1045 * Convert text from Windows format (UCS-2 with CRLF line endings) to standard
     1046 * Utf-8.
     1047 *
     1048 * @returns iprt status code
     1049 *
     1050 * @param  pwszSrc    the text to be converted
     1051 * @param  cbSrc      the length of @a pwszSrc in bytes
     1052 * @param  pszBuf     where to write the converted string
     1053 * @param  cbBuf      the size of the buffer pointed to by @a pszBuf
     1054 * @param  pcbActual  where to store the size of the converted string.
     1055 *                    optional.
     1056 */
     1057static int clipWinTxtToUtf8(PRTUTF16 pwszSrc, size_t cbSrc, char *pszBuf,
     1058                            size_t cbBuf, size_t *pcbActual)
     1059{
     1060    PRTUTF16 pwszTmp = NULL;
     1061    size_t cwSrc = cbSrc / 2, cwTmp = 0, cbDest = 0;
     1062    int rc = VINF_SUCCESS;
     1063
     1064    LogFlowFunc (("pwszSrc=%.*ls, cbSrc=%u\n", cbSrc, pwszSrc, cbSrc));
     1065    /* How long will the converted text be? */
     1066    AssertPtr(pwszSrc);
     1067    AssertPtr(pszBuf);
     1068    rc = vboxClipboardUtf16GetLinSize(pwszSrc, cwSrc, &cwTmp);
     1069    if (RT_SUCCESS(rc) && cwTmp == 0)
     1070        rc = VERR_NO_DATA;
     1071    if (RT_SUCCESS(rc))
     1072        pwszTmp = (PRTUTF16)RTMemAlloc(cwTmp * 2);
     1073    if (!pwszTmp)
     1074        rc = VERR_NO_MEMORY;
     1075    /* Convert the text. */
     1076    if (RT_SUCCESS(rc))
     1077        rc = vboxClipboardUtf16WinToLin(pwszSrc, cwSrc, pwszTmp, cwTmp);
     1078    if (RT_SUCCESS(rc))
     1079        /* Convert the Utf16 string to Utf8. */
     1080        rc = RTUtf16ToUtf8Ex(pwszTmp + 1, cwTmp - 1, &pszBuf, cbBuf,
     1081                             &cbDest);
     1082    RTMemFree(reinterpret_cast<void *>(pwszTmp));
     1083    if (pcbActual)
     1084        *pcbActual = cbDest + 1;
     1085    LogFlowFunc(("returning %Rrc\n", rc));
     1086    if (RT_SUCCESS(rc))
     1087        LogFlowFunc (("converted string is %.*s. Returning.\n", cbDest,
     1088                      pszBuf));
     1089    return rc;
     1090}
     1091
     1092/**
     1093 * Satisfy a request from X11 to convert the clipboard text to
     1094 * COMPOUND_TEXT.  We return null-terminated text, but can cope with non-null-
     1095 * terminated input.
    9781096 *
    9791097 * @returns true if we successfully convert the data to the format
    9801098 * requested, false otherwise.
    9811099 *
    982  * @param  atomTypeReturn  Where to store the atom for the type of the data
     1100 * @param  pDisplay        an X11 display structure, needed for conversions
     1101 *                         performed by Xlib
     1102 * @param  pv              the text to be converted (UCS-2 with Windows EOLs)
     1103 * @param  cb              the length of the text in @cb in bytes
     1104 * @param  atomTypeReturn  where to store the atom for the type of the data
    9831105 *                         we are returning
    984  * @param  pValReturn      Where to store the pointer to the data we are
     1106 * @param  pValReturn      where to store the pointer to the data we are
    9851107 *                         returning.  This should be to memory allocated by
    9861108 *                         XtMalloc, which will be freed by the Xt toolkit
    9871109 *                         later.
    988  * @param  pcLenReturn     Where to store the length of the data we are
     1110 * @param  pcLenReturn     where to store the length of the data we are
    9891111 *                         returning
    990  * @param  piFormatReturn  Where to store the bit width (8, 16, 32) of the
     1112 * @param  piFormatReturn  where to store the bit width (8, 16, 32) of the
    9911113 *                         data we are returning
    992  * @note  X11 backend code, called by the callback for XtOwnSelection.
    993  */
    994 static Boolean vboxClipboardConvertToUtf8ForX11(CLIPBACKEND
    995                                                                       *pCtx,
    996                                                 Atom *atomTarget,
    997                                                 Atom *atomTypeReturn,
    998                                                 XtPointer *pValReturn,
    999                                                 unsigned long *pcLenReturn,
    1000                                                 int *piFormatReturn)
    1001 {
    1002     PRTUTF16 pu16SrcText, pu16DestText;
    1003     char *pu8DestText;
    1004     void *pvVBox = NULL;
    1005     uint32_t cbVBox = 0;
    1006     size_t cwSrcLen, cwDestLen, cbDestLen;
    1007     int rc;
    1008 
    1009     LogFlowFunc (("called\n"));
    1010     /* Read the clipboard data from the guest. */
    1011     rc = vboxClipboardReadVBoxData(pCtx,
    1012                                    VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    1013                                    &pvVBox, &cbVBox);
    1014     if ((rc != VINF_SUCCESS) || (cbVBox == 0))
    1015     {
    1016         /* If vboxClipboardReadVBoxData fails then we may be terminating */
    1017         LogRelFunc (("vboxClipboardReadVBoxData returned %Rrc%s\n", rc,
    1018                      RT_SUCCESS(rc) ? ", cbVBox == 0" :  ""));
    1019         RTMemFree(pvVBox);
    1020         return false;
    1021     }
    1022     pu16SrcText = reinterpret_cast<PRTUTF16>(pvVBox);
    1023     cwSrcLen = cbVBox / 2;
    1024     /* How long will the converted text be? */
    1025     rc = vboxClipboardUtf16GetLinSize(pu16SrcText, cwSrcLen, &cwDestLen);
    1026     if (RT_FAILURE(rc))
    1027     {
    1028         LogRelFunc (("clipboard conversion failed.  vboxClipboardUtf16GetLinSize returned %Rrc.  Abandoning.\n", rc));
    1029         RTMemFree(pvVBox);
    1030         AssertRCReturn(rc, false);
    1031     }
    1032     if (cwDestLen == 0)
    1033     {
    1034         LogFlowFunc(("received empty clipboard data from the guest, returning false.\n"));
    1035         RTMemFree(pvVBox);
    1036         return false;
    1037     }
    1038     pu16DestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDestLen * 2));
    1039     if (pu16DestText == 0)
    1040     {
    1041         LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 2));
    1042         RTMemFree(pvVBox);
    1043         return false;
    1044     }
    1045     /* Convert the text. */
    1046     rc = vboxClipboardUtf16WinToLin(pu16SrcText, cwSrcLen, pu16DestText, cwDestLen);
    1047     if (RT_FAILURE(rc))
    1048     {
    1049         LogRelFunc (("clipboard conversion failed.  vboxClipboardUtf16WinToLin() returned %Rrc.  Abandoning.\n", rc));
    1050         RTMemFree(reinterpret_cast<void *>(pu16DestText));
    1051         RTMemFree(pvVBox);
    1052         return false;
    1053     }
    1054     /* Allocate enough space, as RTUtf16ToUtf8Ex may fail if the
    1055        space is too tightly calculated. */
    1056     pu8DestText = XtMalloc(cwDestLen * 4);
    1057     if (pu8DestText == 0)
    1058     {
    1059         LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 4));
    1060         RTMemFree(reinterpret_cast<void *>(pu16DestText));
    1061         RTMemFree(pvVBox);
    1062         return false;
    1063     }
    1064     /* Convert the Utf16 string to Utf8. */
    1065     rc = RTUtf16ToUtf8Ex(pu16DestText + 1, cwDestLen - 1, &pu8DestText, cwDestLen * 4,
    1066                          &cbDestLen);
    1067     RTMemFree(reinterpret_cast<void *>(pu16DestText));
    1068     if (RT_FAILURE(rc))
    1069     {
    1070         LogRelFunc (("clipboard conversion failed.  RTUtf16ToUtf8Ex() returned %Rrc.  Abandoning.\n", rc));
    1071         XtFree(pu8DestText);
    1072         RTMemFree(pvVBox);
    1073         return false;
    1074     }
    1075     LogFlowFunc (("converted string is %.*s. Returning.\n", cbDestLen, pu8DestText));
    1076     RTMemFree(pvVBox);
    1077     *atomTypeReturn = *atomTarget;
    1078     *pValReturn = reinterpret_cast<XtPointer>(pu8DestText);
    1079     *pcLenReturn = cbDestLen + 1;
    1080     *piFormatReturn = 8;
    1081     return true;
    1082 }
    1083 
    1084 /**
    1085  * Satisfy a request from X11 to convert the clipboard text to
    1086  * COMPOUND_TEXT.  We return non-zero terminated text.
    1087  * @todo that works, but it is bad.  Change it to return zero-terminated
    1088  *       text.
    1089  *
    1090  * @returns true if we successfully convert the data to the format
    1091  * requested, false otherwise.
    1092  *
    1093  * @param  atomTypeReturn  Where to store the atom for the type of the data
    1094  *                         we are returning
    1095  * @param  pValReturn      Where to store the pointer to the data we are
    1096  *                         returning.  This should be to memory allocated by
    1097  *                         XtMalloc, which will be freed by the Xt toolkit
    1098  *                         later.
    1099  * @param  pcLenReturn     Where to store the length of the data we are
    1100  *                         returning
    1101  * @param  piFormatReturn  Where to store the bit width (8, 16, 32) of the
    1102  *                         data we are returning
    1103  * @note  X11 backend code, called by the callback for XtOwnSelection.
    1104  */
    1105 static Boolean vboxClipboardConvertToCTextForX11(CLIPBACKEND
    1106                                                                       *pCtx,
    1107                                                  Atom *atomTypeReturn,
    1108                                                  XtPointer *pValReturn,
    1109                                                  unsigned long *pcLenReturn,
    1110                                                  int *piFormatReturn)
    1111 {
    1112     PRTUTF16 pu16SrcText, pu16DestText;
    1113     void *pvVBox = NULL;
    1114     uint32_t cbVBox = 0;
    1115     char *pu8DestText = 0;
    1116     size_t cwSrcLen, cwDestLen, cbDestLen;
     1114 */
     1115static Boolean clipConvertToCTextForX11(Display *pDisplay, PRTUTF16 pwszSrc,
     1116                                        size_t cbSrc, Atom *atomTypeReturn,
     1117                                        XtPointer *pValReturn,
     1118                                        unsigned long *pcLenReturn,
     1119                                        int *piFormatReturn)
     1120{
     1121    char *pszTmp = NULL;
     1122    size_t cbTmp = 0, cbActual = 0;
    11171123    XTextProperty property;
    1118     int rc;
    1119 
    1120     LogFlowFunc (("called\n"));
    1121     /* Read the clipboard data from the guest. */
    1122     rc = vboxClipboardReadVBoxData(pCtx,
    1123                                    VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    1124                                    &pvVBox, &cbVBox);
    1125     if ((rc != VINF_SUCCESS) || (cbVBox == 0))
    1126     {
    1127         /* If vboxClipboardReadVBoxData fails then we may be terminating */
    1128         LogRelFunc (("vboxClipboardReadVBoxData returned %Rrc%s\n", rc,
    1129                       RT_SUCCESS(rc) ? ", cbVBox == 0" :  ""));
    1130         RTMemFree(pvVBox);
    1131         return false;
    1132     }
    1133     pu16SrcText = reinterpret_cast<PRTUTF16>(pvVBox);
    1134     cwSrcLen = cbVBox / 2;
    1135     /* How long will the converted text be? */
    1136     rc = vboxClipboardUtf16GetLinSize(pu16SrcText, cwSrcLen, &cwDestLen);
    1137     if (RT_FAILURE(rc))
    1138     {
    1139         LogRelFunc (("clipboard conversion failed.  vboxClipboardUtf16GetLinSize returned %Rrc.  Abandoning.\n", rc));
    1140         RTMemFree(pvVBox);
    1141         AssertRCReturn(rc, false);
    1142     }
    1143     if (cwDestLen == 0)
    1144     {
    1145         LogFlowFunc(("received empty clipboard data from the guest, returning false.\n"));
    1146         RTMemFree(pvVBox);
    1147         return false;
    1148     }
    1149     pu16DestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDestLen * 2));
    1150     if (pu16DestText == 0)
    1151     {
    1152         LogRelFunc (("failed to allocate %d bytes\n", cwDestLen * 2));
    1153         RTMemFree(pvVBox);
    1154         return false;
    1155     }
    1156     /* Convert the text. */
    1157     rc = vboxClipboardUtf16WinToLin(pu16SrcText, cwSrcLen, pu16DestText, cwDestLen);
    1158     if (RT_FAILURE(rc))
    1159     {
    1160         LogRelFunc (("clipboard conversion failed.  vboxClipboardUtf16WinToLin() returned %Rrc.  Abandoning.\n", rc));
    1161         RTMemFree(reinterpret_cast<void *>(pu16DestText));
    1162         RTMemFree(pvVBox);
    1163         return false;
    1164     }
    1165     /* Convert the Utf16 string to Utf8. */
    1166     rc = RTUtf16ToUtf8Ex(pu16DestText + 1, cwDestLen - 1, &pu8DestText, 0, &cbDestLen);
    1167     RTMemFree(reinterpret_cast<void *>(pu16DestText));
    1168     if (RT_FAILURE(rc))
    1169     {
    1170         LogRelFunc (("clipboard conversion failed.  RTUtf16ToUtf8Ex() returned %Rrc.  Abandoning.\n", rc));
    1171         RTMemFree(pvVBox);
    1172         return false;
    1173     }
     1124    int rc = VINF_SUCCESS, xrc = 0;
     1125
     1126    /* This may slightly overestimate the space needed. */
     1127    rc = RTUtf16CalcUtf8LenEx(pwszSrc, cbSrc / 2, &cbTmp);
     1128    ++cbTmp;  /* Null terminator */
     1129    if (RT_SUCCESS(rc))
     1130    {
     1131        pszTmp = (char *)RTMemAlloc(cbTmp);
     1132        if (!pszTmp)
     1133            rc = VERR_NO_MEMORY;
     1134    }
     1135    if (RT_SUCCESS(rc))
     1136        rc = clipWinTxtToUtf8(pwszSrc, cbSrc, pszTmp, cbTmp + 1,
     1137                              &cbActual);
    11741138    /* And finally (!) convert the Utf8 text to compound text. */
    1175 #ifdef RT_OS_SOLARIS
    1176     rc = XmbTextListToTextProperty(XtDisplay(pCtx->widget), &pu8DestText, 1,
    1177                                      XCompoundTextStyle, &property);
     1139#ifdef X_HAVE_UTF8_STRING
     1140    if (RT_SUCCESS(rc))
     1141        xrc = Xutf8TextListToTextProperty(pDisplay, &pszTmp, 1,
     1142                                          XCompoundTextStyle, &property);
    11781143#else
    1179     rc = Xutf8TextListToTextProperty(XtDisplay(pCtx->widget), &pu8DestText, 1,
    1180                                      XCompoundTextStyle, &property);
     1144    if (RT_SUCCESS(rc))
     1145        xrc = XmbTextListToTextProperty(pDisplay, &pszTmp, 1,
     1146                                        XCompoundTextStyle, &property);
    11811147#endif
    1182     RTMemFree(pu8DestText);
    1183     if (rc < 0)
    1184     {
    1185         const char *pcReason;
    1186         switch(rc)
    1187         {
    1188         case XNoMemory:
    1189             pcReason = "out of memory";
    1190             break;
    1191         case XLocaleNotSupported:
    1192             pcReason = "locale (Utf8) not supported";
    1193             break;
    1194         case XConverterNotFound:
    1195             pcReason = "converter not found";
    1196             break;
    1197         default:
    1198             pcReason = "unknown error";
    1199         }
    1200         LogRelFunc (("Xutf8TextListToTextProperty failed.  Reason: %s\n",
    1201                 pcReason));
    1202         RTMemFree(pvVBox);
    1203         return false;
    1204     }
    1205     LogFlowFunc (("converted string is %s. Returning.\n", property.value));
    1206     RTMemFree(pvVBox);
     1148    if (RT_SUCCESS(rc) && xrc < 0)
     1149        rc = (  xrc == XNoMemory           ? VERR_NO_MEMORY
     1150              : xrc == XLocaleNotSupported ? VERR_NOT_SUPPORTED
     1151              : xrc == XConverterNotFound  ? VERR_NOT_SUPPORTED
     1152              :                              VERR_UNRESOLVED_ERROR);
     1153    RTMemFree(pszTmp);
    12071154    *atomTypeReturn = property.encoding;
    12081155    *pValReturn = reinterpret_cast<XtPointer>(property.value);
    12091156    *pcLenReturn = property.nitems + 1;
    12101157    *piFormatReturn = property.format;
    1211     return true;
     1158    LogFlowFunc(("returning, internal rc=%Rrc\n"));
     1159    if (RT_SUCCESS(rc))
     1160        LogFlowFunc (("converted string is %s\n", property.value));
     1161    return RT_SUCCESS(rc);
    12121162}
    12131163
     
    12251175    CLIPFORMAT enmFormat = INVALID;
    12261176    CLIPBACKEND *pCtx = clipLookupContext(widget);
     1177    int rc = VINF_SUCCESS;
     1178    bool retval = false;
    12271179
    12281180    LogFlowFunc(("\n"));
     
    12561208    {
    12571209    case TARGETS:
    1258         return vboxClipboardConvertTargetsForX11(pCtx, atomTypeReturn,
    1259                                                  pValReturn, pcLenReturn,
    1260                                                  piFormatReturn);
     1210        return clipCreateX11Targets(pCtx, atomTypeReturn, pValReturn,
     1211                                    pcLenReturn, piFormatReturn);
    12611212    case UTF8:
    1262         return vboxClipboardConvertToUtf8ForX11(pCtx, atomTarget,
    1263                                                 atomTypeReturn,
    1264                                                 pValReturn, pcLenReturn,
    1265                                                 piFormatReturn);
     1213    {
     1214        /* Read the clipboard data from the guest. */
     1215        void *pv = NULL;
     1216        uint32_t cb = 0;
     1217        rc = clipReadVBoxClipboard(pCtx,
     1218                                   VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     1219                                   &pv, &cb);
     1220        if (RT_SUCCESS(rc) && (cb != 0))
     1221        {
     1222            /* This may slightly overestimate the space needed. */
     1223            size_t cbDest = 0;
     1224            rc = RTUtf16CalcUtf8LenEx((PRTUTF16)pv, cb / 2, &cbDest);
     1225            if (RT_SUCCESS(rc))
     1226            {
     1227                char *pszDest = (char *)XtMalloc(cbDest + 1);
     1228                size_t cbActual = 0;
     1229                if (pszDest)
     1230                    rc = clipWinTxtToUtf8((PRTUTF16)pv, cb, pszDest,
     1231                                          cbDest + 1, &cbActual);
     1232                if (RT_SUCCESS(rc))
     1233                {
     1234                    *atomTypeReturn = *atomTarget;
     1235                    *pValReturn = (XtPointer)pszDest;
     1236                    *pcLenReturn = cbActual;
     1237                    *piFormatReturn = 8;
     1238                    retval = true;
     1239                }
     1240            }
     1241        }
     1242        RTMemFree(pv);
     1243        break;
     1244    }
    12661245    case CTEXT:
    1267         return vboxClipboardConvertToCTextForX11(pCtx, atomTypeReturn,
    1268                                                  pValReturn, pcLenReturn,
    1269                                                  piFormatReturn);
     1246    {
     1247        /* Read the clipboard data from the guest. */
     1248        void *pv = NULL;
     1249        uint32_t cb = 0;
     1250        rc = clipReadVBoxClipboard(pCtx,
     1251                                   VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     1252                                   &pv, &cb);
     1253        if (RT_SUCCESS(rc) && (cb != 0))
     1254            retval = clipConvertToCTextForX11(XtDisplay(pCtx->widget),
     1255                                              (PRTUTF16)pv, cb,
     1256                                              atomTypeReturn, pValReturn,
     1257                                              pcLenReturn, piFormatReturn);
     1258        RTMemFree(pv);
     1259        break;
     1260    }
    12701261    default:
    12711262        LogFunc (("bad format\n"));
    12721263        return false;
    12731264    }
     1265    return retval;
    12741266}
    12751267
     
    12851277    LogFlowFunc (("called, giving X11 clipboard ownership\n"));
    12861278    /* These should be set to the right values as soon as we start polling */
    1287     pCtx->X11TextFormat = INVALID;
    1288     pCtx->X11BitmapFormat = INVALID;
     1279    clipInvalidateX11Contents(pCtx);
    12891280    pCtx->fOwnsClipboard = false;
    1290     pCtx->notifyVBox = true;
     1281    clipInvalidateVBoxCache(pCtx);
    12911282}
    12921283
     
    13541345        /* VBox thinks it currently owns the clipboard, so we must notify it
    13551346         * as soon as we know what formats X11 has to offer. */
    1356         pCtx->notifyVBox = true;
     1347        clipInvalidateVBoxCache(pCtx);
    13571348        pCtx->fOwnsClipboard = false;
    13581349    }
     
    13721363     * Immediately return if we are not connected to the host X server.
    13731364     */
    1374     if (!g_fHaveX11)
     1365    if (!pCtx->fHaveX11)
    13751366        return;
    13761367    /* This must be freed by the worker callback */
     
    13911382                                       XtIntervalId * /* interval */)
    13921383{
    1393     CLIPX11CLIPBOARDREQ *pRequest = (CLIPX11CLIPBOARDREQ *)pUserData;
    1394     CLIPBACKEND *pCtx = pRequest->pCtx;
    1395     LogFlowFunc (("u32Format = %d, cb = %d\n", pRequest->format,
    1396                   pRequest->cb));
     1384    CLIPX11CLIPBOARDREQ *pReq = (CLIPX11CLIPBOARDREQ *)pUserData;
     1385    CLIPBACKEND *pCtx = pReq->mCtx;
     1386    LogFlowFunc (("pReq->mFormat = %02X, pReq->mSize = %d\n", pReq->mFormat,
     1387                  pReq->mSize));
    13971388
    13981389    int rc = VINF_SUCCESS;
    13991390    /* Set this to start with, just in case */
    1400     *pRequest->pcbActual = 0;
     1391    *pReq->mActual = 0;
    14011392    /* Do not continue if we already own the clipboard */
    14021393    if (pCtx->fOwnsClipboard == true)
     
    14071398         * VBox wants to read data in the given format.
    14081399         */
    1409         if (pRequest->format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     1400        if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    14101401        {
    1411             if (pCtx->atomX11TextFormat == None)
     1402            pReq->mTextFormat = pCtx->X11TextFormat;
     1403            if (pReq->mTextFormat == 0)
    14121404                /* VBox thinks we have data and we don't */
    14131405                rc = VERR_NO_DATA;
     
    14161408                 * owner */
    14171409                XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"),
    1418                                     pCtx->atomX11TextFormat,
     1410                                    clipGetAtom(pCtx->widget,
     1411                                        g_aFormats[pCtx->X11TextFormat].pcszAtom),
    14191412                                    clipConvertX11CB,
    1420                                     reinterpret_cast<XtPointer>(pRequest),
     1413                                    reinterpret_cast<XtPointer>(pReq),
    14211414                                    CurrentTime);
    14221415        }
     
    14261419    if (RT_FAILURE(rc))
    14271420    {
    1428         pRequest->rc = rc;
     1421        pReq->mRC = rc;
    14291422        /* The clipboard callback was never scheduled, so we must signal
    14301423         * that the request processing is finished ourselves. */
    1431         RTSemEventSignal(pRequest->finished);
     1424        RTSemEventSignal(pReq->mSem);
    14321425    }
    14331426    LogFlowFunc(("status %Rrc\n", rc));
     
    14551448     * Immediately return if we are not connected to the host X server.
    14561449     */
    1457     if (!g_fHaveX11)
     1450    if (!pCtx->fHaveX11)
    14581451        return VINF_SUCCESS;
    14591452
    1460     CLIPX11CLIPBOARDREQ request;
    1461     request.rc = VERR_WRONG_ORDER;
    1462     request.pv = pv;
    1463     request.cb = cb;
    1464     request.pcbActual = pcbActual;
    1465     request.format = u32Format;
    1466     request.pCtx = pCtx;
     1453    CLIPX11CLIPBOARDREQ req = { 0 };
     1454    req.mRC = VERR_WRONG_ORDER;
     1455    req.mBuffer = pv;
     1456    req.mSize = cb;
     1457    req.mActual = pcbActual;
     1458    req.mFormat = u32Format;
     1459    req.mCtx = pCtx;
    14671460    /* The worker function will signal this when it has finished. */
    1468     int rc = RTSemEventCreate(&request.finished);
     1461    int rc = RTSemEventCreate(&req.mSem);
    14691462    if (RT_SUCCESS(rc))
    14701463    {
    14711464        /* We use this to schedule a worker function on the event thread. */
    14721465        clipSchedule(pCtx->appContext, vboxClipboardReadX11Worker,
    1473                      (XtPointer) &request);
    1474         rc = RTSemEventWait(request.finished, RT_INDEFINITE_WAIT);
     1466                     (XtPointer) &req);
     1467        rc = RTSemEventWait(req.mSem, RT_INDEFINITE_WAIT);
    14751468        if (RT_SUCCESS(rc))
    1476             rc = request.rc;
    1477         RTSemEventDestroy(request.finished);
     1469            rc = req.mRC;
     1470        RTSemEventDestroy(req.mSem);
    14781471    }
    14791472    return rc;
Note: See TracChangeset for help on using the changeset viewer.

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