MouseImpl.cpp revision 9171169d99a08b8dba6b409f0fbc598f01b5527f
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox COM class implementation
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (C) 2006-2012 Oracle Corporation
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/** @name Mouse device capabilities bitfield
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** The mouse device can do relative reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The mouse device can do absolute reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The mouse device can do absolute reporting */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Mouse driver instance data.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Pointer to the mouse object. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the driver instance structure. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Pointer to the mouse port interface of the driver/device above us. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** Our mouse connector interface. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /** The capabilities of this device. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens// constructor / destructor
fa9e4066f08beec538e775443c5be79dd423fcabahrens/////////////////////////////////////////////////////////////////////////////
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// public methods only for internal purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/////////////////////////////////////////////////////////////////////////////
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initializes the mouse object.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM result indicator
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param parent handle of our parent object
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Enclose the state transition NotReady->InInit->Ready */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = mEventSource->init(static_cast<IMouse*>(this));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.init(mEventSource, VBoxEventType_OnGuestMouse,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, 0, 0, 0, 0, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Confirm a successful initialization */
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 /* Enclose the state transition Ready->InUninit->NotReady */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// IMouse properties
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 VMMDevMouseInterface *pVMMDev = mParent->getVMMDevMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return E_FAIL; /* No assertion, as the front-ends can send events
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * at all sorts of inconvenient times. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = pVMMDevPort->pfnUpdateMouseCapabilities(pVMMDevPort, fCapsAdded,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept absolute
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param absoluteSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(AbsoluteSupported) (BOOL *absoluteSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept relative
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param relativeSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(RelativeSupported) (BOOL *relativeSupported)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns whether the currently active device portfolio can accept multi-touch
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mouse events.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param multiTouchSupported address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(MultiTouchSupported) (BOOL *multiTouchSupported)
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 * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pfNeedsHostCursor address of result variable
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw// IMouse methods
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. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::COMGETTER(EventSource)(IEventSource ** aEventSource)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw // no need to lock - lifetime constant
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a relative pointer event to the relative device we deem most
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * appropriate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send an absolute pointer event to the emulated absolute device we deem most
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * appropriate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportAbsEventToMouseDev(int32_t x, int32_t y,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportMultiTouchEventToDevice(uint8_t cContacts,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned i;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < MOUSE_MAX_DEVICES; ++i)
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks int vrc = pUpPort->pfnPutEventMultiTouch(pUpPort, cContacts, pau64Contacts, u32ScanTime);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks tr("Could not send the multi-touch event to the virtual device (%Rrc)"),
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 * @returns COM status code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::reportAbsEventToVMMDev(int32_t x, int32_t y)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VMMDevMouseInterface *pVMMDev = mParent->getVMMDevMouseInterface();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
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 * @returns COM status code
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 * Send the absolute mouse position to the VMM device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = reportRelEventToMouseDev(cJiggle, 0, dz, dw, fButtons);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid Mouse::fireMouseEvent(bool fAbsolute, LONG x, LONG y, LONG dz, LONG dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* If mouse button is pressed, we generate new event, to avoid reusable events coalescing and thus
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dropping key press events */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.init(mEventSource, VBoxEventType_OnGuestMouse, mode, x, y,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mMouseEvent.reinit(VBoxEventType_OnGuestMouse, mode, x, y, dz, dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < cContacts; i++)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw evDesc.init(mEventSource, VBoxEventType_OnGuestMultiTouch,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cContacts, ComSafeArrayAsInParam(xPositions), ComSafeArrayAsInParam(yPositions),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ComSafeArrayAsInParam(contactIds), ComSafeArrayAsInParam(contactFlags), u32ScanTime);
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 * @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
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
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);
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 * @returns COM status value
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwHRESULT Mouse::convertDisplayRes(LONG x, LONG y, int32_t *pxAdj, int32_t *pyAdj,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
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 /* Takes the display lock */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = pDisplay->getScreenResolution(0, &displayWidth,
bda89588bd7667394a834e8a9a34612cce2ae9c3jp *pxAdj = displayWidth ? (x * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pyAdj = displayHeight ? (y * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Takes the display lock */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pxAdj = x1 < x2 ? ((x - x1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pyAdj = y1 < y2 ? ((y - y1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
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 * @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
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz, LONG dw,
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d, fButtons=0x%x\n",
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 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 * 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 * @returns COM status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aCount Number of contacts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aContacts Information about each contact.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aScanTime Timestamp.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw com::SafeArray <LONG64> arrayContacts(ComSafeArrayInArg(aContacts));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw __FUNCTION__, aCount, arrayContacts.size(), aScanTime));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a multi-touch event. Version for scripting languages.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns COM status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aCount Number of contacts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aContacts Information about each contact.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param aScanTime Timestamp.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwSTDMETHODIMP Mouse::PutEventMultiTouchString(LONG aCount,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @todo implement: convert the string to LONG64 array and call putEventMultiTouch. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens// private methods
fa9e4066f08beec538e775443c5be79dd423fcabahrens/////////////////////////////////////////////////////////////////////////////
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
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.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Deliver 0 contacts too, touch device may use this to reset the state. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Create a copy with converted coords. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < aCount; i++)
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
29a0b7379cd3103841d05e3ed04486412049acccmarks __FUNCTION__, i, x, y, contactId, fInContact, fInRange));
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks /* x1,y1 are inclusive and x2,y2 are exclusive,
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks * while x,y start from 1 and are inclusive.
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Out of range. Skip the contact. */
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 pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = reportMultiTouchEventToDevice(cContacts, cContacts? pau64Contacts: NULL, (uint32_t)aScanTime);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Send the original contact information. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens fireMultiTouchEvent(cContacts, cContacts? paContacts: NULL, (uint32_t)aScanTime);
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? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RT_BOOL(mfVMMDevGuestCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
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 bool fAbsDev = false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fRelDev = false;
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool fMTDev = false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Does the VMM device currently support absolute reporting? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (mfVMMDevGuestCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Does the VMM device currently support absolute reporting? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Can we currently send relative events to the guest? */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** Can we currently send absolute events to the guest? */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** Can we currently send absolute events to the guest? */
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 bool fAbsDev, fRelDev, fMTDev, fCanAbs, fNeedsHostCursor;
fa9e4066f08beec538e775443c5be79dd423fcabahrens updateVMMDevMouseCaps(VMMDEV_MOUSE_HOST_HAS_ABS_DEV, 0);
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);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * A virtual device is notifying us about its current state and capabilities
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLCALLBACK(void) Mouse::mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @interface_method_impl{PDMIBASE,pfnQueryInterface}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pDrv->IConnector);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Destruct a mouse driver instance.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * @returns VBox status.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pDrvIns The driver instance data.
fa9e4066f08beec538e775443c5be79dd423fcabahrensDECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
bda89588bd7667394a834e8a9a34612cce2ae9c3jp AutoWriteLock mouseLock(pThis->pMouse COMMA_LOCKVAL_SRC_POS);
bda89588bd7667394a834e8a9a34612cce2ae9c3jp for (unsigned cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Construct a mouse driver instance.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @copydoc FNPDMDRVCONSTRUCT
fa9e4066f08beec538e775443c5be79dd423fcabahrensDECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens PDRVMAINMOUSE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Validate configuration.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ("Configuration error: Not possible to attach anything to this driver!\n"),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->IConnector.pfnReportModes = Mouse::mouseReportModes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the IMousePort interface of the above driver/device.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the Mouse object pointer and update the mpDrv member.
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThis->pMouse = (Mouse *)pv; /** @todo Check this cast! */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AutoReadLock mouseLock(pThis->pMouse COMMA_LOCKVAL_SRC_POS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Main mouse driver registration record.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* u32Version */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* szName */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "MainMouse",
de122929e7c37df60cbea70616404e22d20e025bmarks /* szRCMod */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* szR0Mod */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pszDescription */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "Main mouse driver (Main as in the API).",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* fFlags */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* fClass. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* cMaxInstances */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* cbInstance */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnConstruct */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnDestruct */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnRelocate */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnIOCtl */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnPowerOn */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnReset */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnSuspend */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnResume */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnAttach */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnDetach */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* pfnPowerOff */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pfnSoftReset */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* u32EndVersion */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* vi: set tabstop=4 shiftwidth=4 expandtab: */