static void xtest_init_devices(void)
{
    ScreenRec screen;

    /* random stuff that needs initialization */
    memset(&screen, 0, sizeof(screen));
    screenInfo.numScreens = 1;
    screenInfo.screens[0] = &screen;
    screen.myNum = 0;
    screen.id = 100;
    screen.width = 640;
    screen.height = 480;
    screen.DeviceCursorInitialize = device_cursor_init;
    dixResetPrivates();
    InitAtoms();

    /* this also inits the xtest devices */
    InitCoreDevices();

    g_assert(xtestpointer);
    g_assert(xtestkeyboard);
    g_assert(IsXTestDevice(xtestpointer, NULL));
    g_assert(IsXTestDevice(xtestkeyboard, NULL));
    g_assert(IsXTestDevice(xtestpointer, inputInfo.pointer));
    g_assert(IsXTestDevice(xtestkeyboard, inputInfo.keyboard));
    g_assert(GetXTestDevice(inputInfo.pointer) == xtestpointer);
    g_assert(GetXTestDevice(inputInfo.keyboard) == xtestkeyboard);
}
Exemple #2
0
void
XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
{
    EventListPtr        events;
    int                 nevents, i;
    DeviceIntPtr        ptr;

    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
     * post through the attached master pointer we'd get duplicate events.
     *
     * if dev is a master keyboard, post through the XTEST device
     *
     * if dev is a floating slave, post through the device itself.
     */

    if (IsMaster(dev))
        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
    else if (!dev->u.master)
        ptr = dev;
    else
        return;

    events = InitEventList(GetMaximumEventsNum());
    OsBlockSignals();
    nevents = GetPointerEvents(events, ptr,
                               press ? ButtonPress : ButtonRelease, button,
                               0 /* flags */, 0 /* first */,
                               0 /* num_val */, NULL);
    OsReleaseSignals();

    for (i = 0; i < nevents; i++)
        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);

    FreeEventList(events, GetMaximumEventsNum());
}
static int
remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
              int flags[MAXDEVICES])
{
    DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
    int rc = Success;

    if (r->return_mode != XIAttachToMaster &&
        r->return_mode != XIFloating)
        return BadValue;

    rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
    if (rc != Success)
        goto unwind;

    if (!IsMaster(ptr))
    {
        client->errorValue = r->deviceid;
        rc = BadDevice;
        goto unwind;
    }

    /* XXX: For now, don't allow removal of VCP, VCK */
    if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard)
    {
        rc = BadDevice;
        goto unwind;
    }


    ptr = GetMaster(ptr, MASTER_POINTER);
    rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
    if (rc != Success)
        goto unwind;
    keybd = GetMaster(ptr, MASTER_KEYBOARD);
    rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
    if (rc != Success)
        goto unwind;

    XTestptr = GetXTestDevice(ptr);
    rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess);
    if (rc != Success)
        goto unwind;

    XTestkeybd = GetXTestDevice(keybd);
    rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client,
                         DixDestroyAccess);
    if (rc != Success)
        goto unwind;

    disable_clientpointer(ptr);

    /* Disabling sends the devices floating, reattach them if
     * desired. */
    if (r->return_mode == XIAttachToMaster)
    {
        DeviceIntPtr attached,
                     newptr,
                     newkeybd;

        rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess);
        if (rc != Success)
            goto unwind;

        if (!IsMaster(newptr))
        {
            client->errorValue = r->return_pointer;
            rc = BadDevice;
            goto unwind;
        }

        rc = dixLookupDevice(&newkeybd, r->return_keyboard,
                             client, DixAddAccess);
        if (rc != Success)
            goto unwind;

        if (!IsMaster(newkeybd))
        {
            client->errorValue = r->return_keyboard;
            rc = BadDevice;
            goto unwind;
        }

        for (attached = inputInfo.devices; attached; attached = attached->next)
        {
            if (!IsMaster(attached)) {
                if (GetMaster(attached, MASTER_ATTACHED) == ptr)
                {
                    AttachDevice(client, attached, newptr);
                    flags[attached->id] |= XISlaveAttached;
                }
                if (GetMaster(attached, MASTER_ATTACHED) == keybd)
                {
                    AttachDevice(client, attached, newkeybd);
                    flags[attached->id] |= XISlaveAttached;
                }
            }
        }
    }

    /* can't disable until we removed pairing */
    keybd->spriteInfo->paired = NULL;
    ptr->spriteInfo->paired = NULL;
    XTestptr->spriteInfo->paired = NULL;
    XTestkeybd->spriteInfo->paired = NULL;

    /* disable the remove the devices, XTest devices must be done first
       else the sprites they rely on will be destroyed  */
    DisableDevice(XTestptr, FALSE);
    DisableDevice(XTestkeybd, FALSE);
    DisableDevice(keybd, FALSE);
    DisableDevice(ptr, FALSE);
    flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached;
    flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached;
    flags[keybd->id] |= XIDeviceDisabled;
    flags[ptr->id] |= XIDeviceDisabled;

    RemoveDevice(XTestptr, FALSE);
    RemoveDevice(XTestkeybd, FALSE);
    RemoveDevice(keybd, FALSE);
    RemoveDevice(ptr, FALSE);
    flags[XTestptr->id] |= XISlaveRemoved;
    flags[XTestkeybd->id] |= XISlaveRemoved;
    flags[keybd->id] |= XIMasterRemoved;
    flags[ptr->id] |= XIMasterRemoved;

