VirtualBox

Ignore:
Timestamp:
Aug 12, 2015 10:31:53 AM (9 years ago)
Author:
vboxsync
Message:

DnD/VBoxClient: Be more responsive by splitting up failed guest->host dragging attempts, bail out from wrong dragging modes more gracefully.

File:
1 edited

Legend:

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

    r56781 r57283  
    571571    /** List of allowed formats. */
    572572    RTCList<RTCString>          m_lstAllowedFormats;
     573    /** Number of failed attempts by the host
     574     *  to query for an active drag and drop operation on the guest. */
     575    uint16_t                    m_cFailedPendingAttempts;
    573576};
    574577
     
    692695        m_enmMode   = Unknown;
    693696        m_eventQueueList.clear();
     697        m_cFailedPendingAttempts = 0;
    694698
    695699        /* Reset the selection request buffer. */
     
    10541058                     && m_wndCur               == static_cast<Window>(e.xclient.data.l[XdndPositionWindow]))
    10551059            {
     1060                if (m_enmState != Dragging) /* Wrong mode? Bail out. */
     1061                {
     1062                    reset();
     1063                    break;
     1064                }
     1065
    10561066                int32_t lPos      = e.xclient.data.l[XdndPositionXY];
    10571067                Atom    atmAction = m_curVer >= 2 /* Actions other than "copy" or only supported since protocol version 2. */
     
    11031113            {
    11041114                LogFlowThisFunc(("XA_XdndDrop\n"));
    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();
     1115
     1116                if (m_enmState != Dropped) /* Wrong mode? Bail out. */
     1117                {
     1118                    /* Can occur when dragging from guest->host, but then back in to the guest again. */
     1119                    logInfo("Could not drop on own proxy window\n"); /* Not fatal. */
     1120
     1121                    /* Let the source know. */
     1122                    rc = m_wndProxy.sendFinished(m_wndCur, DND_IGNORE_ACTION);
     1123
     1124                    /* Start over. */
     1125                    reset();
     1126                    break;
     1127                }
     1128
     1129                m_eventQueueList.append(e);
     1130                rc = RTSemEventSignal(m_eventQueueEvent);
    11131131            }
    1114             else if (   e.xclient.message_type == xAtom(XA_XdndFinished)
    1115                      && m_wndCur               == static_cast<Window>(e.xclient.data.l[XdndFinishedWindow]))
     1132            else
    11161133            {
    1117                 LogFlowThisFunc(("XA_XdndFinished\n"));
    1118                 logInfo("Finished drop on own proxy window\n"); /* Not fatal. */
     1134                logInfo("Unhandled event from wnd=%#x, msg=%s\n", e.xclient.window, xAtomToString(e.xclient.message_type).c_str());
    11191135
    11201136                /* Let the source know. */
     
    13541370    switch (e.type)
    13551371    {
     1372        /*
     1373         * This can happen if a guest->host drag operation
     1374         * goes back from the host to the guest. This is not what
     1375         * we want and thus resetting everything.
     1376         */
    13561377        case ButtonPress:
    1357             LogFlowThisFunc(("ButtonPress\n"));
     1378        case ButtonRelease:
     1379            LogFlowThisFunc(("Mouse button press/release\n"));
    13581380            rc = VINF_SUCCESS;
    1359             break;
    1360 
    1361         case ButtonRelease:
    1362             LogFlowThisFunc(("ButtonRelease\n"));
    1363             rc = VINF_SUCCESS;
     1381
     1382            reset();
    13641383            break;
    13651384
     
    19631982            )
    19641983    {
    1965         rc = VERR_INVALID_STATE;
     1984        /* No need to query for the source window again. */
     1985        rc = VINF_SUCCESS;
    19661986    }
    19671987    else
     
    19842004            /* Map the window on the current cursor position, which should provoke
    19852005             * an XdndEnter event. */
    1986             rc = proxyWinShow(NULL, NULL);
     2006            rc = proxyWinShow();
    19872007            if (RT_SUCCESS(rc))
    19882008            {
     
    19902010                if (RT_SUCCESS(rc))
    19912011                {
     2012                    bool fWaitFailed = false; /* Waiting for status changed failed? */
     2013
    19922014                    /* Wait until we're in "Dragging" state. */
    1993                     rc = waitForStatusChange(Dragging, 1000 /* 1s timeout */);
     2015                    rc = waitForStatusChange(Dragging, 100 /* 100ms timeout */);
     2016
     2017                    /*
     2018                     * Note: Don't wait too long here, as this mostly will make
     2019                     *       the drag and drop experience on the host being laggy
     2020                     *       and unresponsive.
     2021                     *
     2022                     *       Instead, let the host query multiple times with 100ms
     2023                     *       timeout each (see above) and only report an error if
     2024                     *       the overall querying time has been exceeded.<
     2025                     */
     2026                    if (RT_SUCCESS(rc))
     2027                    {
     2028                        m_enmMode = GH;
     2029                    }
     2030                    else if (rc == VERR_TIMEOUT)
     2031                    {
     2032                        /** @todo Make m_cFailedPendingAttempts configurable. For slower window managers? */
     2033                        if (m_cFailedPendingAttempts++ > 50) /* Tolerate up to 5s total (100ms for each slot). */
     2034                            fWaitFailed = true;
     2035                        else
     2036                            rc = VINF_SUCCESS;
     2037                    }
     2038                    else if (RT_FAILURE(rc))
     2039                        fWaitFailed = true;
     2040
     2041                    if (fWaitFailed)
     2042                    {
     2043                        logError("Error mapping proxy window to guest source window %#x ('%s'), rc=%Rrc\n",
     2044                                 wndSelection, pszWndName, rc);
     2045
     2046                        /* Reset the counter in any case. */
     2047                        m_cFailedPendingAttempts = 0;
     2048                    }
    19942049                }
    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);
    20022050            }
    20032051
     
    20702118    m_enmState = Dropped;
    20712119
    2072     /* Show the proxy window, so that the current source window will find it. */
    2073     int iRootX, iRootY;
    2074     proxyWinShow(&iRootX, &iRootY);
    2075 
    20762120#ifdef DEBUG
    20772121    XWindowAttributes xwa;
     
    20792123    LogFlowThisFunc(("wndProxy=%#x, wndCur=%#x, x=%d, y=%d, width=%d, height=%d\n",
    20802124                     m_wndProxy.hWnd, m_wndCur, xwa.x, xwa.y, xwa.width, xwa.height));
     2125
     2126    Window wndSelection = XGetSelectionOwner(m_pDisplay, xAtom(XA_XdndSelection));
     2127    LogFlowThisFunc(("wndSelection=%#x\n", wndSelection));
    20812128#endif
    20822129
    2083     /* We send a fake release event to the current window, cause
     2130    /* We send a fake mouse move event to the current window, cause
    20842131     * this should have the grab. */
    2085 #if 0
    2086     //mouseButtonSet(m_wndCur /* Destination window */, xwa.x + (xwa.width / 2), xwa.y + (xwa.height / 2), 1 /* Button */, false /* fPress */);
    2087 #else
    2088     mouseButtonSet(m_wndCur /* Destination window */, -1 /* Root X */, -1 /* Root Y */, 1 /* Button */, false /* fPress */);
    2089 #endif
     2132    mouseCursorFakeMove();
    20902133
    20912134    /**
     
    23662409        LogFlowThisFunc(("Note: XText extension not available or disabled\n"));
    23672410
     2411        unsigned int mask;
     2412
    23682413        if (   rx == -1
    23692414            && ry == -1)
    23702415        {
    2371             Window wndTemp, wndChild;
    2372             int wx, wy; unsigned int mask;
    2373             XQueryPointer(m_pDisplay, m_wndRoot, &wndTemp, &wndChild, &rx, &ry, &wx, &wy, &mask);
    2374             LogFlowThisFunc(("cursorRootX=%d, cursorRootY=%d\n", rx, ry));
     2416            Window wndRoot, wndChild;
     2417            int wx, wy;
     2418            XQueryPointer(m_pDisplay, m_wndRoot, &wndRoot, &wndChild, &rx, &ry, &wx, &wy, &mask);
     2419            LogFlowThisFunc(("Mouse pointer is at root x=%d, y=%d\n", rx, ry));
    23752420        }
    23762421
     
    23852430        eBtn.time         = CurrentTime;
    23862431        eBtn.button       = iButton;
    2387         eBtn.state       |= iButton == 1 ? Button1Mask /*:
    2388                             iButton == 2 ? Button2MotionMask :
    2389                             iButton == 3 ? Button3MotionMask :
    2390                             iButton == 4 ? Button4MotionMask :
    2391                             iButton == 5 ? Button5MotionMask*/ : 0;
     2432        eBtn.state        = mask | (iButton == 1 ? Button1MotionMask :
     2433                                    iButton == 2 ? Button2MotionMask :
     2434                                    iButton == 3 ? Button3MotionMask :
     2435                                    iButton == 4 ? Button4MotionMask :
     2436                                    iButton == 5 ? Button5MotionMask : 0);
    23922437        eBtn.type         = fPress ? ButtonPress : ButtonRelease;
    23932438        eBtn.send_event   = False;
     
    23962441
    23972442        XTranslateCoordinates(m_pDisplay, eBtn.root, eBtn.window, eBtn.x_root, eBtn.y_root, &eBtn.x, &eBtn.y, &eBtn.subwindow);
    2398         LogFlowThisFunc(("x=%d, y=%d\n", eBtn.x, eBtn.y));
    2399 #if 1
     2443        LogFlowThisFunc(("state=0x%x, x=%d, y=%d\n", eBtn.state, eBtn.x, eBtn.y));
     2444
    24002445        int xRc = XSendEvent(m_pDisplay, wndDest, True /* fPropagate */,
    2401                                fPress
    2402                              ? ButtonPressMask : ButtonReleaseMask,
     2446                             ButtonPressMask,
    24032447                             reinterpret_cast<XEvent*>(&eBtn));
    24042448        if (xRc == 0)
    24052449            logError("Error sending XButtonEvent event to window=%#x: %s\n", wndDest, gX11->xErrorToString(xRc).c_str());
    2406 #else
    2407         int xRc = XSendEvent(m_pDisplay, eBtn.window, False /* fPropagate */,
    2408                              0 /* Mask */, reinterpret_cast<XEvent*>(&eBtn));
    2409         if (xRc == 0)
    2410             logError("Error sending XButtonEvent event to window=%#x: %s\n", wndDest, gX11->xErrorToString(xRc).c_str());
    2411 #endif
     2450
     2451        XFlush(m_pDisplay);
    24122452
    24132453#ifdef VBOX_DND_WITH_XTEST
     
    28602900    /* Was the drop accepted by the host? That is, anything than ignoring. */
    28612901    bool fDropAccepted = uAction > DND_IGNORE_ACTION;
     2902
     2903    LogFlowFunc(("uAction=%RU32\n", uAction));
    28622904
    28632905    /* Confirm the result of the transfer to the target window. */
     
    28772919    {
    28782920        LogRel(("DnD: Error sending XA_XdndFinished event to source window=%#x: %s\n",
    2879                hWndSource, gX11->xErrorToString(xRc).c_str()));
     2921                hWndSource, gX11->xErrorToString(xRc).c_str()));
    28802922
    28812923        return VERR_GENERAL_FAILURE; /** @todo Fudge. */
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