VirtualBox

source: vbox/trunk/src/VBox/Main/MouseImpl.cpp@ 16684

Last change on this file since 16684 was 15716, checked in by vboxsync, 16 years ago

#3285: Improve error handling API to include unique error numbers
Document

  • IMouse::putMouseEvent
  • IMouse::putMouseEventAbsolute
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/* $Id: MouseImpl.cpp 15716 2008-12-22 13:36:56Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include "MouseImpl.h"
25#include "DisplayImpl.h"
26#include "VMMDev.h"
27
28#include "Logging.h"
29
30#include <VBox/pdmdrv.h>
31#include <iprt/asm.h>
32#include <VBox/VBoxDev.h>
33
34/**
35 * Mouse driver instance data.
36 */
37typedef struct DRVMAINMOUSE
38{
39 /** Pointer to the mouse object. */
40 Mouse *pMouse;
41 /** Pointer to the driver instance structure. */
42 PPDMDRVINS pDrvIns;
43 /** Pointer to the mouse port interface of the driver/device above us. */
44 PPDMIMOUSEPORT pUpPort;
45 /** Our mouse connector interface. */
46 PDMIMOUSECONNECTOR Connector;
47} DRVMAINMOUSE, *PDRVMAINMOUSE;
48
49/** Converts PDMIMOUSECONNECTOR pointer to a DRVMAINMOUSE pointer. */
50#define PDMIMOUSECONNECTOR_2_MAINMOUSE(pInterface) ( (PDRVMAINMOUSE) ((uintptr_t)pInterface - OFFSETOF(DRVMAINMOUSE, Connector)) )
51
52
53// constructor / destructor
54/////////////////////////////////////////////////////////////////////////////
55
56DEFINE_EMPTY_CTOR_DTOR (Mouse)
57
58HRESULT Mouse::FinalConstruct()
59{
60 mpDrv = NULL;
61 return S_OK;
62}
63
64void Mouse::FinalRelease()
65{
66 uninit();
67}
68
69// public methods only for internal purposes
70/////////////////////////////////////////////////////////////////////////////
71
72/**
73 * Initializes the mouse object.
74 *
75 * @returns COM result indicator
76 * @param parent handle of our parent object
77 */
78HRESULT Mouse::init (Console *parent)
79{
80 LogFlowThisFunc (("\n"));
81
82 ComAssertRet (parent, E_INVALIDARG);
83
84 /* Enclose the state transition NotReady->InInit->Ready */
85 AutoInitSpan autoInitSpan (this);
86 AssertReturn (autoInitSpan.isOk(), E_FAIL);
87
88 unconst(mParent) = parent;
89
90#ifdef RT_OS_L4
91 /* L4 console has no own mouse cursor */
92 uHostCaps = VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
93#else
94 uHostCaps = 0;
95#endif
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Uninitializes the instance and sets the ready flag to FALSE.
105 * Called either from FinalRelease() or by the parent when it gets destroyed.
106 */
107void Mouse::uninit()
108{
109 LogFlowThisFunc (("\n"));
110
111 /* Enclose the state transition Ready->InUninit->NotReady */
112 AutoUninitSpan autoUninitSpan (this);
113 if (autoUninitSpan.uninitDone())
114 return;
115
116 if (mpDrv)
117 mpDrv->pMouse = NULL;
118 mpDrv = NULL;
119
120 unconst (mParent).setNull();
121}
122
123// IMouse properties
124/////////////////////////////////////////////////////////////////////////////
125
126/**
127 * Returns whether the current setup can accept absolute mouse
128 * events.
129 *
130 * @returns COM status code
131 * @param absoluteSupported address of result variable
132 */
133STDMETHODIMP Mouse::COMGETTER(AbsoluteSupported) (BOOL *absoluteSupported)
134{
135 if (!absoluteSupported)
136 return E_POINTER;
137
138 AutoCaller autoCaller (this);
139 CheckComRCReturnRC (autoCaller.rc());
140
141 AutoWriteLock alock (this);
142
143 CHECK_CONSOLE_DRV (mpDrv);
144
145 ComAssertRet (mParent->getVMMDev(), E_FAIL);
146 ComAssertRet (mParent->getVMMDev()->getVMMDevPort(), E_FAIL);
147
148 *absoluteSupported = FALSE;
149 uint32_t mouseCaps;
150 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps);
151 *absoluteSupported = mouseCaps & VMMDEV_MOUSEGUESTWANTSABS;
152
153 return S_OK;
154}
155
156/**
157 * Returns whether the current setup can accept relative mouse
158 * events.
159 *
160 * @returns COM status code
161 * @param absoluteSupported address of result variable
162 */
163STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *needsHostCursor)
164{
165 if (!needsHostCursor)
166 return E_POINTER;
167
168 AutoCaller autoCaller (this);
169 CheckComRCReturnRC (autoCaller.rc());
170
171 AutoWriteLock alock (this);
172
173 CHECK_CONSOLE_DRV (mpDrv);
174
175 ComAssertRet (mParent->getVMMDev(), E_FAIL);
176 ComAssertRet (mParent->getVMMDev()->getVMMDevPort(), E_FAIL);
177
178 *needsHostCursor = FALSE;
179 uint32_t mouseCaps;
180 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps);
181 *needsHostCursor = mouseCaps & VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
182
183 return S_OK;
184}
185
186// IMouse methods
187/////////////////////////////////////////////////////////////////////////////
188
189/**
190 * Send a mouse event.
191 *
192 * @returns COM status code
193 * @param dx X movement
194 * @param dy Y movement
195 * @param dz Z movement
196 * @param buttonState The mouse button state
197 */
198STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG buttonState)
199{
200 HRESULT rc = S_OK;
201
202 AutoCaller autoCaller (this);
203 CheckComRCReturnRC (autoCaller.rc());
204
205 AutoWriteLock alock (this);
206
207 CHECK_CONSOLE_DRV (mpDrv);
208
209 ComAssertRet (mParent->getVMMDev(), E_FAIL);
210 ComAssertRet (mParent->getVMMDev()->getVMMDevPort(), E_FAIL);
211
212 uint32_t mouseCaps;
213 mParent->getVMMDev()->getVMMDevPort()
214 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
215 &mouseCaps);
216 /*
217 * This method being called implies that the host no
218 * longer wants to use absolute coordinates. If the VMM
219 * device isn't aware of that yet, tell it.
220 */
221 if (mouseCaps & VMMDEV_MOUSEHOSTWANTSABS)
222 {
223 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities(
224 mParent->getVMMDev()->getVMMDevPort(), uHostCaps);
225 }
226
227 uint32_t fButtons = 0;
228 if (buttonState & MouseButtonState_LeftButton)
229 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
230 if (buttonState & MouseButtonState_RightButton)
231 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
232 if (buttonState & MouseButtonState_MiddleButton)
233 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
234
235 int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, fButtons);
236 if (RT_FAILURE (vrc))
237 rc = setError (VBOX_E_IPRT_ERROR,
238 tr ("Could not send the mouse event to the virtual mouse (%Rrc)"),
239 vrc);
240
241 return rc;
242}
243
244/**
245 * Send an absolute mouse event to the VM. This only works
246 * when the required guest support has been installed.
247 *
248 * @returns COM status code
249 * @param x X position (pixel)
250 * @param y Y position (pixel)
251 * @param dz Z movement
252 * @param buttonState The mouse button state
253 */
254STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz,
255 LONG buttonState)
256{
257 HRESULT rc = S_OK;
258
259 AutoCaller autoCaller (this);
260 CheckComRCReturnRC (autoCaller.rc());
261
262 AutoWriteLock alock (this);
263
264 CHECK_CONSOLE_DRV (mpDrv);
265
266 ComAssertRet (mParent->getVMMDev(), E_FAIL);
267 ComAssertRet (mParent->getVMMDev()->getVMMDevPort(), E_FAIL);
268
269 uint32_t mouseCaps;
270 mParent->getVMMDev()->getVMMDevPort()
271 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
272 &mouseCaps);
273 /*
274 * This method being called implies that the host wants
275 * to use absolute coordinates. If the VMM device isn't
276 * aware of that yet, tell it.
277 */
278 if (!(mouseCaps & VMMDEV_MOUSEHOSTWANTSABS))
279 {
280 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities(
281 mParent->getVMMDev()->getVMMDevPort(),
282 uHostCaps | VMMDEV_MOUSEHOSTWANTSABS);
283 }
284
285 Display *pDisplay = mParent->getDisplay();
286 ComAssertRet (pDisplay, E_FAIL);
287
288 ULONG displayWidth;
289 ULONG displayHeight;
290 rc = pDisplay->COMGETTER(Width)(&displayWidth);
291 ComAssertComRCRet (rc, rc);
292 rc = pDisplay->COMGETTER(Height)(&displayHeight);
293 ComAssertComRCRet (rc, rc);
294
295 uint32_t mouseXAbs = displayWidth? (x * 0xFFFF) / displayWidth: 0;
296 uint32_t mouseYAbs = displayHeight? (y * 0xFFFF) / displayHeight: 0;
297
298 /*
299 * Send the absolute mouse position to the VMM device.
300 */
301 int vrc = mParent->getVMMDev()->getVMMDevPort()
302 ->pfnSetAbsoluteMouse(mParent->getVMMDev()->getVMMDevPort(),
303 mouseXAbs, mouseYAbs);
304 ComAssertRCRet (vrc, E_FAIL);
305
306 // Check if the guest actually wants absolute mouse positions.
307 if (mouseCaps & VMMDEV_MOUSEGUESTWANTSABS)
308 {
309 uint32_t fButtons = 0;
310 if (buttonState & MouseButtonState_LeftButton)
311 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
312 if (buttonState & MouseButtonState_RightButton)
313 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
314 if (buttonState & MouseButtonState_MiddleButton)
315 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
316
317 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz,
318 fButtons);
319 if (RT_FAILURE (vrc))
320 rc = setError (VBOX_E_IPRT_ERROR,
321 tr ("Could not send the mouse event to the virtual mouse (%Rrc)"),
322 vrc);
323 }
324
325 return rc;
326}
327
328// private methods
329/////////////////////////////////////////////////////////////////////////////
330
331/**
332 * Queries an interface to the driver.
333 *
334 * @returns Pointer to interface.
335 * @returns NULL if the interface was not supported by the driver.
336 * @param pInterface Pointer to this interface structure.
337 * @param enmInterface The requested interface identification.
338 */
339DECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
340{
341 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
342 PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
343 switch (enmInterface)
344 {
345 case PDMINTERFACE_BASE:
346 return &pDrvIns->IBase;
347 case PDMINTERFACE_MOUSE_CONNECTOR:
348 return &pDrv->Connector;
349 default:
350 return NULL;
351 }
352}
353
354
355/**
356 * Destruct a mouse driver instance.
357 *
358 * @returns VBox status.
359 * @param pDrvIns The driver instance data.
360 */
361DECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
362{
363 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
364 LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
365 if (pData->pMouse)
366 {
367 AutoWriteLock mouseLock (pData->pMouse);
368 pData->pMouse->mpDrv = NULL;
369 }
370}
371
372
373/**
374 * Construct a mouse driver instance.
375 *
376 * @returns VBox status.
377 * @param pDrvIns The driver instance data.
378 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
379 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
380 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
381 * iInstance it's expected to be used a bit in this function.
382 */
383DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
384{
385 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
386 LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
387
388 /*
389 * Validate configuration.
390 */
391 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
392 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
393 PPDMIBASE pBaseIgnore;
394 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
395 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
396 {
397 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
398 return VERR_PDM_DRVINS_NO_ATTACH;
399 }
400
401 /*
402 * IBase.
403 */
404 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
405
406 /*
407 * Get the IMousePort interface of the above driver/device.
408 */
409 pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MOUSE_PORT);
410 if (!pData->pUpPort)
411 {
412 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
413 return VERR_PDM_MISSING_INTERFACE_ABOVE;
414 }
415
416 /*
417 * Get the Mouse object pointer and update the mpDrv member.
418 */
419 void *pv;
420 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
421 if (RT_FAILURE(rc))
422 {
423 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
424 return rc;
425 }
426 pData->pMouse = (Mouse *)pv; /** @todo Check this cast! */
427 pData->pMouse->mpDrv = pData;
428
429 return VINF_SUCCESS;
430}
431
432
433/**
434 * Main mouse driver registration record.
435 */
436const PDMDRVREG Mouse::DrvReg =
437{
438 /* u32Version */
439 PDM_DRVREG_VERSION,
440 /* szDriverName */
441 "MainMouse",
442 /* pszDescription */
443 "Main mouse driver (Main as in the API).",
444 /* fFlags */
445 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
446 /* fClass. */
447 PDM_DRVREG_CLASS_MOUSE,
448 /* cMaxInstances */
449 ~0,
450 /* cbInstance */
451 sizeof(DRVMAINMOUSE),
452 /* pfnConstruct */
453 Mouse::drvConstruct,
454 /* pfnDestruct */
455 Mouse::drvDestruct,
456 /* pfnIOCtl */
457 NULL,
458 /* pfnPowerOn */
459 NULL,
460 /* pfnReset */
461 NULL,
462 /* pfnSuspend */
463 NULL,
464 /* pfnResume */
465 NULL,
466 /* pfnDetach */
467 NULL
468};
469/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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