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