VirtualBox

Ignore:
Timestamp:
Jul 3, 2015 12:58:05 PM (10 years ago)
Author:
vboxsync
Message:

DnD/VBoxClient: Bugfixes for stale/timing out proxy window move events , introduced VBoxDnDProxyWnd class.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp

    r56760 r56781  
    3434#include <limits.h>
    3535
    36 # ifdef LOG_GROUP
    37  # undef LOG_GROUP
    38 # endif
     36#ifdef LOG_GROUP
     37# undef LOG_GROUP
     38#endif
    3939#define LOG_GROUP LOG_GROUP_GUEST_DND
    4040#include <VBox/log.h>
     
    4242
    4343#include "VBox/HostServices/DragAndDropSvc.h"
    44 
    4544#include "VBoxClient.h"
    4645
     
    174173    XdndPositionWindow = 0,         /* Source window (sender). */
    175174    XdndPositionFlags,              /* Flags. */
    176     XdndPositionCoords,             /* 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. */
    177176    XdndPositionTimeStamp,          /* Time stamp for retrieving the data. */
    178177    XdndPositionAction,             /* Action requested by the user. */
     
    181180    XdndStatusWindow = 0,           /* Target window (sender).*/
    182181    XdndStatusFlags,                /* Flags returned by target. */
    183     XdndStatusPt,                   /* X + Y of "no msg" rectangle (root window coords). */
    184     XdndStatusArea,                 /* 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. */
    185184    XdndStatusAction,               /* Action accepted by target. */
    186185
     
    410409#endif
    411410
     411/** @todo Move all proxy window-related stuff into this class! Clean up this mess. */
     412class VBoxDnDProxyWnd
     413{
     414
     415public:
     416
     417    VBoxDnDProxyWnd(void);
     418
     419    virtual ~VBoxDnDProxyWnd(void);
     420
     421public:
     422
     423    int init(Display *pDisplay);
     424    void destroy();
     425
     426    int sendFinished(Window hWndSource, uint32_t uAction);
     427
     428public:
     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
    412439/**
    413440 * Class for handling a single drag and drop operation, that is,
     
    474501
    475502    /* X11 helpers. */
     503    int  mouseCursorFakeMove(void) const;
    476504    int  mouseCursorMove(int iPosX, int iPosY) const;
    477505    void mouseButtonSet(Window wndDest, int rx, int ry, int iButton, bool fPress);
     
    512540    /** Root window handle. */
    513541    Window                      m_wndRoot;
    514     /** Proxy window handle. */
    515     Window                      m_wndProxy;
     542    /** Proxy window. */
     543    VBoxDnDProxyWnd             m_wndProxy;
    516544    /** Current source/target window handle. */
    517545    Window                      m_wndCur;
     
    600628    , m_pScreen(0)
    601629    , m_wndRoot(0)
    602     , m_wndProxy(0)
    603630    , m_wndCur(0)
    604631    , m_curVer(-1)
     
    617644    LogFlowFuncEnter();
    618645
    619     if (m_wndProxy != 0)
    620         XDestroyWindow(m_pDisplay, m_wndProxy);
     646    if (m_wndProxy.hWnd != 0)
     647        XDestroyWindow(m_pDisplay, m_wndProxy.hWnd);
    621648
    622649    int rc2 = VbglR3DnDDisconnect(&m_dndCtx);
     
    650677        /* If we are currently the Xdnd selection owner, clear that. */
    651678        Window pWnd = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
    652         if (pWnd == m_wndProxy)
     679        if (pWnd == m_wndProxy.hWnd)
    653680            XSetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection), None, CurrentTime);
    654681
    655682        /* 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);
    658685
    659686        /* Reset the internal state. */
     
    749776        attr.background_pixel      = XWhitePixel(m_pDisplay, m_screenId);
    750777        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 */,
    752779                                   100, 100,                                 /* Position */
    753780                                   100, 100,                                 /* Width + height */
     
    762789                                   &attr);                                   /* Attributes for value mask */
    763790#else
    764         m_wndProxy = XCreateWindow(m_pDisplay, m_wndRoot                 /* Parent */,
     791        m_wndProxy.hWnd = XCreateWindow(m_pDisplay, m_wndRoot            /* Parent */,
    765792                                   0, 0,                                 /* Position */
    766793                                   1, 1,                                 /* Width + height */
     
    772799                                   &attr);                               /* Attributes for value mask */
    773800#endif
    774         if (!m_wndProxy)
     801        if (!m_wndProxy.hWnd)
    775802        {
    776803            LogRel(("DnD: Error creating proxy window\n"));
     
    779806        }
    780807
     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
    781815#ifdef VBOX_DND_DEBUG_WND
    782816        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);
    785819        XFlush(m_pDisplay);
    786820#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);
    788822
    789823        /* Set the window's name for easier lookup. */
    790         XStoreName(m_pDisplay, m_wndProxy, "VBoxClientWndDnD");
     824        XStoreName(m_pDisplay, m_wndProxy.hWnd, "VBoxClientWndDnD");
    791825
    792826        /* Make the new window Xdnd aware. */
    793827        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,
    795829                        reinterpret_cast<unsigned char*>(&ver), 1);
    796830    } while (0);
     
    890924                RTStrFree(pszWndName);
    891925
    892                 uint16_t x = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusPt]);
    893                 uint16_t y = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusPt]);
    894                 uint16_t w = RT_HI_U16((uint32_t)e.xclient.data.l[XdndStatusArea]);
    895                 uint16_t h = RT_LO_U16((uint32_t)e.xclient.data.l[XdndStatusArea]);
     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]);
    896930                LogFlowThisFunc(("\tReported dead area: x=%RU16, y=%RU16, w=%RU16, h=%RU16\n", x, y, w, h));
    897931
     
    952986                char *pszWndName = wndX11GetNameA(wndSelection);
    953987                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));
    957989                RTStrFree(pszWndName);
    958990
    959                 mouseButtonSet(m_wndProxy, -1, -1, 1, true /* fPress */);
     991                mouseButtonSet(m_wndProxy.hWnd, -1, -1, 1, true /* fPress */);
    960992
    961993                /*
     
    10221054                     && m_wndCur               == static_cast<Window>(e.xclient.data.l[XdndPositionWindow]))
    10231055            {
    1024                 int32_t lPos      = e.xclient.data.l[XdndPositionCoords];
     1056                int32_t lPos      = e.xclient.data.l[XdndPositionXY];
    10251057                Atom    atmAction = m_curVer >= 2 /* Actions other than "copy" or only supported since protocol version 2. */
    10261058                                  ? e.xclient.data.l[XdndPositionAction] : xAtom(XA_XdndActionCopy);
    10271059
    10281060                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),
    10301062                                 xAtomToString(atmAction).c_str()));
    10311063
     
    10411073                m.message_type = xAtom(XA_XdndStatus);
    10421074                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;
    10461085
    10471086                int xRc = XSendEvent(m_pDisplay, e.xclient.data.l[XdndPositionWindow],
     
    10641103            {
    10651104                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();
    10701113            }
    10711114            else if (   e.xclient.message_type == xAtom(XA_XdndFinished)
     
    10731116            {
    10741117                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();
    10791125            }
    10801126            break;
     
    15361582        if (m_lstFormats.size() > 3)
    15371583        {
    1538             rc = wndXDnDSetFormatList(m_wndProxy, xAtom(XA_XdndTypeList), m_lstFormats);
     1584            rc = wndXDnDSetFormatList(m_wndProxy.hWnd, xAtom(XA_XdndTypeList), m_lstFormats);
    15391585            if (RT_FAILURE(rc))
    15401586                break;
     
    15461592        if (RT_FAILURE(rc))
    15471593            break;
    1548         rc = wndXDnDSetActionList(m_wndProxy, lstActions);
     1594        rc = wndXDnDSetActionList(m_wndProxy.hWnd, lstActions);
    15491595
    15501596        /* Set the DnD selection owner to our window. */
    15511597        /** @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);
    15531599
    15541600        m_enmMode  = HG;
     
    16701716        m.message_type            = xAtom(XA_XdndLeave);
    16711717        m.format                  = 32;
    1672         m.data.l[XdndLeaveWindow] = m_wndProxy;
     1718        m.data.l[XdndLeaveWindow] = m_wndProxy.hWnd;
    16731719
    16741720        xRc = XSendEvent(m_pDisplay, m_wndCur, False, NoEventMask, reinterpret_cast<XEvent*>(&m));
     
    17071753        m.message_type = xAtom(XA_XdndEnter);
    17081754        m.format       = 32;
    1709         m.data.l[XdndEnterWindow] = m_wndProxy;
     1755        m.data.l[XdndEnterWindow] = m_wndProxy.hWnd;
    17101756        m.data.l[XdndEnterFlags]  = RT_MAKE_U32_FROM_U8(
    17111757                                    /* Bit 0 is set if the source supports more than three data types. */
     
    17431789        m.message_type = xAtom(XA_XdndPosition);
    17441790        m.format       = 32;
    1745         m.data.l[XdndPositionWindow]    = m_wndProxy;                    /* X window ID of source window. */
    1746         m.data.l[XdndPositionCoords]    = 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. */
    17471793        m.data.l[XdndPositionTimeStamp] = CurrentTime;                   /* Timestamp for retrieving data. */
    17481794        m.data.l[XdndPositionAction]    = pa;                            /* Actions requested by the user. */
     
    17811827int DragInstance::hgDrop(uint32_t u32xPos, uint32_t u32yPos, uint32_t uDefaultAction)
    17821828{
    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));
    17841830    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=%RU32\n", u32xPos, u32yPos, uDefaultAction));
    17851831
     
    18781924    m.message_type = xAtom(XA_XdndDrop);
    18791925    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. */
    18831929
    18841930    int xRc = XSendEvent(m_pDisplay, m_wndCur, False /* Propagate */, NoEventMask, reinterpret_cast<XEvent*>(&m));
     
    19021948    LogFlowThisFunc(("mode=%RU32, state=%RU32\n", m_enmMode, m_enmState));
    19031949
     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
    19041956    /* Currently in wrong mode? Bail out. */
    19051957    if (m_enmMode == HG)
    1906         return VERR_INVALID_STATE;
    1907 
     1958        rc = VERR_INVALID_STATE;
    19081959    /* 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)
    19441976        {
    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);
    19471987            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);
    19492005        }
    19502006    }
    1951     else
    1952         RTThreadSleep(3000);
    19532007
    19542008    /*
     
    19602014    if (RT_SUCCESS(rc2))
    19612015    {
    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        }
    19682024
    19692025        RTCritSectLeave(&m_dataCS);
     
    19802036    }
    19812037
    1982     if (RT_FAILURE(rc)) /* Start over on failure. */
    1983         reset();
    1984 
    19852038    LogFlowFuncLeaveRC(rc);
    19862039    return rc;
     
    20252078    XGetWindowAttributes(m_pDisplay, m_wndCur, &xwa);
    20262079    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));
    20282081#endif
    20292082
     
    20652118
    20662119        XConvertSelection(m_pDisplay, xAtom(XA_XdndSelection), aFormat, xAtom(XA_XdndSelection),
    2067                           m_wndProxy, tsDrop);
     2120                          m_wndProxy.hWnd, tsDrop);
    20682121
    20692122        /* Wait for the selection notify event. */
     
    20782131                && evSelNotify.xselection.display   == m_pDisplay
    20792132                && evSelNotify.xselection.selection == xAtom(XA_XdndSelection)
    2080                 && evSelNotify.xselection.requestor == m_wndProxy
     2133                && evSelNotify.xselection.requestor == m_wndProxy.hWnd
    20812134                && evSelNotify.xselection.target    == aFormat)
    20822135            {
     
    20872140                unsigned long cItems, cbRemaining;
    20882141                unsigned char *pcData = NULL;
    2089                 int xRc = XGetWindowProperty(m_pDisplay, m_wndProxy,
     2142                int xRc = XGetWindowProperty(m_pDisplay, m_wndProxy.hWnd,
    20902143                                             xAtom(XA_XdndSelection)  /* Property */,
    20912144                                             0                        /* Offset */,
     
    20962149                if (xRc != Success)
    20972150                    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());
    20992152
    21002153                LogFlowThisFunc(("strType=%s, iPropFormat=%d, cItems=%RU32, cbRemaining=%RU32\n",
     
    21322185                        /* Send the raw data to the host. */
    21332186                        rc = VbglR3DnDGHSendData(&m_dndCtx, strFormat.c_str(), pcData, cbData);
     2187                        LogFlowThisFunc(("Sent strFormat=%s, rc=%Rrc\n", strFormat.c_str(), rc));
    21342188                    }
    2135 
    2136                     LogFlowThisFunc(("Sent strFormat=%s, rc=%Rrc\n", strFormat.c_str(), rc));
    21372189
    21382190                    if (RT_SUCCESS(rc))
    21392191                    {
    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);
    21592193                    }
    21602194                    else
     
    21822216                if (fCancel)
    21832217                {
    2184                     LogFlowFunc(("Cancelling drop ...\n"));
     2218                    logInfo("Cancelling dropping to host\n");
    21852219
    21862220                    /* Cancel the operation -- inform the source window by
    21872221                     * 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);
    22032223                }
    22042224
     
    22392259
    22402260/**
     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 */
     2270int 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/**
    22412312 * Moves the mouse pointer to a specific position.
    22422313 *
     
    22502321    /** @todo What about multiple screens? Test this! */
    22512322
    2252     const int iScrX = DisplayWidth(m_pDisplay, iScreenID);
     2323    const int iScrX = XDisplayWidth(m_pDisplay, iScreenID);
    22532324    const int iScrY = XDisplayHeight(m_pDisplay, iScreenID);
    22542325
     
    23932464
    23942465    /* 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);
    23972468
    23982469    /* 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);
    24042473
    24052474    XFlush(m_pDisplay);
     
    24242493    LogFlowFuncEnter();
    24252494
    2426     XUnmapWindow(m_pDisplay, m_wndProxy);
     2495    XUnmapWindow(m_pDisplay, m_wndProxy.hWnd);
    24272496    XFlush(m_pDisplay);
    24282497
     
    27482817
    27492818    return uActions;
     2819}
     2820
     2821/*******************************************************************************
     2822 * VBoxDnDProxyWnd implementation.
     2823 ******************************************************************************/
     2824
     2825VBoxDnDProxyWnd::VBoxDnDProxyWnd(void)
     2826    : pDisp(NULL)
     2827    , hWnd(0)
     2828    , iX(0)
     2829    , iY(0)
     2830    , iWidth(0)
     2831    , iHeight(0)
     2832{
     2833
     2834}
     2835
     2836VBoxDnDProxyWnd::~VBoxDnDProxyWnd(void)
     2837{
     2838    destroy();
     2839}
     2840
     2841int 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
     2853void VBoxDnDProxyWnd::destroy(void)
     2854{
     2855
     2856}
     2857
     2858int 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;
    27502885}
    27512886
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette