VirtualBox

Ignore:
Timestamp:
Dec 5, 2022 9:00:05 AM (2 years ago)
Author:
vboxsync
Message:

DnD/VBoxClient: Revamped the X11/HGCM event handling so that it can handle more than one event per signalling the event. Also, don't clear the event queue implicitly in DragInstance::proxyWinHide(), to avoid any (unwanted) side effects (use DragInstance::reset() for that).

File:
1 edited

Legend:

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

    r97739 r97740  
    821821        m_cFailedPendingAttempts = 0;
    822822
    823         m_eventQueueList.clear();
    824 
    825823        /* Reset the selection request buffer. */
    826824        if (m_pvSelReqData)
     
    831829            Assert(m_cbSelReqData);
    832830            m_cbSelReqData = 0;
     831        }
     832
     833        rc2 = RTCritSectEnter(&m_eventQueueCS);
     834        if (RT_SUCCESS(rc2))
     835        {
     836            m_eventQueueList.clear();
     837
     838            rc2 = RTCritSectLeave(&m_eventQueueCS);
     839            AssertRC(rc2);
    833840        }
    834841
     
    28302837    XFlush(m_pDisplay);
    28312838
    2832     m_eventQueueList.clear();
    2833 
    28342839    return VINF_SUCCESS; /** @todo Add error checking. */
    28352840}
     
    33193324            RT_ZERO(e);
    33203325
    3321             LogFlowFunc(("Waiting for new event ...\n"));
     3326            LogFlowFunc(("Waiting for new events ...\n"));
    33223327            rc = RTSemEventWait(m_hEventSem, RT_INDEFINITE_WAIT);
    33233328            if (RT_FAILURE(rc))
    33243329                break;
    33253330
    3326             AssertMsg(m_eventQueue.size(), ("Event queue is empty when it shouldn't\n"));
    3327 
    3328             e = m_eventQueue.first();
    3329             m_eventQueue.removeFirst();
    3330 
    3331             if (e.enmType == DNDEVENT::DnDEventType_HGCM)
     3331            size_t cEvents = 0;
     3332
     3333            int rc2 = RTCritSectEnter(&m_eventQueueCS);
     3334            if (RT_SUCCESS(rc2))
    33323335            {
    3333                 PVBGLR3DNDEVENT pVbglR3Event = e.hgcm;
    3334                 AssertPtrBreak(pVbglR3Event);
    3335 
    3336                 LogFlowThisFunc(("HGCM event, enmType=%RU32\n", pVbglR3Event->enmType));
    3337                 switch (pVbglR3Event->enmType)
     3336                cEvents = m_eventQueue.size();
     3337
     3338                rc2 = RTCritSectLeave(&m_eventQueueCS);
     3339                AssertRC(rc2);
     3340            }
     3341
     3342            while (cEvents)
     3343            {
     3344                rc2 = RTCritSectEnter(&m_eventQueueCS);
     3345                if (RT_SUCCESS(rc2))
    33383346                {
    3339                     case VBGLR3DNDEVENTTYPE_HG_ENTER:
     3347                    if (m_eventQueue.isEmpty())
    33403348                    {
    3341                         if (pVbglR3Event->u.HG_Enter.cbFormats)
     3349                        rc2 = RTCritSectLeave(&m_eventQueueCS);
     3350                        AssertRC(rc2);
     3351                        break;
     3352                    }
     3353
     3354                    e = m_eventQueue.first();
     3355                    m_eventQueue.removeFirst();
     3356
     3357                    rc2 = RTCritSectLeave(&m_eventQueueCS);
     3358                    AssertRC(rc2);
     3359                }
     3360
     3361                if (e.enmType == DNDEVENT::DnDEventType_HGCM)
     3362                {
     3363                    PVBGLR3DNDEVENT pVbglR3Event = e.hgcm;
     3364                    AssertPtrBreak(pVbglR3Event);
     3365
     3366                    LogFlowThisFunc(("HGCM event enmType=%RU32\n", pVbglR3Event->enmType));
     3367                    switch (pVbglR3Event->enmType)
     3368                    {
     3369                        case VBGLR3DNDEVENTTYPE_HG_ENTER:
    33423370                        {
    3343                             RTCList<RTCString> lstFormats =
    3344                                 RTCString(pVbglR3Event->u.HG_Enter.pszFormats, pVbglR3Event->u.HG_Enter.cbFormats - 1).split("\r\n");
    3345                             rc = m_pCurDnD->hgEnter(lstFormats, pVbglR3Event->u.HG_Enter.dndLstActionsAllowed);
    3346                             if (RT_FAILURE(rc))
     3371                            if (pVbglR3Event->u.HG_Enter.cbFormats)
     3372                            {
     3373                                RTCList<RTCString> lstFormats =
     3374                                    RTCString(pVbglR3Event->u.HG_Enter.pszFormats, pVbglR3Event->u.HG_Enter.cbFormats - 1).split("\r\n");
     3375                                rc = m_pCurDnD->hgEnter(lstFormats, pVbglR3Event->u.HG_Enter.dndLstActionsAllowed);
     3376                                if (RT_FAILURE(rc))
     3377                                    break;
     3378                                /* Enter is always followed by a move event. */
     3379                            }
     3380                            else
     3381                            {
     3382                                AssertMsgFailed(("cbFormats is 0\n"));
     3383                                rc = VERR_INVALID_PARAMETER;
    33473384                                break;
    3348                             /* Enter is always followed by a move event. */
     3385                            }
     3386
     3387                            /* Note: After HOST_DND_FN_HG_EVT_ENTER there immediately is a move
     3388                             *       event, so fall through is intentional here. */
     3389                            RT_FALL_THROUGH();
    33493390                        }
    3350                         else
     3391
     3392                        case VBGLR3DNDEVENTTYPE_HG_MOVE:
    33513393                        {
    3352                             AssertMsgFailed(("cbFormats is 0\n"));
    3353                             rc = VERR_INVALID_PARAMETER;
     3394                            rc = m_pCurDnD->hgMove(pVbglR3Event->u.HG_Move.uXpos, pVbglR3Event->u.HG_Move.uYpos,
     3395                                                   pVbglR3Event->u.HG_Move.dndActionDefault);
    33543396                            break;
    33553397                        }
    33563398
    3357                         /* Note: After HOST_DND_FN_HG_EVT_ENTER there immediately is a move
    3358                          *       event, so fall through is intentional here. */
    3359                         RT_FALL_THROUGH();
     3399                        case VBGLR3DNDEVENTTYPE_HG_LEAVE:
     3400                        {
     3401                            rc = m_pCurDnD->hgLeave();
     3402                            break;
     3403                        }
     3404
     3405                        case VBGLR3DNDEVENTTYPE_HG_DROP:
     3406                        {
     3407                            rc = m_pCurDnD->hgDrop(pVbglR3Event->u.HG_Drop.uXpos, pVbglR3Event->u.HG_Drop.uYpos,
     3408                                                   pVbglR3Event->u.HG_Drop.dndActionDefault);
     3409                            break;
     3410                        }
     3411
     3412                        /* Note: VbglR3DnDRecvNextMsg() will return HOST_DND_FN_HG_SND_DATA_HDR when
     3413                         *       the host has finished copying over all the data to the guest.
     3414                         *
     3415                         *       The actual data transfer (and message processing for it) will be done
     3416                         *       internally by VbglR3DnDRecvNextMsg() to not duplicate any code for different
     3417                         *       platforms.
     3418                         *
     3419                         *       The data header now will contain all the (meta) data the guest needs in
     3420                         *       order to complete the DnD operation. */
     3421                        case VBGLR3DNDEVENTTYPE_HG_RECEIVE:
     3422                        {
     3423                            rc = m_pCurDnD->hgDataReceive(&pVbglR3Event->u.HG_Received.Meta);
     3424                            break;
     3425                        }
     3426
     3427                        case VBGLR3DNDEVENTTYPE_HG_CANCEL:
     3428                        {
     3429                            m_pCurDnD->reset(); /** @todo Test this! */
     3430                            break;
     3431                        }
     3432
     3433#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     3434                        case VBGLR3DNDEVENTTYPE_GH_ERROR:
     3435                        {
     3436                            m_pCurDnD->reset();
     3437                            break;
     3438                        }
     3439
     3440                        case VBGLR3DNDEVENTTYPE_GH_REQ_PENDING:
     3441                        {
     3442                            rc = m_pCurDnD->ghIsDnDPending();
     3443                            break;
     3444                        }
     3445
     3446                        case VBGLR3DNDEVENTTYPE_GH_DROP:
     3447                        {
     3448                            rc = m_pCurDnD->ghDropped(pVbglR3Event->u.GH_Drop.pszFormat, pVbglR3Event->u.GH_Drop.dndActionRequested);
     3449                            break;
     3450                        }
     3451#endif
     3452                        case VBGLR3DNDEVENTTYPE_QUIT:
     3453                        {
     3454                            rc = VINF_SUCCESS;
     3455                            break;
     3456                        }
     3457
     3458                        default:
     3459                        {
     3460                            VBClLogError("Received unsupported message type %RU32\n", pVbglR3Event->enmType);
     3461                            rc = VERR_NOT_SUPPORTED;
     3462                            break;
     3463                        }
    33603464                    }
    33613465
    3362                     case VBGLR3DNDEVENTTYPE_HG_MOVE:
     3466                    LogFlowFunc(("Message %RU32 processed with %Rrc\n", pVbglR3Event->enmType, rc));
     3467                    if (RT_FAILURE(rc))
    33633468                    {
    3364                         rc = m_pCurDnD->hgMove(pVbglR3Event->u.HG_Move.uXpos, pVbglR3Event->u.HG_Move.uYpos,
    3365                                                pVbglR3Event->u.HG_Move.dndActionDefault);
     3469                        /* Tell the user. */
     3470                        VBClLogError("Processing message %RU32 failed with %Rrc\n", pVbglR3Event->enmType, rc);
     3471
     3472                        /* If anything went wrong, do a reset and start over. */
     3473                        reset();
     3474                    }
     3475
     3476                    const bool fQuit = pVbglR3Event->enmType == VBGLR3DNDEVENTTYPE_QUIT;
     3477
     3478                    VbglR3DnDEventFree(e.hgcm);
     3479                    e.hgcm = NULL;
     3480
     3481                    if (fQuit)
    33663482                        break;
    3367                     }
    3368 
    3369                     case VBGLR3DNDEVENTTYPE_HG_LEAVE:
    3370                     {
    3371                         rc = m_pCurDnD->hgLeave();
    3372                         break;
    3373                     }
    3374 
    3375                     case VBGLR3DNDEVENTTYPE_HG_DROP:
    3376                     {
    3377                         rc = m_pCurDnD->hgDrop(pVbglR3Event->u.HG_Drop.uXpos, pVbglR3Event->u.HG_Drop.uYpos,
    3378                                                pVbglR3Event->u.HG_Drop.dndActionDefault);
    3379                         break;
    3380                     }
    3381 
    3382                     /* Note: VbglR3DnDRecvNextMsg() will return HOST_DND_FN_HG_SND_DATA_HDR when
    3383                      *       the host has finished copying over all the data to the guest.
    3384                      *
    3385                      *       The actual data transfer (and message processing for it) will be done
    3386                      *       internally by VbglR3DnDRecvNextMsg() to not duplicate any code for different
    3387                      *       platforms.
    3388                      *
    3389                      *       The data header now will contain all the (meta) data the guest needs in
    3390                      *       order to complete the DnD operation. */
    3391                     case VBGLR3DNDEVENTTYPE_HG_RECEIVE:
    3392                     {
    3393                         rc = m_pCurDnD->hgDataReceive(&pVbglR3Event->u.HG_Received.Meta);
    3394                         break;
    3395                     }
    3396 
    3397                     case VBGLR3DNDEVENTTYPE_HG_CANCEL:
    3398                     {
    3399                         m_pCurDnD->reset(); /** @todo Test this! */
    3400                         break;
    3401                     }
    3402 
    3403 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    3404                     case VBGLR3DNDEVENTTYPE_GH_ERROR:
    3405                     {
    3406                         m_pCurDnD->reset();
    3407                         break;
    3408                     }
    3409 
    3410                     case VBGLR3DNDEVENTTYPE_GH_REQ_PENDING:
    3411                     {
    3412                         rc = m_pCurDnD->ghIsDnDPending();
    3413                         break;
    3414                     }
    3415 
    3416                     case VBGLR3DNDEVENTTYPE_GH_DROP:
    3417                     {
    3418                         rc = m_pCurDnD->ghDropped(pVbglR3Event->u.GH_Drop.pszFormat, pVbglR3Event->u.GH_Drop.dndActionRequested);
    3419                         break;
    3420                     }
    3421 #endif
    3422                     case VBGLR3DNDEVENTTYPE_QUIT:
    3423                     {
    3424                         rc = VINF_SUCCESS;
    3425                         break;
    3426                     }
    3427 
    3428                     default:
    3429                     {
    3430                         VBClLogError("Received unsupported message type %RU32\n", pVbglR3Event->enmType);
    3431                         rc = VERR_NOT_SUPPORTED;
    3432                         break;
    3433                     }
    34343483                }
    3435 
    3436                 LogFlowFunc(("Message %RU32 processed with %Rrc\n", pVbglR3Event->enmType, rc));
    3437                 if (RT_FAILURE(rc))
     3484                else if (e.enmType == DNDEVENT::DnDEventType_X11)
    34383485                {
    3439                     /* Tell the user. */
    3440                     VBClLogError("Processing message %RU32 failed with %Rrc\n", pVbglR3Event->enmType, rc);
    3441 
    3442                     /* If anything went wrong, do a reset and start over. */
    3443                     m_pCurDnD->reset();
     3486                    LogFlowThisFunc(("X11 event (type %#x)\n", e.x11.type));
     3487                    m_pCurDnD->onX11Event(e.x11);
    34443488                }
    3445 
    3446                 const bool fQuit = pVbglR3Event->enmType == VBGLR3DNDEVENTTYPE_QUIT;
    3447 
    3448                 VbglR3DnDEventFree(e.hgcm);
    3449                 e.hgcm = NULL;
    3450 
    3451                 if (fQuit)
    3452                     break;
    3453             }
    3454             else if (e.enmType == DNDEVENT::DnDEventType_X11)
    3455             {
    3456                 m_pCurDnD->onX11Event(e.x11);
    3457             }
    3458             else
    3459                 AssertMsgFailed(("Unknown event queue type %RU32\n", e.enmType));
     3489                else
     3490                    AssertMsgFailed(("Unknown event queue type %RU32\n", e.enmType));
     3491
     3492                --cEvents;
     3493
     3494            } /* for */
    34603495
    34613496            /*
     
    36383673        {
    36393674            cMsgSkippedInvalid = 0; /* Reset skipped messages count. */
    3640             pThis->m_eventQueue.append(e);
     3675
     3676            int rc2 = RTCritSectEnter(&pThis->m_eventQueueCS);
     3677            if (RT_SUCCESS(rc2))
     3678            {
     3679                VBClLogVerbose(2, "Received new HGCM message (type %#x)\n", e.hgcm->enmType);
     3680
     3681                pThis->m_eventQueue.append(e);
     3682
     3683                rc2 = RTCritSectLeave(&pThis->m_eventQueueCS);
     3684                AssertRC(rc2);
     3685            }
    36413686
    36423687            rc = RTSemEventSignal(pThis->m_hEventSem);
     
    36933738
    36943739    DNDEVENT e;
     3740    RT_ZERO(e);
     3741    e.enmType = DNDEVENT::DnDEventType_X11;
     3742
    36953743    do
    36963744    {
     
    37023750         * of time.
    37033751         */
    3704         if (XEventsQueued(pThis->m_pDisplay, QueuedAfterFlush) > 0)
    3705         {
    3706             RT_ZERO(e);
    3707             e.enmType = DNDEVENT::DnDEventType_X11;
    3708 
     3752        unsigned cNewEvents = 0;
     3753        unsigned cQueued    = XEventsQueued(pThis->m_pDisplay, QueuedAfterFlush);
     3754        while (cQueued)
     3755        {
    37093756            /* XNextEvent will block until a new X event becomes available. */
    37103757            XNextEvent(pThis->m_pDisplay, &e.x11);
    37113758            {
    3712                 /* At the moment we only have one drag instance. */
    3713                 DragInstance *pInstance = pThis->m_pCurDnD;
    3714                 AssertPtr(pInstance);
    3715 
    3716                 pInstance->onX11Event(e.x11);
     3759                rc2 = RTCritSectEnter(&pThis->m_eventQueueCS);
     3760                if (RT_SUCCESS(rc2))
     3761                {
     3762                    LogFlowFunc(("Added new X11 event, type=%d\n", e.x11.type));
     3763
     3764                    pThis->m_eventQueue.append(e);
     3765                    cNewEvents++;
     3766
     3767                    rc2 = RTCritSectLeave(&pThis->m_eventQueueCS);
     3768                    AssertRC(rc2);
     3769                }
    37173770            }
    3718         }
    3719         else
    3720             RTThreadSleep(25 /* ms */);
     3771
     3772            cQueued--;
     3773        }
     3774
     3775        if (cNewEvents)
     3776        {
     3777            rc = RTSemEventSignal(pThis->m_hEventSem);
     3778            if (RT_FAILURE(rc))
     3779                break;
     3780
     3781            continue;
     3782        }
     3783
     3784        /* No new events; wait a bit. */
     3785        RTThreadSleep(25 /* ms */);
    37213786
    37223787    } while (!ASMAtomicReadBool(&pThis->m_fStop));
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