Changeset 56781 in vbox for trunk/src/VBox/Additions/x11/VBoxClient
- Timestamp:
- Jul 3, 2015 12:58:05 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r56760 r56781 34 34 #include <limits.h> 35 35 36 # 37 38 # 36 #ifdef LOG_GROUP 37 # undef LOG_GROUP 38 #endif 39 39 #define LOG_GROUP LOG_GROUP_GUEST_DND 40 40 #include <VBox/log.h> … … 42 42 43 43 #include "VBox/HostServices/DragAndDropSvc.h" 44 45 44 #include "VBoxClient.h" 46 45 … … 174 173 XdndPositionWindow = 0, /* Source window (sender). */ 175 174 XdndPositionFlags, /* Flags. */ 176 XdndPosition Coords,/* X/Y coordinates of the mouse position relative to the root window. */175 XdndPositionXY, /* X/Y coordinates of the mouse position relative to the root window. */ 177 176 XdndPositionTimeStamp, /* Time stamp for retrieving the data. */ 178 177 XdndPositionAction, /* Action requested by the user. */ … … 181 180 XdndStatusWindow = 0, /* Target window (sender).*/ 182 181 XdndStatusFlags, /* Flags returned by target. */ 183 XdndStatus Pt,/* X + Y of "no msg" rectangle (root window coords). */184 XdndStatus Area,/* Width + height of "no msg" rectangle. */182 XdndStatusNoMsgXY, /* X + Y of "no msg" rectangle (root window coords). */ 183 XdndStatusNoMsgWH, /* Width + height of "no msg" rectangle. */ 185 184 XdndStatusAction, /* Action accepted by target. */ 186 185 … … 410 409 #endif 411 410 411 /** @todo Move all proxy window-related stuff into this class! Clean up this mess. */ 412 class VBoxDnDProxyWnd 413 { 414 415 public: 416 417 VBoxDnDProxyWnd(void); 418 419 virtual ~VBoxDnDProxyWnd(void); 420 421 public: 422 423 int init(Display *pDisplay); 424 void destroy(); 425 426 int sendFinished(Window hWndSource, uint32_t uAction); 427 428 public: 429 430 Display *pDisp; 431 /** Proxy window handle. */ 432 Window hWnd; 433 int iX; 434 int iY; 435 int iWidth; 436 int iHeight; 437 }; 438 412 439 /** 413 440 * Class for handling a single drag and drop operation, that is, … … 474 501 475 502 /* X11 helpers. */ 503 int mouseCursorFakeMove(void) const; 476 504 int mouseCursorMove(int iPosX, int iPosY) const; 477 505 void mouseButtonSet(Window wndDest, int rx, int ry, int iButton, bool fPress); … … 512 540 /** Root window handle. */ 513 541 Window m_wndRoot; 514 /** Proxy window handle. */515 Windowm_wndProxy;542 /** Proxy window. */ 543 VBoxDnDProxyWnd m_wndProxy; 516 544 /** Current source/target window handle. */ 517 545 Window m_wndCur; … … 600 628 , m_pScreen(0) 601 629 , m_wndRoot(0) 602 , m_wndProxy(0)603 630 , m_wndCur(0) 604 631 , m_curVer(-1) … … 617 644 LogFlowFuncEnter(); 618 645 619 if (m_wndProxy != 0)620 XDestroyWindow(m_pDisplay, m_wndProxy );646 if (m_wndProxy.hWnd != 0) 647 XDestroyWindow(m_pDisplay, m_wndProxy.hWnd); 621 648 622 649 int rc2 = VbglR3DnDDisconnect(&m_dndCtx); … … 650 677 /* If we are currently the Xdnd selection owner, clear that. */ 651 678 Window pWnd = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 652 if (pWnd == m_wndProxy )679 if (pWnd == m_wndProxy.hWnd) 653 680 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), None, CurrentTime); 654 681 655 682 /* Clear any other DnD specific data on the proxy window. */ 656 wndXDnDClearFormatList(m_wndProxy );657 wndXDnDClearActionList(m_wndProxy );683 wndXDnDClearFormatList(m_wndProxy.hWnd); 684 wndXDnDClearActionList(m_wndProxy.hWnd); 658 685 659 686 /* Reset the internal state. */ … … 749 776 attr.background_pixel = XWhitePixel(m_pDisplay, m_screenId); 750 777 attr.border_pixel = XBlackPixel(m_pDisplay, m_screenId); 751 m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot/* Parent */,778 m_wndProxy.hWnd = XCreateWindow(m_pDisplay, m_wndRoot /* Parent */, 752 779 100, 100, /* Position */ 753 780 100, 100, /* Width + height */ … … 762 789 &attr); /* Attributes for value mask */ 763 790 #else 764 m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot/* Parent */,791 m_wndProxy.hWnd = XCreateWindow(m_pDisplay, m_wndRoot /* Parent */, 765 792 0, 0, /* Position */ 766 793 1, 1, /* Width + height */ … … 772 799 &attr); /* Attributes for value mask */ 773 800 #endif 774 if (!m_wndProxy )801 if (!m_wndProxy.hWnd) 775 802 { 776 803 LogRel(("DnD: Error creating proxy window\n")); … … 779 806 } 780 807 808 rc = m_wndProxy.init(m_pDisplay); 809 if (RT_FAILURE(rc)) 810 { 811 LogRel(("DnD: Error initializing proxy window, rc=%Rrc\n", rc)); 812 break; 813 } 814 781 815 #ifdef VBOX_DND_DEBUG_WND 782 816 XFlush(m_pDisplay); 783 XMapWindow(m_pDisplay, m_wndProxy );784 XRaiseWindow(m_pDisplay, m_wndProxy );817 XMapWindow(m_pDisplay, m_wndProxy.hWnd); 818 XRaiseWindow(m_pDisplay, m_wndProxy.hWnd); 785 819 XFlush(m_pDisplay); 786 820 #endif 787 logInfo("Proxy window=0x%x, root window=0x%x ...\n", m_wndProxy , m_wndRoot);821 logInfo("Proxy window=0x%x, root window=0x%x ...\n", m_wndProxy.hWnd, m_wndRoot); 788 822 789 823 /* Set the window's name for easier lookup. */ 790 XStoreName(m_pDisplay, m_wndProxy , "VBoxClientWndDnD");824 XStoreName(m_pDisplay, m_wndProxy.hWnd, "VBoxClientWndDnD"); 791 825 792 826 /* Make the new window Xdnd aware. */ 793 827 Atom ver = VBOX_XDND_VERSION; 794 XChangeProperty(m_pDisplay, m_wndProxy , xAtom(XA_XdndAware), XA_ATOM, 32, PropModeReplace,828 XChangeProperty(m_pDisplay, m_wndProxy.hWnd, xAtom(XA_XdndAware), XA_ATOM, 32, PropModeReplace, 795 829 reinterpret_cast<unsigned char*>(&ver), 1); 796 830 } while (0); … … 890 924 RTStrFree(pszWndName); 891 925 892 uint16_t x = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatus Pt]);893 uint16_t y = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatus Pt]);894 uint16_t w = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatus Area]);895 uint16_t h = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatus Area]);926 uint16_t x = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]); 927 uint16_t y = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgXY]); 928 uint16_t w = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]); 929 uint16_t h = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusNoMsgWH]); 896 930 LogFlowThisFunc(("\tReported dead area: x=%RU16, y=%RU16, w=%RU16, h=%RU16\n", x, y, w, h)); 897 931 … … 952 986 char *pszWndName = wndX11GetNameA(wndSelection); 953 987 AssertPtr(pszWndName); 954 955 LogFlowThisFunc(("wndSelection=%#x ('%s'), wndProxy=%#x\n", wndSelection, pszWndName, m_wndProxy)); 956 988 LogFlowThisFunc(("wndSelection=%#x ('%s'), wndProxy=%#x\n", wndSelection, pszWndName, m_wndProxy.hWnd)); 957 989 RTStrFree(pszWndName); 958 990 959 mouseButtonSet(m_wndProxy , -1, -1, 1, true /* fPress */);991 mouseButtonSet(m_wndProxy.hWnd, -1, -1, 1, true /* fPress */); 960 992 961 993 /* … … 1022 1054 && m_wndCur == static_cast<Window>(e.xclient.data.l[XdndPositionWindow])) 1023 1055 { 1024 int32_t lPos = e.xclient.data.l[XdndPosition Coords];1056 int32_t lPos = e.xclient.data.l[XdndPositionXY]; 1025 1057 Atom atmAction = m_curVer >= 2 /* Actions other than "copy" or only supported since protocol version 2. */ 1026 1058 ? e.xclient.data.l[XdndPositionAction] : xAtom(XA_XdndActionCopy); 1027 1059 1028 1060 LogFlowThisFunc(("XA_XdndPosition: wndProxy=%#x, wndCur=%#x, x=%RI32, y=%RI32, strAction=%s\n", 1029 m_wndProxy , m_wndCur, RT_HIWORD(lPos), RT_LOWORD(lPos),1061 m_wndProxy.hWnd, m_wndCur, RT_HIWORD(lPos), RT_LOWORD(lPos), 1030 1062 xAtomToString(atmAction).c_str())); 1031 1063 … … 1041 1073 m.message_type = xAtom(XA_XdndStatus); 1042 1074 m.format = 32; 1043 m.data.l[XdndStatusWindow] = m_wndProxy; 1044 m.data.l[XdndStatusFlags] = fAcceptDrop ? RT_BIT(0) : 0; /* Whether to accept the drop or not. */ 1045 m.data.l[XdndStatusAction] = fAcceptDrop ? toAtomAction(DND_COPY_ACTION) : None; /** @todo Handle default action! */ 1075 m.data.l[XdndStatusWindow] = m_wndProxy.hWnd; 1076 m.data.l[XdndStatusFlags] = fAcceptDrop ? RT_BIT(0) : 0; /* Whether to accept the drop or not. */ 1077 1078 /* We don't want any new XA_XdndPosition messages while being 1079 * in our proxy window. */ 1080 m.data.l[XdndStatusNoMsgXY] = RT_MAKE_U32(m_wndProxy.iY, m_wndProxy.iX); 1081 m.data.l[XdndStatusNoMsgWH] = RT_MAKE_U32(m_wndProxy.iHeight, m_wndProxy.iWidth); 1082 1083 /** @todo Handle default action! */ 1084 m.data.l[XdndStatusAction] = fAcceptDrop ? toAtomAction(DND_COPY_ACTION) : None; 1046 1085 1047 1086 int xRc = XSendEvent(m_pDisplay, e.xclient.data.l[XdndPositionWindow], … … 1064 1103 { 1065 1104 LogFlowThisFunc(("XA_XdndDrop\n")); 1066 logInfo("Notified guest target window that drop operation is finished\n"); 1067 1068 m_eventQueueList.append(e); 1069 rc = RTSemEventSignal(m_eventQueueEvent); 1105 /* Can occur when dragging from guest->host, but then back in to the guest again. */ 1106 logInfo("Could not drop on own proxy window\n"); /* Not fatal. */ 1107 1108 /* Let the source know. */ 1109 rc = m_wndProxy.sendFinished(m_wndCur, DND_IGNORE_ACTION); 1110 1111 /* Start over. */ 1112 reset(); 1070 1113 } 1071 1114 else if ( e.xclient.message_type == xAtom(XA_XdndFinished) … … 1073 1116 { 1074 1117 LogFlowThisFunc(("XA_XdndFinished\n")); 1075 logInfo("Guest target window finished drag and drop operation\n"); 1076 1077 m_eventQueueList.append(e); 1078 rc = RTSemEventSignal(m_eventQueueEvent); 1118 logInfo("Finished drop on own proxy window\n"); /* Not fatal. */ 1119 1120 /* Let the source know. */ 1121 rc = m_wndProxy.sendFinished(m_wndCur, DND_IGNORE_ACTION); 1122 1123 /* Start over. */ 1124 reset(); 1079 1125 } 1080 1126 break; … … 1536 1582 if (m_lstFormats.size() > 3) 1537 1583 { 1538 rc = wndXDnDSetFormatList(m_wndProxy , xAtom(XA_XdndTypeList), m_lstFormats);1584 rc = wndXDnDSetFormatList(m_wndProxy.hWnd, xAtom(XA_XdndTypeList), m_lstFormats); 1539 1585 if (RT_FAILURE(rc)) 1540 1586 break; … … 1546 1592 if (RT_FAILURE(rc)) 1547 1593 break; 1548 rc = wndXDnDSetActionList(m_wndProxy , lstActions);1594 rc = wndXDnDSetActionList(m_wndProxy.hWnd, lstActions); 1549 1595 1550 1596 /* Set the DnD selection owner to our window. */ 1551 1597 /** @todo Don't use CurrentTime -- according to ICCCM section 2.1. */ 1552 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy , CurrentTime);1598 XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), m_wndProxy.hWnd, CurrentTime); 1553 1599 1554 1600 m_enmMode = HG; … … 1670 1716 m.message_type = xAtom(XA_XdndLeave); 1671 1717 m.format = 32; 1672 m.data.l[XdndLeaveWindow] = m_wndProxy ;1718 m.data.l[XdndLeaveWindow] = m_wndProxy.hWnd; 1673 1719 1674 1720 xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); … … 1707 1753 m.message_type = xAtom(XA_XdndEnter); 1708 1754 m.format = 32; 1709 m.data.l[XdndEnterWindow] = m_wndProxy ;1755 m.data.l[XdndEnterWindow] = m_wndProxy.hWnd; 1710 1756 m.data.l[XdndEnterFlags] = RT_MAKE_U32_FROM_U8( 1711 1757 /* Bit 0 is set if the source supports more than three data types. */ … … 1743 1789 m.message_type = xAtom(XA_XdndPosition); 1744 1790 m.format = 32; 1745 m.data.l[XdndPositionWindow] = m_wndProxy ;/* X window ID of source window. */1746 m.data.l[XdndPosition Coords]= RT_MAKE_U32(u32yPos, u32xPos); /* Cursor coordinates relative to the root window. */1791 m.data.l[XdndPositionWindow] = m_wndProxy.hWnd; /* X window ID of source window. */ 1792 m.data.l[XdndPositionXY] = RT_MAKE_U32(u32yPos, u32xPos); /* Cursor coordinates relative to the root window. */ 1747 1793 m.data.l[XdndPositionTimeStamp] = CurrentTime; /* Timestamp for retrieving data. */ 1748 1794 m.data.l[XdndPositionAction] = pa; /* Actions requested by the user. */ … … 1781 1827 int DragInstance::hgDrop(uint32_t u32xPos, uint32_t u32yPos, uint32_t uDefaultAction) 1782 1828 { 1783 LogFlowThisFunc(("wndCur=%#x, wndProxy=%#x, mode=%RU32, state=%RU32\n", m_wndCur, m_wndProxy , m_enmMode, m_enmState));1829 LogFlowThisFunc(("wndCur=%#x, wndProxy=%#x, mode=%RU32, state=%RU32\n", m_wndCur, m_wndProxy.hWnd, m_enmMode, m_enmState)); 1784 1830 LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uDefaultAction)); 1785 1831 … … 1878 1924 m.message_type = xAtom(XA_XdndDrop); 1879 1925 m.format = 32; 1880 m.data.l[XdndDropWindow] = m_wndProxy ; /* Source window. */1881 m.data.l[XdndDropFlags] = 0; /* Reserved for future use. */1882 m.data.l[XdndDropTimeStamp] = CurrentTime; /* Our DnD data does not rely on any timing, so just use the current time. */1926 m.data.l[XdndDropWindow] = m_wndProxy.hWnd; /* Source window. */ 1927 m.data.l[XdndDropFlags] = 0; /* Reserved for future use. */ 1928 m.data.l[XdndDropTimeStamp] = CurrentTime; /* Our DnD data does not rely on any timing, so just use the current time. */ 1883 1929 1884 1930 int xRc = XSendEvent(m_pDisplay, m_wndCur, False /* Propagate */, NoEventMask, reinterpret_cast<XEvent*>(&m)); … … 1902 1948 LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState)); 1903 1949 1950 int rc; 1951 1952 RTCString strFormats = "\r\n"; /** @todo If empty, IOCTL fails with VERR_ACCESS_DENIED. */ 1953 uint32_t uDefAction = DND_IGNORE_ACTION; 1954 uint32_t uAllActions = DND_IGNORE_ACTION; 1955 1904 1956 /* Currently in wrong mode? Bail out. */ 1905 1957 if (m_enmMode == HG) 1906 return VERR_INVALID_STATE; 1907 1958 rc = VERR_INVALID_STATE; 1908 1959 /* Message already processed successfully? */ 1909 if ( m_enmMode == GH 1910 && ( m_enmState == Dragging 1911 || m_enmState == Dropped) 1912 ) 1913 { 1914 return VERR_INVALID_STATE; 1915 } 1916 1917 int rc = VINF_SUCCESS; 1918 1919 /* Determine the current window which currently has the XdndSelection set. */ 1920 Window wndSelection = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 1921 LogFlowThisFunc(("wndSelection=%#x, wndProxy=%#x, wndCur=%#x\n", wndSelection, m_wndProxy, m_wndCur)); 1922 1923 RTCString strFormats = "None"; /** @todo If empty, IOCTL fails with VERR_ACCESS_DENIED. */ 1924 uint32_t uDefAction = DND_IGNORE_ACTION; 1925 uint32_t uAllActions = DND_IGNORE_ACTION; 1926 1927 /* Is this another window which has a Xdnd selection and not our proxy window? */ 1928 if ( wndSelection 1929 && wndSelection != m_wndCur) 1930 { 1931 #ifdef DEBUG 1932 char *pszWndName = wndX11GetNameA(wndSelection); 1933 AssertPtr(pszWndName); 1934 LogFlowThisFunc(("*** New source window ('%s') ***\n", pszWndName)); 1935 RTStrFree(pszWndName); 1936 #endif 1937 /* Start over. */ 1938 reset(); 1939 1940 /* Map the window on the current cursor position, which should provoke 1941 * an XdndEnter event. */ 1942 rc = proxyWinShow(NULL, NULL); 1943 if (RT_SUCCESS(rc)) 1960 else if ( m_enmMode == GH 1961 && ( m_enmState == Dragging 1962 || m_enmState == Dropped) 1963 ) 1964 { 1965 rc = VERR_INVALID_STATE; 1966 } 1967 else 1968 { 1969 /* Determine the current window which currently has the XdndSelection set. */ 1970 Window wndSelection = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection)); 1971 LogFlowThisFunc(("wndSelection=%#x, wndProxy=%#x, wndCur=%#x\n", wndSelection, m_wndProxy.hWnd, m_wndCur)); 1972 1973 /* Is this another window which has a Xdnd selection and not our proxy window? */ 1974 if ( wndSelection 1975 && wndSelection != m_wndCur) 1944 1976 { 1945 /* Wait until we're in "Dragging" state. */ 1946 rc = waitForStatusChange(Dragging, 5 * 1000); 1977 char *pszWndName = wndX11GetNameA(wndSelection); 1978 AssertPtr(pszWndName); 1979 logInfo("New guest source window %#x ('%s')\n", wndSelection, pszWndName); 1980 1981 /* Start over. */ 1982 reset(); 1983 1984 /* Map the window on the current cursor position, which should provoke 1985 * an XdndEnter event. */ 1986 rc = proxyWinShow(NULL, NULL); 1947 1987 if (RT_SUCCESS(rc)) 1948 m_enmMode = GH; 1988 { 1989 rc = mouseCursorFakeMove(); 1990 if (RT_SUCCESS(rc)) 1991 { 1992 /* Wait until we're in "Dragging" state. */ 1993 rc = waitForStatusChange(Dragging, 1000 /* 1s timeout */); 1994 } 1995 if (RT_SUCCESS(rc)) 1996 { 1997 m_enmMode = GH; 1998 } 1999 else 2000 logError("Error mapping proxy window to guest source window %#x ('%s'), rc=%Rrc\n", 2001 wndSelection, pszWndName, rc); 2002 } 2003 2004 RTStrFree(pszWndName); 1949 2005 } 1950 2006 } 1951 else1952 RTThreadSleep(3000);1953 2007 1954 2008 /* … … 1960 2014 if (RT_SUCCESS(rc2)) 1961 2015 { 1962 strFormats = gX11->xAtomListToString(m_lstFormats); 1963 if (strFormats.isEmpty()) 1964 strFormats = "\r\n"; /** @todo If empty, IOCTL fails with VERR_ACCESS_DENIED. */ 1965 uDefAction = DND_COPY_ACTION; /** @todo Handle default action! */ 1966 uAllActions = DND_COPY_ACTION; /** @todo Ditto. */ 1967 uAllActions |= toHGCMActions(m_lstActions); 2016 RTCString strFormatsCur = gX11->xAtomListToString(m_lstFormats); 2017 if (!strFormatsCur.isEmpty()) 2018 { 2019 strFormats = strFormatsCur; 2020 uDefAction = DND_COPY_ACTION; /** @todo Handle default action! */ 2021 uAllActions = DND_COPY_ACTION; /** @todo Ditto. */ 2022 uAllActions |= toHGCMActions(m_lstActions); 2023 } 1968 2024 1969 2025 RTCritSectLeave(&m_dataCS); … … 1980 2036 } 1981 2037 1982 if (RT_FAILURE(rc)) /* Start over on failure. */1983 reset();1984 1985 2038 LogFlowFuncLeaveRC(rc); 1986 2039 return rc; … … 2025 2078 XGetWindowAttributes(m_pDisplay, m_wndCur, &xwa); 2026 2079 LogFlowThisFunc(("wndProxy=%#x, wndCur=%#x, x=%d, y=%d, width=%d, height=%d\n", 2027 m_wndProxy , m_wndCur, xwa.x, xwa.y, xwa.width, xwa.height));2080 m_wndProxy.hWnd, m_wndCur, xwa.x, xwa.y, xwa.width, xwa.height)); 2028 2081 #endif 2029 2082 … … 2065 2118 2066 2119 XConvertSelection(m_pDisplay, xAtom(XA_XdndSelection), aFormat, xAtom(XA_XdndSelection), 2067 m_wndProxy , tsDrop);2120 m_wndProxy.hWnd, tsDrop); 2068 2121 2069 2122 /* Wait for the selection notify event. */ … … 2078 2131 && evSelNotify.xselection.display == m_pDisplay 2079 2132 && evSelNotify.xselection.selection == xAtom(XA_XdndSelection) 2080 && evSelNotify.xselection.requestor == m_wndProxy 2133 && evSelNotify.xselection.requestor == m_wndProxy.hWnd 2081 2134 && evSelNotify.xselection.target == aFormat) 2082 2135 { … … 2087 2140 unsigned long cItems, cbRemaining; 2088 2141 unsigned char *pcData = NULL; 2089 int xRc = XGetWindowProperty(m_pDisplay, m_wndProxy ,2142 int xRc = XGetWindowProperty(m_pDisplay, m_wndProxy.hWnd, 2090 2143 xAtom(XA_XdndSelection) /* Property */, 2091 2144 0 /* Offset */, … … 2096 2149 if (xRc != Success) 2097 2150 logError("Error getting XA_XdndSelection property of proxy window=%#x: %s\n", 2098 m_wndProxy , gX11->xErrorToString(xRc).c_str());2151 m_wndProxy.hWnd, gX11->xErrorToString(xRc).c_str()); 2099 2152 2100 2153 LogFlowThisFunc(("strType=%s, iPropFormat=%d, cItems=%RU32, cbRemaining=%RU32\n", … … 2132 2185 /* Send the raw data to the host. */ 2133 2186 rc = VbglR3DnDGHSendData(&m_dndCtx, strFormat.c_str(), pcData, cbData); 2187 LogFlowThisFunc(("Sent strFormat=%s, rc=%Rrc\n", strFormat.c_str(), rc)); 2134 2188 } 2135 2136 LogFlowThisFunc(("Sent strFormat=%s, rc=%Rrc\n", strFormat.c_str(), rc));2137 2189 2138 2190 if (RT_SUCCESS(rc)) 2139 2191 { 2140 /* Was the drop accepted by the host? That is, anything than ignoring. */ 2141 bool fDropAccepted = uAction > DND_IGNORE_ACTION; 2142 2143 /* Confirm the result of the transfer to the target window. */ 2144 XClientMessageEvent m; 2145 RT_ZERO(m); 2146 m.type = ClientMessage; 2147 m.display = m_pDisplay; 2148 m.window = wndSource; 2149 m.message_type = xAtom(XA_XdndFinished); 2150 m.format = 32; 2151 m.data.l[XdndFinishedWindow] = m_wndProxy; /* Target window. */ 2152 m.data.l[XdndFinishedFlags] = fDropAccepted ? RT_BIT(0) : 0; /* Was the drop accepted? */ 2153 m.data.l[XdndFinishedAction] = fDropAccepted ? toAtomAction(uAction) : None; /* Action used on accept. */ 2154 2155 xRc = XSendEvent(m_pDisplay, wndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 2156 if (xRc == 0) 2157 logError("Error sending XA_XdndFinished event to source window=%#x: %s\n", 2158 wndSource, gX11->xErrorToString(xRc).c_str()); 2192 rc = m_wndProxy.sendFinished(wndSource, uAction); 2159 2193 } 2160 2194 else … … 2182 2216 if (fCancel) 2183 2217 { 2184 LogFlowFunc(("Cancelling drop ...\n"));2218 logInfo("Cancelling dropping to host\n"); 2185 2219 2186 2220 /* Cancel the operation -- inform the source window by 2187 2221 * sending a XdndFinished message so that the source can toss the required data. */ 2188 XClientMessageEvent m; 2189 RT_ZERO(m); 2190 m.type = ClientMessage; 2191 m.display = m_pDisplay; 2192 m.window = m_wndProxy; 2193 m.message_type = xAtom(XA_XdndFinished); 2194 m.format = 32; 2195 m.data.l[XdndFinishedWindow] = m_wndProxy; /* Target window. */ 2196 m.data.l[XdndFinishedFlags] = 0; /* Did not accept the drop. */ 2197 m.data.l[XdndFinishedAction] = None; /* Action used on accept. */ 2198 2199 xRc = XSendEvent(m_pDisplay, wndSource, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 2200 if (xRc == 0) 2201 logError("Error sending XA_XdndFinished event to source window=%#x: %s\n", 2202 wndSource, gX11->xErrorToString(xRc).c_str()); 2222 rc = m_wndProxy.sendFinished(wndSource, DND_IGNORE_ACTION); 2203 2223 } 2204 2224 … … 2239 2259 2240 2260 /** 2261 * Fakes moving the mouse cursor to provoke various drag and drop 2262 * events such as entering a target window or moving within a 2263 * source window. 2264 * 2265 * Not the most elegant and probably correct function, but does 2266 * the work for now. 2267 * 2268 * @returns IPRT status code. 2269 */ 2270 int DragInstance::mouseCursorFakeMove(void) const 2271 { 2272 int iScreenID = XDefaultScreen(m_pDisplay); 2273 /** @todo What about multiple screens? Test this! */ 2274 2275 const int iScrX = XDisplayWidth(m_pDisplay, iScreenID); 2276 const int iScrY = XDisplayHeight(m_pDisplay, iScreenID); 2277 2278 int fx, fy, rx, ry; 2279 Window wndTemp, wndChild; 2280 int wx, wy; unsigned int mask; 2281 XQueryPointer(m_pDisplay, m_wndRoot, &wndTemp, &wndChild, &rx, &ry, &wx, &wy, &mask); 2282 2283 /* 2284 * Apply some simple clipping and change the position slightly. 2285 */ 2286 2287 /* FakeX */ 2288 if (rx == 0) fx = 1; 2289 else if (rx == iScrX) fx = iScrX - 1; 2290 else fx = rx + 1; 2291 2292 /* FakeY */ 2293 if (ry == 0) fy = 1; 2294 else if (ry == iScrY) fy = iScrY - 1; 2295 else fy = ry + 1; 2296 2297 /* 2298 * Move the cursor to trigger the wanted events. 2299 */ 2300 LogFlowThisFunc(("cursorRootX=%d, cursorRootY=%d\n", fx, fy)); 2301 int rc = mouseCursorMove(fx, fy); 2302 if (RT_SUCCESS(rc)) 2303 { 2304 /* Move the cursor back to its original position. */ 2305 rc = mouseCursorMove(rx, ry); 2306 } 2307 2308 return rc; 2309 } 2310 2311 /** 2241 2312 * Moves the mouse pointer to a specific position. 2242 2313 * … … 2250 2321 /** @todo What about multiple screens? Test this! */ 2251 2322 2252 const int iScrX = DisplayWidth(m_pDisplay, iScreenID);2323 const int iScrX = XDisplayWidth(m_pDisplay, iScreenID); 2253 2324 const int iScrY = XDisplayHeight(m_pDisplay, iScreenID); 2254 2325 … … 2393 2464 2394 2465 /* Bring our proxy window into foreground. */ 2395 XMapWindow(m_pDisplay, m_wndProxy );2396 XRaiseWindow(m_pDisplay, m_wndProxy );2466 XMapWindow(m_pDisplay, m_wndProxy.hWnd); 2467 XRaiseWindow(m_pDisplay, m_wndProxy.hWnd); 2397 2468 2398 2469 /* Spawn our proxy window over the entire screen, making it an easy drop target for the host's cursor. */ 2399 int iScreenID = XDefaultScreen(m_pDisplay); 2400 LogFlowThisFunc(("Proxy window screenID=%d, x=%d, y=%d, width=%d, height=%d\n", 2401 iScreenID, 0, 0, XDisplayWidth(m_pDisplay, iScreenID), XDisplayHeight(m_pDisplay, iScreenID))); 2402 XMoveResizeWindow(m_pDisplay, m_wndProxy, 0, 0, XDisplayWidth(m_pDisplay, iScreenID), XDisplayHeight(m_pDisplay, iScreenID)); 2403 /** @todo What about multiple screens? Test this! */ 2470 LogFlowThisFunc(("Proxy window x=%d, y=%d, width=%d, height=%d\n", 2471 m_wndProxy.iX, m_wndProxy.iY, m_wndProxy.iWidth, m_wndProxy.iHeight)); 2472 XMoveResizeWindow(m_pDisplay, m_wndProxy.hWnd, m_wndProxy.iX, m_wndProxy.iY, m_wndProxy.iWidth, m_wndProxy.iHeight); 2404 2473 2405 2474 XFlush(m_pDisplay); … … 2424 2493 LogFlowFuncEnter(); 2425 2494 2426 XUnmapWindow(m_pDisplay, m_wndProxy );2495 XUnmapWindow(m_pDisplay, m_wndProxy.hWnd); 2427 2496 XFlush(m_pDisplay); 2428 2497 … … 2748 2817 2749 2818 return uActions; 2819 } 2820 2821 /******************************************************************************* 2822 * VBoxDnDProxyWnd implementation. 2823 ******************************************************************************/ 2824 2825 VBoxDnDProxyWnd::VBoxDnDProxyWnd(void) 2826 : pDisp(NULL) 2827 , hWnd(0) 2828 , iX(0) 2829 , iY(0) 2830 , iWidth(0) 2831 , iHeight(0) 2832 { 2833 2834 } 2835 2836 VBoxDnDProxyWnd::~VBoxDnDProxyWnd(void) 2837 { 2838 destroy(); 2839 } 2840 2841 int VBoxDnDProxyWnd::init(Display *pDisplay) 2842 { 2843 /** @todo What about multiple screens? Test this! */ 2844 int iScreenID = XDefaultScreen(pDisplay); 2845 2846 iWidth = XDisplayWidth(pDisplay, iScreenID); 2847 iHeight = XDisplayHeight(pDisplay, iScreenID); 2848 pDisp = pDisplay; 2849 2850 return VINF_SUCCESS; 2851 } 2852 2853 void VBoxDnDProxyWnd::destroy(void) 2854 { 2855 2856 } 2857 2858 int VBoxDnDProxyWnd::sendFinished(Window hWndSource, uint32_t uAction) 2859 { 2860 /* Was the drop accepted by the host? That is, anything than ignoring. */ 2861 bool fDropAccepted = uAction > DND_IGNORE_ACTION; 2862 2863 /* Confirm the result of the transfer to the target window. */ 2864 XClientMessageEvent m; 2865 RT_ZERO(m); 2866 m.type = ClientMessage; 2867 m.display = pDisp; 2868 m.window = hWnd; 2869 m.message_type = xAtom(XA_XdndFinished); 2870 m.format = 32; 2871 m.data.l[XdndFinishedWindow] = hWnd; /* Target window. */ 2872 m.data.l[XdndFinishedFlags] = fDropAccepted ? RT_BIT(0) : 0; /* Was the drop accepted? */ 2873 m.data.l[XdndFinishedAction] = fDropAccepted ? DragInstance::toAtomAction(uAction) : None; /* Action used on accept. */ 2874 2875 int xRc = XSendEvent(pDisp, hWndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 2876 if (xRc == 0) 2877 { 2878 LogRel(("DnD: Error sending XA_XdndFinished event to source window=%#x: %s\n", 2879 hWndSource, gX11->xErrorToString(xRc).c_str())); 2880 2881 return VERR_GENERAL_FAILURE; /** @todo Fudge. */ 2882 } 2883 2884 return VINF_SUCCESS; 2750 2885 } 2751 2886
Note:
See TracChangeset
for help on using the changeset viewer.