unwind:
    return rc;
}
static int
ProcXTestFakeInput(ClientPtr client)
{
    REQUEST(xXTestFakeInputReq);
    int nev, n, type, rc;
    xEvent *ev;
    DeviceIntPtr dev = NULL;
    WindowPtr root;
    Bool extension = FALSE;
    ValuatorMask mask;
    int valuators[MAX_VALUATORS] = { 0 };
    int numValuators = 0;
    int firstValuator = 0;
    int nevents = 0;
    int i;
    int base = 0;
    int flags = 0;
    int need_ptr_update = 1;

    nev = (stuff->length << 2) - sizeof(xReq);
    if ((nev % sizeof(xEvent)) || !nev)
        return BadLength;
    nev /= sizeof(xEvent);
    UpdateCurrentTime();
    ev = (xEvent *) &((xReq *) stuff)[1];
    type = ev->u.u.type & 0177;

    if (type >= EXTENSION_EVENT_BASE) {
        extension = TRUE;

        /* check device */
        rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
                             DixWriteAccess);
        if (rc != Success) {
            client->errorValue = stuff->deviceid & 0177;
            return rc;
        }

        /* check type */
        type -= DeviceValuator;
        switch (type) {
        case XI_DeviceKeyPress:
        case XI_DeviceKeyRelease:
            if (!dev->key) {
                client->errorValue = ev->u.u.type;
                return BadValue;
            }
            break;
        case XI_DeviceButtonPress:
        case XI_DeviceButtonRelease:
            if (!dev->button) {
                client->errorValue = ev->u.u.type;
                return BadValue;
            }
            break;
        case XI_DeviceMotionNotify:
            if (!dev->valuator) {
                client->errorValue = ev->u.u.type;
                return BadValue;
            }
            break;
        case XI_ProximityIn:
        case XI_ProximityOut:
            if (!dev->proximity) {
                client->errorValue = ev->u.u.type;
                return BadValue;
            }
            break;
        default:
            client->errorValue = ev->u.u.type;
            return BadValue;
        }

        /* check validity */
        if (nev == 1 && type == XI_DeviceMotionNotify)
            return BadLength;   /* DevMotion must be followed by DevValuator */

        if (type == XI_DeviceMotionNotify) {
            firstValuator = ((deviceValuator *) (ev + 1))->first_valuator;
            if (firstValuator > dev->valuator->numAxes) {
                client->errorValue = ev->u.u.type;
                return BadValue;
            }

            if (ev->u.u.detail == xFalse)
                flags |= POINTER_ABSOLUTE;
        }
        else {
            firstValuator = 0;
            flags |= POINTER_ABSOLUTE;
        }

        if (nev > 1 && !dev->valuator) {
            client->errorValue = firstValuator;
            return BadValue;
        }

        /* check validity of valuator events */
        base = firstValuator;
        for (n = 1; n < nev; n++) {
            deviceValuator *dv = (deviceValuator *) (ev + n);
            if (dv->type != DeviceValuator) {
                client->errorValue = dv->type;
                return BadValue;
            }
            if (dv->first_valuator != base) {
                client->errorValue = dv->first_valuator;
                return BadValue;
            }
            switch (dv->num_valuators) {
            case 6:
                valuators[base + 5] = dv->valuator5;
            case 5:
                valuators[base + 4] = dv->valuator4;
            case 4:
                valuators[base + 3] = dv->valuator3;
            case 3:
                valuators[base + 2] = dv->valuator2;
            case 2:
                valuators[base + 1] = dv->valuator1;
            case 1:
                valuators[base] = dv->valuator0;
                break;
            default:
                client->errorValue = dv->num_valuators;
                return BadValue;
            }

            base += dv->num_valuators;
            numValuators += dv->num_valuators;

            if (firstValuator + numValuators > dev->valuator->numAxes) {
                client->errorValue = dv->num_valuators;
                return BadValue;
            }
        }
        type = type - XI_DeviceKeyPress + KeyPress;

    }
    else {
        if (nev != 1)
            return BadLength;
        switch (type) {
        case KeyPress:
        case KeyRelease:
            dev = PickKeyboard(client);
            break;
        case ButtonPress:
        case ButtonRelease:
            dev = PickPointer(client);
            break;
        case MotionNotify:
            dev = PickPointer(client);
            valuators[0] = ev->u.keyButtonPointer.rootX;
            valuators[1] = ev->u.keyButtonPointer.rootY;
            numValuators = 2;
            firstValuator = 0;
            if (ev->u.u.detail == xFalse)
                flags = POINTER_ABSOLUTE | POINTER_DESKTOP;
            break;
        default:
            client->errorValue = ev->u.u.type;
            return BadValue;
        }

        /* Technically the protocol doesn't allow for BadAccess here but
         * this can only happen when all MDs are disabled.  */
        if (!dev)
            return BadAccess;

        dev = GetXTestDevice(dev);
    }


    /* If the event has a time set, wait for it to pass */
    if (ev->u.keyButtonPointer.time) {
        TimeStamp activateTime;
        CARD32 ms;

        activateTime = currentTime;
        ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
        if (ms < activateTime.milliseconds)
            activateTime.months++;
        activateTime.milliseconds = ms;
        ev->u.keyButtonPointer.time = 0;

        /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer
         * extension) for code similar to this */

        if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) {
            return BadAlloc;
        }
        /* swap the request back so we can simply re-execute it */
        if (client->swapped) {
            (void) XTestSwapFakeInput(client, (xReq *) stuff);
            swaps(&stuff->length);
        }
        ResetCurrentRequest(client);
        client->sequence--;
        return Success;
    }

    switch (type) {
    case KeyPress:
    case KeyRelease:
        if (!dev->key)
            return BadDevice;

        if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
            ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) {
            client->errorValue = ev->u.u.detail;
            return BadValue;
        }

        need_ptr_update = 0;
        break;
    case MotionNotify:
        if (!dev->valuator)
            return BadDevice;

        if (!(extension || ev->u.keyButtonPointer.root == None)) {
            rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root,
                                 client, DixGetAttrAccess);
            if (rc != Success)
                return rc;
            if (root->parent) {
                client->errorValue = ev->u.keyButtonPointer.root;
                return BadValue;
            }

            /* Add the root window's offset to the valuators */
            if ((flags & POINTER_ABSOLUTE) && firstValuator <= 1 && numValuators > 0) {
                if (firstValuator == 0)
                    valuators[0] += root->drawable.pScreen->x;
                if (firstValuator < 2 && firstValuator + numValuators > 1)
                    valuators[1 - firstValuator] += root->drawable.pScreen->y;
            }
        }
        if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) {
            client->errorValue = ev->u.u.detail;
            return BadValue;
        }

        /* FIXME: Xinerama! */

        break;
    case ButtonPress:
    case ButtonRelease:
        if (!dev->button)
            return BadDevice;

        if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) {
            client->errorValue = ev->u.u.detail;
            return BadValue;
        }
        break;
    }
    if (screenIsSaved == SCREEN_SAVER_ON)
        dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);

    switch (type) {
    case MotionNotify:
        valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
        nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
        break;
    case ButtonPress:
    case ButtonRelease:
        valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
        nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
                                   flags, &mask);
        break;
    case KeyPress:
    case KeyRelease:
        nevents =
            GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
        break;
    }

    for (i = 0; i < nevents; i++)
        mieqProcessDeviceEvent(dev, &xtest_evlist[i], miPointerGetScreen(inputInfo.pointer));

    if (need_ptr_update)
        miPointerUpdateSprite(dev);
    return Success;
}