Changeset 50460 in vbox
- Timestamp:
- Feb 14, 2014 9:46:58 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 92295
- Location:
- trunk
- Files:
-
- 15 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/DragAndDropSvc.h
r50305 r50460 97 97 /** The host informs the guest that a DnD drop operation 98 98 * has been started and that the host wants the data in 99 * a specific mime-type. */99 * a specific MIME type. */ 100 100 HOST_DND_GH_EVT_DROPPED, 101 101 … … 134 134 */ 135 135 GUEST_DND_GH_ACK_PENDING = 500, 136 /** 137 * Sends data of the requsted MIME type to the host. There can 138 * be more than one message if the actual data does not fit 139 * into one. 140 */ 136 141 GUEST_DND_GH_SND_DATA, 137 142 GUEST_DND_GH_EVT_ERROR, -
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r50101 r50460 51 51 VBoxDnDDropSource.cpp \ 52 52 VBoxDnDDropTarget.cpp 53 VBoxTray_LIBS += \ 54 $(PATH_STAGE_LIB)/additions/VBoxDnDGuestR3Lib$(VBOX_SUFF_LIB) 53 55 endif 54 56 ifdef VBOX_WITH_GUEST_PROPS -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
r50399 r50460 1402 1402 1403 1403 rc = VbglR3DnDProcessNextMessage(uClientID, &pEvent->Event); 1404 LogFlowFunc(("VbglR3DnDProcessNextMessage returned rc=%Rrc\n", rc)); 1404 LogFlowFunc(("VbglR3DnDProcessNextMessage returned uType=%RU32, rc=%Rrc\n", 1405 pEvent->Event.uType, rc)); 1405 1406 1406 1407 if (ASMAtomicReadBool(&pCtx->fShutdown)) -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp
r50101 r50460 27 27 #include "VBoxDnD.h" 28 28 29 #ifdef DEBUG 30 /* Enable the following line to get much more debug output about 31 * (un)known clipboard formats. */ 32 //#define VBOX_DND_DEBUG_FORMATS 33 #endif 34 29 35 /** @todo Implement IDataObjectAsyncCapability interface? */ 30 36 … … 188 194 AssertPtrReturn(pMedium, DV_E_FORMATETC); 189 195 190 LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));191 192 196 ULONG lIndex; 193 197 if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */ … … 195 199 if (lIndex >= mcFormats) /* Paranoia. */ 196 200 return DV_E_FORMATETC; 201 202 LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium)); 197 203 198 204 FORMATETC *pThisFormat = &mpFormatEtc[lIndex]; … … 474 480 const char* VBoxDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt) 475 481 { 482 #ifdef VBOX_DND_DEBUG_FORMATS 476 483 char szFormat[128]; 477 484 if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat))) 478 485 LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat)); 486 #endif 479 487 480 488 switch (fmt) … … 572 580 } 573 581 582 #ifdef VBOX_DND_DEBUG_FORMATS 574 583 LogFlowFunc(("Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n", 575 584 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), 576 585 pFormatEtc->dwAspect)); 577 586 #endif 578 587 return false; 579 588 } -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r50305 r50460 39 39 40 40 #include "VBGLR3Internal.h" 41 #include "VBox/GuestHost/DragAndDrop.h" 41 42 #include "VBox/HostServices/DragAndDropSvc.h" 42 43 … … 47 48 * Todo: 48 49 * - Sending dirs/files in the G->H case 49 * - Maybe the EOL converting of text mime-types (not fully sure, eventually50 * - Maybe the EOL converting of text MIME types (not fully sure, eventually 50 51 * better done on the host side) 51 52 */ 52 53 static int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath);54 53 55 54 /****************************************************************************** 56 55 * Private internal functions * 57 56 ******************************************************************************/ 58 59 static int vbglR3DnDCreateDropDir(char* pszDropDir, size_t cbSize)60 {61 AssertPtrReturn(pszDropDir, VERR_INVALID_POINTER);62 AssertReturn(cbSize, VERR_INVALID_PARAMETER);63 64 /** @todo On Windows we also could use the registry to override65 * this path, on Posix a dotfile and/or a guest property66 * can be used. */67 68 /* Get the users temp directory. Don't use the user's root directory (or69 * something inside it) because we don't know for how long/if the data will70 * be kept after the guest OS used it. */71 int rc = RTPathTemp(pszDropDir, cbSize);72 if (RT_FAILURE(rc))73 return rc;74 75 /* Append our base drop directory. */76 rc = RTPathAppend(pszDropDir, cbSize, "VirtualBox Dropped Files");77 if (RT_FAILURE(rc))78 return rc;79 80 /* Create it when necessary. */81 if (!RTDirExists(pszDropDir))82 {83 rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);84 if (RT_FAILURE(rc))85 return rc;86 }87 88 /* The actually drop directory consist of the current time stamp and a89 * unique number when necessary. */90 char pszTime[64];91 RTTIMESPEC time;92 if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))93 return VERR_BUFFER_OVERFLOW;94 rc = vbglR3DnDPathSanitize(pszTime, sizeof(pszTime));95 if (RT_FAILURE(rc))96 return rc;97 98 rc = RTPathAppend(pszDropDir, cbSize, pszTime);99 if (RT_FAILURE(rc))100 return rc;101 102 /* Create it (only accessible by the current user) */103 return RTDirCreateUniqueNumbered(pszDropDir, cbSize, RTFS_UNIX_IRWXU, 3, '-');104 }105 57 106 58 static int vbglR3DnDQueryNextHostMessageType(uint32_t uClientId, uint32_t *puMsg, uint32_t *pcParms, bool fWait) … … 319 271 AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER); 320 272 273 if (!*pcbDataRecv) 274 return VERR_INVALID_PARAMETER; 275 321 276 /* Make a string list out of the uri data. */ 322 RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); 277 RTCList<RTCString> uriList = 278 RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); 323 279 if (uriList.isEmpty()) 324 280 return VINF_SUCCESS; … … 331 287 /* Create and query the (unique) drop target directory. */ 332 288 char pszDropDir[RTPATH_MAX]; 333 int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));289 int rc = DnDDirCreateDroppedFiles(pszDropDir, sizeof(pszDropDir)); 334 290 if (RT_FAILURE(rc)) 335 291 { … … 349 305 if (pszFilePath) 350 306 { 351 rc = vbglR3DnDPathSanitize(pszFilePath, strlen(pszFilePath));307 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath)); 352 308 if (RT_FAILURE(rc)) 353 309 break; 354 310 355 311 /** @todo Use RTPathJoin? */ 356 RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); 312 RTCString strFullPath 313 = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); 357 314 char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); 358 315 if (pszNewUri) … … 376 333 } 377 334 378 /* Lists for holding created files & directories in the case of a379 * rollback. */335 /* Lists for holding created files & directories 336 * in the case of a rollback. */ 380 337 RTCList<RTCString> guestDirList; 381 338 RTCList<RTCString> guestFileList; 382 char pszPath name[RTPATH_MAX];339 char pszPathName[RTPATH_MAX]; 383 340 uint32_t cbPathname = 0; 384 341 bool fLoop = RT_SUCCESS(rc); /* No error occurred yet? */ … … 396 353 uint32_t fMode = 0; 397 354 rc = vbglR3DnDHGProcessSendDirMessage(uClientId, 398 pszPath name,399 sizeof(pszPath name),355 pszPathName, 356 sizeof(pszPathName), 400 357 &cbPathname, 401 358 &fMode); 402 359 if (RT_SUCCESS(rc)) 403 rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));360 rc = DnDPathSanitize(pszPathName, sizeof(pszPathName)); 404 361 if (RT_SUCCESS(rc)) 405 362 { 406 char *pszNewDir = RTPathJoinA(pszDropDir, pszPath name);363 char *pszNewDir = RTPathJoinA(pszDropDir, pszPathName); 407 364 if (pszNewDir) 408 365 { … … 423 380 uint32_t fMode = 0; 424 381 rc = vbglR3DnDHGProcessSendFileMessage(uClientId, 425 pszPath name,426 sizeof(pszPath name),382 pszPathName, 383 sizeof(pszPathName), 427 384 &cbPathname, 428 385 pvTmpData, … … 431 388 &fMode); 432 389 if (RT_SUCCESS(rc)) 433 rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));390 rc = DnDPathSanitize(pszPathName, sizeof(pszPathName)); 434 391 if (RT_SUCCESS(rc)) 435 392 { 436 char *pszNewFile = RTPathJoinA(pszDropDir, pszPath name);393 char *pszNewFile = RTPathJoinA(pszDropDir, pszPathName); 437 394 if (pszNewFile) 438 395 { … … 666 623 { 667 624 /* Check if this is an URI event. If so, let VbglR3 do all the actual 668 * data transfer + file 625 * data transfer + file/directory creation internally without letting 669 626 * the caller know. 670 627 * … … 747 704 } 748 705 749 return rc;750 }751 752 static int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath)753 {754 int rc = VINF_SUCCESS;755 #ifdef RT_OS_WINDOWS756 /* Filter out characters not allowed on Windows platforms, put in by757 RTTimeSpecToString(). */758 /** @todo Use something like RTPathSanitize() when available. Later. */759 RTUNICP aCpSet[] =760 { ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_',761 0xa0, 0xd7af, '\0' };762 ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, aCpSet, '_' /* Replacement */);763 if (cReplaced < 0)764 rc = VERR_INVALID_UTF8_ENCODING;765 #endif766 706 return rc; 767 707 } … … 886 826 break; 887 827 } 828 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 888 829 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING: 889 830 { … … 908 849 break; 909 850 } 851 #endif 910 852 default: 853 { 854 pEvent->uType = uMsg; 855 911 856 rc = VERR_NOT_SUPPORTED; 912 857 break; 858 } 913 859 } 914 860 } … … 979 925 } 980 926 981 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData) 927 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, 928 void *pvData, uint32_t cbData) 982 929 { 983 930 AssertPtrReturn(pvData, VERR_INVALID_POINTER); … … 993 940 994 941 int rc = VINF_SUCCESS; 995 uint32_t cbMax = _ 1M; /** @todo Remove 1 MB limit. */942 uint32_t cbMax = _64K; /* Transfer max. 64K chunks per message. */ 996 943 uint32_t cbSent = 0; 997 944 998 945 while (cbSent < cbData) 999 946 { 1000 /* Initialize parameter */1001 947 uint32_t cbToSend = RT_MIN(cbData - cbSent, cbMax); 1002 948 Msg.pData.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbToSend); 1003 /* Do request */ 949 1004 950 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1005 951 if (RT_SUCCESS(rc)) 1006 {1007 952 rc = Msg.hdr.result; 1008 /* Did the host cancel the event? */ 1009 if (rc == VERR_CANCELLED) 1010 break; 1011 } 1012 else 953 954 if (RT_FAILURE(rc)) 1013 955 break; 956 1014 957 cbSent += cbToSend; 1015 // RTThreadSleep(500); 1016 } 958 } 959 960 if (RT_SUCCESS(rc)) 961 Assert(cbSent == cbData); 1017 962 1018 963 return rc; -
trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk
r50338 r50460 75 75 VBoxClient_SOURCES += \ 76 76 draganddrop.cpp 77 VBoxClient_LIBS += \ 78 $(PATH_STAGE_LIB)/additions/VBoxDnDGuestR3Lib$(VBOX_SUFF_LIB) 77 79 endif 78 80 -
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r50305 r50460 455 455 ifdef VBOX_WITH_DRAG_AND_DROP_GH 456 456 VirtualBox_QT_MOCHDRS += \ 457 src/runtime/UIDnDMIMEData.h 457 src/runtime/UIDnDMIMEData.h \ 458 src/runtime/UIDnDDrag.h 458 459 endif 459 460 endif … … 492 493 493 494 ifdef VBOX_WITH_DRAG_AND_DROP 495 VirtualBox_QT_MOCSRCS += \ 496 src/runtime/UIDnDHandler.cpp 494 497 ifdef VBOX_WITH_DRAG_AND_DROP_GH 495 498 VirtualBox_QT_MOCSRCS += \ 499 src/runtime/UIDnDDrag.cpp \ 496 500 src/runtime/UIDnDMIMEData.cpp 497 501 endif … … 781 785 ifdef VBOX_WITH_DRAG_AND_DROP_GH 782 786 VirtualBox_SOURCES += \ 783 src/runtime/UIDnDMIMEData.cpp 784 VirtualBox_QT_MOCSRCS += \ 785 src/runtime/UIDnDMIMEData.cpp 787 src/runtime/UIDnDMIMEData.cpp \ 788 src/runtime/UIDnDDrag.cpp 789 VirtualBox_SOURCES.win += \ 790 src/runtime/UIDnDDropSource_win.cpp \ 791 src/runtime/UIDnDDataObject_win.cpp \ 792 src/runtime/UIDnDEnumFormat_win.cpp 786 793 endif 787 794 endif -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
r50306 r50460 34 34 #include "UIDnDHandler.h" 35 35 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 36 # include "UIDnD MIMEData.h"36 # include "UIDnDDrag.h" 37 37 #endif 38 38 #include "UIMessageCenter.h" … … 46 46 47 47 UIDnDHandler::UIDnDHandler(void) 48 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 49 : pMData(NULL) 50 #endif 48 : mMode(Unknown) 51 49 { 52 50 } … … 60 58 const QMimeData *pMimeData, QWidget * /* pParent = NULL */) 61 59 { 60 if (mMode == GH) /* Wrong mode? Bail out. */ 61 return Qt::IgnoreAction; 62 62 63 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", 63 64 screenId, x, y, toVBoxDnDAction(proposedAction))); … … 78 79 const QMimeData *pMimeData, QWidget * /* pParent = NULL */) 79 80 { 81 if (mMode == GH) /* Wrong mode? Bail out. */ 82 return Qt::IgnoreAction; 83 80 84 #ifdef DEBUG_andy 81 85 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", … … 99 103 const QMimeData *pMimeData, QWidget *pParent /* = NULL */) 100 104 { 105 if (mMode == GH) /* Wrong mode? Bail out. */ 106 return Qt::IgnoreAction; 107 101 108 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", 102 109 screenId, x, y, toVBoxDnDAction(proposedAction))); … … 114 121 if (result != KDragAndDropAction_Ignore) 115 122 { 116 /* Get the actual ly data*/123 /* Get the actual MIME data in the requested format. */ 117 124 const QByteArray &d = pMimeData->data(format); 118 125 if ( !d.isEmpty() 119 126 && !format.isEmpty()) 120 127 { 121 /* We need the data in the vector format. */ 128 /* Convert the actual MIME data to a vector (needed 129 * for the COM wrapper). */ 122 130 QVector<uint8_t> dv(d.size()); 123 131 memcpy(dv.data(), d.constData(), d.size()); … … 126 134 if (guest.isOk()) 127 135 { 128 msgCenter().showModalProgressDialog(progress, tr("Dropping data ..."), ":/progress_dnd_hg_90px.png", pParent); 129 if (!progress.GetCanceled() && (!progress.isOk() || progress.GetResultCode() != 0)) 136 msgCenter().showModalProgressDialog(progress, 137 tr("Dropping data ..."), ":/progress_dnd_hg_90px.png", 138 pParent); 139 if ( !progress.GetCanceled() 140 && ( !progress.isOk() 141 || progress.GetResultCode() != 0)) 130 142 { 131 143 msgCenter().cannotDropData(progress, pParent); … … 146 158 void UIDnDHandler::dragHGLeave(CGuest &guest, ulong screenId, QWidget * /* pParent = NULL */) 147 159 { 160 if (mMode == GH) /* Wrong mode? Bail out. */ 161 return; 162 148 163 LogFlowFunc(("screenId=%RU32\n", screenId)); 149 164 guest.DragHGLeave(screenId); … … 154 169 int rc; 155 170 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 171 if (mMode == HG) /* Wrong mode? Bail out. */ 172 return VERR_WRONG_ORDER; 173 156 174 /* 157 175 * How this works: Host is asking the guest if there is any DnD … … 169 187 LogFlowFunc(("defaultAction=%d, numFormats=%d\n", defaultAction, vecFmtGuest.size())); 170 188 171 /*172 * Do guest -> host format conversion, if needed.173 * On X11 this already maps to the Xdnd protocol.174 ** @todo What about the MacOS Carbon Drag Manager? Needs testing.175 *176 * See: https://www.iana.org/assignments/media-types/media-types.xhtml177 */178 LogFlowFunc(("Number of guest formats: %d\n", vecFmtGuest.size()));179 189 QStringList lstFmtNative; 180 for (int i = 0; i < vecFmtGuest.size(); i++)190 if (defaultAction != KDragAndDropAction_Ignore) 181 191 { 182 const QString &strFmtGuest = vecFmtGuest.at(i); 183 LogFlowFunc(("\tFormat %d: %s\n", i, 184 strFmtGuest.toAscii().constData())); 192 /* 193 * Do guest -> host format conversion, if needed. 194 * On X11 this already maps to the Xdnd protocol. 195 ** @todo What about the MacOS Carbon Drag Manager? Needs testing. 196 * 197 * See: https://www.iana.org/assignments/media-types/media-types.xhtml 198 */ 199 LogFlowFunc(("Number of guest formats: %d\n", vecFmtGuest.size())); 200 for (int i = 0; i < vecFmtGuest.size(); i++) 201 { 202 const QString &strFmtGuest = vecFmtGuest.at(i); 203 LogFlowFunc(("\tFormat %d: %s\n", i, 204 strFmtGuest.toAscii().constData())); 185 205 # ifdef RT_OS_WINDOWS 186 /* CF_TEXT */187 if ( strFmtGuest.contains("text/plain", Qt::CaseInsensitive)188 && !lstFmtNative.contains("text/plain"))189 {190 lstFmtNative << "text/plain";191 }192 /* CF_HDROP */193 else if ( strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)194 && !lstFmtNative.contains("text/uri-list"))195 {196 lstFmtNative << "text/uri-list";197 }206 /* CF_TEXT */ 207 if ( strFmtGuest.contains("text/plain", Qt::CaseInsensitive) 208 && !lstFmtNative.contains("text/plain")) 209 { 210 lstFmtNative << "text/plain"; 211 } 212 /* CF_HDROP */ 213 else if ( strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive) 214 && !lstFmtNative.contains("text/uri-list")) 215 { 216 lstFmtNative << "text/uri-list"; 217 } 198 218 # else 199 /* On non-Windows just do a 1:1 mapping. */200 lstFmtNative << strFmtGuest;219 /* On non-Windows just do a 1:1 mapping. */ 220 lstFmtNative << strFmtGuest; 201 221 # ifdef RT_OS_MACOS 202 /** @todo Does the mapping apply here? Don't think so ... */222 /** @todo Does the mapping apply here? Don't think so ... */ 203 223 # endif 204 224 # endif /* !RT_OS_WINDOWS */ 225 } 226 227 LogFlowFunc(("Number of native formats: %d\n", lstFmtNative.size())); 228 # ifdef DEBUG 229 for (int i = 0; i < lstFmtNative.size(); i++) 230 LogFlowFunc(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData())); 231 # endif 205 232 } 206 233 207 LogFlowFunc(("Number of native formats: %d\n", lstFmtNative.size())); 208 # ifdef DEBUG 209 for (int i = 0; i < lstFmtNative.size(); i++) 210 LogFlowFunc(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData())); 211 # endif 212 213 if ( defaultAction != KDragAndDropAction_Ignore 214 && !lstFmtNative.isEmpty()) 234 if (!lstFmtNative.isEmpty()) 215 235 { 216 236 try 217 237 { 218 QDrag *pDrag = new QDrag(pParent); 219 220 /* pMData is transfered to the QDrag object, so no need for deletion. */ 221 pMData = new UIDnDMimeData(session, lstFmtNative, 222 toQtDnDAction(defaultAction), 223 toQtDnDActions(vecActions), pParent); 224 225 /* Inform this object that MIME data from the guest is available so that 226 * it can update the MIME data object accordingly. */ 227 connect(pMData, SIGNAL(sigDataAvailable(QString)), 228 this, SLOT(sltDataAvailable(QString)), Qt::DirectConnection); 229 230 /* Inform the MIME data object of any changes in the current action. */ 231 connect(pDrag, SIGNAL(actionChanged(Qt::DropAction)), 232 pMData, SLOT(sltDropActionChanged(Qt::DropAction))); 233 234 /* Fire it up. 235 * 236 * On Windows this will start a modal operation using OLE's 237 * DoDragDrop() method, so this call will block until the DnD operation 238 * is finished. */ 239 pDrag->setMimeData(pMData); 240 Qt::DropAction dropAction = 241 pDrag->exec(toQtDnDActions(vecActions), toQtDnDAction(defaultAction)); 242 LogFlowFunc(("dropAction=%ld\n", toVBoxDnDAction(dropAction))); 243 # ifdef RT_OS_WINDOWS 244 /* Since the QDrag::exec() call above was blocking on Windows, decide what 245 * to do now, e.g. if there was a "drop" action. 246 * 247 * Note: The UIDnDMimeData object will not be not accessible here anymore, 248 * since QDrag had its ownership and deleted it after the (blocking) 249 * QDrag::exec() call. */ 250 # endif 251 rc = VINF_SUCCESS; 238 UIDnDDrag *pDrag = new UIDnDDrag(session, lstFmtNative, 239 toQtDnDAction(defaultAction), 240 toQtDnDActions(vecActions), pParent); 241 rc = pDrag->DoDragDrop(); 242 243 delete pDrag; 252 244 } 253 245 catch (std::bad_alloc) … … 258 250 else 259 251 rc = VINF_SUCCESS; 260 #else 252 #else /* !VBOX_WITH_DRAG_AND_DROP_GH */ 261 253 NOREF(session); 262 254 NOREF(screenId); … … 274 266 */ 275 267 268 /* static */ 276 269 KDragAndDropAction UIDnDHandler::toVBoxDnDAction(Qt::DropAction action) 277 270 { … … 286 279 } 287 280 281 /* static */ 288 282 QVector<KDragAndDropAction> UIDnDHandler::toVBoxDnDActions(Qt::DropActions actions) 289 283 { … … 301 295 } 302 296 297 /* static */ 303 298 Qt::DropAction UIDnDHandler::toQtDnDAction(KDragAndDropAction action) 304 299 { … … 315 310 } 316 311 312 /* static */ 317 313 Qt::DropActions UIDnDHandler::toQtDnDActions(const QVector<KDragAndDropAction> &vecActions) 318 314 { … … 343 339 } 344 340 345 void UIDnDHandler::sltDataAvailable(const QString &mimeType)346 {347 #ifdef VBOX_WITH_DRAG_AND_DROP_GH348 LogFlowFunc(("pMData=0x%p, mimeType=%s\n",349 pMData, mimeType.toAscii().constData()));350 351 if (pMData)352 pMData->setData(mimeType);353 #endif354 }355 356 341 #include "UIDnDHandler.moc" 357 342 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h
r50306 r50460 35 35 36 36 public: 37 37 38 /* Singleton factory. */ 38 39 static UIDnDHandler* instance(void) … … 42 43 return m_pInstance; 43 44 } 45 44 46 static void destroy(void) 45 47 { … … 50 52 } 51 53 } 54 55 /** 56 * Current operation mode. 57 */ 58 enum Mode 59 { 60 /** Unknown mode. */ 61 Unknown = 0, 62 /** Host to guest. */ 63 HG, 64 /** Guest to host. */ 65 GH 66 }; 52 67 53 68 /* Host -> Guest. */ … … 60 75 int dragGHPending(CSession &session, ulong screenId, QWidget *pParent = NULL); 61 76 62 public slots:77 public: 63 78 64 void sltDataAvailable(const QString &mimetype); 79 static KDragAndDropAction toVBoxDnDAction(Qt::DropAction action); 80 static QVector<KDragAndDropAction> toVBoxDnDActions(Qt::DropActions actions); 81 static Qt::DropAction toQtDnDAction(KDragAndDropAction action); 82 static Qt::DropActions toQtDnDActions(const QVector<KDragAndDropAction> &vecActions); 65 83 66 84 private: … … 70 88 virtual ~UIDnDHandler(void) {} 71 89 72 /* Private helpers. */ 73 static KDragAndDropAction toVBoxDnDAction(Qt::DropAction action); 74 static QVector<KDragAndDropAction> toVBoxDnDActions(Qt::DropActions actions); 75 static Qt::DropAction toQtDnDAction(KDragAndDropAction action); 76 static Qt::DropActions toQtDnDActions(const QVector<KDragAndDropAction> &vecActions); 77 78 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 79 UIDnDMimeData *pMData; 80 friend class UIDnDMimeData; 81 #endif 90 /** The current operation mode. */ 91 Mode mMode; 82 92 }; 83 93 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
r50305 r50460 20 20 /* Qt includes: */ 21 21 #include <QApplication> 22 #include <QFileInfo> 22 23 #include <QKeyEvent> 23 24 #include <QMimeData> … … 34 35 /* GUI includes: */ 35 36 #include "UIDnDMIMEData.h" 37 #include "UIDnDDrag.h" 36 38 #include "UIMessageCenter.h" 37 39 38 40 UIDnDMimeData::UIDnDMimeData(CSession &session, QStringList formats, 39 41 Qt::DropAction defAction, Qt::DropActions actions, 40 QWidget*pParent)42 UIDnDDrag *pParent) 41 43 : m_pParent(pParent) 42 44 , m_session(session) … … 96 98 } 97 99 98 bool UIDnDMimeData::hasFormat(const QString & mimeType) const99 { 100 bool fRc = m_lstFormats.contains( mimeType);100 bool UIDnDMimeData::hasFormat(const QString &strMIMEType) const 101 { 102 bool fRc = m_lstFormats.contains(strMIMEType); 101 103 LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool)\n", 102 mimeType.toStdString().c_str(),103 fRc, QMimeData::hasFormat( mimeType)));104 strMIMEType.toStdString().c_str(), 105 fRc, QMimeData::hasFormat(strMIMEType))); 104 106 return fRc; 105 107 } 106 108 107 QVariant UIDnDMimeData::retrieveData(const QString & mimeType,109 QVariant UIDnDMimeData::retrieveData(const QString &strMIMEType, 108 110 QVariant::Type type) const 109 111 { 110 112 LogFlowFunc(("m_enmState=%d, mimeType=%s, type=%d (%s)\n", 111 m_enmState, mimeType.toStdString().c_str(),113 m_enmState, strMIMEType.toStdString().c_str(), 112 114 type, QVariant::typeToName(type))); 113 115 114 116 bool fCanDrop = true; 115 117 116 #if 0117 118 #ifdef RT_OS_WINDOWS 118 Qt::MouseButtons mouseBtns = Qt::NoButton; 119 bool fLeftBtnDown = RT_BOOL(GetAsyncKeyState(VK_LBUTTON) & 0x8000); 120 if (fLeftBtnDown) 121 mouseBtns |= Qt::LeftButton; 122 # ifdef DEBUG_andy 123 LogFlowFunc(("mouseButtons=0x%x, GetAsyncKeyState(VK_LBUTTON)=%RTbool\n", 124 mouseBtns, fLeftBtnDown)); 125 # endif 126 if (mouseBtns == Qt::NoButton) 127 m_enmState = Dropped; 128 #endif 129 #endif 130 131 #ifdef RT_OS_WINDOWS 132 /* On Windows we only will get into this function if OLE's DoDragDrop 133 * routine (called by QtDrag) decides that a drop event just happened. 134 * So just update our internal state to reflect the same as on other 135 * platforms. */ 119 /* On Windows this function will be called several times by Qt's 120 * OLE-specific internals to figure out which data formats we have 121 * to offer. So just assume we can drop data here for a start.* */ 136 122 fCanDrop = true; 137 123 #else 138 /* Mouse button released? See eventFilter for more information. */ 124 /* On non-Windows our state gets updated via an own event filter 125 * (see UIDnDMimeData::eventFilter). This filter will update the current 126 * operation state for us (based on the mouse buttons). */ 139 127 if (m_enmState != Dropped) 140 128 fCanDrop = false; … … 143 131 /* Do we support the requested MIME type? */ 144 132 if ( fCanDrop 145 && !m_lstFormats.contains( mimeType))133 && !m_lstFormats.contains(strMIMEType)) 146 134 { 147 135 LogFlowFunc(("Unsupported MIME type=%s\n", 148 mimeType.toStdString().c_str()));136 strMIMEType.toStdString().c_str())); 149 137 fCanDrop = false; 150 138 } … … 169 157 LogFlowFunc(("Skipping request, m_enmState=%d ...\n", 170 158 m_enmState)); 171 return QMimeData::retrieveData(mimeType, type); 172 } 173 174 if (m_enmState == Dragging) 175 { 176 int rc = VINF_SUCCESS; 177 178 CGuest guest = m_session.GetConsole().GetGuest(); 179 /* Start getting the data from the guest. First inform the guest we 180 * want the data in the specified MIME type. */ 181 CProgress progress = guest.DragGHDropped(mimeType, 182 UIDnDHandler::toVBoxDnDAction(m_defAction)); 183 if (guest.isOk()) 184 { 185 msgCenter().showModalProgressDialog(progress, 186 tr("Retrieving data ..."), ":/progress_dnd_gh_90px.png", 187 m_pParent); 188 if (!progress.GetCanceled()) 189 { 190 if ( progress.isOk() 191 && progress.GetResultCode() == 0) 192 { 193 /** @todo What about retrieving bigger files? Loop? */ 194 195 /* After the data successfully arrived from the guest, we query it from Main. */ 196 QVector<uint8_t> data = guest.DragGHGetData(); 197 if (!data.isEmpty()) 198 { 199 switch (type) 200 { 201 case QVariant::String: 202 { 203 m_data = QVariant(QString(reinterpret_cast<const char*>(data.data()))); 204 break; 205 } 206 207 case QVariant::ByteArray: 208 { 209 QByteArray ba(reinterpret_cast<const char*>(data.constData()), data.size()); 210 m_data = QVariant(ba); 211 break; 212 } 213 214 case QVariant::List: 215 { 216 QString strData = QString(reinterpret_cast<const char*>(data.data())); 217 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts); 218 219 m_data = QVariant(lstString); 220 break; 221 } 222 223 default: 224 AssertMsgFailed(("Should never happen, d'oh!\n")); 225 rc = VERR_NOT_SUPPORTED; 226 break; 227 } 228 } 229 /** @todo How often to retry on empty data received? */ 230 231 if (RT_SUCCESS(rc)) 232 emit sigDataAvailable(mimeType); 233 234 m_enmState = DataRetrieved; 235 } 236 else 237 msgCenter().cannotDropData(progress, m_pParent); 238 } 239 else 240 m_enmState = Canceled; 159 return QMimeData::retrieveData(strMIMEType, type); 160 } 161 162 int rc = VINF_SUCCESS; 163 if (m_enmState == Dropped) 164 { 165 AssertPtr(m_pParent); 166 rc = m_pParent->RetrieveData(strMIMEType, type, m_data); 167 if (RT_SUCCESS(rc)) 168 { 169 /* Tell ourselves that data became available. */ 170 emit sigDataAvailable(strMIMEType); 241 171 } 242 172 else 243 msgCenter().cannotDropData(guest, m_pParent); 244 } 245 246 //return QMimeData::retrieveData(mimeType, type); 247 return m_data; 173 { 174 m_enmState = Canceled; 175 } 176 } 177 178 LogFlowFunc(("Returning rc=%Rrc, m_enmState=%ld\n", 179 rc, m_enmState)); 180 return QMimeData::retrieveData(strMIMEType, type); 248 181 } 249 182 … … 327 260 for (int i = 0; i < lstData.size(); i++) 328 261 { 329 QString strURL = lstData.at(i).toString(); 330 LogFlowFunc(("\tURL: %s\n", 331 strURL.toAscii().constData())); 332 lstURL << QUrl(strURL.toAscii()); 262 QFileInfo fileInfo(lstData.at(i).toString()); 263 #ifdef DEBUG 264 LogFlowFunc(("\tURL: %s (fExists=%RTbool, fIsDir=%RTbool, cb=%RU64)\n", 265 fileInfo.absoluteFilePath().constData(), fileInfo.exists(), 266 fileInfo.isDir(), fileInfo.size())); 267 #endif 268 lstURL << QUrl::fromLocalFile(fileInfo.absoluteFilePath()); 333 269 } 334 270 LogFlowFunc(("Number of URLs: %d\n", lstURL.size())); 335 271 336 QMimeData::setUrls(f); 272 if (RT_SUCCESS(rc)) 273 QMimeData::setUrls(lstURL); 337 274 break; 338 275 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h
r50305 r50460 32 32 #include "UIDnDHandler.h" 33 33 34 /* Forward declarations: */ 35 class UIDnDDrag; 36 34 37 /** @todo Subclass QWindowsMime / QMacPasteboardMime 35 38 * to register own/more MIME types. */ … … 45 48 enum State 46 49 { 50 /** Host is in dragging state, without 51 * having retrieved the metadata from the guest yet. */ 47 52 Dragging = 0, 48 DataRetrieved, 53 /** Guest sent over the (MIME) metadata so that the 54 * host knows which DnD targets can be used. */ 55 MetaDataRetrieved, 56 /** There has been a "dropped" action which indicates 57 * that the guest can continue sending more data (if any) 58 * over to the host, based on the (MIME) metadata. */ 49 59 Dropped, 60 /** The operation has been canceled. */ 50 61 Canceled 51 62 }; … … 55 66 UIDnDMimeData(CSession &session, QStringList formats, 56 67 Qt::DropAction defAction, 57 Qt::DropActions actions, QWidget*pParent);68 Qt::DropActions actions, UIDnDDrag *pParent); 58 69 59 70 int setData(const QString &mimeType); … … 89 100 private: 90 101 91 /* Private members. */ 92 QWidget *m_pParent; 102 UIDnDDrag *m_pParent; 93 103 CSession m_session; 94 104 QStringList m_lstFormats; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
r50265 r50460 1092 1092 1093 1093 #ifdef VBOX_WITH_DRAG_AND_DROP 1094 1095 1094 void UIMachineView::dragEnterEvent(QDragEnterEvent *pEvent) 1096 1095 { … … 1178 1177 gDnD->dragGHPending(session(), screenId(), this); 1179 1178 } 1180 1181 1179 #endif /* VBOX_WITH_DRAG_AND_DROP */ 1182 1180 -
trunk/src/VBox/GuestHost/Makefile.kmk
r41477 r50460 5 5 6 6 # 7 # Copyright (C) 2008-201 2Oracle Corporation7 # Copyright (C) 2008-2014 Oracle Corporation 8 8 # 9 9 # This file is part of VirtualBox Open Source Edition (OSE), as … … 32 32 endif 33 33 34 ifdef VBOX_WITH_DRAG_AND_DROP 35 include $(PATH_SUB_CURRENT)/DragAndDrop/Makefile.kmk 36 endif 37 34 38 include $(FILE_KBUILD_SUB_FOOTER) 35 39 -
trunk/src/VBox/HostServices/DragAndDrop/Makefile.kmk
r42261 r50460 43 43 $(LIB_VMM) \ 44 44 $(LIB_RUNTIME) \ 45 $(LIB_REM) 45 $(LIB_REM) \ 46 $(PATH_STAGE_LIB)/VBoxDnDHostR3Lib$(VBOX_SUFF_LIB) 46 47 47 48 VBoxDragAndDropSvc_LDFLAGS.darwin = \ -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r50316 r50460 5 5 6 6 /* 7 * Copyright (C) 2011-201 3Oracle Corporation7 * Copyright (C) 2011-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 48 48 { 49 49 public: 50 DnDHGSendDirPrivate(const RTCString &strPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 51 : m_strPath(strPath) 52 , m_cbSize(cbSize) 53 , m_pfnProgressCallback(pfnProgressCallback) 54 , m_pvProgressUser(pvProgressUser) 50 51 DnDHGSendDirPrivate(const RTCString &strPath, 52 uint32_t fMode, uint64_t cbSize, 53 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 54 : m_strPath(strPath) 55 , m_cbSize(cbSize) 56 , m_pfnProgressCallback(pfnProgressCallback) 57 , m_pvProgressUser(pvProgressUser) 55 58 { 56 59 VBOXHGCMSVCPARM paTmpParms[3]; 57 60 paTmpParms[0].setString(m_strPath.c_str()); 58 paTmpParms[1].setUInt32( m_strPath.length() + 1);61 paTmpParms[1].setUInt32((uint32_t)(m_strPath.length() + 1)); 59 62 paTmpParms[2].setUInt32(fMode); 60 63 … … 74 77 75 78 protected: 76 RTCString m_strPath;79 RTCString m_strPath; 77 80 78 81 /* Progress stuff */ … … 90 93 { 91 94 public: 92 DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 93 virtual ~DnDHGSendFilePrivate(); 95 96 DnDHGSendFilePrivate(const RTCString &strHostPath, 97 const RTCString &strGuestPath, 98 uint32_t fMode, uint64_t cbSize, 99 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 100 virtual ~DnDHGSendFilePrivate(void); 94 101 95 102 int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 117 124 { 118 125 public: 119 DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 126 127 DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms, 128 VBOXHGCMSVCPARM paParms[], 129 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 120 130 int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 121 131 … … 149 159 { 150 160 m_paSkelParms[0].setString(m_strGuestPath.c_str()); 151 m_paSkelParms[1].setUInt32( m_strGuestPath.length() + 1);161 m_paSkelParms[1].setUInt32((uint32_t)(m_strGuestPath.length() + 1)); 152 162 m_paSkelParms[2].setPointer(NULL, 0); 153 163 m_paSkelParms[3].setUInt32(0); … … 198 208 199 209 /* Tell the guest the actual size. */ 200 paParms[3].setUInt32( cbRead);210 paParms[3].setUInt32((uint32_t)cbRead); 201 211 } 202 212 } … … 205 215 { 206 216 /* Check if we are done. */ 217 Assert(m_cbFileProcessed <= m_cbFileSize); 207 218 bool fDone = m_cbFileSize == m_cbFileProcessed; 208 219 if (!fDone) … … 231 242 { 232 243 RTFileClose(m_hCurFile); 233 m_hCurFile = 0;244 m_hCurFile = NIL_RTFILE; 234 245 } 235 246 } … … 325 336 PFNDNDPROGRESS pfnProgressCallback, 326 337 void *pvProgressUser) 327 : m_cb All(0)338 : m_cbTotal(0) 328 339 , m_cbTransfered(0) 329 340 , m_pfnProgressCallback(pfnProgressCallback) 330 341 , m_pvProgressUser(pvProgressUser) 331 342 { 343 if (cParms < 5) /* Paranoia. */ 344 return; 345 346 const char *pszFormat = static_cast<const char*>(paParms[1].u.pointer.addr); 347 uint32_t cbFormat = paParms[1].u.pointer.size; 348 349 int rc = VINF_SUCCESS; 332 350 RTCString strNewURIs; 333 351 334 /* Check the format for any uri type. */ 335 if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), 336 paParms[1].u.pointer.size)) 337 { 338 LogFlowFunc(("Old data: '%s'\n", (char*)paParms[3].u.pointer.addr)); 352 /* Do we need to build up a file tree? */ 353 if (DnDMIMEHasFileURLs(pszFormat, cbFormat)) 354 { 355 const char *pszList = static_cast<const char*>(paParms[3].u.pointer.addr); 356 AssertPtr(pszList); 357 uint32_t cbList = paParms[3].u.pointer.size; 358 Assert(cbList); 359 360 LogFlowFunc(("Old data: '%s'\n", pszList)); 339 361 340 362 /* The list is separated by newline (even if only one file is listed). */ 341 RTCList<RTCString> lstURIOrg = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr),342 paParms[3].u.pointer.size).split("\r\n");363 RTCList<RTCString> lstURIOrg 364 = RTCString(pszList, cbList).split("\r\n"); 343 365 if (!lstURIOrg.isEmpty()) 344 366 { 345 RTCList<RTCString> lstURINew; 346 for (size_t i = 0; i < lstURIOrg.size(); ++i) 347 { 348 const RTCString &strURI = lstURIOrg.at(i); 349 350 /* Query the path component of a file URI. If this hasn't a 351 * file scheme NULL is returned. */ 352 char *pszFilePath; 353 if ((pszFilePath = RTUriFilePath(strURI.c_str(), URI_FILE_FORMAT_AUTO))) 354 { 355 /* Add the path to our internal file list (recursive in 356 * the case of a directory). */ 357 char *pszFilename; 358 if ((pszFilename = RTPathFilename(pszFilePath))) 359 { 360 char *pszNewURI = RTUriFileCreate(pszFilename); 361 if (pszNewURI) 362 { 363 lstURINew.append(pszNewURI); 364 RTStrFree(pszNewURI); 365 366 buildFileTree(pszFilePath, pszFilename - pszFilePath); 367 } 368 } 369 370 RTStrFree(pszFilePath); 371 } 372 else /* Just append the raw data. */ 373 lstURINew.append(strURI); 374 } 375 376 /* We have to change the actual DnD data. Remove any host paths and 377 * just decode the filename into the new data. The guest tools will 378 * add the correct path again, before sending the DnD drop event to 379 * some window. */ 380 strNewURIs = RTCString::join(lstURINew, "\r\n") + "\r\n"; 381 382 /* Note: We don't delete the old pointer here, cause this is done 383 * by the caller. We just use the RTString data, which has the 384 * scope of this ctor. This is enough cause the data is copied in 385 * the DnDHGSendDataMessagePrivate anyway. */ 386 paParms[3].u.pointer.addr = (void*)strNewURIs.c_str(); 387 paParms[3].u.pointer.size = strNewURIs.length() + 1; 388 paParms[4].u.uint32 = strNewURIs.length() + 1; 367 rc = m_lstURI.AppendPathsFromList(lstURIOrg, 0 /* fFlags */); 368 if (RT_SUCCESS(rc)) 369 { 370 /* Add the total size of all meta data + files transferred to 371 * the message's total count. */ 372 m_cbTotal += m_lstURI.TotalBytes(); 373 374 /* We have to change the actual DnD data. Remove any host paths and 375 * just decode the filename into the new data. The guest tools will 376 * add the correct path again, before sending the DnD drop event to 377 * some window. */ 378 strNewURIs = m_lstURI.RootToString(); 379 380 /* Note: We don't delete the old pointer here, cause this is done 381 * by the caller. We just use the RTString data, which has the 382 * scope of this ctor. This is enough cause the data is copied in 383 * the DnDHGSendDataMessagePrivate anyway. */ 384 paParms[3].u.pointer.addr = (void *)strNewURIs.c_str(); 385 paParms[3].u.pointer.size = (uint32_t)(strNewURIs.length() + 1); 386 paParms[4].u.uint32 = (uint32_t)(strNewURIs.length() + 1); 387 388 LogFlowFunc(("Set new data: '%s'\n", (char*)paParms[3].u.pointer.addr)); 389 } 389 390 } 390 391 } 391 392 392 393 /* Add the size of the data to the todo list. */ 393 m_cbAll += paParms[4].u.uint32; 394 m_cbTotal += paParms[4].u.uint32; 395 LogFlowFunc(("cbTotal=%zu\n", m_cbTotal)); 394 396 395 397 /* The first message is the meta info for the data and the data itself. */ 396 398 m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, 397 399 &DnDHGSendDataMessage::progressCallback, this); 398 #ifdef DEBUG399 LogFlowFunc(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));400 LogFlowFunc(("cbAll: %zu\n", m_cbAll));401 LogFlowFunc(("cbData: %RU32\n", paParms[4].u.uint32));402 403 for (size_t i = 0; i < m_uriList.size(); ++i)404 LogFlowFunc(("file: %s : %s - %o - %ld\n",405 m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(),406 m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));407 #endif408 400 } 409 401 … … 430 422 } 431 423 432 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 424 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, 425 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 433 426 { 434 427 if (!m_pNextPathMsg) … … 444 437 } 445 438 446 /* File data to send? */439 /* File/directory data to send? */ 447 440 if (!m_pNextPathMsg) 448 441 { 449 if (m_ uriList.isEmpty())442 if (m_lstURI.IsEmpty()) 450 443 return rc; 444 451 445 /* Create new messages based on our internal path list. Currently 452 446 * this could be directories or regular files. */ 453 PathEntry nextPath = m_uriList.first();447 const DnDURIPath &nextPath = m_lstURI.First(); 454 448 try 455 449 { 450 LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n", 451 nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath.c_str(), 452 nextPath.m_fMode, nextPath.m_cbSize, 453 RTFS_IS_DIRECTORY(nextPath.m_fMode), RTFS_IS_FILE(nextPath.m_fMode))); 454 456 455 if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) 457 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_str GuestPath,456 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strDstPath, 458 457 nextPath.m_fMode, nextPath.m_cbSize, 459 &DnDHGSendDataMessage::progressCallback, this); 458 &DnDHGSendDataMessage::progressCallback, 459 this /* pvProgressUser */); 460 460 else if (RTFS_IS_FILE(nextPath.m_fMode)) 461 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_str HostPath, nextPath.m_strGuestPath,461 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strSrcPath, nextPath.m_strDstPath, 462 462 nextPath.m_fMode, nextPath.m_cbSize, 463 &DnDHGSendDataMessage::progressCallback, this); 463 &DnDHGSendDataMessage::progressCallback, 464 this /* pvProgressUser */); 464 465 else 465 AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", 466 nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); 467 468 m_uriList.removeFirst(); 466 AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n", 467 nextPath.m_fMode, nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath), 468 VERR_NO_DATA); 469 470 m_lstURI.RemoveFirst(); 469 471 } 470 472 catch(std::bad_alloc &) … … 473 475 } 474 476 } 475 476 return rc;477 }478 479 bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const480 {481 LogFlowFunc(("format %s\n", pcszFormat));482 483 /** @todo text/uri also an official variant? */484 return ( RTStrNICmp(pcszFormat, "text/uri-list", cbMax) == 0485 || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0);486 }487 488 int DnDHGSendDataMessage::buildFileTree(const char *pcszPath, size_t cbBaseLen)489 {490 RTFSOBJINFO objInfo;491 int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);492 if (RT_FAILURE(rc))493 return rc;494 495 /*496 * These are the types we currently support. Symlinks are not directly497 * supported. First the guest could be an OS which doesn't support it and498 * second the symlink could point to a file which is out of the base tree.499 * Both things are hard to support. For now we just copy the target file in500 * this case.501 */502 if (!( RTFS_IS_DIRECTORY(objInfo.Attr.fMode)503 || RTFS_IS_FILE(objInfo.Attr.fMode)504 || RTFS_IS_SYMLINK(objInfo.Attr.fMode)))505 return VINF_SUCCESS;506 507 uint64_t cbSize = 0;508 rc = RTFileQuerySize(pcszPath, &cbSize);509 if (rc == VERR_IS_A_DIRECTORY)510 rc = VINF_SUCCESS;511 512 if (RT_FAILURE(rc))513 return rc;514 515 m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize));516 m_cbAll += cbSize;517 LogFlowFunc(("cbFile: %RU64\n", cbSize));518 519 PRTDIR hDir;520 /* We have to try to open even symlinks, cause they could be symlinks521 * to directories. */522 rc = RTDirOpen(&hDir, pcszPath);523 /* The following error happens when this was a symlink to an file or a524 * regular file. */525 if (rc == VERR_PATH_NOT_FOUND)526 return VINF_SUCCESS;527 if (RT_FAILURE(rc))528 return rc;529 530 while (RT_SUCCESS(rc))531 {532 RTDIRENTRY DirEntry;533 rc = RTDirRead(hDir, &DirEntry, NULL);534 if (RT_FAILURE(rc))535 {536 if (rc == VERR_NO_MORE_FILES)537 rc = VINF_SUCCESS;538 break;539 }540 switch (DirEntry.enmType)541 {542 case RTDIRENTRYTYPE_DIRECTORY:543 {544 /* Skip "." and ".." entries. */545 if ( RTStrCmp(DirEntry.szName, ".") == 0546 || RTStrCmp(DirEntry.szName, "..") == 0)547 break;548 if (char *pszRecDir = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName))549 {550 rc = buildFileTree(pszRecDir, cbBaseLen);551 RTStrFree(pszRecDir);552 }553 else554 rc = VERR_NO_MEMORY;555 break;556 }557 case RTDIRENTRYTYPE_SYMLINK:558 case RTDIRENTRYTYPE_FILE:559 {560 char *pszNewFile;561 if ((pszNewFile = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName)))562 {563 /* We need the size and the mode of the file. */564 RTFSOBJINFO objInfo1;565 rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING);566 if (RT_FAILURE(rc))567 return rc;568 rc = RTFileQuerySize(pszNewFile, &cbSize);569 if (RT_FAILURE(rc))570 break;571 572 m_uriList.append(PathEntry(pszNewFile, &pszNewFile[cbBaseLen],573 objInfo1.Attr.fMode, cbSize));574 m_cbAll += cbSize;575 576 RTStrFree(pszNewFile);577 }578 else579 rc = VERR_NO_MEMORY;580 break;581 }582 583 default:584 break;585 }586 }587 588 RTDirClose(hDir);589 477 590 478 return rc; … … 601 489 pSelf->m_cbTransfered += cbDone; 602 490 603 /* Advance progress info */491 /* Advance progress info. */ 604 492 int rc = VINF_SUCCESS; 605 493 if ( pSelf->m_pfnProgressCallback 606 && pSelf->m_cbAll) 607 { 608 rc = pSelf->m_pfnProgressCallback((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbAll, 494 && pSelf->m_cbTotal) 495 { 496 AssertMsg(pSelf->m_cbTransfered <= pSelf->m_cbTotal, 497 ("More bytes transferred (%zu) than expected (%zu), cbDone=%zu\n", 498 pSelf->m_cbTransfered, pSelf->m_cbTotal, cbDone)); 499 500 unsigned uPercentage = (unsigned)((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbTotal); 501 rc = pSelf->m_pfnProgressCallback(RT_CLAMP(uPercentage, 0, 100), 609 502 DragAndDropSvc::DND_PROGRESS_RUNNING, 610 503 VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser); -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h
r50308 r50460 4 4 5 5 /* 6 * Copyright (C) 2011-201 2Oracle Corporation6 * Copyright (C) 2011-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 18 18 #define ___VBox_HostService_DnD_dndmanager_h 19 19 20 #include <VBox/GuestHost/DragAndDrop.h> 20 21 #include <VBox/HostServices/Service.h> 21 22 #include <VBox/HostServices/DragAndDropSvc.h> … … 34 35 { 35 36 public: 36 DnDMessage() 37 : m_pNextMsg(NULL) 38 { 39 } 40 virtual ~DnDMessage() 37 38 DnDMessage(void) 39 : m_pNextMsg(NULL) 40 { 41 } 42 43 virtual ~DnDMessage(void) 41 44 { 42 45 clearNextMsg(); 43 46 } 44 47 45 virtual HGCM::Message* nextHGCMMessage( )48 virtual HGCM::Message* nextHGCMMessage(void) 46 49 { 47 50 return m_pNextMsg; 48 51 } 52 49 53 virtual int currentMessageInfo(uint32_t *puMsg, uint32_t *pcParms) 50 54 { … … 60 64 return VINF_SUCCESS; 61 65 } 62 virtual int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 66 67 virtual int currentMessage(uint32_t uMsg, uint32_t cParms, 68 VBOXHGCMSVCPARM paParms[]) 63 69 { 64 70 if (!m_pNextMsg) … … 71 77 return rc; 72 78 } 73 virtual void clearNextMsg() 79 80 virtual void clearNextMsg(void) 74 81 { 75 82 if (m_pNextMsg) … … 80 87 } 81 88 82 virtual bool isMessageWaiting( ) const { return m_pNextMsg != NULL; }89 virtual bool isMessageWaiting(void) const { return m_pNextMsg != NULL; } 83 90 84 91 protected: 92 85 93 HGCM::Message *m_pNextMsg; 86 94 }; … … 106 114 public: 107 115 108 DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser); 116 DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, 117 VBOXHGCMSVCPARM paParms[], 118 PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser); 119 109 120 virtual ~DnDHGSendDataMessage(void); 110 121 … … 117 128 protected: 118 129 119 struct PathEntry120 {121 PathEntry(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize)122 : m_strHostPath(strHostPath)123 , m_strGuestPath(strGuestPath)124 , m_fMode(fMode)125 , m_cbSize(cbSize) {}126 RTCString m_strHostPath;127 RTCString m_strGuestPath;128 uint32_t m_fMode;129 uint64_t m_cbSize;130 };131 132 bool hasFileUrls(const char *pcszFormat, size_t cbMax) const;133 int buildFileTree(const char *pcszPath, size_t cbBaseLen);134 130 static DECLCALLBACK(int) progressCallback(size_t cbDone, void *pvUser); 135 131 136 RTCList<PathEntry> m_uriList;137 132 DnDMessage *m_pNextPathMsg; 138 133 139 /* Total size (in bytes). */ 140 size_t m_cbAll; 141 /* Transferred size (in bytes). */ 134 DnDURIList m_lstURI; 135 /* Total message size (in bytes). */ 136 size_t m_cbTotal; 137 /* Transferred message size (in bytes). */ 142 138 size_t m_cbTransfered; 139 143 140 PFNDNDPROGRESS m_pfnProgressCallback; 144 141 void *m_pvProgressUser; … … 152 149 { 153 150 public: 154 DnDHGCancelMessage() 155 { 156 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 0, 0); 151 152 DnDHGCancelMessage(void) 153 { 154 m_pNextMsg 155 = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 156 0 /* cParms */, 0 /* aParms */); 157 157 } 158 158 }; … … 165 165 { 166 166 public: 167 167 168 DnDManager(PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser) 168 : m_pCurMsg(0)169 , m_fOpInProcess(false)170 , m_pfnProgressCallback(pfnProgressCallback)171 , m_pvProgressUser(pvProgressUser)169 : m_pCurMsg(0) 170 , m_fOpInProcess(false) 171 , m_pfnProgressCallback(pfnProgressCallback) 172 , m_pvProgressUser(pvProgressUser) 172 173 {} 173 virtual ~DnDManager() 174 175 virtual ~DnDManager(void) 174 176 { 175 177 clear(); … … 178 180 int addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 179 181 180 HGCM::Message *nextHGCMMessage( );182 HGCM::Message *nextHGCMMessage(void); 181 183 int nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms); 182 184 int nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 183 185 184 void clear( );185 186 bool hasActiveOperation( ) const { return m_fOpInProcess; }186 void clear(void); 187 188 bool hasActiveOperation(void) const { return m_fOpInProcess; } 187 189 188 190 private: … … 196 198 void *m_pvProgressUser; 197 199 }; 198 199 200 #endif /* ___VBox_HostService_DnD_dndmanager_h */ 200 201 -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r50308 r50460 470 470 DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data; 471 471 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS; 472 data.uPercentage = uPercentage;472 data.uPercentage = RT_CLAMP(uPercentage, 0, 100); 473 473 data.uState = uState; 474 474 data.rc = rc; -
trunk/src/VBox/Main/Makefile.kmk
r50313 r50460 392 392 $(if $(VBOX_WITH_XPCOM),src-server/xpcom/server.cpp,) 393 393 394 ifn1of ($(KBUILD_TARGET), win darwin) 394 ifn1of ($(KBUILD_TARGET), win darwin) 395 395 VBoxSVC_SOURCES += $(PATH_ROOT)/src/VBox/Devices/Network/slirp/resolv_conf_parser.c 396 396 endif … … 663 663 VBoxC_LIBS += $(PATH_STAGE_LIB)/VBoxOGLTest$(VBOX_SUFF_LIB) 664 664 VBoxC_LDFLAGS.darwin += -framework OpenGL 665 endif 666 667 ifdef VBOX_WITH_DRAG_AND_DROP 668 VBoxC_LIBS += $(PATH_STAGE_LIB)/VBoxDnDHostR3Lib$(VBOX_SUFF_LIB) 665 669 endif 666 670 -
trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
r50265 r50460 24 24 # include "GuestDnDImpl.h" 25 25 26 # include <iprt/dir.h> 27 # include <iprt/path.h> 28 # include <iprt/stream.h> 29 # include <iprt/semaphore.h> 30 # include <iprt/cpp/utils.h> 31 26 32 # include <VMMDev.h> 27 33 28 34 # include <VBox/com/list.h> 35 # include <VBox/GuestHost/DragAndDrop.h> 29 36 # include <VBox/HostServices/DragAndDropSvc.h> 30 37 … … 34 41 # define LOG_GROUP LOG_GROUP_GUEST_DND 35 42 # include <VBox/log.h> 36 37 # include <iprt/stream.h>38 # include <iprt/semaphore.h>39 # include <iprt/cpp/utils.h>40 43 41 44 /* How does this work: … … 209 212 }; 210 213 214 /** @todo This class needs a major cleanup. Later. */ 211 215 class GuestDnDPrivate 212 216 { 213 217 private: 214 /* todo: currently we only support one response. Maybe this needs to be extended at some time. */ 218 219 /** @todo Currently we only support one response. Maybe this needs to be extended at some time. */ 215 220 GuestDnDPrivate(GuestDnD *q, const ComObjPtr<Guest>& pGuest) 216 221 : q_ptr(q) … … 225 230 void hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const; 226 231 227 /* Static helper */232 /* Static helpers. */ 228 233 static RTCString toFormatString(ComSafeArrayIn(IN_BSTR, formats)); 229 234 static void toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats)); … … 238 243 ComObjPtr<Guest> p; 239 244 240 /* Private helper members */245 /* Private helper members. */ 241 246 static const RTCList<RTCString> m_sstrAllowedMimeTypes; 242 247 DnDGuestResponse *m_pDnDResponse; … … 396 401 ComPtr<IDisplay> pDisplay; 397 402 HRESULT rc = p->mParent->COMGETTER(Display)(pDisplay.asOutParam()); 398 if (FAILED(rc)) throw rc; 403 if (FAILED(rc)) 404 throw rc; 405 399 406 ComPtr<IFramebuffer> pFramebuffer; 400 407 LONG xShift, yShift; 401 rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(), &xShift, &yShift); 402 if (FAILED(rc)) throw rc; 408 rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(), 409 &xShift, &yShift); 410 if (FAILED(rc)) 411 throw rc; 412 403 413 *puX += xShift; 404 414 *puY += yShift; … … 696 706 } 697 707 698 HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction) 708 HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, 709 DragAndDropAction_T defaultAction, 710 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 711 ComSafeArrayIn(IN_BSTR, formats), 712 BSTR *pstrFormat, 713 DragAndDropAction_T *pResultAction) 699 714 { 700 715 DPTR(GuestDnD); … … 783 798 pDnD->resetProgress(p); 784 799 800 /* Note: The actual data transfer of files/directoies is performed by the 801 * DnD host service. */ 785 802 d->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA, 786 803 i, … … 854 871 855 872 Utf8Str strFormat(bstrFormat); 856 HRESULT rc= S_OK;873 HRESULT hr = S_OK; 857 874 858 875 uint32_t uAction = d->toHGCMAction(action); … … 861 878 return S_OK; 862 879 880 const char *pcszFormat = strFormat.c_str(); 881 LogFlowFunc(("strFormat=%s, uAction=0x%x\n", pcszFormat, uAction)); 882 if (DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat))) 883 { 884 char szDropDir[RTPATH_MAX]; 885 int rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir)); 886 if (RT_FAILURE(rc)) 887 return p->setError(VBOX_E_IPRT_ERROR, 888 p->tr("Unable to create the temporary drag'n drop directory \"%s\" (%Rrc)\n"), 889 szDropDir, rc); 890 LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir)); 891 } 892 863 893 try 864 894 { 865 LogFlowFunc(("strFormat=%s, uAction=0x%x\n", strFormat.c_str(), uAction));866 867 895 VBOXHGCMSVCPARM paParms[3]; 868 896 int i = 0; … … 872 900 873 901 DnDGuestResponse *pDnD = d->response(); 902 874 903 /* Reset any old data and the progress status. */ 875 904 pDnD->reset(); … … 885 914 catch (HRESULT rc2) 886 915 { 887 rc= rc2;888 } 889 890 return rc;916 hr = rc2; 917 } 918 919 return hr; 891 920 } 892 921 … … 906 935 if (cbData) 907 936 { 908 /* Copy the data into a nsafe array of bytes. */937 /* Copy the data into a safe array of bytes. */ 909 938 const void *pvData = pDnD->data(); 910 939 if (sfaData.resize(cbData)) … … 1006 1035 if (RT_SUCCESS(rc)) 1007 1036 { 1037 /** @todo Store pCBData->cbAllSize in the guest's response struct 1038 * if not set already. */ 1008 1039 uint32_t cbTotalSize = pCBData->cbAllSize; 1009 1040 unsigned int cPercentage; … … 1015 1046 /** @todo Don't use anonymous enums. */ 1016 1047 uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING; 1017 if ( pCBData->cbAllSize == cbCurSize1048 if ( cbTotalSize == cbCurSize 1018 1049 /* Empty data? Should not happen, but anyway ... */ 1019 || ! pCBData->cbAllSize)1050 || !cbTotalSize) 1020 1051 { 1021 1052 uState = DragAndDropSvc::DND_PROGRESS_COMPLETE; … … 1024 1055 rc = pResp->setProgress(cPercentage, uState); 1025 1056 } 1026 /* Todo: for now we instantly confirm the cancel. Check if the 1027 * guest should first clean up stuff itself and than really confirm 1028 * the cancel request by an extra message. */ 1057 1058 /** @todo For now we instantly confirm the cancel. Check if the 1059 * guest should first clean up stuff itself and than really confirm 1060 * the cancel request by an extra message. */ 1029 1061 if (rc == VERR_CANCELLED) 1030 1062 pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); … … 1053 1085 return rc; 1054 1086 } 1055 1056 1087 #endif /* VBOX_WITH_DRAG_AND_DROP */ 1057 1088 -
trunk/src/VBox/Main/src-client/GuestImpl.cpp
r50370 r50460 838 838 } 839 839 840 STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 840 STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, 841 DragAndDropAction_T defaultAction, 842 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 843 ComSafeArrayIn(IN_BSTR, formats), 844 DragAndDropAction_T *pResultAction) 841 845 { 842 846 /* Input validation */ … … 849 853 850 854 #ifdef VBOX_WITH_DRAG_AND_DROP 851 return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction); 855 return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction, 856 ComSafeArrayInArg(allowedActions), 857 ComSafeArrayInArg(formats), 858 pResultAction); 852 859 #else /* VBOX_WITH_DRAG_AND_DROP */ 853 860 ReturnComNotImplemented(); … … 855 862 } 856 863 857 STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 864 STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, 865 DragAndDropAction_T defaultAction, 866 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 867 ComSafeArrayIn(IN_BSTR, formats), 868 DragAndDropAction_T *pResultAction) 858 869 { 859 870 /* Input validation */ … … 866 877 867 878 #ifdef VBOX_WITH_DRAG_AND_DROP 868 return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction); 879 return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction, 880 ComSafeArrayInArg(allowedActions), 881 ComSafeArrayInArg(formats), 882 pResultAction); 869 883 #else /* VBOX_WITH_DRAG_AND_DROP */ 870 884 ReturnComNotImplemented(); … … 884 898 } 885 899 886 STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction) 900 STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, 901 DragAndDropAction_T defaultAction, 902 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 903 ComSafeArrayIn(IN_BSTR, formats), 904 BSTR *pstrFormat, DragAndDropAction_T *pResultAction) 887 905 { 888 906 /* Input validation */ … … 896 914 897 915 #ifdef VBOX_WITH_DRAG_AND_DROP 898 return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pstrFormat, pResultAction); 916 return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY, 917 defaultAction, 918 ComSafeArrayInArg(allowedActions), 919 ComSafeArrayInArg(formats), 920 pstrFormat, pResultAction); 899 921 #else /* VBOX_WITH_DRAG_AND_DROP */ 900 922 ReturnComNotImplemented(); … … 902 924 } 903 925 904 STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress) 926 STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, 927 ComSafeArrayIn(BYTE, data), 928 IProgress **ppProgress) 905 929 { 906 930 /* Input validation */ … … 913 937 914 938 #ifdef VBOX_WITH_DRAG_AND_DROP 915 return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat, ComSafeArrayInArg(data), ppProgress); 939 return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat, 940 ComSafeArrayInArg(data), ppProgress); 916 941 #else /* VBOX_WITH_DRAG_AND_DROP */ 917 942 ReturnComNotImplemented(); … … 919 944 } 920 945 921 STDMETHODIMP Guest::DragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction) 946 STDMETHODIMP Guest::DragGHPending(ULONG uScreenId, 947 ComSafeArrayOut(BSTR, formats), 948 ComSafeArrayOut(DragAndDropAction_T, allowedActions), 949 DragAndDropAction_T *pDefaultAction) 922 950 { 923 951 /* Input validation */ … … 930 958 931 959 #if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH) 932 return m_pGuestDnD->dragGHPending(uScreenId, ComSafeArrayOutArg(formats), ComSafeArrayOutArg(allowedActions), pDefaultAction); 960 return m_pGuestDnD->dragGHPending(uScreenId, 961 ComSafeArrayOutArg(formats), 962 ComSafeArrayOutArg(allowedActions), 963 pDefaultAction); 933 964 #else /* VBOX_WITH_DRAG_AND_DROP */ 934 965 ReturnComNotImplemented(); … … 936 967 } 937 968 938 STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress) 969 STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, 970 IProgress **ppProgress) 939 971 { 940 972 /* Input validation */
Note:
See TracChangeset
for help on using the changeset viewer.