xtest.c revision 65b04b38
105b261ecSmrg/*
205b261ecSmrg
34642e01fSmrg   Copyright 1992, 1998  The Open Group
405b261ecSmrg
54642e01fSmrg   Permission to use, copy, modify, distribute, and sell this software and its
64642e01fSmrg   documentation for any purpose is hereby granted without fee, provided that
74642e01fSmrg   the above copyright notice appear in all copies and that both that
84642e01fSmrg   copyright notice and this permission notice appear in supporting
94642e01fSmrg   documentation.
1005b261ecSmrg
114642e01fSmrg   The above copyright notice and this permission notice shall be included
124642e01fSmrg   in all copies or substantial portions of the Software.
1305b261ecSmrg
144642e01fSmrg   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
154642e01fSmrg   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
164642e01fSmrg   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
174642e01fSmrg   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
184642e01fSmrg   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194642e01fSmrg   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204642e01fSmrg   OTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
224642e01fSmrg   Except as contained in this notice, the name of The Open Group shall
234642e01fSmrg   not be used in advertising or otherwise to promote the sale, use or
244642e01fSmrg   other dealings in this Software without prior written authorization
254642e01fSmrg   from The Open Group.
2605b261ecSmrg
274642e01fSmrg */
2805b261ecSmrg
2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3005b261ecSmrg#include <dix-config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
354202a189Smrg#include <X11/Xatom.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "os.h"
3805b261ecSmrg#include "dixstruct.h"
3905b261ecSmrg#include "extnsionst.h"
4005b261ecSmrg#include "windowstr.h"
4105b261ecSmrg#include "inputstr.h"
4205b261ecSmrg#include "scrnintstr.h"
4305b261ecSmrg#include "dixevents.h"
4405b261ecSmrg#include "sleepuntil.h"
454642e01fSmrg#include "mi.h"
464202a189Smrg#include "xkbsrv.h"
474202a189Smrg#include "xkbstr.h"
48684baedfSmrg#include <X11/extensions/xtestproto.h>
4905b261ecSmrg#include <X11/extensions/XI.h>
5005b261ecSmrg#include <X11/extensions/XIproto.h>
514202a189Smrg#include "exglobals.h"
524202a189Smrg#include "mipointer.h"
534202a189Smrg#include "xserver-properties.h"
544202a189Smrg#include "exevents.h"
5565b04b38Smrg#include "inpututils.h"
5605b261ecSmrg
5705b261ecSmrg#include "modinit.h"
5805b261ecSmrg
5905b261ecSmrgextern int DeviceValuator;
604202a189Smrg
614202a189Smrg/* XTest events are sent during request processing and may be interruped by
624202a189Smrg * a SIGIO. We need a separate event list to avoid events overwriting each
634202a189Smrg * other's memory */
644202a189Smrgstatic EventListPtr xtest_evlist;
654202a189Smrg
664202a189Smrg/**
674202a189Smrg * xtestpointer
684202a189Smrg * is the virtual pointer for XTest. It is the first slave
694202a189Smrg * device of the VCP.
704202a189Smrg * xtestkeyboard
714202a189Smrg * is the virtual keyboard for XTest. It is the first slave
724202a189Smrg * device of the VCK
734202a189Smrg *
744202a189Smrg * Neither of these devices can be deleted.
754202a189Smrg */
764202a189SmrgDeviceIntPtr xtestpointer, xtestkeyboard;
7705b261ecSmrg
7805b261ecSmrg#ifdef PANORAMIX
7905b261ecSmrg#include "panoramiX.h"
8005b261ecSmrg#include "panoramiXsrv.h"
8105b261ecSmrg#endif
8205b261ecSmrg
8305b261ecSmrgstatic int XTestSwapFakeInput(
844642e01fSmrg        ClientPtr /* client */,
854642e01fSmrg        xReq * /* req */
864642e01fSmrg        );
8705b261ecSmrg
8805b261ecSmrg
8905b261ecSmrgstatic int
904202a189SmrgProcXTestGetVersion(ClientPtr client)
9105b261ecSmrg{
9205b261ecSmrg    xXTestGetVersionReply rep;
934642e01fSmrg    int n;
9405b261ecSmrg
9505b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGetVersionReq);
9605b261ecSmrg    rep.type = X_Reply;
9705b261ecSmrg    rep.length = 0;
9805b261ecSmrg    rep.sequenceNumber = client->sequence;
9905b261ecSmrg    rep.majorVersion = XTestMajorVersion;
10005b261ecSmrg    rep.minorVersion = XTestMinorVersion;
10105b261ecSmrg    if (client->swapped) {
1024642e01fSmrg        swaps(&rep.sequenceNumber, n);
1034642e01fSmrg        swaps(&rep.minorVersion, n);
10405b261ecSmrg    }
10505b261ecSmrg    WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
1064202a189Smrg    return Success;
10705b261ecSmrg}
10805b261ecSmrg
10905b261ecSmrgstatic int
1104202a189SmrgProcXTestCompareCursor(ClientPtr client)
11105b261ecSmrg{
11205b261ecSmrg    REQUEST(xXTestCompareCursorReq);
11305b261ecSmrg    xXTestCompareCursorReply rep;
11405b261ecSmrg    WindowPtr pWin;
11505b261ecSmrg    CursorPtr pCursor;
1164642e01fSmrg    int n, rc;
1174642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
11805b261ecSmrg
11905b261ecSmrg    REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
1204642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
12105b261ecSmrg    if (rc != Success)
12205b261ecSmrg        return rc;
12305b261ecSmrg    if (stuff->cursor == None)
1244642e01fSmrg        pCursor = NullCursor;
12505b261ecSmrg    else if (stuff->cursor == XTestCurrentCursor)
1264642e01fSmrg        pCursor = GetSpriteCursor(ptr);
12705b261ecSmrg    else {
128b86d567bSmrg        rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
129b86d567bSmrg				     client, DixReadAccess);
1304642e01fSmrg        if (rc != Success)
1314642e01fSmrg        {
1324642e01fSmrg            client->errorValue = stuff->cursor;
1334202a189Smrg            return rc;
1344642e01fSmrg        }
13505b261ecSmrg    }
13605b261ecSmrg    rep.type = X_Reply;
13705b261ecSmrg    rep.length = 0;
13805b261ecSmrg    rep.sequenceNumber = client->sequence;
13905b261ecSmrg    rep.same = (wCursor(pWin) == pCursor);
14005b261ecSmrg    if (client->swapped) {
1414642e01fSmrg        swaps(&rep.sequenceNumber, n);
14205b261ecSmrg    }
14305b261ecSmrg    WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
1444202a189Smrg    return Success;
14505b261ecSmrg}
14605b261ecSmrg
14705b261ecSmrgstatic int
1484202a189SmrgProcXTestFakeInput(ClientPtr client)
14905b261ecSmrg{
15005b261ecSmrg    REQUEST(xXTestFakeInputReq);
15105b261ecSmrg    int nev, n, type, rc;
15205b261ecSmrg    xEvent *ev;
15305b261ecSmrg    DeviceIntPtr dev = NULL;
15405b261ecSmrg    WindowPtr root;
15505b261ecSmrg    Bool extension = FALSE;
15605b261ecSmrg    deviceValuator *dv = NULL;
15765b04b38Smrg    ValuatorMask mask;
1584642e01fSmrg    int valuators[MAX_VALUATORS] = {0};
1594642e01fSmrg    int numValuators = 0;
1604642e01fSmrg    int firstValuator = 0;
161b86d567bSmrg    int nevents = 0;
1624642e01fSmrg    int i;
1634642e01fSmrg    int base = 0;
1644642e01fSmrg    int flags = 0;
1654202a189Smrg    int need_ptr_update = 1;
16605b261ecSmrg
16705b261ecSmrg    nev = (stuff->length << 2) - sizeof(xReq);
16805b261ecSmrg    if ((nev % sizeof(xEvent)) || !nev)
1694642e01fSmrg        return BadLength;
17005b261ecSmrg    nev /= sizeof(xEvent);
17105b261ecSmrg    UpdateCurrentTime();
17205b261ecSmrg    ev = (xEvent *)&((xReq *)stuff)[1];
17305b261ecSmrg    type = ev->u.u.type & 0177;
1744642e01fSmrg
17505b261ecSmrg    if (type >= EXTENSION_EVENT_BASE)
17605b261ecSmrg    {
1774642e01fSmrg        extension = TRUE;
1784642e01fSmrg
1794642e01fSmrg        /* check device */
1804642e01fSmrg        rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
1814642e01fSmrg                DixWriteAccess);
1824642e01fSmrg        if (rc != Success)
1834642e01fSmrg        {
1844642e01fSmrg            client->errorValue = stuff->deviceid & 0177;
1854642e01fSmrg            return rc;
1864642e01fSmrg        }
1874642e01fSmrg
1884642e01fSmrg        /* check type */
1894642e01fSmrg        type -= DeviceValuator;
1904642e01fSmrg        switch (type) {
1914642e01fSmrg            case XI_DeviceKeyPress:
1924642e01fSmrg            case XI_DeviceKeyRelease:
1934202a189Smrg                if (!dev->key)
1944202a189Smrg                {
1954202a189Smrg                    client->errorValue = ev->u.u.type;
1964202a189Smrg                    return BadValue;
1974202a189Smrg                }
1984202a189Smrg                break;
1994642e01fSmrg            case XI_DeviceButtonPress:
2004642e01fSmrg            case XI_DeviceButtonRelease:
2014202a189Smrg                if (!dev->button)
2024202a189Smrg                {
2034202a189Smrg                    client->errorValue = ev->u.u.type;
2044202a189Smrg                    return BadValue;
2054202a189Smrg                }
2064202a189Smrg                break;
2074642e01fSmrg            case XI_DeviceMotionNotify:
2084202a189Smrg                if (!dev->valuator)
2094202a189Smrg                {
2104202a189Smrg                    client->errorValue = ev->u.u.type;
2114202a189Smrg                    return BadValue;
2124202a189Smrg                }
2134202a189Smrg                break;
2144642e01fSmrg            case XI_ProximityIn:
2154642e01fSmrg            case XI_ProximityOut:
2164202a189Smrg                if (!dev->proximity)
2174202a189Smrg                {
2184202a189Smrg                    client->errorValue = ev->u.u.type;
2194202a189Smrg                    return BadValue;
2204202a189Smrg                }
2214642e01fSmrg                break;
2224642e01fSmrg            default:
2234642e01fSmrg                client->errorValue = ev->u.u.type;
2244642e01fSmrg                return BadValue;
2254642e01fSmrg        }
2264642e01fSmrg
2274642e01fSmrg        /* check validity */
2284642e01fSmrg        if (nev == 1 && type == XI_DeviceMotionNotify)
2294642e01fSmrg            return BadLength; /* DevMotion must be followed by DevValuator */
2304642e01fSmrg
2314642e01fSmrg        if (type == XI_DeviceMotionNotify)
2324642e01fSmrg        {
2334642e01fSmrg            firstValuator = ((deviceValuator *)(ev+1))->first_valuator;
2344642e01fSmrg            if (firstValuator > dev->valuator->numAxes)
2354642e01fSmrg            {
2364642e01fSmrg                client->errorValue = ev->u.u.type;
2374642e01fSmrg                return BadValue;
2384642e01fSmrg            }
2394642e01fSmrg
2404642e01fSmrg            if (ev->u.u.detail == xFalse)
2414642e01fSmrg                flags |= POINTER_ABSOLUTE;
2424642e01fSmrg        } else
2434642e01fSmrg        {
2444642e01fSmrg            firstValuator = 0;
2454642e01fSmrg            flags |= POINTER_ABSOLUTE;
2464642e01fSmrg        }
2474642e01fSmrg
2484202a189Smrg        if (nev > 1 && !dev->valuator)
2494642e01fSmrg        {
2504642e01fSmrg            client->errorValue = dv->first_valuator;
2514642e01fSmrg            return BadValue;
2524642e01fSmrg        }
2534642e01fSmrg
2544642e01fSmrg
2554642e01fSmrg        /* check validity of valuator events */
2564642e01fSmrg        base = firstValuator;
2574642e01fSmrg        for (n = 1; n < nev; n++)
2584642e01fSmrg        {
2594642e01fSmrg            dv = (deviceValuator *)(ev + n);
2604642e01fSmrg            if (dv->type != DeviceValuator)
2614642e01fSmrg            {
2624642e01fSmrg                client->errorValue = dv->type;
2634642e01fSmrg                return BadValue;
2644642e01fSmrg            }
2654642e01fSmrg            if (dv->first_valuator != base)
2664642e01fSmrg            {
2674642e01fSmrg                client->errorValue = dv->first_valuator;
2684642e01fSmrg                return BadValue;
2694642e01fSmrg            }
2704642e01fSmrg            switch(dv->num_valuators)
2714642e01fSmrg            {
2724642e01fSmrg                case 6: valuators[base + 5] = dv->valuator5;
2734642e01fSmrg                case 5: valuators[base + 4] = dv->valuator4;
2744642e01fSmrg                case 4: valuators[base + 3] = dv->valuator3;
2754642e01fSmrg                case 3: valuators[base + 2] = dv->valuator2;
2764642e01fSmrg                case 2: valuators[base + 1] = dv->valuator1;
2774642e01fSmrg                case 1: valuators[base] = dv->valuator0;
2784642e01fSmrg                        break;
2794642e01fSmrg                default:
2804642e01fSmrg                        client->errorValue = dv->num_valuators;
2814642e01fSmrg                        return BadValue;
2824642e01fSmrg            }
2834642e01fSmrg
2844642e01fSmrg            base += dv->num_valuators;
2854642e01fSmrg            numValuators += dv->num_valuators;
2864642e01fSmrg
2874642e01fSmrg            if (firstValuator + numValuators > dev->valuator->numAxes)
2884642e01fSmrg            {
2894642e01fSmrg                client->errorValue = dv->num_valuators;
2904642e01fSmrg                return BadValue;
2914642e01fSmrg            }
2924642e01fSmrg        }
2934642e01fSmrg        type = type - XI_DeviceKeyPress + KeyPress;
2944642e01fSmrg
2954642e01fSmrg    } else
29605b261ecSmrg    {
2974642e01fSmrg        if (nev != 1)
2984642e01fSmrg            return BadLength;
2994642e01fSmrg        switch (type)
3004642e01fSmrg        {
3014642e01fSmrg            case KeyPress:
3024642e01fSmrg            case KeyRelease:
3034642e01fSmrg                dev = PickKeyboard(client);
3044642e01fSmrg                break;
3054642e01fSmrg            case ButtonPress:
3064642e01fSmrg            case ButtonRelease:
3074642e01fSmrg                dev = PickPointer(client);
3084642e01fSmrg                break;
3094642e01fSmrg            case MotionNotify:
3104642e01fSmrg                dev = PickPointer(client);
3114642e01fSmrg                valuators[0] = ev->u.keyButtonPointer.rootX;
3124642e01fSmrg                valuators[1] = ev->u.keyButtonPointer.rootY;
3134642e01fSmrg                numValuators = 2;
3144642e01fSmrg                firstValuator = 0;
3154642e01fSmrg                if (ev->u.u.detail == xFalse)
3164642e01fSmrg                    flags = POINTER_ABSOLUTE | POINTER_SCREEN;
3174642e01fSmrg                break;
3184642e01fSmrg            default:
3194642e01fSmrg                client->errorValue = ev->u.u.type;
3204642e01fSmrg                return BadValue;
3214642e01fSmrg        }
3224642e01fSmrg
3234202a189Smrg        dev = GetXTestDevice(dev);
32405b261ecSmrg    }
3254642e01fSmrg
3264642e01fSmrg    /* If the event has a time set, wait for it to pass */
32705b261ecSmrg    if (ev->u.keyButtonPointer.time)
32805b261ecSmrg    {
3294642e01fSmrg        TimeStamp activateTime;
3304642e01fSmrg        CARD32 ms;
3314642e01fSmrg
3324642e01fSmrg        activateTime = currentTime;
3334642e01fSmrg        ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
3344642e01fSmrg        if (ms < activateTime.milliseconds)
3354642e01fSmrg            activateTime.months++;
3364642e01fSmrg        activateTime.milliseconds = ms;
3374642e01fSmrg        ev->u.keyButtonPointer.time = 0;
3384642e01fSmrg
3394202a189Smrg        /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer
3404202a189Smrg         * extension) for code similar to this */
3414642e01fSmrg
3424642e01fSmrg        if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
3434642e01fSmrg        {
3444642e01fSmrg            return BadAlloc;
3454642e01fSmrg        }
3464642e01fSmrg        /* swap the request back so we can simply re-execute it */
3474642e01fSmrg        if (client->swapped)
3484642e01fSmrg        {
3494642e01fSmrg            (void) XTestSwapFakeInput(client, (xReq *)stuff);
3504642e01fSmrg            swaps(&stuff->length, n);
3514642e01fSmrg        }
3524642e01fSmrg        ResetCurrentRequest (client);
3534642e01fSmrg        client->sequence--;
3544642e01fSmrg        return Success;
35505b261ecSmrg    }
3564642e01fSmrg
35705b261ecSmrg    switch (type)
35805b261ecSmrg    {
3594642e01fSmrg        case KeyPress:
3604642e01fSmrg        case KeyRelease:
3614202a189Smrg            if (!dev->key)
3624202a189Smrg                return BadDevice;
3634202a189Smrg
3644202a189Smrg            if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
3654202a189Smrg                ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code)
3664642e01fSmrg            {
3674642e01fSmrg                client->errorValue = ev->u.u.detail;
3684642e01fSmrg                return BadValue;
3694642e01fSmrg            }
3704202a189Smrg
3714202a189Smrg            need_ptr_update = 0;
3724642e01fSmrg            break;
3734642e01fSmrg        case MotionNotify:
3744202a189Smrg            if (!dev->valuator)
3754202a189Smrg                return BadDevice;
3764202a189Smrg
37765b04b38Smrg            if (!(extension || ev->u.keyButtonPointer.root == None))
3784642e01fSmrg            {
3794642e01fSmrg                rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root,
3804642e01fSmrg                                     client, DixGetAttrAccess);
3814642e01fSmrg                if (rc != Success)
3824642e01fSmrg                    return rc;
3834642e01fSmrg                if (root->parent)
3844642e01fSmrg                {
3854642e01fSmrg                    client->errorValue = ev->u.keyButtonPointer.root;
3864642e01fSmrg                    return BadValue;
3874642e01fSmrg                }
3884642e01fSmrg            }
3894642e01fSmrg            if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse)
3904642e01fSmrg            {
3914642e01fSmrg                client->errorValue = ev->u.u.detail;
3924642e01fSmrg                return BadValue;
3934642e01fSmrg            }
3944642e01fSmrg
3954642e01fSmrg            /* FIXME: Xinerama! */
3964642e01fSmrg
3974642e01fSmrg            break;
3984642e01fSmrg        case ButtonPress:
3994642e01fSmrg        case ButtonRelease:
4004202a189Smrg            if (!dev->button)
4014202a189Smrg                return BadDevice;
4024202a189Smrg
4034642e01fSmrg            if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
4044642e01fSmrg            {
4054642e01fSmrg                client->errorValue = ev->u.u.detail;
4064642e01fSmrg                return BadValue;
4074642e01fSmrg            }
4084642e01fSmrg            break;
40905b261ecSmrg    }
41005b261ecSmrg    if (screenIsSaved == SCREEN_SAVER_ON)
4114642e01fSmrg        dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
4124642e01fSmrg
4134642e01fSmrg    switch(type) {
4144642e01fSmrg        case MotionNotify:
41565b04b38Smrg            valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
41665b04b38Smrg            nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
4174642e01fSmrg            break;
4184642e01fSmrg        case ButtonPress:
4194642e01fSmrg        case ButtonRelease:
42065b04b38Smrg            valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
4214202a189Smrg            nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
42265b04b38Smrg                                       flags, &mask);
4234642e01fSmrg            break;
4244642e01fSmrg        case KeyPress:
4254642e01fSmrg        case KeyRelease:
4264202a189Smrg            nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
4274642e01fSmrg            break;
4284642e01fSmrg    }
4294642e01fSmrg
4304642e01fSmrg    for (i = 0; i < nevents; i++)
4314202a189Smrg        mieqProcessDeviceEvent(dev, (InternalEvent*)(xtest_evlist+i)->event, NULL);
4324642e01fSmrg
4334202a189Smrg    if (need_ptr_update)
4344202a189Smrg        miPointerUpdateSprite(dev);
4354202a189Smrg    return Success;
43605b261ecSmrg}
43705b261ecSmrg
43805b261ecSmrgstatic int
4394202a189SmrgProcXTestGrabControl(ClientPtr client)
44005b261ecSmrg{
44105b261ecSmrg    REQUEST(xXTestGrabControlReq);
44205b261ecSmrg
44305b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGrabControlReq);
44405b261ecSmrg    if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse))
44505b261ecSmrg    {
4464642e01fSmrg        client->errorValue = stuff->impervious;
4474202a189Smrg        return BadValue;
44805b261ecSmrg    }
44905b261ecSmrg    if (stuff->impervious)
4504642e01fSmrg        MakeClientGrabImpervious(client);
45105b261ecSmrg    else
4524642e01fSmrg        MakeClientGrabPervious(client);
4534202a189Smrg    return Success;
45405b261ecSmrg}
45505b261ecSmrg
45605b261ecSmrgstatic int
4574202a189SmrgProcXTestDispatch (ClientPtr client)
45805b261ecSmrg{
45905b261ecSmrg    REQUEST(xReq);
46005b261ecSmrg    switch (stuff->data)
46105b261ecSmrg    {
4624642e01fSmrg        case X_XTestGetVersion:
4634642e01fSmrg            return ProcXTestGetVersion(client);
4644642e01fSmrg        case X_XTestCompareCursor:
4654642e01fSmrg            return ProcXTestCompareCursor(client);
4664642e01fSmrg        case X_XTestFakeInput:
4674642e01fSmrg            return ProcXTestFakeInput(client);
4684642e01fSmrg        case X_XTestGrabControl:
4694642e01fSmrg            return ProcXTestGrabControl(client);
4704642e01fSmrg        default:
4714642e01fSmrg            return BadRequest;
47205b261ecSmrg    }
47305b261ecSmrg}
47405b261ecSmrg
47505b261ecSmrgstatic int
4764202a189SmrgSProcXTestGetVersion(ClientPtr client)
47705b261ecSmrg{
4784642e01fSmrg    int n;
47905b261ecSmrg    REQUEST(xXTestGetVersionReq);
48005b261ecSmrg
48105b261ecSmrg    swaps(&stuff->length, n);
48205b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGetVersionReq);
48305b261ecSmrg    swaps(&stuff->minorVersion, n);
48405b261ecSmrg    return ProcXTestGetVersion(client);
48505b261ecSmrg}
48605b261ecSmrg
48705b261ecSmrgstatic int
4884202a189SmrgSProcXTestCompareCursor(ClientPtr client)
48905b261ecSmrg{
4904642e01fSmrg    int n;
49105b261ecSmrg    REQUEST(xXTestCompareCursorReq);
49205b261ecSmrg
49305b261ecSmrg    swaps(&stuff->length, n);
49405b261ecSmrg    REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
49505b261ecSmrg    swapl(&stuff->window, n);
49605b261ecSmrg    swapl(&stuff->cursor, n);
49705b261ecSmrg    return ProcXTestCompareCursor(client);
49805b261ecSmrg}
49905b261ecSmrg
50005b261ecSmrgstatic int
5014202a189SmrgXTestSwapFakeInput(ClientPtr client, xReq *req)
50205b261ecSmrg{
5034642e01fSmrg    int nev;
5044642e01fSmrg    xEvent *ev;
50505b261ecSmrg    xEvent sev;
50605b261ecSmrg    EventSwapPtr proc;
50705b261ecSmrg
50805b261ecSmrg    nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
50905b261ecSmrg    for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
51005b261ecSmrg    {
5114642e01fSmrg        /* Swap event */
5124642e01fSmrg        proc = EventSwapVector[ev->u.u.type & 0177];
5134642e01fSmrg        /* no swapping proc; invalid event type? */
5144642e01fSmrg        if (!proc ||  proc ==  NotImplemented) {
5154642e01fSmrg            client->errorValue = ev->u.u.type;
5164642e01fSmrg            return BadValue;
5174642e01fSmrg        }
5184642e01fSmrg        (*proc)(ev, &sev);
5194642e01fSmrg        *ev = sev;
52005b261ecSmrg    }
52105b261ecSmrg    return Success;
52205b261ecSmrg}
52305b261ecSmrg
52405b261ecSmrgstatic int
5254202a189SmrgSProcXTestFakeInput(ClientPtr client)
52605b261ecSmrg{
5274642e01fSmrg    int n;
52805b261ecSmrg    REQUEST(xReq);
52905b261ecSmrg
53005b261ecSmrg    swaps(&stuff->length, n);
53105b261ecSmrg    n = XTestSwapFakeInput(client, stuff);
53205b261ecSmrg    if (n != Success)
5334642e01fSmrg        return n;
53405b261ecSmrg    return ProcXTestFakeInput(client);
53505b261ecSmrg}
53605b261ecSmrg
53705b261ecSmrgstatic int
5384202a189SmrgSProcXTestGrabControl(ClientPtr client)
53905b261ecSmrg{
5404642e01fSmrg    int n;
54105b261ecSmrg    REQUEST(xXTestGrabControlReq);
54205b261ecSmrg
54305b261ecSmrg    swaps(&stuff->length, n);
54405b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGrabControlReq);
54505b261ecSmrg    return ProcXTestGrabControl(client);
54605b261ecSmrg}
54705b261ecSmrg
54805b261ecSmrgstatic int
5494202a189SmrgSProcXTestDispatch (ClientPtr client)
55005b261ecSmrg{
55105b261ecSmrg    REQUEST(xReq);
55205b261ecSmrg    switch (stuff->data)
55305b261ecSmrg    {
5544642e01fSmrg        case X_XTestGetVersion:
5554642e01fSmrg            return SProcXTestGetVersion(client);
5564642e01fSmrg        case X_XTestCompareCursor:
5574642e01fSmrg            return SProcXTestCompareCursor(client);
5584642e01fSmrg        case X_XTestFakeInput:
5594642e01fSmrg            return SProcXTestFakeInput(client);
5604642e01fSmrg        case X_XTestGrabControl:
5614642e01fSmrg            return SProcXTestGrabControl(client);
5624642e01fSmrg        default:
5634642e01fSmrg            return BadRequest;
56405b261ecSmrg    }
56505b261ecSmrg}
5664202a189Smrg
5674202a189Smrg/**
5684202a189Smrg * Allocate an virtual slave device for xtest events, this
5694202a189Smrg * is a slave device to inputInfo master devices
5704202a189Smrg */
5714202a189Smrgvoid InitXTestDevices(void)
5724202a189Smrg{
5734202a189Smrg    if(AllocXTestDevice(serverClient, "Virtual core",
5744202a189Smrg                       &xtestpointer, &xtestkeyboard,
5754202a189Smrg                       inputInfo.pointer, inputInfo.keyboard) != Success)
5764202a189Smrg        FatalError("Failed to allocate XTest devices");
5774202a189Smrg
5784202a189Smrg    if (ActivateDevice(xtestpointer, TRUE) != Success ||
5794202a189Smrg        ActivateDevice(xtestkeyboard, TRUE) != Success)
5804202a189Smrg        FatalError("Failed to activate XTest core devices.");
5814202a189Smrg    if (!EnableDevice(xtestpointer, TRUE) ||
5824202a189Smrg        !EnableDevice(xtestkeyboard, TRUE))
5834202a189Smrg        FatalError("Failed to enable XTest core devices.");
5844202a189Smrg
5854202a189Smrg    AttachDevice(NULL, xtestpointer, inputInfo.pointer);
5864202a189Smrg    AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard);
5874202a189Smrg}
5884202a189Smrg
5894202a189Smrg/**
5904202a189Smrg * Don't allow changing the XTest property.
5914202a189Smrg */
5924202a189Smrgstatic int
5934202a189SmrgDeviceSetXTestProperty(DeviceIntPtr dev, Atom property,
5944202a189Smrg                      XIPropertyValuePtr prop, BOOL checkonly)
5954202a189Smrg{
5964202a189Smrg    if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE))
5974202a189Smrg        return BadAccess;
5984202a189Smrg
5994202a189Smrg    return Success;
6004202a189Smrg}
6014202a189Smrg
6024202a189Smrg/**
6034202a189Smrg * Allocate a device pair that is initialised as a slave
6044202a189Smrg * device with properties that identify the devices as belonging
6054202a189Smrg * to XTest subsystem.
6064202a189Smrg * This only creates the pair, Activate/Enable Device
6074202a189Smrg * still need to be called.
6084202a189Smrg */
6094202a189Smrgint AllocXTestDevice (ClientPtr client, char* name,
6104202a189Smrg                     DeviceIntPtr* ptr, DeviceIntPtr* keybd,
6114202a189Smrg                     DeviceIntPtr master_ptr, DeviceIntPtr master_keybd)
6124202a189Smrg{
6134202a189Smrg    int retval;
6144202a189Smrg    int len = strlen(name);
6154202a189Smrg    char *xtestname = calloc(len + 7, 1 );
6164202a189Smrg    char dummy = 1;
6174202a189Smrg
6184202a189Smrg    strncpy( xtestname, name, len);
6194202a189Smrg    strncat( xtestname, " XTEST", 6 );
6204202a189Smrg
6214202a189Smrg    retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE);
6224202a189Smrg    if ( retval == Success ){
6234202a189Smrg	(*ptr)->xtest_master_id = master_ptr->id;
6244202a189Smrg	(*keybd)->xtest_master_id = master_keybd->id;
6254202a189Smrg
6264202a189Smrg        XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
6274202a189Smrg                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
6284202a189Smrg                FALSE);
6294202a189Smrg        XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
6304202a189Smrg        XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL);
6314202a189Smrg        XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
6324202a189Smrg                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
6334202a189Smrg                FALSE);
6344202a189Smrg        XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
6354202a189Smrg        XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
6364202a189Smrg    }
6374202a189Smrg
6384202a189Smrg    free( xtestname );
6394202a189Smrg
6404202a189Smrg    return retval;
6414202a189Smrg}
6424202a189Smrg
6434202a189Smrg/**
6444202a189Smrg * If master is NULL, return TRUE if the given device is an xtest device or
6454202a189Smrg * FALSE otherwise.
6464202a189Smrg * If master is not NULL, return TRUE if the given device is this master's
6474202a189Smrg * xtest device.
6484202a189Smrg */
6494202a189SmrgBOOL
6504202a189SmrgIsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
6514202a189Smrg{
6524202a189Smrg    if (IsMaster(dev))
6534202a189Smrg        return FALSE;
6544202a189Smrg
6554202a189Smrg    /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest
6564202a189Smrg     * device */
6574202a189Smrg    if (master)
6584202a189Smrg	return dev->xtest_master_id == master->id;
6594202a189Smrg
6604202a189Smrg    return dev->xtest_master_id != 0;
6614202a189Smrg}
6624202a189Smrg
6634202a189Smrg/**
6644202a189Smrg * @return The X Test virtual device for the given master.
6654202a189Smrg */
6664202a189SmrgDeviceIntPtr
6674202a189SmrgGetXTestDevice(DeviceIntPtr master)
6684202a189Smrg{
6694202a189Smrg    DeviceIntPtr it;
6704202a189Smrg
6714202a189Smrg    for (it = inputInfo.devices; it; it = it->next)
6724202a189Smrg    {
6734202a189Smrg        if (IsXTestDevice(it, master))
6744202a189Smrg            return it;
6754202a189Smrg    }
6764202a189Smrg
6774202a189Smrg    /* This only happens if master is a slave device. don't do that */
6784202a189Smrg    return NULL;
6794202a189Smrg}
6804202a189Smrg
68165b04b38Smrgvoid
68265b04b38SmrgXTestExtensionInit(INITARGS)
68365b04b38Smrg{
68465b04b38Smrg    AddExtension(XTestExtensionName, 0, 0,
68565b04b38Smrg            ProcXTestDispatch, SProcXTestDispatch,
68665b04b38Smrg            NULL, StandardMinorOpcode);
68765b04b38Smrg
68865b04b38Smrg    xtest_evlist = InitEventList(GetMaximumEventsNum());
68965b04b38Smrg}
690