Changeset 51675 in vbox for trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
- Timestamp:
- Jun 20, 2014 10:17:20 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
r51556 r51675 64 64 65 65 VBoxDnDWnd::VBoxDnDWnd(void) 66 : hWnd(NULL), 66 : hThread(NIL_RTTHREAD), 67 mEventSem(NIL_RTSEMEVENT), 68 hWnd(NULL), 67 69 uAllActions(DND_IGNORE_ACTION), 68 70 mfMouseButtonDown(false), … … 83 85 VBoxDnDWnd::~VBoxDnDWnd(void) 84 86 { 85 /** @todo Shutdown crit sect / event etc! */ 86 87 reset(); 88 } 89 87 Destroy(); 88 } 89 90 /** 91 * Initializes the proxy window with a given DnD context. 92 * 93 * @return IPRT status code. 94 * @param pContext Pointer to context to use. 95 */ 90 96 int VBoxDnDWnd::Initialize(PVBOXDNDCONTEXT pContext) 91 97 { … … 102 108 { 103 109 /* Message pump thread for our proxy window. */ 104 rc = RTThreadCreate(& gCtx.hEvtQueue, VBoxDnDWnd::Thread, this,110 rc = RTThreadCreate(&hThread, VBoxDnDWnd::Thread, this, 105 111 0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 106 112 "VBoxTrayDnDWnd"); 107 if (RT_FAILURE(rc)) 108 LogRel(("DnD: Failed to start proxy window thread, rc=%Rrc\n", rc)); 109 /** @todo Wait for thread to be started! */ 110 } 113 if (RT_SUCCESS(rc)) 114 rc = RTThreadUserWait(hThread, 30 * 1000 /* Timeout in ms */); 115 } 116 117 if (RT_FAILURE(rc)) 118 LogRel(("DnD: Failed to initialize proxy window, rc=%Rrc\n", rc)); 111 119 112 120 LogFlowThisFunc(("Returning rc=%Rrc\n", rc)); … … 115 123 116 124 /** 125 * Destroys the proxy window and releases all remaining 126 * resources again. 127 * 128 */ 129 void VBoxDnDWnd::Destroy(void) 130 { 131 if (hThread != NIL_RTTHREAD) 132 { 133 int rcThread = VERR_WRONG_ORDER; 134 int rc = RTThreadWait(hThread, 60 * 1000 /* Timeout in ms */, &rcThread); 135 LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n", 136 rc, rcThread)); 137 } 138 139 reset(); 140 141 RTCritSectDelete(&mCritSect); 142 if (mEventSem != NIL_RTSEMEVENT) 143 RTSemEventDestroy(mEventSem); 144 145 LogFlowFuncLeave(); 146 } 147 148 /** 117 149 * Thread for handling the window's message pump. 118 150 * 119 151 * @return IPRT status code. 120 * @param hThread 121 * @param pvUser 152 * @param hThread Handle to this thread. 153 * @param pvUser Pointer to VBoxDnDWnd instance which 154 * is using the thread. 122 155 */ 123 156 /* static */ … … 152 185 #endif 153 186 187 bool fSignalled = false; /* Thread signalled? */ 188 154 189 int rc = VINF_SUCCESS; 155 190 if (!RegisterClassEx(&wndClass)) … … 223 258 if (RT_SUCCESS(rc)) 224 259 { 260 rc = RTThreadUserSignal(hThread); 261 fSignalled = RT_SUCCESS(rc); 262 225 263 bool fShutdown = false; 226 do264 while (RT_SUCCESS(rc)) 227 265 { 228 266 MSG uMsg; … … 243 281 244 282 /** @todo Immediately drop on failure? */ 245 246 } while (RT_SUCCESS(rc)); 283 } 247 284 248 285 #ifdef VBOX_WITH_DRAG_AND_DROP_GH … … 254 291 } 255 292 293 if (!fSignalled) 294 { 295 int rc2 = RTThreadUserSignal(hThread); 296 AssertRC(rc2); 297 } 298 256 299 LogFlowFuncLeaveRC(rc); 257 300 return rc; 258 301 } 259 302 303 /** 304 * Monitor enumeration callback for building up a simple bounding 305 * box, capable of holding all enumerated monitors. 306 * 307 * @return BOOL TRUE if enumeration should continue, 308 * FALSE if not. 309 * @param hMonitor Handle to current monitor being enumerated. 310 * @param hdcMonitor The current monitor's DC (device context). 311 * @param lprcMonitor The current monitor's RECT. 312 * @param lParam Pointer to a RECT structure holding the 313 * bounding box to build. 314 */ 260 315 /* static */ 261 316 BOOL CALLBACK VBoxDnDWnd::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, … … 283 338 } 284 339 340 /** 341 * The proxy window's WndProc. 342 */ 285 343 LRESULT CALLBACK VBoxDnDWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 286 344 { … … 606 664 } 607 665 666 /** 667 * Unregisters this proxy as a drop target. 668 * 669 * @return IPRT status code. 670 */ 608 671 int VBoxDnDWnd::UnregisterAsDropTarget(void) 609 672 { … … 633 696 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 634 697 698 /** 699 * Handles the creation of a proxy window. 700 * 701 * @return IPRT status code. 702 */ 635 703 int VBoxDnDWnd::OnCreate(void) 636 704 { … … 646 714 } 647 715 716 /** 717 * Handles the destruction of a proxy window. 718 */ 648 719 void VBoxDnDWnd::OnDestroy(void) 649 720 { … … 652 723 } 653 724 725 /** 726 * Handles actions required when the host cursor enters 727 * the guest's screen to initiate a host -> guest DnD operation. 728 * 729 * @return IPRT status code. 730 * @param lstFormats Supported formats offered by the host. 731 * @param uAllActions Supported actions offered by the host. 732 */ 654 733 int VBoxDnDWnd::OnHgEnter(const RTCList<RTCString> &lstFormats, uint32_t uAllActions) 655 734 { … … 716 795 } 717 796 797 /** 798 * Handles actions required when the host cursor moves inside 799 * the guest's screen. 800 * 801 * @return IPRT status code. 802 * @param u32xPos Absolute X position (in pixels) of the host cursor 803 * inside the guest. 804 * @param u32yPos Absolute Y position (in pixels) of the host cursor 805 * inside the guest. 806 * @param uAction Action the host wants to perform while moving. 807 * Currently ignored. 808 */ 718 809 int VBoxDnDWnd::OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction) 719 810 { … … 753 844 } 754 845 846 /** 847 * Handles actions required when the host cursor leaves 848 * the guest's screen again. 849 * 850 * @return IPRT status code. 851 */ 755 852 int VBoxDnDWnd::OnHgLeave(void) 756 853 { … … 773 870 } 774 871 872 /** 873 * Handles actions required when the host cursor wants to drop 874 * and therefore start a "drop" action in the guest. 875 * 876 * @return IPRT status code. 877 */ 775 878 int VBoxDnDWnd::OnHgDrop(void) 776 879 { … … 812 915 } 813 916 917 /** 918 * Handles actions required when the host has sent over DnD data 919 * to the guest after a "drop" event. 920 * 921 * @return IPRT status code. 922 * @param pvData Pointer to raw data received. 923 * @param cbData Size of data (in bytes) received. 924 */ 814 925 int VBoxDnDWnd::OnHgDataReceived(const void *pvData, uint32_t cbData) 815 926 { … … 843 954 } 844 955 956 /** 957 * Handles actions required when the host wants to cancel an action 958 * host -> guest operation. 959 * 960 * @return IPRT status code. 961 */ 845 962 int VBoxDnDWnd::OnHgCancel(void) 846 963 { … … 864 981 865 982 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 983 /** 984 * Handles actions required to start a guest -> host DnD operation. 985 * This works by letting the host ask whether a DnD operation is pending 986 * on the guest. The guest must not know anything about the host's DnD state 987 * and/or operations due to security reasons. 988 * 989 * To capture a pending DnD operation on the guest which then can be communicated 990 * to the host the proxy window needs to be registered as a drop target. This drop 991 * target then will act as a proxy target between the guest OS and the host. In other 992 * words, the guest OS will use this proxy target as a regular (invisible) window 993 * which can be used by the regular guest OS' DnD mechanisms, independently of the 994 * host OS. To make sure this proxy target is able receive an in-progress DnD operation 995 * on the guest, it will be shown invisibly across all active guest OS screens. Just 996 * think of an opened umbrella across all screens here. 997 * 998 * As soon as the proxy target and its underlying data object receive appropriate 999 * DnD messages they'll be hidden again, and the control will be transferred back 1000 * this class again. 1001 * 1002 * @return IPRT status code. 1003 * @param uScreenID Screen ID the host wants to query a pending operation 1004 * for. Currently not used/needed here. 1005 */ 866 1006 int VBoxDnDWnd::OnGhIsDnDPending(uint32_t uScreenID) 867 1007 { … … 995 1135 } 996 1136 997 int VBoxDnDWnd::OnGhDropped(const char *pszFormat, uint32_t cbFormats, 1137 /** 1138 * Handles actions required to let the guest know that the host 1139 * started a "drop" action on the host. This will tell the guest 1140 * to send data in a specific format the host requested. 1141 * 1142 * @return IPRT status code. 1143 * @param pszFormat Format the host requests the data in. 1144 * @param cbFormat Size (in bytes) of format string. 1145 * @param uDefAction Default action on the host. 1146 */ 1147 int VBoxDnDWnd::OnGhDropped(const char *pszFormat, uint32_t cbFormat, 998 1148 uint32_t uDefAction) 999 1149 { 1000 1150 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 1001 AssertReturn(cbFormat s, VERR_INVALID_PARAMETER);1151 AssertReturn(cbFormat, VERR_INVALID_PARAMETER); 1002 1152 1003 1153 LogFlowThisFunc(("mMode=%ld, mState=%ld, pDropTarget=0x%p, pszFormat=%s, uDefAction=0x%x\n", … … 1043 1193 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 1044 1194 1195 /** 1196 * Injects a DnD event in this proxy window's Windows 1197 * event queue. The (allocated) event will be deleted by 1198 * this class after processing. 1199 * 1200 * @return IPRT status code. 1201 * @param pEvent Event to inject. 1202 */ 1045 1203 int VBoxDnDWnd::ProcessEvent(PVBOXDNDEVENT pEvent) 1046 1204 { 1047 1205 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1048 1206 1049 PostMessage(hWnd, WM_VBOXTRAY_DND_MESSAGE, 1050 0 /* wParm */, (LPARAM)pEvent /* lParm */); 1207 BOOL fRc = PostMessage(hWnd, WM_VBOXTRAY_DND_MESSAGE, 1208 0 /* wParm */, (LPARAM)pEvent /* lParm */); 1209 if (!fRc) 1210 { 1211 static int s_iBitchedAboutFailedDnDMessages = 0; 1212 if (s_iBitchedAboutFailedDnDMessages++ < 10) 1213 { 1214 DWORD dwErr = GetLastError(); 1215 LogRel(("DnD: Processing event %p failed with %ld (%Rrc), skpping\n", 1216 pEvent, dwErr, RTErrConvertFromWin32(dwErr))); 1217 } 1218 1219 RTMemFree(pEvent); 1220 pEvent = NULL; 1221 1222 return VERR_NO_MEMORY; 1223 } 1051 1224 1052 1225 return VINF_SUCCESS; 1053 1226 } 1054 1227 1228 /** 1229 * Hides the proxy window again. 1230 * 1231 * @return IPRT status code. 1232 */ 1055 1233 int VBoxDnDWnd::hide(void) 1056 1234 { … … 1063 1241 } 1064 1242 1243 /** 1244 * Shows the (invisible) proxy window in fullscreen, 1245 * spawned across all active guest monitors. 1246 * 1247 * @return IPRT status code. 1248 */ 1065 1249 int VBoxDnDWnd::makeFullscreen(void) 1066 1250 { … … 1137 1321 } 1138 1322 1323 /** 1324 * Moves the guest mouse cursor to a specific position. 1325 * 1326 * @return IPRT status code. 1327 * @param x X position (in pixels) to move cursor to. 1328 * @param y Y position (in pixels) to move cursor to. 1329 * @param dwMouseInputFlags Additional movement flags. @sa MOUSEEVENTF_ flags. 1330 */ 1139 1331 int VBoxDnDWnd::mouseMove(int x, int y, DWORD dwMouseInputFlags) 1140 1332 { … … 1175 1367 } 1176 1368 1369 /** 1370 * Releases a previously pressed left guest mouse button. 1371 * 1372 * @return IPRT status code. 1373 */ 1177 1374 int VBoxDnDWnd::mouseRelease(void) 1178 1375 { … … 1199 1396 } 1200 1397 1398 /** 1399 * Resets the proxy window. 1400 */ 1201 1401 void VBoxDnDWnd::reset(void) 1202 1402 { … … 1214 1414 } 1215 1415 1416 /** 1417 * Sets the current operation mode of this proxy window. 1418 * 1419 * @return IPRT status code. 1420 * @param enmMode New mode to set. 1421 */ 1216 1422 int VBoxDnDWnd::setMode(Mode enmMode) 1217 1423 { … … 1225 1431 } 1226 1432 1227 static LRESULT CALLBACK vboxDnDWndProcInstance(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1433 /** 1434 * Static helper function for having an own WndProc for proxy 1435 * window instances. 1436 */ 1437 static LRESULT CALLBACK vboxDnDWndProcInstance(HWND hWnd, UINT uMsg, 1438 WPARAM wParam, LPARAM lParam) 1228 1439 { 1229 1440 LONG_PTR pUserData = GetWindowLongPtr(hWnd, GWLP_USERDATA); … … 1237 1448 } 1238 1449 1239 static LRESULT CALLBACK vboxDnDWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1450 /** 1451 * Static helper function for routing Windows messages to a specific 1452 * proxy window instance. 1453 */ 1454 static LRESULT CALLBACK vboxDnDWndProc(HWND hWnd, UINT uMsg, 1455 WPARAM wParam, LPARAM lParam) 1240 1456 { 1241 1457 /* Note: WM_NCCREATE is not the first ever message which arrives, but … … 1346 1562 /* Set shutdown indicator. */ 1347 1563 ASMAtomicWriteBool(&pCtx->fShutdown, true); 1348 1349 /** @todo Notify / wait for HGCM thread! */1350 1564 } 1351 1565
Note:
See TracChangeset
for help on using the changeset viewer.