VirtualBox

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

Last change on this file since 6381 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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