MouseImpl.cpp revision 9171169d99a08b8dba6b409f0fbc598f01b5527f
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* $Id$ */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** @file
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox COM class implementation
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (C) 2006-2012 Oracle Corporation
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This file is part of VirtualBox Open Source Edition (OSE), as
fa9e4066f08beec538e775443c5be79dd423fcabahrens * available from http://www.virtualbox.org. This file is free software;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * you can redistribute it and/or modify it under the terms of the GNU
fa9e4066f08beec538e775443c5be79dd423fcabahrens * General Public License (GPL) as published by the Free Software
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Foundation, in version 2 as it comes in the "COPYING" file of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/cpp/utils.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "MouseImpl.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "DisplayImpl.h"
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks#include "VMMDev.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "AutoCaller.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "Logging.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <VBox/vmm/pdmdrv.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <VBox/VMMDev.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/asm.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** @name Mouse device capabilities bitfield
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @{ */
fa9e4066f08beec538e775443c5be79dd423fcabahrensenum
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** The mouse device can do relative reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens MOUSE_DEVCAP_RELATIVE = 1,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The mouse device can do absolute reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens MOUSE_DEVCAP_ABSOLUTE = 2,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The mouse device can do absolute reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens MOUSE_DEVCAP_MULTI_TOUCH = 4
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks/** @} */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Mouse driver instance data.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct DRVMAINMOUSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Pointer to the mouse object. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens Mouse *pMouse;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the driver instance structure. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens PPDMDRVINS pDrvIns;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Pointer to the mouse port interface of the driver/device above us. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens PPDMIMOUSEPORT pUpPort;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Our mouse connector interface. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDMIMOUSECONNECTOR IConnector;
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The capabilities of this device. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32DevCaps;
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens// constructor / destructor
fa9e4066f08beec538e775443c5be79dd423fcabahrens/////////////////////////////////////////////////////////////////////////////
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensMouse::Mouse()
fa9e4066f08beec538e775443c5be79dd423fcabahrens : mParent(NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwMouse::~Mouse()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::FinalConstruct()
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_ZERO(mpDrv);
fa9e4066f08beec538e775443c5be79dd423fcabahrens mcLastX = 0x8000;
fa9e4066f08beec538e775443c5be79dd423fcabahrens mcLastY = 0x8000;
fa9e4066f08beec538e775443c5be79dd423fcabahrens mfLastButtons = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens mfVMMDevGuestCaps = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return BaseFinalConstruct();
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid Mouse::FinalRelease()
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uninit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BaseFinalRelease();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// public methods only for internal purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/////////////////////////////////////////////////////////////////////////////
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initializes the mouse object.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM result indicator
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param parent handle of our parent object
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::init (ConsoleMouseInterface *parent)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowThisFunc(("\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertRet(parent, E_INVALIDARG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Enclose the state transition NotReady->InInit->Ready */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoInitSpan autoInitSpan(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReturn(autoInitSpan.isOk(), E_FAIL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unconst(mParent) = parent;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unconst(mEventSource).createObject();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = mEventSource->init(static_cast<IMouse*>(this));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertComRCReturnRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.init(mEventSource, VBoxEventType_OnGuestMouse,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, 0, 0, 0, 0, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Confirm a successful initialization */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw autoInitSpan.setSucceeded();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Uninitializes the instance and sets the ready flag to FALSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Called either from FinalRelease() or by the parent when it gets destroyed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid Mouse::uninit()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowThisFunc(("\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Enclose the state transition Ready->InUninit->NotReady */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoUninitSpan autoUninitSpan(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (autoUninitSpan.uninitDone())
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i])
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mpDrv[i]->pMouse = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mpDrv[i] = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.uninit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unconst(mEventSource).setNull();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unconst(mParent) = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// IMouse properties
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/////////////////////////////////////////////////////////////////////////////
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** Report the front-end's mouse handling capabilities to the VMM device and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * thus to the guest.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note all calls out of this object are made with no locks held! */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::updateVMMDevMouseCaps(uint32_t fCapsAdded,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t fCapsRemoved)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VMMDevMouseInterface *pVMMDev = mParent->getVMMDevMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pVMMDev)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_FAIL; /* No assertion, as the front-ends can send events
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * at all sorts of inconvenient times. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pVMMDevPort)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_FAIL; /* same here */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = pVMMDevPort->pfnUpdateMouseCapabilities(pVMMDevPort, fCapsAdded,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fCapsRemoved);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return RT_SUCCESS(rc) ? S_OK : E_FAIL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept absolute
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param absoluteSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(AbsoluteSupported) (BOOL *absoluteSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!absoluteSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_POINTER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *absoluteSupported = supportsAbs();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept relative
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param relativeSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(RelativeSupported) (BOOL *relativeSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!relativeSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_POINTER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *relativeSupported = supportsRel();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept multi-touch
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param multiTouchSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(MultiTouchSupported) (BOOL *multiTouchSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!multiTouchSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_POINTER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *multiTouchSupported = supportsMT();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the guest can currently switch to drawing the mouse cursor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * itself if it is asked to by the front-end.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pfNeedsHostCursor address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pfNeedsHostCursor)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_POINTER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pfNeedsHostCursor = guestNeedsHostCursor();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// IMouse methods
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/////////////////////////////////////////////////////////////////////////////
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** Converts a bitfield containing information about mouse buttons currently
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * held down from the format used by the front-end to the format used by PDM
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and the emulated pointing devices. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic uint32_t mouseButtonsToPDM(LONG buttonState)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t fButtons = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buttonState & MouseButtonState_LeftButton)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buttonState & MouseButtonState_RightButton)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buttonState & MouseButtonState_MiddleButton)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buttonState & MouseButtonState_XButton1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons |= PDMIMOUSEPORT_BUTTON_X1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buttonState & MouseButtonState_XButton2)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons |= PDMIMOUSEPORT_BUTTON_X2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return fButtons;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(EventSource)(IEventSource ** aEventSource)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw CheckComArgOutPointerValid(aEventSource);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw // no need to lock - lifetime constant
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mEventSource.queryInterfaceTo(aEventSource);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a relative pointer event to the relative device we deem most
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * appropriate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t dw, uint32_t fButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (dx || dy || dz || dw || fButtons != mfLastButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMIMOUSEPORT pUpPort = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pUpPort = mpDrv[i]->pUpPort;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pUpPort)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_FAILURE(vrc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return setError(VBOX_E_IPRT_ERROR,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vrc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mfLastButtons = fButtons;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send an absolute pointer event to the emulated absolute device we deem most
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * appropriate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportAbsEventToMouseDev(int32_t x, int32_t y,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t dz, int32_t dw, uint32_t fButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( x < VMMDEV_MOUSE_RANGE_MIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || x > VMMDEV_MOUSE_RANGE_MAX)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( y < VMMDEV_MOUSE_RANGE_MIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || y > VMMDEV_MOUSE_RANGE_MAX)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ( x != mcLastX || y != mcLastY
fa9e4066f08beec538e775443c5be79dd423fcabahrens || dz || dw || fButtons != mfLastButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens PPDMIMOUSEPORT pUpPort = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pUpPort = mpDrv[i]->pUpPort;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pUpPort)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return S_OK;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens int vrc = pUpPort->pfnPutEventAbs(pUpPort, x, y, dz,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_FAILURE(vrc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return setError(VBOX_E_IPRT_ERROR,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vrc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mfLastButtons = fButtons;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportMultiTouchEventToDevice(uint8_t cContacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const uint64_t *pau64Contacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32ScanTime)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT hrc = S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMIMOUSEPORT pUpPort = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks if ( mpDrv[i]
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MULTI_TOUCH))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pUpPort = mpDrv[i]->pUpPort;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks if (pUpPort)
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks {
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks int vrc = pUpPort->pfnPutEventMultiTouch(pUpPort, cContacts, pau64Contacts, u32ScanTime);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_FAILURE(vrc))
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks hrc = setError(VBOX_E_IPRT_ERROR,
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks tr("Could not send the multi-touch event to the virtual device (%Rrc)"),
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks vrc);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens hrc = E_UNEXPECTED;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return hrc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send an absolute position event to the VMM device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note all calls out of this object are made with no locks held!
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportAbsEventToVMMDev(int32_t x, int32_t y)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VMMDevMouseInterface *pVMMDev = mParent->getVMMDevMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertRet(pVMMDev, E_FAIL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertRet(pVMMDevPort, E_FAIL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (x != mcLastX || y != mcLastY)
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort,
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks x, y);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_FAILURE(vrc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return setError(VBOX_E_IPRT_ERROR,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vrc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send an absolute pointer event to a pointing device (the VMM device if
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * possible or whatever emulated absolute device seems best to us if not).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportAbsEvent(int32_t x, int32_t y,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t dz, int32_t dw, uint32_t fButtons,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fUsesVMMDevEvent)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** If we are using the VMMDev to report absolute position but without
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * VMMDev IRQ support then we need to send a small "jiggle" to the emulated
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * relative mouse device to alert the guest to changes. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG cJiggle = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (vmmdevCanAbs())
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send the absolute mouse position to the VMM device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (x != mcLastX || y != mcLastY)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportAbsEventToVMMDev(x, y);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cJiggle = !fUsesVMMDevEvent;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportRelEventToMouseDev(cJiggle, 0, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportAbsEventToMouseDev(x, y, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mcLastX = x;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mcLastY = y;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid Mouse::fireMouseEvent(bool fAbsolute, LONG x, LONG y, LONG dz, LONG dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG fButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* If mouse button is pressed, we generate new event, to avoid reusable events coalescing and thus
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dropping key press events */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw GuestMouseEventMode_T mode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fAbsolute)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mode = GuestMouseEventMode_Absolute;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mode = GuestMouseEventMode_Relative;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fButtons != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VBoxEventDesc evDesc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.init(mEventSource, VBoxEventType_OnGuestMouse, mode, x, y,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.fire(0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.reinit(VBoxEventType_OnGuestMouse, mode, x, y, dz, dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.fire(0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid Mouse::fireMultiTouchEvent(uint8_t cContacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const LONG64 *paContacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32ScanTime)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray<SHORT> xPositions(cContacts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray<SHORT> yPositions(cContacts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray<USHORT> contactIds(cContacts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray<USHORT> contactFlags(cContacts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint8_t i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < cContacts; i++)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32Lo = RT_LO_U32(paContacts[i]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32Hi = RT_HI_U32(paContacts[i]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw xPositions[i] = (int16_t)u32Lo;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw yPositions[i] = (int16_t)(u32Lo >> 16);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw contactIds[i] = RT_BYTE1(u32Hi);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw contactFlags[i] = RT_BYTE2(u32Hi);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VBoxEventDesc evDesc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.init(mEventSource, VBoxEventType_OnGuestMultiTouch,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cContacts, ComSafeArrayAsInParam(xPositions), ComSafeArrayAsInParam(yPositions),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComSafeArrayAsInParam(contactIds), ComSafeArrayAsInParam(contactFlags), u32ScanTime);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.fire(0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a relative mouse event to the guest.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note the VMMDev capability change is so that the guest knows we are sending
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * real events over the PS/2 device and not dummy events to signal the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * arrival of new absolute pointer data
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param dx X movement
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param dy Y movement
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param dz Z movement
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fButtons The mouse button state
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG fButtons)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t fButtonsAdj;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dx, dy, dz, dw));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtonsAdj = mouseButtonsToPDM(fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Make sure that the guest knows that we are sending real movement
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * events to the PS/2 device and not just dummy wake-up ones. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw updateVMMDevMouseCaps(0, VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportRelEventToMouseDev(dx, dy, dz, dw, fButtonsAdj);
4c841f6070b4f88f9dc008de526b313bbebd4e32marks
4c841f6070b4f88f9dc008de526b313bbebd4e32marks fireMouseEvent(false, dx, dy, dz, dw, fButtons);
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
4c841f6070b4f88f9dc008de526b313bbebd4e32marks}
4c841f6070b4f88f9dc008de526b313bbebd4e32marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Convert an (X, Y) value pair in screen co-ordinates (starting from 1) to a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * value from VMMDEV_MOUSE_RANGE_MIN to VMMDEV_MOUSE_RANGE_MAX. Sets the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * optional validity value to false if the pair is not on an active screen and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to true otherwise.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note since guests with recent versions of X.Org use a different method
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to everyone else to map the valuator value to a screen pixel (they
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * multiply by the screen dimension, do a floating point divide by
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the valuator maximum and round the result, while everyone else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * does truncating integer operations) we adjust the value we send
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * so that it maps to the right pixel both when the result is rounded
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and when it is truncated.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status value
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::convertDisplayRes(LONG x, LONG y, int32_t *pxAdj, int32_t *pyAdj,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool *pfValid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pxAdj, E_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pyAdj, E_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrNullReturn(pfValid, E_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertRet(pDisplay, E_FAIL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** The amount to add to the result (multiplied by the screen width/height)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to compensate for differences in guest methods for mapping back to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * pixels */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enum { ADJUST_RANGE = - 3 * VMMDEV_MOUSE_RANGE / 4 };
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pfValid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pfValid = true;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!(mfVMMDevGuestCaps & VMMDEV_MOUSE_NEW_PROTOCOL))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ULONG displayWidth, displayHeight;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Takes the display lock */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = pDisplay->getScreenResolution(0, &displayWidth,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &displayHeight, NULL, NULL, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
bda89588bd7667394a834e8a9a34612cce2ae9c3jp *pxAdj = displayWidth ? (x * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
bda89588bd7667394a834e8a9a34612cce2ae9c3jp / (LONG) displayWidth: 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pyAdj = displayHeight ? (y * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw / (LONG) displayHeight: 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t x1, y1, x2, y2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Takes the display lock */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pxAdj = x1 < x2 ? ((x - x1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw / (x2 - x1) : 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pyAdj = y1 < y2 ? ((y - y1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw / (y2 - y1) : 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( *pxAdj < VMMDEV_MOUSE_RANGE_MIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || *pxAdj > VMMDEV_MOUSE_RANGE_MAX
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || *pyAdj < VMMDEV_MOUSE_RANGE_MIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || *pyAdj > VMMDEV_MOUSE_RANGE_MAX)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pfValid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pfValid = false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send an absolute mouse event to the VM. This requires either VirtualBox-
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specific drivers installed in the guest or absolute pointing device
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * emulation.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note the VMMDev capability change is so that the guest knows we are sending
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * dummy events over the PS/2 device to signal the arrival of new
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * absolute pointer data, and not pointer real movement data
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note all calls out of this object are made with no locks held!
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param x X position (pixel), starting from 1
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param y Y position (pixel), starting from 1
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param dz Z movement
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fButtons The mouse button state
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz, LONG dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG fButtons)
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks{
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks AutoCaller autoCaller(this);
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks if (FAILED(autoCaller.rc())) return autoCaller.rc();
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d, fButtons=0x%x\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw __PRETTY_FUNCTION__, x, y, dz, dw, fButtons));
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t xAdj, yAdj;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t fButtonsAdj;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fValid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @todo the front end should do this conversion to avoid races */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @note Or maybe not... races are pretty inherent in everything done in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * this object and not really bad as far as I can see. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = convertDisplayRes(x, y, &xAdj, &yAdj, &fValid);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(rc)) return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fButtonsAdj = mouseButtonsToPDM(fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* If we are doing old-style (IRQ-less) absolute reporting to the VMM
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * device then make sure the guest is aware of it, so that it knows to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ignore relative movement on the PS/2 device. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw updateVMMDevMouseCaps(VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fValid)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportAbsEvent(xAdj, yAdj, dz, dw, fButtonsAdj,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_BOOL( mfVMMDevGuestCaps
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw & VMMDEV_MOUSE_NEW_PROTOCOL));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fireMouseEvent(true, x, y, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a multi-touch event. This requires multi-touch pointing device emulation.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @note all calls out of this object are made with no locks held!
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aCount Number of contacts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aContacts Information about each contact.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aScanTime Timestamp.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutEventMultiTouch(LONG aCount,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComSafeArrayIn(LONG64, aContacts),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ULONG aScanTime)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoCaller autoCaller(this);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (FAILED(autoCaller.rc())) return autoCaller.rc();
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray <LONG64> arrayContacts(ComSafeArrayInArg(aContacts));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogRel3(("%s: aCount %d(actual %d), aScanTime %u\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw __FUNCTION__, aCount, arrayContacts.size(), aScanTime));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = S_OK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((LONG)arrayContacts.size() >= aCount)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG64* paContacts = arrayContacts.raw();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = putEventMultiTouch(aCount, paContacts, aScanTime);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = E_INVALIDARG;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a multi-touch event. Version for scripting languages.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aCount Number of contacts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aContacts Information about each contact.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aScanTime Timestamp.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutEventMultiTouchString(LONG aCount,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw IN_BSTR aContacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ULONG aScanTime)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @todo implement: convert the string to LONG64 array and call putEventMultiTouch. */
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks NOREF(aCount);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks NOREF(aContacts);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NOREF(aScanTime);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks return E_NOTIMPL;
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks}
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
fa9e4066f08beec538e775443c5be79dd423fcabahrens// private methods
fa9e4066f08beec538e775443c5be79dd423fcabahrens/////////////////////////////////////////////////////////////////////////////
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
fa9e4066f08beec538e775443c5be79dd423fcabahrensHRESULT Mouse::putEventMultiTouch(LONG aCount,
fa9e4066f08beec538e775443c5be79dd423fcabahrens LONG64 *paContacts,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ULONG aScanTime)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (aCount >= 256)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_INVALIDARG;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertRet(pDisplay, E_FAIL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Touch events are mapped to the primary monitor, because the emulated USB
fa9e4066f08beec538e775443c5be79dd423fcabahrens * touchscreen device is associated with one (normally the primary) screen in the guest.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ULONG uScreenId = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ULONG cWidth = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ULONG cHeight = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG xOrigin = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG yOrigin = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComAssertComRCRetRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t* pau64Contacts = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint8_t cContacts = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Deliver 0 contacts too, touch device may use this to reset the state. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (aCount > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Create a copy with converted coords. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pau64Contacts)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
bda89588bd7667394a834e8a9a34612cce2ae9c3jp int32_t x1 = xOrigin;
bda89588bd7667394a834e8a9a34612cce2ae9c3jp int32_t y1 = yOrigin;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int32_t x2 = x1 + cWidth;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t y2 = y1 + cHeight;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogRel3(("%s: screen [%d] %d,%d %d,%d\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw __FUNCTION__, uScreenId, x1, y1, x2, y2));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LONG i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < aCount; i++)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t u32Lo = RT_LO_U32(paContacts[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint32_t u32Hi = RT_HI_U32(paContacts[i]);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t x = (int16_t)u32Lo;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t y = (int16_t)(u32Lo >> 16);
29a0b7379cd3103841d05e3ed04486412049acccmarks uint8_t contactId = RT_BYTE1(u32Hi);
29a0b7379cd3103841d05e3ed04486412049acccmarks bool fInContact = (RT_BYTE2(u32Hi) & 0x1) != 0;
29a0b7379cd3103841d05e3ed04486412049acccmarks bool fInRange = (RT_BYTE2(u32Hi) & 0x2) != 0;
29a0b7379cd3103841d05e3ed04486412049acccmarks
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
29a0b7379cd3103841d05e3ed04486412049acccmarks __FUNCTION__, i, x, y, contactId, fInContact, fInRange));
29a0b7379cd3103841d05e3ed04486412049acccmarks
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks /* x1,y1 are inclusive and x2,y2 are exclusive,
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks * while x,y start from 1 and are inclusive.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (x <= x1 || x > x2 || y <= y1 || y > y2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Out of range. Skip the contact. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens int32_t xAdj = x1 < x2? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t yAdj = y1 < y2? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && xAdj <= VMMDEV_MOUSE_RANGE_MAX
fa9e4066f08beec538e775443c5be79dd423fcabahrens && yAdj >= VMMDEV_MOUSE_RANGE_MIN
fa9e4066f08beec538e775443c5be79dd423fcabahrens && yAdj <= VMMDEV_MOUSE_RANGE_MAX);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fValid)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint8_t fu8 = (fInContact? 0x01: 0x00)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw | (fInRange? 0x02: 0x00);
fa9e4066f08beec538e775443c5be79dd423fcabahrens pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (uint16_t)yAdj,
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_MAKE_U16(contactId, fu8),
fa9e4066f08beec538e775443c5be79dd423fcabahrens 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cContacts++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = E_OUTOFMEMORY;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (SUCCEEDED(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = reportMultiTouchEventToDevice(cContacts, cContacts? pau64Contacts: NULL, (uint32_t)aScanTime);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Send the original contact information. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens fireMultiTouchEvent(cContacts, cContacts? paContacts: NULL, (uint32_t)aScanTime);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTMemTmpFree(pau64Contacts);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Does the guest currently rely on the host to draw the mouse cursor or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * can it switch to doing it itself in software? */
fa9e4066f08beec538e775443c5be79dd423fcabahrensbool Mouse::guestNeedsHostCursor(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RT_BOOL(mfVMMDevGuestCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Check what sort of reporting can be done using the devices currently
fa9e4066f08beec538e775443c5be79dd423fcabahrens * enabled. Does not consider the VMM device. */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid Mouse::getDeviceCaps(bool *pfAbs, bool *pfRel, bool *pfMT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fAbsDev = false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fRelDev = false;
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fMTDev = false;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (mpDrv[i])
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fAbsDev = true;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fRelDev = true;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MULTI_TOUCH)
fa9e4066f08beec538e775443c5be79dd423fcabahrens fMTDev = true;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pfAbs)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *pfAbs = fAbsDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pfRel)
fa9e4066f08beec538e775443c5be79dd423fcabahrens *pfRel = fRelDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pfMT)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pfMT = fMTDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Does the VMM device currently support absolute reporting? */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwbool Mouse::vmmdevCanAbs(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fRelDev;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens getDeviceCaps(NULL, &fRelDev, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (mfVMMDevGuestCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens && fRelDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Does the VMM device currently support absolute reporting? */
fa9e4066f08beec538e775443c5be79dd423fcabahrensbool Mouse::deviceCanAbs(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fAbsDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw getDeviceCaps(&fAbsDev, NULL, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return fAbsDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Can we currently send relative events to the guest? */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwbool Mouse::supportsRel(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fRelDev;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw getDeviceCaps(NULL, &fRelDev, NULL);
bda89588bd7667394a834e8a9a34612cce2ae9c3jp return fRelDev;
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks}
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Can we currently send absolute events to the guest? */
fa9e4066f08beec538e775443c5be79dd423fcabahrensbool Mouse::supportsAbs(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fAbsDev;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw getDeviceCaps(&fAbsDev, NULL, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return fAbsDev || vmmdevCanAbs();
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** Can we currently send absolute events to the guest? */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwbool Mouse::supportsMT(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fMTDev;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw getDeviceCaps(NULL, NULL, &fMTDev);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return fMTDev;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** Check what sort of reporting can be done using the devices currently
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * enabled (including the VMM device) and notify the guest and the front-end.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid Mouse::sendMouseCapsNotifications(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fAbsDev, fRelDev, fMTDev, fCanAbs, fNeedsHostCursor;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw getDeviceCaps(&fAbsDev, &fRelDev, &fMTDev);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fCanAbs = supportsAbs();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fNeedsHostCursor = guestNeedsHostCursor();
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fAbsDev)
fa9e4066f08beec538e775443c5be79dd423fcabahrens updateVMMDevMouseCaps(VMMDEV_MOUSE_HOST_HAS_ABS_DEV, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens updateVMMDevMouseCaps(0, VMMDEV_MOUSE_HOST_HAS_ABS_DEV);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** @todo this call takes the Console lock in order to update the cached
fa9e4066f08beec538e775443c5be79dd423fcabahrens * callback data atomically. However I can't see any sign that the cached
fa9e4066f08beec538e775443c5be79dd423fcabahrens * data is ever used again. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens mParent->onMouseCapabilityChange(fCanAbs, fRelDev, fMTDev, fNeedsHostCursor);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * A virtual device is notifying us about its current state and capabilities
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLCALLBACK(void) Mouse::mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMT)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (fRel)
fa9e4066f08beec538e775443c5be79dd423fcabahrens pDrv->u32DevCaps |= MOUSE_DEVCAP_RELATIVE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->u32DevCaps &= ~MOUSE_DEVCAP_RELATIVE;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (fAbs)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock pDrv->u32DevCaps |= MOUSE_DEVCAP_ABSOLUTE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->u32DevCaps &= ~MOUSE_DEVCAP_ABSOLUTE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fMT)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->u32DevCaps |= MOUSE_DEVCAP_MULTI_TOUCH;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
fa9e4066f08beec538e775443c5be79dd423fcabahrens pDrv->u32DevCaps &= ~MOUSE_DEVCAP_MULTI_TOUCH;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pMouse->sendMouseCapsNotifications();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @interface_method_impl{PDMIBASE,pfnQueryInterface}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pDrv->IConnector);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Destruct a mouse driver instance.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * @returns VBox status.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pDrvIns The driver instance data.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensDECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThis->pMouse)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
bda89588bd7667394a834e8a9a34612cce2ae9c3jp AutoWriteLock mouseLock(pThis->pMouse COMMA_LOCKVAL_SRC_POS);
bda89588bd7667394a834e8a9a34612cce2ae9c3jp for (unsigned cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThis->pMouse->mpDrv[cDev] == pThis)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThis->pMouse->mpDrv[cDev] = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Construct a mouse driver instance.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @copydoc FNPDMDRVCONSTRUCT
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensDECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
bda89588bd7667394a834e8a9a34612cce2ae9c3jp{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Validate configuration.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ("Configuration error: Not possible to attach anything to this driver!\n"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VERR_PDM_DRVINS_NO_ATTACH);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * IBase.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->IConnector.pfnReportModes = Mouse::mouseReportModes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the IMousePort interface of the above driver/device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pThis->pUpPort)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VERR_PDM_MISSING_INTERFACE_ABOVE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the Mouse object pointer and update the mpDrv member.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw void *pv;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (RT_FAILURE(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->pMouse = (Mouse *)pv; /** @todo Check this cast! */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned cDev;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoReadLock mouseLock(pThis->pMouse COMMA_LOCKVAL_SRC_POS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pThis->pMouse->mpDrv[cDev])
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->pMouse->mpDrv[cDev] = pThis;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (cDev == MOUSE_MAX_DEVICES)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_NO_MORE_HANDLES;
7106075a406fbb9356893d9b37bc3053be6071c1marks
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Main mouse driver registration record.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwconst PDMDRVREG Mouse::DrvReg =
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* u32Version */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDM_DRVREG_VERSION,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* szName */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "MainMouse",
de122929e7c37df60cbea70616404e22d20e025bmarks /* szRCMod */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* szR0Mod */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pszDescription */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "Main mouse driver (Main as in the API).",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* fFlags */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* fClass. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDM_DRVREG_CLASS_MOUSE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* cMaxInstances */
de122929e7c37df60cbea70616404e22d20e025bmarks ~0U,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* cbInstance */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof(DRVMAINMOUSE),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnConstruct */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Mouse::drvConstruct,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnDestruct */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Mouse::drvDestruct,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnRelocate */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnIOCtl */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnPowerOn */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnReset */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnSuspend */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnResume */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnAttach */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnDetach */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnPowerOff */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnSoftReset */
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* u32EndVersion */
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDM_DRVREG_VERSION
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw};
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* vi: set tabstop=4 shiftwidth=4 expandtab: */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw