Changeset 49891 in vbox
- Timestamp:
- Dec 12, 2013 8:09:20 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/VBox-4.1 merged: 85944-85947,85949-85950,85953,86701,86728,87009 /branches/andy/draganddrop (added) merged: 90781-91268
- Property svn:mergeinfo changed
-
trunk/include/VBox/HostServices/DragAndDropSvc.h
r42264 r49891 4 4 5 5 /* 6 * Copyright (C) 2011-201 2Oracle Corporation6 * Copyright (C) 2011-2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 72 72 HOST_DND_HG_EVT_DROPPED, 73 73 HOST_DND_HG_EVT_CANCEL, 74 /** Gets the actual MIME data, based on 75 * the format(s) specified by HOST_DND_HG_EVT_ENTER. */ 74 76 HOST_DND_HG_SND_DATA, 77 /** Sent when the actual buffer for HOST_DND_HG_SND_DATA 78 * was too small. */ 75 79 HOST_DND_HG_SND_MORE_DATA, 76 80 HOST_DND_HG_SND_DIR, … … 392 396 uint32_t uPercentage; 393 397 uint32_t uState; 398 int rc; 394 399 } VBOXDNDCBHGEVTPROGRESSDATA; 395 typedef VBOXDNDCBHGEVTPROGRESSDATA *PVBOXDNDCBHGEVTPROGRESSDATA 400 typedef VBOXDNDCBHGEVTPROGRESSDATA *PVBOXDNDCBHGEVTPROGRESSDATA; 396 401 397 402 typedef struct VBOXDNDCBGHACKPENDINGDATA … … 419 424 /** Callback data header. */ 420 425 VBOXDNDCBHEADERDATA hdr; 421 int32_t 426 int32_t rc; 422 427 } VBOXDNDCBEVTERRORDATA; 423 428 typedef VBOXDNDCBEVTERRORDATA *PVBOXDNDCBEVTERRORDATA; -
trunk/include/VBox/VBoxGuestLib.h
r49349 r49891 78 78 79 79 RT_C_DECLS_BEGIN 80 81 80 82 81 /** @defgroup grp_guest_lib_r0 Ring-0 interface. … … 694 693 { 695 694 uint32_t uType; /** The event type this struct contains */ 696 uint32_t uScreenId; /** Screen idthis request belongs to */695 uint32_t uScreenId; /** Screen ID this request belongs to */ 697 696 char *pszFormats; /** Format list (\r\n separated) */ 698 697 uint32_t cbFormats; /** Size of pszFormats (\0 included) */ … … 715 714 typedef VBGLR3DNDHGCMEVENT *PVBGLR3DNDHGCMEVENT; 716 715 typedef const PVBGLR3DNDHGCMEVENT CPVBGLR3DNDHGCMEVENT; 717 VBGLR3DECL(int) VbglR3DnDInit(void);718 VBGLR3DECL(int) VbglR3DnDTerm(void);719 720 716 VBGLR3DECL(int) VbglR3DnDConnect(uint32_t *pu32ClientId); 721 717 VBGLR3DECL(int) VbglR3DnDDisconnect(uint32_t u32ClientId); 722 718 723 VBGLR3DECL(int) VbglR3DnDProcessNextMessage( CPVBGLR3DNDHGCMEVENT pEvent);724 725 VBGLR3DECL(int) VbglR3DnDHGAcknowledgeOperation(uint32_t u Action);726 VBGLR3DECL(int) VbglR3DnDHGRequestData( const char* pcszFormat);719 VBGLR3DECL(int) VbglR3DnDProcessNextMessage(uint32_t u32ClientId, CPVBGLR3DNDHGCMEVENT pEvent); 720 721 VBGLR3DECL(int) VbglR3DnDHGAcknowledgeOperation(uint32_t u32ClientId, uint32_t uAction); 722 VBGLR3DECL(int) VbglR3DnDHGRequestData(uint32_t u32ClientId, const char* pcszFormat); 727 723 # ifdef VBOX_WITH_DRAG_AND_DROP_GH 728 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t u DefAction, uint32_t uAllActions, const char* pcszFormat);729 VBGLR3DECL(int) VbglR3DnDGHSendData( void *pvData, uint32_t cbData);730 VBGLR3DECL(int) VbglR3DnDGHErrorEvent( int rcOp);724 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t u32ClientId, uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormat); 725 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData); 726 VBGLR3DECL(int) VbglR3DnDGHErrorEvent(uint32_t u32ClientId, int rcOp); 731 727 # endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 732 728 /** @} */ -
trunk/include/VBox/log.h
r48809 r49891 222 222 /** Guest control. */ 223 223 LOG_GROUP_GUEST_CONTROL, 224 /** Guest drag'n drop. */ 225 LOG_GROUP_GUEST_DND, 224 226 /** GUI group. */ 225 227 LOG_GROUP_GUI, … … 770 772 "GMM", \ 771 773 "GUEST_CONTROL", \ 774 "GUEST_DND", \ 772 775 "GUI", \ 773 776 "GVMM", \ -
trunk/src/VBox
- Property svn:mergeinfo changed
/branches/andy/draganddrop/src/VBox (added) merged: 90781-91268
- Property svn:mergeinfo changed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r48070 r49891 26 26 endif 27 27 VBoxTray_SDKS = ReorderCompilerIncs $(VBOX_WINDDK_GST) 28 VBoxTray_DEFS = VBOX_WITH_HGCM LOG_TO_BACKDOOR 28 VBoxTray_DEFS = \ 29 VBOX_WITH_HGCM \ 30 VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\" 29 31 VBoxTray_INCS = ../include 30 32 VBoxTray_SOURCES = \ … … 39 41 VBoxHelpers.cpp \ 40 42 VBoxTray.rc 43 ifdef VBOX_WITH_DRAG_AND_DROP 44 VBoxTray_DEFS += \ 45 VBOX_WITH_DRAG_AND_DROP \ 46 $(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH,) 47 VBoxTray_SOURCES += \ 48 VBoxDnD.cpp \ 49 VBoxDnDDataObject.cpp \ 50 VBoxDnDEnumFormat.cpp \ 51 VBoxDnDDropSource.cpp 52 endif 41 53 ifdef VBOX_WITH_GUEST_PROPS 42 VBoxTray_DEFS += 54 VBoxTray_DEFS += _WIN32_IE=0x500 VBOX_WITH_GUEST_PROPS 43 55 VBoxTray_SOURCES += \ 44 56 VBoxHostVersion.cpp \ … … 46 58 endif 47 59 ifdef VBOX_WITH_SHARED_FOLDERS 48 VBoxTray_DEFS += 60 VBoxTray_DEFS += VBOX_WITH_SHARED_FOLDERS 49 61 VBoxTray_SOURCES += \ 50 62 VBoxSharedFolders.cpp … … 57 69 VBoxMMR.cpp 58 70 endif 59 60 71 ifdef VBOX_WITH_WDDM 61 72 VBoxTray_DEFS += VBOX_WITH_WDDM -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r44528 r49891 525 525 } 526 526 527 #ifndef DEBUG_andy 527 528 Log(("VBoxTray: vboxClipboardProcessMsg returned with rc = %ld\n", rc)); 529 #endif 528 530 return rc; 529 531 } -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp
r48979 r49891 964 964 else 965 965 { 966 #ifndef DEBUG_andy /* Too noisy for me. */ 966 967 Log(("VBoxTray: VBoxDisplayThread: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n")); 968 #endif 967 969 /* sleep a bit to not eat too much CPU in case the above call always fails */ 968 970 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
r48070 r49891 20 20 * Header Files * 21 21 *******************************************************************************/ 22 #ifdef DEBUG 23 # define LOG_ENABLED 24 # define LOG_GROUP LOG_GROUP_DEFAULT 25 #endif 26 27 #include <package-generated.h> 28 #include "product-generated.h" 29 22 30 #include "VBoxTray.h" 23 31 #include "VBoxTrayMsg.h" … … 30 38 #include "VBoxHostVersion.h" 31 39 #include "VBoxSharedFolders.h" 40 #ifdef VBOX_WITH_DRAG_AND_DROP 41 # include "VBoxDnD.h" 42 #endif 32 43 #include "VBoxIPC.h" 33 44 #include "VBoxLA.h" … … 42 53 #include <iprt/buildconfig.h> 43 54 #include <iprt/ldr.h> 55 #include <iprt/process.h> 56 #include <iprt/system.h> 57 #include <iprt/time.h> 58 #include <VBox/log.h> 44 59 45 60 /* Default desktop state tracking */ … … 133 148 DWORD gMajorVersion; 134 149 150 static PRTLOGGER g_pLoggerRelease = NULL; 151 static uint32_t g_cHistory = 10; /* Enable log rotation, 10 files. */ 152 static uint32_t g_uHistoryFileTime = RT_SEC_1DAY; /* Max 1 day per file. */ 153 static uint64_t g_uHistoryFileSize = 100 * _1M; /* Max 100MB per file. */ 135 154 136 155 /* The service table. */ … … 195 214 NULL /* pfnStop */, 196 215 VBoxMMRDestroy 216 }, 217 #endif 218 #ifdef VBOX_WITH_DRAG_AND_DROP 219 { 220 "Drag and Drop", 221 VBoxDnDInit, 222 VBoxDnDThread, 223 VBoxDnDStop, 224 VBoxDnDDestroy 197 225 }, 198 226 #endif … … 475 503 ghVBoxDriver = NULL; 476 504 } 505 } 506 507 /** 508 * Release logger callback. 509 * 510 * @return IPRT status code. 511 * @param pLoggerRelease 512 * @param enmPhase 513 * @param pfnLog 514 */ 515 static void vboxTrayLogHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog) 516 { 517 /* Some introductory information. */ 518 static RTTIMESPEC s_TimeSpec; 519 char szTmp[256]; 520 if (enmPhase == RTLOGPHASE_BEGIN) 521 RTTimeNow(&s_TimeSpec); 522 RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp)); 523 524 switch (enmPhase) 525 { 526 case RTLOGPHASE_BEGIN: 527 { 528 pfnLog(pLoggerRelease, 529 "VBoxTray %s r%s %s (%s %s) release log\n" 530 "Log opened %s\n", 531 RTBldCfgVersion(), RTBldCfgRevisionStr(), VBOX_BUILD_TARGET, 532 __DATE__, __TIME__, szTmp); 533 534 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp)); 535 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) 536 pfnLog(pLoggerRelease, "OS Product: %s\n", szTmp); 537 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp)); 538 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) 539 pfnLog(pLoggerRelease, "OS Release: %s\n", szTmp); 540 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp)); 541 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) 542 pfnLog(pLoggerRelease, "OS Version: %s\n", szTmp); 543 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) 544 pfnLog(pLoggerRelease, "OS Service Pack: %s\n", szTmp); 545 546 /* the package type is interesting for Linux distributions */ 547 char szExecName[RTPATH_MAX]; 548 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName)); 549 pfnLog(pLoggerRelease, 550 "Executable: %s\n" 551 "Process ID: %u\n" 552 "Package type: %s" 553 #ifdef VBOX_OSE 554 " (OSE)" 555 #endif 556 "\n", 557 pszExecName ? pszExecName : "unknown", 558 RTProcSelf(), 559 VBOX_PACKAGE_STRING); 560 break; 561 } 562 563 case RTLOGPHASE_PREROTATE: 564 pfnLog(pLoggerRelease, "Log rotated - Log started %s\n", szTmp); 565 break; 566 567 case RTLOGPHASE_POSTROTATE: 568 pfnLog(pLoggerRelease, "Log continuation - Log started %s\n", szTmp); 569 break; 570 571 case RTLOGPHASE_END: 572 pfnLog(pLoggerRelease, "End of log file - Log started %s\n", szTmp); 573 break; 574 575 default: 576 /* nothing */; 577 } 578 } 579 580 /** 581 * Creates the default release logger outputting to the specified file. 582 * Pass NULL for disabled logging. 583 * 584 * @return IPRT status code. 585 * @param pszLogFile Filename for log output. Optional. 586 */ 587 static int vboxTrayLogCreate(const char *pszLogFile) 588 { 589 /* Create release logger (stdout + file). */ 590 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; 591 RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG; 592 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 593 fFlags |= RTLOGFLAGS_USECRLF; 594 #endif 595 char szError[RTPATH_MAX + 128] = ""; 596 int rc = RTLogCreateEx(&g_pLoggerRelease, fFlags, 597 #ifdef DEBUG 598 "all.e.l.f", 599 "VBOXTRAY_LOG", 600 #else 601 "all", 602 "VBOXTRAY_RELEASE_LOG", 603 #endif 604 RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT, 605 vboxTrayLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime, 606 szError, sizeof(szError), pszLogFile); 607 if (RT_SUCCESS(rc)) 608 { 609 #ifdef DEBUG 610 RTLogSetDefaultInstance(g_pLoggerRelease); 611 #else 612 /* Register this logger as the release logger. */ 613 RTLogRelSetDefaultInstance(g_pLoggerRelease); 614 #endif 615 /* Explicitly flush the log in case of VBOXTRAY_RELEASE_LOG=buffered. */ 616 RTLogFlush(g_pLoggerRelease); 617 } 618 else 619 MessageBox(GetDesktopWindow(), 620 szError, "VBoxTray - Logging Error", MB_OK | MB_ICONERROR); 621 622 return rc; 623 } 624 625 static void vboxTrayLogDestroy(void) 626 { 627 RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); 477 628 } 478 629 … … 802 953 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 803 954 { 955 #ifndef DEBUG_andy 804 956 Log(("VBoxTray: msg %p\n", msg.message)); 957 #endif 805 958 if (msg.message == WM_QUIT) 806 959 { … … 833 986 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 834 987 { 835 /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */ 988 /* Note: Do not use a global namespace ("Global\\") for mutex name here, 989 * will blow up NT4 compatibility! */ 836 990 HANDLE hMutexAppRunning = CreateMutex(NULL, FALSE, "VBoxTray"); 837 991 if ( hMutexAppRunning != NULL 838 992 && GetLastError() == ERROR_ALREADY_EXISTS) 839 993 { 840 /* Close the mutex for this application instance. */994 /* VBoxTray already running? Bail out. */ 841 995 CloseHandle (hMutexAppRunning); 842 996 hMutexAppRunning = NULL; … … 847 1001 848 1002 int rc = RTR3InitExeNoArguments(0); 1003 if (RT_SUCCESS(rc)) 1004 rc = vboxTrayLogCreate(NULL /* pszLogFile */); 1005 849 1006 if (RT_SUCCESS(rc)) 850 1007 { … … 931 1088 932 1089 VbglR3Term(); 1090 1091 vboxTrayLogDestroy(); 1092 933 1093 return RT_SUCCESS(rc) ? 0 : 1; 934 1094 } -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxVRDP.cpp
r46593 r49891 409 409 else 410 410 { 411 #ifndef DEBUG_andy /* Too noisy for me. */ 411 412 Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n")); 412 413 #endif 413 414 /* sleep a bit to not eat too much CPU in case the above call always fails */ 414 415 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) … … 422 423 else 423 424 { 425 #ifndef DEBUG_andy 424 426 Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n")); 425 427 #endif 426 428 /* sleep a bit to not eat too much CPU in case the above call always fails */ 427 429 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r42261 r49891 5 5 6 6 /* 7 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 41 41 #include "VBox/HostServices/DragAndDropSvc.h" 42 42 43 #define VERBOSE 144 45 #if defined(VERBOSE) && defined(DEBUG_poetzsch)46 # include <iprt/stream.h>47 # define DO(s) RTPrintf s48 #else49 # define DO(s) do {} while(0)50 //# define DO(s) Log s51 #endif52 53 43 /* Here all the communication with the host over HGCM is handled platform 54 44 * neutral. Also the receiving of URIs content (directory trees and files) is … … 61 51 */ 62 52 63 /* Not really used at the moment (only one client is possible): */64 uint32_t g_clientId = 0;65 66 53 /****************************************************************************** 67 54 * Private internal functions * … … 70 57 static int vbglR3DnDCreateDropDir(char* pszDropDir, size_t cbSize) 71 58 { 72 /* Validate input */73 59 AssertPtrReturn(pszDropDir, VERR_INVALID_POINTER); 74 60 AssertReturn(cbSize, VERR_INVALID_PARAMETER); 75 61 76 /* Get the users document directory (usually $HOME/Documents). */ 77 int rc = RTPathUserDocuments(pszDropDir, cbSize); 62 /** @todo On Windows we also could use the registry to override 63 * this path, on Posix a dotfile and/or a guest property 64 * can be used. */ 65 66 /* Get the users temp directory. Don't use the user's root directory (or 67 * something inside it) because we don't know for how long/if the data will 68 * be kept after the guest OS used it. */ 69 int rc = RTPathTemp(pszDropDir, cbSize); 78 70 if (RT_FAILURE(rc)) 79 71 return rc; 72 80 73 /* Append our base drop directory. */ 81 74 rc = RTPathAppend(pszDropDir, cbSize, "VirtualBox Dropped Files"); 82 75 if (RT_FAILURE(rc)) 83 76 return rc; 77 84 78 /* Create it when necessary. */ 85 79 if (!RTDirExists(pszDropDir)) … … 89 83 return rc; 90 84 } 85 91 86 /* The actually drop directory consist of the current time stamp and a 92 87 * unique number when necessary. */ … … 95 90 if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime))) 96 91 return VERR_BUFFER_OVERFLOW; 92 #ifdef RT_OS_WINDOWS 93 /* Filter out characters not allowed on Windows platforms, put in by 94 RTTimeSpecToString(). */ 95 /** @todo Use something like RTPathSanitize() when available. Later. */ 96 RTUNICP aCpSet[] = 97 { ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_', 98 0xa0, 0xd7af, '\0' }; 99 RTStrPurgeComplementSet(pszTime, aCpSet, '_' /* Replacement */); 100 #endif 101 97 102 rc = RTPathAppend(pszDropDir, cbSize, pszTime); 98 103 if (RT_FAILURE(rc)) … … 105 110 static int vbglR3DnDQueryNextHostMessageType(uint32_t uClientId, uint32_t *puMsg, uint32_t *pcParms, bool fWait) 106 111 { 107 /* Validate input */108 112 AssertPtrReturn(puMsg, VERR_INVALID_POINTER); 109 113 AssertPtrReturn(pcParms, VERR_INVALID_POINTER); 110 114 111 /* Initialize header */112 115 DragAndDropSvc::VBOXDNDNEXTMSGMSG Msg; 113 116 RT_ZERO(Msg); … … 116 119 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG; 117 120 Msg.hdr.cParms = 3; 118 /* Initialize parameter */ 121 119 122 Msg.msg.SetUInt32(0); 120 123 Msg.num_parms.SetUInt32(0); 121 124 Msg.block.SetUInt32(fWait); 122 /* Do request */ 125 123 126 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 124 127 if (RT_SUCCESS(rc)) … … 132 135 } 133 136 } 137 134 138 return rc; 135 139 } … … 146 150 uint32_t *pcbFormatsRecv) 147 151 { 148 /* Validate input */149 152 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 150 153 AssertPtrReturn(puX, VERR_INVALID_POINTER); … … 156 159 AssertPtrReturn(pcbFormatsRecv, VERR_INVALID_POINTER); 157 160 158 /* Initialize header */159 161 DragAndDropSvc::VBOXDNDHGACTIONMSG Msg; 160 162 RT_ZERO(Msg); … … 162 164 Msg.hdr.u32Function = uMsg; 163 165 Msg.hdr.cParms = 7; 164 /* Initialize parameter */ 166 165 167 Msg.uScreenId.SetUInt32(0); 166 168 Msg.uX.SetUInt32(0); … … 170 172 Msg.pvFormats.SetPtr(pszFormats, cbFormats); 171 173 Msg.cFormats.SetUInt32(0); 172 /* Do request */ 174 173 175 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 174 176 if (RT_SUCCESS(rc)) … … 188 190 } 189 191 } 192 190 193 return rc; 191 194 } … … 193 196 static int vbglR3DnDHGProcessLeaveMessage(uint32_t uClientId) 194 197 { 195 /* Initialize header */196 198 DragAndDropSvc::VBOXDNDHGLEAVEMSG Msg; 197 199 RT_ZERO(Msg); … … 199 201 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_LEAVE; 200 202 Msg.hdr.cParms = 0; 201 /* Do request */ 202 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 203 if (RT_SUCCESS(rc)) 204 rc = Msg.hdr.result; 203 204 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 205 if (RT_SUCCESS(rc)) 206 rc = Msg.hdr.result; 207 205 208 return rc; 206 209 } … … 208 211 static int vbglR3DnDHGProcessCancelMessage(uint32_t uClientId) 209 212 { 210 /* Initialize header */211 213 DragAndDropSvc::VBOXDNDHGCANCELMSG Msg; 212 214 RT_ZERO(Msg); … … 214 216 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_CANCEL; 215 217 Msg.hdr.cParms = 0; 216 /* Do request */ 217 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 218 if (RT_SUCCESS(rc)) 219 rc = Msg.hdr.result; 218 219 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 220 if (RT_SUCCESS(rc)) 221 rc = Msg.hdr.result; 222 220 223 return rc; 221 224 } … … 227 230 uint32_t *pfMode) 228 231 { 229 /* Validate input */230 232 AssertPtrReturn(pszDirname, VERR_INVALID_POINTER); 231 233 AssertReturn(cbDirname, VERR_INVALID_PARAMETER); … … 233 235 AssertPtrReturn(pfMode, VERR_INVALID_POINTER); 234 236 235 /* Initialize header */236 237 DragAndDropSvc::VBOXDNDHGSENDDIRMSG Msg; 237 238 RT_ZERO(Msg); … … 239 240 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DIR; 240 241 Msg.hdr.cParms = 3; 241 /* Initialize parameter */ 242 242 243 Msg.pvName.SetPtr(pszDirname, cbDirname); 243 244 Msg.cName.SetUInt32(0); 244 245 Msg.fMode.SetUInt32(0); 245 /* Do request */ 246 246 247 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 247 248 if (RT_SUCCESS(rc)) … … 257 258 } 258 259 } 260 259 261 return rc; 260 262 } … … 269 271 uint32_t *pfMode) 270 272 { 271 /* Validate input */272 273 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 273 274 AssertReturn(cbFilename, VERR_INVALID_PARAMETER); … … 278 279 AssertPtrReturn(pfMode, VERR_INVALID_POINTER); 279 280 280 /* Initialize header */281 281 DragAndDropSvc::VBOXDNDHGSENDFILEMSG Msg; 282 282 RT_ZERO(Msg); … … 284 284 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_FILE; 285 285 Msg.hdr.cParms = 5; 286 /* Initialize parameter */ 286 287 287 Msg.pvName.SetPtr(pszFilename, cbFilename); 288 288 Msg.cName.SetUInt32(0); … … 290 290 Msg.cData.SetUInt32(0); 291 291 Msg.fMode.SetUInt32(0); 292 /* Do request */ 292 293 293 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 294 294 if (RT_SUCCESS(rc)) … … 306 306 } 307 307 } 308 308 309 return rc; 309 310 } … … 376 377 uint32_t uNextMsg; 377 378 uint32_t cNextParms; 378 rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false); 379 DO(("%Rrc - %d\n", rc , uNextMsg)); 379 rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false /* fWait */); 380 380 if (RT_SUCCESS(rc)) 381 381 { … … 392 392 if (RT_SUCCESS(rc)) 393 393 { 394 DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc));395 394 char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname); 396 395 rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); … … 415 414 { 416 415 char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname); 417 DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc));418 416 RTFILE hFile; 417 /** @todo r=andy Keep the file open and locked during the actual file transfer. Otherwise this will 418 * create all sorts of funny races because we don't know if the guest has 419 * modified the file in between the file data send calls. */ 419 420 rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE); 420 421 if (RT_SUCCESS(rc)) … … 443 444 /* Break out of the loop. */ 444 445 } 445 default: fLoop = false; break; 446 default: 447 fLoop = false; 448 break; 446 449 } 447 } else 450 } 451 else 448 452 { 449 453 if (rc == VERR_NO_DATA) … … 451 455 break; 452 456 } 453 }while(fLoop); 457 458 } while (fLoop); 454 459 455 460 RTMemFree(pvTmpData); 461 456 462 /* Cleanup on failure or if the user has canceled. */ 457 463 if (RT_FAILURE(rc)) … … 477 483 uint32_t *pcbDataRecv) 478 484 { 479 /* Validate input */480 485 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 481 486 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); … … 486 491 AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER); 487 492 488 /* Initialize header */489 493 DragAndDropSvc::VBOXDNDHGSENDDATAMSG Msg; 490 494 RT_ZERO(Msg); … … 492 496 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DATA; 493 497 Msg.hdr.cParms = 5; 494 /* Initialize parameter */ 498 495 499 Msg.uScreenId.SetUInt32(0); 496 500 Msg.pvFormat.SetPtr(pszFormat, cbFormat); … … 498 502 Msg.pvData.SetPtr(pvData, cbData); 499 503 Msg.cData.SetUInt32(0); 500 /* Do request */ 504 501 505 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 502 506 if (RT_SUCCESS(rc)) … … 515 519 } 516 520 } 521 517 522 return rc; 518 523 } … … 523 528 uint32_t *pcbDataRecv) 524 529 { 525 /* Validate input */526 530 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 527 531 AssertReturn(cbData, VERR_INVALID_PARAMETER); 528 532 AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER); 529 533 530 /* Initialize header */531 534 DragAndDropSvc::VBOXDNDHGSENDMOREDATAMSG Msg; 532 535 RT_ZERO(Msg); 533 Msg.hdr.u32ClientID = g_clientId;536 Msg.hdr.u32ClientID = uClientId; 534 537 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA; 535 538 Msg.hdr.cParms = 2; 536 /* Initialize parameter */ 539 537 540 Msg.pvData.SetPtr(pvData, cbData); 538 541 Msg.cData.SetUInt32(0); 539 /* Do request */ 542 540 543 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 541 544 if (RT_SUCCESS(rc)) … … 554 557 } 555 558 556 static int vbglR3DnDHGProcessSendDataMessage s(uint32_t uClientId,557 uint32_t *puScreenId,558 char *pszFormat,559 uint32_t cbFormat,560 uint32_t *pcbFormatRecv,561 void **ppvData,562 uint32_t cbData,563 size_t *pcbDataRecv)559 static int vbglR3DnDHGProcessSendDataMessageLoop(uint32_t uClientId, 560 uint32_t *puScreenId, 561 char *pszFormat, 562 uint32_t cbFormat, 563 uint32_t *pcbFormatRecv, 564 void **ppvData, 565 uint32_t cbData, 566 size_t *pcbDataRecv) 564 567 { 565 568 uint32_t cbDataRecv = 0; … … 572 575 cbData, 573 576 &cbDataRecv); 574 575 size_t cbAllDataRecv = cbDataRecv; 577 uint32_t cbAllDataRecv = cbDataRecv; 576 578 while (rc == VERR_BUFFER_OVERFLOW) 577 579 { … … 624 626 size_t *pcbDataRecv) 625 627 { 626 int rc = vbglR3DnDHGProcessSendDataMessages(uClientId, 627 puScreenId, 628 pszFormat, 629 cbFormat, 630 pcbFormatRecv, 631 ppvData, 632 cbData, 633 pcbDataRecv); 634 if (RT_SUCCESS(rc)) 635 { 636 /* Check if this is a uri-event */ 628 int rc = vbglR3DnDHGProcessSendDataMessageLoop(uClientId, 629 puScreenId, 630 pszFormat, 631 cbFormat, 632 pcbFormatRecv, 633 ppvData, 634 cbData, 635 pcbDataRecv); 636 if (RT_SUCCESS(rc)) 637 { 638 /* Check if this is a uri-event. If so, let VbglR3 do all the actual 639 * data transfer + file /directory creation internally without letting 640 * the caller know. */ 637 641 if (RTStrNICmp(pszFormat, "text/uri-list", *pcbFormatRecv) == 0) 638 642 rc = vbglR3DnDHGProcessURIMessages(uClientId, … … 645 649 pcbDataRecv); 646 650 } 651 647 652 return rc; 648 653 } … … 651 656 uint32_t *puScreenId) 652 657 { 653 /* Validate input */654 658 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 655 659 656 /* Initialize header */657 660 DragAndDropSvc::VBOXDNDGHREQPENDINGMSG Msg; 658 661 RT_ZERO(Msg); … … 660 663 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_REQ_PENDING; 661 664 Msg.hdr.cParms = 1; 662 /* Initialize parameter */ 665 663 666 Msg.uScreenId.SetUInt32(0); 664 /* Do request */ 667 665 668 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 666 669 if (RT_SUCCESS(rc)) … … 673 676 } 674 677 } 678 675 679 return rc; 676 680 } … … 682 686 uint32_t *puAction) 683 687 { 684 /* Validate input */685 688 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 686 689 AssertReturn(cbFormat, VERR_INVALID_PARAMETER); … … 688 691 AssertPtrReturn(puAction, VERR_INVALID_POINTER); 689 692 690 /* Initialize header */691 693 DragAndDropSvc::VBOXDNDGHDROPPEDMSG Msg; 692 694 RT_ZERO(Msg); … … 694 696 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_EVT_DROPPED; 695 697 Msg.hdr.cParms = 3; 696 /* Initialize parameter */ 698 697 699 Msg.pvFormat.SetPtr(pszFormat, cbFormat); 698 700 Msg.cFormat.SetUInt32(0); 699 701 Msg.uAction.SetUInt32(0); 700 /* Do request */ 702 701 703 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 702 704 if (RT_SUCCESS(rc)) … … 712 714 } 713 715 } 716 714 717 return rc; 715 718 } … … 719 722 ******************************************************************************/ 720 723 721 /**722 * Initialize Drag & Drop.723 *724 * This will enable the Drag & Drop events.725 *726 * @returns VBox status code.727 */728 VBGLR3DECL(int) VbglR3DnDInit(void)729 {730 return VbglR3DnDConnect(&g_clientId);731 }732 733 /**734 * Terminate Drag and Drop.735 *736 * This will Drag and Drop events.737 *738 * @returns VBox status.739 */740 VBGLR3DECL(int) VbglR3DnDTerm(void)741 {742 return VbglR3DnDDisconnect(g_clientId);743 }744 745 724 VBGLR3DECL(int) VbglR3DnDConnect(uint32_t *pu32ClientId) 746 725 { 747 /* Validate input */748 726 AssertPtrReturn(pu32ClientId, VERR_INVALID_POINTER); 749 727 … … 770 748 VBGLR3DECL(int) VbglR3DnDDisconnect(uint32_t u32ClientId) 771 749 { 772 /* Initialize header */773 750 VBoxGuestHGCMDisconnectInfo Info; 774 751 Info.result = VERR_WRONG_ORDER; 775 752 Info.u32ClientID = u32ClientId; 753 776 754 /* Do request */ 777 755 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_DISCONNECT, &Info, sizeof(Info)); 778 756 if (RT_SUCCESS(rc)) 779 757 rc = Info.result; 780 return rc; 781 } 782 783 VBGLR3DECL(int) VbglR3DnDProcessNextMessage(CPVBGLR3DNDHGCMEVENT pEvent) 784 { 785 /* Validate input */ 758 759 return rc; 760 } 761 762 VBGLR3DECL(int) VbglR3DnDProcessNextMessage(uint32_t u32ClientId, CPVBGLR3DNDHGCMEVENT pEvent) 763 { 786 764 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 787 765 … … 789 767 uint32_t uNumParms = 0; 790 768 const uint32_t ccbFormats = _64K; 791 const uint32_t ccbData = _ 1M;792 int rc = vbglR3DnDQueryNextHostMessageType( g_clientId, &uMsg, &uNumParms, true);793 if (RT_SUCCESS(rc))794 {795 DO(("Got message %d\n", uMsg));769 const uint32_t ccbData = _64K; 770 int rc = vbglR3DnDQueryNextHostMessageType(u32ClientId, &uMsg, &uNumParms, 771 true /* fWait */); 772 if (RT_SUCCESS(rc)) 773 { 796 774 switch(uMsg) 797 775 { … … 803 781 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); 804 782 if (!pEvent->pszFormats) 805 return VERR_NO_MEMORY; 806 rc = vbglR3DnDHGProcessActionMessage(g_clientId, 807 uMsg, 808 &pEvent->uScreenId, 809 &pEvent->u.a.uXpos, 810 &pEvent->u.a.uYpos, 811 &pEvent->u.a.uDefAction, 812 &pEvent->u.a.uAllActions, 813 pEvent->pszFormats, 814 ccbFormats, 815 &pEvent->cbFormats); 783 rc = VERR_NO_MEMORY; 784 785 if (RT_SUCCESS(rc)) 786 rc = vbglR3DnDHGProcessActionMessage(u32ClientId, 787 uMsg, 788 &pEvent->uScreenId, 789 &pEvent->u.a.uXpos, 790 &pEvent->u.a.uYpos, 791 &pEvent->u.a.uDefAction, 792 &pEvent->u.a.uAllActions, 793 pEvent->pszFormats, 794 ccbFormats, 795 &pEvent->cbFormats); 816 796 break; 817 797 } … … 819 799 { 820 800 pEvent->uType = uMsg; 821 rc = vbglR3DnDHGProcessLeaveMessage( g_clientId);801 rc = vbglR3DnDHGProcessLeaveMessage(u32ClientId); 822 802 break; 823 803 } … … 827 807 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); 828 808 if (!pEvent->pszFormats) 829 r eturnVERR_NO_MEMORY;830 pEvent->u.b.pvData = RTMemAlloc(ccbData); 831 if ( !pEvent->u.b.pvData)809 rc = VERR_NO_MEMORY; 810 811 if (RT_SUCCESS(rc)) 832 812 { 833 RTMemFree(pEvent->pszFormats); 834 pEvent->pszFormats = NULL; 835 return VERR_NO_MEMORY; 813 pEvent->u.b.pvData = RTMemAlloc(ccbData); 814 if (!pEvent->u.b.pvData) 815 { 816 RTMemFree(pEvent->pszFormats); 817 pEvent->pszFormats = NULL; 818 rc = VERR_NO_MEMORY; 819 } 836 820 } 837 rc = vbglR3DnDHGProcessSendDataMessage(g_clientId, 838 &pEvent->uScreenId, 839 pEvent->pszFormats, 840 ccbFormats, 841 &pEvent->cbFormats, 842 &pEvent->u.b.pvData, 843 ccbData, 844 &pEvent->u.b.cbData); 821 822 if (RT_SUCCESS(rc)) 823 rc = vbglR3DnDHGProcessSendDataMessage(u32ClientId, 824 &pEvent->uScreenId, 825 pEvent->pszFormats, 826 ccbFormats, 827 &pEvent->cbFormats, 828 &pEvent->u.b.pvData, 829 ccbData, 830 &pEvent->u.b.cbData); 831 break; 832 } 833 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: 834 { 835 pEvent->uType = uMsg; 836 rc = vbglR3DnDHGProcessCancelMessage(u32ClientId); 845 837 break; 846 838 } … … 849 841 { 850 842 pEvent->uType = uMsg; 851 rc = vbglR3DnDGHProcessRequestPendingMessage( g_clientId,843 rc = vbglR3DnDGHProcessRequestPendingMessage(u32ClientId, 852 844 &pEvent->uScreenId); 853 845 break; … … 858 850 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); 859 851 if (!pEvent->pszFormats) 860 return VERR_NO_MEMORY; 861 rc = vbglR3DnDGHProcessDroppedMessage(g_clientId, 862 pEvent->pszFormats, 863 ccbFormats, 864 &pEvent->cbFormats, 865 &pEvent->u.a.uDefAction); 852 rc = VERR_NO_MEMORY; 853 854 if (RT_SUCCESS(rc)) 855 rc = vbglR3DnDGHProcessDroppedMessage(u32ClientId, 856 pEvent->pszFormats, 857 ccbFormats, 858 &pEvent->cbFormats, 859 &pEvent->u.a.uDefAction); 866 860 break; 867 861 } 868 862 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 869 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: 870 { 871 pEvent->uType = uMsg; 872 rc = vbglR3DnDHGProcessCancelMessage(g_clientId); 873 if (RT_SUCCESS(rc)) 874 rc = VERR_CANCELLED; 863 default: 864 AssertMsgFailedReturn(("Message %u isn't expected in this context", uMsg), 865 VERR_INVALID_PARAMETER); 875 866 break; 876 } 877 default: AssertMsgFailedReturn(("Message %u isn't expected in this context", uMsg), VERR_INVALID_PARAMETER); break; 878 } 879 } 880 return rc; 881 } 882 883 VBGLR3DECL(int) VbglR3DnDHGAcknowledgeOperation(uint32_t uAction) 884 { 885 DO(("ACK: %u\n", uAction)); 886 /* Initialize header */ 867 } 868 } 869 870 return rc; 871 } 872 873 VBGLR3DECL(int) VbglR3DnDHGAcknowledgeOperation(uint32_t u32ClientId, uint32_t uAction) 874 { 887 875 DragAndDropSvc::VBOXDNDHGACKOPMSG Msg; 888 876 RT_ZERO(Msg); 889 877 Msg.hdr.result = VERR_WRONG_ORDER; 890 Msg.hdr.u32ClientID = g_clientId;878 Msg.hdr.u32ClientID = u32ClientId; 891 879 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_ACK_OP; 892 880 Msg.hdr.cParms = 1; … … 897 885 if (RT_SUCCESS(rc)) 898 886 rc = Msg.hdr.result; 899 return rc; 900 } 901 902 VBGLR3DECL(int) VbglR3DnDHGRequestData(const char* pcszFormat) 903 { 904 DO(("DATA_REQ: '%s'\n", pcszFormat)); 905 /* Validate input */ 887 888 return rc; 889 } 890 891 VBGLR3DECL(int) VbglR3DnDHGRequestData(uint32_t u32ClientId, const char* pcszFormat) 892 { 906 893 AssertPtrReturn(pcszFormat, VERR_INVALID_PARAMETER); 907 894 908 /* Initialize header */909 895 DragAndDropSvc::VBOXDNDHGREQDATAMSG Msg; 910 896 RT_ZERO(Msg); 911 897 Msg.hdr.result = VERR_WRONG_ORDER; 912 Msg.hdr.u32ClientID = g_clientId;898 Msg.hdr.u32ClientID = u32ClientId; 913 899 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_REQ_DATA; 914 900 Msg.hdr.cParms = 1; … … 918 904 if (RT_SUCCESS(rc)) 919 905 rc = Msg.hdr.result; 920 return rc; 921 } 922 923 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormat) 924 { 925 DO(("PEND: %u: %u (%s)\n", uDefAction, uAllActions, pcszFormat)); 926 /* Validate input */ 906 907 return rc; 908 } 909 910 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t u32ClientId, 911 uint32_t uDefAction, uint32_t uAllActions, 912 const char* pcszFormat) 913 { 927 914 AssertPtrReturn(pcszFormat, VERR_INVALID_POINTER); 928 915 929 /* Initialize header */930 916 DragAndDropSvc::VBOXDNDGHACKPENDINGMSG Msg; 931 917 RT_ZERO(Msg); 932 918 Msg.hdr.result = VERR_WRONG_ORDER; 933 Msg.hdr.u32ClientID = g_clientId;919 Msg.hdr.u32ClientID = u32ClientId; 934 920 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_ACK_PENDING; 935 921 Msg.hdr.cParms = 3; … … 942 928 if (RT_SUCCESS(rc)) 943 929 rc = Msg.hdr.result; 944 return rc; 945 } 946 947 VBGLR3DECL(int) VbglR3DnDGHSendData(void *pvData, uint32_t cbData) 948 { 949 DO(("DATA: %x (%u)\n", pvData, cbData)); 950 /* Validate input */ 930 931 return rc; 932 } 933 934 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData) 935 { 951 936 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 952 937 AssertReturn(cbData, VERR_INVALID_PARAMETER); … … 962 947 */ 963 948 964 /* Initialize header */965 949 DragAndDropSvc::VBOXDNDGHSENDDATAMSG Msg; 966 950 RT_ZERO(Msg); 967 951 Msg.hdr.result = VERR_WRONG_ORDER; 968 Msg.hdr.u32ClientID = g_clientId;952 Msg.hdr.u32ClientID = u32ClientId; 969 953 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DATA; 970 954 Msg.hdr.cParms = 2; … … 992 976 // RTThreadSleep(500); 993 977 } 994 return rc; 995 } 996 997 VBGLR3DECL(int) VbglR3DnDGHErrorEvent(int rcOp) 998 { 999 DO(("GH_ERROR\n")); 1000 1001 /* Initialize header */ 978 979 return rc; 980 } 981 982 VBGLR3DECL(int) VbglR3DnDGHErrorEvent(uint32_t u32ClientId, int rcOp) 983 { 1002 984 DragAndDropSvc::VBOXDNDGHEVTERRORMSG Msg; 1003 985 RT_ZERO(Msg); 1004 986 Msg.hdr.result = VERR_WRONG_ORDER; 1005 Msg.hdr.u32ClientID = g_clientId;987 Msg.hdr.u32ClientID = u32ClientId; 1006 988 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_EVT_ERROR; 1007 989 Msg.hdr.cParms = 1; … … 1012 994 if (RT_SUCCESS(rc)) 1013 995 rc = Msg.hdr.result; 1014 return rc; 1015 } 996 997 return rc; 998 } -
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r49455 r49891 4 4 5 5 /* 6 * Copyright (C) 2011-201 2Oracle Corporation6 * Copyright (C) 2011-2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 55 55 * G->H: 56 56 * This is a lot more trickery than H->G. When a pending event from HGCM 57 * arrives, we ask s if there is currentlyan owner of the XdndSelection57 * arrives, we ask if there currently is an owner of the XdndSelection 58 58 * property. If so, our proxy window is shown (1x1, but without backing store) 59 59 * and some mouse event is triggered. This should be followed by an XdndEnter … … 65 65 * Todo: 66 66 * - this isn't finished, yet. Currently the mouse isn't correctly released 67 * in the guest (both, when the drop was successfully or canceled).67 * in the guest (both, when the drop was successfully or canceled). 68 68 * - cancel (e.g. with the ESC key) doesn't work 69 69 * … … 74 74 * - really check for the Xdnd version and the supported features 75 75 */ 76 77 #define VERBOSE 178 79 #if defined(VERBOSE) && defined(DEBUG_poetzsch)80 # include <iprt/stream.h>81 # define DO(s) RTPrintf s82 #else83 # define DO(s) do {} while (0)84 //# define DO(s) Log s85 #endif86 76 87 77 #define VBOX_XDND_VERSION (4) … … 154 144 public: 155 145 156 static xHelpers * instance(Display *pDisplay = 0)146 static xHelpers *getInstance(Display *pDisplay = 0) 157 147 { 158 148 if (!m_pInstance) 159 149 { 160 AssertPtrReturn(pDisplay, 0);150 AssertPtrReturn(pDisplay, NULL); 161 151 m_pInstance = new xHelpers(pDisplay); 162 152 } 153 163 154 return m_pInstance; 164 155 } … … 211 202 212 203 /* Some xHelpers convenience defines. */ 213 #define gX11 xHelpers:: instance()204 #define gX11 xHelpers::getInstance() 214 205 #define xAtom(xa) gX11->xAtom((xa)) 215 206 #define xAtomToString(xa) gX11->xAtomToString((xa)) … … 285 276 286 277 /* Todo: make this iterative */ 287 Window xHelpers::applicationWindowBelowCursor(Window parentWin) const278 Window xHelpers::applicationWindowBelowCursor(Window wndParent) const 288 279 { 289 280 /* No parent, nothing to do. */ 290 if( parentWin== 0)281 if(wndParent == 0) 291 282 return 0; 292 283 293 Window appWin= 0;284 Window wndApp = 0; 294 285 int cProps = -1; 295 286 /* Fetch all x11 window properties of the parent window. */ 296 Atom *pProps = XListProperties(m_pDisplay, parentWin, &cProps);287 Atom *pProps = XListProperties(m_pDisplay, wndParent, &cProps); 297 288 if (cProps > 0) 298 289 { 299 290 /* We check the window for the WM_STATE property. */ 300 for (int i = 0; i < cProps; ++i)301 if (pProps[i] == xAtom(XA_WM_STATE))291 for (int i = 0; i < cProps; ++i) 292 if (pProps[i] == xAtom(XA_WM_STATE)) 302 293 { 303 294 /* Found it. */ 304 appWin = parentWin;295 wndApp = wndParent; 305 296 break; 306 297 } … … 309 300 } 310 301 311 if (! appWin)312 { 313 Window childWin, wtmp;302 if (!wndApp) 303 { 304 Window wndChild, wndTemp; 314 305 int tmp; 315 306 unsigned int utmp; 316 307 /* Query the next child window of the parent window at the current 317 308 * mouse position. */ 318 XQueryPointer(m_pDisplay, parentWin, &wtmp, &childWin, &tmp, &tmp, &tmp, &tmp, &utmp);309 XQueryPointer(m_pDisplay, wndParent, &wndTemp, &wndChild, &tmp, &tmp, &tmp, &tmp, &utmp); 319 310 /* Recursive call our self to dive into the child tree. */ 320 appWin = applicationWindowBelowCursor(childWin);321 } 322 323 return appWin;311 wndApp = applicationWindowBelowCursor(wndChild); 312 } 313 314 return wndApp; 324 315 } 325 316 … … 390 381 391 382 /* Member vars */ 383 uint32_t m_uClientID; 392 384 DragAndDropService *m_pParent; 393 385 Display *m_pDisplay; 394 386 int m_screenId; 395 387 Screen *m_pScreen; 396 Window m_ rootWin;397 Window m_ proxyWin;398 Window m_ curWin;388 Window m_wndRoot; 389 Window m_wndProxy; 390 Window m_wndCur; 399 391 long m_curVer; 400 392 RTCList<Atom> m_formats; … … 418 410 { 419 411 public: 420 DragAndDropService( )412 DragAndDropService(void) 421 413 : m_pDisplay(0) 422 414 , m_hHGCMThread(NIL_RTTHREAD) … … 433 425 virtual int run(bool fDaemonised = false); 434 426 435 virtual void cleanup( )427 virtual void cleanup(void) 436 428 { 437 429 /* Cleanup */ 438 430 x11DragAndDropTerm(); 439 VbglR3DnDTerm();440 431 }; 441 432 442 433 private: 443 int x11DragAndDropInit( );444 int x11DragAndDropTerm( );434 int x11DragAndDropInit(void); 435 int x11DragAndDropTerm(void); 445 436 static int hgcmEventThread(RTTHREAD hThread, void *pvUser); 446 437 static int x11EventThread(RTTHREAD hThread, void *pvUser); … … 451 442 * Unfortunately this doesn't work exactly with the events we need. So we 452 443 * use this predicate method below and XCheckIfEvent. */ 453 static Bool isDnDRespondEvent(Display * /* pDisplay */, XEvent *pEvent, char *pUser)444 static bool isDnDRespondEvent(Display * /* pDisplay */, XEvent *pEvent, char *pUser) 454 445 { 455 446 if (!pEvent) 456 return False;447 return false; 457 448 if ( pEvent->type == SelectionClear 458 449 || pEvent->type == ClientMessage … … 463 454 // || ( pEvent->type == SelectionRequest 464 455 // && reinterpret_cast<XSelectionRequestEvent*>(pEvent)->requestor == reinterpret_cast<Window>(pUser))) 465 return True;466 return False;456 return true; 457 return false; 467 458 } 468 459 … … 487 478 488 479 DragInstance::DragInstance(Display *pDisplay, DragAndDropService *pParent) 489 : m_pParent(pParent) 480 : m_uClientID(0) 481 , m_pParent(pParent) 490 482 , m_pDisplay(pDisplay) 491 483 , m_pScreen(0) 492 , m_ rootWin(0)493 , m_ proxyWin(0)494 , m_ curWin(0)484 , m_wndRoot(0) 485 , m_wndProxy(0) 486 , m_wndCur(0) 495 487 , m_curVer(-1) 496 488 , m_mode(Unknown) … … 500 492 } 501 493 502 void DragInstance::uninit( )494 void DragInstance::uninit(void) 503 495 { 504 496 reset(); 505 if (m_proxyWin != 0) 506 XDestroyWindow(m_pDisplay, m_proxyWin); 497 if (m_wndProxy != 0) 498 XDestroyWindow(m_pDisplay, m_wndProxy); 499 500 if (m_uClientID) 501 { 502 VbglR3DnDDisconnect(m_uClientID); 503 m_uClientID = 0; 504 } 505 507 506 m_state = Uninitialized; 508 507 m_screenId = -1; 509 508 m_pScreen = 0; 510 m_ rootWin= 0;511 m_ proxyWin= 0;512 } 513 514 void DragInstance::reset( )509 m_wndRoot = 0; 510 m_wndProxy = 0; 511 } 512 513 void DragInstance::reset(void) 515 514 { 516 515 /* Hide the proxy win. */ … … 518 517 /* If we are currently the Xdnd selection owner, clear that. */ 519 518 Window w = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 520 if (w == m_ proxyWin)519 if (w == m_wndProxy) 521 520 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), None, CurrentTime); 522 521 /* Clear any other DnD specific data on the proxy win. */ 523 clearFormatsWindowProperty(m_ proxyWin);524 clearActionsWindowProperty(m_ proxyWin);522 clearFormatsWindowProperty(m_wndProxy); 523 clearActionsWindowProperty(m_wndProxy); 525 524 /* Reset the internal state. */ 526 525 m_formats.clear(); 527 m_ curWin= 0;526 m_wndCur = 0; 528 527 m_curVer = -1; 529 528 m_state = Initialized; … … 546 545 int DragInstance::init(uint32_t u32ScreenId) 547 546 { 548 int rc = VINF_SUCCESS; 547 int rc; 548 549 549 do 550 550 { 551 551 uninit(); 552 /* Enough screens configured in the x11 server? */ 552 553 rc = VbglR3DnDConnect(&m_uClientID); 554 if (RT_FAILURE(rc)) 555 break; 556 557 /* 558 * Enough screens configured in the x11 server? 559 */ 553 560 if ((int)u32ScreenId > ScreenCount(m_pDisplay)) 554 561 { 555 rc = VERR_ GENERAL_FAILURE;562 rc = VERR_INVALID_PARAMETER; 556 563 break; 557 564 } … … 565 572 m_screenId = u32ScreenId; 566 573 /* Now query the corresponding root window of this screen. */ 567 m_ rootWin= RootWindow(m_pDisplay, m_screenId);568 if (!m_ rootWin)574 m_wndRoot = RootWindow(m_pDisplay, m_screenId); 575 if (!m_wndRoot) 569 576 { 570 577 rc = VERR_GENERAL_FAILURE; 571 578 break; 572 579 } 573 /* Create an invisible window which will act as proxy for the DnD 580 581 /* 582 * Create an invisible window which will act as proxy for the DnD 574 583 * operation. This window will be used for both the GH and HG 575 * direction. */ 584 * direction. 585 */ 576 586 XSetWindowAttributes attr; 577 587 RT_ZERO(attr); 578 588 attr.do_not_propagate_mask = 0; 579 589 attr.override_redirect = True; 580 // attr.background_pixel = WhitePixel(m_pDisplay, m_screenId); 581 m_proxyWin = XCreateWindow(m_pDisplay, m_rootWin, 0, 0, 1, 1, 0, 590 #if 0 591 attr.background_pixel = WhitePixel(m_pDisplay, m_screenId); 592 #endif 593 m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot, 0, 0, 1, 1, 0, 582 594 CopyFromParent, InputOnly, CopyFromParent, 583 595 CWOverrideRedirect | CWDontPropagate, 584 596 &attr); 585 586 // m_proxyWin = XCreateSimpleWindow(m_pDisplay, m_rootWin, 0, 0, 50, 50, 0, WhitePixel(m_pDisplay, m_screenId), WhitePixel(m_pDisplay, m_screenId)); 587 588 if (!m_proxyWin) 597 #ifdef DEBUG_andy 598 m_wndProxy = XCreateSimpleWindow(m_pDisplay, m_wndRoot, 0, 0, 50, 50, 0, 599 WhitePixel(m_pDisplay, m_screenId), 600 WhitePixel(m_pDisplay, m_screenId)); 601 #endif 602 if (!m_wndProxy) 589 603 { 590 604 rc = VERR_GENERAL_FAILURE; 591 605 break; 592 606 } 607 593 608 /* Make the new window Xdnd aware. */ 594 609 Atom ver = VBOX_XDND_VERSION; 595 XChangeProperty(m_pDisplay, m_ proxyWin, xAtom(XA_XdndAware), XA_ATOM, 32, PropModeReplace,610 XChangeProperty(m_pDisplay, m_wndProxy, xAtom(XA_XdndAware), XA_ATOM, 32, PropModeReplace, 596 611 reinterpret_cast<unsigned char*>(&ver), 1); 597 612 } while (0); 598 613 599 m_state = Initialized; 600 614 if (RT_SUCCESS(rc)) 615 m_state = Initialized; 616 617 LogFlowFuncLeaveRC(rc); 601 618 return rc; 602 619 } … … 606 623 */ 607 624 608 int DragInstance::hgEnter(const RTCList<RTCString> &formats, uint32_t actions) 609 { 610 int rc = VINF_SUCCESS; 611 625 int DragInstance::hgEnter(const RTCList<RTCString> &formats, uint32_t uActions) 626 { 612 627 reset(); 613 DO(("DnD_ENTR: formats=%u: ", formats.size())); 614 #if defined(VERBOSE) && defined(DEBUG_poetzsch) 628 629 #ifdef DEBUG 630 LogFlowThisFunc(("uActions=0x%x, lstFormats=%zu: ", uActions, formats.size())); 615 631 for (size_t i = 0; i < formats.size(); ++i) 616 DO(("'%s' ", formats.at(i).c_str()));617 #endif /* DEBUG */ 618 DO(("\n")); 632 LogFlow(("'%s' ", formats.at(i).c_str())); 633 LogFlow(("\n")); 634 #endif 619 635 620 636 m_formats = toAtomList(formats); … … 622 638 /* If we have more than 3 formats we have to use the type list extension. */ 623 639 if (m_formats.size() > 3) 624 setFormatsWindowProperty(m_ proxyWin, xAtom(XA_XdndTypeList));640 setFormatsWindowProperty(m_wndProxy, xAtom(XA_XdndTypeList)); 625 641 626 642 /* Announce the possible actions */ 627 setActionsWindowProperty(m_ proxyWin, toX11Actions(actions));643 setActionsWindowProperty(m_wndProxy, toX11Actions(uActions)); 628 644 629 645 /* Set the DnD selection owner to our window. */ 630 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_ proxyWin, CurrentTime);646 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy, CurrentTime); 631 647 632 648 m_mode = HG; 633 649 m_state = Dragging; 634 650 635 return rc; 636 } 637 638 int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t action) 639 { 640 DO(("DnD_MOVE: ")); 651 return VINF_SUCCESS; 652 } 653 654 int DragInstance::hgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction) 655 { 656 LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", 657 u32xPos, u32yPos, uAction)); 641 658 642 659 if ( m_mode != HG … … 650 667 moveCursor(u32xPos, u32yPos); 651 668 652 Window newWin = None; /* Default to _no_ window below the cursor. */ 653 long newVer = -1; /* This means the current window is _not_ XdndAware. */ 669 long newVer = -1; /* This means the current window is _not_ XdndAware. */ 654 670 655 671 /* Search for the application window below the cursor. */ 656 newWin = gX11->applicationWindowBelowCursor(m_rootWin);657 if ( newWin!= None)672 Window wndCursor = gX11->applicationWindowBelowCursor(m_wndRoot); 673 if (wndCursor != None) 658 674 { 659 675 /* Temp stuff for the XGetWindowProperty call. */ … … 662 678 unsigned long cItems, cbRemaining; 663 679 unsigned char *pcData = NULL; 680 664 681 /* Query the XdndAware property from the window. We are interested in 665 682 * the version and if it is XdndAware at all. */ 666 xrc = XGetWindowProperty(m_pDisplay, newWin, xAtom(XA_XdndAware), 0, 2, False, AnyPropertyType, &atmp, &fmt, &cItems, &cbRemaining, &pcData); 683 xrc = XGetWindowProperty(m_pDisplay, wndCursor, xAtom(XA_XdndAware), 684 0, 2, False, AnyPropertyType, 685 &atmp, &fmt, &cItems, &cbRemaining, &pcData); 667 686 if (RT_UNLIKELY(xrc != Success)) 668 DO(("DnD_MOVE: error in getting the window property (%s)\n", gX11->xErrorToString(xrc).c_str()));687 LogFlowThisFunc(("Error in getting the window property: %s\n", gX11->xErrorToString(xrc).c_str())); 669 688 else 670 689 { 671 690 if (RT_UNLIKELY(pcData == NULL || fmt != 32 || cItems != 1)) 672 DO(("Prop=error[data=%#x,fmt=%u,items=%u]", pcData, fmt, cItems));691 LogFlowThisFunc(("Wrong properties pcData=%#x, iFmt=%u, cItems=%u\n", pcData, fmt, cItems)); 673 692 else 674 693 { 675 694 newVer = reinterpret_cast<long*>(pcData)[0]; 676 DO(("XdndAware=%u", newVer));695 LogFlowThisFunc(("wndCursor=%#x, XdndAware=%u\n", newVer)); 677 696 } 678 697 XFree(pcData); … … 680 699 } 681 700 682 if (newWin != m_curWin && m_curVer != -1) 683 { 684 DO(("leave=%#x ", m_curWin)); 701 /* 702 * Is the window under the cursor another one than our current one? 703 */ 704 if (wndCursor != m_wndCur && m_curVer != -1) 705 { 706 LogFlowThisFunc(("Leaving window=%#x\n", m_wndCur)); 685 707 686 708 /* We left the current XdndAware window. Announce this to the window. */ 687 688 709 XClientMessageEvent m; 689 710 RT_ZERO(m); 690 711 m.type = ClientMessage; 691 712 m.display = m_pDisplay; 692 m.window = m_ curWin;713 m.window = m_wndCur; 693 714 m.message_type = xAtom(XA_XdndLeave); 694 715 m.format = 32; 695 m.data.l[0] = m_ proxyWin;696 697 xrc = XSendEvent(m_pDisplay, m_ curWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m));716 m.data.l[0] = m_wndProxy; 717 718 xrc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 698 719 if (RT_UNLIKELY(xrc == 0)) 699 DO(("DnD_MOVE: error sending xevent\n")); 700 } 701 702 if (newWin != m_curWin && newVer != -1) 703 { 704 DO(("enter=%#x ", newWin)); 705 706 /* We enter a new window. Announce the XdndEnter event to the new 720 LogFlowThisFunc(("Error sending XA_XdndLeave to old window=%#x\n", m_wndCur)); 721 } 722 723 /* 724 * Do we have a new window which now is under the cursor? 725 */ 726 if (wndCursor != m_wndCur && newVer != -1) 727 { 728 LogFlowThisFunc(("Entering window=%#x\n", wndCursor)); 729 730 /* 731 * We enter a new window. Announce the XdndEnter event to the new 707 732 * window. The first three mime types are attached to the event (the 708 733 * others could be requested by the XdndTypeList property from the 709 * window itself). */710 734 * window itself). 735 */ 711 736 XClientMessageEvent m; 712 737 RT_ZERO(m); 713 738 m.type = ClientMessage; 714 739 m.display = m_pDisplay; 715 m.window = newWin;740 m.window = wndCursor; 716 741 m.message_type = xAtom(XA_XdndEnter); 717 742 m.format = 32; 718 m.data.l[0] = m_ proxyWin;743 m.data.l[0] = m_wndProxy; 719 744 m.data.l[1] = RT_MAKE_U32_FROM_U8(m_formats.size() > 3 ? 1 : 0, 0, 0, RT_MIN(VBOX_XDND_VERSION, newVer)); 720 745 m.data.l[2] = m_formats.value(0, None); … … 722 747 m.data.l[4] = m_formats.value(2, None); 723 748 724 xrc = XSendEvent(m_pDisplay, newWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m));749 xrc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 725 750 if (RT_UNLIKELY(xrc == 0)) 726 DO(("DnD_MOVE: error sending xevent\n"));751 LogFlowThisFunc(("Error sending XA_XdndEnter to new window=%#x\n", wndCursor)); 727 752 } 728 753 729 754 if (newVer != -1) 730 755 { 731 DO(("move=%#x pos=%ux%u ", newWin, u32xPos, u32yPos)); 732 733 /* Send a XdndPosition event with the proposed action to the guest. */ 734 735 Atom pa = toX11Action(action); 736 DO(("action='%s' ", xAtomToString(pa).c_str())); 756 LogFlowThisFunc(("Moving window=%#x, xPos=%RU32, yPos=%RU32\n", 757 wndCursor, u32xPos, u32yPos)); 758 759 /* 760 * Send a XdndPosition event with the proposed action to the guest. 761 */ 762 Atom pa = toX11Action(uAction); 763 LogFlowThisFunc(("strAction='%s' ", xAtomToString(pa).c_str())); 737 764 738 765 XClientMessageEvent m; … … 740 767 m.type = ClientMessage; 741 768 m.display = m_pDisplay; 742 m.window = newWin;769 m.window = wndCursor; 743 770 m.message_type = xAtom(XA_XdndPosition); 744 771 m.format = 32; 745 m.data.l[0] = m_ proxyWin;772 m.data.l[0] = m_wndProxy; 746 773 m.data.l[2] = RT_MAKE_U32(u32yPos, u32xPos); 747 774 m.data.l[3] = CurrentTime; 748 775 m.data.l[4] = pa; 749 776 750 xrc = XSendEvent(m_pDisplay, newWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m));777 xrc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 751 778 if (RT_UNLIKELY(xrc == 0)) 752 DO(("DnD_MOVE: error sending xevent\n")); 753 } 754 if (newWin == None && newVer == -1) 779 LogFlowThisFunc(("Error sending XA_XdndPosition to window=%#x\n", wndCursor)); 780 } 781 782 if (wndCursor == None && newVer == -1) 783 { 755 784 /* No window to process, so send a ignore ack event to the host. */ 756 rc = VbglR3DnDHGAcknowledgeOperation(DND_IGNORE_ACTION); 757 758 m_curWin = newWin; 785 rc = VbglR3DnDHGAcknowledgeOperation(m_uClientID, DND_IGNORE_ACTION); 786 } 787 788 m_wndCur = wndCursor; 759 789 m_curVer = RT_MIN(VBOX_XDND_VERSION, newVer); 760 790 761 DO(("\n")); 762 791 LogFlowFuncLeaveRC(rc); 763 792 return rc; 764 793 } … … 774 803 int rc = VINF_SUCCESS; 775 804 if ( e.xclient.message_type == xAtom(XA_XdndStatus) 776 && m_ curWin== static_cast<Window>(e.xclient.data.l[0]))805 && m_wndCur == static_cast<Window>(e.xclient.data.l[0])) 777 806 { 778 807 /* The XdndStatus message tell us if the window will accept the DnD 779 808 * event and with which action. We immediately send this info down to 780 809 * the host as a response of a previous DnD message. */ 781 DO(("DnD_STAT: win=%#x,accept=%RTbool,action='%s'\n", 782 e.xclient.data.l[0], 783 ASMBitTest(&e.xclient.data.l[1], 0), 784 xAtomToString(e.xclient.data.l[4]).c_str())); 810 LogFlowThisFunc(("XA_XdndStatus wnd=%#x, accept=%RTbool, action='%s'\n", 811 e.xclient.data.l[0], 812 ASMBitTest(&e.xclient.data.l[1], 0), 813 xAtomToString(e.xclient.data.l[4]).c_str())); 814 785 815 uint32_t uAction = DND_IGNORE_ACTION; 786 /* Todo: compare this with the allowed actions. */816 /** @todo Compare this with the allowed actions. */ 787 817 if (ASMBitTest(&e.xclient.data.l[1], 0)) 788 818 uAction = toHGCMAction(static_cast<Atom>(e.xclient.data.l[4])); 789 rc = VbglR3DnDHGAcknowledgeOperation(uAction); 819 820 rc = VbglR3DnDHGAcknowledgeOperation(m_uClientID, uAction); 790 821 } 791 822 else if (e.xclient.message_type == xAtom(XA_XdndFinished)) 792 823 { 793 824 /* This message is send on a un/successful DnD drop request. */ 794 DO(("DnD_FINI: win=%#x,success=%RTbool,action='%s'\n",825 LogFlowThisFunc(("XA_XdndFinished: wnd=%#x, success=%RTbool, action='%s'\n", 795 826 e.xclient.data.l[0], 796 827 ASMBitTest(&e.xclient.data.l[1], 0), 797 828 xAtomToString(e.xclient.data.l[2]).c_str())); 829 798 830 reset(); 799 831 } 800 832 else 801 DO(("DnD_CLI: win=%#x,msg='%s'\n", e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str())); 833 LogFlowThisFunc(("Unhandled: wnd=%#x, msg='%s'\n", 834 e.xclient.data.l[0], xAtomToString(e.xclient.message_type).c_str())); 835 836 LogFlowFuncLeaveRC(rc); 802 837 return rc; 803 838 } 804 839 805 int DragInstance::hgDrop() 806 { 807 DO(("DnD_DROP: win=%#x\n", m_curWin)); 840 int DragInstance::hgDrop(void) 841 { 842 LogFlowThisFunc(("wndCur=%#x, mMode=%RU32, mState=%RU32\n", 843 m_wndCur, m_mode, m_state)); 808 844 809 845 if ( m_mode != HG … … 818 854 m.type = ClientMessage; 819 855 m.display = m_pDisplay; 820 m.window = m_ curWin;856 m.window = m_wndCur; 821 857 m.message_type = xAtom(XA_XdndDrop); 822 858 m.format = 32; 823 m.data.l[0] = m_ proxyWin;859 m.data.l[0] = m_wndProxy; 824 860 m.data.l[2] = CurrentTime; 825 861 826 int xrc = XSendEvent(m_pDisplay, m_ curWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m));862 int xrc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 827 863 if (RT_UNLIKELY(xrc == 0)) 828 DO(("DnD_DROP: error sending xevent\n"));829 830 m_ curWin= None;864 LogFlowThisFunc(("Error sending XA_XdndDrop to window=%#x\n", m_wndCur)); 865 866 m_wndCur = None; 831 867 m_curVer = -1; 832 868 833 869 m_state = Dropped; 834 870 871 LogFlowFuncLeaveRC(rc); 835 872 return rc; 836 873 } … … 844 881 return VERR_INVALID_STATE; 845 882 846 DO(("DnD_SELR: owner=%#x,requestor=%#x,sel_atom='%s',tar_atom='%s',prop_atom='%s',time=%u\n",847 e.xselectionrequest.owner,848 e.xselectionrequest.requestor,849 xAtomToString(e.xselectionrequest.selection).c_str(),850 xAtomToString(e.xselectionrequest.target).c_str(),851 xAtomToString(e.xselectionrequest.property).c_str(),852 e.xselectionrequest.time));883 LogFlowThisFunc(("owner=%#x, requestor=%#x, sel_atom='%s', tar_atom='%s', prop_atom='%s', time=%u\n", 884 e.xselectionrequest.owner, 885 e.xselectionrequest.requestor, 886 xAtomToString(e.xselectionrequest.selection).c_str(), 887 xAtomToString(e.xselectionrequest.target).c_str(), 888 xAtomToString(e.xselectionrequest.property).c_str(), 889 e.xselectionrequest.time)); 853 890 854 891 int rc = VINF_SUCCESS; 855 892 856 /* A window is asking for some data. Normally here the data would be copied 893 /* 894 * A window is asking for some data. Normally here the data would be copied 857 895 * into the selection buffer and send to the requestor. Obviously we can't 858 896 * do that, cause we first need to ask the host for the data of the 859 897 * requested mime type. This is done and later answered with the correct 860 * data (s. dataReceived). */ 898 * data (s. dataReceived). 899 */ 861 900 862 901 /* Is the requestor asking for the possible mime types? */ 863 902 if(e.xselectionrequest.target == xAtom(XA_TARGETS)) 864 903 { 865 DO(("DnD_SELR: ask for target list\n")); 904 LogFlowThisFunc(("wnd=%#x asking for target list\n", e.xselectionrequest.requestor)); 905 866 906 /* If so, set the window property with the formats on the requestor 867 907 * window. */ 868 908 setFormatsWindowProperty(e.xselectionrequest.requestor, e.xselectionrequest.property); 909 869 910 XEvent s; 870 911 RT_ZERO(s); … … 876 917 s.xselection.target = e.xselectionrequest.target; 877 918 s.xselection.property = e.xselectionrequest.property; 919 878 920 int xrc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s); 879 921 if (RT_UNLIKELY(xrc == 0)) 880 DO(("DnD_SELR: error sending xevent\n"));922 LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor)); 881 923 } 882 924 /* Is the requestor asking for a specific mime type (we support)? */ 883 925 else if(m_formats.contains(e.xselectionrequest.target)) 884 926 { 885 DO(("DnD_SELR: ask for data (format='%s')\n", xAtomToString(e.xselectionrequest.target).c_str())); 927 LogFlowThisFunc(("wnd=%#x asking for data (format='%s')\n", 928 e.xselectionrequest.requestor, xAtomToString(e.xselectionrequest.target).c_str())); 929 886 930 /* If so, we need to inform the host about this request. Save the 887 931 * selection request event for later use. */ … … 889 933 // || m_curWin != e.xselectionrequest.requestor) 890 934 { 891 DO(("DnD_SELR: refuse\n")); 935 LogFlowThisFunc(("Refusing ...\n")); 936 892 937 XEvent s; 893 938 RT_ZERO(s); … … 899 944 s.xselection.target = None; 900 945 s.xselection.property = e.xselectionrequest.property; 946 901 947 int xrc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s); 902 948 if (RT_UNLIKELY(xrc == 0)) 903 DO(("DnD_SELR: error sending xevent\n"));949 LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor)); 904 950 } 905 951 else 906 952 { 953 LogFlowThisFunc(("Copying data from host ...\n")); 954 907 955 memcpy(&m_selEvent, &e, sizeof(XEvent)); 908 rc = VbglR3DnDHGRequestData( xAtomToString(e.xselectionrequest.target).c_str());956 rc = VbglR3DnDHGRequestData(m_uClientID, xAtomToString(e.xselectionrequest.target).c_str()); 909 957 } 910 958 } … … 912 960 else 913 961 { 914 DO(("DnD_SELR: refuse\n")); 962 LogFlowThisFunc(("Refusing unknown command\n")); 963 915 964 /* We don't understand this request message and therefore answer with an 916 965 * refusal messages. */ … … 926 975 int xrc = XSendEvent(e.xselection.display, e.xselectionrequest.requestor, False, 0, &s); 927 976 if (RT_UNLIKELY(xrc == 0)) 928 DO(("DnD_SELR: error sending xevent\n")); 929 } 930 977 LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", e.xselectionrequest.requestor)); 978 } 979 980 LogFlowFuncLeaveRC(rc); 931 981 return rc; 932 982 } … … 951 1001 memcpy(pvNewData, pvData, cData); 952 1002 953 /* The host send us the DnD data in the requested mime type. This allows us 1003 /* 1004 * The host send us the DnD data in the requested mime type. This allows us 954 1005 * to fill the XdndSelection property of the requestor window with the data 955 * and afterwards inform him about the new status. */ 1006 * and afterwards inform him about the new status. 1007 */ 956 1008 XEvent s; 957 1009 RT_ZERO(s); … … 965 1017 s.xselection.property = m_selEvent.xselectionrequest.property; 966 1018 967 DO(("DnD_SEND:owner=%#x,requestor=%#x,sel_atom='%s',tar_atom='%s',prop_atom='%s',time=%u\n",968 m_selEvent.xselectionrequest.owner,969 s.xselection.requestor,970 xAtomToString(s.xselection.selection).c_str(),971 xAtomToString(s.xselection.target).c_str(),972 xAtomToString(s.xselection.property).c_str(),973 s.xselection.time));1019 LogFlowThisFunc(("owner=%#x,requestor=%#x,sel_atom='%s',tar_atom='%s',prop_atom='%s',time=%u\n", 1020 m_selEvent.xselectionrequest.owner, 1021 s.xselection.requestor, 1022 xAtomToString(s.xselection.selection).c_str(), 1023 xAtomToString(s.xselection.target).c_str(), 1024 xAtomToString(s.xselection.property).c_str(), 1025 s.xselection.time)); 974 1026 975 1027 /* Fill up the property with the data. */ … … 978 1030 int xrc = XSendEvent(s.xselection.display, s.xselection.requestor, True, 0, &s); 979 1031 if (RT_UNLIKELY(xrc == 0)) 980 DO(("DnD_SEND: error sending xevent\n"));1032 LogFlowThisFunc(("Error sending SelectionNotify event to wnd=%#x\n", s.xselection.requestor)); 981 1033 982 1034 return VINF_SUCCESS; … … 989 1041 */ 990 1042 991 int DragInstance::ghIsDnDPending( )1043 int DragInstance::ghIsDnDPending(void) 992 1044 { 993 1045 int rc = VINF_SUCCESS; 994 Window w = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 995 DO(("Checking pending %X %X\n", w, m_proxyWin)); 1046 Window wndOwner = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 1047 LogFlowThisFunc(("Checking pending wndOwner=%#x wndProxy=%#x\n", wndOwner, m_wndProxy)); 1048 996 1049 /* Is there someone own the Xdnd selection which aren't we. */ 997 if ( w 998 && w != m_proxyWin)1050 if ( wndOwner 1051 && wndOwner != m_wndProxy) 999 1052 { 1000 1053 /* Map the window on the current cursor position, which should provoke … … 1007 1060 int xrc = Success; 1008 1061 XClientMessageEvent *clme = reinterpret_cast<XClientMessageEvent*>(&e); 1009 DO(("next X event %s\n", gX11->xAtomToString(clme->message_type).c_str()));1062 LogFlowThisFunc(("Next X event %s\n", gX11->xAtomToString(clme->message_type).c_str())); 1010 1063 if (clme->message_type == xAtom(XA_XdndEnter)) 1011 1064 { … … 1018 1071 m_formats.clear(); 1019 1072 m_actions.clear(); 1020 m_ curWin = w;1021 DO(("XA_XdndEnter\n"));1073 m_wndCur = wndOwner; 1074 LogFlowThisFunc(("XA_XdndEnter\n")); 1022 1075 /* Check if the mime types are in the msg itself or if we need 1023 1076 * to fetch the XdndTypeList property from the window. */ … … 1026 1079 for (int i = 2; i < 5; ++i) 1027 1080 { 1028 DO(("receive list msg: %s\n", gX11->xAtomToString(clme->data.l[i]).c_str()));1081 LogFlowThisFunc(("Receive list msg: %s\n", gX11->xAtomToString(clme->data.l[i]).c_str())); 1029 1082 m_formats.append(clme->data.l[i]); 1030 1083 } … … 1032 1085 else 1033 1086 { 1034 xrc = XGetWindowProperty(m_pDisplay, w , xAtom(XA_XdndTypeList), 0, VBOX_MAX_XPROPERTIES, False, XA_ATOM, &type, &f, &n, &a, &ret);1087 xrc = XGetWindowProperty(m_pDisplay, wndOwner, xAtom(XA_XdndTypeList), 0, VBOX_MAX_XPROPERTIES, False, XA_ATOM, &type, &f, &n, &a, &ret); 1035 1088 if ( xrc == Success 1036 1089 && n > 0 … … 1040 1093 for (int i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i) 1041 1094 { 1042 DO(("receive list: %s\n", gX11->xAtomToString(data[i]).c_str()));1095 LogFlowThisFunc(("Receive list: %s\n", gX11->xAtomToString(data[i]).c_str())); 1043 1096 m_formats.append(data[i]); 1044 1097 } … … 1047 1100 } 1048 1101 /* Fetch the possible list of actions, if this property is set. */ 1049 xrc = XGetWindowProperty(m_pDisplay, w , xAtom(XA_XdndActionList), 0, VBOX_MAX_XPROPERTIES, False, XA_ATOM, &type, &f, &n, &a, &ret);1102 xrc = XGetWindowProperty(m_pDisplay, wndOwner, xAtom(XA_XdndActionList), 0, VBOX_MAX_XPROPERTIES, False, XA_ATOM, &type, &f, &n, &a, &ret); 1050 1103 if ( xrc == Success 1051 1104 && n > 0 … … 1055 1108 for (int i = 0; i < RT_MIN(VBOX_MAX_XPROPERTIES, n); ++i) 1056 1109 { 1057 DO(("receive actions: %s\n", gX11->xAtomToString(data[i]).c_str()));1110 LogFlowThisFunc(("Receive actions: %s\n", gX11->xAtomToString(data[i]).c_str())); 1058 1111 m_actions.append(data[i]); 1059 1112 } … … 1072 1125 m.message_type = xAtom(XA_XdndStatus); 1073 1126 m.format = 32; 1074 m.data.l[0] = m_ proxyWin;1127 m.data.l[0] = m_wndProxy; 1075 1128 m.data.l[1] = 1; 1076 1129 m.data.l[4] = xAtom(XA_XdndActionCopy); 1077 1130 xrc = XSendEvent(m_pDisplay, clme->data.l[0], False, 0, reinterpret_cast<XEvent*>(&m)); 1078 1131 if (RT_UNLIKELY(xrc == 0)) 1079 DO(("DnD_PNDG: error sending xevent\n"));1132 LogFlowThisFunc(("Error sending xevent\n")); 1080 1133 } 1081 1134 else if (clme->message_type == xAtom(XA_XdndPosition)) 1082 1135 { 1083 DO(("XA_XdndPosition\n"));1136 LogFlowThisFunc(("XA_XdndPosition\n")); 1084 1137 XClientMessageEvent m; 1085 1138 RT_ZERO(m); … … 1089 1142 m.message_type = xAtom(XA_XdndStatus); 1090 1143 m.format = 32; 1091 m.data.l[0] = m_ proxyWin;1144 m.data.l[0] = m_wndProxy; 1092 1145 m.data.l[1] = 1; 1093 1146 m.data.l[4] = clme->data.l[4]; 1094 1147 xrc = XSendEvent(m_pDisplay, clme->data.l[0], False, 0, reinterpret_cast<XEvent*>(&m)); 1095 1148 if (RT_UNLIKELY(xrc == 0)) 1096 DO(("DnD_PNDG: error sending xevent\n"));1149 LogFlowThisFunc(("Error sending xevent\n")); 1097 1150 } 1098 1151 else if (clme->message_type == xAtom(XA_XdndLeave)) … … 1102 1155 hideProxyWin(); 1103 1156 1104 rc = VbglR3DnDGHAcknowledgePending(DND_COPY_ACTION, toHGCMActions(m_actions), gX11->xAtomListToString(m_formats).c_str()); 1105 } 1157 rc = VbglR3DnDGHAcknowledgePending(DND_COPY_ACTION, toHGCMActions(m_actions), 1158 gX11->xAtomListToString(m_formats).c_str()); 1159 } 1160 1161 LogFlowFuncLeaveRC(rc); 1106 1162 return rc; 1107 1163 } … … 1109 1165 int DragInstance::ghDropped(const RTCString &strFormat, uint32_t action) 1110 1166 { 1111 DO(("DND_DRO:format='%s' action=%d\n", strFormat.c_str(), action));1167 LogFlowThisFunc(("format='%s' action=%d\n", strFormat.c_str(), action)); 1112 1168 int rc = VINF_SUCCESS; 1113 1169 … … 1118 1174 /* We send a fake release event to the current window, cause 1119 1175 * this should have the grab. */ 1120 sendButtonEvent(m_ curWin, rx, ry, 1, false);1176 sendButtonEvent(m_wndCur, rx, ry, 1, false); 1121 1177 /* The fake button release event, should lead to an XdndDrop event from the 1122 1178 * source. Because of the showing of the proxy window, sometimes other Xdnd … … 1145 1201 /* Request to convert the selection in the specific format and 1146 1202 * place it to our proxy window as property. */ 1147 Window srcWin = m_ curWin;//clme->data.l[0];1203 Window srcWin = m_wndCur;//clme->data.l[0]; 1148 1204 Atom aFormat = gX11->stringToxAtom(strFormat.c_str()); 1149 XConvertSelection(m_pDisplay, xAtom(XA_XdndSelection), aFormat, xAtom(XA_XdndSelection), m_ proxyWin, clme->data.l[2]);1205 XConvertSelection(m_pDisplay, xAtom(XA_XdndSelection), aFormat, xAtom(XA_XdndSelection), m_wndProxy, clme->data.l[2]); 1150 1206 /* Wait for the selection notify event. */ 1151 1207 RT_ZERO(e); … … 1156 1212 && e.xselection.display == m_pDisplay 1157 1213 && e.xselection.selection == xAtom(XA_XdndSelection) 1158 && e.xselection.requestor == m_ proxyWin1214 && e.xselection.requestor == m_wndProxy 1159 1215 && e.xselection.target == aFormat) 1160 1216 { 1161 DO(("DND_DRO: selection notfiy (from: %x)\n", m_curWin));1217 LogFlowThisFunc(("Selection notfiy (from: %x)\n", m_wndCur)); 1162 1218 Atom type; 1163 1219 int format; 1164 1220 unsigned long cItems, cbRemaining; 1165 1221 unsigned char *ucData = 0; 1166 XGetWindowProperty(m_pDisplay, m_ proxyWin, xAtom(XA_XdndSelection),1222 XGetWindowProperty(m_pDisplay, m_wndProxy, xAtom(XA_XdndSelection), 1167 1223 0, VBOX_MAX_XPROPERTIES, True, AnyPropertyType, 1168 1224 &type, &format, &cItems, &cbRemaining, &ucData); 1169 DO(("DND_DRO:%s %d %d %s\n", gX11->xAtomToString(type).c_str(), cItems, format, ucData));1225 LogFlowThisFunc(("%s %d %d %s\n", gX11->xAtomToString(type).c_str(), cItems, format, ucData)); 1170 1226 if ( type != None 1171 1227 && ucData != NULL … … 1181 1237 && ucData[cbData - 1] != '\0') 1182 1238 { 1183 DO(("rebuild %u\n", cbData));1239 LogFlowThisFunc(("Rebuild %u\n", cbData)); 1184 1240 unsigned char *ucData1 = static_cast<unsigned char*>(RTMemAlloc(cbData + 1)); 1185 1241 if (ucData1) … … 1198 1254 rc = VbglR3DnDGHSendData(ucData, cbData); 1199 1255 1200 DO(("send responce\n"));1256 LogFlowThisFunc(("send responce\n")); 1201 1257 /* Confirm the result of the transfer to the source window. */ 1202 1258 XClientMessageEvent m; … … 1207 1263 m.message_type = xAtom(XA_XdndFinished); 1208 1264 m.format = 32; 1209 m.data.l[0] = m_ proxyWin;1265 m.data.l[0] = m_wndProxy; 1210 1266 m.data.l[1] = RT_SUCCESS(rc) ? 1 : 0; /* Confirm or deny success */ 1211 1267 m.data.l[2] = RT_SUCCESS(rc) ? toX11Action(action) : None; /* Action used on success */ … … 1213 1269 int xrc = XSendEvent(m_pDisplay, srcWin, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1214 1270 if (RT_UNLIKELY(xrc == 0)) 1215 DO(("DnD_DRO: error sending xevent\n"));1271 LogFlowThisFunc(("Error sending xevent\n")); 1216 1272 } 1217 1273 else … … 1236 1292 m.message_type = xAtom(XA_XdndFinished); 1237 1293 m.format = 32; 1238 m.data.l[0] = m_ proxyWin;1294 m.data.l[0] = m_wndProxy; 1239 1295 m.data.l[1] = 0; 1240 1296 m.data.l[2] = None; 1241 1297 int xrc = XSendEvent(m_pDisplay, srcWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1242 1298 if (RT_UNLIKELY(xrc == 0)) 1243 DO(("DnD_DRO: error sending xevent\n"));1244 m_ curWin= 0;1299 LogFlowThisFunc(("Error sending xevent\n")); 1300 m_wndCur = 0; 1245 1301 } 1246 1302 /* Cleanup */ … … 1268 1324 reset(); 1269 1325 1326 LogFlowFuncLeaveRC(rc); 1270 1327 return rc; 1271 1328 } … … 1281 1338 /* Move the guest pointer to the DnD position, so we can find the window 1282 1339 * below that position. */ 1283 XWarpPointer(m_pDisplay, None, m_ rootWin, 0, 0, 0, 0, u32xPos, u32yPos);1340 XWarpPointer(m_pDisplay, None, m_wndRoot, 0, 0, 0, 0, u32xPos, u32yPos); 1284 1341 return VINF_SUCCESS; 1285 1342 } … … 1295 1352 RT_ZERO(be); 1296 1353 be.display = m_pDisplay; 1297 be.root = m_ rootWin;1354 be.root = m_wndRoot; 1298 1355 be.window = w; 1299 1356 be.subwindow = None; … … 1312 1369 int xrc = XSendEvent(m_pDisplay, be.window, True, ButtonPressMask, reinterpret_cast<XEvent*>(&be)); 1313 1370 if (RT_UNLIKELY(xrc == 0)) 1314 DO(("DnD_BTN: error sending xevent\n")); 1315 } 1316 1371 LogFlowThisFunc(("Error sending xevent\n")); 1372 } 1317 1373 } 1318 1374 … … 1323 1379 Window r, c; 1324 1380 // XTestGrabControl(m_pDisplay, False); 1325 XQueryPointer(m_pDisplay, m_ rootWin, &r, &c, &rx, &ry, &cx, &cy, &m);1381 XQueryPointer(m_pDisplay, m_wndRoot, &r, &c, &rx, &ry, &cx, &cy, &m); 1326 1382 XSynchronize(m_pDisplay, True); 1327 XMapWindow(m_pDisplay, m_ proxyWin);1328 XRaiseWindow(m_pDisplay, m_ proxyWin);1329 XMoveResizeWindow(m_pDisplay, m_ proxyWin, rx, ry, 1, 1);1330 XWarpPointer(m_pDisplay, None, m_ rootWin, 0, 0, 0, 0, rx , ry);1383 XMapWindow(m_pDisplay, m_wndProxy); 1384 XRaiseWindow(m_pDisplay, m_wndProxy); 1385 XMoveResizeWindow(m_pDisplay, m_wndProxy, rx, ry, 1, 1); 1386 XWarpPointer(m_pDisplay, None, m_wndRoot, 0, 0, 0, 0, rx , ry); 1331 1387 XSynchronize(m_pDisplay, False); 1332 1388 // XTestGrabControl(m_pDisplay, True); 1333 1389 } 1334 1390 1335 void DragInstance::hideProxyWin( ) const1336 { 1337 XUnmapWindow(m_pDisplay, m_ proxyWin);1391 void DragInstance::hideProxyWin(void) const 1392 { 1393 XUnmapWindow(m_pDisplay, m_wndProxy); 1338 1394 } 1339 1395 1340 1396 /* Currently, not used */ 1341 void DragInstance::registerForEvents(Window w ) const1397 void DragInstance::registerForEvents(Window wndThis) const 1342 1398 { 1343 1399 // if (w == m_proxyWin) 1344 1400 // return; 1345 1401 1346 DO(("%x\n", w));1402 LogFlowThisFunc(("%x\n", wndThis)); 1347 1403 // XSelectInput(m_pDisplay, w, Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask);//| SubstructureNotifyMask); 1348 1404 // XSelectInput(m_pDisplay, w, ButtonMotionMask); //PointerMotionMask); 1349 XSelectInput(m_pDisplay, w , PointerMotionMask); //PointerMotionMask);1405 XSelectInput(m_pDisplay, wndThis, PointerMotionMask); //PointerMotionMask); 1350 1406 Window hRealRoot, hParent; 1351 1407 Window *phChildrenRaw = NULL; 1352 1408 unsigned cChildren; 1353 if (XQueryTree(m_pDisplay, w , &hRealRoot, &hParent, &phChildrenRaw, &cChildren))1409 if (XQueryTree(m_pDisplay, wndThis, &hRealRoot, &hParent, &phChildrenRaw, &cChildren)) 1354 1410 { 1355 1411 for (unsigned i = 0; i < cChildren; ++i) … … 1359 1415 } 1360 1416 1361 void DragInstance::setActionsWindowProperty(Window w in, const RTCList<Atom> &actionList) const1417 void DragInstance::setActionsWindowProperty(Window wndThis, const RTCList<Atom> &actionList) const 1362 1418 { 1363 1419 if (actionList.isEmpty()) 1364 1420 return; 1365 1421 1366 XChangeProperty(m_pDisplay, w in, xAtom(XA_XdndActionList), XA_ATOM, 32, PropModeReplace,1422 XChangeProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList), XA_ATOM, 32, PropModeReplace, 1367 1423 reinterpret_cast<const unsigned char*>(actionList.raw()), actionList.size()); 1368 1424 } 1369 1425 1370 void DragInstance::clearActionsWindowProperty(Window w in) const1371 { 1372 XDeleteProperty(m_pDisplay, w in, xAtom(XA_XdndActionList));1373 } 1374 1375 void DragInstance::setFormatsWindowProperty(Window w in, Atom property) const1426 void DragInstance::clearActionsWindowProperty(Window wndThis) const 1427 { 1428 XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndActionList)); 1429 } 1430 1431 void DragInstance::setFormatsWindowProperty(Window wndThis, Atom property) const 1376 1432 { 1377 1433 if (m_formats.isEmpty()) … … 1384 1440 1385 1441 /* Add the property with the property data to the window. */ 1386 XChangeProperty(m_pDisplay, w in, property, XA_ATOM, 32, PropModeReplace,1442 XChangeProperty(m_pDisplay, wndThis, property, XA_ATOM, 32, PropModeReplace, 1387 1443 reinterpret_cast<const unsigned char*>(targets.raw()), targets.size()); 1388 1444 } 1389 1445 1390 void DragInstance::clearFormatsWindowProperty(Window w in) const1391 { 1392 XDeleteProperty(m_pDisplay, w in, xAtom(XA_XdndTypeList));1446 void DragInstance::clearFormatsWindowProperty(Window wndThis) const 1447 { 1448 XDeleteProperty(m_pDisplay, wndThis, xAtom(XA_XdndTypeList)); 1393 1449 } 1394 1450 … … 1417 1473 * even if the data isn't zero terminated. */ 1418 1474 char *pszTmp = RTStrDupN(pszStr, cSize); 1419 DO(("f: %s\n", pszTmp));1475 LogFlowThisFunc(("f: %s\n", pszTmp)); 1420 1476 atomList.append(XInternAtom(m_pDisplay, pszTmp, False)); 1421 1477 RTStrFree(pszTmp); … … 1512 1568 if (!m_eventQueue.isEmpty()) 1513 1569 { 1514 DO(("new msg size %d\n", m_eventQueue.size()));1570 LogFlowThisFunc(("new msg size %d\n", m_eventQueue.size())); 1515 1571 /* Check if there is a client message in the queue. */ 1516 1572 for (size_t i = 0; i < m_eventQueue.size(); ++i) … … 1518 1574 DnDEvent e = m_eventQueue.at(i); 1519 1575 if( e.type == DnDEvent::X11_Type) 1520 DO(("new msg\n"));1576 LogFlowThisFunc(("new msg\n")); 1521 1577 if( e.type == DnDEvent::X11_Type 1522 1578 && e.x11.type == type) … … 1551 1607 do 1552 1608 { 1553 /* Initialize our service */1554 rc = VbglR3DnDInit();1555 if (RT_FAILURE(rc))1556 break;1557 1558 1609 /* Initialize X11 DND */ 1559 1610 rc = x11DragAndDropInit(); … … 1562 1613 1563 1614 m_pCurDnD = new DragInstance(m_pDisplay, this); 1615 if (!m_pCurDnD) 1616 { 1617 rc = VERR_NO_MEMORY; 1618 break; 1619 } 1564 1620 /* Note: For multiple screen support in VBox it is not necessary to use 1565 1621 * another screen number than zero. Maybe in the future it will become 1566 1622 * necessary if VBox supports multiple X11 screens. */ 1567 m_pCurDnD->init(0); 1623 rc = m_pCurDnD->init(0); 1624 if (RT_FAILURE(rc)) 1625 break; 1626 1568 1627 /* Loop over new events */ 1569 1628 do … … 1577 1636 e = m_eventQueue.first(); 1578 1637 m_eventQueue.removeFirst(); 1579 DO(("new msg %d\n", e.type));1638 LogFlowThisFunc(("new msg %d\n", e.type)); 1580 1639 if (e.type == DnDEvent::HGCM_Type) 1581 1640 { … … 1624 1683 } 1625 1684 #endif 1685 default: 1686 LogFlowThisFunc(("Unknown message: %RU32\n", e.hgcm.uType)); 1687 break; 1626 1688 } 1689 1627 1690 /* Some messages require cleanup. */ 1628 1691 switch (e.hgcm.uType) … … 1647 1710 break; 1648 1711 } 1712 default: 1713 break; 1649 1714 } 1650 1651 1715 } 1652 1716 else if(e.type == DnDEvent::X11_Type) 1653 1717 { 1654 DO(("X11 type: %u\n", e.x11.type));1718 LogFlowThisFunc(("X11 type: %u\n", e.x11.type)); 1655 1719 /* Now the X11 event stuff */ 1656 1720 switch (e.x11.type) … … 1658 1722 case SelectionRequest: m_pCurDnD->hgX11SelectionRequest(e.x11); break; 1659 1723 case ClientMessage: m_pCurDnD->hgX11ClientMessage(e.x11); break; 1660 case SelectionClear: DO(("DnD_CLER\n")); break;1724 case SelectionClear: LogFlowThisFunc(("DnD_CLER\n")); break; 1661 1725 // case MotionNotify: m_pCurDnD->hide(); break; 1662 1726 } … … 1666 1730 } while (0); 1667 1731 1668 Log RelFlowFunc(("returning %Rrc\n", rc));1732 LogFlowFuncLeaveRC(rc); 1669 1733 return rc; 1670 1734 } 1671 1735 1672 int DragAndDropService::x11DragAndDropInit( )1736 int DragAndDropService::x11DragAndDropInit(void) 1673 1737 { 1674 1738 /* Connect to the x11 server. */ … … 1678 1742 return VERR_NOT_FOUND; 1679 1743 1680 xHelpers::instance(m_pDisplay); 1744 xHelpers *pHelpers = xHelpers::getInstance(m_pDisplay); 1745 if (!pHelpers) 1746 return VERR_NO_MEMORY; 1681 1747 1682 1748 int rc = VINF_SUCCESS; … … 1706 1772 } 1707 1773 1708 int DragAndDropService::x11DragAndDropTerm( )1774 int DragAndDropService::x11DragAndDropTerm(void) 1709 1775 { 1710 1776 /* Mark that we are stopping. */ … … 1724 1790 int xrc = XSendEvent(m_pDisplay, None, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1725 1791 if (RT_UNLIKELY(xrc == 0)) 1726 DO(("DnD_TERM: error sending xevent\n"));1792 LogFlowThisFunc(("Error sending xevent\n")); 1727 1793 } 1728 1794 … … 1755 1821 DragAndDropService *pThis = static_cast<DragAndDropService*>(pvUser); 1756 1822 DnDEvent e; 1823 1824 uint32_t uClientID; 1825 int rc = VbglR3DnDConnect(&uClientID); 1826 if (RT_FAILURE(rc)) { 1827 LogFlowFunc(("Unable to connect to HGCM service, rc=%Rrc\n", rc)); 1828 return rc; 1829 } 1830 1757 1831 do 1758 1832 { … … 1760 1834 e.type = DnDEvent::HGCM_Type; 1761 1835 /* Wait for new events */ 1762 int rc = VbglR3DnDProcessNextMessage(&e.hgcm);1836 rc = VbglR3DnDProcessNextMessage(uClientID, &e.hgcm); 1763 1837 if (RT_SUCCESS(rc)) 1764 1838 { … … 1769 1843 } 1770 1844 } while (!ASMAtomicReadBool(&pThis->m_fSrvStopping)); 1845 1846 VbglR3DnDDisconnect(uClientID); 1771 1847 1772 1848 return VINF_SUCCESS; … … 1815 1891 1816 1892 /* Static factory */ 1817 VBoxClient::Service *VBoxClient::GetDragAndDropService() 1818 { 1819 return new(DragAndDropService); 1820 } 1893 VBoxClient::Service *VBoxClient::GetDragAndDropService(void) 1894 { 1895 DragAndDropService *pService = new DragAndDropService(); 1896 return pService; 1897 } 1898 -
trunk/src/VBox/Frontends
- Property svn:mergeinfo changed
/branches/andy/draganddrop/src/VBox/Frontends (added) merged: 90781-91268
- Property svn:mergeinfo changed
-
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
r45358 r49891 7 7 8 8 /* 9 * Copyright (C) 2011-201 2Oracle Corporation9 * Copyright (C) 2011-2013 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 #include <QTimer> 26 26 27 #ifdef LOG_GROUP 28 # undef LOG_GROUP 29 #endif 30 #define LOG_GROUP LOG_GROUP_GUEST_DND 31 #include <VBox/log.h> 32 27 33 /* GUI includes: */ 28 34 #include "UIDnDHandler.h" … … 46 52 Qt::DropAction UIDnDHandler::dragHGEnter(CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget * /* pParent = 0 */) 47 53 { 54 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", 55 screenId, x, y, toVBoxDnDAction(proposedAction))); 56 48 57 /* Ask the guest for starting a DnD event. */ 49 58 KDragAndDropAction result = guest.DragHGEnter(screenId, … … 59 68 Qt::DropAction UIDnDHandler::dragHGMove(CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget * /* pParent = 0 */) 60 69 { 61 /* Ask the guest for starting a DnD event. */ 70 #ifdef DEBUG_andy 71 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", 72 screenId, x, y, toVBoxDnDAction(proposedAction))); 73 #endif 74 75 /* Notify the guest that the mouse has been moved while doing 76 * a drag'n drop operation. */ 62 77 KDragAndDropAction result = guest.DragHGMove(screenId, 63 78 x, … … 72 87 Qt::DropAction UIDnDHandler::dragHGDrop(CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent /* = 0 */) 73 88 { 89 LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n", 90 screenId, x, y, toVBoxDnDAction(proposedAction))); 91 74 92 /* The format the guest requests. */ 75 93 QString format; … … 116 134 void UIDnDHandler::dragHGLeave(CGuest &guest, ulong screenId, QWidget * /* pParent = 0 */) 117 135 { 136 LogFlowFunc(("screenId=%RU32\n", screenId)); 118 137 guest.DragHGLeave(screenId); 119 138 } … … 144 163 , m_fState(Dragging) 145 164 { 146 /* This is unbelievable hacky, but I didn't found another way. Stupid 165 /* 166 * This is unbelievable hacky, but I didn't find another way. Stupid 147 167 * Qt QDrag interface is so less verbose, that we in principle know 148 168 * nothing about what happens when the user drag something around. It … … 158 178 * one installed by the QDrag object. 159 179 * 160 * Todo: test this on all supported platforms (X11 works) */ 180 ** @todo: Test this on all supported platforms (X11 works). 181 */ 161 182 QTimer::singleShot(0, this, SLOT(sltInstallEventFilter())); 162 183 } … … 258 279 void UIDnDHandler::dragGHPending(CSession &session, ulong screenId, QWidget *pParent /* = 0 */) 259 280 { 260 /* How does this work: Host is asking the guest if there is any DnD 281 /* 282 * How this works: Host is asking the guest if there is any DnD 261 283 * operation pending, when the mouse leaves the guest window 262 284 * (DragGHPending). On return there is some info about a running DnD … … 264 286 * this information we create a Qt QDrag object with our own QMimeType 265 287 * implementation and call exec. Please note, this *blocks* until the DnD 266 * operation has finished. */ 288 * operation has finished. 289 */ 267 290 CGuest guest = session.GetConsole().GetGuest(); 268 291 QVector<QString> formats; -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r44102 r49891 5 5 6 6 /* 7 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 20 ******************************************************************************/ 21 21 22 #define LOG_GROUP LOG_GROUP_HGCM 22 #ifdef LOG_GROUP 23 #undef LOG_GROUP 24 #endif 25 #define LOG_GROUP LOG_GROUP_GUEST_DND 23 26 24 27 #include "dndmanager.h" … … 29 32 #include <iprt/path.h> 30 33 #include <iprt/uri.h> 31 32 #define VERBOSE 133 34 #if defined(VERBOSE) && defined(DEBUG_poetzsch)35 # include <iprt/stream.h>36 # define DO(s) RTPrintf s37 #else38 # define DO(s) do {} while(0)39 //# define DO(s) Log s40 #endif41 34 42 35 /****************************************************************************** … … 65 58 paTmpParms[1].setUInt32(m_strPath.length() + 1); 66 59 paTmpParms[2].setUInt32(fMode); 60 67 61 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms); 68 62 } … … 97 91 public: 98 92 DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 99 ~DnDHGSendFilePrivate();93 virtual ~DnDHGSendFilePrivate(); 100 94 101 95 int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 104 98 RTCString m_strHostPath; 105 99 RTCString m_strGuestPath; 106 uint64_t m_cb Size;107 uint64_t m_cb Done;100 uint64_t m_cbFileSize; 101 uint64_t m_cbFileProcessed; 108 102 RTFILE m_hCurFile; 109 103 VBOXHGCMSVCPARM m_paSkelParms[5]; … … 146 140 : m_strHostPath(strHostPath) 147 141 , m_strGuestPath(strGuestPath) 148 , m_cb Size(cbSize)149 , m_cb Done(0)142 , m_cbFileSize(cbSize) 143 , m_cbFileProcessed(0) 150 144 , m_hCurFile(0) 151 145 , m_pfnProgressCallback(pfnProgressCallback) … … 157 151 m_paSkelParms[3].setUInt32(0); 158 152 m_paSkelParms[4].setUInt32(fMode); 153 159 154 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms); 160 155 } … … 178 173 if (!m_hCurFile) 179 174 { 180 rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_ALL); 181 if (RT_FAILURE(rc)) 182 return rc; 183 } 184 185 /* How big is the pointer provided by the guest? */ 186 uint32_t cbToRead = paParms[2].u.pointer.size; 175 /* Open files on the host with RTFILE_O_DENY_WRITE to prevent races where the host 176 * writes to the file while the guest transfers it over. */ 177 rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), 178 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 179 } 180 187 181 size_t cbRead; 188 rc = RTFileRead(m_hCurFile, paParms[2].u.pointer.addr, cbToRead, &cbRead); 189 if (RT_FAILURE(rc)) 190 { 191 /* On error, immediately close the file. */ 192 RTFileClose(m_hCurFile); 193 m_hCurFile = 0; 194 return rc; 195 } 196 m_cbDone += cbRead; 197 /* Tell the guest the actual size. */ 198 paParms[3].setUInt32(cbRead); 199 /* Check if we are done. */ 200 if (m_cbSize == m_cbDone) 201 { 202 RTFileClose(m_hCurFile); 203 m_hCurFile = 0; 204 } 205 else 206 { 207 /* More data! Prepare the next message. */ 208 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms); 209 } 210 211 /* Advance progress info */ 212 if ( RT_SUCCESS(rc) 213 && m_pfnProgressCallback) 214 rc = m_pfnProgressCallback(cbRead, m_pvProgressUser); 182 if (RT_SUCCESS(rc)) 183 { 184 /* Get buffer size + pointer to buffer from guest side. */ 185 uint32_t cbToRead = paParms[2].u.pointer.size; 186 Assert(cbToRead); 187 void *pvBuf = paParms[2].u.pointer.addr; 188 AssertPtr(pvBuf); 189 rc = RTFileRead(m_hCurFile, pvBuf, cbToRead, &cbRead); 190 if (RT_LIKELY(RT_SUCCESS(rc))) 191 { 192 /* Advance. */ 193 m_cbFileProcessed += cbRead; 194 Assert(m_cbFileProcessed <= m_cbFileSize); 195 196 /* Tell the guest the actual size. */ 197 paParms[3].setUInt32(cbRead); 198 } 199 } 200 201 if (RT_SUCCESS(rc)) 202 { 203 /* Check if we are done. */ 204 bool fDone = m_cbFileSize == m_cbFileProcessed; 205 if (!fDone) 206 { 207 try 208 { 209 /* More data! Prepare the next message. */ 210 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */, 211 m_paSkelParms); 212 } 213 catch(std::bad_alloc &) 214 { 215 rc = VERR_NO_MEMORY; 216 } 217 } 218 219 /* Advance progress info. */ 220 if ( RT_SUCCESS(rc) 221 && m_pfnProgressCallback) 222 rc = m_pfnProgressCallback(cbRead, m_pvProgressUser); 223 224 if ( fDone 225 || RT_FAILURE(rc)) 226 { 227 RTFileClose(m_hCurFile); 228 m_hCurFile = 0; 229 } 230 } 215 231 216 232 return rc; … … 241 257 242 258 HGCM::Message *pCurMsg = m_pNextMsg; 259 AssertPtr(pCurMsg); 260 243 261 m_pNextMsg = 0; 244 262 rc = pCurMsg->getData(uMsg, cParms, paParms); … … 258 276 paTmpParms[0].setPointer(static_cast<uint8_t*>(pvOldData) + paParms[iPos].u.pointer.size, cOldData - paParms[iPos].u.pointer.size); 259 277 paTmpParms[1].setUInt32(cOldData - paParms[iPos].u.pointer.size); 260 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA, 2, paTmpParms); 261 } 278 279 try 280 { 281 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA, 2, paTmpParms); 282 } 283 catch(std::bad_alloc &) 284 { 285 rc = VERR_NO_MEMORY; 286 } 287 } 288 262 289 delete pCurMsg; 263 290 … … 280 307 */ 281 308 DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser) 282 : m_cbAll(0)283 , m_cbTransfered(0)284 , m_pfnProgressCallback(pfnProgressCallback)285 , m_pvProgressUser(pvProgressUser)309 : m_cbAll(0) 310 , m_cbTransfered(0) 311 , m_pfnProgressCallback(pfnProgressCallback) 312 , m_pvProgressUser(pvProgressUser) 286 313 { 287 314 RTCString strNewUris; … … 289 316 if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), paParms[1].u.pointer.size)) 290 317 { 291 DO(("old data'%s'\n", (char*)paParms[3].u.pointer.addr));318 LogFlowFunc(("Old data: '%s'\n", (char*)paParms[3].u.pointer.addr)); 292 319 /* The list is separated by newline (Even if only one file is 293 320 * listed). */ 294 RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr), paParms[3].u.pointer.size).split("\r\n"); 321 RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr), 322 paParms[3].u.pointer.size).split("\r\n"); 295 323 if (!oldUriList.isEmpty()) 296 324 { … … 337 365 m_cbAll += paParms[4].u.uint32; 338 366 /* The first message is the meta info for the data and the data itself. */ 339 m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, &DnDHGSendDataMessage::progressCallback, this); 340 341 DO(("new data '%s'\n", (char*)paParms[3].u.pointer.addr)); 342 DO(("cbAll: %u\n", m_cbAll)); 343 DO(("cbData: %u\n", paParms[4].u.uint32)); 367 m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, 368 &DnDHGSendDataMessage::progressCallback, this); 369 370 LogFlowFunc(("new data '%s'\n", (char*)paParms[3].u.pointer.addr)); 371 LogFlowFunc(("cbAll: %zu\n", m_cbAll)); 372 LogFlowFunc(("cbData: %RU32\n", paParms[4].u.uint32)); 344 373 345 374 for (size_t i = 0; i < m_uriList.size(); ++i) 346 DO(("file: %s : %s - %o - %ld\n", m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(), m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize)); 375 LogFlowFunc(("file: %s : %s - %o - %ld\n", 376 m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(), 377 m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize)); 347 378 } 348 379 … … 391 422 * this could be directories or regular files. */ 392 423 PathEntry nextPath = m_uriList.first(); 393 if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) 394 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); 395 else if (RTFS_IS_FILE(nextPath.m_fMode)) 396 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); 397 else 398 AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); 399 m_uriList.removeFirst(); 400 } 424 try 425 { 426 if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) 427 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath, 428 nextPath.m_fMode, nextPath.m_cbSize, 429 &DnDHGSendDataMessage::progressCallback, this); 430 else if (RTFS_IS_FILE(nextPath.m_fMode)) 431 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath, 432 nextPath.m_fMode, nextPath.m_cbSize, 433 &DnDHGSendDataMessage::progressCallback, this); 434 else 435 AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", 436 nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); 437 438 m_uriList.removeFirst(); 439 } 440 catch(std::bad_alloc &) 441 { 442 rc = VERR_NO_MEMORY; 443 } 444 } 445 401 446 return rc; 402 447 } … … 404 449 bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const 405 450 { 406 DO(("format %s\n", pcszFormat));407 /* text/uri also an official variant? */451 LogFlowFunc(("format %s\n", pcszFormat)); 452 /** @todo text/uri also an official variant? */ 408 453 return RTStrNICmp(pcszFormat, "text/uri-list", cbMax) == 0 409 454 || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0; … … 435 480 m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize)); 436 481 m_cbAll += cbSize; 437 DO(("cbFile: %u\n", cbSize));482 LogFlowFunc(("cbFile: %RU64\n", cbSize)); 438 483 439 484 PRTDIR hDir; … … 518 563 && pSelf->m_cbAll) 519 564 rc = pSelf->m_pfnProgressCallback((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbAll, 520 DragAndDropSvc::DND_PROGRESS_RUNNING, pSelf->m_pvProgressUser);565 DragAndDropSvc::DND_PROGRESS_RUNNING, VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser); 521 566 522 567 return rc; … … 530 575 { 531 576 int rc = VINF_SUCCESS; 532 switch (uMsg) 533 { 534 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER: 535 { 536 clear(); 537 LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n")); 538 DO(("HOST_DND_HG_EVT_ENTER\n")); 539 /* Verify parameter count and types. */ 540 if ( cParms != 7 541 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 542 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 543 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 544 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 545 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 546 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 547 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 548 rc = VERR_INVALID_PARAMETER; 549 else 550 { 551 m_fOpInProcess = true; 552 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 553 m_dndMessageQueue.append(pMessage); 554 } 555 break; 556 } 557 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE: 558 { 559 LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n")); 560 DO(("HOST_DND_HG_EVT_MOVE\n")); 561 /* Verify parameter count and types. */ 562 if ( cParms != 7 563 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 564 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 565 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 566 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 567 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 568 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 569 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 570 rc = VERR_INVALID_PARAMETER; 571 else 572 { 573 m_fOpInProcess = true; 574 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 575 m_dndMessageQueue.append(pMessage); 576 } 577 break; 578 } 579 case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE: 580 { 581 LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n")); 582 DO(("HOST_DND_HG_EVT_LEAVE\n")); 583 584 /* Verify parameter count and types. */ 585 if (cParms != 0) 586 rc = VERR_INVALID_PARAMETER; 587 else 588 { 589 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 590 m_dndMessageQueue.append(pMessage); 591 } 592 m_fOpInProcess = false; 593 break; 594 } 595 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED: 596 { 597 LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n")); 598 DO(("HOST_DND_HG_EVT_DROPPED\n")); 599 /* Verify parameter count and types. */ 600 if ( cParms != 7 601 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 602 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 603 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 604 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 605 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 606 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 607 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 608 rc = VERR_INVALID_PARAMETER; 609 else 610 { 611 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 612 m_dndMessageQueue.append(pMessage); 613 } 614 break; 615 } 616 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 617 { 618 LogFlowFunc(("HOST_DND_HG_SND_DATA\n")); 619 DO(("HOST_DND_HG_SND_DATA\n")); 620 621 /* Verify parameter count and types. */ 622 if ( cParms != 5 623 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 624 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* format */ 625 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */ 626 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 627 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */) 628 rc = VERR_INVALID_PARAMETER; 629 else 630 { 631 DnDHGSendDataMessage *pMessage = new DnDHGSendDataMessage(uMsg, cParms, paParms, m_pfnProgressCallback, m_pvProgressUser); 632 m_dndMessageQueue.append(pMessage); 633 } 634 break; 635 } 636 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 637 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING: 638 { 639 LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n")); 640 DO(("HOST_DND_GH_REQ_PENDING\n")); 641 642 /* Verify parameter count and types. */ 643 if ( cParms != 1 644 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */) 645 rc = VERR_INVALID_PARAMETER; 646 else 647 { 648 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 649 m_dndMessageQueue.append(pMessage); 650 } 651 break; 652 } 653 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED: 654 { 655 LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n")); 656 DO(("HOST_DND_GH_EVT_DROPPED\n")); 657 658 /* Verify parameter count and types. */ 659 if ( cParms != 3 660 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */ 661 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */ 662 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */) 663 rc = VERR_INVALID_PARAMETER; 664 else 665 { 666 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 667 m_dndMessageQueue.append(pMessage); 668 } 669 break; 670 } 671 #endif 672 default: rc = VERR_NOT_IMPLEMENTED; break; 577 578 try 579 { 580 switch (uMsg) 581 { 582 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER: 583 { 584 clear(); 585 LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n")); 586 587 /* Verify parameter count and types. */ 588 if ( cParms != 7 589 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 590 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 591 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 592 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 593 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 594 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 595 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 596 rc = VERR_INVALID_PARAMETER; 597 else 598 { 599 m_fOpInProcess = true; 600 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 601 m_dndMessageQueue.append(pMessage); 602 } 603 break; 604 } 605 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE: 606 { 607 LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n")); 608 609 /* Verify parameter count and types. */ 610 if ( cParms != 7 611 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 612 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 613 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 614 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 615 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 616 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 617 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 618 rc = VERR_INVALID_PARAMETER; 619 else 620 { 621 m_fOpInProcess = true; 622 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 623 m_dndMessageQueue.append(pMessage); 624 } 625 break; 626 } 627 case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE: 628 { 629 LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n")); 630 631 /* Verify parameter count and types. */ 632 if (cParms != 0) 633 rc = VERR_INVALID_PARAMETER; 634 else 635 { 636 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 637 m_dndMessageQueue.append(pMessage); 638 } 639 m_fOpInProcess = false; 640 break; 641 } 642 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED: 643 { 644 LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n")); 645 646 /* Verify parameter count and types. */ 647 if ( cParms != 7 648 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 649 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */ 650 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */ 651 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */ 652 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */ 653 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 654 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 655 rc = VERR_INVALID_PARAMETER; 656 else 657 { 658 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 659 m_dndMessageQueue.append(pMessage); 660 } 661 break; 662 } 663 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 664 { 665 LogFlowFunc(("HOST_DND_HG_SND_DATA\n")); 666 667 /* Verify parameter count and types. */ 668 if ( cParms != 5 669 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */ 670 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* format */ 671 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */ 672 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 673 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */) 674 rc = VERR_INVALID_PARAMETER; 675 else 676 { 677 DnDHGSendDataMessage *pMessage = new DnDHGSendDataMessage(uMsg, cParms, paParms, m_pfnProgressCallback, m_pvProgressUser); 678 m_dndMessageQueue.append(pMessage); 679 } 680 break; 681 } 682 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 683 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING: 684 { 685 LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n")); 686 687 /* Verify parameter count and types. */ 688 if ( cParms != 1 689 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */) 690 rc = VERR_INVALID_PARAMETER; 691 else 692 { 693 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 694 m_dndMessageQueue.append(pMessage); 695 } 696 break; 697 } 698 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED: 699 { 700 LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n")); 701 702 /* Verify parameter count and types. */ 703 if ( cParms != 3 704 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */ 705 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */ 706 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */) 707 rc = VERR_INVALID_PARAMETER; 708 else 709 { 710 try 711 { 712 DnDGenericMessage *pMessage 713 = new DnDGenericMessage(uMsg, cParms, paParms); 714 m_dndMessageQueue.append(pMessage); 715 } 716 catch(std::bad_alloc &) 717 { 718 rc = VERR_NO_MEMORY; 719 } 720 } 721 break; 722 } 723 #endif 724 default: 725 rc = VERR_NOT_IMPLEMENTED; 726 break; 727 } 728 } 729 catch(std::bad_alloc &) 730 { 731 rc = VERR_NO_MEMORY; 673 732 } 674 733 … … 710 769 } 711 770 712 DO(("next msg info: %d %d%Rrc\n", *puMsg, *pcParms, rc));771 LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puMsg, *pcParms, rc)); 713 772 return rc; 714 773 } … … 716 775 int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 717 776 { 777 LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms)); 778 718 779 if (!m_pCurMsg) 719 780 { 720 781 /* Check for pending messages in our queue. */ 721 782 if (m_dndMessageQueue.isEmpty()) 783 { 784 LogFlowFunc(("Message queue is empty, returning\n")); 722 785 return VERR_NO_DATA; 786 } 787 723 788 m_pCurMsg = m_dndMessageQueue.first(); 724 789 m_dndMessageQueue.removeFirst(); … … 727 792 /* Fetch the current message info */ 728 793 int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms); 729 /* If this message not provide any additional sub messages, clear it. */794 /* If this message doesn't provide any additional sub messages, clear it. */ 730 795 if (!m_pCurMsg->isMessageWaiting()) 796 { 797 delete m_pCurMsg; 798 m_pCurMsg = NULL; 799 } 800 801 /* 802 * If there was an error handling the current message or the user has canceled 803 * the operation, we need to cleanup all pending events and inform the progress 804 * callback about our exit. 805 */ 806 if ( RT_FAILURE(rc) 807 && m_pfnProgressCallback) 808 { 809 /* Clear any pending messages. */ 810 clear(); 811 812 /* Create a new cancel message to inform the guest + call 813 * the host whether the current transfer was canceled or aborted 814 * due to an error. */ 815 try 816 { 817 Assert(!m_pCurMsg); 818 m_pCurMsg = new DnDHGCancelMessage(); 819 m_pfnProgressCallback(100 /* Percent */, 820 rc == VERR_CANCELLED 821 ? DragAndDropSvc::DND_PROGRESS_CANCELLED 822 : DragAndDropSvc::DND_PROGRESS_ERROR, rc, m_pvProgressUser); 823 } 824 catch(std::bad_alloc &) 825 { 826 rc = VERR_NO_MEMORY; 827 } 828 } 829 830 LogFlowFunc(("Message processed with rc=%Rrc\n", rc)); 831 return rc; 832 } 833 834 void DnDManager::clear() 835 { 836 if (m_pCurMsg) 731 837 { 732 838 delete m_pCurMsg; 733 839 m_pCurMsg = 0; 734 840 } 735 736 /* If the user has canceled the operation, we need to cleanup all pending737 * events and inform the progress callback about our successful cleanup. */738 if ( rc == VERR_CANCELLED739 && m_pfnProgressCallback)740 {741 /* Clear any pending messages */742 clear();743 /* Create a new cancel message to inform the guest. */744 m_pCurMsg = new DnDHGCancelMessage();745 m_pfnProgressCallback(100, DragAndDropSvc::DND_PROGRESS_CANCELLED, m_pvProgressUser);746 }747 748 DO(("next msg: %d %d %Rrc\n", uMsg, cParms, rc));749 return rc;750 }751 752 void DnDManager::clear()753 {754 if (m_pCurMsg)755 {756 delete m_pCurMsg;757 m_pCurMsg = 0;758 }759 841 while (!m_dndMessageQueue.isEmpty()) 760 842 { -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h
r42342 r49891 24 24 #include <iprt/cpp/list.h> 25 25 26 typedef DECLCALLBACK(int) FNDNDPROGRESS(unsigned uPercentage, uint32_t uState, void *pvUser);26 typedef DECLCALLBACK(int) FNDNDPROGRESS(unsigned uPercentage, uint32_t uState, int rc, void *pvUser); 27 27 typedef FNDNDPROGRESS *PFNDNDPROGRESS; 28 28 … … 168 168 , m_pvProgressUser(pvProgressUser) 169 169 {} 170 ~DnDManager()170 virtual ~DnDManager() 171 171 { 172 172 clear(); -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r43996 r49891 5 5 6 6 /* 7 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 55 55 * Header Files * 56 56 ******************************************************************************/ 57 #define LOG_GROUP LOG_GROUP_HGCM 57 #ifdef LOG_GROUP 58 #undef LOG_GROUP 59 #endif 60 #define LOG_GROUP LOG_GROUP_GUEST_DND 58 61 59 62 #include "dndmanager.h" 60 61 //# define DO(s) RTPrintf s62 #define DO(s) do {} while(0)63 //#define DO(s) Log s64 63 65 64 /****************************************************************************** … … 88 87 int hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 89 88 90 static DECLCALLBACK(int) progressCallback(u nsigned uPercentage, uint32_t uState, void *pvUser);89 static DECLCALLBACK(int) progressCallback(uint32_t uPercentage, uint32_t uState, int rc, void *pvUser); 91 90 int hostMessage(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 92 91 void modeSet(uint32_t u32Mode); … … 128 127 { 129 128 LogFlowFunc(("New client (%ld) connected\n", u32ClientID)); 130 DO(("New client (%ld) connected\n", u32ClientID));131 129 if (m_cClients < UINT32_MAX) 132 130 m_cClients++; … … 173 171 void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 174 172 { 173 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32\n", 174 u32ClientID, u32Function, cParms)); 175 175 176 int rc = VINF_SUCCESS; 176 LogFlowFunc(("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",177 u32ClientID, u32Function, cParms, paParms));178 // RTPrintf("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",179 // u32ClientID, u32Function, cParms, paParms);180 181 177 switch (u32Function) 182 178 { 183 179 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG: 184 180 { 185 DO(("GUEST_DND_GET_NEXT_HOST_MSG\n"));181 LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n")); 186 182 if ( cParms != 3 187 183 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */ … … 203 199 case DragAndDropSvc::GUEST_DND_HG_ACK_OP: 204 200 { 205 DO(("GUEST_DND_HG_ACK_OP\n"));201 LogFlowFunc(("GUEST_DND_HG_ACK_OP\n")); 206 202 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 207 203 && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST) 208 204 { 209 DO(("=> ignoring!\n"));205 LogFlowFunc(("=> ignoring!\n")); 210 206 break; 211 207 } … … 227 223 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA: 228 224 { 229 DO(("GUEST_DND_HG_REQ_DATA\n"));225 LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n")); 230 226 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 231 227 && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST) 232 228 { 233 DO(("=> ignoring!\n"));229 LogFlowFunc(("=> ignoring!\n")); 234 230 break; 235 231 } … … 257 253 case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING: 258 254 { 259 DO(("GUEST_DND_GH_ACK_PENDING\n"));255 LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n")); 260 256 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 261 257 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 262 258 { 263 DO(("=> ignoring!\n"));259 LogFlowFunc(("=> ignoring!\n")); 264 260 break; 265 261 } … … 285 281 case DragAndDropSvc::GUEST_DND_GH_SND_DATA: 286 282 { 287 DO(("GUEST_DND_GH_SND_DATA\n"));283 LogFlowFunc(("GUEST_DND_GH_SND_DATA\n")); 288 284 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 289 285 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 290 286 { 291 DO(("=> ignoring\n"));287 LogFlowFunc(("=> ignoring\n")); 292 288 break; 293 289 } … … 310 306 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR: 311 307 { 312 DO(("GUEST_DND_GH_EVT_ERROR\n"));308 LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n")); 313 309 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 314 310 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 315 311 { 316 DO(("=> ignoring!\n"));312 LogFlowFunc(("=> ignoring!\n")); 317 313 break; 318 314 } … … 338 334 /* All other messages are handled by the DnD manager. */ 339 335 rc = m_pManager->nextMessage(u32Function, cParms, paParms); 340 /* Check for error. Buffer overflow is allowed. It signals the341 * guest to ask for more data in the next event. */342 if ( RT_FAILURE(rc)343 && rc != VERR_CANCELLED344 && rc != VERR_BUFFER_OVERFLOW) /* Buffer overflow is allowed. */345 {346 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms));347 rc = VINF_HGCM_ASYNC_EXECUTE;348 }349 336 break; 350 337 } … … 355 342 if (rc != VINF_HGCM_ASYNC_EXECUTE) 356 343 m_pHelpers->pfnCallComplete(callHandle, rc); 357 DO(("guest call:%Rrc\n", rc));344 LogFlowFunc(("Returning rc=%Rrc\n", rc)); 358 345 } 359 346 … … 415 402 int DragAndDropService::hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 416 403 { 404 LogFlowFunc(("u32Function=%RU32, cParms=%RU32\n", u32Function, cParms)); 405 417 406 int rc = VINF_SUCCESS; 418 407 if (u32Function == DragAndDropSvc::HOST_DND_SET_MODE) … … 428 417 { 429 418 rc = m_pManager->addMessage(u32Function, cParms, paParms); 430 if ( 419 if ( RT_SUCCESS(rc) 431 420 && !m_clientQueue.isEmpty()) 432 421 { 433 422 HGCM::Client *pClient = m_clientQueue.first(); 423 AssertPtr(pClient); 434 424 /* Check if this was a request for getting the next host 435 425 * message. If so, return the message id and the parameter … … 437 427 if (pClient->message() == DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG) 438 428 { 439 DO(("client is waiting for next host msg\n"));440 // rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32); 429 LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId())); 430 441 431 uint32_t uMsg1; 442 432 uint32_t cParms1; … … 463 453 } 464 454 465 DECLCALLBACK(int) DragAndDropService::progressCallback(u nsigned uPercentage, uint32_t uState, void *pvUser)455 DECLCALLBACK(int) DragAndDropService::progressCallback(uint32_t uPercentage, uint32_t uState, int rc, void *pvUser) 466 456 { 467 457 AssertPtrReturn(pvUser, VERR_INVALID_POINTER); … … 471 461 if (pSelf->m_pfnHostCallback) 472 462 { 473 DO(("GUEST_DND_HG_EVT_PROGRESS %u\n", uPercentage)); 463 LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS: uPercentage=%RU32, uState=%RU32, rc=%Rrc\n", 464 uPercentage, uState, rc)); 474 465 DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data; 475 466 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS; 476 467 data.uPercentage = uPercentage; 477 468 data.uState = uState; 469 data.rc = rc; 478 470 479 471 return pSelf->m_pfnHostCallback(pSelf->m_pvHostData, DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS, &data, sizeof(data)); -
trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
r45367 r49891 5 5 6 6 /* 7 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 29 29 # include <VBox/HostServices/DragAndDropSvc.h> 30 30 31 # ifdef LOG_GROUP 32 # undef LOG_GROUP 33 # endif 34 # define LOG_GROUP LOG_GROUP_GUEST_DND 35 # include <VBox/log.h> 36 31 37 # include <iprt/stream.h> 32 38 # include <iprt/semaphore.h> … … 48 54 * of it to the Main IGuest interface (see UIDnDHandler.cpp). 49 55 * 2. Main: Public interface for doing Drag and Drop. Also manage the IProgress 50 * interfaces for blocking the caller by showing a progress dialog .(see51 * this file) 56 * interfaces for blocking the caller by showing a progress dialog (see 57 * this file). 52 58 * 3. HGCM service: Handle all messages from the host to the guest at once and 53 * encapsulate the internal communication details .(see dndmanager.cpp and54 * friends) 59 * encapsulate the internal communication details (see dndmanager.cpp and 60 * friends). 55 61 * 4. Guest additions: Split into the platform neutral part (see 56 62 * VBoxGuestR3LibDragAndDrop.cpp) and the guest OS specific parts. 57 63 * Receive/send message from/to the HGCM service and does all guest specific 58 * operations. Currently only X11 is supported .(see draganddrop.cpp within59 * VBoxClient) 60 * 61 * Host 64 * operations. Currently only X11 is supported (see draganddrop.cpp within 65 * VBoxClient). 66 * 67 * Host -> Guest: 62 68 * 1. There are DnD Enter, Move, Leave events which are send exactly like this 63 69 * to the guest. The info includes the pos, mimetypes and allowed actions. … … 86 92 * Dropping of a directory, means recursively transferring _all_ the content. 87 93 * 88 * Directories and files are placed into a public visible userdirectory on the89 * guest ( ~/Documents/VirtualBox Dropped Files). We can't delete them after the94 * Directories and files are placed into the user's temporary directory on the 95 * guest (e.g. /tmp/VirtualBox Dropped Files). We can't delete them after the 90 96 * DnD operation, because we didn't know what the DnD target does with it. E.g. 91 97 * it could just be opened in place. This could lead ofc to filling up the disk … … 111 117 * Cancel is supported in both directions and cleans up all previous steps 112 118 * (thats is: deleting already transfered dirs/files). 113 *114 * There are a lot of DO (debug output) calls in the code. This could be115 * disabled, but should be removed (or replaced by Log calls) when this is116 * nearly finished.117 *118 * For Windows guests there could be different communication become necessary.119 * So the current interface isn't set in stone and should be made public only,120 * after someone had deeply looked into the Win guest support. See121 * http://www.catch22.net/tuts/dragdrop for a start.122 *123 * How to test:124 * First set VBOX_WITH_DRAG_AND_DROP=1 in LocalConfig.kmk. The best is if the125 * host match the guest OS arch. Just build the tree and point a shared folder126 * within the guest to the additions subfolder in bin. Start the guest and127 * execute ./VBoxClient --dragandrop --nodaemon within this shared folder. You128 * should now be able of dragging text or files to the guest. I used a 64bit129 * Linux for both the host and the guest. If the archs don't match, you need to130 * first setup a build environment in the guest ofc.131 119 * 132 120 * In general I propose the following changes in the VBox HGCM infrastructure … … 152 140 * Todo: 153 141 * - Dragging out of the guest (partly done) 154 * - ESC doesn't really work 142 * - ESC doesn't really work (on Windows guests it's already implemented) 155 143 * - transfer of URIs (that is the files and patching of the data) 156 144 * - testing in a multi monitor setup … … 230 218 231 219 void adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const; 232 void hostCall( const char* psczFunction,uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;220 void hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const; 233 221 234 222 /* Static helper */ … … 254 242 /* What mime-types are supported by VirtualBox. 255 243 * Note: If you add something here, make sure you test it with all guest OS's! 244 ** @todo Make this MIME list configurable / extendable (by extra data?). Currently 245 * this is done hardcoded on every guest platform (POSIX/Windows). 256 246 */ 257 247 /* static */ … … 296 286 int DnDGuestResponse::waitForGuestResponse() 297 287 { 298 return RTSemEventWait(m_EventSem, 300); 288 int vrc = RTSemEventWait(m_EventSem, 300); 289 #ifdef DEBUG_andy 290 LogFlowFunc(("rc=%Rrc\n", vrc)); 291 #endif 292 return vrc; 299 293 } 300 294 … … 340 334 int DnDGuestResponse::setProgress(unsigned uPercentage, uint32_t uState, int rcOp /* = VINF_SUCCESS */) 341 335 { 336 LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", uPercentage, uState, rcOp)); 337 342 338 int vrc = VINF_SUCCESS; 343 HRESULT rc;344 339 if (!m_progress.isNull()) 345 340 { 346 341 BOOL fCompleted; 347 rc = m_progress->COMGETTER(Completed)(&fCompleted);342 HRESULT rc = m_progress->COMGETTER(Completed)(&fCompleted); 348 343 if (!fCompleted) 349 344 { 350 345 if (uState == DragAndDropSvc::DND_PROGRESS_ERROR) 346 { 351 347 rc = m_progress->notifyComplete(E_FAIL, 352 348 COM_IIDOF(IGuest), 353 349 m_parent->getComponentName(), 354 350 m_parent->tr("Guest error (%Rrc)"), rcOp); 351 } 355 352 else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED) 356 rc = m_progress->notifyComplete(S_OK); 357 else 353 { 354 rc = m_progress->Cancel(); 355 vrc = VERR_CANCELLED; 356 } 357 else /* uState == DragAndDropSvc::DND_PROGRESS_RUNNING */ 358 358 { 359 359 rc = m_progress->SetCurrentOperationProgress(uPercentage); 360 #ifndef DEBUG_andy 361 Assert(SUCCEEDED(rc)); 362 #endif 360 363 if ( uState == DragAndDropSvc::DND_PROGRESS_COMPLETE 361 364 || uPercentage >= 100) 362 365 rc = m_progress->notifyComplete(S_OK); 363 366 } 367 #ifndef DEBUG_andy 368 Assert(SUCCEEDED(rc)); 369 #endif 364 370 } 365 BOOL fCanceled = FALSE; 366 rc = m_progress->COMGETTER(Canceled)(&fCanceled); 367 if (fCanceled) 368 vrc = VERR_CANCELLED; 369 } 371 } 372 370 373 return vrc; 371 374 } … … 391 394 } 392 395 393 void GuestDnDPrivate::hostCall( const char* psczFunction,uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const394 { 395 VMMDev *vmmDev = 0;396 void GuestDnDPrivate::hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const 397 { 398 VMMDev *vmmDev = NULL; 396 399 { 397 400 /* Make sure mParent is valid, so set the read lock while using. … … 409 412 p->tr("VMM device is not available (is the VM running?)")); 410 413 411 LogFlowFunc(("hgcmHostCall msg=% s; numParms=%u\n", psczFunction, u32Function));414 LogFlowFunc(("hgcmHostCall msg=%RU32, numParms=%RU32\n", u32Function, cParms)); 412 415 int vrc = vmmDev->hgcmHostCall("VBoxDragAndDropSvc", 413 416 u32Function, … … 576 579 paParms[i++].setUInt32(strFormats.length() + 1); 577 580 578 d->hostCall("HOST_DND_HG_EVT_ENTER", 579 DragAndDropSvc::HOST_DND_HG_EVT_ENTER, 581 d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_ENTER, 580 582 i, 581 583 paParms); … … 588 590 /* Copy the response info */ 589 591 *pResultAction = d->toMainAction(pDnD->defAction()); 592 LogFlowFunc(("*pResultAction=%ld\n", *pResultAction)); 590 593 } 591 594 catch (HRESULT rc2) … … 636 639 paParms[i++].setUInt32(strFormats.length() + 1); 637 640 638 d->hostCall("HOST_DND_HG_EVT_MOVE", 639 DragAndDropSvc::HOST_DND_HG_EVT_MOVE, 641 d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_MOVE, 640 642 i, 641 643 paParms); … … 648 650 /* Copy the response info */ 649 651 *pResultAction = d->toMainAction(pDnD->defAction()); 652 LogFlowFunc(("*pResultAction=%ld\n", *pResultAction)); 650 653 } 651 654 catch (HRESULT rc2) … … 666 669 try 667 670 { 668 d->hostCall("HOST_DND_HG_EVT_LEAVE", 669 DragAndDropSvc::HOST_DND_HG_EVT_LEAVE, 671 d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_LEAVE, 670 672 0, 671 673 NULL); … … 722 724 paParms[i++].setUInt32(strFormats.length() + 1); 723 725 724 d->hostCall("HOST_DND_HG_EVT_DROPPED", 725 DragAndDropSvc::HOST_DND_HG_EVT_DROPPED, 726 d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED, 726 727 i, 727 728 paParms); … … 735 736 *pResultAction = d->toMainAction(pDnD->defAction()); 736 737 Bstr(pDnD->format()).cloneTo(pstrFormat); 738 739 LogFlowFunc(("*pResultAction=%ld\n", *pResultAction)); 737 740 } 738 741 catch (HRESULT rc2) … … 768 771 pDnD->resetProgress(p); 769 772 770 d->hostCall("HOST_DND_HG_SND_DATA", 771 DragAndDropSvc::HOST_DND_HG_SND_DATA, 773 d->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA, 772 774 i, 773 775 paParms); … … 801 803 paParms[i++].setUInt32(uScreenId); 802 804 803 d->hostCall("HOST_DND_GH_REQ_PENDING", 804 DragAndDropSvc::HOST_DND_GH_REQ_PENDING, 805 d->hostCall(DragAndDropSvc::HOST_DND_GH_REQ_PENDING, 805 806 i, 806 807 paParms); … … 855 856 pDnD->resetProgress(p); 856 857 857 d->hostCall("HOST_DND_GH_EVT_DROPPED", 858 DragAndDropSvc::HOST_DND_GH_EVT_DROPPED, 858 d->hostCall(DragAndDropSvc::HOST_DND_GH_EVT_DROPPED, 859 859 i, 860 860 paParms); … … 902 902 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms) 903 903 { 904 LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n", 905 pvExtension, u32Function, pvParms, cbParms)); 906 904 907 ComObjPtr<Guest> pGuest = reinterpret_cast<Guest*>(pvExtension); 905 908 if (!pGuest->m_pGuestDnD) … … 909 912 const ComObjPtr<Guest> &p = d->p; 910 913 911 DnDGuestResponse *p DnD= d->response();912 if (p DnD== NULL)914 DnDGuestResponse *pResp = d->response(); 915 if (pResp == NULL) 913 916 return VERR_INVALID_PARAMETER; 914 917 … … 922 925 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER); 923 926 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 924 p DnD->setDefAction(pCBData->uAction);925 rc = p DnD->notifyAboutGuestResponse();927 pResp->setDefAction(pCBData->uAction); 928 rc = pResp->notifyAboutGuestResponse(); 926 929 break; 927 930 } … … 932 935 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER); 933 936 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 934 p DnD->setFormat(pCBData->pszFormat);935 rc = p DnD->notifyAboutGuestResponse();937 pResp->setFormat(pCBData->pszFormat); 938 rc = pResp->notifyAboutGuestResponse(); 936 939 break; 937 940 } … … 942 945 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER); 943 946 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 944 rc = p DnD->setProgress(pCBData->uPercentage, pCBData->uState);947 rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc); 945 948 break; 946 949 } … … 952 955 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER); 953 956 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 954 p DnD->setFormat(pCBData->pszFormat);955 p DnD->setDefAction(pCBData->uDefAction);956 p DnD->setAllActions(pCBData->uAllActions);957 rc = p DnD->notifyAboutGuestResponse();957 pResp->setFormat(pCBData->pszFormat); 958 pResp->setDefAction(pCBData->uDefAction); 959 pResp->setAllActions(pCBData->uAllActions); 960 rc = pResp->notifyAboutGuestResponse(); 958 961 break; 959 962 } … … 965 968 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 966 969 uint32_t cbCurSize = 0; 967 p DnD->addData(pCBData->pvData, pCBData->cbData, &cbCurSize);968 rc = p DnD->setProgress(100.0 / pCBData->cbAllSize * cbCurSize, (pCBData->cbAllSize == cbCurSize ? DragAndDropSvc::DND_PROGRESS_COMPLETE : DragAndDropSvc::DND_PROGRESS_RUNNING));970 pResp->addData(pCBData->pvData, pCBData->cbData, &cbCurSize); 971 rc = pResp->setProgress(100.0 / pCBData->cbAllSize * cbCurSize, (pCBData->cbAllSize == cbCurSize ? DragAndDropSvc::DND_PROGRESS_COMPLETE : DragAndDropSvc::DND_PROGRESS_RUNNING)); 969 972 /* Todo: for now we instantly confirm the cancel. Check if the 970 973 * guest should first clean up stuff itself and than really confirm 971 974 * the cancel request by an extra message. */ 972 975 if (rc == VERR_CANCELLED) 973 p DnD->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);976 pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); 974 977 break; 975 978 } … … 981 984 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 982 985 /* Cleanup */ 983 p DnD->resetData();984 rc = p DnD->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);986 pResp->resetData(); 987 rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc); 985 988 break; 986 989 } 987 990 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 988 default: AssertMsgFailedReturn(("Function %u not recognized!\n", u32Function), VERR_INVALID_PARAMETER); break; 989 } 990 991 default: 992 AssertMsgFailedReturn(("Function %RU32 not supported\n", u32Function), VERR_NOT_SUPPORTED); 993 break; 994 } 995 996 LogFlowFunc(("Returning rc=%Rrc\n", rc)); 991 997 return rc; 992 998 } -
trunk/tools/bin/gen-slickedit-workspace.sh
r49226 r49891 146 146 ;; 147 147 esac 148 if test -n "$3"; 148 if test -n "$3"; 149 149 then 150 150 MY_FOLDER="$1-$3.lst" … … 225 225 if test -d "${f}"; 226 226 then 227 if test -z "${MY_OPT_USE_WILDCARDS}"; 227 if test -z "${MY_OPT_USE_WILDCARDS}"; 228 228 then 229 229 my_sub_tree "${MY_FILE}" "${f}" 230 230 else 231 231 case "${f}" in 232 ${MY_ROOT_DIR}/include*) 232 ${MY_ROOT_DIR}/include*) 233 233 my_sub_tree "${MY_FILE}" "${f}" "Headers" 234 234 ;; 235 *) my_wildcard "${MY_FILE}" "${f}" 235 *) my_wildcard "${MY_FILE}" "${f}" 236 236 ;; 237 237 esac … … 257 257 if test -s "${MY_FILE}-Headers.lst"; 258 258 then 259 if test -z "${MY_OPT_USE_WILDCARDS}"; 259 if test -z "${MY_OPT_USE_WILDCARDS}"; 260 260 then 261 261 echo ' <Folder Name="Headers" Filters="*.h;*.hpp">' >> "${MY_FILE}" … … 908 908 # src/VBox/HostServices 909 909 my_generate_project "GuestCntl" "src/VBox/HostServices/GuestControl" --begin-incs "include" "src/VBox/HostServices/GuestControl" --end-includes "src/VBox/HostServices/GuestControl" 910 my_generate_project "DragAndDrop" "src/VBox/HostServices/DragAndDrop" --begin-incs "include" "src/VBox/HostServices/DragAndDrop" --end-includes "src/VBox/HostServices/DragAndDrop" 910 911 my_generate_project "GuestProps" "src/VBox/HostServices/GuestProperties" --begin-incs "include" "src/VBox/HostServices/GuestProperties" --end-includes "src/VBox/HostServices/GuestProperties" 911 912 my_generate_project "ShClip-HS" "src/VBox/HostServices/SharedClipboard" --begin-incs "include" "src/VBox/HostServices/SharedClipboard" --end-includes "src/VBox/HostServices/SharedClipboard"
Note:
See TracChangeset
for help on using the changeset viewer.