Ejemplo n.º 1
0
/**
 * Send an absolute position event to the display device.
 * @note all calls out of this object are made with no locks held!
 * @param  x  Cursor X position in pixels relative to the first screen, where
 *            (1, 1) is the upper left corner.
 * @param  y  Cursor Y position in pixels relative to the first screen, where
 *            (1, 1) is the upper left corner.
 */
HRESULT Mouse::i_reportAbsEventToDisplayDevice(int32_t x, int32_t y)
{
    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);

    if (x != mcLastX || y != mcLastY)
    {
        pDisplay->i_reportHostCursorPosition(x - 1, y - 1);
    }
    return S_OK;
}
Ejemplo n.º 2
0
/**
 * Convert an (X, Y) value pair in screen co-ordinates (starting from 1) to a
 * value from VMMDEV_MOUSE_RANGE_MIN to VMMDEV_MOUSE_RANGE_MAX.  Sets the
 * optional validity value to false if the pair is not on an active screen and
 * to true otherwise.
 * @note      since guests with recent versions of X.Org use a different method
 *            to everyone else to map the valuator value to a screen pixel (they
 *            multiply by the screen dimension, do a floating point divide by
 *            the valuator maximum and round the result, while everyone else
 *            does truncating integer operations) we adjust the value we send
 *            so that it maps to the right pixel both when the result is rounded
 *            and when it is truncated.
 *
 * @returns   COM status value
 */
