xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xtest.c (20153B)


      1 /*
      2 
      3    Copyright 1992, 1998  The Open Group
      4 
      5    Permission to use, copy, modify, distribute, and sell this software and its
      6    documentation for any purpose is hereby granted without fee, provided that
      7    the above copyright notice appear in all copies and that both that
      8    copyright notice and this permission notice appear in supporting
      9    documentation.
     10 
     11    The above copyright notice and this permission notice shall be included
     12    in all copies or substantial portions of the Software.
     13 
     14    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17    IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20    OTHER DEALINGS IN THE SOFTWARE.
     21 
     22    Except as contained in this notice, the name of The Open Group shall
     23    not be used in advertising or otherwise to promote the sale, use or
     24    other dealings in this Software without prior written authorization
     25    from The Open Group.
     26 
     27  */
     28 
     29 #ifdef HAVE_DIX_CONFIG_H
     30 #include <dix-config.h>
     31 #endif
     32 
     33 #include <X11/X.h>
     34 #include <X11/Xproto.h>
     35 #include <X11/Xatom.h>
     36 #include "misc.h"
     37 #include "os.h"
     38 #include "dixstruct.h"
     39 #include "extnsionst.h"
     40 #include "windowstr.h"
     41 #include "inputstr.h"
     42 #include "scrnintstr.h"
     43 #include "dixevents.h"
     44 #include "sleepuntil.h"
     45 #include "mi.h"
     46 #include "xkbsrv.h"
     47 #include "xkbstr.h"
     48 #include <X11/extensions/xtestproto.h>
     49 #include <X11/extensions/XI.h>
     50 #include <X11/extensions/XIproto.h>
     51 #include "exglobals.h"
     52 #include "mipointer.h"
     53 #include "xserver-properties.h"
     54 #include "exevents.h"
     55 #include "eventstr.h"
     56 #include "inpututils.h"
     57 
     58 #include "extinit.h"
     59 
     60 /* XTest events are sent during request processing and may be interrupted by
     61  * a SIGIO. We need a separate event list to avoid events overwriting each
     62  * other's memory.
     63  */
     64 static InternalEvent *xtest_evlist;
     65 
     66 /**
     67  * xtestpointer
     68  * is the virtual pointer for XTest. It is the first slave
     69  * device of the VCP.
     70  * xtestkeyboard
     71  * is the virtual keyboard for XTest. It is the first slave
     72  * device of the VCK
     73  *
     74  * Neither of these devices can be deleted.
     75  */
     76 DeviceIntPtr xtestpointer, xtestkeyboard;
     77 
     78 #ifdef PANORAMIX
     79 #include "panoramiX.h"
     80 #include "panoramiXsrv.h"
     81 #endif
     82 
     83 static int XTestSwapFakeInput(ClientPtr /* client */ ,
     84                               xReq *    /* req */
     85     );
     86 
     87 static int
     88 ProcXTestGetVersion(ClientPtr client)
     89 {
     90     xXTestGetVersionReply rep = {
     91         .type = X_Reply,
     92         .sequenceNumber = client->sequence,
     93         .length = 0,
     94         .majorVersion = XTestMajorVersion,
     95         .minorVersion = XTestMinorVersion
     96     };
     97 
     98     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
     99 
    100     if (client->swapped) {
    101         swaps(&rep.sequenceNumber);
    102         swaps(&rep.minorVersion);
    103     }
    104     WriteToClient(client, sizeof(xXTestGetVersionReply), &rep);
    105     return Success;
    106 }
    107 
    108 static int
    109 ProcXTestCompareCursor(ClientPtr client)
    110 {
    111     REQUEST(xXTestCompareCursorReq);
    112     xXTestCompareCursorReply rep;
    113     WindowPtr pWin;
    114     CursorPtr pCursor;
    115     int rc;
    116     DeviceIntPtr ptr = PickPointer(client);
    117 
    118     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
    119     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    120     if (rc != Success)
    121         return rc;
    122 
    123     if (!ptr)
    124         return BadAccess;
    125 
    126     if (stuff->cursor == None)
    127         pCursor = NullCursor;
    128     else if (stuff->cursor == XTestCurrentCursor)
    129         pCursor = GetSpriteCursor(ptr);
    130     else {
    131         rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor,
    132                                      RT_CURSOR, client, DixReadAccess);
    133         if (rc != Success) {
    134             client->errorValue = stuff->cursor;
    135             return rc;
    136         }
    137     }
    138     rep = (xXTestCompareCursorReply) {
    139         .type = X_Reply,
    140         .sequenceNumber = client->sequence,
    141         .length = 0,
    142         .same = (wCursor(pWin) == pCursor)
    143     };
    144     if (client->swapped) {
    145         swaps(&rep.sequenceNumber);
    146     }
    147     WriteToClient(client, sizeof(xXTestCompareCursorReply), &rep);
    148     return Success;
    149 }
    150 
    151 static int
    152 ProcXTestFakeInput(ClientPtr client)
    153 {
    154     REQUEST(xXTestFakeInputReq);
    155     int nev, n, type, rc;
    156     xEvent *ev;
    157     DeviceIntPtr dev = NULL;
    158     WindowPtr root;
    159     Bool extension = FALSE;
    160     ValuatorMask mask;
    161     int valuators[MAX_VALUATORS] = { 0 };
    162     int numValuators = 0;
    163     int firstValuator = 0;
    164     int nevents = 0;
    165     int i;
    166     int base = 0;
    167     int flags = 0;
    168     int need_ptr_update = 1;
    169 
    170     nev = (stuff->length << 2) - sizeof(xReq);
    171     if ((nev % sizeof(xEvent)) || !nev)
    172         return BadLength;
    173     nev /= sizeof(xEvent);
    174     UpdateCurrentTime();
    175     ev = (xEvent *) &((xReq *) stuff)[1];
    176     type = ev->u.u.type & 0177;
    177 
    178     if (type >= EXTENSION_EVENT_BASE) {
    179         extension = TRUE;
    180 
    181         /* check device */
    182         rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
    183                              DixWriteAccess);
    184         if (rc != Success) {
    185             client->errorValue = stuff->deviceid & 0177;
    186             return rc;
    187         }
    188 
    189         /* check type */
    190         type -= DeviceValuator;
    191         switch (type) {
    192         case XI_DeviceKeyPress:
    193         case XI_DeviceKeyRelease:
    194             if (!dev->key) {
    195                 client->errorValue = ev->u.u.type;
    196                 return BadValue;
    197             }
    198             break;
    199         case XI_DeviceButtonPress:
    200         case XI_DeviceButtonRelease:
    201             if (!dev->button) {
    202                 client->errorValue = ev->u.u.type;
    203                 return BadValue;
    204             }
    205             break;
    206         case XI_DeviceMotionNotify:
    207             if (!dev->valuator) {
    208                 client->errorValue = ev->u.u.type;
    209                 return BadValue;
    210             }
    211             break;
    212         case XI_ProximityIn:
    213         case XI_ProximityOut:
    214             if (!dev->proximity) {
    215                 client->errorValue = ev->u.u.type;
    216                 return BadValue;
    217             }
    218             break;
    219         default:
    220             client->errorValue = ev->u.u.type;
    221             return BadValue;
    222         }
    223 
    224         /* check validity */
    225         if (nev == 1 && type == XI_DeviceMotionNotify)
    226             return BadLength;   /* DevMotion must be followed by DevValuator */
    227 
    228         if (type == XI_DeviceMotionNotify) {
    229             firstValuator = ((deviceValuator *) (ev + 1))->first_valuator;
    230             if (firstValuator > dev->valuator->numAxes) {
    231                 client->errorValue = ev->u.u.type;
    232                 return BadValue;
    233             }
    234 
    235             if (ev->u.u.detail == xFalse)
    236                 flags |= POINTER_ABSOLUTE;
    237         }
    238         else {
    239             firstValuator = 0;
    240             flags |= POINTER_ABSOLUTE;
    241         }
    242 
    243         if (nev > 1 && !dev->valuator) {
    244             client->errorValue = firstValuator;
    245             return BadValue;
    246         }
    247 
    248         /* check validity of valuator events */
    249         base = firstValuator;
    250         for (n = 1; n < nev; n++) {
    251             deviceValuator *dv = (deviceValuator *) (ev + n);
    252             if (dv->type != DeviceValuator) {
    253                 client->errorValue = dv->type;
    254                 return BadValue;
    255             }
    256             if (dv->first_valuator != base) {
    257                 client->errorValue = dv->first_valuator;
    258                 return BadValue;
    259             }
    260             switch (dv->num_valuators) {
    261             case 6:
    262                 valuators[base + 5] = dv->valuator5;
    263             case 5:
    264                 valuators[base + 4] = dv->valuator4;
    265             case 4:
    266                 valuators[base + 3] = dv->valuator3;
    267             case 3:
    268                 valuators[base + 2] = dv->valuator2;
    269             case 2:
    270                 valuators[base + 1] = dv->valuator1;
    271             case 1:
    272                 valuators[base] = dv->valuator0;
    273                 break;
    274             default:
    275                 client->errorValue = dv->num_valuators;
    276                 return BadValue;
    277             }
    278 
    279             base += dv->num_valuators;
    280             numValuators += dv->num_valuators;
    281 
    282             if (firstValuator + numValuators > dev->valuator->numAxes) {
    283                 client->errorValue = dv->num_valuators;
    284                 return BadValue;
    285             }
    286         }
    287         type = type - XI_DeviceKeyPress + KeyPress;
    288 
    289     }
    290     else {
    291         if (nev != 1)
    292             return BadLength;
    293         switch (type) {
    294         case KeyPress:
    295         case KeyRelease:
    296             dev = PickKeyboard(client);
    297             break;
    298         case ButtonPress:
    299         case ButtonRelease:
    300             dev = PickPointer(client);
    301             break;
    302         case MotionNotify:
    303             dev = PickPointer(client);
    304             valuators[0] = ev->u.keyButtonPointer.rootX;
    305             valuators[1] = ev->u.keyButtonPointer.rootY;
    306             numValuators = 2;
    307             firstValuator = 0;
    308             if (ev->u.u.detail == xFalse)
    309                 flags = POINTER_ABSOLUTE | POINTER_DESKTOP;
    310             break;
    311         default:
    312             client->errorValue = ev->u.u.type;
    313             return BadValue;
    314         }
    315 
    316         /* Technically the protocol doesn't allow for BadAccess here but
    317          * this can only happen when all MDs are disabled.  */
    318         if (!dev)
    319             return BadAccess;
    320 
    321         dev = GetXTestDevice(dev);
    322     }
    323 
    324 
    325     /* If the event has a time set, wait for it to pass */
    326     if (ev->u.keyButtonPointer.time) {
    327         TimeStamp activateTime;
    328         CARD32 ms;
    329 
    330         activateTime = currentTime;
    331         ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
    332         if (ms < activateTime.milliseconds)
    333             activateTime.months++;
    334         activateTime.milliseconds = ms;
    335         ev->u.keyButtonPointer.time = 0;
    336 
    337         /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer
    338          * extension) for code similar to this */
    339 
    340         if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) {
    341             return BadAlloc;
    342         }
    343         /* swap the request back so we can simply re-execute it */
    344         if (client->swapped) {
    345             (void) XTestSwapFakeInput(client, (xReq *) stuff);
    346             swaps(&stuff->length);
    347         }
    348         ResetCurrentRequest(client);
    349         client->sequence--;
    350         return Success;
    351     }
    352 
    353     switch (type) {
    354     case KeyPress:
    355     case KeyRelease:
    356         if (!dev->key)
    357             return BadDevice;
    358 
    359         if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
    360             ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) {
    361             client->errorValue = ev->u.u.detail;
    362             return BadValue;
    363         }
    364 
    365         need_ptr_update = 0;
    366         break;
    367     case MotionNotify:
    368         if (!dev->valuator)
    369             return BadDevice;
    370 
    371         if (!(extension || ev->u.keyButtonPointer.root == None)) {
    372             rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root,
    373                                  client, DixGetAttrAccess);
    374             if (rc != Success)
    375                 return rc;
    376             if (root->parent) {
    377                 client->errorValue = ev->u.keyButtonPointer.root;
    378                 return BadValue;
    379             }
    380 
    381             /* Add the root window's offset to the valuators */
    382             if ((flags & POINTER_ABSOLUTE) && firstValuator <= 1 && numValuators > 0) {
    383                 if (firstValuator == 0)
    384                     valuators[0] += root->drawable.pScreen->x;
    385                 if (firstValuator < 2 && firstValuator + numValuators > 1)
    386                     valuators[1 - firstValuator] += root->drawable.pScreen->y;
    387             }
    388         }
    389         if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) {
    390             client->errorValue = ev->u.u.detail;
    391             return BadValue;
    392         }
    393 
    394         /* FIXME: Xinerama! */
    395 
    396         break;
    397     case ButtonPress:
    398     case ButtonRelease:
    399         if (!dev->button)
    400             return BadDevice;
    401 
    402         if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) {
    403             client->errorValue = ev->u.u.detail;
    404             return BadValue;
    405         }
    406         break;
    407     }
    408     if (screenIsSaved == SCREEN_SAVER_ON)
    409         dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
    410 
    411     switch (type) {
    412     case MotionNotify:
    413         valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
    414         nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
    415         break;
    416     case ButtonPress:
    417     case ButtonRelease:
    418         valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
    419         nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
    420                                    flags, &mask);
    421         break;
    422     case KeyPress:
    423     case KeyRelease:
    424         nevents =
    425             GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
    426         break;
    427     }
    428 
    429     for (i = 0; i < nevents; i++)
    430         mieqProcessDeviceEvent(dev, &xtest_evlist[i], miPointerGetScreen(inputInfo.pointer));
    431 
    432     if (need_ptr_update)
    433         miPointerUpdateSprite(dev);
    434     return Success;
    435 }
    436 
    437 static int
    438 ProcXTestGrabControl(ClientPtr client)
    439 {
    440     REQUEST(xXTestGrabControlReq);
    441 
    442     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
    443     if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) {
    444         client->errorValue = stuff->impervious;
    445         return BadValue;
    446     }
    447     if (stuff->impervious)
    448         MakeClientGrabImpervious(client);
    449     else
    450         MakeClientGrabPervious(client);
    451     return Success;
    452 }
    453 
    454 static int
    455 ProcXTestDispatch(ClientPtr client)
    456 {
    457     REQUEST(xReq);
    458     switch (stuff->data) {
    459     case X_XTestGetVersion:
    460         return ProcXTestGetVersion(client);
    461     case X_XTestCompareCursor:
    462         return ProcXTestCompareCursor(client);
    463     case X_XTestFakeInput:
    464         return ProcXTestFakeInput(client);
    465     case X_XTestGrabControl:
    466         return ProcXTestGrabControl(client);
    467     default:
    468         return BadRequest;
    469     }
    470 }
    471 
    472 static int _X_COLD
    473 SProcXTestGetVersion(ClientPtr client)
    474 {
    475     REQUEST(xXTestGetVersionReq);
    476 
    477     swaps(&stuff->length);
    478     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
    479     swaps(&stuff->minorVersion);
    480     return ProcXTestGetVersion(client);
    481 }
    482 
    483 static int _X_COLD
    484 SProcXTestCompareCursor(ClientPtr client)
    485 {
    486     REQUEST(xXTestCompareCursorReq);
    487 
    488     swaps(&stuff->length);
    489     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
    490     swapl(&stuff->window);
    491     swapl(&stuff->cursor);
    492     return ProcXTestCompareCursor(client);
    493 }
    494 
    495 static int _X_COLD
    496 XTestSwapFakeInput(ClientPtr client, xReq * req)
    497 {
    498     int nev;
    499     xEvent *ev;
    500     xEvent sev;
    501     EventSwapPtr proc;
    502 
    503     nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
    504     for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) {
    505         /* Swap event */
    506         proc = EventSwapVector[ev->u.u.type & 0177];
    507         /* no swapping proc; invalid event type? */
    508         if (!proc || proc == NotImplemented) {
    509             client->errorValue = ev->u.u.type;
    510             return BadValue;
    511         }
    512         (*proc) (ev, &sev);
    513         *ev = sev;
    514     }
    515     return Success;
    516 }
    517 
    518 static int _X_COLD
    519 SProcXTestFakeInput(ClientPtr client)
    520 {
    521     int n;
    522 
    523     REQUEST(xReq);
    524 
    525     swaps(&stuff->length);
    526     n = XTestSwapFakeInput(client, stuff);
    527     if (n != Success)
    528         return n;
    529     return ProcXTestFakeInput(client);
    530 }
    531 
    532 static int _X_COLD
    533 SProcXTestGrabControl(ClientPtr client)
    534 {
    535     REQUEST(xXTestGrabControlReq);
    536 
    537     swaps(&stuff->length);
    538     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
    539     return ProcXTestGrabControl(client);
    540 }
    541 
    542 static int _X_COLD
    543 SProcXTestDispatch(ClientPtr client)
    544 {
    545     REQUEST(xReq);
    546     switch (stuff->data) {
    547     case X_XTestGetVersion:
    548         return SProcXTestGetVersion(client);
    549     case X_XTestCompareCursor:
    550         return SProcXTestCompareCursor(client);
    551     case X_XTestFakeInput:
    552         return SProcXTestFakeInput(client);
    553     case X_XTestGrabControl:
    554         return SProcXTestGrabControl(client);
    555     default:
    556         return BadRequest;
    557     }
    558 }
    559 
    560 /**
    561  * Allocate an virtual slave device for xtest events, this
    562  * is a slave device to inputInfo master devices
    563  */
    564 void
    565 InitXTestDevices(void)
    566 {
    567     if (AllocXTestDevice(serverClient, "Virtual core",
    568                          &xtestpointer, &xtestkeyboard,
    569                          inputInfo.pointer, inputInfo.keyboard) != Success)
    570          FatalError("Failed to allocate XTest devices");
    571 
    572     if (ActivateDevice(xtestpointer, TRUE) != Success ||
    573         ActivateDevice(xtestkeyboard, TRUE) != Success)
    574         FatalError("Failed to activate XTest core devices.");
    575     if (!EnableDevice(xtestpointer, TRUE) || !EnableDevice(xtestkeyboard, TRUE))
    576         FatalError("Failed to enable XTest core devices.");
    577 
    578     AttachDevice(NULL, xtestpointer, inputInfo.pointer);
    579 
    580     AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard);
    581 }
    582 
    583 /**
    584  * Don't allow changing the XTest property.
    585  */
    586 static int
    587 DeviceSetXTestProperty(DeviceIntPtr dev, Atom property,
    588                        XIPropertyValuePtr prop, BOOL checkonly)
    589 {
    590     if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE))
    591         return BadAccess;
    592 
    593     return Success;
    594 }
    595 
    596 /**
    597  * Allocate a device pair that is initialised as a slave
    598  * device with properties that identify the devices as belonging
    599  * to XTest subsystem.
    600  * This only creates the pair, Activate/Enable Device
    601  * still need to be called.
    602  */
    603 int
    604 AllocXTestDevice(ClientPtr client, const char *name,
    605                  DeviceIntPtr *ptr, DeviceIntPtr *keybd,
    606                  DeviceIntPtr master_ptr, DeviceIntPtr master_keybd)
    607 {
    608     int retval;
    609     char *xtestname;
    610     char dummy = 1;
    611 
    612     if (asprintf(&xtestname, "%s XTEST", name) == -1)
    613         return BadAlloc;
    614 
    615     retval =
    616         AllocDevicePair(client, xtestname, ptr, keybd, CorePointerProc,
    617                         CoreKeyboardProc, FALSE);
    618     if (retval == Success) {
    619         (*ptr)->xtest_master_id = master_ptr->id;
    620         (*keybd)->xtest_master_id = master_keybd->id;
    621 
    622         XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
    623                                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
    624                                FALSE);
    625         XISetDevicePropertyDeletable(*ptr,
    626                                      XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
    627                                      FALSE);
    628         XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL);
    629         XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
    630                                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
    631                                FALSE);
    632         XISetDevicePropertyDeletable(*keybd,
    633                                      XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
    634                                      FALSE);
    635         XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
    636     }
    637 
    638     free(xtestname);
    639 
    640     return retval;
    641 }
    642 
    643 /**
    644  * If master is NULL, return TRUE if the given device is an xtest device or
    645  * FALSE otherwise.
    646  * If master is not NULL, return TRUE if the given device is this master's
    647  * xtest device.
    648  */
    649 BOOL
    650 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
    651 {
    652     if (IsMaster(dev))
    653         return FALSE;
    654 
    655     /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest
    656      * device */
    657     if (master)
    658         return dev->xtest_master_id == master->id;
    659 
    660     return dev->xtest_master_id != 0;
    661 }
    662 
    663 /**
    664  * @return The X Test virtual device for the given master.
    665  */
    666 DeviceIntPtr
    667 GetXTestDevice(DeviceIntPtr master)
    668 {
    669     DeviceIntPtr it;
    670 
    671     for (it = inputInfo.devices; it; it = it->next) {
    672         if (IsXTestDevice(it, master))
    673             return it;
    674     }
    675 
    676     /* This only happens if master is a slave device. don't do that */
    677     return NULL;
    678 }
    679 
    680 static void
    681 XTestExtensionTearDown(ExtensionEntry * e)
    682 {
    683     FreeEventList(xtest_evlist, GetMaximumEventsNum());
    684     xtest_evlist = NULL;
    685 }
    686 
    687 void
    688 XTestExtensionInit(void)
    689 {
    690     AddExtension(XTestExtensionName, 0, 0,
    691                  ProcXTestDispatch, SProcXTestDispatch,
    692                  XTestExtensionTearDown, StandardMinorOpcode);
    693 
    694     xtest_evlist = InitEventList(GetMaximumEventsNum());
    695 }