From eaedc21febeadad4cf0e370f5d97e7bdb4470870 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 5 Apr 2011 09:51:44 +0000 Subject: xserver xkeyboard-config libxcb xkbcomp mesa git update 5 Apr 2011 --- xorg-server/Xext/geext.c | 524 +++++++++--------- xorg-server/Xext/xtest.c | 1381 +++++++++++++++++++++++----------------------- 2 files changed, 951 insertions(+), 954 deletions(-) (limited to 'xorg-server/Xext') diff --git a/xorg-server/Xext/geext.c b/xorg-server/Xext/geext.c index 951daf682..a6fbb0947 100644 --- a/xorg-server/Xext/geext.c +++ b/xorg-server/Xext/geext.c @@ -1,262 +1,262 @@ -/* - * Copyright 2007-2008 Peter Hutterer - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Peter Hutterer, University of South Australia, NICTA - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif -#include "windowstr.h" -#include - -#include "geint.h" -#include "geext.h" -#include "protocol-versions.h" - -DevPrivateKeyRec GEClientPrivateKeyRec; - -int RT_GECLIENT = 0; - -GEExtension GEExtensions[MAXEXTENSIONS]; - -/* Major available requests */ -static const int version_requests[] = { - X_GEQueryVersion, /* before client sends QueryVersion */ - X_GEQueryVersion, /* must be set to last request in version 1 */ -}; - -/* Forward declarations */ -static void SGEGenericEvent(xEvent* from, xEvent* to); - -#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) - -/************************************************************/ -/* request handlers */ -/************************************************************/ - -static int -ProcGEQueryVersion(ClientPtr client) -{ - int n; - GEClientInfoPtr pGEClient = GEGetClient(client); - xGEQueryVersionReply rep; - REQUEST(xGEQueryVersionReq); - - REQUEST_SIZE_MATCH(xGEQueryVersionReq); - - rep.repType = X_Reply; - rep.RepType = X_GEQueryVersion; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - /* return the supported version by the server */ - rep.majorVersion = SERVER_GE_MAJOR_VERSION; - rep.minorVersion = SERVER_GE_MINOR_VERSION; - - /* Remember version the client requested */ - pGEClient->major_version = stuff->majorVersion; - pGEClient->minor_version = stuff->minorVersion; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - - WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep); - return Success; -} - -int (*ProcGEVector[GENumberRequests])(ClientPtr) = { - /* Version 1.0 */ - ProcGEQueryVersion -}; - -/************************************************************/ -/* swapped request handlers */ -/************************************************************/ -static int -SProcGEQueryVersion(ClientPtr client) -{ - int n; - REQUEST(xGEQueryVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xGEQueryVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion, n); - return(*ProcGEVector[stuff->ReqType])(client); -} - -int (*SProcGEVector[GENumberRequests])(ClientPtr) = { - /* Version 1.0 */ - SProcGEQueryVersion -}; - - -/************************************************************/ -/* callbacks */ -/************************************************************/ - -/* dispatch requests */ -static int -ProcGEDispatch(ClientPtr client) -{ - GEClientInfoPtr pGEClient = GEGetClient(client); - REQUEST(xGEReq); - - if (pGEClient->major_version >= NUM_VERSION_REQUESTS) - return BadRequest; - if (stuff->ReqType > version_requests[pGEClient->major_version]) - return BadRequest; - - return (ProcGEVector[stuff->ReqType])(client); -} - -/* dispatch swapped requests */ -static int -SProcGEDispatch(ClientPtr client) -{ - REQUEST(xGEReq); - if (stuff->ReqType >= GENumberRequests) - return BadRequest; - return (*SProcGEVector[stuff->ReqType])(client); -} - -/** - * Called when a new client inits a connection to the X server. - * - * We alloc a simple struct to store the client's major/minor version. Can be - * used in the furture for versioning support. - */ -static void -GEClientCallback(CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - GEClientInfoPtr pGEClient = GEGetClient(pClient); - - pGEClient->major_version = 0; - pGEClient->minor_version = 0; -} - -/* Reset extension. Called on server shutdown. */ -static void -GEResetProc(ExtensionEntry *extEntry) -{ - DeleteCallback(&ClientStateCallback, GEClientCallback, 0); - EventSwapVector[GenericEvent] = NotImplemented; -} - -/* Calls the registered event swap function for the extension. - * - * Each extension can register a swap function to handle GenericEvents being - * swapped properly. The server calls SGEGenericEvent() before the event is - * written on the wire, this one calls the registered swap function to do the - * work. - */ -static void -SGEGenericEvent(xEvent* from, xEvent* to) -{ - xGenericEvent* gefrom = (xGenericEvent*)from; - xGenericEvent* geto = (xGenericEvent*)to; - - if (gefrom->extension > MAXEXTENSIONS) - { - ErrorF("GE: Invalid extension offset for event.\n"); - return; - } - - if (GEExtensions[gefrom->extension & 0x7F].evswap) - GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto); -} - -/* Init extension, register at server. - * Since other extensions may rely on XGE (XInput does already), it is a good - * idea to init XGE first, before any other extension. - */ -void -GEExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (!dixRegisterPrivateKey(&GEClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(GEClientInfoRec))) - FatalError("GEExtensionInit: GE private request failed.\n"); - - if(!AddCallback(&ClientStateCallback, GEClientCallback, 0)) - { - FatalError("GEExtensionInit: register client callback failed.\n"); - } - - if((extEntry = AddExtension(GE_NAME, - 0, GENumberErrors, - ProcGEDispatch, SProcGEDispatch, - GEResetProc, StandardMinorOpcode)) != 0) - { - memset(GEExtensions, 0, sizeof(GEExtensions)); - - EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent; - } else { - FatalError("GEInit: AddExtensions failed.\n"); - } - -} - -/************************************************************/ -/* interface for extensions */ -/************************************************************/ - -/* Register an extension with GE. The given swap function will be called each - * time an event is sent to a client with different byte order. - * @param extension The extensions major opcode - * @param ev_swap The event swap function. - * @param ev_fill Called for an event before delivery. The extension now has - * the chance to fill in necessary fields for the event. - */ -void -GERegisterExtension(int extension, - void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)) -{ - if ((extension & 0x7F) >= MAXEXTENSIONS) - FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n"); - - /* extension opcodes are > 128, might as well save some space here */ - GEExtensions[extension & 0x7f].evswap = ev_swap; -} - - -/* Sets type and extension field for a generic event. This is just an - * auxiliary function, extensions could do it manually too. - */ -void -GEInitEvent(xGenericEvent* ev, int extension) -{ - ev->type = GenericEvent; - ev->extension = extension; - ev->length = 0; -} - +/* + * Copyright 2007-2008 Peter Hutterer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Peter Hutterer, University of South Australia, NICTA + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif +#include "windowstr.h" +#include + +#include "geint.h" +#include "geext.h" +#include "protocol-versions.h" + +DevPrivateKeyRec GEClientPrivateKeyRec; + +int RT_GECLIENT = 0; + +GEExtension GEExtensions[MAXEXTENSIONS]; + +/* Major available requests */ +static const int version_requests[] = { + X_GEQueryVersion, /* before client sends QueryVersion */ + X_GEQueryVersion, /* must be set to last request in version 1 */ +}; + +/* Forward declarations */ +static void SGEGenericEvent(xEvent* from, xEvent* to); + +#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) + +/************************************************************/ +/* request handlers */ +/************************************************************/ + +static int +ProcGEQueryVersion(ClientPtr client) +{ + int n; + GEClientInfoPtr pGEClient = GEGetClient(client); + xGEQueryVersionReply rep; + REQUEST(xGEQueryVersionReq); + + REQUEST_SIZE_MATCH(xGEQueryVersionReq); + + rep.repType = X_Reply; + rep.RepType = X_GEQueryVersion; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* return the supported version by the server */ + rep.majorVersion = SERVER_GE_MAJOR_VERSION; + rep.minorVersion = SERVER_GE_MINOR_VERSION; + + /* Remember version the client requested */ + pGEClient->major_version = stuff->majorVersion; + pGEClient->minor_version = stuff->minorVersion; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + + WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep); + return Success; +} + +int (*ProcGEVector[GENumberRequests])(ClientPtr) = { + /* Version 1.0 */ + ProcGEQueryVersion +}; + +/************************************************************/ +/* swapped request handlers */ +/************************************************************/ +static int +SProcGEQueryVersion(ClientPtr client) +{ + int n; + REQUEST(xGEQueryVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGEQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return(*ProcGEVector[stuff->ReqType])(client); +} + +int (*SProcGEVector[GENumberRequests])(ClientPtr) = { + /* Version 1.0 */ + SProcGEQueryVersion +}; + + +/************************************************************/ +/* callbacks */ +/************************************************************/ + +/* dispatch requests */ +static int +ProcGEDispatch(ClientPtr client) +{ + GEClientInfoPtr pGEClient = GEGetClient(client); + REQUEST(xGEReq); + + if (pGEClient->major_version >= NUM_VERSION_REQUESTS) + return BadRequest; + if (stuff->ReqType > version_requests[pGEClient->major_version]) + return BadRequest; + + return (ProcGEVector[stuff->ReqType])(client); +} + +/* dispatch swapped requests */ +static int +SProcGEDispatch(ClientPtr client) +{ + REQUEST(xGEReq); + if (stuff->ReqType >= GENumberRequests) + return BadRequest; + return (*SProcGEVector[stuff->ReqType])(client); +} + +/** + * Called when a new client inits a connection to the X server. + * + * We alloc a simple struct to store the client's major/minor version. Can be + * used in the furture for versioning support. + */ +static void +GEClientCallback(CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + GEClientInfoPtr pGEClient = GEGetClient(pClient); + + pGEClient->major_version = 0; + pGEClient->minor_version = 0; +} + +/* Reset extension. Called on server shutdown. */ +static void +GEResetProc(ExtensionEntry *extEntry) +{ + DeleteCallback(&ClientStateCallback, GEClientCallback, 0); + EventSwapVector[GenericEvent] = NotImplemented; +} + +/* Calls the registered event swap function for the extension. + * + * Each extension can register a swap function to handle GenericEvents being + * swapped properly. The server calls SGEGenericEvent() before the event is + * written on the wire, this one calls the registered swap function to do the + * work. + */ +static void +SGEGenericEvent(xEvent* from, xEvent* to) +{ + xGenericEvent* gefrom = (xGenericEvent*)from; + xGenericEvent* geto = (xGenericEvent*)to; + + if ((gefrom->extension & 0x7f) > MAXEXTENSIONS) + { + ErrorF("GE: Invalid extension offset for event.\n"); + return; + } + + if (GEExtensions[gefrom->extension & 0x7F].evswap) + GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto); +} + +/* Init extension, register at server. + * Since other extensions may rely on XGE (XInput does already), it is a good + * idea to init XGE first, before any other extension. + */ +void +GEExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (!dixRegisterPrivateKey(&GEClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(GEClientInfoRec))) + FatalError("GEExtensionInit: GE private request failed.\n"); + + if(!AddCallback(&ClientStateCallback, GEClientCallback, 0)) + { + FatalError("GEExtensionInit: register client callback failed.\n"); + } + + if((extEntry = AddExtension(GE_NAME, + 0, GENumberErrors, + ProcGEDispatch, SProcGEDispatch, + GEResetProc, StandardMinorOpcode)) != 0) + { + memset(GEExtensions, 0, sizeof(GEExtensions)); + + EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent; + } else { + FatalError("GEInit: AddExtensions failed.\n"); + } + +} + +/************************************************************/ +/* interface for extensions */ +/************************************************************/ + +/* Register an extension with GE. The given swap function will be called each + * time an event is sent to a client with different byte order. + * @param extension The extensions major opcode + * @param ev_swap The event swap function. + * @param ev_fill Called for an event before delivery. The extension now has + * the chance to fill in necessary fields for the event. + */ +void +GERegisterExtension(int extension, + void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)) +{ + if ((extension & 0x7F) >= MAXEXTENSIONS) + FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n"); + + /* extension opcodes are > 128, might as well save some space here */ + GEExtensions[extension & 0x7f].evswap = ev_swap; +} + + +/* Sets type and extension field for a generic event. This is just an + * auxiliary function, extensions could do it manually too. + */ +void +GEInitEvent(xGenericEvent* ev, int extension) +{ + ev->type = GenericEvent; + ev->extension = extension; + ev->length = 0; +} + diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c index 859057e2b..6780aa62a 100644 --- a/xorg-server/Xext/xtest.c +++ b/xorg-server/Xext/xtest.c @@ -1,692 +1,689 @@ -/* - - Copyright 1992, 1998 The Open Group - - Permission to use, copy, modify, distribute, and sell this software and its - documentation for any purpose is hereby granted without fee, provided that - the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation. - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of The Open Group shall - not be used in advertising or otherwise to promote the sale, use or - other dealings in this Software without prior written authorization - from The Open Group. - - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "windowstr.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "dixevents.h" -#include "sleepuntil.h" -#include "mi.h" -#include "xkbsrv.h" -#include "xkbstr.h" -#include -#include -#include -#include "exglobals.h" -#include "mipointer.h" -#include "xserver-properties.h" -#include "exevents.h" -#include "inpututils.h" - -#include "modinit.h" - -extern int DeviceValuator; - -/* XTest events are sent during request processing and may be interruped by - * a SIGIO. We need a separate event list to avoid events overwriting each - * other's memory */ -static EventListPtr xtest_evlist; - -/** - * xtestpointer - * is the virtual pointer for XTest. It is the first slave - * device of the VCP. - * xtestkeyboard - * is the virtual keyboard for XTest. It is the first slave - * device of the VCK - * - * Neither of these devices can be deleted. - */ -DeviceIntPtr xtestpointer, xtestkeyboard; - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -static int XTestSwapFakeInput( - ClientPtr /* client */, - xReq * /* req */ - ); - - -static int -ProcXTestGetVersion(ClientPtr client) -{ - xXTestGetVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xXTestGetVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = XTestMajorVersion; - rep.minorVersion = XTestMinorVersion; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); - return Success; -} - -static int -ProcXTestCompareCursor(ClientPtr client) -{ - REQUEST(xXTestCompareCursorReq); - xXTestCompareCursorReply rep; - WindowPtr pWin; - CursorPtr pCursor; - int n, rc; - DeviceIntPtr ptr = PickPointer(client); - - REQUEST_SIZE_MATCH(xXTestCompareCursorReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - if (stuff->cursor == None) - pCursor = NullCursor; - else if (stuff->cursor == XTestCurrentCursor) - pCursor = GetSpriteCursor(ptr); - else { - rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, - client, DixReadAccess); - if (rc != Success) - { - client->errorValue = stuff->cursor; - return rc; - } - } - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.same = (wCursor(pWin) == pCursor); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - } - WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); - return Success; -} - -static int -ProcXTestFakeInput(ClientPtr client) -{ - REQUEST(xXTestFakeInputReq); - int nev, n, type, rc; - xEvent *ev; - DeviceIntPtr dev = NULL; - WindowPtr root; - Bool extension = FALSE; - deviceValuator *dv = NULL; - 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 = dv->first_valuator; - return BadValue; - } - - - /* check validity of valuator events */ - base = firstValuator; - for (n = 1; n < nev; n++) - { - 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_SCREEN; - break; - default: - client->errorValue = ev->u.u.type; - return BadValue; - } - - 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, n); - } - 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; - - /* broken lib, XI events have root uninitialized */ - if (extension || ev->u.keyButtonPointer.root == None) - root = GetCurrentRootWindow(dev); - else - { - 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; - } - } - 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, (InternalEvent*)(xtest_evlist+i)->event, NULL); - - if (need_ptr_update) - miPointerUpdateSprite(dev); - return Success; -} - -static int -ProcXTestGrabControl(ClientPtr client) -{ - REQUEST(xXTestGrabControlReq); - - REQUEST_SIZE_MATCH(xXTestGrabControlReq); - if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) - { - client->errorValue = stuff->impervious; - return BadValue; - } - if (stuff->impervious) - MakeClientGrabImpervious(client); - else - MakeClientGrabPervious(client); - return Success; -} - -static int -ProcXTestDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XTestGetVersion: - return ProcXTestGetVersion(client); - case X_XTestCompareCursor: - return ProcXTestCompareCursor(client); - case X_XTestFakeInput: - return ProcXTestFakeInput(client); - case X_XTestGrabControl: - return ProcXTestGrabControl(client); - default: - return BadRequest; - } -} - -static int -SProcXTestGetVersion(ClientPtr client) -{ - int n; - REQUEST(xXTestGetVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestGetVersionReq); - swaps(&stuff->minorVersion, n); - return ProcXTestGetVersion(client); -} - -static int -SProcXTestCompareCursor(ClientPtr client) -{ - int n; - REQUEST(xXTestCompareCursorReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestCompareCursorReq); - swapl(&stuff->window, n); - swapl(&stuff->cursor, n); - return ProcXTestCompareCursor(client); -} - -static int -XTestSwapFakeInput(ClientPtr client, xReq *req) -{ - int nev; - xEvent *ev; - xEvent sev; - EventSwapPtr proc; - - nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); - for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) - { - /* Swap event */ - proc = EventSwapVector[ev->u.u.type & 0177]; - /* no swapping proc; invalid event type? */ - if (!proc || proc == NotImplemented) { - client->errorValue = ev->u.u.type; - return BadValue; - } - (*proc)(ev, &sev); - *ev = sev; - } - return Success; -} - -static int -SProcXTestFakeInput(ClientPtr client) -{ - int n; - REQUEST(xReq); - - swaps(&stuff->length, n); - n = XTestSwapFakeInput(client, stuff); - if (n != Success) - return n; - return ProcXTestFakeInput(client); -} - -static int -SProcXTestGrabControl(ClientPtr client) -{ - int n; - REQUEST(xXTestGrabControlReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestGrabControlReq); - return ProcXTestGrabControl(client); -} - -static int -SProcXTestDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XTestGetVersion: - return SProcXTestGetVersion(client); - case X_XTestCompareCursor: - return SProcXTestCompareCursor(client); - case X_XTestFakeInput: - return SProcXTestFakeInput(client); - case X_XTestGrabControl: - return SProcXTestGrabControl(client); - default: - return BadRequest; - } -} - -/** - * Allocate an virtual slave device for xtest events, this - * is a slave device to inputInfo master devices - */ -void InitXTestDevices(void) -{ - if(AllocXTestDevice(serverClient, "Virtual core", - &xtestpointer, &xtestkeyboard, - inputInfo.pointer, inputInfo.keyboard) != Success) - FatalError("Failed to allocate XTest devices"); - - if (ActivateDevice(xtestpointer, TRUE) != Success || - ActivateDevice(xtestkeyboard, TRUE) != Success) - FatalError("Failed to activate XTest core devices."); - if (!EnableDevice(xtestpointer, TRUE) || - !EnableDevice(xtestkeyboard, TRUE)) - FatalError("Failed to enable XTest core devices."); - - AttachDevice(NULL, xtestpointer, inputInfo.pointer); - AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard); -} - -/** - * Don't allow changing the XTest property. - */ -static int -DeviceSetXTestProperty(DeviceIntPtr dev, Atom property, - XIPropertyValuePtr prop, BOOL checkonly) -{ - if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE)) - return BadAccess; - - return Success; -} - -/** - * Allocate a device pair that is initialised as a slave - * device with properties that identify the devices as belonging - * to XTest subsystem. - * This only creates the pair, Activate/Enable Device - * still need to be called. - */ -int AllocXTestDevice (ClientPtr client, char* name, - DeviceIntPtr* ptr, DeviceIntPtr* keybd, - DeviceIntPtr master_ptr, DeviceIntPtr master_keybd) -{ - int retval; - int len = strlen(name); - char *xtestname = calloc(len + 7, 1 ); - char dummy = 1; - - strncpy( xtestname, name, len); - strncat( xtestname, " XTEST", 6 ); - - retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE); - if ( retval == Success ){ - (*ptr)->xtest_master_id = master_ptr->id; - (*keybd)->xtest_master_id = master_keybd->id; - - XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), - XA_INTEGER, 8, PropModeReplace, 1, &dummy, - FALSE); - XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); - XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL); - XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), - XA_INTEGER, 8, PropModeReplace, 1, &dummy, - FALSE); - XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); - XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL); - } - - free( xtestname ); - - return retval; -} - -/** - * If master is NULL, return TRUE if the given device is an xtest device or - * FALSE otherwise. - * If master is not NULL, return TRUE if the given device is this master's - * xtest device. - */ -BOOL -IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master) -{ - if (IsMaster(dev)) - return FALSE; - - /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest - * device */ - if (master) - return dev->xtest_master_id == master->id; - - return dev->xtest_master_id != 0; -} - -/** - * @return The X Test virtual device for the given master. - */ -DeviceIntPtr -GetXTestDevice(DeviceIntPtr master) -{ - DeviceIntPtr it; - - for (it = inputInfo.devices; it; it = it->next) - { - if (IsXTestDevice(it, master)) - return it; - } - - /* This only happens if master is a slave device. don't do that */ - return NULL; -} - -void -XTestExtensionInit(INITARGS) -{ - AddExtension(XTestExtensionName, 0, 0, - ProcXTestDispatch, SProcXTestDispatch, - NULL, StandardMinorOpcode); - - xtest_evlist = InitEventList(GetMaximumEventsNum()); -} +/* + + Copyright 1992, 1998 The Open Group + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of The Open Group shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from The Open Group. + + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "dixevents.h" +#include "sleepuntil.h" +#include "mi.h" +#include "xkbsrv.h" +#include "xkbstr.h" +#include +#include +#include +#include "exglobals.h" +#include "mipointer.h" +#include "xserver-properties.h" +#include "exevents.h" +#include "inpututils.h" + +#include "modinit.h" + +extern int DeviceValuator; + +/* XTest events are sent during request processing and may be interruped by + * a SIGIO. We need a separate event list to avoid events overwriting each + * other's memory */ +static EventListPtr xtest_evlist; + +/** + * xtestpointer + * is the virtual pointer for XTest. It is the first slave + * device of the VCP. + * xtestkeyboard + * is the virtual keyboard for XTest. It is the first slave + * device of the VCK + * + * Neither of these devices can be deleted. + */ +DeviceIntPtr xtestpointer, xtestkeyboard; + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static int XTestSwapFakeInput( + ClientPtr /* client */, + xReq * /* req */ + ); + + +static int +ProcXTestGetVersion(ClientPtr client) +{ + xXTestGetVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XTestMajorVersion; + rep.minorVersion = XTestMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXTestCompareCursor(ClientPtr client) +{ + REQUEST(xXTestCompareCursorReq); + xXTestCompareCursorReply rep; + WindowPtr pWin; + CursorPtr pCursor; + int n, rc; + DeviceIntPtr ptr = PickPointer(client); + + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + if (stuff->cursor == None) + pCursor = NullCursor; + else if (stuff->cursor == XTestCurrentCursor) + pCursor = GetSpriteCursor(ptr); + else { + rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, + client, DixReadAccess); + if (rc != Success) + { + client->errorValue = stuff->cursor; + return rc; + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.same = (wCursor(pWin) == pCursor); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); + return Success; +} + +static int +ProcXTestFakeInput(ClientPtr client) +{ + REQUEST(xXTestFakeInputReq); + int nev, n, type, rc; + xEvent *ev; + DeviceIntPtr dev = NULL; + WindowPtr root; + Bool extension = FALSE; + deviceValuator *dv = NULL; + 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 = dv->first_valuator; + return BadValue; + } + + + /* check validity of valuator events */ + base = firstValuator; + for (n = 1; n < nev; n++) + { + 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_SCREEN; + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + + 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, n); + } + 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; + } + } + 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, (InternalEvent*)(xtest_evlist+i)->event, NULL); + + if (need_ptr_update) + miPointerUpdateSprite(dev); + return Success; +} + +static int +ProcXTestGrabControl(ClientPtr client) +{ + REQUEST(xXTestGrabControlReq); + + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) + { + client->errorValue = stuff->impervious; + return BadValue; + } + if (stuff->impervious) + MakeClientGrabImpervious(client); + else + MakeClientGrabPervious(client); + return Success; +} + +static int +ProcXTestDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +static int +SProcXTestGetVersion(ClientPtr client) +{ + int n; + REQUEST(xXTestGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + swaps(&stuff->minorVersion, n); + return ProcXTestGetVersion(client); +} + +static int +SProcXTestCompareCursor(ClientPtr client) +{ + int n; + REQUEST(xXTestCompareCursorReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + swapl(&stuff->window, n); + swapl(&stuff->cursor, n); + return ProcXTestCompareCursor(client); +} + +static int +XTestSwapFakeInput(ClientPtr client, xReq *req) +{ + int nev; + xEvent *ev; + xEvent sev; + EventSwapPtr proc; + + nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); + for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) + { + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || proc == NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc)(ev, &sev); + *ev = sev; + } + return Success; +} + +static int +SProcXTestFakeInput(ClientPtr client) +{ + int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + n = XTestSwapFakeInput(client, stuff); + if (n != Success) + return n; + return ProcXTestFakeInput(client); +} + +static int +SProcXTestGrabControl(ClientPtr client) +{ + int n; + REQUEST(xXTestGrabControlReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + return ProcXTestGrabControl(client); +} + +static int +SProcXTestDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +/** + * Allocate an virtual slave device for xtest events, this + * is a slave device to inputInfo master devices + */ +void InitXTestDevices(void) +{ + if(AllocXTestDevice(serverClient, "Virtual core", + &xtestpointer, &xtestkeyboard, + inputInfo.pointer, inputInfo.keyboard) != Success) + FatalError("Failed to allocate XTest devices"); + + if (ActivateDevice(xtestpointer, TRUE) != Success || + ActivateDevice(xtestkeyboard, TRUE) != Success) + FatalError("Failed to activate XTest core devices."); + if (!EnableDevice(xtestpointer, TRUE) || + !EnableDevice(xtestkeyboard, TRUE)) + FatalError("Failed to enable XTest core devices."); + + AttachDevice(NULL, xtestpointer, inputInfo.pointer); + AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard); +} + +/** + * Don't allow changing the XTest property. + */ +static int +DeviceSetXTestProperty(DeviceIntPtr dev, Atom property, + XIPropertyValuePtr prop, BOOL checkonly) +{ + if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE)) + return BadAccess; + + return Success; +} + +/** + * Allocate a device pair that is initialised as a slave + * device with properties that identify the devices as belonging + * to XTest subsystem. + * This only creates the pair, Activate/Enable Device + * still need to be called. + */ +int AllocXTestDevice (ClientPtr client, char* name, + DeviceIntPtr* ptr, DeviceIntPtr* keybd, + DeviceIntPtr master_ptr, DeviceIntPtr master_keybd) +{ + int retval; + int len = strlen(name); + char *xtestname = calloc(len + 7, 1 ); + char dummy = 1; + + strncpy( xtestname, name, len); + strncat( xtestname, " XTEST", 6 ); + + retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE); + if ( retval == Success ){ + (*ptr)->xtest_master_id = master_ptr->id; + (*keybd)->xtest_master_id = master_keybd->id; + + XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), + XA_INTEGER, 8, PropModeReplace, 1, &dummy, + FALSE); + XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); + XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL); + XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), + XA_INTEGER, 8, PropModeReplace, 1, &dummy, + FALSE); + XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); + XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL); + } + + free( xtestname ); + + return retval; +} + +/** + * If master is NULL, return TRUE if the given device is an xtest device or + * FALSE otherwise. + * If master is not NULL, return TRUE if the given device is this master's + * xtest device. + */ +BOOL +IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master) +{ + if (IsMaster(dev)) + return FALSE; + + /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest + * device */ + if (master) + return dev->xtest_master_id == master->id; + + return dev->xtest_master_id != 0; +} + +/** + * @return The X Test virtual device for the given master. + */ +DeviceIntPtr +GetXTestDevice(DeviceIntPtr master) +{ + DeviceIntPtr it; + + for (it = inputInfo.devices; it; it = it->next) + { + if (IsXTestDevice(it, master)) + return it; + } + + /* This only happens if master is a slave device. don't do that */ + return NULL; +} + +void +XTestExtensionInit(INITARGS) +{ + AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + NULL, StandardMinorOpcode); + + xtest_evlist = InitEventList(GetMaximumEventsNum()); +} -- cgit v1.2.3