HRESULT Mouse::convertDisplayRes(LONG x, LONG y, int32_t *pxAdj, int32_t *pyAdj,
                                 bool *pfValid)
{
    AssertPtrReturn(pxAdj, E_POINTER);
    AssertPtrReturn(pyAdj, E_POINTER);
    AssertPtrNullReturn(pfValid, E_POINTER);
    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);
    /** The amount to add to the result (multiplied by the screen width/height)
     * to compensate for differences in guest methods for mapping back to
     * pixels */
    enum { ADJUST_RANGE = - 3 * VMMDEV_MOUSE_RANGE / 4 };

    if (pfValid)
        *pfValid = true;
    if (!(mfVMMDevGuestCaps & VMMDEV_MOUSE_NEW_PROTOCOL))
    {
        ULONG displayWidth, displayHeight;
        /* Takes the display lock */
        HRESULT rc = pDisplay->getScreenResolution(0, &displayWidth,
                                                   &displayHeight, NULL);
        if (FAILED(rc))
            return rc;

        *pxAdj = displayWidth ?   (x * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
                                / (LONG) displayWidth: 0;
        *pyAdj = displayHeight ?   (y * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
                                 / (LONG) displayHeight: 0;
    }
    else
    {
        int32_t x1, y1, x2, y2;
        /* Takes the display lock */
        pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2);
        *pxAdj = x1 < x2 ?   ((x - x1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
                           / (x2 - x1) : 0;
        *pyAdj = y1 < y2 ?   ((y - y1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
                           / (y2 - y1) : 0;
        if (   *pxAdj < VMMDEV_MOUSE_RANGE_MIN
            || *pxAdj > VMMDEV_MOUSE_RANGE_MAX
            || *pyAdj < VMMDEV_MOUSE_RANGE_MIN
            || *pyAdj > VMMDEV_MOUSE_RANGE_MAX)
            if (pfValid)
                *pfValid = false;
    }
    return S_OK;
}
Ejemplo n.º 3
0
/** Report the front-end's mouse handling capabilities to the VMM device and
 * thus to the guest.
 * @note all calls out of this object are made with no locks held! */
HRESULT Mouse::updateVMMDevMouseCaps(uint32_t fCapsAdded,
                                     uint32_t fCapsRemoved)
{
    VMMDevMouseInterface *pVMMDev = mParent->getVMMDevMouseInterface();
    if (!pVMMDev)
        return E_FAIL;  /* No assertion, as the front-ends can send events
                         * at all sorts of inconvenient times. */
    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    if (pDisplay == NULL)
        return E_FAIL;
    PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
    if (!pVMMDevPort)
        return E_FAIL;  /* same here */

    int rc = pVMMDevPort->pfnUpdateMouseCapabilities(pVMMDevPort, fCapsAdded,
                                                     fCapsRemoved);
    if (RT_FAILURE(rc))
        return E_FAIL;
    return pDisplay->i_reportHostCursorCapabilities(fCapsAdded, fCapsRemoved);
}
Ejemplo n.º 4
0
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
HRESULT Mouse::putEventMultiTouch(LONG aCount,
                                  LONG64 *paContacts,
                                  ULONG aScanTime)
{
    if (aCount >= 256)
    {
         return E_INVALIDARG;
    }

    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);

    HRESULT rc = S_OK;

    uint64_t* pau64Contacts = NULL;
    uint8_t cContacts = 0;

    /* Deliver 0 contacts too, touch device may use this to reset the state. */
    if (aCount > 0)
    {
        /* Create a copy with converted coords. */
        pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
        if (pau64Contacts)
        {
            int32_t x1, y1, x2, y2;
            /* Takes the display lock */
            pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2);

            LONG i;
            for (i = 0; i < aCount; i++)
            {
                uint32_t u32Lo = RT_LO_U32(paContacts[i]);
                uint32_t u32Hi = RT_HI_U32(paContacts[i]);
                int32_t x = (int16_t)u32Lo;
                int32_t y = (int16_t)(u32Lo >> 16);
                uint8_t contactId =  RT_BYTE1(u32Hi);
                bool fInContact   = (RT_BYTE2(u32Hi) & 0x1) != 0;
                bool fInRange     = (RT_BYTE2(u32Hi) & 0x2) != 0;

                LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
                         __FUNCTION__, i, x, y, contactId, fInContact, fInRange));

                /* Framebuffer dimensions are 0,0 width, height, that is x2,y2 are exclusive,
                 * while coords are inclusive.
                 */
                int32_t xAdj = x1 < x2 ?   ((x - 1 - x1) * VMMDEV_MOUSE_RANGE)
                                         / (x2 - x1) : 0;
                int32_t yAdj = y1 < y2 ?   ((y - 1 - y1) * VMMDEV_MOUSE_RANGE)
                                         / (y2 - y1) : 0;

                bool fValid = (   xAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && xAdj <= VMMDEV_MOUSE_RANGE_MAX
                               && yAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && yAdj <= VMMDEV_MOUSE_RANGE_MAX);

                if (fValid)
                {
                    uint8_t fu8 =   (fInContact? 0x01: 0x00)
                                  | (fInRange?   0x02: 0x00);
                    pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
                                                                    (uint16_t)yAdj,
                                                                    RT_MAKE_U16(contactId, fu8),
                                                                    0);
                    cContacts++;
                }
            }
        }
        else
        {
Ejemplo n.º 5
0
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
HRESULT Mouse::putEventMultiTouch(LONG aCount,
                                  LONG64 *paContacts,
                                  ULONG aScanTime)
{
    if (aCount >= 256)
    {
         return E_INVALIDARG;
    }

    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);

    /* Touch events are mapped to the primary monitor, because the emulated USB
     * touchscreen device is associated with one (normally the primary) screen in the guest.
     */
    ULONG uScreenId = 0;

    ULONG cWidth  = 0;
    ULONG cHeight = 0;
    LONG  xOrigin = 0;
    LONG  yOrigin = 0;
    HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin);
    ComAssertComRCRetRC(rc);

    uint64_t* pau64Contacts = NULL;
    uint8_t cContacts = 0;

    /* Deliver 0 contacts too, touch device may use this to reset the state. */
    if (aCount > 0)
    {
        /* Create a copy with converted coords. */
        pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
        if (pau64Contacts)
        {
            int32_t x1 = xOrigin;
            int32_t y1 = yOrigin;
            int32_t x2 = x1 + cWidth;
            int32_t y2 = y1 + cHeight;

            LogRel3(("%s: screen [%d] %d,%d %d,%d\n",
                     __FUNCTION__, uScreenId, x1, y1, x2, y2));

            LONG i;
            for (i = 0; i < aCount; i++)
            {
                uint32_t u32Lo = RT_LO_U32(paContacts[i]);
                uint32_t u32Hi = RT_HI_U32(paContacts[i]);
                int32_t x = (int16_t)u32Lo;
                int32_t y = (int16_t)(u32Lo >> 16);
                uint8_t contactId =  RT_BYTE1(u32Hi);
                bool fInContact   = (RT_BYTE2(u32Hi) & 0x1) != 0;
                bool fInRange     = (RT_BYTE2(u32Hi) & 0x2) != 0;

                LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
                         __FUNCTION__, i, x, y, contactId, fInContact, fInRange));

                /* x1,y1 are inclusive and x2,y2 are exclusive,
                 * while x,y start from 1 and are inclusive.
                 */
                if (x <= x1 || x > x2 || y <= y1 || y > y2)
                {
                    /* Out of range. Skip the contact. */
                    continue;
                }

                int32_t xAdj = x1 < x2? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0;
                int32_t yAdj = y1 < y2? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0;

                bool fValid = (   xAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && xAdj <= VMMDEV_MOUSE_RANGE_MAX
                               && yAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && yAdj <= VMMDEV_MOUSE_RANGE_MAX);

                if (fValid)
                {
                    uint8_t fu8 =   (fInContact? 0x01: 0x00)
                                  | (fInRange?   0x02: 0x00);
                    pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
                                                                    (uint16_t)yAdj,
                                                                    RT_MAKE_U16(contactId, fu8),
                                                                    0);
                    cContacts++;
                }
            }
        }
        else
        {