VirtualBox

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

Last change on this file since 15404 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • 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 14772 2008-11-28 12:41:22Z 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()
224 ->pfnSetMouseCapabilities(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 (E_FAIL, tr ("Could not send the mouse event to the virtual mouse (%Rrc)"),
238 vrc);
239
240 return rc;
241}
242
243/**
244 * Send an absolute mouse event to the VM. This only works
245 * when the required guest support has been installed.
246 *
247 * @returns COM status code
248 * @param x X position (pixel)
249 * @param y Y position (pixel)
250 * @param dz Z movement
251 * @param buttonState The mouse button state
252 */
253STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz,
254 LONG buttonState)
255{
256 HRESULT rc = S_OK;
257
258 AutoCaller autoCaller (this);
259 CheckComRCReturnRC (autoCaller.rc());
260
261 AutoWriteLock alock (this);
262
263 CHECK_CONSOLE_DRV (mpDrv);
264
265 ComAssertRet (mParent->getVMMDev(), E_FAIL);
266 ComAssertRet (mParent->getVMMDev()->getVMMDevPort(), E_FAIL);
267
268 uint32_t mouseCaps;
269 mParent->getVMMDev()->getVMMDevPort()
270 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
271 &mouseCaps);
272 /*
273 * This method being called implies that the host wants
274 * to use absolute coordinates. If the VMM device isn't
275 * aware of that yet, tell it.
276 */
277 if (!(mouseCaps & VMMDEV_MOUSEHOSTWANTSABS))
278 {
279 mParent->getVMMDev()->getVMMDevPort()
280 ->pfnSetMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
281 uHostCaps | VMMDEV_MOUSEHOSTWANTSABS);
282 }
283
284 Display *pDisplay = mParent->getDisplay();
285 ComAssertRet (pDisplay, E_FAIL);
286
287 ULONG displayWidth;
288 ULONG displayHeight;
289 rc = pDisplay->COMGETTER(Width)(&displayWidth);
290 ComAssertComRCRet (rc, rc);
291 rc = pDisplay->COMGETTER(Height)(&displayHeight);
292 ComAssertComRCRet (rc, rc);
293
294 uint32_t mouseXAbs = displayWidth? (x * 0xFFFF) / displayWidth: 0;
295 uint32_t mouseYAbs = displayHeight? (y * 0xFFFF) / displayHeight: 0;
296
297 /*
298 * Send the absolute mouse position to the VMM device
299 */
300 int vrc = mParent->getVMMDev()->getVMMDevPort()
301 ->pfnSetAbsoluteMouse(mParent->getVMMDev()->getVMMDevPort(),
302 mouseXAbs, mouseYAbs);
303 ComAssertRCRet (vrc, E_FAIL);
304
305 // check if the guest actually wants absolute mouse positions
306 if (mouseCaps & VMMDEV_MOUSEGUESTWANTSABS)
307 {
308 uint32_t fButtons = 0;
309 if (buttonState & MouseButtonState_LeftButton)
310 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
311 if (buttonState & MouseButtonState_RightButton)
312 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
313 if (buttonState & MouseButtonState_MiddleButton)
314 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
315
316 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz,
317 fButtons);
318 if (RT_FAILURE (vrc))
319 rc = setError (E_FAIL, tr ("Could not send the mouse event to the virtual mouse (%Rrc)"),
320 vrc);
321 }
322
323 return rc;
324}
325
326// private methods
327/////////////////////////////////////////////////////////////////////////////
328
329/**
330 * Queries an interface to the driver.
331 *
332 * @returns Pointer to interface.
333 * @returns NULL if the interface was not supported by the driver.
334 * @param pInterface Pointer to this interface structure.
335 * @param enmInterface The requested interface identification.
336 */
337DECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
338{
339 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
340 PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
341 switch (enmInterface)
342 {
343 case PDMINTERFACE_BASE:
344 return &pDrvIns->IBase;
345 case PDMINTERFACE_MOUSE_CONNECTOR:
346 return &pDrv->Connector;
347 default:
348 return NULL;
349 }
350}
351
352
353/**
354 * Destruct a mouse driver instance.
355 *
356 * @returns VBox status.
357 * @param pDrvIns The driver instance data.
358 */
359DECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
360{
361 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
362 LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
363 if (pData->pMouse)
364 {
365 AutoWriteLock mouseLock (pData->pMouse);
366 pData->pMouse->mpDrv = NULL;
367 }
368}
369
370
371/**
372 * Construct a mouse driver instance.
373 *
374 * @returns VBox status.
375 * @param pDrvIns The driver instance data.
376 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
377 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
378 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
379 * iInstance it's expected to be used a bit in this function.
380 */
381DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
382{
383 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
384 LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
385
386 /*
387 * Validate configuration.
388 */
389 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
390 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
391 PPDMIBASE pBaseIgnore;
392 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
393 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
394 {
395 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
396 return VERR_PDM_DRVINS_NO_ATTACH;
397 }
398
399 /*
400 * IBase.
401 */
402 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
403
404 /*
405 * Get the IMousePort interface of the above driver/device.
406 */
407 pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MOUSE_PORT);
408 if (!pData->pUpPort)
409 {
410 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
411 return VERR_PDM_MISSING_INTERFACE_ABOVE;
412 }
413
414 /*
415 * Get the Mouse object pointer and update the mpDrv member.
416 */
417 void *pv;
418 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
419 if (RT_FAILURE(rc))
420 {
421 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
422 return rc;
423 }
424 pData->pMouse = (Mouse *)pv; /** @todo Check this cast! */
425 pData->pMouse->mpDrv = pData;
426
427 return VINF_SUCCESS;
428}
429
430
431/**
432 * Main mouse driver registration record.
433 */
434const PDMDRVREG Mouse::DrvReg =
435{
436 /* u32Version */
437 PDM_DRVREG_VERSION,
438 /* szDriverName */
439 "MainMouse",
440 /* pszDescription */
441 "Main mouse driver (Main as in the API).",
442 /* fFlags */
443 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
444 /* fClass. */
445 PDM_DRVREG_CLASS_MOUSE,
446 /* cMaxInstances */
447 ~0,
448 /* cbInstance */
449 sizeof(DRVMAINMOUSE),
450 /* pfnConstruct */
451 Mouse::drvConstruct,
452 /* pfnDestruct */
453 Mouse::drvDestruct,
454 /* pfnIOCtl */
455 NULL,
456 /* pfnPowerOn */
457 NULL,
458 /* pfnReset */
459 NULL,
460 /* pfnSuspend */
461 NULL,
462 /* pfnResume */
463 NULL,
464 /* pfnDetach */
465 NULL
466};
467/* 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