VirtualBox

Ignore:
Timestamp:
Jun 19, 2023 9:11:37 AM (23 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
157911
Message:

Shared Clipboard: Unified root list entry code to also use the generic list entry code, a lot of updates for the cross OS transfer handling code, more updates for HTTP server transfer handling.

This also changed the handling of how that transfers are being initiated, as we needed to have this for X11: Before, transfers were initiated as soon as on side announced the URI list format -- now we postpone initiating the transfer until the receiving side requests the data as URI list.

bugref:9437

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard-x11.cpp

    r99987 r100204  
    4040#include <iprt/semaphore.h>
    4141
    42 #include <VBox/log.h>
     42#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
     43#include <iprt/log.h>
     44
    4345#include <VBox/VBoxGuestLib.h>
    4446#include <VBox/HostServices/VBoxClipboardSvc.h>
     
    5052#include "clipboard.h"
    5153
    52 
     54#include <iprt/req.h>
     55
     56
     57#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     58#if 0
     59/**
     60 * Worker for reading the transfer root list from the host.
     61 */
     62static DECLCALLBACK(int) vbclX11ReqTransferReadRootListWorker(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     63{
     64    RT_NOREF(pCtx);
     65
     66    LogFlowFuncEnter();
     67
     68    int rc = ShClTransferRootListRead(pTransfer);
     69
     70    LogFlowFuncLeaveRC(rc);
     71    return rc;
     72}
     73#endif
     74
     75/**
     76 * Worker for waiting for a transfer status change.
     77 */
     78static DECLCALLBACK(int) vbclX11TransferWaitForStatusWorker(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS enmSts,
     79                                                            RTMSINTERVAL msTimeout)
     80{
     81    RT_NOREF(pCtx);
     82
     83    LogFlowFuncEnter();
     84
     85    int rc = VERR_TIMEOUT;
     86
     87    ShClTransferAcquire(pTransfer);
     88
     89    uint64_t const tsStartMs = RTTimeMilliTS();
     90
     91    while (RTTimeMilliTS() - tsStartMs <= msTimeout)
     92    {
     93        if (ShClTransferGetStatus(pTransfer) == enmSts) /* Currently we only have busy waiting here. */
     94        {
     95            rc = VINF_SUCCESS;
     96            break;
     97        }
     98        RTThreadSleep(100);
     99    }
     100
     101    ShClTransferRelease(pTransfer);
     102
     103    return rc;
     104}
     105
     106/**
     107 * @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnRegistered
     108 *
     109 * This starts the HTTP server if not done yet and registers the transfer with it.
     110 *
     111 * @thread Clipbpoard main thread.
     112 */
     113static DECLCALLBACK(void) vbclX11OnHttpTransferRegisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
     114{
     115    RT_NOREF(pTransferCtx);
     116
     117    LogFlowFuncEnter();
     118
     119    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     120    AssertPtr(pCtx);
     121
     122    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     123    AssertPtr(pTransfer);
     124
     125    ShClTransferAcquire(pTransfer);
     126
     127    /* We only need to start the HTTP server when we actually receive data from the remote (host). */
     128    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
     129    {
     130        /* Retrieve the root entries as a first action, so that the transfer is ready to go
     131         * once it gets registered to HTTP server below. */
     132        int rc2 = ShClTransferRootListRead(pTransfer);
     133        if (RT_SUCCESS(rc2))
     134        {
     135            ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx);
     136            rc2 = ShClTransferHttpServerRegisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
     137        }
     138
     139        if (RT_FAILURE(rc2))
     140            LogRel(("Shared Clipboard: Registering HTTP transfer failed: %Rrc\n", rc2));
     141    }
     142
     143    LogFlowFuncLeave();
     144}
     145
     146/**
     147 * Unregisters a transfer from a HTTP server.
     148 *
     149 * This also stops the HTTP server if no active transfers are found anymore.
     150 *
     151 * @param   pCtx                Shared clipboard context to unregister transfer for.
     152 * @param   pTransfer           Transfer to unregister.
     153 *
     154 * @thread Clipbpoard main thread.
     155 */
     156static void vbclX11HttpTransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     157{
     158    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
     159    {
     160        ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
     161        ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx);
     162    }
     163
     164    ShClTransferRelease(pTransfer);
     165}
     166
     167/**
     168 * @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnUnregistered
     169 *
     170 * Unregisters a (now) unregistered transfer from the HTTP server.
     171 *
     172 * @thread Clipbpoard main thread.
     173 */
     174static DECLCALLBACK(void) vbclX11OnHttpTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
     175{
     176    RT_NOREF(pTransferCtx);
     177    vbclX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
     178}
     179
     180/**
     181 * @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnCompleted
     182 *
     183 * Unregisters a complete transfer from the HTTP server.
     184 *
     185 * @thread Clipbpoard main thread.
     186 */
     187static DECLCALLBACK(void) vbclX11OnHttpTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc)
     188{
     189    RT_NOREF(rc);
     190    vbclX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
     191}
     192
     193/** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnError
     194 *
     195 * Unregisters a failed transfer from the HTTP server.
     196 *
     197 * @thread Clipbpoard main thread.
     198 */
     199static DECLCALLBACK(void) vbclX11OnHttpTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc)
     200{
     201    return vbclX11OnHttpTransferCompletedCallback(pCtx, rc);
     202}
     203#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
     204
     205/**
     206 * Worker for a reading clipboard from the host.
     207 */
     208static DECLCALLBACK(int) vbclX11ReqReadDataWorker(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser)
     209{
     210    RT_NOREF(pvUser);
     211
     212    LogFlowFuncEnter();
     213
     214    int rc = VERR_NO_DATA; /* Play safe. */
     215
     216    uint32_t cbRead = 0;
     217
     218    uint32_t cbData = _4K; /** @todo Make this dynamic. */
     219    void    *pvData = RTMemAlloc(cbData);
     220    if (pvData)
     221    {
     222        rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead);
     223    }
     224    else
     225        rc = VERR_NO_MEMORY;
     226
     227    /*
     228     * A return value of VINF_BUFFER_OVERFLOW tells us to try again with a
     229     * larger buffer.  The size of the buffer needed is placed in *pcb.
     230     * So we start all over again.
     231     */
     232    if (rc == VINF_BUFFER_OVERFLOW)
     233    {
     234        /* cbRead contains the size required. */
     235
     236        cbData = cbRead;
     237        pvData = RTMemRealloc(pvData, cbRead);
     238        if (pvData)
     239        {
     240            rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead);
     241            if (rc == VINF_BUFFER_OVERFLOW)
     242                rc = VERR_BUFFER_OVERFLOW;
     243        }
     244        else
     245            rc = VERR_NO_MEMORY;
     246    }
     247
     248    if (!cbRead)
     249        rc = VERR_NO_DATA;
     250
     251    if (RT_SUCCESS(rc))
     252    {
     253        if (ppv)
     254            *ppv = pvData;
     255        if (pcb)
     256            *pcb = cbRead; /* Actual bytes read. */
     257    }
     258    else
     259    {
     260        /*
     261         * Catch other errors. This also catches the case in which the buffer was
     262         * too small a second time, possibly because the clipboard contents
     263         * changed half-way through the operation.  Since we can't say whether or
     264         * not this is actually an error, we just return size 0.
     265         */
     266        RTMemFree(pvData);
     267    }
     268
     269    LogFlowFuncLeaveRC(rc);
     270    return rc;
     271}
     272
     273/**
     274 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource
     275 *
     276 * Requests URI data from the host.
     277 * This initiates a transfer on the host. Most of the handling will be done VbglR3 then.
     278 *
     279 * @thread  X11 event thread.
     280 */
    53281static DECLCALLBACK(int) vbclX11OnRequestDataFromSourceCallback(PSHCLCONTEXT pCtx,
    54282                                                                SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser)
     
    58286    LogFlowFunc(("pCtx=%p, uFmt=%#x\n", pCtx, uFmt));
    59287
    60     int rc = VINF_SUCCESS;
    61 
    62 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     288    /* Request reading host clipboard data. */
     289    PRTREQ pReq = NULL;
     290    int rc = RTReqQueueCallEx(pCtx->X11.hReqQ, &pReq, SHCL_TIMEOUT_DEFAULT_MS, RTREQFLAGS_IPRT_STATUS,
     291                              (PFNRT)vbclX11ReqReadDataWorker, 5, pCtx, uFmt, ppv, pcb, pvUser);
     292    RTReqRelease(pReq);
     293
     294#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    63295    if (uFmt == VBOX_SHCL_FMT_URI_LIST)
    64296    {
    65         //rc = VbglR3ClipboardRootListRead()
    66         rc = VERR_NO_DATA;
    67     }
    68     else
    69 #endif
    70     {
    71         uint32_t cbRead = 0;
    72 
    73         uint32_t cbData = _4K; /** @todo Make this dynamic. */
    74         void    *pvData = RTMemAlloc(cbData);
    75         if (pvData)
    76         {
    77             rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead);
    78         }
    79         else
    80             rc = VERR_NO_MEMORY;
    81 
    82         /*
    83          * A return value of VINF_BUFFER_OVERFLOW tells us to try again with a
    84          * larger buffer.  The size of the buffer needed is placed in *pcb.
    85          * So we start all over again.
    86          */
    87         if (rc == VINF_BUFFER_OVERFLOW)
    88         {
    89             /* cbRead contains the size required. */
    90 
    91             cbData = cbRead;
    92             pvData = RTMemRealloc(pvData, cbRead);
    93             if (pvData)
     297        PSHCLHTTPSERVER pSrv = &pCtx->X11.HttpCtx.HttpServer;
     298
     299        rc = ShClTransferHttpServerWaitForStatusChange(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED, SHCL_TIMEOUT_DEFAULT_MS);
     300        if (RT_SUCCESS(rc))
     301        {
     302            PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferFirst(pSrv);
     303            if (pTransfer)
    94304            {
    95                 rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead);
    96                 if (rc == VINF_BUFFER_OVERFLOW)
    97                     rc = VERR_BUFFER_OVERFLOW;
     305                rc = vbclX11TransferWaitForStatusWorker(pCtx, pTransfer, SHCLTRANSFERSTATUS_STARTED, SHCL_TIMEOUT_DEFAULT_MS);
     306                if (RT_SUCCESS(rc))
     307                {
     308                    char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID);
     309                    char *pszData = NULL;
     310                    RTStrAPrintf(&pszData, "copy\n%s", pszURL);
     311
     312                    *ppv = pszData;
     313                    *pcb = strlen(pszData) + 1 /* Include terminator */;
     314
     315                    RTStrFree(pszURL);
     316
     317                    rc = VINF_SUCCESS;
     318
     319                    LogFlowFunc(("pszURL=%s\n", pszURL));
     320                }
    98321            }
    99322            else
    100                 rc = VERR_NO_MEMORY;
    101         }
    102 
    103         if (!cbRead)
    104             rc = VERR_NO_DATA;
    105 
    106         if (RT_SUCCESS(rc))
    107         {
    108             *pcb = cbRead; /* Actual bytes read. */
    109             *ppv = pvData;
     323                AssertMsgFailed(("No registered transfer found for HTTP server\n"));
    110324        }
    111325        else
    112         {
    113             /*
    114              * Catch other errors. This also catches the case in which the buffer was
    115              * too small a second time, possibly because the clipboard contents
    116              * changed half-way through the operation.  Since we can't say whether or
    117              * not this is actually an error, we just return size 0.
    118              */
    119             RTMemFree(pvData);
    120         }
    121     }
     326            LogRel(("Shared Clipboard: Could not start transfer, as the HTTP server is not running\n"));
     327    }
     328#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
    122329
    123330    if (RT_FAILURE(rc))
     
    129336
    130337/**
    131  * Opaque data structure describing a request from the host for clipboard
    132  * data, passed in when the request is forwarded to the X11 backend so that
    133  * it can be completed correctly.
    134  */
    135 struct CLIPREADCBREQ
    136 {
    137     /** The data format that was requested. */
    138     SHCLFORMAT uFmt;
    139 };
    140 
     338 * Worker for reporting clipboard formats to the host.
     339 */
     340static DECLCALLBACK(int) vbclX11ReqReportFormatsWorker(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser)
     341{
     342    RT_NOREF(pvUser);
     343
     344    LogFlowFunc(("fFormats=%#x\n", fFormats));
     345
     346    int rc = VbglR3ClipboardReportFormats(pCtx->CmdCtx.idClient, fFormats);
     347
     348    LogFlowFuncLeaveRC(rc);
     349    return rc;
     350}
     351
     352/**
     353 * @copydoc SHCLCALLBACKS::pfnReportFormats
     354 *
     355 * Reports clipboard formats to the host.
     356 *
     357 * @thread  X11 event thread.
     358 */
    141359static DECLCALLBACK(int) vbclX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser)
    142360{
    143     RT_NOREF(pvUser);
    144 
    145     LogFlowFunc(("fFormats=%#x\n", fFormats));
    146 
    147     int rc = VbglR3ClipboardReportFormats(pCtx->CmdCtx.idClient, fFormats);
    148     LogFlowFuncLeaveRC(rc);
    149 
    150     return rc;
    151 }
    152 
    153 static DECLCALLBACK(int) vbclX11OnSendDataToDestCallback(PSHCLCONTEXT pCtx, void *pv, uint32_t cb, void *pvUser)
    154 {
    155     PSHCLX11READDATAREQ pData = (PSHCLX11READDATAREQ)pvUser;
    156     AssertPtrReturn(pData, VERR_INVALID_POINTER);
    157 
    158     LogFlowFunc(("rcCompletion=%Rrc, Format=0x%x, pv=%p, cb=%RU32\n", pData->rcCompletion, pData->pReq->uFmt, pv, cb));
    159 
    160     Assert((cb == 0 && pv == NULL) || (cb != 0 && pv != NULL));
    161     pData->rcCompletion = VbglR3ClipboardWriteDataEx(&pCtx->CmdCtx, pData->pReq->uFmt, pv, cb);
    162 
    163     RTMemFree(pData->pReq);
    164 
    165     LogFlowFuncLeaveRC(pData->rcCompletion);
    166 
    167     return VINF_SUCCESS;
     361    /* Request reading host clipboard data. */
     362    PRTREQ pReq = NULL;
     363    int rc = RTReqQueueCallEx(pCtx->X11.hReqQ, &pReq, SHCL_TIMEOUT_DEFAULT_MS, RTREQFLAGS_IPRT_STATUS,
     364                              (PFNRT)vbclX11ReqReportFormatsWorker, 3, pCtx, fFormats, pvUser);
     365    RTReqRelease(pReq);
     366
     367    LogFlowFuncLeaveRC(rc);
     368    return rc;
    168369}
    169370
     
    181382    Callbacks.pfnReportFormats           = vbclX11ReportFormatsCallback;
    182383    Callbacks.pfnOnRequestDataFromSource = vbclX11OnRequestDataFromSourceCallback;
    183     Callbacks.pfnOnSendDataToDest        = vbclX11OnSendDataToDestCallback;
    184384
    185385    int rc = ShClX11Init(&g_Ctx.X11, &Callbacks, &g_Ctx, false /* fHeadless */);
     
    220420}
    221421
    222 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    223 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnStart */
    224 static DECLCALLBACK(int) vboxClipboardOnTransferStartCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
    225 {
    226     PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
    227     AssertPtr(pCtx);
    228 
    229     PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
    230     AssertPtr(pTransfer);
    231 
    232     /* We only need to start the HTTP server (and register the transfer to it) when we actually receive data from the host. */
    233     if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    234         return ShClHttpTransferRegisterAndMaybeStart(&pCtx->X11.HttpCtx, pTransfer);
    235 
    236     return VINF_SUCCESS;
    237 }
    238 
    239 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnCompleted */
    240 static DECLCALLBACK(void) vboxClipboardOnTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc)
    241 {
    242     RT_NOREF(rc);
    243 
    244     PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
    245     AssertPtr(pCtx);
    246 
    247     PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
    248     AssertPtr(pTransfer);
    249 
    250     /* See comment in vboxClipboardOnTransferInitCallback(). */
    251     if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    252         ShClHttpTransferUnregisterAndMaybeStop(&pCtx->X11.HttpCtx, pTransfer);
    253 }
    254 
    255 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnError */
    256 static DECLCALLBACK(void) vboxClipboardOnTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc)
    257 {
    258     return vboxClipboardOnTransferCompletedCallback(pCtx, rc);
    259 }
    260 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
    261 
    262422/**
    263423 * The main loop of the X11-specifc Shared Clipboard code.
    264424 *
    265425 * @returns VBox status code.
     426 *
     427 * @thread  Clipboard service worker thread.
    266428 */
    267429int VBClX11ClipboardMain(void)
    268430{
    269     int rc;
    270 
    271431    PSHCLCONTEXT pCtx = &g_Ctx;
     432
     433    int rc = RTReqQueueCreate(&pCtx->X11.hReqQ);
     434    AssertRCReturn(rc, rc);
    272435
    273436    bool fShutdown = false;
     
    286449    pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT);
    287450
    288     pCtx->CmdCtx.Transfers.Callbacks.pfnOnStart      = vboxClipboardOnTransferStartCallback;
    289     pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted  = vboxClipboardOnTransferCompletedCallback;
    290     pCtx->CmdCtx.Transfers.Callbacks.pfnOnError      = vboxClipboardOnTransferErrorCallback;
     451    pCtx->CmdCtx.Transfers.Callbacks.pfnOnRegistered   = vbclX11OnHttpTransferRegisteredCallback;
     452    pCtx->CmdCtx.Transfers.Callbacks.pfnOnUnregistered = vbclX11OnHttpTransferUnregisteredCallback;
     453    pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted    = vbclX11OnHttpTransferCompletedCallback;
     454    pCtx->CmdCtx.Transfers.Callbacks.pfnOnError        = vbclX11OnHttpTransferErrorCallback;
    291455# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
    292456#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    293457
    294     /* The thread waits for incoming messages from the host. */
     458    LogFlowFunc(("fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64 ...\n",
     459                 pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures));
     460
     461    /* The thread processes incoming messages from the host and the worker queue. */
     462    PVBGLR3CLIPBOARDEVENT pEvent = NULL;
    295463    for (;;)
    296464    {
    297         PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT));
     465        if (!pEvent)
     466            pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT));
    298467        AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY);
    299 
    300         LogFlowFunc(("Waiting for host message (fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64) ...\n",
    301                      pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures));
    302468
    303469        uint32_t idMsg  = 0;
    304470        uint32_t cParms = 0;
    305         rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */);
     471        rc = VbglR3ClipboardMsgPeek(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */);
    306472        if (RT_SUCCESS(rc))
    307473        {
     
    312478#endif
    313479        }
     480        else if (rc == VERR_TRY_AGAIN) /* No new message (yet). */
     481        {
     482            RTReqQueueProcess(pCtx->X11.hReqQ, RT_MS_1SEC);
     483            continue;
     484        }
    314485
    315486        if (RT_FAILURE(rc))
     
    324495
    325496            /* Wait a bit before retrying. */
    326             RTThreadSleep(1000);
     497            RTThreadSleep(RT_MS_1SEC);
    327498            continue;
    328499        }
     
    336507                case VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS:
    337508                {
    338                     ShClX11ReportFormatsToX11(&g_Ctx.X11, pEvent->u.fReportedFormats);
     509                    ShClX11ReportFormatsToX11Async(&g_Ctx.X11, pEvent->u.fReportedFormats);
    339510                    break;
    340511                }
     
    342513                case VBGLR3CLIPBOARDEVENTTYPE_READ_DATA:
    343514                {
    344                     /* The host needs data in the specified format. */
    345                     CLIPREADCBREQ *pReq;
    346                     pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ));
    347                     if (pReq)
     515                    PSHCLEVENT pReadDataEvent;
     516                    rc = ShClEventSourceGenerateAndRegisterEvent(&pCtx->EventSrc, &pReadDataEvent);
     517                    if (RT_SUCCESS(rc))
    348518                    {
    349                         pReq->uFmt = pEvent->u.fReadData;
    350                         ShClX11ReadDataFromX11(&g_Ctx.X11, pReq->uFmt, pReq);
     519                        rc = ShClX11ReadDataFromX11Async(&g_Ctx.X11, pEvent->u.fReadData, UINT32_MAX, pReadDataEvent);
     520                        if (RT_SUCCESS(rc))
     521                        {
     522                            PSHCLEVENTPAYLOAD pPayload;
     523                            rc = ShClEventWait(pReadDataEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     524                            if (RT_SUCCESS(rc))
     525                            {
     526                                if (pPayload)
     527                                {
     528                                    Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE));
     529                                    PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData;
     530
     531                                    rc = VbglR3ClipboardWriteDataEx(&pCtx->CmdCtx, pEvent->u.fReadData,
     532                                                                    pResp->Read.pvData, pResp->Read.cbData);
     533
     534                                    RTMemFree(pResp->Read.pvData);
     535                                    pResp->Read.cbData = 0;
     536
     537                                    ShClPayloadFree(pPayload);
     538                                }
     539                            }
     540                        }
     541
     542                        ShClEventRelease(pReadDataEvent);
     543                        pReadDataEvent = NULL;
    351544                    }
    352                     else
    353                         rc = VERR_NO_MEMORY;
     545
     546                    if (RT_FAILURE(rc))
     547                        VbglR3ClipboardWriteDataEx(&pCtx->CmdCtx, pEvent->u.fReadData, NULL, 0);
     548
    354549                    break;
    355550                }
     
    365560                case VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS:
    366561                {
    367                     /* Nothing to do here. */
     562                    if (pEvent->u.TransferStatus.Report.uStatus == SHCLTRANSFERSTATUS_STARTED)
     563                    {
     564
     565                    }
    368566                    rc = VINF_SUCCESS;
    369567                    break;
     
    394592    }
    395593
    396     LogFlowFuncLeaveRC(rc);
    397     return rc;
    398 }
    399 
     594    RTReqQueueDestroy(pCtx->X11.hReqQ);
     595
     596    LogFlowFuncLeaveRC(rc);
     597    return rc;
     598}
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard.h

    r99590 r100204  
    3333
    3434/**
    35  * Struct keeping a Shared Clipboard context.
     35 * Struct keeping am X11 Shared Clipboard context.
    3636 */
    3737struct SHCLCONTEXT
     
    4545    union
    4646    {
     47        /** Event source for waiting for request responses. */
     48        SHCLEVENTSOURCE  EventSrc;
    4749        /** X11 clipboard context. */
    4850        SHCLX11CTX       X11;
Note: See TracChangeset for help on using the changeset viewer.

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