xtest.c revision 05b261ec
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1992, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included
1205b261ecSmrgin all copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
2405b261ecSmrgother dealings in this Software without prior written authorization
2505b261ecSmrgfrom The Open Group.
2605b261ecSmrg
2705b261ecSmrg*/
2805b261ecSmrg
2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3005b261ecSmrg#include <dix-config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#define NEED_EVENTS
3505b261ecSmrg#include <X11/Xproto.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"
4505b261ecSmrg#define _XTEST_SERVER_
4605b261ecSmrg#include <X11/extensions/XTest.h>
4705b261ecSmrg#include <X11/extensions/xteststr.h>
4805b261ecSmrg#ifdef XINPUT
4905b261ecSmrg#include <X11/extensions/XI.h>
5005b261ecSmrg#include <X11/extensions/XIproto.h>
5105b261ecSmrg#define EXTENSION_EVENT_BASE	64
5205b261ecSmrg#include "extinit.h"		/* LookupDeviceIntRec */
5305b261ecSmrg#endif /* XINPUT */
5405b261ecSmrg
5505b261ecSmrg#include "modinit.h"
5605b261ecSmrg
5705b261ecSmrg#if 0
5805b261ecSmrgstatic unsigned char XTestReqCode;
5905b261ecSmrg#endif
6005b261ecSmrg
6105b261ecSmrg#ifdef XINPUT
6205b261ecSmrgextern int DeviceValuator;
6305b261ecSmrg#endif /* XINPUT */
6405b261ecSmrg
6505b261ecSmrg#ifdef PANORAMIX
6605b261ecSmrg#include "panoramiX.h"
6705b261ecSmrg#include "panoramiXsrv.h"
6805b261ecSmrg#endif
6905b261ecSmrg
7005b261ecSmrgstatic void XTestResetProc(
7105b261ecSmrg    ExtensionEntry * /* extEntry */
7205b261ecSmrg);
7305b261ecSmrgstatic int XTestSwapFakeInput(
7405b261ecSmrg    ClientPtr /* client */,
7505b261ecSmrg    xReq * /* req */
7605b261ecSmrg);
7705b261ecSmrg
7805b261ecSmrgstatic DISPATCH_PROC(ProcXTestCompareCursor);
7905b261ecSmrgstatic DISPATCH_PROC(ProcXTestDispatch);
8005b261ecSmrgstatic DISPATCH_PROC(ProcXTestFakeInput);
8105b261ecSmrgstatic DISPATCH_PROC(ProcXTestGetVersion);
8205b261ecSmrgstatic DISPATCH_PROC(ProcXTestGrabControl);
8305b261ecSmrgstatic DISPATCH_PROC(SProcXTestCompareCursor);
8405b261ecSmrgstatic DISPATCH_PROC(SProcXTestDispatch);
8505b261ecSmrgstatic DISPATCH_PROC(SProcXTestFakeInput);
8605b261ecSmrgstatic DISPATCH_PROC(SProcXTestGetVersion);
8705b261ecSmrgstatic DISPATCH_PROC(SProcXTestGrabControl);
8805b261ecSmrg
8905b261ecSmrgvoid
9005b261ecSmrgXTestExtensionInit(INITARGS)
9105b261ecSmrg{
9205b261ecSmrg#if 0
9305b261ecSmrg    ExtensionEntry *extEntry;
9405b261ecSmrg
9505b261ecSmrg    if ((extEntry = AddExtension(XTestExtensionName, 0, 0,
9605b261ecSmrg				 ProcXTestDispatch, SProcXTestDispatch,
9705b261ecSmrg				 XTestResetProc, StandardMinorOpcode)) != 0)
9805b261ecSmrg	XTestReqCode = (unsigned char)extEntry->base;
9905b261ecSmrg#else
10005b261ecSmrg    (void) AddExtension(XTestExtensionName, 0, 0,
10105b261ecSmrg			ProcXTestDispatch, SProcXTestDispatch,
10205b261ecSmrg			XTestResetProc, StandardMinorOpcode);
10305b261ecSmrg#endif
10405b261ecSmrg}
10505b261ecSmrg
10605b261ecSmrg/*ARGSUSED*/
10705b261ecSmrgstatic void
10805b261ecSmrgXTestResetProc (extEntry)
10905b261ecSmrgExtensionEntry	*extEntry;
11005b261ecSmrg{
11105b261ecSmrg}
11205b261ecSmrg
11305b261ecSmrgstatic int
11405b261ecSmrgProcXTestGetVersion(client)
11505b261ecSmrg    register ClientPtr client;
11605b261ecSmrg{
11705b261ecSmrg    xXTestGetVersionReply rep;
11805b261ecSmrg    register int n;
11905b261ecSmrg
12005b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGetVersionReq);
12105b261ecSmrg    rep.type = X_Reply;
12205b261ecSmrg    rep.length = 0;
12305b261ecSmrg    rep.sequenceNumber = client->sequence;
12405b261ecSmrg    rep.majorVersion = XTestMajorVersion;
12505b261ecSmrg    rep.minorVersion = XTestMinorVersion;
12605b261ecSmrg    if (client->swapped) {
12705b261ecSmrg    	swaps(&rep.sequenceNumber, n);
12805b261ecSmrg	swaps(&rep.minorVersion, n);
12905b261ecSmrg    }
13005b261ecSmrg    WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
13105b261ecSmrg    return(client->noClientException);
13205b261ecSmrg}
13305b261ecSmrg
13405b261ecSmrgstatic int
13505b261ecSmrgProcXTestCompareCursor(client)
13605b261ecSmrg    register ClientPtr client;
13705b261ecSmrg{
13805b261ecSmrg    REQUEST(xXTestCompareCursorReq);
13905b261ecSmrg    xXTestCompareCursorReply rep;
14005b261ecSmrg    WindowPtr pWin;
14105b261ecSmrg    CursorPtr pCursor;
14205b261ecSmrg    register int n, rc;
14305b261ecSmrg
14405b261ecSmrg    REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
14505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
14605b261ecSmrg    if (rc != Success)
14705b261ecSmrg        return rc;
14805b261ecSmrg    if (stuff->cursor == None)
14905b261ecSmrg	pCursor = NullCursor;
15005b261ecSmrg    else if (stuff->cursor == XTestCurrentCursor)
15105b261ecSmrg	pCursor = GetSpriteCursor();
15205b261ecSmrg    else {
15305b261ecSmrg	pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
15405b261ecSmrg	if (!pCursor)
15505b261ecSmrg	{
15605b261ecSmrg	    client->errorValue = stuff->cursor;
15705b261ecSmrg	    return (BadCursor);
15805b261ecSmrg	}
15905b261ecSmrg    }
16005b261ecSmrg    rep.type = X_Reply;
16105b261ecSmrg    rep.length = 0;
16205b261ecSmrg    rep.sequenceNumber = client->sequence;
16305b261ecSmrg    rep.same = (wCursor(pWin) == pCursor);
16405b261ecSmrg    if (client->swapped) {
16505b261ecSmrg    	swaps(&rep.sequenceNumber, n);
16605b261ecSmrg    }
16705b261ecSmrg    WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
16805b261ecSmrg    return(client->noClientException);
16905b261ecSmrg}
17005b261ecSmrg
17105b261ecSmrgstatic int
17205b261ecSmrgProcXTestFakeInput(client)
17305b261ecSmrg    register ClientPtr client;
17405b261ecSmrg{
17505b261ecSmrg    REQUEST(xXTestFakeInputReq);
17605b261ecSmrg    int nev, n, type, rc;
17705b261ecSmrg    xEvent *ev;
17805b261ecSmrg    DeviceIntPtr dev = NULL;
17905b261ecSmrg    WindowPtr root;
18005b261ecSmrg#ifdef XINPUT
18105b261ecSmrg    Bool extension = FALSE;
18205b261ecSmrg    deviceValuator *dv = NULL;
18305b261ecSmrg    int base;
18405b261ecSmrg    int *values;
18505b261ecSmrg#endif /* XINPUT */
18605b261ecSmrg
18705b261ecSmrg    nev = (stuff->length << 2) - sizeof(xReq);
18805b261ecSmrg    if ((nev % sizeof(xEvent)) || !nev)
18905b261ecSmrg	return BadLength;
19005b261ecSmrg    nev /= sizeof(xEvent);
19105b261ecSmrg    UpdateCurrentTime();
19205b261ecSmrg    ev = (xEvent *)&((xReq *)stuff)[1];
19305b261ecSmrg    type = ev->u.u.type & 0177;
19405b261ecSmrg#ifdef XINPUT
19505b261ecSmrg    if (type >= EXTENSION_EVENT_BASE)
19605b261ecSmrg    {
19705b261ecSmrg	type -= DeviceValuator;
19805b261ecSmrg	switch (type) {
19905b261ecSmrg	case XI_DeviceKeyPress:
20005b261ecSmrg	case XI_DeviceKeyRelease:
20105b261ecSmrg	case XI_DeviceButtonPress:
20205b261ecSmrg	case XI_DeviceButtonRelease:
20305b261ecSmrg	case XI_DeviceMotionNotify:
20405b261ecSmrg	case XI_ProximityIn:
20505b261ecSmrg	case XI_ProximityOut:
20605b261ecSmrg	    break;
20705b261ecSmrg	default:
20805b261ecSmrg	    client->errorValue = ev->u.u.type;
20905b261ecSmrg	    return BadValue;
21005b261ecSmrg	}
21105b261ecSmrg	if (nev == 1 && type == XI_DeviceMotionNotify)
21205b261ecSmrg	    return BadLength;
21305b261ecSmrg	if (type == XI_DeviceMotionNotify)
21405b261ecSmrg	    base = ((deviceValuator *)(ev+1))->first_valuator;
21505b261ecSmrg	else
21605b261ecSmrg	    base = 0;
21705b261ecSmrg	for (n = 1; n < nev; n++)
21805b261ecSmrg	{
21905b261ecSmrg	    dv = (deviceValuator *)(ev + n);
22005b261ecSmrg	    if (dv->type != DeviceValuator)
22105b261ecSmrg	    {
22205b261ecSmrg		client->errorValue = dv->type;
22305b261ecSmrg		return BadValue;
22405b261ecSmrg	    }
22505b261ecSmrg	    if (dv->first_valuator != base)
22605b261ecSmrg	    {
22705b261ecSmrg		client->errorValue = dv->first_valuator;
22805b261ecSmrg		return BadValue;
22905b261ecSmrg	    }
23005b261ecSmrg	    if (!dv->num_valuators || dv->num_valuators > 6)
23105b261ecSmrg	    {
23205b261ecSmrg		client->errorValue = dv->num_valuators;
23305b261ecSmrg		return BadValue;
23405b261ecSmrg	    }
23505b261ecSmrg	    base += dv->num_valuators;
23605b261ecSmrg	}
23705b261ecSmrg	type = type - XI_DeviceKeyPress + KeyPress;
23805b261ecSmrg	extension = TRUE;
23905b261ecSmrg    }
24005b261ecSmrg    else
24105b261ecSmrg#endif /* XINPUT */
24205b261ecSmrg    {
24305b261ecSmrg	if (nev != 1)
24405b261ecSmrg	    return BadLength;
24505b261ecSmrg	switch (type)
24605b261ecSmrg	{
24705b261ecSmrg	case KeyPress:
24805b261ecSmrg	case KeyRelease:
24905b261ecSmrg	case MotionNotify:
25005b261ecSmrg	case ButtonPress:
25105b261ecSmrg	case ButtonRelease:
25205b261ecSmrg	    break;
25305b261ecSmrg	default:
25405b261ecSmrg	    client->errorValue = ev->u.u.type;
25505b261ecSmrg	    return BadValue;
25605b261ecSmrg	}
25705b261ecSmrg    }
25805b261ecSmrg    if (ev->u.keyButtonPointer.time)
25905b261ecSmrg    {
26005b261ecSmrg	TimeStamp activateTime;
26105b261ecSmrg	CARD32 ms;
26205b261ecSmrg
26305b261ecSmrg	activateTime = currentTime;
26405b261ecSmrg	ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
26505b261ecSmrg	if (ms < activateTime.milliseconds)
26605b261ecSmrg	    activateTime.months++;
26705b261ecSmrg	activateTime.milliseconds = ms;
26805b261ecSmrg	ev->u.keyButtonPointer.time = 0;
26905b261ecSmrg
27005b261ecSmrg	/* see mbuf.c:QueueDisplayRequest for code similar to this */
27105b261ecSmrg
27205b261ecSmrg	if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
27305b261ecSmrg	{
27405b261ecSmrg	    return BadAlloc;
27505b261ecSmrg	}
27605b261ecSmrg	/* swap the request back so we can simply re-execute it */
27705b261ecSmrg	if (client->swapped)
27805b261ecSmrg	{
27905b261ecSmrg    	    (void) XTestSwapFakeInput(client, (xReq *)stuff);
28005b261ecSmrg	    swaps(&stuff->length, n);
28105b261ecSmrg	}
28205b261ecSmrg	ResetCurrentRequest (client);
28305b261ecSmrg	client->sequence--;
28405b261ecSmrg	return Success;
28505b261ecSmrg    }
28605b261ecSmrg#ifdef XINPUT
28705b261ecSmrg    if (extension)
28805b261ecSmrg    {
28905b261ecSmrg	dev = LookupDeviceIntRec(stuff->deviceid & 0177);
29005b261ecSmrg	if (!dev)
29105b261ecSmrg	{
29205b261ecSmrg	    client->errorValue = stuff->deviceid & 0177;
29305b261ecSmrg	    return BadValue;
29405b261ecSmrg	}
29505b261ecSmrg	if (nev > 1)
29605b261ecSmrg	{
29705b261ecSmrg	    dv = (deviceValuator *)(ev + 1);
29805b261ecSmrg	    if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes)
29905b261ecSmrg	    {
30005b261ecSmrg		client->errorValue = dv->first_valuator;
30105b261ecSmrg		return BadValue;
30205b261ecSmrg	    }
30305b261ecSmrg	    if (dv->first_valuator + dv->num_valuators >
30405b261ecSmrg		dev->valuator->numAxes)
30505b261ecSmrg	    {
30605b261ecSmrg		client->errorValue = dv->num_valuators;
30705b261ecSmrg		return BadValue;
30805b261ecSmrg	    }
30905b261ecSmrg	}
31005b261ecSmrg    }
31105b261ecSmrg#endif /* XINPUT */
31205b261ecSmrg    switch (type)
31305b261ecSmrg    {
31405b261ecSmrg    case KeyPress:
31505b261ecSmrg    case KeyRelease:
31605b261ecSmrg#ifdef XINPUT
31705b261ecSmrg	if (!extension)
31805b261ecSmrg#endif /* XINPUT */
31905b261ecSmrg	    dev = (DeviceIntPtr)LookupKeyboardDevice();
32005b261ecSmrg	if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
32105b261ecSmrg	    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
32205b261ecSmrg	{
32305b261ecSmrg	    client->errorValue = ev->u.u.detail;
32405b261ecSmrg	    return BadValue;
32505b261ecSmrg	}
32605b261ecSmrg	break;
32705b261ecSmrg    case MotionNotify:
32805b261ecSmrg#ifdef XINPUT
32905b261ecSmrg	if (extension)
33005b261ecSmrg	{
33105b261ecSmrg	    if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue)
33205b261ecSmrg	    {
33305b261ecSmrg		client->errorValue = ev->u.u.detail;
33405b261ecSmrg		return BadValue;
33505b261ecSmrg	    }
33605b261ecSmrg	    if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute)
33705b261ecSmrg	    {
33805b261ecSmrg		values = dev->valuator->axisVal + dv->first_valuator;
33905b261ecSmrg		for (n = 1; n < nev; n++)
34005b261ecSmrg		{
34105b261ecSmrg		    dv = (deviceValuator *)(ev + n);
34205b261ecSmrg		    switch (dv->num_valuators)
34305b261ecSmrg		    {
34405b261ecSmrg		    case 6:
34505b261ecSmrg			dv->valuator5 += values[5];
34605b261ecSmrg		    case 5:
34705b261ecSmrg			dv->valuator4 += values[4];
34805b261ecSmrg		    case 4:
34905b261ecSmrg			dv->valuator3 += values[3];
35005b261ecSmrg		    case 3:
35105b261ecSmrg			dv->valuator2 += values[2];
35205b261ecSmrg		    case 2:
35305b261ecSmrg			dv->valuator1 += values[1];
35405b261ecSmrg		    case 1:
35505b261ecSmrg			dv->valuator0 += values[0];
35605b261ecSmrg		    }
35705b261ecSmrg		    values += 6;
35805b261ecSmrg		}
35905b261ecSmrg	    }
36005b261ecSmrg	    break;
36105b261ecSmrg	}
36205b261ecSmrg#endif /* XINPUT */
36305b261ecSmrg	dev = (DeviceIntPtr)LookupPointerDevice();
36405b261ecSmrg	if (ev->u.keyButtonPointer.root == None)
36505b261ecSmrg	    root = GetCurrentRootWindow();
36605b261ecSmrg	else
36705b261ecSmrg	{
36805b261ecSmrg	    rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client,
36905b261ecSmrg				 DixUnknownAccess);
37005b261ecSmrg	    if (rc != Success)
37105b261ecSmrg		return rc;
37205b261ecSmrg	    if (root->parent)
37305b261ecSmrg	    {
37405b261ecSmrg		client->errorValue = ev->u.keyButtonPointer.root;
37505b261ecSmrg		return BadValue;
37605b261ecSmrg	    }
37705b261ecSmrg	}
37805b261ecSmrg	if (ev->u.u.detail == xTrue)
37905b261ecSmrg	{
38005b261ecSmrg	    int x, y;
38105b261ecSmrg	    GetSpritePosition(&x, &y);
38205b261ecSmrg	    ev->u.keyButtonPointer.rootX += x;
38305b261ecSmrg	    ev->u.keyButtonPointer.rootY += y;
38405b261ecSmrg	}
38505b261ecSmrg	else if (ev->u.u.detail != xFalse)
38605b261ecSmrg	{
38705b261ecSmrg	    client->errorValue = ev->u.u.detail;
38805b261ecSmrg	    return BadValue;
38905b261ecSmrg	}
39005b261ecSmrg
39105b261ecSmrg#ifdef PANORAMIX
39205b261ecSmrg	if (!noPanoramiXExtension) {
39305b261ecSmrg	    ScreenPtr pScreen = root->drawable.pScreen;
39405b261ecSmrg	    BoxRec    box;
39505b261ecSmrg	    int       i;
39605b261ecSmrg	    int       x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x;
39705b261ecSmrg	    int       y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y;
39805b261ecSmrg	    if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
39905b261ecSmrg				 x, y, &box)) {
40005b261ecSmrg		FOR_NSCREENS(i) {
40105b261ecSmrg		    if (i == pScreen->myNum) continue;
40205b261ecSmrg		    if (POINT_IN_REGION(pScreen,
40305b261ecSmrg					&XineramaScreenRegions[i],
40405b261ecSmrg					x, y, &box)) {
40505b261ecSmrg			root = WindowTable[i];
40605b261ecSmrg			x   -= panoramiXdataPtr[i].x;
40705b261ecSmrg			y   -= panoramiXdataPtr[i].y;
40805b261ecSmrg			ev->u.keyButtonPointer.rootX = x;
40905b261ecSmrg			ev->u.keyButtonPointer.rootY = y;
41005b261ecSmrg			break;
41105b261ecSmrg		    }
41205b261ecSmrg		}
41305b261ecSmrg	    }
41405b261ecSmrg	}
41505b261ecSmrg#endif
41605b261ecSmrg
41705b261ecSmrg	if (ev->u.keyButtonPointer.rootX < 0)
41805b261ecSmrg	    ev->u.keyButtonPointer.rootX = 0;
41905b261ecSmrg	else if (ev->u.keyButtonPointer.rootX >= root->drawable.width)
42005b261ecSmrg	    ev->u.keyButtonPointer.rootX = root->drawable.width - 1;
42105b261ecSmrg	if (ev->u.keyButtonPointer.rootY < 0)
42205b261ecSmrg	    ev->u.keyButtonPointer.rootY = 0;
42305b261ecSmrg	else if (ev->u.keyButtonPointer.rootY >= root->drawable.height)
42405b261ecSmrg	    ev->u.keyButtonPointer.rootY = root->drawable.height - 1;
42505b261ecSmrg
42605b261ecSmrg#ifdef PANORAMIX
42705b261ecSmrg	if ((!noPanoramiXExtension
42805b261ecSmrg	     && root->drawable.pScreen->myNum != XineramaGetCursorScreen())
42905b261ecSmrg	    || (noPanoramiXExtension && root != GetCurrentRootWindow()))
43005b261ecSmrg
43105b261ecSmrg#else
43205b261ecSmrg	if (root != GetCurrentRootWindow())
43305b261ecSmrg#endif
43405b261ecSmrg	{
43505b261ecSmrg	    NewCurrentScreen(root->drawable.pScreen,
43605b261ecSmrg			     ev->u.keyButtonPointer.rootX,
43705b261ecSmrg			     ev->u.keyButtonPointer.rootY);
43805b261ecSmrg	    return client->noClientException;
43905b261ecSmrg	}
44005b261ecSmrg	(*root->drawable.pScreen->SetCursorPosition)
44105b261ecSmrg	    (root->drawable.pScreen,
44205b261ecSmrg	     ev->u.keyButtonPointer.rootX,
44305b261ecSmrg	     ev->u.keyButtonPointer.rootY, FALSE);
44405b261ecSmrg        dev->valuator->lastx = ev->u.keyButtonPointer.rootX;
44505b261ecSmrg        dev->valuator->lasty = ev->u.keyButtonPointer.rootY;
44605b261ecSmrg	break;
44705b261ecSmrg    case ButtonPress:
44805b261ecSmrg    case ButtonRelease:
44905b261ecSmrg#ifdef XINPUT
45005b261ecSmrg	if (!extension)
45105b261ecSmrg#endif /* XINPUT */
45205b261ecSmrg	    dev = (DeviceIntPtr)LookupPointerDevice();
45305b261ecSmrg	if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
45405b261ecSmrg	{
45505b261ecSmrg	    client->errorValue = ev->u.u.detail;
45605b261ecSmrg	    return BadValue;
45705b261ecSmrg	}
45805b261ecSmrg	break;
45905b261ecSmrg    }
46005b261ecSmrg    if (screenIsSaved == SCREEN_SAVER_ON)
46105b261ecSmrg	SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
46205b261ecSmrg    ev->u.keyButtonPointer.time = currentTime.milliseconds;
46305b261ecSmrg    (*dev->public.processInputProc)(ev, dev, nev);
46405b261ecSmrg    return client->noClientException;
46505b261ecSmrg}
46605b261ecSmrg
46705b261ecSmrgstatic int
46805b261ecSmrgProcXTestGrabControl(client)
46905b261ecSmrg    register ClientPtr client;
47005b261ecSmrg{
47105b261ecSmrg    REQUEST(xXTestGrabControlReq);
47205b261ecSmrg
47305b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGrabControlReq);
47405b261ecSmrg    if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse))
47505b261ecSmrg    {
47605b261ecSmrg	client->errorValue = stuff->impervious;
47705b261ecSmrg        return(BadValue);
47805b261ecSmrg    }
47905b261ecSmrg    if (stuff->impervious)
48005b261ecSmrg	MakeClientGrabImpervious(client);
48105b261ecSmrg    else
48205b261ecSmrg	MakeClientGrabPervious(client);
48305b261ecSmrg    return(client->noClientException);
48405b261ecSmrg}
48505b261ecSmrg
48605b261ecSmrgstatic int
48705b261ecSmrgProcXTestDispatch (client)
48805b261ecSmrg    register ClientPtr	client;
48905b261ecSmrg{
49005b261ecSmrg    REQUEST(xReq);
49105b261ecSmrg    switch (stuff->data)
49205b261ecSmrg    {
49305b261ecSmrg    case X_XTestGetVersion:
49405b261ecSmrg	return ProcXTestGetVersion(client);
49505b261ecSmrg    case X_XTestCompareCursor:
49605b261ecSmrg	return ProcXTestCompareCursor(client);
49705b261ecSmrg    case X_XTestFakeInput:
49805b261ecSmrg	return ProcXTestFakeInput(client);
49905b261ecSmrg    case X_XTestGrabControl:
50005b261ecSmrg	return ProcXTestGrabControl(client);
50105b261ecSmrg    default:
50205b261ecSmrg	return BadRequest;
50305b261ecSmrg    }
50405b261ecSmrg}
50505b261ecSmrg
50605b261ecSmrgstatic int
50705b261ecSmrgSProcXTestGetVersion(client)
50805b261ecSmrg    register ClientPtr	client;
50905b261ecSmrg{
51005b261ecSmrg    register int n;
51105b261ecSmrg    REQUEST(xXTestGetVersionReq);
51205b261ecSmrg
51305b261ecSmrg    swaps(&stuff->length, n);
51405b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGetVersionReq);
51505b261ecSmrg    swaps(&stuff->minorVersion, n);
51605b261ecSmrg    return ProcXTestGetVersion(client);
51705b261ecSmrg}
51805b261ecSmrg
51905b261ecSmrgstatic int
52005b261ecSmrgSProcXTestCompareCursor(client)
52105b261ecSmrg    register ClientPtr	client;
52205b261ecSmrg{
52305b261ecSmrg    register int n;
52405b261ecSmrg    REQUEST(xXTestCompareCursorReq);
52505b261ecSmrg
52605b261ecSmrg    swaps(&stuff->length, n);
52705b261ecSmrg    REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
52805b261ecSmrg    swapl(&stuff->window, n);
52905b261ecSmrg    swapl(&stuff->cursor, n);
53005b261ecSmrg    return ProcXTestCompareCursor(client);
53105b261ecSmrg}
53205b261ecSmrg
53305b261ecSmrgstatic int
53405b261ecSmrgXTestSwapFakeInput(client, req)
53505b261ecSmrg    register ClientPtr	client;
53605b261ecSmrg    xReq *req;
53705b261ecSmrg{
53805b261ecSmrg    register int nev;
53905b261ecSmrg    register xEvent *ev;
54005b261ecSmrg    xEvent sev;
54105b261ecSmrg    EventSwapPtr proc;
54205b261ecSmrg
54305b261ecSmrg    nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
54405b261ecSmrg    for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
54505b261ecSmrg    {
54605b261ecSmrg    	/* Swap event */
54705b261ecSmrg    	proc = EventSwapVector[ev->u.u.type & 0177];
54805b261ecSmrg	/* no swapping proc; invalid event type? */
54905b261ecSmrg    	if (!proc ||  proc ==  NotImplemented) {
55005b261ecSmrg	    client->errorValue = ev->u.u.type;
55105b261ecSmrg	    return BadValue;
55205b261ecSmrg	}
55305b261ecSmrg    	(*proc)(ev, &sev);
55405b261ecSmrg	*ev = sev;
55505b261ecSmrg    }
55605b261ecSmrg    return Success;
55705b261ecSmrg}
55805b261ecSmrg
55905b261ecSmrgstatic int
56005b261ecSmrgSProcXTestFakeInput(client)
56105b261ecSmrg    register ClientPtr	client;
56205b261ecSmrg{
56305b261ecSmrg    register int n;
56405b261ecSmrg    REQUEST(xReq);
56505b261ecSmrg
56605b261ecSmrg    swaps(&stuff->length, n);
56705b261ecSmrg    n = XTestSwapFakeInput(client, stuff);
56805b261ecSmrg    if (n != Success)
56905b261ecSmrg	return n;
57005b261ecSmrg    return ProcXTestFakeInput(client);
57105b261ecSmrg}
57205b261ecSmrg
57305b261ecSmrgstatic int
57405b261ecSmrgSProcXTestGrabControl(client)
57505b261ecSmrg    register ClientPtr	client;
57605b261ecSmrg{
57705b261ecSmrg    register int n;
57805b261ecSmrg    REQUEST(xXTestGrabControlReq);
57905b261ecSmrg
58005b261ecSmrg    swaps(&stuff->length, n);
58105b261ecSmrg    REQUEST_SIZE_MATCH(xXTestGrabControlReq);
58205b261ecSmrg    return ProcXTestGrabControl(client);
58305b261ecSmrg}
58405b261ecSmrg
58505b261ecSmrgstatic int
58605b261ecSmrgSProcXTestDispatch (client)
58705b261ecSmrg    register ClientPtr	client;
58805b261ecSmrg{
58905b261ecSmrg    REQUEST(xReq);
59005b261ecSmrg    switch (stuff->data)
59105b261ecSmrg    {
59205b261ecSmrg    case X_XTestGetVersion:
59305b261ecSmrg	return SProcXTestGetVersion(client);
59405b261ecSmrg    case X_XTestCompareCursor:
59505b261ecSmrg	return SProcXTestCompareCursor(client);
59605b261ecSmrg    case X_XTestFakeInput:
59705b261ecSmrg	return SProcXTestFakeInput(client);
59805b261ecSmrg    case X_XTestGrabControl:
59905b261ecSmrg	return SProcXTestGrabControl(client);
60005b261ecSmrg    default:
60105b261ecSmrg	return BadRequest;
60205b261ecSmrg    }
60305b261ecSmrg}
604