Changeset 85537 in vbox for trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
- Timestamp:
- Jul 30, 2020 6:55:32 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r85451 r85537 62 62 int getRC(void) const { return mRC; } 63 63 bool isOk(void) const { return RT_SUCCESS(mRC); } 64 const ComObjPtr<GuestDnDTarget> &getTarget(void) const { return mTarget; }65 64 66 65 protected: … … 87 86 void handler() 88 87 { 89 GuestDnDTarget::i_sendDataThreadTask(this); 90 } 91 92 virtual ~GuestDnDSendDataTask(void) 93 { 94 if (mpCtx) 95 { 96 delete mpCtx; 97 mpCtx = NULL; 98 } 99 } 100 101 102 GuestDnDSendCtx *getCtx(void) { return mpCtx; } 88 const ComObjPtr<GuestDnDTarget> pThis(mTarget); 89 Assert(!pThis.isNull()); 90 91 AutoCaller autoCaller(pThis); 92 if (FAILED(autoCaller.rc())) 93 return; 94 95 int vrc = pThis->i_sendData(mpCtx, RT_INDEFINITE_WAIT /* msTimeout */); 96 if (RT_FAILURE(vrc)) /* In case we missed some error handling within i_sendData(). */ 97 { 98 if (vrc != VERR_CANCELLED) 99 LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc)); 100 101 /* Make sure to fire a cancel request to the guest side in case something went wrong. */ 102 pThis->sendCancel(); 103 } 104 } 105 106 virtual ~GuestDnDSendDataTask(void) { } 103 107 104 108 protected: … … 295 299 296 300 LogRel2(("DnD: Offered formats to guest:\n")); 297 RTCList<RTCString> lstFormats = strFormats.split( "\r\n");301 RTCList<RTCString> lstFormats = strFormats.split(DND_PATH_SEPARATOR); 298 302 for (size_t i = 0; i < lstFormats.size(); i++) 299 303 LogRel2(("DnD: \t%s\n", lstFormats[i].c_str())); … … 307 311 308 312 /* Adjust the coordinates in a multi-monitor setup. */ 309 int rc = G UESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);313 int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY); 310 314 if (RT_SUCCESS(rc)) 311 315 { … … 322 326 Msg.setNextUInt32(cbFormats); 323 327 324 rc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());328 rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 325 329 if (RT_SUCCESS(rc)) 326 330 { 327 GuestDnDResponse *pResp = G UESTDNDINST()->response();331 GuestDnDResponse *pResp = GuestDnDInst()->response(); 328 332 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse())) 329 333 resAction = GuestDnD::toMainAction(pResp->getActionDefault()); … … 385 389 HRESULT hr = S_OK; 386 390 387 int rc = G UESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);391 int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY); 388 392 if (RT_SUCCESS(rc)) 389 393 { … … 400 404 Msg.setNextUInt32(cbFormats); 401 405 402 rc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());406 rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 403 407 if (RT_SUCCESS(rc)) 404 408 { 405 GuestDnDResponse *pResp = G UESTDNDINST()->response();409 GuestDnDResponse *pResp = GuestDnDInst()->response(); 406 410 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse())) 407 411 resAction = GuestDnD::toMainAction(pResp->getActionDefault()); … … 440 444 Msg.setNextUInt32(0); /** @todo ContextID not used yet. */ 441 445 442 int rc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());446 int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 443 447 if (RT_SUCCESS(rc)) 444 448 { 445 GuestDnDResponse *pResp = G UESTDNDINST()->response();449 GuestDnDResponse *pResp = GuestDnDInst()->response(); 446 450 if (pResp) 447 451 pResp->waitForGuestResponse(); … … 479 483 480 484 /* Default action is ignoring. */ 481 DnDAction_T resAction = DnDAction_Ignore; 485 DnDAction_T resAct = DnDAction_Ignore; 486 Utf8Str resFmt; 482 487 483 488 /* Check & convert the drag & drop actions to HGCM codes. */ … … 507 512 508 513 /* Adjust the coordinates in a multi-monitor setup. */ 509 HRESULT hr = G UESTDNDINST()->adjustScreenCoordinates(aScreenId, &aX, &aY);514 HRESULT hr = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY); 510 515 if (SUCCEEDED(hr)) 511 516 { … … 522 527 Msg.setNextUInt32(cbFormats); 523 528 524 int vrc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());529 int vrc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 525 530 if (RT_SUCCESS(vrc)) 526 531 { 527 GuestDnDResponse *pResp = GUESTDNDINST()->response(); 528 AssertPtr(pResp); 529 530 vrc = pResp->waitForGuestResponse(); 531 if (RT_SUCCESS(vrc)) 532 GuestDnDResponse *pResp = GuestDnDInst()->response(); 533 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse())) 532 534 { 533 resAct ion= GuestDnD::toMainAction(pResp->getActionDefault());535 resAct = GuestDnD::toMainAction(pResp->getActionDefault()); 534 536 535 537 GuestDnDMIMEList lstFormats = pResp->formats(); 536 538 if (lstFormats.size() == 1) /* Exactly one format to use specified? */ 537 539 { 538 aFormat = lstFormats.at(0); 539 LogFlowFunc(("resFormat=%s, resAction=%RU32\n", aFormat.c_str(), pResp->getActionDefault())); 540 resFmt = lstFormats.at(0); 540 541 } 541 542 else … … 552 553 hr = setError(hr, tr("Retrieving drop coordinates failed")); 553 554 555 LogFlowFunc(("resFmt=%s, resAct=%RU32, vrc=%Rhrc\n", resFmt.c_str(), resAct, hr)); 556 554 557 if (SUCCEEDED(hr)) 555 558 { 559 aFormat = resFmt; 556 560 if (aResultAction) 557 *aResultAction = resAction; 558 } 559 560 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); 561 *aResultAction = resAct; 562 } 563 561 564 return hr; 562 565 #endif /* VBOX_WITH_DRAG_AND_DROP */ 563 }564 565 /**566 * Thread handler function for sending data to the guest.567 *568 * @param pTask Thread task this handler is associated with.569 */570 /* static */571 void GuestDnDTarget::i_sendDataThreadTask(GuestDnDSendDataTask *pTask)572 {573 LogFlowFunc(("pTask=%p\n", pTask));574 AssertPtrReturnVoid(pTask);575 576 const ComObjPtr<GuestDnDTarget> pThis(pTask->getTarget());577 Assert(!pThis.isNull());578 579 AutoCaller autoCaller(pThis);580 if (FAILED(autoCaller.rc()))581 return;582 583 int vrc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */);584 if (RT_FAILURE(vrc)) /* In case we missed some error handling within i_sendData(). */585 {586 AssertFailed();587 LogRel(("DnD: Sending data to guest failed with %Rrc\n", vrc));588 }589 590 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);591 592 Assert(pThis->m_DataBase.cTransfersPending);593 if (pThis->m_DataBase.cTransfersPending)594 pThis->m_DataBase.cTransfersPending--;595 596 LogFlowFunc(("pTarget=%p, vrc=%Rrc (ignored)\n", (GuestDnDTarget *)pThis, vrc));597 566 } 598 567 … … 626 595 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 627 596 597 /* Check if this object still is in a pending state and bail out if so. */ 598 if (m_fIsPending) 599 return setError(E_FAIL, tr("Current drop operation to guest still in progress")); 600 601 /* Reset our internal state. */ 602 i_reset(); 603 628 604 /* At the moment we only support one transfer at a time. */ 629 if ( m_DataBase.cTransfersPending)630 return setError(E_INVALIDARG, tr("Another dr op operationalready is in progress"));631 632 /* Ditto. */633 GuestDnDResponse *pResp = G UESTDNDINST()->response();605 if (GuestDnDInst()->getTargetCount()) 606 return setError(E_INVALIDARG, tr("Another drag and drop operation to the guest already is in progress")); 607 608 /* Reset progress object. */ 609 GuestDnDResponse *pResp = GuestDnDInst()->response(); 634 610 AssertPtr(pResp); 635 636 611 HRESULT hr = pResp->resetProgress(m_pGuest); 637 612 if (FAILED(hr)) 638 613 return hr; 639 614 640 GuestDnDSendDataTask *pTask = NULL; 641 GuestDnDSendCtx *pSendCtx = NULL; 615 GuestDnDSendDataTask *pTask = NULL; 642 616 643 617 try 644 618 { 645 /* pSendCtx is passed into SendDataTask where one is deleted in destructor. */ 646 pSendCtx = new GuestDnDSendCtx(); 647 pSendCtx->pTarget = this; 648 pSendCtx->pResp = pResp; 649 pSendCtx->uScreenID = aScreenId; 650 651 pSendCtx->Meta.strFmt = aFormat; 652 pSendCtx->Meta.add(aData); 653 654 /* pTask is responsible for deletion of pSendCtx after creating */ 655 pTask = new GuestDnDSendDataTask(this, pSendCtx); 619 mData.mSendCtx.reset(); 620 621 mData.mSendCtx.pTarget = this; 622 mData.mSendCtx.pResp = pResp; 623 mData.mSendCtx.uScreenID = aScreenId; 624 625 mData.mSendCtx.Meta.strFmt = aFormat; 626 mData.mSendCtx.Meta.add(aData); 627 628 pTask = new GuestDnDSendDataTask(this, &mData.mSendCtx); 656 629 if (!pTask->isOk()) 657 630 { … … 660 633 throw hr = E_FAIL; 661 634 } 662 663 /* Drop write lock before creating thread. */664 alock.release();665 635 666 636 /* This function delete pTask in case of exceptions, … … 681 651 if (SUCCEEDED(hr)) 682 652 { 683 /* Re-acquire write lock. */ 684 alock.acquire(); 685 686 m_DataBase.cTransfersPending++; 687 653 /* Register ourselves at the DnD manager. */ 654 GuestDnDInst()->registerTarget(this); 655 656 /* Return progress to caller. */ 688 657 hr = pResp->queryProgressTo(aProgress.asOutParam()); 689 658 ComAssertComRC(hr); 690 659 } 691 660 else 692 hr = setError(hr, tr("Starting thread for GuestDnDTarget ::i_sendDataThread (%Rhrc)"), hr);661 hr = setError(hr, tr("Starting thread for GuestDnDTarget failed (%Rhrc)"), hr); 693 662 694 663 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); … … 767 736 768 737 return strError; 738 } 739 740 void GuestDnDTarget::i_reset(void) 741 { 742 LogFlowThisFunc(("\n")); 743 744 mData.mSendCtx.reset(); 745 746 m_fIsPending = false; 747 748 /* Unregister ourselves from the DnD manager. */ 749 GuestDnDInst()->unregisterTarget(this); 769 750 } 770 751 … … 780 761 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 781 762 782 /* Is this context already in sending state? */ 783 if (ASMAtomicReadBool(&pCtx->fIsActive)) 784 return VERR_WRONG_ORDER; 785 ASMAtomicWriteBool(&pCtx->fIsActive, true); 763 /* Don't allow receiving the actual data until our current transfer is complete. */ 764 if (m_fIsPending) 765 return setError(E_FAIL, tr("Current drop operation to guest still in progress")); 786 766 787 767 /* Clear all remaining outgoing messages. */ … … 810 790 } 811 791 812 ASMAtomicWriteBool(&pCtx->fIsActive, false); 792 if (RT_FAILURE(rc)) 793 LogRel(("DnD: Sending data to guest failed with %Rrc\n", rc)); 794 795 /* Reset state. */ 796 i_reset(); 813 797 814 798 LogFlowFuncLeaveRC(rc); … … 839 823 840 824 #ifdef DEBUG 841 RTCList<RTCString> lstFilesURI = RTCString((char *)pvData, cbData).split( "\r\n");825 RTCList<RTCString> lstFilesURI = RTCString((char *)pvData, cbData).split(DND_PATH_SEPARATOR); 842 826 LogFlowFunc(("lstFilesURI=%zu\n", lstFilesURI.size())); 843 827 for (size_t i = 0; i < lstFilesURI.size(); i++) … … 871 855 } 872 856 873 rc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());857 rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 874 858 if (RT_FAILURE(rc)) 875 859 break; … … 907 891 908 892 LogRel2(("DnD: Sending meta data header to guest (%RU64 bytes total data, %RU32 bytes meta data, %RU64 objects)\n", 909 pCtx->getTotal (), pCtx->Meta.cbData, pCtx->Transfer.cObjToProcess));893 pCtx->getTotalAnnounced(), pCtx->Meta.cbData, pCtx->Transfer.cObjToProcess)); 910 894 911 895 Msg.setNextUInt32(0); /** @todo uContext; not used yet. */ 912 896 Msg.setNextUInt32(0); /** @todo uFlags; not used yet. */ 913 897 Msg.setNextUInt32(pCtx->uScreenID); /* uScreen */ 914 Msg.setNextUInt64(pCtx->getTotal ());/* cbTotal */898 Msg.setNextUInt64(pCtx->getTotalAnnounced()); /* cbTotal */ 915 899 Msg.setNextUInt32((uint32_t)pCtx->Meta.cbData); /* cbMeta*/ 916 900 Msg.setNextPointer(unconst(pCtx->Meta.strFmt.c_str()), (uint32_t)pCtx->Meta.strFmt.length() + 1); /* pvMetaFmt */ … … 922 906 Msg.setNextUInt32(0); /** @todo cbChecksum; not used yet. */ 923 907 924 int rc = G UESTDNDINST()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());908 int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 925 909 926 910 LogFlowFuncLeaveRC(rc); … … 1398 1382 * Update internal state to reflect everything we need to work with it. 1399 1383 */ 1400 pCtx->cbExtra = DnDTransferListObjTotalBytes(&pCtx->Transfer.List);1384 pCtx->cbExtra = DnDTransferListObjTotalBytes(&pCtx->Transfer.List); 1401 1385 /* cbExtra can be 0, if all files are of 0 bytes size. */ 1402 1386 pCtx->Transfer.cObjToProcess = DnDTransferListObjCount(&pCtx->Transfer.List); … … 1431 1415 pCtx->Meta.cbData = cbData; 1432 1416 pCtx->Meta.cbAllocated = cbData; 1417 pCtx->Meta.cbAnnounced = cbData; 1433 1418 } 1434 1419 … … 1530 1515 AssertRCReturn(rc, rc); 1531 1516 1532 if (pCtx->isComplete()) 1533 { 1534 Assert(pCtx->Transfer.isComplete()); 1517 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pList); 1518 if (!pObj) /* Transfer complete? */ 1535 1519 return VINF_EOF; 1536 }1537 1538 PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pList);1539 AssertPtrReturn(pObj, VERR_WRONG_ORDER);1540 1520 1541 1521 switch (DnDTransferObjectGetType(pObj))
Note:
See TracChangeset
for help on using the changeset viewer.