VirtualBox

Changeset 50101 in vbox


Ignore:
Timestamp:
Jan 17, 2014 11:33:40 PM (11 years ago)
Author:
vboxsync
Message:

DnD/VBoxTray: Update; implemented own drop target for guest->host support (work in progress).

Location:
trunk/src/VBox/Additions/WINNT/VBoxTray
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r49891 r50101  
    55
    66#
    7 # Copyright (C) 2006-2012 Oracle Corporation
     7# Copyright (C) 2006-2014 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    4949        VBoxDnDDataObject.cpp \
    5050        VBoxDnDEnumFormat.cpp \
    51         VBoxDnDDropSource.cpp
     51        VBoxDnDDropSource.cpp \
     52        VBoxDnDDropTarget.cpp
    5253endif
    5354ifdef VBOX_WITH_GUEST_PROPS
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp

    r49947 r50101  
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2525#include <iprt/asm.h>
    2626#include <iprt/assert.h>
    27 #include <iprt/critsect.h>
    2827#include <iprt/err.h>
    2928#include <iprt/ldr.h>
     
    4443#endif
    4544
     45/** @todo Merge this with messages from VBoxTray.h. */
    4646#define WM_VBOXTRAY_DND_MESSAGE       WM_APP + 401
    4747
    4848static LRESULT CALLBACK vboxDnDWndProcInstance(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    4949static LRESULT CALLBACK vboxDnDWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    50 
    51 struct VBOXDNDCONTEXT;
    52 class VBoxDnDWnd;
    53 
    54 /*
    55  * A drag'n drop event from the host.
    56  */
    57 typedef struct VBOXDNDEVENT
    58 {
    59     /** The actual event data. */
    60     VBGLR3DNDHGCMEVENT Event;
    61 
    62 } VBOXDNDEVENT, *PVBOXDNDEVENT;
    63 
    64 /**
    65  * DnD context data.
    66  */
    67 typedef struct VBOXDNDCONTEXT
    68 {
    69     /** Pointer to the service environment. */
    70     const VBOXSERVICEENV      *pEnv;
    71     /** Shutdown indicator. */
    72     bool                       fShutdown;
    73     /** Thread handle for main event queue
    74      *  processing. */
    75     RTTHREAD                   hEvtQueue;
    76     /** The DnD main event queue. */
    77     RTCMTList<VBOXDNDEVENT>    lstEvtQueue;
    78     /** Semaphore for waiting on main event queue
    79      *  events. */
    80     RTSEMEVENT                 hEvtQueueSem;
    81     /** List of drag'n drop windows. At
    82      *  the moment only one source is supported. */
    83     RTCMTList<VBoxDnDWnd*>     lstWnd;
    84 
    85 } VBOXDNDCONTEXT, *PVBOXDNDCONTEXT;
    86 static VBOXDNDCONTEXT gCtx = {0};
    87 
    88 /**
    89  * Everything which is required to successfully start
    90  * a drag'n drop operation via DoDragDrop().
    91  */
    92 typedef struct VBOXDNDSTARTUPINFO
    93 {
    94     /** Our DnD data object, holding
    95      *  the raw DnD data. */
    96     VBoxDnDDataObject         *pDataObject;
    97     /** The drop source for sending the
    98      *  DnD request to a IDropTarget. */
    99     VBoxDnDDropSource         *pDropSource;
    100     /** The DnD effects which are wanted / allowed. */
    101     DWORD                      dwOKEffects;
    102 
    103 } VBOXDNDSTARTUPINFO, *PVBOXDNDSTARTUPINFO;
    104 
    105 /**
    106  * Class for handling a DnD proxy window.
    107  ** @todo Unify this and VBoxClient's DragInstance!
    108  */
    109 class VBoxDnDWnd
    110 {
    111     enum State
    112     {
    113         Uninitialized,
    114         Initialized,
    115         Dragging,
    116         Dropped,
    117         Canceled
    118     };
    119 
    120     enum Mode
    121     {
    122         Unknown,
    123         HG,
    124         GH
    125     };
    126 
    127 public:
    128 
    129     VBoxDnDWnd(void);
    130     virtual ~VBoxDnDWnd(void);
    131 
    132 public:
    133 
    134     int Initialize(PVBOXDNDCONTEXT pContext);
    135 
    136 public:
    137 
    138     /** The window's thread for the native message pump and
    139      *  OLE context. */
    140     static int Thread(RTTHREAD hThread, void *pvUser);
    141 
    142 public:
    143 
    144     static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM lParam);
    145     /** The per-instance wndproc routine. */
    146     LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    147 
    148 public:
    149 
    150     int DragRelease(void);
    151 
    152     int OnCreate(void);
    153     void OnDestroy(void);
    154 
    155     /* H->G */
    156     int OnHgEnter(const RTCList<RTCString> &formats, uint32_t uAllActions);
    157     int OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAllActions);
    158     int OnHgDrop(void);
    159     int OnHgLeave(void);
    160     int OnHgDataReceived(const void *pvData, uint32_t cData);
    161     int OnHgCancel(void);
    162 
    163 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    164     /* G->H */
    165     int OnGhIsDnDPending(void);
    166     int OnGhDropped(const RTCString &strFormat, uint32_t action);
    167 #endif
    168 
    169     int ProcessEvent(PVBOXDNDEVENT pEvent);
    170 
    171 protected:
    172 
    173     void reset(void);
    174 
    175 public: /** @todo Make protected! */
    176 
    177     /** Pointer to DnD context. */
    178     PVBOXDNDCONTEXT            pContext;
    179     RTCRITSECT                 mCritSect;
    180     RTSEMEVENT                 mEventSem;
    181 #ifdef RT_OS_WINDOWS
    182     /** The window's handle. */
    183     HWND                       hWnd;
    184     /** List of allowed MIME types this
    185      *  client can handle. Make this a per-instance
    186      *  property so that we can selectively allow/forbid
    187      *  certain types later on runtime. */
    188     RTCList<RTCString>         lstAllowedFormats;
    189     /** List of formats for the current
    190      *  drag'n drop operation. */
    191     RTCList<RTCString>         lstFormats;
    192     /** Flags of all current drag'n drop
    193      *  actions allowed. */
    194     uint32_t                   uAllActions;
    195     /** The startup information required
    196      *  for the actual DoDragDrop() call. */
    197     VBOXDNDSTARTUPINFO         startupInfo;
    198     bool                       mfMouseButtonDown;
    199 #else
    200     /** @todo */
    201 #endif
    202 
    203     /** The window's own HGCM client ID. */
    204     uint32_t                   mClientID;
    205     Mode                       mMode;
    206     State                      mState;
    207     RTCString                  mFormatRequested;
    208     RTCList<RTCString>         mLstFormats;
    209     RTCList<RTCString>         mLstActions;
    210 };
    21150
    21251VBoxDnDWnd::VBoxDnDWnd(void)
    21352    : hWnd(NULL),
    21453      mfMouseButtonDown(false),
     54#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     55      pDropTarget(NULL),
     56#endif
    21557      mClientID(UINT32_MAX),
    21658      mMode(Unknown),
     
    21860{
    21961    RT_ZERO(startupInfo);
     62
     63    reset();
    22064}
    22165
     
    22569
    22670    reset();
    227 }
    228 
    229 int VBoxDnDWnd::DragRelease(void)
    230 {
    231     /* Release mouse button in the guest to start the "drop"
    232      * action at the current mouse cursor position. */
    233     INPUT Input[1] = { 0 };
    234     Input[0].type       = INPUT_MOUSE;
    235     Input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;
    236     SendInput(1, Input, sizeof(INPUT));
    237 
    238     return VINF_SUCCESS;
    23971}
    24072
     
    345177            LogFlowFunc(("Debug proxy window created, hWnd=0x%x\n", pThis->hWnd));
    346178#endif
    347 
    348179        }
    349180    }
     
    444275        case WM_MOUSEMOVE:
    445276        {
    446             LogFlowThisFunc(("WM_MOUSEMOVE: mfMouseButtonDown=%RTbool, mState=%ld\n",
    447                          mfMouseButtonDown, mState));
    448 
    449             /* Dragging not started yet? Kick it off ... */
    450             if (   mfMouseButtonDown
    451                 && (mState != Dragging))
     277            LogFlowThisFunc(("WM_MOUSEMOVE: mfMouseButtonDown=%RTbool, mMode=%ld, mState=%ld\n",
     278                             mfMouseButtonDown, mMode, mState));
     279#ifdef DEBUG_andy
     280            POINT p;
     281            GetCursorPos(&p);
     282            LogFlowThisFunc(("WM_MOUSEMOVE: curX=%ld, curY=%ld\n", p.x, p.y));
     283#endif
     284            int rc = VINF_SUCCESS;
     285            if (mMode == HG) /* Host to guest. */
    452286            {
    453                 mState = Dragging;
    454 
    455 #ifdef VBOX_DND_DEBUG_WND
    456                 /* Delay hinding the proxy window a bit when debugging, to see
    457                  * whether the desired range is covered correctly. */
    458                 RTThreadSleep(5000);
    459 #endif
    460                 ShowWindow(hWnd, SW_HIDE);
    461 
    462                 int rc = VINF_SUCCESS;
    463 
    464                 LogFlowThisFunc(("Starting drag'n drop: uAllActions=0x%x, dwOKEffects=0x%x ...\n",
    465                                  uAllActions, startupInfo.dwOKEffects));
    466 
    467                 AssertPtr(startupInfo.pDataObject);
    468                 AssertPtr(startupInfo.pDropSource);
    469                 DWORD dwEffect;
    470                 HRESULT hr = DoDragDrop(startupInfo.pDataObject, startupInfo.pDropSource,
    471                                         startupInfo.dwOKEffects, &dwEffect);
    472                 LogFlowThisFunc(("rc=%Rhrc, dwEffect=%RI32\n", hr, dwEffect));
    473                 switch (hr)
     287                /* Dragging not started yet? Kick it off ... */
     288                if (   mfMouseButtonDown
     289                    && (mState != Dragging))
    474290                {
    475                     case DRAGDROP_S_DROP:
    476                         mState = Dropped;
    477                         break;
    478 
    479                     case DRAGDROP_S_CANCEL:
    480                         mState = Canceled;
    481                         break;
    482 
    483                     default:
    484                         LogFlowThisFunc(("Drag'n drop failed with %Rhrc\n", hr));
    485                         mState = Canceled;
    486                         rc = VERR_GENERAL_FAILURE; /** @todo Find a better status code. */
    487                         break;
     291                    mState = Dragging;
     292#if 0
     293                    /* Delay hiding the proxy window a bit when debugging, to see
     294                     * whether the desired range is covered correctly. */
     295                    RTThreadSleep(5000);
     296#endif
     297                    hide();
     298
     299                    LogFlowThisFunc(("Starting drag'n drop: uAllActions=0x%x, dwOKEffects=0x%x ...\n",
     300                                     uAllActions, startupInfo.dwOKEffects));
     301
     302                    AssertPtr(startupInfo.pDataObject);
     303                    AssertPtr(startupInfo.pDropSource);
     304                    DWORD dwEffect;
     305                    HRESULT hr = DoDragDrop(startupInfo.pDataObject, startupInfo.pDropSource,
     306                                            startupInfo.dwOKEffects, &dwEffect);
     307                    LogFlowThisFunc(("rc=%Rhrc, dwEffect=%RI32\n", hr, dwEffect));
     308                    switch (hr)
     309                    {
     310                        case DRAGDROP_S_DROP:
     311                            mState = Dropped;
     312                            break;
     313
     314                        case DRAGDROP_S_CANCEL:
     315                            mState = Canceled;
     316                            break;
     317
     318                        default:
     319                            LogFlowThisFunc(("Drag'n drop failed with %Rhrc\n", hr));
     320                            mState = Canceled;
     321                            rc = VERR_GENERAL_FAILURE; /** @todo Find a better status code. */
     322                            break;
     323                    }
     324
     325                    int rc2 = RTCritSectEnter(&mCritSect);
     326                    if (RT_SUCCESS(rc2))
     327                    {
     328                        startupInfo.pDropSource->Release();
     329                        startupInfo.pDataObject->Release();
     330
     331                        RT_ZERO(startupInfo);
     332
     333                        rc2 = RTCritSectLeave(&mCritSect);
     334                        if (RT_SUCCESS(rc))
     335                            rc = rc2;
     336                    }
     337
     338                    mMode = Unknown;
    488339                }
    489 
    490                 int rc2 = RTCritSectEnter(&mCritSect);
    491                 if (RT_SUCCESS(rc2))
    492                 {
    493                     startupInfo.pDropSource->Release();
    494                     startupInfo.pDataObject->Release();
    495 
    496                     RT_ZERO(startupInfo);
    497 
    498                     RTCritSectLeave(&mCritSect);
    499                 }
    500 
    501                 LogFlowThisFunc(("Drag'n drop resulted in mState=%ld, rc=%Rrc\n",
    502                              mState, rc));
    503340            }
    504 
     341            else if (mMode == GH) /* Guest to host. */
     342            {
     343                hide();
     344            }
     345            else
     346                rc = VERR_NOT_SUPPORTED;
     347
     348            LogFlowThisFunc(("WM_MOUSEMOVE: mMode=%ld, mState=%ld, rc=%Rrc\n",
     349                             mMode, mState, rc));
    505350            return 0;
    506351        }
     
    520365                {
    521366                    LogFlowThisFunc(("HOST_DND_HG_EVT_ENTER\n"));
     367
     368                    reset();
     369
     370                    Assert(mMode == Unknown);
     371                    mMode = HG;
    522372
    523373                    if (pEvent->Event.cbFormats)
     
    540390                {
    541391                    LogFlowThisFunc(("HOST_DND_HG_EVT_MOVE: %d,%d\n",
    542                                  pEvent->Event.u.a.uXpos, pEvent->Event.u.a.uYpos));
    543 
    544                     rc = OnHgMove(pEvent->Event.u.a.uXpos, pEvent->Event.u.a.uYpos, pEvent->Event.u.a.uDefAction);
     392                                     pEvent->Event.u.a.uXpos, pEvent->Event.u.a.uYpos));
     393
     394                    rc = OnHgMove(pEvent->Event.u.a.uXpos, pEvent->Event.u.a.uYpos,
     395                                  pEvent->Event.u.a.uDefAction);
    545396                    break;
    546397                }
     
    566417                    LogFlowThisFunc(("HOST_DND_HG_SND_DATA\n"));
    567418
    568                     rc = OnHgDataReceived(pEvent->Event.u.b.pvData, pEvent->Event.u.b.cbData);
     419                    rc = OnHgDataReceived(pEvent->Event.u.b.pvData,
     420                                          pEvent->Event.u.b.cbData);
    569421                    break;
    570422                }
     
    575427
    576428                    rc = OnHgCancel();
     429
     430                    reset();
    577431                    break;
    578432                }
    579433
    580 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    581434                case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
    582435                {
    583436                    LogFlowThisFunc(("HOST_DND_GH_REQ_PENDING\n"));
    584 
     437#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     438                    Assert(   mMode == Unknown
     439                           || mMode == GH);
     440                    mMode = GH;
     441                    rc = OnGhIsDnDPending(pEvent->Event.uScreenId);
     442#else
     443                    rc = VERR_NOT_SUPPORTED;
     444#endif
    585445                    break;
    586446                }
     
    589449                {
    590450                    LogFlowThisFunc(("HOST_DND_GH_EVT_DROPPED\n"));
    591 
     451#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     452                    Assert(mMode == GH);
     453                    rc = OnGhDropped(pEvent->Event.pszFormats,
     454                                     pEvent->Event.cbFormats,
     455                                     pEvent->Event.u.a.uDefAction);
     456                    mMode = Unknown;
     457#else
     458                    rc = VERR_NOT_SUPPORTED;
     459#endif
    592460                    break;
    593461                }
     
    596464                {
    597465                    LogFlowThisFunc(("GUEST_DND_GH_EVT_ERROR\n"));
    598 
     466#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     467                    reset();
     468                    rc = VINF_SUCCESS; /** @todo GUEST_DND_GH_EVT_ERROR */
     469#else
     470                    rc = VERR_NOT_SUPPORTED;
     471#endif
    599472                    break;
    600473                }
    601 #endif
     474
    602475                default:
    603476                    rc = VERR_NOT_SUPPORTED;
     
    635508
    636509            LogFlowThisFunc(("Processing event %RU32 resulted in rc=%Rrc\n",
    637                          pEvent->Event.uType, rc));
     510                             pEvent->Event.uType, rc));
    638511            if (pEvent)
    639512                RTMemFree(pEvent);
     
    648521}
    649522
     523#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     524/**
     525 * Registers this proxy window as a local drop target.
     526 *
     527 * @return  IPRT status code.
     528 */
     529int VBoxDnDWnd::RegisterAsDropTarget(void)
     530{
     531    if (pDropTarget) /* Already registered as drop target? */
     532        return VINF_SUCCESS;
     533
     534    int rc = VBoxDnDDropTarget::CreateDropTarget(this /* pParent */,
     535                                                 &pDropTarget);
     536    if (RT_SUCCESS(rc))
     537    {
     538        AssertPtr(pDropTarget);
     539        HRESULT hr = CoLockObjectExternal(pDropTarget, TRUE /* fLock */,
     540                                          FALSE /* fLastUnlockReleases */);
     541        if (SUCCEEDED(hr))
     542            hr = RegisterDragDrop(hWnd, pDropTarget);
     543
     544        if (FAILED(hr))
     545        {
     546            LogRel(("DnD: Creating drop target failed with hr=0x%x\n", hr));
     547            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
     548        }
     549    }
     550
     551    LogFlowFuncLeaveRC(rc);
     552    return rc;
     553}
     554
     555int VBoxDnDWnd::UnregisterAsDropTarget(void)
     556{
     557    if (!pDropTarget) /* No drop target? Bail out. */
     558        return VINF_SUCCESS;
     559
     560    HRESULT hr = RevokeDragDrop(hWnd);
     561    if (SUCCEEDED(hr))
     562        hr = CoLockObjectExternal(pDropTarget, FALSE /* fLock */,
     563                                  TRUE /* fLastUnlockReleases */);
     564    if (SUCCEEDED(hr))
     565        pDropTarget->Release();
     566
     567    int rc = SUCCEEDED(hr)
     568           ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fix this. */
     569
     570    LogFlowFuncLeaveRC(rc);
     571    return rc;
     572}
     573#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     574
    650575int VBoxDnDWnd::OnCreate(void)
    651576{
     
    657582    }
    658583
    659     LogFlowThisFunc(("Client ID=%RU32\n", mClientID));
     584    LogFlowThisFunc(("Client ID=%RU32, rc=%Rrc\n", mClientID, rc));
    660585    return rc;
    661586}
     
    664589{
    665590    VbglR3DnDDisconnect(mClientID);
     591    LogFlowThisFuncLeave();
    666592}
    667593
    668594int VBoxDnDWnd::OnHgEnter(const RTCList<RTCString> &lstFormats, uint32_t uAllActions)
    669595{
    670     reset();
    671 
    672     mState = Initialized;
    673 
    674596#ifdef DEBUG
    675597    LogFlowThisFunc(("uActions=0x%x, lstFormats=%zu: ", uAllActions, lstFormats.size()));
     
    740662    }
    741663
    742     /*
    743      * Prepare the proxy window.
    744      */
     664    if (RT_SUCCESS(rc))
     665        rc = makeFullscreen();
     666
     667    LogFlowFuncLeaveRC(rc);
     668    return rc;
     669}
     670
     671int VBoxDnDWnd::OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
     672{
     673    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=0x%x\n",
     674                     u32xPos, u32yPos, uAction));
     675
     676    /** @todo Put this block into a function! */
     677    /** @todo Multi-monitor setups? */
     678    int iScreenX = GetSystemMetrics(SM_CXSCREEN) - 1;
     679    int iScreenY = GetSystemMetrics(SM_CYSCREEN) - 1;
     680
     681    INPUT Input[1] = { 0 };
     682    Input[0].type       = INPUT_MOUSE;
     683    Input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;
     684    Input[0].mi.dx      = u32xPos * (65535 / iScreenX);
     685    Input[0].mi.dy      = u32yPos * (65535 / iScreenY);
     686    SendInput(1, Input, sizeof(INPUT));
     687
     688#ifdef DEBUG_andy
     689    POINT p;
     690    GetCursorPos(&p);
     691    LogFlowThisFunc(("curX=%d, curY=%d\n", p.x, p.y));
     692#endif
     693
     694    uint32_t uActionNotify = DND_IGNORE_ACTION;
     695    int rc = RTCritSectEnter(&mCritSect);
     696    if (RT_SUCCESS(rc))
     697    {
     698        if (   (Dragging == mState)
     699            && startupInfo.pDropSource)
     700            uActionNotify = startupInfo.pDropSource->GetCurrentAction();
     701
     702        RTCritSectLeave(&mCritSect);
     703    }
     704
     705    if (RT_SUCCESS(rc))
     706    {
     707        rc = VbglR3DnDHGAcknowledgeOperation(mClientID, uActionNotify);
     708        if (RT_FAILURE(rc))
     709            LogFlowThisFunc(("Acknowleding operation failed with rc=%Rrc\n", rc));
     710    }
     711
     712    LogFlowThisFunc(("Returning uActionNotify=0x%x, rc=%Rrc\n", uActionNotify, rc));
     713    return rc;
     714}
     715
     716int VBoxDnDWnd::OnHgLeave(void)
     717{
     718    LogFlowThisFunc(("mMode=%ld, mState=%RU32\n", mMode, mState));
     719    LogRel(("DnD: Drag'n drop operation aborted\n"));
     720
     721    reset();
     722
     723    int rc = VINF_SUCCESS;
     724
     725    /* Post ESC to our window to officially abort the
     726     * drag'n drop operation. */
     727    PostMessage(hWnd, WM_KEYDOWN, VK_ESCAPE, 0 /* lParam */);
     728
     729    LogFlowFuncLeaveRC(rc);
     730    return rc;
     731}
     732
     733int VBoxDnDWnd::OnHgDrop(void)
     734{
     735    LogFlowThisFunc(("mMode=%ld, mState=%RU32\n", mMode, mState));
     736
     737    int rc = VINF_SUCCESS;
     738    if (mState == Dragging)
     739    {
     740        Assert(lstFormats.size() >= 1);
     741
     742        /** @todo What to do when multiple formats are available? */
     743        mFormatRequested = lstFormats.at(0);
     744
     745        rc = RTCritSectEnter(&mCritSect);
     746        if (RT_SUCCESS(rc))
     747        {
     748            if (startupInfo.pDataObject)
     749                startupInfo.pDataObject->SetStatus(VBoxDnDDataObject::Dropping);
     750            else
     751                rc = VERR_NOT_FOUND;
     752
     753            RTCritSectLeave(&mCritSect);
     754        }
     755
     756        if (RT_SUCCESS(rc))
     757        {
     758            LogRel(("DnD: Requesting data as '%s' ...\n", mFormatRequested.c_str()));
     759            rc = VbglR3DnDHGRequestData(mClientID, mFormatRequested.c_str());
     760            if (RT_FAILURE(rc))
     761                LogFlowThisFunc(("Requesting data failed with rc=%Rrc\n", rc));
     762        }
     763    }
     764
     765    LogFlowFuncLeaveRC(rc);
     766    return rc;
     767}
     768
     769int VBoxDnDWnd::OnHgDataReceived(const void *pvData, uint32_t cbData)
     770{
     771    LogFlowThisFunc(("mState=%ld, pvData=%p, cbData=%RU32\n",
     772                     mState, pvData, cbData));
     773
     774    mState = Dropped;
     775
     776    int rc = VINF_SUCCESS;
     777    if (pvData)
     778    {
     779        Assert(cbData);
     780        rc = RTCritSectEnter(&mCritSect);
     781        if (RT_SUCCESS(rc))
     782        {
     783            if (startupInfo.pDataObject)
     784                rc = startupInfo.pDataObject->Signal(mFormatRequested, pvData, cbData);
     785            else
     786                rc = VERR_NOT_FOUND;
     787
     788            RTCritSectLeave(&mCritSect);
     789        }
     790    }
     791
     792    int rc2 = dragRelease();
     793    if (RT_SUCCESS(rc))
     794        rc = rc2;
     795
     796    LogFlowFuncLeaveRC(rc);
     797    return rc;
     798}
     799
     800int VBoxDnDWnd::OnHgCancel(void)
     801{
     802    int rc = RTCritSectEnter(&mCritSect);
     803    if (RT_SUCCESS(rc))
     804    {
     805        if (startupInfo.pDataObject)
     806            startupInfo.pDataObject->Abort();
     807
     808        RTCritSectLeave(&mCritSect);
     809    }
     810
     811    int rc2 = dragRelease();
     812    if (RT_SUCCESS(rc))
     813        rc = rc2;
     814
     815    return rc;
     816}
     817
     818#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     819int VBoxDnDWnd::OnGhIsDnDPending(uint32_t uScreenID)
     820{
     821    LogFlowThisFunc(("mMode=%ld, mState=%ld, uScreenID=%RU32\n",
     822                     mMode, mState, uScreenID));
     823
     824    if (mState == Uninitialized)
     825        reset();
     826
     827    int rc;
     828    if (mState == Initialized)
     829    {
     830        //rc = makeFullscreen();
     831        rc = VINF_SUCCESS;
     832        if (RT_SUCCESS(rc))
     833            rc = RegisterAsDropTarget();
     834
     835        if (RT_SUCCESS(rc))
     836            mState = Dragging;
     837    }
     838    else
     839        rc = VINF_SUCCESS;
     840
     841    if (   RT_SUCCESS(rc)
     842        && (mState == Dragging))
     843    {
     844        /** @todo Put this block into a function! */
     845        POINT p;
     846        GetCursorPos(&p);
     847
     848#ifdef DEBUG_andy
     849        LogFlowThisFunc(("Setting cursor to curX=%d, curY=%d\n", p.x, p.y));
     850#endif
     851        /** @todo Multi-monitor setups? */
     852        int iScreenX = GetSystemMetrics(SM_CXSCREEN) - 1;
     853        int iScreenY = GetSystemMetrics(SM_CYSCREEN) - 1;
     854
     855        static int pos = 100;
     856        pos++;
     857
     858        INPUT Input[1] = { 0 };
     859        Input[0].type       = INPUT_MOUSE;
     860        Input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;
     861        Input[0].mi.dx      = pos * (65535 / iScreenX); //p.x * (65535 / iScreenX);
     862        Input[0].mi.dy      = 100 * (65535 / iScreenY); //p.y * (65535 / iScreenY);
     863        SendInput(1, Input, sizeof(INPUT));
     864
     865#ifdef DEBUG_andy
     866        CURSORINFO ci;
     867        RT_ZERO(ci);
     868        ci.cbSize = sizeof(ci);
     869        BOOL fRc = GetCursorInfo(&ci);
     870        if (fRc)
     871            LogFlowThisFunc(("Cursor shown=%RTbool, cursor=0x%p, x=%d, y=%d\n",
     872                             (ci.flags & CURSOR_SHOWING) ? true : false,
     873                             ci.hCursor, ci.ptScreenPos.x, ci.ptScreenPos.y));
     874#endif
     875    }
     876
     877    int rc2= VbglR3DnDGHAcknowledgePending(mClientID,
     878                                           DND_COPY_ACTION, DND_COPY_ACTION, "text/plain;charset=utf-8");
     879    LogFlowThisFunc(("sent=%Rrc\n", rc2));
     880
     881    LogFlowFuncLeaveRC(rc);
     882    return rc;
     883}
     884
     885int VBoxDnDWnd::OnGhDropped(const char *pszFormats, uint32_t cbFormats,
     886                            uint32_t uDefAction)
     887{
     888    LogFlowThisFunc(("mMode=%ld, mState=%ld, cbFormats=%RU32, uDefAction=0x%x\n",
     889                     mMode, mState, cbFormats, uDefAction));
     890
     891    int rc;
     892    if (mState == Dragging)
     893    {
     894    }
     895    else
     896        rc = VERR_WRONG_ORDER;
     897
     898    LogFlowFuncLeaveRC(rc);
     899    return rc;
     900}
     901#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     902
     903int VBoxDnDWnd::ProcessEvent(PVBOXDNDEVENT pEvent)
     904{
     905    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     906
     907    PostMessage(hWnd, WM_VBOXTRAY_DND_MESSAGE,
     908                0 /* wParm */, (LPARAM)pEvent /* lParm */);
     909
     910    return VINF_SUCCESS;
     911}
     912
     913int VBoxDnDWnd::dragRelease(void)
     914{
     915    /* Release mouse button in the guest to start the "drop"
     916     * action at the current mouse cursor position. */
     917    INPUT Input[1] = { 0 };
     918    Input[0].type       = INPUT_MOUSE;
     919    Input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;
     920    SendInput(1, Input, sizeof(INPUT));
     921
     922    return VINF_SUCCESS;
     923}
     924
     925int VBoxDnDWnd::hide(void)
     926{
     927    ShowWindow(hWnd, SW_HIDE);
     928
     929    return VINF_SUCCESS;
     930}
     931
     932int VBoxDnDWnd::makeFullscreen(void)
     933{
     934    int rc = VINF_SUCCESS;
     935
    745936    RECT r;
    746937    RT_ZERO(r);
    747938
    748     if (RT_SUCCESS(rc))
    749     {
    750         HDC hDC = GetDC(NULL);
    751         BOOL fRc = EnumDisplayMonitors(hDC, NULL, VBoxDnDWnd::MonitorEnumProc, (LPARAM)&r);
     939    BOOL fRc;
     940    HDC hDC = GetDC(NULL /* Entire screen */);
     941    if (hDC)
     942    {
     943        fRc = EnumDisplayMonitors(hDC, NULL, VBoxDnDWnd::MonitorEnumProc,
     944                                  (LPARAM)&r);
    752945        if (!fRc)
    753946            rc = VERR_NOT_FOUND;
    754947        ReleaseDC(NULL, hDC);
    755948    }
     949    else
     950        rc = VERR_ACCESS_DENIED;
    756951
    757952    if (RT_FAILURE(rc))
     
    772967    if (RT_SUCCESS(rc))
    773968    {
    774         SetWindowPos(hWnd, HWND_TOPMOST,
    775                      r.left,
    776                      r.top,
    777                      r.right - r.left,
    778                      r.bottom - r.top,
     969        fRc = SetWindowPos(hWnd, HWND_TOPMOST,
     970                           r.left,
     971                           r.top,
     972                           r.right - r.left,
     973                           r.bottom - r.top,
    779974#ifdef VBOX_DND_DEBUG_WND
    780                      SWP_SHOWWINDOW);
     975                           SWP_SHOWWINDOW);
    781976#else
    782                      SWP_SHOWWINDOW | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
    783 #endif
    784         LogFlowFunc(("Virtual screen is %ld,%ld,%ld,%ld (%ld x %ld)\n",
    785                      r.left, r.top, r.right, r.bottom,
    786                      r.right - r.left, r.bottom - r.top));
     977                           SWP_SHOWWINDOW | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
     978#endif
     979        if (fRc)
     980            LogFlowFunc(("Virtual screen is %ld,%ld,%ld,%ld (%ld x %ld)\n",
     981                         r.left, r.top, r.right, r.bottom,
     982                         r.right - r.left, r.bottom - r.top));
     983        else
     984        {
     985            DWORD dwErr = GetLastError();
     986            LogRel(("DnD: Failed to set proxy window position, rc=%Rrc\n",
     987                    RTErrConvertFromWin32(dwErr)));
     988        }
    787989    }
    788990    else
     
    793995}
    794996
    795 int VBoxDnDWnd::OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
    796 {
    797     LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=0x%x\n",
    798                      u32xPos, u32yPos, uAction));
    799 
    800     /** @todo Multi-monitor setups? */
    801     int iScreenX = GetSystemMetrics(SM_CXSCREEN) - 1;
    802     int iScreenY = GetSystemMetrics(SM_CYSCREEN) - 1;
    803 
    804     INPUT Input[1] = { 0 };
    805     Input[0].type       = INPUT_MOUSE;
    806     Input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;
    807     Input[0].mi.dx      = u32xPos * (65535 / iScreenX);
    808     Input[0].mi.dy      = u32yPos * (65535 / iScreenY);
    809     SendInput(1, Input, sizeof(INPUT));
    810 
    811 #ifdef DEBUG
    812     POINT p;
    813     GetCursorPos(&p);
    814     LogFlowThisFunc(("curX=%d, cury=%d\n", p.x, p.y));
    815 #endif
    816 
    817     uint32_t uActionNotify = DND_IGNORE_ACTION;
    818     int rc = RTCritSectEnter(&mCritSect);
    819     if (RT_SUCCESS(rc))
    820     {
    821         if (   (Dragging == mState)
    822             && startupInfo.pDropSource)
    823             uActionNotify = startupInfo.pDropSource->GetCurrentAction();
    824 
    825         RTCritSectLeave(&mCritSect);
    826     }
    827 
    828     if (RT_SUCCESS(rc))
    829     {
    830         rc = VbglR3DnDHGAcknowledgeOperation(mClientID, uActionNotify);
    831         if (RT_FAILURE(rc))
    832             LogFlowThisFunc(("Acknowleding operation failed with rc=%Rrc\n", rc));
    833     }
    834 
    835     LogFlowThisFunc(("Returning uActionNotify=0x%x, rc=%Rrc\n", uActionNotify, rc));
    836     return rc;
    837 }
    838 
    839 int VBoxDnDWnd::OnHgLeave(void)
    840 {
    841     LogFlowThisFunc(("mMode=%RU32, mState=%RU32\n", mMode, mState));
    842     LogRel(("DnD: Drag'n drop operation aborted\n"));
    843 
    844     reset();
    845 
    846     int rc = VINF_SUCCESS;
    847 
    848     /* Post ESC to our window to officially abort the
    849      * drag'n drop operation. */
    850     PostMessage(hWnd, WM_KEYDOWN, VK_ESCAPE, 0 /* lParam */);
    851 
    852     LogFlowFuncLeaveRC(rc);
    853     return rc;
    854 }
    855 
    856 int VBoxDnDWnd::OnHgDrop(void)
    857 {
    858     LogFlowThisFunc(("mMode=%RU32, mState=%RU32\n", mMode, mState));
    859 
    860     int rc = VINF_SUCCESS;
    861     if (mState == Dragging)
    862     {
    863         Assert(lstFormats.size() >= 1);
    864 
    865         /** @todo What to do when multiple formats are available? */
    866         mFormatRequested = lstFormats.at(0);
    867 
    868         rc = RTCritSectEnter(&mCritSect);
    869         if (RT_SUCCESS(rc))
    870         {
    871             if (startupInfo.pDataObject)
    872                 startupInfo.pDataObject->SetStatus(VBoxDnDDataObject::Dropping);
    873             else
    874                 rc = VERR_NOT_FOUND;
    875 
    876             RTCritSectLeave(&mCritSect);
    877         }
    878 
    879         if (RT_SUCCESS(rc))
    880         {
    881             LogRel(("DnD: Requesting data as '%s' ...\n", mFormatRequested.c_str()));
    882             rc = VbglR3DnDHGRequestData(mClientID, mFormatRequested.c_str());
    883             if (RT_FAILURE(rc))
    884                 LogFlowThisFunc(("Requesting data failed with rc=%Rrc\n", rc));
    885         }
    886     }
    887 
    888     LogFlowFuncLeaveRC(rc);
    889     return rc;
    890 }
    891 
    892 int VBoxDnDWnd::OnHgDataReceived(const void *pvData, uint32_t cbData)
    893 {
    894     LogFlowThisFunc(("mState=%ld, pvData=%p, cbData=%RU32\n",
    895                      mState, pvData, cbData));
    896 
    897     mState = Dropped;
    898 
    899     int rc = VINF_SUCCESS;
    900     if (pvData)
    901     {
    902         Assert(cbData);
    903         rc = RTCritSectEnter(&mCritSect);
    904         if (RT_SUCCESS(rc))
    905         {
    906             if (startupInfo.pDataObject)
    907                 rc = startupInfo.pDataObject->Signal(mFormatRequested, pvData, cbData);
    908             else
    909                 rc = VERR_NOT_FOUND;
    910 
    911             RTCritSectLeave(&mCritSect);
    912         }
    913     }
    914 
    915     int rc2 = DragRelease();
    916     if (RT_SUCCESS(rc))
    917         rc = rc2;
    918 
    919     LogFlowFuncLeaveRC(rc);
    920     return rc;
    921 }
    922 
    923 int VBoxDnDWnd::OnHgCancel(void)
    924 {
    925     int rc = RTCritSectEnter(&mCritSect);
    926     if (RT_SUCCESS(rc))
    927     {
    928         if (startupInfo.pDataObject)
    929             startupInfo.pDataObject->Abort();
    930 
    931         RTCritSectLeave(&mCritSect);
    932     }
    933 
    934     int rc2 = DragRelease();
    935     if (RT_SUCCESS(rc))
    936         rc = rc2;
    937 
    938     return rc;
    939 }
    940 
    941 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    942 int VBoxDnDWnd::OnGhIsDnDPending(void)
    943 {
    944     return 0;
    945 }
    946 
    947 int VBoxDnDWnd::OnGhDropped(const RTCString &strFormat, uint32_t action)
    948 {
    949     return 0;
    950 }
    951 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    952 
    953 int VBoxDnDWnd::ProcessEvent(PVBOXDNDEVENT pEvent)
    954 {
    955     AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    956 
    957     PostMessage(hWnd, WM_VBOXTRAY_DND_MESSAGE,
    958                 0 /* wParm */, (LPARAM)pEvent /* lParm */);
    959 
    960     return VINF_SUCCESS;
    961 }
    962 
    963997void VBoxDnDWnd::reset(void)
    964998{
    965     LogFlowThisFunc(("mState=%ld\n", mState));
     999    LogFlowThisFunc(("Old mState=%ld\n", mState));
    9661000
    9671001    lstAllowedFormats.clear();
    9681002    lstFormats.clear();
    9691003    uAllActions = DND_IGNORE_ACTION;
     1004
     1005    mMode = Unknown;
     1006    mState = Initialized;
    9701007}
    9711008
     
    11091146    AssertPtr(pWnd);
    11101147
     1148    /* Number of invalid messages skipped in a row. */
     1149    int cMsgSkippedInvalid = 0;
     1150
    11111151    do
    11121152    {
     
    11271167        if (RT_SUCCESS(rc))
    11281168        {
     1169            cMsgSkippedInvalid = 0; /* Reset skipped messages count. */
     1170
    11291171            LogFlowFunc(("Received new event, type=%RU32\n", pEvent->Event.uType));
    11301172
     
    11401182        }
    11411183        else
     1184        {
    11421185            LogFlowFunc(("Processing next message failed with rc=%Rrc\n", rc));
     1186
     1187            /* Old(er) hosts either are broken regarding DnD support or otherwise
     1188             * don't support the stuff we do on the guest side, so make sure we
     1189             * don't process invalid messages forever. */
     1190            if (rc == VERR_INVALID_PARAMETER)
     1191                cMsgSkippedInvalid++;
     1192            if (cMsgSkippedInvalid > 3)
     1193            {
     1194                LogFlowFunc(("Too many invalid/skipped messages from host, exiting ...\n"));
     1195                break;
     1196            }
     1197        }
    11431198
    11441199        if (ASMAtomicReadBool(&pCtx->fShutdown))
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h

    r49947 r50101  
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1818#ifndef __VBOXTRAYDND__H
    1919#define __VBOXTRAYDND__H
     20
     21#include <iprt/critsect.h>
    2022
    2123#include <iprt/cpp/mtlist.h>
     
    130132};
    131133
     134class VBoxDnDDropTarget : public IDropTarget
     135{
     136public:
     137
     138    VBoxDnDDropTarget(VBoxDnDWnd *pThis);
     139    virtual ~VBoxDnDDropTarget(void);
     140
     141public:
     142
     143    static int CreateDropTarget(VBoxDnDWnd *pParent, IDropTarget **ppDropTarget);
     144
     145public: /* IUnknown methods. */
     146
     147    STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
     148    STDMETHOD_(ULONG, AddRef)(void);
     149    STDMETHOD_(ULONG, Release)(void);
     150
     151public: /* IDropTarget methods. */
     152
     153        STDMETHOD(DragEnter)(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
     154        STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
     155        STDMETHOD(DragLeave)(void);
     156        STDMETHOD(Drop)(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
     157
     158protected:
     159
     160    static DWORD GetDropEffect(DWORD grfKeyState, DWORD dwAllowedEffects);
     161
     162protected:
     163
     164    LONG mRefCount;
     165    VBoxDnDWnd *mpWndParent;
     166    uint32_t mClientID;
     167    DWORD mdwCurEffect;
     168    IDataObject *mpDataObject;
     169    bool mfHasDropData;
     170};
     171
    132172class VBoxDnDEnumFormatEtc : public IEnumFORMATETC
    133173{
     
    160200        FORMATETC * m_pFormatEtc;
    161201};
     202
     203struct VBOXDNDCONTEXT;
     204class VBoxDnDWnd;
     205
     206/*
     207 * A drag'n drop event from the host.
     208 */
     209typedef struct VBOXDNDEVENT
     210{
     211    /** The actual event data. */
     212    VBGLR3DNDHGCMEVENT Event;
     213
     214} VBOXDNDEVENT, *PVBOXDNDEVENT;
     215
     216/**
     217 * DnD context data.
     218 */
     219typedef struct VBOXDNDCONTEXT
     220{
     221    /** Pointer to the service environment. */
     222    const VBOXSERVICEENV      *pEnv;
     223    /** Shutdown indicator. */
     224    bool                       fShutdown;
     225    /** Thread handle for main event queue
     226     *  processing. */
     227    RTTHREAD                   hEvtQueue;
     228    /** The DnD main event queue. */
     229    RTCMTList<VBOXDNDEVENT>    lstEvtQueue;
     230    /** Semaphore for waiting on main event queue
     231     *  events. */
     232    RTSEMEVENT                 hEvtQueueSem;
     233    /** List of drag'n drop windows. At
     234     *  the moment only one source is supported. */
     235    RTCMTList<VBoxDnDWnd*>     lstWnd;
     236
     237} VBOXDNDCONTEXT, *PVBOXDNDCONTEXT;
     238static VBOXDNDCONTEXT gCtx = {0};
     239
     240/**
     241 * Everything which is required to successfully start
     242 * a drag'n drop operation via DoDragDrop().
     243 */
     244typedef struct VBOXDNDSTARTUPINFO
     245{
     246    /** Our DnD data object, holding
     247     *  the raw DnD data. */
     248    VBoxDnDDataObject         *pDataObject;
     249    /** The drop source for sending the
     250     *  DnD request to a IDropTarget. */
     251    VBoxDnDDropSource         *pDropSource;
     252    /** The DnD effects which are wanted / allowed. */
     253    DWORD                      dwOKEffects;
     254
     255} VBOXDNDSTARTUPINFO, *PVBOXDNDSTARTUPINFO;
     256
     257/**
     258 * Class for handling a DnD proxy window.
     259 ** @todo Unify this and VBoxClient's DragInstance!
     260 */
     261class VBoxDnDWnd
     262{
     263    /**
     264     * Current state of a DnD proxy
     265     * window.
     266     */
     267    enum State
     268    {
     269        Uninitialized = 0,
     270        Initialized,
     271        Dragging,
     272        Dropped,
     273        Canceled
     274    };
     275
     276    /**
     277     * Current operation mode of
     278     * a DnD proxy window.
     279     */
     280    enum Mode
     281    {
     282        /** Unknown mode. */
     283        Unknown = 0,
     284        /** Host to guest. */
     285        HG,
     286        /** Guest to host. */
     287        GH
     288    };
     289
     290public:
     291
     292    VBoxDnDWnd(void);
     293    virtual ~VBoxDnDWnd(void);
     294
     295public:
     296
     297    int Initialize(PVBOXDNDCONTEXT pContext);
     298
     299public:
     300
     301    /** The window's thread for the native message pump and
     302     *  OLE context. */
     303    static int Thread(RTTHREAD hThread, void *pvUser);
     304
     305public:
     306
     307    static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM lParam);
     308    /** The per-instance wndproc routine. */
     309    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
     310
     311public:
     312
     313#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     314    int RegisterAsDropTarget(void);
     315    int UnregisterAsDropTarget(void);
     316#endif
     317
     318public:
     319
     320    int OnCreate(void);
     321    void OnDestroy(void);
     322
     323    /* H->G */
     324    int OnHgEnter(const RTCList<RTCString> &formats, uint32_t uAllActions);
     325    int OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAllActions);
     326    int OnHgDrop(void);
     327    int OnHgLeave(void);
     328    int OnHgDataReceived(const void *pvData, uint32_t cData);
     329    int OnHgCancel(void);
     330
     331#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     332    /* G->H */
     333    int OnGhIsDnDPending(uint32_t uScreenID);
     334    int OnGhDropped(const char *pszFormats, uint32_t cbFormats, uint32_t uDefAction);
     335#endif
     336
     337    int ProcessEvent(PVBOXDNDEVENT pEvent);
     338
     339public:
     340
     341    int hide(void);
     342
     343protected:
     344
     345    int dragRelease(void);
     346    int makeFullscreen(void);
     347    void reset(void);
     348
     349public: /** @todo Make protected! */
     350
     351    /** Pointer to DnD context. */
     352    PVBOXDNDCONTEXT            pContext;
     353    RTCRITSECT                 mCritSect;
     354    RTSEMEVENT                 mEventSem;
     355#ifdef RT_OS_WINDOWS
     356    /** The window's handle. */
     357    HWND                       hWnd;
     358    /** List of allowed MIME types this
     359     *  client can handle. Make this a per-instance
     360     *  property so that we can selectively allow/forbid
     361     *  certain types later on runtime. */
     362    RTCList<RTCString>         lstAllowedFormats;
     363    /** List of formats for the current
     364     *  drag'n drop operation. */
     365    RTCList<RTCString>         lstFormats;
     366    /** Flags of all current drag'n drop
     367     *  actions allowed. */
     368    uint32_t                   uAllActions;
     369    /** The startup information required
     370     *  for the actual DoDragDrop() call. */
     371    VBOXDNDSTARTUPINFO         startupInfo;
     372    /** Is the left mouse button being pressed
     373     *  currently while being in this window? */
     374    bool                       mfMouseButtonDown;
     375# ifdef VBOX_WITH_DRAG_AND_DROP_GH
     376    IDropTarget               *pDropTarget;
     377# endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     378#else
     379    /** @todo Implement me. */
     380#endif
     381
     382    /** The window's own HGCM client ID. */
     383    uint32_t                   mClientID;
     384    /** The current operation mode. */
     385    Mode                       mMode;
     386    /** The current state. */
     387    State                      mState;
     388    RTCString                  mFormatRequested;
     389    RTCList<RTCString>         mLstFormats;
     390    RTCList<RTCString>         mLstActions;
     391};
    162392#endif /* __VBOXTRAYDND__H */
    163393
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp

    r49947 r50101  
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    355355                    RTMemFree(pBuf);
    356356                }
     357                else
     358                    rc = VERR_NO_MEMORY;
     359
     360                if (RT_FAILURE(rc))
     361                    hr = DV_E_FORMATETC;
    357362            }
    358363        }
     
    362367    {
    363368        LogFlowFunc(("Copying medium ...\n"));
    364         switch(pThisMedium->tymed)
     369        switch (pThisMedium->tymed)
    365370        {
    366371
    367372        case TYMED_HGLOBAL:
    368             pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, NULL);
     373            pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
     374                                                         pThisFormat->cfFormat, NULL);
    369375            break;
    370376
     
    373379        }
    374380
    375         pMedium->tymed                  = pThisFormat->tymed;
     381        pMedium->tymed          = pThisFormat->tymed;
    376382        pMedium->pUnkForRelease = NULL;
    377383    }
     
    569575                 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    570576                 pFormatEtc->dwAspect));
     577
    571578    return false;
    572 
    573579}
    574580
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