Changeset 100204 in vbox for trunk/src/VBox/Additions/x11/VBoxClient
- Timestamp:
- Jun 19, 2023 9:11:37 AM (23 months ago)
- svn:sync-xref-src-repo-rev:
- 157911
- 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 40 40 #include <iprt/semaphore.h> 41 41 42 #include <VBox/log.h> 42 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD 43 #include <iprt/log.h> 44 43 45 #include <VBox/VBoxGuestLib.h> 44 46 #include <VBox/HostServices/VBoxClipboardSvc.h> … … 50 52 #include "clipboard.h" 51 53 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 */ 62 static 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 */ 78 static 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 */ 113 static 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 */ 156 static 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 */ 174 static 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 */ 187 static 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 */ 199 static 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 */ 208 static 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 */ 53 281 static DECLCALLBACK(int) vbclX11OnRequestDataFromSourceCallback(PSHCLCONTEXT pCtx, 54 282 SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) … … 58 286 LogFlowFunc(("pCtx=%p, uFmt=%#x\n", pCtx, uFmt)); 59 287 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 63 295 if (uFmt == VBOX_SHCL_FMT_URI_LIST) 64 296 { 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) 94 304 { 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 } 98 321 } 99 322 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")); 110 324 } 111 325 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 */ 122 329 123 330 if (RT_FAILURE(rc)) … … 129 336 130 337 /** 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 */ 340 static 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 */ 141 359 static DECLCALLBACK(int) vbclX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats, void *pvUser) 142 360 { 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; 168 369 } 169 370 … … 181 382 Callbacks.pfnReportFormats = vbclX11ReportFormatsCallback; 182 383 Callbacks.pfnOnRequestDataFromSource = vbclX11OnRequestDataFromSourceCallback; 183 Callbacks.pfnOnSendDataToDest = vbclX11OnSendDataToDestCallback;184 384 185 385 int rc = ShClX11Init(&g_Ctx.X11, &Callbacks, &g_Ctx, false /* fHeadless */); … … 220 420 } 221 421 222 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP223 /** @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 262 422 /** 263 423 * The main loop of the X11-specifc Shared Clipboard code. 264 424 * 265 425 * @returns VBox status code. 426 * 427 * @thread Clipboard service worker thread. 266 428 */ 267 429 int VBClX11ClipboardMain(void) 268 430 { 269 int rc;270 271 431 PSHCLCONTEXT pCtx = &g_Ctx; 432 433 int rc = RTReqQueueCreate(&pCtx->X11.hReqQ); 434 AssertRCReturn(rc, rc); 272 435 273 436 bool fShutdown = false; … … 286 449 pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT); 287 450 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; 291 455 # endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */ 292 456 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 293 457 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; 295 463 for (;;) 296 464 { 297 PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 465 if (!pEvent) 466 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 298 467 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));302 468 303 469 uint32_t idMsg = 0; 304 470 uint32_t cParms = 0; 305 rc = VbglR3ClipboardMsgPeek Wait(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */);471 rc = VbglR3ClipboardMsgPeek(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */); 306 472 if (RT_SUCCESS(rc)) 307 473 { … … 312 478 #endif 313 479 } 480 else if (rc == VERR_TRY_AGAIN) /* No new message (yet). */ 481 { 482 RTReqQueueProcess(pCtx->X11.hReqQ, RT_MS_1SEC); 483 continue; 484 } 314 485 315 486 if (RT_FAILURE(rc)) … … 324 495 325 496 /* Wait a bit before retrying. */ 326 RTThreadSleep( 1000);497 RTThreadSleep(RT_MS_1SEC); 327 498 continue; 328 499 } … … 336 507 case VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS: 337 508 { 338 ShClX11ReportFormatsToX11 (&g_Ctx.X11, pEvent->u.fReportedFormats);509 ShClX11ReportFormatsToX11Async(&g_Ctx.X11, pEvent->u.fReportedFormats); 339 510 break; 340 511 } … … 342 513 case VBGLR3CLIPBOARDEVENTTYPE_READ_DATA: 343 514 { 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)) 348 518 { 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; 351 544 } 352 else 353 rc = VERR_NO_MEMORY; 545 546 if (RT_FAILURE(rc)) 547 VbglR3ClipboardWriteDataEx(&pCtx->CmdCtx, pEvent->u.fReadData, NULL, 0); 548 354 549 break; 355 550 } … … 365 560 case VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS: 366 561 { 367 /* Nothing to do here. */ 562 if (pEvent->u.TransferStatus.Report.uStatus == SHCLTRANSFERSTATUS_STARTED) 563 { 564 565 } 368 566 rc = VINF_SUCCESS; 369 567 break; … … 394 592 } 395 593 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 33 33 34 34 /** 35 * Struct keeping a Shared Clipboard context.35 * Struct keeping am X11 Shared Clipboard context. 36 36 */ 37 37 struct SHCLCONTEXT … … 45 45 union 46 46 { 47 /** Event source for waiting for request responses. */ 48 SHCLEVENTSOURCE EventSrc; 47 49 /** X11 clipboard context. */ 48 50 SHCLX11CTX X11;
Note:
See TracChangeset
for help on using the changeset viewer.