VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp@ 51489

Last change on this file since 51489 was 51489, checked in by vboxsync, 11 years ago

DnD: Solaris build fix; no C++11 features available (yet).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/* $Id: GuestDnDTargetImpl.cpp 51489 2014-06-02 15:28:06Z vboxsync $ */
2/** @file
3 * VBox Console COM Class implementation - Guest drag'n drop target.
4 */
5
6/*
7 * Copyright (C) 2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "GuestImpl.h"
23#include "GuestDnDTargetImpl.h"
24
25#include "Global.h"
26#include "AutoCaller.h"
27
28#include <iprt/cpp/utils.h> /* For unconst(). */
29
30#include <VBox/com/array.h>
31#include <VBox/HostServices/DragAndDropSvc.h>
32
33#ifdef LOG_GROUP
34 #undef LOG_GROUP
35#endif
36#define LOG_GROUP LOG_GROUP_GUEST_DND
37#include <VBox/log.h>
38
39
40// constructor / destructor
41/////////////////////////////////////////////////////////////////////////////
42
43DEFINE_EMPTY_CTOR_DTOR(GuestDnDTarget)
44
45HRESULT GuestDnDTarget::FinalConstruct(void)
46{
47 LogFlowThisFunc(("\n"));
48 return BaseFinalConstruct();
49}
50
51void GuestDnDTarget::FinalRelease(void)
52{
53 LogFlowThisFuncEnter();
54 uninit();
55 BaseFinalRelease();
56 LogFlowThisFuncLeave();
57}
58
59// public initializer/uninitializer for internal purposes only
60/////////////////////////////////////////////////////////////////////////////
61
62int GuestDnDTarget::init(const ComObjPtr<Guest>& pGuest)
63{
64 LogFlowThisFuncEnter();
65
66 /* Enclose the state transition NotReady->InInit->Ready. */
67 AutoInitSpan autoInitSpan(this);
68 AssertReturn(autoInitSpan.isOk(), E_FAIL);
69
70 unconst(m_pGuest) = pGuest;
71
72 /* Confirm a successful initialization when it's the case. */
73 autoInitSpan.setSucceeded();
74
75 return VINF_SUCCESS;
76}
77
78/**
79 * Uninitializes the instance.
80 * Called from FinalRelease().
81 */
82void GuestDnDTarget::uninit(void)
83{
84 LogFlowThisFunc(("\n"));
85
86 /* Enclose the state transition Ready->InUninit->NotReady. */
87 AutoUninitSpan autoUninitSpan(this);
88 if (autoUninitSpan.uninitDone())
89 return;
90}
91
92// implementation of wrapped private getters/setters for attributes
93/////////////////////////////////////////////////////////////////////////////
94
95HRESULT GuestDnDTarget::enter(ULONG aScreenId, ULONG aX, ULONG aY,
96 DnDAction_T aDefaultAction,
97 const std::vector<DnDAction_T> &aAllowedActions,
98 const std::vector<com::Utf8Str> &aFormats,
99 DnDAction_T *aResultAction)
100{
101#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
102 ReturnComNotImplemented();
103#else /* VBOX_WITH_DRAG_AND_DROP */
104
105 /* Input validation. */
106 if (aDefaultAction == DnDAction_Ignore)
107 return setError(E_INVALIDARG, tr("No default action specified"));
108 if (!aAllowedActions.size())
109 return setError(E_INVALIDARG, tr("Number of allowed actions is empty"));
110 if (!aFormats.size())
111 return setError(E_INVALIDARG, tr("Number of supported formats is empty"));
112
113 AutoCaller autoCaller(this);
114 if (FAILED(autoCaller.rc())) return autoCaller.rc();
115
116 /* Default action is ignoring. */
117 DnDAction_T resAction = DnDAction_Ignore;
118
119 /* Check & convert the drag & drop actions */
120 uint32_t uDefAction = 0;
121 uint32_t uAllowedActions = 0;
122 GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
123 aAllowedActions, &uAllowedActions);
124 /* If there is no usable action, ignore this request. */
125 if (isDnDIgnoreAction(uDefAction))
126 return S_OK;
127
128 /* Make a flat data string out of the supported format list. */
129 Utf8Str strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
130 aFormats);
131 /* If there is no valid supported format, ignore this request. */
132 if (strFormats.isEmpty())
133 return S_OK;
134
135 HRESULT hr = S_OK;
136
137 /* Adjust the coordinates in a multi-monitor setup. */
138 int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
139 if (RT_SUCCESS(rc))
140 {
141 VBOXHGCMSVCPARM paParms[8];
142 int i = 0;
143 paParms[i++].setUInt32(aScreenId);
144 paParms[i++].setUInt32(aX);
145 paParms[i++].setUInt32(aY);
146 paParms[i++].setUInt32(uDefAction);
147 paParms[i++].setUInt32(uAllowedActions);
148 paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
149 paParms[i++].setUInt32(strFormats.length() + 1);
150
151 rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_ENTER,
152 i, paParms);
153 if (RT_SUCCESS(rc))
154 {
155 GuestDnDResponse *pResp = GuestDnDInst()->response();
156 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
157 resAction = GuestDnD::toMainAction(pResp->defAction());
158 }
159 }
160
161 if (aResultAction)
162 *aResultAction = resAction;
163
164 LogFlowFunc(("hr=%Rhrc, resAction=%ld\n", hr, resAction));
165 return hr;
166#endif /* VBOX_WITH_DRAG_AND_DROP */
167}
168
169HRESULT GuestDnDTarget::move(ULONG aScreenId, ULONG aX, ULONG aY,
170 DnDAction_T aDefaultAction,
171 const std::vector<DnDAction_T> &aAllowedActions,
172 const std::vector<com::Utf8Str> &aFormats,
173 DnDAction_T *aResultAction)
174{
175#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
176 ReturnComNotImplemented();
177#else /* VBOX_WITH_DRAG_AND_DROP */
178
179 /* Input validation. */
180
181 AutoCaller autoCaller(this);
182 if (FAILED(autoCaller.rc())) return autoCaller.rc();
183
184 /* Default action is ignoring. */
185 DnDAction_T resAction = DnDAction_Ignore;
186
187 /* Check & convert the drag & drop actions. */
188 uint32_t uDefAction = 0;
189 uint32_t uAllowedActions = 0;
190 GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
191 aAllowedActions, &uAllowedActions);
192 /* If there is no usable action, ignore this request. */
193 if (isDnDIgnoreAction(uDefAction))
194 return S_OK;
195
196 /* Make a flat data string out of the supported format list. */
197 RTCString strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
198 aFormats);
199 /* If there is no valid supported format, ignore this request. */
200 if (strFormats.isEmpty())
201 return S_OK;
202
203 HRESULT hr = S_OK;
204
205 int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
206 if (RT_SUCCESS(rc))
207 {
208 VBOXHGCMSVCPARM paParms[8];
209 int i = 0;
210 paParms[i++].setUInt32(aScreenId);
211 paParms[i++].setUInt32(aX);
212 paParms[i++].setUInt32(aY);
213 paParms[i++].setUInt32(uDefAction);
214 paParms[i++].setUInt32(uAllowedActions);
215 paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
216 paParms[i++].setUInt32(strFormats.length() + 1);
217
218 rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_MOVE,
219 i, paParms);
220 if (RT_SUCCESS(rc))
221 {
222 GuestDnDResponse *pResp = GuestDnDInst()->response();
223 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
224 resAction = GuestDnD::toMainAction(pResp->defAction());
225 }
226 }
227
228 if (aResultAction)
229 *aResultAction = resAction;
230
231 LogFlowFunc(("hr=%Rhrc, *pResultAction=%ld\n", hr, resAction));
232 return hr;
233#endif /* VBOX_WITH_DRAG_AND_DROP */
234}
235
236HRESULT GuestDnDTarget::leave(ULONG uScreenId)
237{
238#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
239 ReturnComNotImplemented();
240#else /* VBOX_WITH_DRAG_AND_DROP */
241
242 AutoCaller autoCaller(this);
243 if (FAILED(autoCaller.rc())) return autoCaller.rc();
244
245 HRESULT hr = S_OK;
246 int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,
247 0 /* cParms */, NULL /* paParms */);
248 if (RT_SUCCESS(rc))
249 {
250 GuestDnDResponse *pResp = GuestDnDInst()->response();
251 if (pResp)
252 pResp->waitForGuestResponse();
253 }
254
255 LogFlowFunc(("hr=%Rhrc\n", hr));
256 return hr;
257#endif /* VBOX_WITH_DRAG_AND_DROP */
258}
259
260HRESULT GuestDnDTarget::drop(ULONG aScreenId, ULONG aX, ULONG aY,
261 DnDAction_T aDefaultAction,
262 const std::vector<DnDAction_T> &aAllowedActions,
263 const std::vector<com::Utf8Str> &aFormats,
264 com::Utf8Str &aFormat, DnDAction_T *aResultAction)
265{
266#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
267 ReturnComNotImplemented();
268#else /* VBOX_WITH_DRAG_AND_DROP */
269
270 /* Input validation. */
271
272 /* Everything else is optional. */
273
274 AutoCaller autoCaller(this);
275 if (FAILED(autoCaller.rc())) return autoCaller.rc();
276
277 /* Default action is ignoring. */
278 DnDAction_T resAction = DnDAction_Ignore;
279
280 /* Check & convert the drag & drop actions. */
281 uint32_t uDefAction = 0;
282 uint32_t uAllowedActions = 0;
283 GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
284 aAllowedActions, &uAllowedActions);
285 /* If there is no usable action, ignore this request. */
286 if (isDnDIgnoreAction(uDefAction))
287 return S_OK;
288
289 /* Make a flat data string out of the supported format list. */
290 Utf8Str strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
291 aFormats);
292 /* If there is no valid supported format, ignore this request. */
293 if (strFormats.isEmpty())
294 return S_OK;
295
296 HRESULT hr = S_OK;
297
298 /* Adjust the coordinates in a multi-monitor setup. */
299 int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
300 if (RT_SUCCESS(rc))
301 {
302 VBOXHGCMSVCPARM paParms[8];
303 int i = 0;
304 paParms[i++].setUInt32(aScreenId);
305 paParms[i++].setUInt32(aX);
306 paParms[i++].setUInt32(aY);
307 paParms[i++].setUInt32(uDefAction);
308 paParms[i++].setUInt32(uAllowedActions);
309 paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
310 paParms[i++].setUInt32(strFormats.length() + 1);
311
312 rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED,
313 i, paParms);
314 if (RT_SUCCESS(rc))
315 {
316 GuestDnDResponse *pResp = GuestDnDInst()->response();
317 if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
318 {
319 resAction = GuestDnD::toMainAction(pResp->defAction());
320 aFormat = pResp->format();
321
322 LogFlowFunc(("resFormat=%s, resAction=%RU32\n",
323 pResp->format().c_str(), pResp->defAction()));
324 }
325 }
326 }
327
328 if (aResultAction)
329 *aResultAction = resAction;
330
331 return hr;
332#endif /* VBOX_WITH_DRAG_AND_DROP */
333}
334
335HRESULT GuestDnDTarget::sendData(ULONG aScreenId,
336 const com::Utf8Str &aFormat,
337 const std::vector<BYTE> &aData,
338 ComPtr<IProgress> &aProgress)
339{
340#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
341 ReturnComNotImplemented();
342#else /* VBOX_WITH_DRAG_AND_DROP */
343
344 /* Input validation */
345
346
347 AutoCaller autoCaller(this);
348 if (FAILED(autoCaller.rc())) return autoCaller.rc();
349
350 HRESULT hr = S_OK;
351
352 VBOXHGCMSVCPARM paParms[8];
353 int i = 0;
354 paParms[i++].setUInt32(aScreenId);
355 paParms[i++].setPointer((void *)aFormat.c_str(), (uint32_t)aFormat.length() + 1);
356 paParms[i++].setUInt32((uint32_t)aFormat.length() + 1);
357 paParms[i++].setPointer((void *)aData.front(), (uint32_t)aData.size());
358 paParms[i++].setUInt32((uint32_t)aData.size());
359
360 GuestDnDResponse *pResp = GuestDnDInst()->response();
361 if (pResp)
362 {
363 /* Reset any old progress status. */
364 pResp->resetProgress(m_pGuest);
365
366 /* Note: The actual data transfer of files/directoies is performed by the
367 * DnD host service. */
368 int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA,
369 i, paParms);
370 if (RT_SUCCESS(rc))
371 {
372 /* Query the progress object to the caller. */
373 if (aProgress)
374 pResp->queryProgressTo(aProgress.asOutParam());
375 }
376 }
377
378 return hr;
379#endif /* VBOX_WITH_DRAG_AND_DROP */
380}
381
Note: See TracBrowser for help on using the repository browser.

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