VirtualBox

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

Last change on this file since 4044 was 4015, checked in by vboxsync, 17 years ago

Use pdmdrv.h or pdmdev.h where appropriate.

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