Changeset 85920 in vbox
- Timestamp:
- Aug 28, 2020 9:40:55 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r85746 r85920 53 53 * For X11 guest Xdnd is used. See http://www.acc.umu.se/~vatten/XDND.html for 54 54 * a walk trough. 55 * 56 * Also useful pages: 57 * - https://www.freedesktop.org/wiki/Draganddropwarts/ 58 * - https://www.freedesktop.org/wiki/Specifications/XDNDRevision/ 55 59 * 56 60 * Host -> Guest: … … 86 90 */ 87 91 88 #define VBOX_XDND_VERSION (4) 92 /********************************************************************************************************************************* 93 * Definitions * 94 ********************************************************************************************************************************/ 95 96 /** The Xdnd protocol version we support. */ 97 #define VBOX_XDND_VERSION (5) 98 99 /** Whether the target window accepts the data being dragged over or not. */ 100 #define VBOX_XDND_STATUS_FLAG_ACCEPT 0x1 101 /** Whether the target window wants XdndPosition messages while dragging stuff over it. */ 102 #define VBOX_XDND_STATUS_FLAG_WANTS_POS 0x2 103 104 /** Whether the target window accepted the drop data or not. */ 105 #define VBOX_XDND_FINISHED_FLAG_SUCCEEDED 0x1 106 107 /** How many X properties our proxy window can hold. */ 89 108 #define VBOX_MAX_XPROPERTIES (LONG_MAX-1) 90 109 … … 218 237 #define VBoxDnDAtomList RTCList<Atom> 219 238 220 /*******************************************************************************221 *222 * xHelpers Declaration223 *224 ******************************************************************************/225 226 239 class xHelpers 227 240 { … … 302 315 #define xAtomToString(xa) xHelpers::getInstance()->xAtomToString((xa)) 303 316 304 /******************************************************************************* 305 * 306 * xHelpers Implementation 307 * 308 ******************************************************************************/ 317 /********************************************************************************************************************************* 318 * xHelpers implementation. * 319 ********************************************************************************************************************************/ 309 320 310 321 xHelpers *xHelpers::m_pInstance = NULL; … … 418 429 } 419 430 420 /*******************************************************************************421 *422 * DragInstance Declaration423 *424 ******************************************************************************/425 426 431 #ifdef DEBUG 427 432 # define VBOX_DND_FN_DECL_LOG(x) inline x /* For LogFlowXXX logging. */ … … 430 435 #endif 431 436 432 /** @todo Move all proxy window-related stuff into this class! Clean up this mess. */ 437 /** 438 * Class which handles a single drag'n drop proxy window. 439 ** @todo Move all proxy window-related stuff into this class! Clean up this mess. 440 */ 433 441 class VBoxDnDProxyWnd 434 442 { … … 570 578 571 579 /* Atom / HGCM formatting helpers. */ 572 int toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const;573 int toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const;580 int appendToAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const; 581 int appendToAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const; 574 582 static Atom toAtomAction(VBOXDNDACTION dndAction); 575 583 static int toAtomActions(VBOXDNDACTIONLIST dndActionList, VBoxDnDAtomList &lstAtoms); … … 627 635 }; 628 636 629 /******************************************************************************* 630 * 631 * DragAndDropService Declaration 632 * 633 ******************************************************************************/ 634 637 /** 638 * Service class which implements drag'n drop. 639 */ 635 640 class DragAndDropService 636 641 { … … 677 682 }; 678 683 679 /******************************************************************************* 680 * 681 * DragInstanc Implementation 682 * 683 ******************************************************************************/ 684 /********************************************************************************************************************************* 685 * DragInstanc implementation. * 686 ********************************************************************************************************************************/ 684 687 685 688 DragInstance::DragInstance(Display *pDisplay, DragAndDropService *pParent) … … 885 888 886 889 /* Make the new window Xdnd aware. */ 887 Atom ver = VBOX_XDND_VERSION;890 Atom atmVer = VBOX_XDND_VERSION; 888 891 XChangeProperty(m_pDisplay, m_wndProxy.hWnd, xAtom(XA_XdndAware), XA_ATOM, 32, PropModeReplace, 889 reinterpret_cast<unsigned char*>(& ver), 1);892 reinterpret_cast<unsigned char*>(&atmVer), 1); 890 893 } while (0); 891 894 … … 1248 1251 * @param e X11 event to handle. 1249 1252 */ 1250 int DragInstance::onX11SelectionRequest(const XEvent &e) 1251 { 1252 AssertReturn(e.type == SelectionRequest, VERR_INVALID_PARAMETER); 1253 int DragInstance::onX11SelectionRequest(const XEvent &evReq) 1254 { 1255 AssertReturn(evReq.type == SelectionRequest, VERR_INVALID_PARAMETER); 1256 1257 const XSelectionRequestEvent *pEvReq = &evReq.xselectionrequest; 1253 1258 1254 1259 LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState)); 1255 1260 LogFlowThisFunc(("Event owner=%#x, requestor=%#x, selection=%s, target=%s, prop=%s, time=%u\n", 1256 e.xselectionrequest.owner,1257 e.xselectionrequest.requestor,1258 xAtomToString( e.xselectionrequest.selection).c_str(),1259 xAtomToString( e.xselectionrequest.target).c_str(),1260 xAtomToString( e.xselectionrequest.property).c_str(),1261 e.xselectionrequest.time));1261 pEvReq->owner, 1262 pEvReq->requestor, 1263 xAtomToString(pEvReq->selection).c_str(), 1264 xAtomToString(pEvReq->target).c_str(), 1265 xAtomToString(pEvReq->property).c_str(), 1266 pEvReq->time)); 1262 1267 int rc; 1263 1268 … … 1268 1273 rc = VINF_SUCCESS; 1269 1274 1270 char *pszWndName = wndX11GetNameA( e.xselectionrequest.requestor);1275 char *pszWndName = wndX11GetNameA(pEvReq->requestor); 1271 1276 AssertPtr(pszWndName); 1272 1277 … … 1276 1281 */ 1277 1282 1278 XEvent s; 1279 RT_ZERO(s); 1280 s.xselection.type = SelectionNotify; 1281 s.xselection.display = e.xselectionrequest.display; 1282 s.xselection.requestor = e.xselectionrequest.requestor; 1283 s.xselection.selection = e.xselectionrequest.selection; 1284 s.xselection.target = e.xselectionrequest.target; 1285 s.xselection.property = None; /* "None" means refusal. */ 1286 s.xselection.time = e.xselectionrequest.time; 1287 1288 const XSelectionRequestEvent *pReq = &e.xselectionrequest; 1283 XEvent evResp; 1284 RT_ZERO(evResp); 1285 1286 XSelectionEvent *pEvResp = &evResp.xselection; 1287 1288 pEvResp->type = SelectionNotify; 1289 pEvResp->display = pEvReq->display; 1290 pEvResp->requestor = pEvReq->requestor; 1291 pEvResp->selection = pEvReq->selection; 1292 pEvResp->target = pEvReq->target; 1293 pEvResp->property = None; /* "None" means refusal. */ 1294 pEvResp->time = pEvReq->time; 1289 1295 1290 1296 #ifdef DEBUG … … 1294 1300 #endif 1295 1301 /* Is the requestor asking for the possible MIME types? */ 1296 if (p Req->target == xAtom(XA_TARGETS))1302 if (pEvReq->target == xAtom(XA_TARGETS)) 1297 1303 { 1298 VBClLogInfo("Target window %#x ('%s') asking for target list\n", e.xselectionrequest.requestor, pszWndName);1304 VBClLogInfo("Target window %#x ('%s') asking for target list\n", pEvReq->requestor, pszWndName); 1299 1305 1300 1306 /* If so, set the window property with the formats on the requestor 1301 1307 * window. */ 1302 rc = wndXDnDSetFormatList(p Req->requestor, pReq->property, m_lstFormats);1308 rc = wndXDnDSetFormatList(pEvReq->requestor, pEvReq->property, m_lstFormats); 1303 1309 if (RT_SUCCESS(rc)) 1304 s.xselection.property = pReq->property;1310 pEvResp->property = pEvReq->property; 1305 1311 } 1306 1312 /* Is the requestor asking for a specific MIME type (we support)? */ 1307 else if (m_lstFormats.contains(p Req->target))1313 else if (m_lstFormats.contains(pEvReq->target)) 1308 1314 { 1309 1315 VBClLogInfo("Target window %#x ('%s') is asking for data as '%s'\n", 1310 p Req->requestor, pszWndName, xAtomToString(pReq->target).c_str());1316 pEvReq->requestor, pszWndName, xAtomToString(pEvReq->target).c_str()); 1311 1317 1312 1318 /* Did we not drop our stuff to the guest yet? Bail out. */ 1313 1319 if (m_enmState != Dropped) 1314 1320 { 1315 LogFlowThisFunc(("Wrong state (%RU32), refusing request\n", m_enmState)); 1321 VBClLogError("Data not dropped by the host on the guest yet (client state %RU32, mode %RU32), refusing selection request by guest\n", 1322 m_enmState, m_enmMode); 1316 1323 } 1317 1324 /* Did we not store the requestor's initial selection request yet? Then do so now. */ … … 1319 1326 { 1320 1327 /* Get the data format the requestor wants from us. */ 1321 RTCString strFormat = xAtomToString(p Req->target);1328 RTCString strFormat = xAtomToString(pEvReq->target); 1322 1329 Assert(strFormat.isNotEmpty()); 1323 1330 VBClLogInfo("Target window=%#x requested data from host as '%s', rc=%Rrc\n", 1324 p Req->requestor, strFormat.c_str(), rc);1331 pEvReq->requestor, strFormat.c_str(), rc); 1325 1332 1326 1333 /* Make a copy of the MIME data to be passed back. The X server will be become … … 1331 1338 1332 1339 /* Always return the requested property. */ 1333 s.xselection.property = pReq->property;1340 evResp.xselection.property = pEvReq->property; 1334 1341 1335 1342 /* Note: Always seems to return BadRequest. Seems fine. */ 1336 int xRc = XChangeProperty( s.xselection.display, s.xselection.requestor, s.xselection.property,1337 s.xselection.target, 8, PropModeReplace,1343 int xRc = XChangeProperty(pEvResp->display, pEvResp->requestor, pEvResp->property, 1344 pEvResp->target, 8, PropModeReplace, 1338 1345 reinterpret_cast<const unsigned char*>(pvData), cbData); 1339 1346 1340 1347 LogFlowFunc(("Changing property '%s' (target '%s') of window=%RU32: %s\n", 1341 xAtomToString(p Req->property).c_str(),1342 xAtomToString(p Req->target).c_str(),1343 p Req->requestor,1348 xAtomToString(pEvReq->property).c_str(), 1349 xAtomToString(pEvReq->target).c_str(), 1350 pEvReq->requestor, 1344 1351 gX11->xErrorToString(xRc).c_str())); 1345 1352 RT_NOREF(xRc); … … 1350 1357 { 1351 1358 VBClLogError("Refusing unknown command/format '%s' of wnd=%#x ('%s')\n", 1352 xAtomToString( e.xselectionrequest.target).c_str(), pReq->requestor, pszWndName);1359 xAtomToString(pEvReq->target).c_str(), pEvReq->requestor, pszWndName); 1353 1360 rc = VERR_NOT_SUPPORTED; 1354 1361 } 1355 1362 1356 1363 LogFlowThisFunc(("Offering type '%s', property '%s' to wnd=%#x ...\n", 1357 xAtomToString(p Req->target).c_str(),1358 xAtomToString(p Req->property).c_str(), pReq->requestor));1359 1360 int xRc = XSendEvent(p Req->display, pReq->requestor, True /* Propagate */, 0, &s);1364 xAtomToString(pEvReq->target).c_str(), 1365 xAtomToString(pEvReq->property).c_str(), pEvReq->requestor)); 1366 1367 int xRc = XSendEvent(pEvReq->display, pEvReq->requestor, True /* Propagate */, 0, &evResp); 1361 1368 if (xRc == 0) 1362 VBClLogError("Error sending SelectionNotify(1) event to wnd=%#x: %s\n", pReq->requestor,1363 gX11->xErrorToString(xRc).c_str());1364 XFlush(p Req->display);1369 VBClLogError("Error sending SelectionNotify(1) event to wnd=%#x: %s\n", 1370 pEvReq->requestor, gX11->xErrorToString(xRc).c_str()); 1371 XFlush(pEvReq->display); 1365 1372 1366 1373 if (pszWndName) … … 1397 1404 */ 1398 1405 case ButtonPress: 1406 RT_FALL_THROUGH(); 1399 1407 case ButtonRelease: 1400 LogFlowThisFunc(("Mouse button press/release\n")); 1408 { 1409 VBClLogInfo("Mouse button %s\n", e.type == ButtonPress ? "pressed" : "released"); 1410 1411 reset(); 1412 1401 1413 rc = VINF_SUCCESS; 1402 1403 reset(); 1404 break; 1414 break; 1415 } 1405 1416 1406 1417 case ClientMessage: … … 1620 1631 break; 1621 1632 1622 rc = toAtomList(lstFormats, m_lstFormats);1633 rc = appendToAtomList(lstFormats, m_lstFormats); 1623 1634 if (RT_FAILURE(rc)) 1624 1635 break; … … 1698 1709 { 1699 1710 /* Temp stuff for the XGetWindowProperty call. */ 1700 Atom atm p;1711 Atom atmTmp; 1701 1712 int fmt; 1702 1713 unsigned long cItems, cbRemaining; … … 1707 1718 xRc = XGetWindowProperty(m_pDisplay, wndCursor, xAtom(XA_XdndAware), 1708 1719 0, 2, False, AnyPropertyType, 1709 &atm p, &fmt, &cItems, &cbRemaining, &pcData);1720 &atmTmp, &fmt, &cItems, &cbRemaining, &pcData); 1710 1721 if (xRc != Success) 1711 1722 { … … 1824 1835 * Send a XdndPosition event with the proposed action to the guest. 1825 1836 */ 1826 Atom pa= toAtomAction(dndActionDefault);1827 LogFlowThisFunc(("strAction=%s\n", xAtomToString( pa).c_str()));1837 Atom atmAction = toAtomAction(dndActionDefault); 1838 LogFlowThisFunc(("strAction=%s\n", xAtomToString(atmAction).c_str())); 1828 1839 1829 1840 XClientMessageEvent m; … … 1835 1846 m.format = 32; 1836 1847 m.data.l[XdndPositionWindow] = m_wndProxy.hWnd; /* X window ID of source window. */ 1848 m.data.l[XdndPositionFlags] = 0; /* Reserved, set to 0. */ 1837 1849 m.data.l[XdndPositionXY] = RT_MAKE_U32(uPosY, uPosX); /* Cursor coordinates relative to the root window. */ 1838 1850 m.data.l[XdndPositionTimeStamp] = CurrentTime; /* Timestamp for retrieving data. */ 1839 m.data.l[XdndPositionAction] = pa;/* Actions requested by the user. */1851 m.data.l[XdndPositionAction] = atmAction; /* Actions requested by the user. */ 1840 1852 1841 1853 xRc = XSendEvent(m_pDisplay, wndCursor, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); … … 2776 2788 * @param wndThis Window to set the format list for. 2777 2789 * @param lstActions Reference to list of XDnD actions to set. 2778 *2779 * @remark2780 2790 */ 2781 2791 int DragInstance::wndXDnDSetActionList(Window wndThis, const VBoxDnDAtomList &lstActions) const … … 2814 2824 XChangeProperty(m_pDisplay, wndThis, atmProp, 2815 2825 XA_ATOM, 32, PropModeReplace, 2816 reinterpret_cast<const unsigned char*>(lstFormats Ext.raw()),2817 lstFormats Ext.size());2826 reinterpret_cast<const unsigned char*>(lstFormats.raw()), 2827 lstFormats.size()); 2818 2828 2819 2829 return VINF_SUCCESS; … … 2821 2831 2822 2832 /** 2823 * Converts a RTCString list to VBoxDnDAtomList list.2833 * Appends a RTCString list to VBoxDnDAtomList list. 2824 2834 * 2825 2835 * @returns IPRT status code. … … 2827 2837 * @param lstAtoms Reference to VBoxDnDAtomList list to store results in. 2828 2838 */ 2829 int DragInstance:: toAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const2839 int DragInstance::appendToAtomList(const RTCList<RTCString> &lstFormats, VBoxDnDAtomList &lstAtoms) const 2830 2840 { 2831 2841 for (size_t i = 0; i < lstFormats.size(); ++i) … … 2836 2846 2837 2847 /** 2838 * Converts a raw-data string list to VBoxDnDAtomList list.2848 * Appends a raw-data string list to VBoxDnDAtomList list. 2839 2849 * 2840 2850 * @returns IPRT status code. … … 2843 2853 * @param lstAtoms Reference to VBoxDnDAtomList list to store results in. 2844 2854 */ 2845 int DragInstance:: toAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const2855 int DragInstance::appendToAtomList(const void *pvData, uint32_t cbData, VBoxDnDAtomList &lstAtoms) const 2846 2856 { 2847 2857 RT_NOREF1(lstAtoms); … … 2952 2962 } 2953 2963 2954 /******************************************************************************* 2955 * VBoxDnDProxyWnd implementation. 2956 ****************************************************************************** /2964 /********************************************************************************************************************************* 2965 * VBoxDnDProxyWnd implementation. * 2966 ********************************************************************************************************************************/ 2957 2967 2958 2968 VBoxDnDProxyWnd::VBoxDnDProxyWnd(void) … … 3020 3030 } 3021 3031 3022 /******************************************************************************* 3023 * DragAndDropService implementation. 3024 ****************************************************************************** /3032 /********************************************************************************************************************************* 3033 * DragAndDropService implementation. * 3034 ********************************************************************************************************************************/ 3025 3035 3026 3036 /** … … 3448 3458 XNextEvent(pThis->m_pDisplay, &e.x11); 3449 3459 { 3450 #ifdef DEBUG3451 switch (e.x11.type)3452 {3453 case ClientMessage:3454 {3455 XClientMessageEvent *pEvent = reinterpret_cast<XClientMessageEvent*>(&e);3456 AssertPtr(pEvent);3457 3458 RTCString strType = xAtomToString(pEvent->message_type);3459 LogFlowFunc(("ClientMessage: %s from wnd=%#x\n", strType.c_str(), pEvent->window));3460 break;3461 }3462 3463 default:3464 LogFlowFunc(("Received X event type=%d\n", e.x11.type));3465 break;3466 }3467 #endif3468 3460 /* At the moment we only have one drag instance. */ 3469 3461 DragInstance *pInstance = pThis->m_pCurDnD;
Note:
See TracChangeset
for help on using the changeset viewer.