"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/dix/devices.c" (29 Mar 2020, 81401 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "devices.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    1 /************************************************************
    2 
    3 Copyright 1987, 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 in
   12 all copies or substantial portions of the Software.
   13 
   14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
   18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   20 
   21 Except as contained in this notice, the name of The Open Group shall not be
   22 used in advertising or otherwise to promote the sale, use or other dealings
   23 in this Software without prior written authorization from The Open Group.
   24 
   25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
   26 
   27                         All Rights Reserved
   28 
   29 Permission to use, copy, modify, and distribute this software and its
   30 documentation for any purpose and without fee is hereby granted,
   31 provided that the above copyright notice appear in all copies and that
   32 both that copyright notice and this permission notice appear in
   33 supporting documentation, and that the name of Digital not be
   34 used in advertising or publicity pertaining to distribution of the
   35 software without specific, written prior permission.
   36 
   37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   43 SOFTWARE.
   44 
   45 ********************************************************/
   46 
   47 #ifdef HAVE_DIX_CONFIG_H
   48 #include <dix-config.h>
   49 #endif
   50 
   51 #include <X11/X.h>
   52 #include "misc.h"
   53 #include "resource.h"
   54 #include <X11/Xproto.h>
   55 #include <X11/Xatom.h>
   56 #include "windowstr.h"
   57 #include "inputstr.h"
   58 #include "scrnintstr.h"
   59 #include "cursorstr.h"
   60 #include "dixstruct.h"
   61 #include "ptrveloc.h"
   62 #include "site.h"
   63 #include "xkbsrv.h"
   64 #include "privates.h"
   65 #include "xace.h"
   66 #include "mi.h"
   67 
   68 #include "dispatch.h"
   69 #include "swaprep.h"
   70 #include "dixevents.h"
   71 #include "mipointer.h"
   72 #include "eventstr.h"
   73 #include "dixgrabs.h"
   74 
   75 #include <X11/extensions/XI.h>
   76 #include <X11/extensions/XI2.h>
   77 #include <X11/extensions/XIproto.h>
   78 #include <math.h>
   79 #include <pixman.h>
   80 #include "exglobals.h"
   81 #include "exevents.h"
   82 #include "xiquerydevice.h"      /* for SizeDeviceClasses */
   83 #include "xiproperty.h"
   84 #include "enterleave.h"         /* for EnterWindow() */
   85 #include "xserver-properties.h"
   86 #include "xichangehierarchy.h"  /* For XISendDeviceHierarchyEvent */
   87 #include "syncsrv.h"
   88 
   89 /** @file
   90  * This file handles input device-related stuff.
   91  */
   92 
   93 static void RecalculateMasterButtons(DeviceIntPtr slave);
   94 
   95 static void
   96 DeviceSetTransform(DeviceIntPtr dev, float *transform_data)
   97 {
   98     struct pixman_f_transform scale;
   99     struct pixman_f_transform transform;
  100     double sx, sy;
  101     int x, y;
  102 
  103     /**
  104      * calculate combined transformation matrix:
  105      *
  106      * M = InvScale * Transform * Scale
  107      *
  108      * So we can later transform points using M * p
  109      *
  110      * Where:
  111      *  Scale scales coordinates into 0..1 range
  112      *  Transform is the user supplied (affine) transform
  113      *  InvScale scales coordinates back up into their native range
  114      */
  115     sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value + 1;
  116     sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value + 1;
  117 
  118     /* invscale */
  119     pixman_f_transform_init_scale(&scale, sx, sy);
  120     scale.m[0][2] = dev->valuator->axes[0].min_value;
  121     scale.m[1][2] = dev->valuator->axes[1].min_value;
  122 
  123     /* transform */
  124     for (y = 0; y < 3; y++)
  125         for (x = 0; x < 3; x++)
  126             transform.m[y][x] = *transform_data++;
  127 
  128     pixman_f_transform_multiply(&dev->scale_and_transform, &scale, &transform);
  129 
  130     /* scale */
  131     pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
  132     scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
  133     scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;
  134 
  135     pixman_f_transform_multiply(&dev->scale_and_transform, &dev->scale_and_transform, &scale);
  136 
  137     /* remove translation component for relative movements */
  138     dev->relative_transform = transform;
  139     dev->relative_transform.m[0][2] = 0;
  140     dev->relative_transform.m[1][2] = 0;
  141 }
  142 
  143 /**
  144  * DIX property handler.
  145  */
  146 static int
  147 DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
  148                   BOOL checkonly)
  149 {
  150     if (property == XIGetKnownProperty(XI_PROP_ENABLED)) {
  151         if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1)
  152             return BadValue;
  153 
  154         /* Don't allow disabling of VCP/VCK or XTest devices */
  155         if ((dev == inputInfo.pointer ||
  156              dev == inputInfo.keyboard ||
  157              IsXTestDevice(dev, NULL))
  158             &&!(*(CARD8 *) prop->data))
  159             return BadAccess;
  160 
  161         if (!checkonly) {
  162             if ((*((CARD8 *) prop->data)) && !dev->enabled)
  163                 EnableDevice(dev, TRUE);
  164             else if (!(*((CARD8 *) prop->data)) && dev->enabled)
  165                 DisableDevice(dev, TRUE);
  166         }
  167     }
  168     else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) {
  169         float *f = (float *) prop->data;
  170         int i;
  171 
  172         if (prop->format != 32 || prop->size != 9 ||
  173             prop->type != XIGetKnownProperty(XATOM_FLOAT))
  174             return BadValue;
  175 
  176         for (i = 0; i < 9; i++)
  177             if (!isfinite(f[i]))
  178                 return BadValue;
  179 
  180         if (!dev->valuator)
  181             return BadMatch;
  182 
  183         if (!checkonly)
  184             DeviceSetTransform(dev, f);
  185     }
  186 
  187     return Success;
  188 }
  189 
  190 /* Pair the keyboard to the pointer device. Keyboard events will follow the
  191  * pointer sprite. Only applicable for master devices.
  192  */
  193 static int
  194 PairDevices(DeviceIntPtr ptr, DeviceIntPtr kbd)
  195 {
  196     if (!ptr)
  197         return BadDevice;
  198 
  199     /* Don't allow pairing for slave devices */
  200     if (!IsMaster(ptr) || !IsMaster(kbd))
  201         return BadDevice;
  202 
  203     if (ptr->spriteInfo->paired)
  204         return BadDevice;
  205 
  206     if (kbd->spriteInfo->spriteOwner) {
  207         free(kbd->spriteInfo->sprite);
  208         kbd->spriteInfo->sprite = NULL;
  209         kbd->spriteInfo->spriteOwner = FALSE;
  210     }
  211 
  212     kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
  213     kbd->spriteInfo->paired = ptr;
  214     ptr->spriteInfo->paired = kbd;
  215     return Success;
  216 }
  217 
  218 /**
  219  * Find and return the next unpaired MD pointer device.
  220  */
  221 static DeviceIntPtr
  222 NextFreePointerDevice(void)
  223 {
  224     DeviceIntPtr dev;
  225 
  226     for (dev = inputInfo.devices; dev; dev = dev->next)
  227         if (IsMaster(dev) &&
  228             dev->spriteInfo->spriteOwner && !dev->spriteInfo->paired)
  229             return dev;
  230     return NULL;
  231 }
  232 
  233 /**
  234  * Create a new input device and init it to sane values. The device is added
  235  * to the server's off_devices list.
  236  *
  237  * @param deviceProc Callback for device control function (switch dev on/off).
  238  * @return The newly created device.
  239  */
  240 DeviceIntPtr
  241 AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
  242 {
  243     DeviceIntPtr dev, *prev;    /* not a typo */
  244     DeviceIntPtr devtmp;
  245     int devid;
  246     char devind[MAXDEVICES];
  247     BOOL enabled;
  248     float transform[9];
  249 
  250     /* Find next available id, 0 and 1 are reserved */
  251     memset(devind, 0, sizeof(char) * MAXDEVICES);
  252     for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
  253         devind[devtmp->id]++;
  254     for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
  255         devind[devtmp->id]++;
  256     for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++);
  257 
  258     if (devid >= MAXDEVICES)
  259         return (DeviceIntPtr) NULL;
  260     dev = calloc(1,
  261                  sizeof(DeviceIntRec) +
  262                  sizeof(SpriteInfoRec));
  263     if (!dev)
  264         return (DeviceIntPtr) NULL;
  265 
  266     if (!dixAllocatePrivates(&dev->devPrivates, PRIVATE_DEVICE)) {
  267         free(dev);
  268         return NULL;
  269     }
  270 
  271     if (!dev)
  272         return (DeviceIntPtr) NULL;
  273 
  274     dev->last.scroll = NULL;
  275     dev->last.touches = NULL;
  276     dev->id = devid;
  277     dev->public.processInputProc = ProcessOtherEvent;
  278     dev->public.realInputProc = ProcessOtherEvent;
  279     dev->public.enqueueInputProc = EnqueueEvent;
  280     dev->deviceProc = deviceProc;
  281     dev->startup = autoStart;
  282 
  283     /* device grab defaults */
  284     UpdateCurrentTimeIf();
  285     dev->deviceGrab.grabTime = currentTime;
  286     dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
  287     dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
  288     dev->deviceGrab.sync.event = calloc(1, sizeof(DeviceEvent));
  289 
  290     XkbSetExtension(dev, ProcessKeyboardEvent);
  291 
  292     dev->coreEvents = TRUE;
  293 
  294     /* sprite defaults */
  295     dev->spriteInfo = (SpriteInfoPtr) &dev[1];
  296 
  297     /*  security creation/labeling check
  298      */
  299     if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
  300         dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE);
  301         free(dev);
  302         return NULL;
  303     }
  304 
  305     inputInfo.numDevices++;
  306 
  307     for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next);
  308     *prev = dev;
  309     dev->next = NULL;
  310 
  311     enabled = FALSE;
  312     XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
  313                            XA_INTEGER, 8, PropModeReplace, 1, &enabled, FALSE);
  314     XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED),
  315                                  FALSE);
  316 
  317     /* unity matrix */
  318     memset(transform, 0, sizeof(transform));
  319     transform[0] = transform[4] = transform[8] = 1.0f;
  320     dev->relative_transform.m[0][0] = 1.0;
  321     dev->relative_transform.m[1][1] = 1.0;
  322     dev->relative_transform.m[2][2] = 1.0;
  323     dev->scale_and_transform = dev->relative_transform;
  324 
  325     XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
  326                            XIGetKnownProperty(XATOM_FLOAT), 32,
  327                            PropModeReplace, 9, transform, FALSE);
  328     XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
  329                                  FALSE);
  330 
  331     XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
  332 
  333     return dev;
  334 }
  335 
  336 void
  337 SendDevicePresenceEvent(int deviceid, int type)
  338 {
  339     DeviceIntRec dummyDev = { .id =  XIAllDevices };
  340     devicePresenceNotify ev;
  341 
  342     UpdateCurrentTimeIf();
  343     ev.type = DevicePresenceNotify;
  344     ev.time = currentTime.milliseconds;
  345     ev.devchange = type;
  346     ev.deviceid = deviceid;
  347 
  348     SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
  349                           (xEvent *) &ev, 1);
  350 }
  351 
  352 /**
  353  * Enable the device through the driver, add the device to the device list.
  354  * Switch device ON through the driver and push it onto the global device
  355  * list. Initialize the DIX sprite or pair the device. All clients are
  356  * notified about the device being enabled.
  357  *
  358  * A master pointer device needs to be enabled before a master keyboard
  359  * device.
  360  *
  361  * @param The device to be enabled.
  362  * @param sendevent True if an XI2 event should be sent.
  363  * @return TRUE on success or FALSE otherwise.
  364  */
  365 Bool
  366 EnableDevice(DeviceIntPtr dev, BOOL sendevent)
  367 {
  368     DeviceIntPtr *prev;
  369     int ret;
  370     DeviceIntPtr other;
  371     BOOL enabled;
  372     int flags[MAXDEVICES] = { 0 };
  373 
  374     for (prev = &inputInfo.off_devices;
  375          *prev && (*prev != dev); prev = &(*prev)->next);
  376 
  377     if (!dev->spriteInfo->sprite) {
  378         if (IsMaster(dev)) {
  379             /* Sprites appear on first root window, so we can hardcode it */
  380             if (dev->spriteInfo->spriteOwner) {
  381                 InitializeSprite(dev, screenInfo.screens[0]->root);
  382                 /* mode doesn't matter */
  383                 EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor);
  384             }
  385             else {
  386                 other = NextFreePointerDevice();
  387                 BUG_RETURN_VAL_MSG(other == NULL, FALSE,
  388                                    "[dix] cannot find pointer to pair with.\n");
  389                 PairDevices(other, dev);
  390             }
  391         }
  392         else {
  393             if (dev->coreEvents)
  394                 other = (IsPointerDevice(dev)) ? inputInfo.pointer:
  395                     inputInfo.keyboard;
  396             else
  397                 other = NULL;   /* auto-float non-core devices */
  398             AttachDevice(NULL, dev, other);
  399         }
  400     }
  401 
  402     input_lock();
  403     if ((*prev != dev) || !dev->inited ||
  404         ((ret = (*dev->deviceProc) (dev, DEVICE_ON)) != Success)) {
  405         ErrorF("[dix] couldn't enable device %d\n", dev->id);
  406         input_unlock();
  407         return FALSE;
  408     }
  409     dev->enabled = TRUE;
  410     *prev = dev->next;
  411 
  412     for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next);
  413     *prev = dev;
  414     dev->next = NULL;
  415     input_unlock();
  416 
  417     enabled = TRUE;
  418     XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
  419                            XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE);
  420 
  421     SendDevicePresenceEvent(dev->id, DeviceEnabled);
  422     if (sendevent) {
  423         flags[dev->id] |= XIDeviceEnabled;
  424         XISendDeviceHierarchyEvent(flags);
  425     }
  426 
  427     if (!IsMaster(dev) && !IsFloating(dev))
  428         XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
  429     RecalculateMasterButtons(dev);
  430 
  431     /* initialise an idle timer for this device*/
  432     dev->idle_counter = SyncInitDeviceIdleTime(dev);
  433 
  434     return TRUE;
  435 }
  436 
  437 
  438 /**
  439  * Switch a device off through the driver and push it onto the off_devices
  440  * list. A device will not send events while disabled. All clients are
  441  * notified about the device being disabled.
  442  *
  443  * Master keyboard devices have to be disabled before master pointer devices
  444  * otherwise things turn bad.
  445  *
  446  * @param sendevent True if an XI2 event should be sent.
  447  * @return TRUE on success or FALSE otherwise.
  448  */
  449 Bool
  450 DisableDevice(DeviceIntPtr dev, BOOL sendevent)
  451 {
  452     DeviceIntPtr *prev, other;
  453     BOOL enabled;
  454     int flags[MAXDEVICES] = { 0 };
  455 
  456     if (!dev->enabled)
  457         return TRUE;
  458 
  459     for (prev = &inputInfo.devices;
  460          *prev && (*prev != dev); prev = &(*prev)->next);
  461     if (*prev != dev)
  462         return FALSE;
  463 
  464     TouchEndPhysicallyActiveTouches(dev);
  465     ReleaseButtonsAndKeys(dev);
  466     SyncRemoveDeviceIdleTime(dev->idle_counter);
  467     dev->idle_counter = NULL;
  468 
  469     /* float attached devices */
  470     if (IsMaster(dev)) {
  471         for (other = inputInfo.devices; other; other = other->next) {
  472             if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) {
  473                 AttachDevice(NULL, other, NULL);
  474                 flags[other->id] |= XISlaveDetached;
  475             }
  476         }
  477     }
  478     else {
  479         for (other = inputInfo.devices; other; other = other->next) {
  480             if (IsMaster(other) && other->lastSlave == dev)
  481                 other->lastSlave = NULL;
  482         }
  483     }
  484 
  485     if (IsMaster(dev) && dev->spriteInfo->sprite) {
  486         for (other = inputInfo.devices; other; other = other->next)
  487             if (other->spriteInfo->paired == dev && !other->spriteInfo->spriteOwner)
  488                 DisableDevice(other, sendevent);
  489     }
  490 
  491     if (dev->spriteInfo->paired)
  492         dev->spriteInfo->paired = NULL;
  493 
  494     input_lock();
  495     (void) (*dev->deviceProc) (dev, DEVICE_OFF);
  496     dev->enabled = FALSE;
  497 
  498     /* now that the device is disabled, we can reset the event reader's
  499      * last.slave */
  500     for (other = inputInfo.devices; other; other = other->next) {
  501         if (other->last.slave == dev)
  502             other->last.slave = NULL;
  503     }
  504     input_unlock();
  505 
  506     FreeSprite(dev);
  507 
  508     LeaveWindow(dev);
  509     SetFocusOut(dev);
  510 
  511     *prev = dev->next;
  512     dev->next = inputInfo.off_devices;
  513     inputInfo.off_devices = dev;
  514 
  515     enabled = FALSE;
  516     XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
  517                            XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE);
  518 
  519     SendDevicePresenceEvent(dev->id, DeviceDisabled);
  520     if (sendevent) {
  521         flags[dev->id] = XIDeviceDisabled;
  522         XISendDeviceHierarchyEvent(flags);
  523     }
  524 
  525     RecalculateMasterButtons(dev);
  526 
  527     return TRUE;
  528 }
  529 
  530 void
  531 DisableAllDevices(void)
  532 {
  533     DeviceIntPtr dev, tmp;
  534 
  535     /* Disable slave devices first, excluding XTest devices */
  536     nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
  537         if (!IsXTestDevice(dev, NULL) && !IsMaster(dev))
  538             DisableDevice(dev, FALSE);
  539     }
  540     /* Disable XTest devices */
  541     nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
  542         if (!IsMaster(dev))
  543             DisableDevice(dev, FALSE);
  544     }
  545     /* master keyboards need to be disabled first */
  546     nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
  547         if (dev->enabled && IsMaster(dev) && IsKeyboardDevice(dev))
  548             DisableDevice(dev, FALSE);
  549     }
  550     nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
  551         if (dev->enabled)
  552             DisableDevice(dev, FALSE);
  553     }
  554 }
  555 
  556 /**
  557  * Initialise a new device through the driver and tell all clients about the
  558  * new device.
  559  *
  560  * Must be called before EnableDevice.
  561  * The device will NOT send events until it is enabled!
  562  *
  563  * @param sendevent True if an XI2 event should be sent.
  564  * @return Success or an error code on failure.
  565  */
  566 int
  567 ActivateDevice(DeviceIntPtr dev, BOOL sendevent)
  568 {
  569     int ret = Success;
  570     ScreenPtr pScreen = screenInfo.screens[0];
  571 
  572     if (!dev || !dev->deviceProc)
  573         return BadImplementation;
  574 
  575     input_lock();
  576     ret = (*dev->deviceProc) (dev, DEVICE_INIT);
  577     input_unlock();
  578     dev->inited = (ret == Success);
  579     if (!dev->inited)
  580         return ret;
  581 
  582     /* Initialize memory for sprites. */
  583     if (IsMaster(dev) && dev->spriteInfo->spriteOwner)
  584         if (!pScreen->DeviceCursorInitialize(dev, pScreen))
  585             ret = BadAlloc;
  586 
  587     SendDevicePresenceEvent(dev->id, DeviceAdded);
  588     if (sendevent) {
  589         int flags[MAXDEVICES] = { 0 };
  590         flags[dev->id] = XISlaveAdded;
  591         XISendDeviceHierarchyEvent(flags);
  592     }
  593     return ret;
  594 }
  595 
  596 /**
  597  * Ring the bell.
  598  * The actual task of ringing the bell is the job of the DDX.
  599  */
  600 static void
  601 CoreKeyboardBell(int volume, DeviceIntPtr pDev, void *arg, int something)
  602 {
  603     KeybdCtrl *ctrl = arg;
  604 
  605     DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
  606 }
  607 
  608 static void
  609 CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl * ctrl)
  610 {
  611     return;
  612 }
  613 
  614 /**
  615  * Device control function for the Virtual Core Keyboard.
  616  */
  617 int
  618 CoreKeyboardProc(DeviceIntPtr pDev, int what)
  619 {
  620 
  621     switch (what) {
  622     case DEVICE_INIT:
  623         if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell,
  624                                       CoreKeyboardCtl)) {
  625             ErrorF("Keyboard initialization failed. This could be a missing "
  626                    "or incorrect setup of xkeyboard-config.\n");
  627             return BadValue;
  628         }
  629         return Success;
  630 
  631     case DEVICE_ON:
  632     case DEVICE_OFF:
  633         return Success;
  634 
  635     case DEVICE_CLOSE:
  636         return Success;
  637     }
  638 
  639     return BadMatch;
  640 }
  641 
  642 /**
  643  * Device control function for the Virtual Core Pointer.
  644  */
  645 int
  646 CorePointerProc(DeviceIntPtr pDev, int what)
  647 {
  648 #define NBUTTONS 10
  649 #define NAXES 2
  650     BYTE map[NBUTTONS + 1];
  651     int i = 0;
  652     Atom btn_labels[NBUTTONS] = { 0 };
  653     Atom axes_labels[NAXES] = { 0 };
  654     ScreenPtr scr = screenInfo.screens[0];
  655 
  656     switch (what) {
  657     case DEVICE_INIT:
  658         for (i = 1; i <= NBUTTONS; i++)
  659             map[i] = i;
  660 
  661         btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
  662         btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
  663         btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
  664         btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
  665         btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
  666         btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
  667         btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
  668         /* don't know about the rest */
  669 
  670         axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
  671         axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
  672 
  673         if (!InitPointerDeviceStruct
  674             ((DevicePtr) pDev, map, NBUTTONS, btn_labels,
  675              (PtrCtrlProcPtr) NoopDDA, GetMotionHistorySize(), NAXES,
  676              axes_labels)) {
  677             ErrorF("Could not initialize device '%s'. Out of memory.\n",
  678                    pDev->name);
  679             return BadAlloc;    /* IPDS only fails on allocs */
  680         }
  681         /* axisVal is per-screen, last.valuators is desktop-wide */
  682         pDev->valuator->axisVal[0] = scr->width / 2;
  683         pDev->last.valuators[0] = pDev->valuator->axisVal[0] + scr->x;
  684         pDev->valuator->axisVal[1] = scr->height / 2;
  685         pDev->last.valuators[1] = pDev->valuator->axisVal[1] + scr->y;
  686         break;
  687 
  688     case DEVICE_CLOSE:
  689         break;
  690 
  691     default:
  692         break;
  693     }
  694 
  695     return Success;
  696 
  697 #undef NBUTTONS
  698 #undef NAXES
  699 }
  700 
  701 /**
  702  * Initialise the two core devices, VCP and VCK (see events.c).
  703  * Both devices are not tied to physical devices, but guarantee that there is
  704  * always a keyboard and a pointer present and keep the protocol semantics.
  705  *
  706  * Note that the server MUST have two core devices at all times, even if there
  707  * is no physical device connected.
  708  */
  709 void
  710 InitCoreDevices(void)
  711 {
  712     int result;
  713 
  714     result = AllocDevicePair(serverClient, "Virtual core",
  715                              &inputInfo.pointer, &inputInfo.keyboard,
  716                              CorePointerProc, CoreKeyboardProc, TRUE);
  717     if (result != Success) {
  718         FatalError("Failed to allocate virtual core devices: %d", result);
  719     }
  720 
  721     result = ActivateDevice(inputInfo.pointer, TRUE);
  722     if (result != Success) {
  723         FatalError("Failed to activate virtual core pointer: %d", result);
  724     }
  725 
  726     result = ActivateDevice(inputInfo.keyboard, TRUE);
  727     if (result != Success) {
  728         FatalError("Failed to activate virtual core keyboard: %d", result);
  729     }
  730 
  731     if (!EnableDevice(inputInfo.pointer, TRUE)) {
  732          FatalError("Failed to enable virtual core pointer.");
  733     }
  734 
  735     if (!EnableDevice(inputInfo.keyboard, TRUE)) {
  736          FatalError("Failed to enable virtual core keyboard.");
  737     }
  738 
  739     InitXTestDevices();
  740 }
  741 
  742 /**
  743  * Activate all switched-off devices and then enable all those devices.
  744  *
  745  * Will return an error if no core keyboard or core pointer is present.
  746  * In theory this should never happen if you call InitCoreDevices() first.
  747  *
  748  * InitAndStartDevices needs to be called AFTER the windows are initialized.
  749  * Devices will start sending events after InitAndStartDevices() has
  750  * completed.
  751  *
  752  * @return Success or error code on failure.
  753  */
  754 int
  755 InitAndStartDevices(void)
  756 {
  757     DeviceIntPtr dev, next;
  758 
  759     for (dev = inputInfo.off_devices; dev; dev = dev->next) {
  760         DebugF("(dix) initialising device %d\n", dev->id);
  761         if (!dev->inited)
  762             ActivateDevice(dev, TRUE);
  763     }
  764 
  765     /* enable real devices */
  766     for (dev = inputInfo.off_devices; dev; dev = next) {
  767         DebugF("(dix) enabling device %d\n", dev->id);
  768         next = dev->next;
  769         if (dev->inited && dev->startup)
  770             EnableDevice(dev, TRUE);
  771     }
  772 
  773     return Success;
  774 }
  775 
  776 /**
  777  * Free the given device class and reset the pointer to NULL.
  778  */
  779 static void
  780 FreeDeviceClass(int type, void **class)
  781 {
  782     if (!(*class))
  783         return;
  784 
  785     switch (type) {
  786     case KeyClass:
  787     {
  788         KeyClassPtr *k = (KeyClassPtr *) class;
  789 
  790         if ((*k)->xkbInfo) {
  791             XkbFreeInfo((*k)->xkbInfo);
  792             (*k)->xkbInfo = NULL;
  793         }
  794         free((*k));
  795         break;
  796     }
  797     case ButtonClass:
  798     {
  799         ButtonClassPtr *b = (ButtonClassPtr *) class;
  800 
  801         free((*b)->xkb_acts);
  802         free((*b));
  803         break;
  804     }
  805     case ValuatorClass:
  806     {
  807         ValuatorClassPtr *v = (ValuatorClassPtr *) class;
  808 
  809         free((*v)->motion);
  810         free((*v));
  811         break;
  812     }
  813     case XITouchClass:
  814     {
  815         TouchClassPtr *t = (TouchClassPtr *) class;
  816         int i;
  817 
  818         for (i = 0; i < (*t)->num_touches; i++) {
  819             free((*t)->touches[i].sprite.spriteTrace);
  820             free((*t)->touches[i].listeners);
  821             free((*t)->touches[i].valuators);
  822         }
  823 
  824         free((*t)->touches);
  825         free((*t));
  826         break;
  827     }
  828     case FocusClass:
  829     {
  830         FocusClassPtr *f = (FocusClassPtr *) class;
  831 
  832         free((*f)->trace);
  833         free((*f));
  834         break;
  835     }
  836     case ProximityClass:
  837     {
  838         ProximityClassPtr *p = (ProximityClassPtr *) class;
  839 
  840         free((*p));
  841         break;
  842     }
  843     }
  844     *class = NULL;
  845 }
  846 
  847 static void
  848 FreeFeedbackClass(int type, void **class)
  849 {
  850     if (!(*class))
  851         return;
  852 
  853     switch (type) {
  854     case KbdFeedbackClass:
  855     {
  856         KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr *) class;
  857         KbdFeedbackPtr k, knext;
  858 
  859         for (k = (*kbdfeed); k; k = knext) {
  860             knext = k->next;
  861             if (k->xkb_sli)
  862                 XkbFreeSrvLedInfo(k->xkb_sli);
  863             free(k);
  864         }
  865         break;
  866     }
  867     case PtrFeedbackClass:
  868     {
  869         PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr *) class;
  870         PtrFeedbackPtr p, pnext;
  871 
  872         for (p = (*ptrfeed); p; p = pnext) {
  873             pnext = p->next;
  874             free(p);
  875         }
  876         break;
  877     }
  878     case IntegerFeedbackClass:
  879     {
  880         IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr *) class;
  881         IntegerFeedbackPtr i, inext;
  882 
  883         for (i = (*intfeed); i; i = inext) {
  884             inext = i->next;
  885             free(i);
  886         }
  887         break;
  888     }
  889     case StringFeedbackClass:
  890     {
  891         StringFeedbackPtr *stringfeed = (StringFeedbackPtr *) class;
  892         StringFeedbackPtr s, snext;
  893 
  894         for (s = (*stringfeed); s; s = snext) {
  895             snext = s->next;
  896             free(s->ctrl.symbols_supported);
  897             free(s->ctrl.symbols_displayed);
  898             free(s);
  899         }
  900         break;
  901     }
  902     case BellFeedbackClass:
  903     {
  904         BellFeedbackPtr *bell = (BellFeedbackPtr *) class;
  905         BellFeedbackPtr b, bnext;
  906 
  907         for (b = (*bell); b; b = bnext) {
  908             bnext = b->next;
  909             free(b);
  910         }
  911         break;
  912     }
  913     case LedFeedbackClass:
  914     {
  915         LedFeedbackPtr *leds = (LedFeedbackPtr *) class;
  916         LedFeedbackPtr l, lnext;
  917 
  918         for (l = (*leds); l; l = lnext) {
  919             lnext = l->next;
  920             if (l->xkb_sli)
  921                 XkbFreeSrvLedInfo(l->xkb_sli);
  922             free(l);
  923         }
  924         break;
  925     }
  926     }
  927     *class = NULL;
  928 }
  929 
  930 static void
  931 FreeAllDeviceClasses(ClassesPtr classes)
  932 {
  933     if (!classes)
  934         return;
  935 
  936     FreeDeviceClass(KeyClass, (void *) &classes->key);
  937     FreeDeviceClass(ValuatorClass, (void *) &classes->valuator);
  938     FreeDeviceClass(XITouchClass, (void *) &classes->touch);
  939     FreeDeviceClass(ButtonClass, (void *) &classes->button);
  940     FreeDeviceClass(FocusClass, (void *) &classes->focus);
  941     FreeDeviceClass(ProximityClass, (void *) &classes->proximity);
  942 
  943     FreeFeedbackClass(KbdFeedbackClass, (void *) &classes->kbdfeed);
  944     FreeFeedbackClass(PtrFeedbackClass, (void *) &classes->ptrfeed);
  945     FreeFeedbackClass(IntegerFeedbackClass, (void *) &classes->intfeed);
  946     FreeFeedbackClass(StringFeedbackClass, (void *) &classes->stringfeed);
  947     FreeFeedbackClass(BellFeedbackClass, (void *) &classes->bell);
  948     FreeFeedbackClass(LedFeedbackClass, (void *) &classes->leds);
  949 
  950 }
  951 
  952 /**
  953  * Close down a device and free all resources.
  954  * Once closed down, the driver will probably not expect you that you'll ever
  955  * enable it again and free associated structs. If you want the device to just
  956  * be disabled, DisableDevice().
  957  * Don't call this function directly, use RemoveDevice() instead.
  958  *
  959  * Called with input lock held.
  960  */
  961 static void
  962 CloseDevice(DeviceIntPtr dev)
  963 {
  964     ScreenPtr screen = screenInfo.screens[0];
  965     ClassesPtr classes;
  966     int j;
  967 
  968     if (!dev)
  969         return;
  970 
  971     XIDeleteAllDeviceProperties(dev);
  972 
  973     if (dev->inited)
  974         (void) (*dev->deviceProc) (dev, DEVICE_CLOSE);
  975 
  976     FreeSprite(dev);
  977 
  978     if (IsMaster(dev))
  979         screen->DeviceCursorCleanup(dev, screen);
  980 
  981     /* free acceleration info */
  982     if (dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
  983         dev->valuator->accelScheme.AccelCleanupProc(dev);
  984 
  985     while (dev->xkb_interest)
  986         XkbRemoveResourceClient((DevicePtr) dev, dev->xkb_interest->resource);
  987 
  988     free(dev->name);
  989 
  990     classes = (ClassesPtr) &dev->key;
  991     FreeAllDeviceClasses(classes);
  992 
  993     if (IsMaster(dev)) {
  994         classes = dev->unused_classes;
  995         FreeAllDeviceClasses(classes);
  996         free(classes);
  997     }
  998 
  999     /* a client may have the device set as client pointer */
 1000     for (j = 0; j < currentMaxClients; j++) {
 1001         if (clients[j] && clients[j]->clientPtr == dev) {
 1002             clients[j]->clientPtr = NULL;
 1003             clients[j]->clientPtr = PickPointer(clients[j]);
 1004         }
 1005     }
 1006 
 1007     if (dev->deviceGrab.grab)
 1008         FreeGrab(dev->deviceGrab.grab);
 1009     free(dev->deviceGrab.sync.event);
 1010     free(dev->config_info);     /* Allocated in xf86ActivateDevice. */
 1011     free(dev->last.scroll);
 1012     for (j = 0; j < dev->last.num_touches; j++)
 1013         free(dev->last.touches[j].valuators);
 1014     free(dev->last.touches);
 1015     dev->config_info = NULL;
 1016     dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE);
 1017     free(dev);
 1018 }
 1019 
 1020 /**
 1021  * Shut down all devices of one list and free all resources.
 1022  */
 1023 static
 1024     void
 1025 CloseDeviceList(DeviceIntPtr *listHead)
 1026 {
 1027     /* Used to mark devices that we tried to free */
 1028     Bool freedIds[MAXDEVICES];
 1029     DeviceIntPtr dev;
 1030     int i;
 1031 
 1032     if (listHead == NULL)
 1033         return;
 1034 
 1035     for (i = 0; i < MAXDEVICES; i++)
 1036         freedIds[i] = FALSE;
 1037 
 1038     dev = *listHead;
 1039     while (dev != NULL) {
 1040         freedIds[dev->id] = TRUE;
 1041         DeleteInputDeviceRequest(dev);
 1042 
 1043         dev = *listHead;
 1044         while (dev != NULL && freedIds[dev->id])
 1045             dev = dev->next;
 1046     }
 1047 }
 1048 
 1049 /**
 1050  * Shut down all devices, free all resources, etc.
 1051  * Only useful if you're shutting down the server!
 1052  */
 1053 void
 1054 CloseDownDevices(void)
 1055 {
 1056     DeviceIntPtr dev;
 1057 
 1058     input_lock();
 1059 
 1060     /* Float all SDs before closing them. Note that at this point resources
 1061      * (e.g. cursors) have been freed already, so we can't just call
 1062      * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
 1063      * to NULL and pretend nothing happened.
 1064      */
 1065     for (dev = inputInfo.devices; dev; dev = dev->next) {
 1066         if (!IsMaster(dev) && !IsFloating(dev))
 1067             dev->master = NULL;
 1068     }
 1069 
 1070     CloseDeviceList(&inputInfo.devices);
 1071     CloseDeviceList(&inputInfo.off_devices);
 1072 
 1073     CloseDevice(inputInfo.pointer);
 1074 
 1075     CloseDevice(inputInfo.keyboard);
 1076 
 1077     inputInfo.devices = NULL;
 1078     inputInfo.off_devices = NULL;
 1079     inputInfo.keyboard = NULL;
 1080     inputInfo.pointer = NULL;
 1081 
 1082     XkbDeleteRulesDflts();
 1083     XkbDeleteRulesUsed();
 1084 
 1085     input_unlock();
 1086 }
 1087 
 1088 /**
 1089  * Signal all devices that we're in the process of aborting.
 1090  * This function is called from a signal handler.
 1091  */
 1092 void
 1093 AbortDevices(void)
 1094 {
 1095     DeviceIntPtr dev;
 1096 
 1097     /* Do not call input_lock as we don't know what
 1098      * state the input thread might be in, and that could
 1099      * cause a dead-lock.
 1100      */
 1101     nt_list_for_each_entry(dev, inputInfo.devices, next) {
 1102         if (!IsMaster(dev))
 1103             (*dev->deviceProc) (dev, DEVICE_ABORT);
 1104     }
 1105 
 1106     nt_list_for_each_entry(dev, inputInfo.off_devices, next) {
 1107         if (!IsMaster(dev))
 1108             (*dev->deviceProc) (dev, DEVICE_ABORT);
 1109     }
 1110 }
 1111 
 1112 /**
 1113  * Remove the cursor sprite for all devices. This needs to be done before any
 1114  * resources are freed or any device is deleted.
 1115  */
 1116 void
 1117 UndisplayDevices(void)
 1118 {
 1119     DeviceIntPtr dev;
 1120     ScreenPtr screen = screenInfo.screens[0];
 1121 
 1122     for (dev = inputInfo.devices; dev; dev = dev->next)
 1123         screen->DisplayCursor(dev, screen, NullCursor);
 1124 }
 1125 
 1126 /**
 1127  * Remove a device from the device list, closes it and thus frees all
 1128  * resources.
 1129  * Removes both enabled and disabled devices and notifies all devices about
 1130  * the removal of the device.
 1131  *
 1132  * No PresenceNotify is sent for device that the client never saw. This can
 1133  * happen if a malloc fails during the addition of master devices. If
 1134  * dev->init is FALSE it means the client never received a DeviceAdded event,
 1135  * so let's not send a DeviceRemoved event either.
 1136  *
 1137  * @param sendevent True if an XI2 event should be sent.
 1138  */
 1139 int
 1140 RemoveDevice(DeviceIntPtr dev, BOOL sendevent)
 1141 {
 1142     DeviceIntPtr prev, tmp, next;
 1143     int ret = BadMatch;
 1144     ScreenPtr screen = screenInfo.screens[0];
 1145     int deviceid;
 1146     int initialized;
 1147     int flags[MAXDEVICES] = { 0 };
 1148 
 1149     DebugF("(dix) removing device %d\n", dev->id);
 1150 
 1151     if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
 1152         return BadImplementation;
 1153 
 1154     initialized = dev->inited;
 1155     deviceid = dev->id;
 1156 
 1157     if (initialized) {
 1158         if (DevHasCursor(dev))
 1159             screen->DisplayCursor(dev, screen, NullCursor);
 1160 
 1161         DisableDevice(dev, sendevent);
 1162         flags[dev->id] = XIDeviceDisabled;
 1163     }
 1164 
 1165     input_lock();
 1166 
 1167     prev = NULL;
 1168     for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
 1169         next = tmp->next;
 1170         if (tmp == dev) {
 1171 
 1172             if (prev == NULL)
 1173                 inputInfo.devices = next;
 1174             else
 1175                 prev->next = next;
 1176 
 1177             flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
 1178             CloseDevice(tmp);
 1179             ret = Success;
 1180             break;
 1181         }
 1182     }
 1183 
 1184     prev = NULL;
 1185     for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
 1186         next = tmp->next;
 1187         if (tmp == dev) {
 1188             flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
 1189             CloseDevice(tmp);
 1190 
 1191             if (prev == NULL)
 1192                 inputInfo.off_devices = next;
 1193             else
 1194                 prev->next = next;
 1195 
 1196             ret = Success;
 1197             break;
 1198         }
 1199     }
 1200 
 1201     input_unlock();
 1202 
 1203     if (ret == Success && initialized) {
 1204         inputInfo.numDevices--;
 1205         SendDevicePresenceEvent(deviceid, DeviceRemoved);
 1206         if (sendevent)
 1207             XISendDeviceHierarchyEvent(flags);
 1208     }
 1209 
 1210     return ret;
 1211 }
 1212 
 1213 int
 1214 NumMotionEvents(void)
 1215 {
 1216     /* only called to fill data in initial connection reply.
 1217      * VCP is ok here, it is the only fixed device we have. */
 1218     return inputInfo.pointer->valuator->numMotionEvents;
 1219 }
 1220 
 1221 int
 1222 dixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode)
 1223 {
 1224     DeviceIntPtr dev;
 1225     int rc;
 1226 
 1227     *pDev = NULL;
 1228 
 1229     for (dev = inputInfo.devices; dev; dev = dev->next) {
 1230         if (dev->id == id)
 1231             goto found;
 1232     }
 1233     for (dev = inputInfo.off_devices; dev; dev = dev->next) {
 1234         if (dev->id == id)
 1235             goto found;
 1236     }
 1237     return BadDevice;
 1238 
 1239  found:
 1240     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
 1241     if (rc == Success)
 1242         *pDev = dev;
 1243     return rc;
 1244 }
 1245 
 1246 void
 1247 QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
 1248 {
 1249     if (inputInfo.keyboard) {
 1250         *minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code;
 1251         *maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code;
 1252     }
 1253 }
 1254 
 1255 Bool
 1256 InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom *labels,
 1257                             CARD8 *map)
 1258 {
 1259     ButtonClassPtr butc;
 1260     int i;
 1261 
 1262     BUG_RETURN_VAL(dev == NULL, FALSE);
 1263     BUG_RETURN_VAL(dev->button != NULL, FALSE);
 1264     BUG_RETURN_VAL(numButtons >= MAX_BUTTONS, FALSE);
 1265 
 1266     butc = calloc(1, sizeof(ButtonClassRec));
 1267     if (!butc)
 1268         return FALSE;
 1269     butc->numButtons = numButtons;
 1270     butc->sourceid = dev->id;
 1271     for (i = 1; i <= numButtons; i++)
 1272         butc->map[i] = map[i];
 1273     for (i = numButtons + 1; i < MAP_LENGTH; i++)
 1274         butc->map[i] = i;
 1275     memcpy(butc->labels, labels, numButtons * sizeof(Atom));
 1276     dev->button = butc;
 1277     return TRUE;
 1278 }
 1279 
 1280 /**
 1281  * Allocate a valuator class and set up the pointers for the axis values
 1282  * appropriately.
 1283  *
 1284  * @param src If non-NULL, the memory is reallocated from src. If NULL, the
 1285  * memory is calloc'd.
 1286  * @parma numAxes Number of axes to allocate.
 1287  * @return The allocated valuator struct.
 1288  */
 1289 ValuatorClassPtr
 1290 AllocValuatorClass(ValuatorClassPtr src, int numAxes)
 1291 {
 1292     ValuatorClassPtr v;
 1293 
 1294     /* force alignment with double */
 1295     union align_u {
 1296         ValuatorClassRec valc;
 1297         double d;
 1298     } *align;
 1299     int size;
 1300 
 1301     size =
 1302         sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
 1303     align = (union align_u *) realloc(src, size);
 1304 
 1305     if (!align)
 1306         return NULL;
 1307 
 1308     if (!src)
 1309         memset(align, 0, size);
 1310 
 1311     v = &align->valc;
 1312     v->numAxes = numAxes;
 1313     v->axisVal = (double *) (align + 1);
 1314     v->axes = (AxisInfoPtr) (v->axisVal + numAxes);
 1315 
 1316     return v;
 1317 }
 1318 
 1319 Bool
 1320 InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
 1321                               int numMotionEvents, int mode)
 1322 {
 1323     int i;
 1324     ValuatorClassPtr valc;
 1325 
 1326     BUG_RETURN_VAL(dev == NULL, FALSE);
 1327 
 1328     if (numAxes > MAX_VALUATORS) {
 1329         LogMessage(X_WARNING,
 1330                    "Device '%s' has %d axes, only using first %d.\n",
 1331                    dev->name, numAxes, MAX_VALUATORS);
 1332         numAxes = MAX_VALUATORS;
 1333     }
 1334 
 1335     valc = AllocValuatorClass(NULL, numAxes);
 1336     if (!valc)
 1337         return FALSE;
 1338 
 1339     dev->last.scroll = valuator_mask_new(numAxes);
 1340     if (!dev->last.scroll) {
 1341         free(valc);
 1342         return FALSE;
 1343     }
 1344 
 1345     valc->sourceid = dev->id;
 1346     valc->motion = NULL;
 1347     valc->first_motion = 0;
 1348     valc->last_motion = 0;
 1349     valc->h_scroll_axis = -1;
 1350     valc->v_scroll_axis = -1;
 1351 
 1352     valc->numMotionEvents = numMotionEvents;
 1353     valc->motionHintWindow = NullWindow;
 1354 
 1355     if ((mode & OutOfProximity) && !dev->proximity)
 1356         InitProximityClassDeviceStruct(dev);
 1357 
 1358     dev->valuator = valc;
 1359 
 1360     AllocateMotionHistory(dev);
 1361 
 1362     for (i = 0; i < numAxes; i++) {
 1363         InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS,
 1364                                NO_AXIS_LIMITS, 0, 0, 0, mode);
 1365         valc->axisVal[i] = 0;
 1366     }
 1367 
 1368     dev->last.numValuators = numAxes;
 1369 
 1370     if (IsMaster(dev) ||        /* do not accelerate master or xtest devices */
 1371         IsXTestDevice(dev, NULL))
 1372         InitPointerAccelerationScheme(dev, PtrAccelNoOp);
 1373     else
 1374         InitPointerAccelerationScheme(dev, PtrAccelDefault);
 1375     return TRUE;
 1376 }
 1377 
 1378 /* global list of acceleration schemes */
 1379 ValuatorAccelerationRec pointerAccelerationScheme[] = {
 1380     {PtrAccelNoOp, NULL, NULL, NULL, NULL},
 1381     {PtrAccelPredictable, acceleratePointerPredictable, NULL,
 1382      InitPredictableAccelerationScheme, AccelerationDefaultCleanup},
 1383     {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL, NULL},
 1384     {-1, NULL, NULL, NULL, NULL}        /* terminator */
 1385 };
 1386 
 1387 /**
 1388  * install an acceleration scheme. returns TRUE on success, and should not
 1389  * change anything if unsuccessful.
 1390  */
 1391 Bool
 1392 InitPointerAccelerationScheme(DeviceIntPtr dev, int scheme)
 1393 {
 1394     int x, i = -1;
 1395     ValuatorClassPtr val;
 1396 
 1397     val = dev->valuator;
 1398 
 1399     if (!val)
 1400         return FALSE;
 1401 
 1402     if (IsMaster(dev) && scheme != PtrAccelNoOp)
 1403         return FALSE;
 1404 
 1405     for (x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
 1406         if (pointerAccelerationScheme[x].number == scheme) {
 1407             i = x;
 1408             break;
 1409         }
 1410     }
 1411 
 1412     if (-1 == i)
 1413         return FALSE;
 1414 
 1415     if (val->accelScheme.AccelCleanupProc)
 1416         val->accelScheme.AccelCleanupProc(dev);
 1417 
 1418     if (pointerAccelerationScheme[i].AccelInitProc) {
 1419         if (!pointerAccelerationScheme[i].AccelInitProc(dev,
 1420                                             &pointerAccelerationScheme[i])) {
 1421             return FALSE;
 1422         }
 1423     }
 1424     else {
 1425         val->accelScheme = pointerAccelerationScheme[i];
 1426     }
 1427     return TRUE;
 1428 }
 1429 
 1430 Bool
 1431 InitFocusClassDeviceStruct(DeviceIntPtr dev)
 1432 {
 1433     FocusClassPtr focc;
 1434 
 1435     BUG_RETURN_VAL(dev == NULL, FALSE);
 1436     BUG_RETURN_VAL(dev->focus != NULL, FALSE);
 1437 
 1438     focc = malloc(sizeof(FocusClassRec));
 1439     if (!focc)
 1440         return FALSE;
 1441     UpdateCurrentTimeIf();
 1442     focc->win = PointerRootWin;
 1443     focc->revert = None;
 1444     focc->time = currentTime;
 1445     focc->trace = (WindowPtr *) NULL;
 1446     focc->traceSize = 0;
 1447     focc->traceGood = 0;
 1448     focc->sourceid = dev->id;
 1449     dev->focus = focc;
 1450     return TRUE;
 1451 }
 1452 
 1453 Bool
 1454 InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
 1455 {
 1456     PtrFeedbackPtr feedc;
 1457 
 1458     BUG_RETURN_VAL(dev == NULL, FALSE);
 1459 
 1460     feedc = malloc(sizeof(PtrFeedbackClassRec));
 1461     if (!feedc)
 1462         return FALSE;
 1463     feedc->CtrlProc = controlProc;
 1464     feedc->ctrl = defaultPointerControl;
 1465     feedc->ctrl.id = 0;
 1466     if ((feedc->next = dev->ptrfeed))
 1467         feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
 1468     dev->ptrfeed = feedc;
 1469     (*controlProc) (dev, &feedc->ctrl);
 1470     return TRUE;
 1471 }
 1472 
 1473 static LedCtrl defaultLedControl = {
 1474     DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0
 1475 };
 1476 
 1477 static BellCtrl defaultBellControl = {
 1478     DEFAULT_BELL,
 1479     DEFAULT_BELL_PITCH,
 1480     DEFAULT_BELL_DURATION,
 1481     0
 1482 };
 1483 
 1484 static IntegerCtrl defaultIntegerControl = {
 1485     DEFAULT_INT_RESOLUTION,
 1486     DEFAULT_INT_MIN_VALUE,
 1487     DEFAULT_INT_MAX_VALUE,
 1488     DEFAULT_INT_DISPLAYED,
 1489     0
 1490 };
 1491 
 1492 Bool
 1493 InitStringFeedbackClassDeviceStruct(DeviceIntPtr dev,
 1494                                     StringCtrlProcPtr controlProc,
 1495                                     int max_symbols, int num_symbols_supported,
 1496                                     KeySym * symbols)
 1497 {
 1498     int i;
 1499     StringFeedbackPtr feedc;
 1500 
 1501     BUG_RETURN_VAL(dev == NULL, FALSE);
 1502 
 1503     feedc = malloc(sizeof(StringFeedbackClassRec));
 1504     if (!feedc)
 1505         return FALSE;
 1506     feedc->CtrlProc = controlProc;
 1507     feedc->ctrl.num_symbols_supported = num_symbols_supported;
 1508     feedc->ctrl.num_symbols_displayed = 0;
 1509     feedc->ctrl.max_symbols = max_symbols;
 1510     feedc->ctrl.symbols_supported =
 1511         xallocarray(num_symbols_supported, sizeof(KeySym));
 1512     feedc->ctrl.symbols_displayed = xallocarray(max_symbols, sizeof(KeySym));
 1513     if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) {
 1514         free(feedc->ctrl.symbols_supported);
 1515         free(feedc->ctrl.symbols_displayed);
 1516         free(feedc);
 1517         return FALSE;
 1518     }
 1519     for (i = 0; i < num_symbols_supported; i++)
 1520         *(feedc->ctrl.symbols_supported + i) = *symbols++;
 1521     for (i = 0; i < max_symbols; i++)
 1522         *(feedc->ctrl.symbols_displayed + i) = (KeySym) 0;
 1523     feedc->ctrl.id = 0;
 1524     if ((feedc->next = dev->stringfeed))
 1525         feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
 1526     dev->stringfeed = feedc;
 1527     (*controlProc) (dev, &feedc->ctrl);
 1528     return TRUE;
 1529 }
 1530 
 1531 Bool
 1532 InitBellFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc,
 1533                                   BellCtrlProcPtr controlProc)
 1534 {
 1535     BellFeedbackPtr feedc;
 1536 
 1537     BUG_RETURN_VAL(dev == NULL, FALSE);
 1538 
 1539     feedc = malloc(sizeof(BellFeedbackClassRec));
 1540     if (!feedc)
 1541         return FALSE;
 1542     feedc->CtrlProc = controlProc;
 1543     feedc->BellProc = bellProc;
 1544     feedc->ctrl = defaultBellControl;
 1545     feedc->ctrl.id = 0;
 1546     if ((feedc->next = dev->bell))
 1547         feedc->ctrl.id = dev->bell->ctrl.id + 1;
 1548     dev->bell = feedc;
 1549     (*controlProc) (dev, &feedc->ctrl);
 1550     return TRUE;
 1551 }
 1552 
 1553 Bool
 1554 InitLedFeedbackClassDeviceStruct(DeviceIntPtr dev, LedCtrlProcPtr controlProc)
 1555 {
 1556     LedFeedbackPtr feedc;
 1557 
 1558     BUG_RETURN_VAL(dev == NULL, FALSE);
 1559 
 1560     feedc = malloc(sizeof(LedFeedbackClassRec));
 1561     if (!feedc)
 1562         return FALSE;
 1563     feedc->CtrlProc = controlProc;
 1564     feedc->ctrl = defaultLedControl;
 1565     feedc->ctrl.id = 0;
 1566     if ((feedc->next = dev->leds))
 1567         feedc->ctrl.id = dev->leds->ctrl.id + 1;
 1568     feedc->xkb_sli = NULL;
 1569     dev->leds = feedc;
 1570     (*controlProc) (dev, &feedc->ctrl);
 1571     return TRUE;
 1572 }
 1573 
 1574 Bool
 1575 InitIntegerFeedbackClassDeviceStruct(DeviceIntPtr dev,
 1576                                      IntegerCtrlProcPtr controlProc)
 1577 {
 1578     IntegerFeedbackPtr feedc;
 1579 
 1580     BUG_RETURN_VAL(dev == NULL, FALSE);
 1581 
 1582     feedc = malloc(sizeof(IntegerFeedbackClassRec));
 1583     if (!feedc)
 1584         return FALSE;
 1585     feedc->CtrlProc = controlProc;
 1586     feedc->ctrl = defaultIntegerControl;
 1587     feedc->ctrl.id = 0;
 1588     if ((feedc->next = dev->intfeed))
 1589         feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
 1590     dev->intfeed = feedc;
 1591     (*controlProc) (dev, &feedc->ctrl);
 1592     return TRUE;
 1593 }
 1594 
 1595 Bool
 1596 InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
 1597                         Atom *btn_labels, PtrCtrlProcPtr controlProc,
 1598                         int numMotionEvents, int numAxes, Atom *axes_labels)
 1599 {
 1600     DeviceIntPtr dev = (DeviceIntPtr) device;
 1601 
 1602     BUG_RETURN_VAL(dev == NULL, FALSE);
 1603     BUG_RETURN_VAL(dev->button != NULL, FALSE);
 1604     BUG_RETURN_VAL(dev->valuator != NULL, FALSE);
 1605     BUG_RETURN_VAL(dev->ptrfeed != NULL, FALSE);
 1606 
 1607     return (InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
 1608             InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
 1609                                           numMotionEvents, Relative) &&
 1610             InitPtrFeedbackClassDeviceStruct(dev, controlProc));
 1611 }
 1612 
 1613 /**
 1614  * Sets up multitouch capabilities on @device.
 1615  *
 1616  * @max_touches The maximum number of simultaneous touches, or 0 for unlimited.
 1617  * @mode The mode of the touch device (XIDirectTouch or XIDependentTouch).
 1618  * @num_axes The number of touch valuator axes.
 1619  */
 1620 Bool
 1621 InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
 1622                            unsigned int mode, unsigned int num_axes)
 1623 {
 1624     TouchClassPtr touch;
 1625     int i;
 1626 
 1627     BUG_RETURN_VAL(device == NULL, FALSE);
 1628     BUG_RETURN_VAL(device->touch != NULL, FALSE);
 1629     BUG_RETURN_VAL(device->valuator == NULL, FALSE);
 1630 
 1631     /* Check the mode is valid, and at least X and Y axes. */
 1632     BUG_RETURN_VAL(mode != XIDirectTouch && mode != XIDependentTouch, FALSE);
 1633     BUG_RETURN_VAL(num_axes < 2, FALSE);
 1634 
 1635     if (num_axes > MAX_VALUATORS) {
 1636         LogMessage(X_WARNING,
 1637                    "Device '%s' has %d touch axes, only using first %d.\n",
 1638                    device->name, num_axes, MAX_VALUATORS);
 1639         num_axes = MAX_VALUATORS;
 1640     }
 1641 
 1642     touch = calloc(1, sizeof(*touch));
 1643     if (!touch)
 1644         return FALSE;
 1645 
 1646     touch->max_touches = max_touches;
 1647     if (max_touches == 0)
 1648         max_touches = 5;        /* arbitrary number plucked out of the air */
 1649     touch->touches = calloc(max_touches, sizeof(*touch->touches));
 1650     if (!touch->touches)
 1651         goto err;
 1652     touch->num_touches = max_touches;
 1653     for (i = 0; i < max_touches; i++)
 1654         TouchInitTouchPoint(touch, device->valuator, i);
 1655 
 1656     touch->mode = mode;
 1657     touch->sourceid = device->id;
 1658 
 1659     device->touch = touch;
 1660     device->last.touches = calloc(max_touches, sizeof(*device->last.touches));
 1661     device->last.num_touches = touch->num_touches;
 1662     for (i = 0; i < touch->num_touches; i++)
 1663         TouchInitDDXTouchPoint(device, &device->last.touches[i]);
 1664 
 1665     return TRUE;
 1666 
 1667  err:
 1668     for (i = 0; i < touch->num_touches; i++)
 1669         TouchFreeTouchPoint(device, i);
 1670 
 1671     free(touch->touches);
 1672     free(touch);
 1673 
 1674     return FALSE;
 1675 }
 1676 
 1677 /*
 1678  * Check if the given buffer contains elements between low (inclusive) and
 1679  * high (inclusive) only.
 1680  *
 1681  * @return TRUE if the device map is invalid, FALSE otherwise.
 1682  */
 1683 Bool
 1684 BadDeviceMap(BYTE * buff, int length, unsigned low, unsigned high, XID *errval)
 1685 {
 1686     int i;
 1687 
 1688     for (i = 0; i < length; i++)
 1689         if (buff[i]) {          /* only check non-zero elements */
 1690             if ((low > buff[i]) || (high < buff[i])) {
 1691                 *errval = buff[i];
 1692                 return TRUE;
 1693             }
 1694         }
 1695     return FALSE;
 1696 }
 1697 
 1698 int
 1699 ProcSetModifierMapping(ClientPtr client)
 1700 {
 1701     xSetModifierMappingReply rep;
 1702     int rc;
 1703 
 1704     REQUEST(xSetModifierMappingReq);
 1705     REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
 1706 
 1707     if (client->req_len != ((stuff->numKeyPerModifier << 1) +
 1708                             bytes_to_int32(sizeof(xSetModifierMappingReq))))
 1709         return BadLength;
 1710 
 1711     rep = (xSetModifierMappingReply) {
 1712         .type = X_Reply,
 1713         .sequenceNumber = client->sequence,
 1714         .length = 0
 1715     };
 1716 
 1717     rc = change_modmap(client, PickKeyboard(client), (KeyCode *) &stuff[1],
 1718                        stuff->numKeyPerModifier);
 1719     if (rc == MappingFailed || rc == -1)
 1720         return BadValue;
 1721     if (rc != MappingSuccess && rc != MappingFailed && rc != MappingBusy)
 1722         return rc;
 1723 
 1724     rep.success = rc;
 1725 
 1726     WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
 1727     return Success;
 1728 }
 1729 
 1730 int
 1731 ProcGetModifierMapping(ClientPtr client)
 1732 {
 1733     xGetModifierMappingReply rep;
 1734     int max_keys_per_mod = 0;
 1735     KeyCode *modkeymap = NULL;
 1736 
 1737     REQUEST_SIZE_MATCH(xReq);
 1738 
 1739     generate_modkeymap(client, PickKeyboard(client), &modkeymap,
 1740                        &max_keys_per_mod);
 1741 
 1742     rep = (xGetModifierMappingReply) {
 1743         .type = X_Reply,
 1744         .numKeyPerModifier = max_keys_per_mod,
 1745         .sequenceNumber = client->sequence,
 1746     /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */
 1747         .length = max_keys_per_mod << 1
 1748     };
 1749 
 1750     WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
 1751     WriteToClient(client, max_keys_per_mod * 8, modkeymap);
 1752 
 1753     free(modkeymap);
 1754 
 1755     return Success;
 1756 }
 1757 
 1758 int
 1759 ProcChangeKeyboardMapping(ClientPtr client)
 1760 {
 1761     REQUEST(xChangeKeyboardMappingReq);
 1762     unsigned len;
 1763     KeySymsRec keysyms;
 1764     DeviceIntPtr pDev, tmp;
 1765     int rc;
 1766 
 1767     REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
 1768 
 1769     len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq));
 1770     if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
 1771         return BadLength;
 1772 
 1773     pDev = PickKeyboard(client);
 1774 
 1775     if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) ||
 1776         (stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) {
 1777         client->errorValue = stuff->firstKeyCode;
 1778         return BadValue;
 1779 
 1780     }
 1781     if (((unsigned) (stuff->firstKeyCode + stuff->keyCodes - 1) >
 1782          pDev->key->xkbInfo->desc->max_key_code) ||
 1783         (stuff->keySymsPerKeyCode == 0)) {
 1784         client->errorValue = stuff->keySymsPerKeyCode;
 1785         return BadValue;
 1786     }
 1787 
 1788     keysyms.minKeyCode = stuff->firstKeyCode;
 1789     keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
 1790     keysyms.mapWidth = stuff->keySymsPerKeyCode;
 1791     keysyms.map = (KeySym *) &stuff[1];
 1792 
 1793     rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
 1794     if (rc != Success)
 1795         return rc;
 1796 
 1797     XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode,
 1798                           stuff->keyCodes, NULL, client);
 1799 
 1800     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
 1801         if (IsMaster(tmp) || GetMaster(tmp, MASTER_KEYBOARD) != pDev)
 1802             continue;
 1803         if (!tmp->key)
 1804             continue;
 1805 
 1806         rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
 1807         if (rc != Success)
 1808             continue;
 1809 
 1810         XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode,
 1811                               stuff->keyCodes, NULL, client);
 1812     }
 1813 
 1814     return Success;
 1815 }
 1816 
 1817 int
 1818 ProcSetPointerMapping(ClientPtr client)
 1819 {
 1820     BYTE *map;
 1821     int ret;
 1822     int i, j;
 1823     DeviceIntPtr ptr = PickPointer(client);
 1824     xSetPointerMappingReply rep;
 1825 
 1826     REQUEST(xSetPointerMappingReq);
 1827     REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
 1828 
 1829     if (client->req_len !=
 1830         bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts))
 1831         return BadLength;
 1832 
 1833     rep = (xSetPointerMappingReply) {
 1834         .type = X_Reply,
 1835         .success = MappingSuccess,
 1836         .sequenceNumber = client->sequence,
 1837         .length = 0
 1838     };
 1839     map = (BYTE *) &stuff[1];
 1840 
 1841     /* So we're bounded here by the number of core buttons.  This check
 1842      * probably wants disabling through XFixes. */
 1843     /* MPX: With ClientPointer, we can return the right number of buttons.
 1844      * Let's just hope nobody changed ClientPointer between GetPointerMapping
 1845      * and SetPointerMapping
 1846      */
 1847     if (stuff->nElts != ptr->button->numButtons) {
 1848         client->errorValue = stuff->nElts;
 1849         return BadValue;
 1850     }
 1851 
 1852     /* Core protocol specs don't allow for duplicate mappings; this check
 1853      * almost certainly wants disabling through XFixes too. */
 1854     for (i = 0; i < stuff->nElts; i++) {
 1855         for (j = i + 1; j < stuff->nElts; j++) {
 1856             if (map[i] && map[i] == map[j]) {
 1857                 client->errorValue = map[i];
 1858                 return BadValue;
 1859             }
 1860         }
 1861     }
 1862 
 1863     ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
 1864     if (ret == MappingBusy)
 1865         rep.success = ret;
 1866     else if (ret == -1)
 1867         return BadValue;
 1868     else if (ret != Success)
 1869         return ret;
 1870 
 1871     WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
 1872     return Success;
 1873 }
 1874 
 1875 int
 1876 ProcGetKeyboardMapping(ClientPtr client)
 1877 {
 1878     xGetKeyboardMappingReply rep;
 1879     DeviceIntPtr kbd = PickKeyboard(client);
 1880     XkbDescPtr xkb;
 1881     KeySymsPtr syms;
 1882     int rc;
 1883 
 1884     REQUEST(xGetKeyboardMappingReq);
 1885     REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
 1886 
 1887     rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
 1888     if (rc != Success)
 1889         return rc;
 1890 
 1891     xkb = kbd->key->xkbInfo->desc;
 1892 
 1893     if ((stuff->firstKeyCode < xkb->min_key_code) ||
 1894         (stuff->firstKeyCode > xkb->max_key_code)) {
 1895         client->errorValue = stuff->firstKeyCode;
 1896         return BadValue;
 1897     }
 1898     if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) {
 1899         client->errorValue = stuff->count;
 1900         return BadValue;
 1901     }
 1902 
 1903     syms = XkbGetCoreMap(kbd);
 1904     if (!syms)
 1905         return BadAlloc;
 1906 
 1907     rep = (xGetKeyboardMappingReply) {
 1908         .type = X_Reply,
 1909         .keySymsPerKeyCode = syms->mapWidth,
 1910         .sequenceNumber = client->sequence,
 1911         /* length is a count of 4 byte quantities and KeySyms are 4 bytes */
 1912         .length = syms->mapWidth * stuff->count
 1913     };
 1914     WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
 1915     client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
 1916     WriteSwappedDataToClient(client,
 1917                              syms->mapWidth * stuff->count * sizeof(KeySym),
 1918                              &syms->map[syms->mapWidth * (stuff->firstKeyCode -
 1919                                                           syms->minKeyCode)]);
 1920     free(syms->map);
 1921     free(syms);
 1922 
 1923     return Success;
 1924 }
 1925 
 1926 int
 1927 ProcGetPointerMapping(ClientPtr client)
 1928 {
 1929     xGetPointerMappingReply rep;
 1930 
 1931     /* Apps may get different values each time they call GetPointerMapping as
 1932      * the ClientPointer could change. */
 1933     DeviceIntPtr ptr = PickPointer(client);
 1934     ButtonClassPtr butc = ptr->button;
 1935     int nElts;
 1936     int rc;
 1937 
 1938     REQUEST_SIZE_MATCH(xReq);
 1939 
 1940     rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
 1941     if (rc != Success)
 1942         return rc;
 1943 
 1944     nElts = (butc) ? butc->numButtons : 0;
 1945     rep = (xGetPointerMappingReply) {
 1946         .type = X_Reply,
 1947         .nElts = nElts,
 1948         .sequenceNumber = client->sequence,
 1949         .length = ((unsigned) nElts + (4 - 1)) / 4
 1950     };
 1951     WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
 1952     if (butc)
 1953         WriteToClient(client, nElts, &butc->map[1]);
 1954     return Success;
 1955 }
 1956 
 1957 void
 1958 NoteLedState(DeviceIntPtr keybd, int led, Bool on)
 1959 {
 1960     KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
 1961 
 1962     if (on)
 1963         ctrl->leds |= ((Leds) 1 << (led - 1));
 1964     else
 1965         ctrl->leds &= ~((Leds) 1 << (led - 1));
 1966 }
 1967 
 1968 int
 1969 Ones(unsigned long mask)
 1970 {                               /* HACKMEM 169 */
 1971     unsigned long y;
 1972 
 1973     y = (mask >> 1) & 033333333333;
 1974     y = mask - y - ((y >> 1) & 033333333333);
 1975     return (((y + (y >> 3)) & 030707070707) % 077);
 1976 }
 1977 
 1978 static int
 1979 DoChangeKeyboardControl(ClientPtr client, DeviceIntPtr keybd, XID *vlist,
 1980                         BITS32 vmask)
 1981 {
 1982 #define DO_ALL    (-1)
 1983     KeybdCtrl ctrl;
 1984     int t;
 1985     int led = DO_ALL;
 1986     int key = DO_ALL;
 1987     BITS32 index2;
 1988     int mask = vmask, i;
 1989     XkbEventCauseRec cause;
 1990 
 1991     ctrl = keybd->kbdfeed->ctrl;
 1992     while (vmask) {
 1993         index2 = (BITS32) lowbit(vmask);
 1994         vmask &= ~index2;
 1995         switch (index2) {
 1996         case KBKeyClickPercent:
 1997             t = (INT8) *vlist;
 1998             vlist++;
 1999             if (t == -1) {
 2000                 t = defaultKeyboardControl.click;
 2001             }
 2002             else if (t < 0 || t > 100) {
 2003                 client->errorValue = t;
 2004                 return BadValue;
 2005             }
 2006             ctrl.click = t;
 2007             break;
 2008         case KBBellPercent:
 2009             t = (INT8) *vlist;
 2010             vlist++;
 2011             if (t == -1) {
 2012                 t = defaultKeyboardControl.bell;
 2013             }
 2014             else if (t < 0 || t > 100) {
 2015                 client->errorValue = t;
 2016                 return BadValue;
 2017             }
 2018             ctrl.bell = t;
 2019             break;
 2020         case KBBellPitch:
 2021             t = (INT16) *vlist;
 2022             vlist++;
 2023             if (t == -1) {
 2024                 t = defaultKeyboardControl.bell_pitch;
 2025             }
 2026             else if (t < 0) {
 2027                 client->errorValue = t;
 2028                 return BadValue;
 2029             }
 2030             ctrl.bell_pitch = t;
 2031             break;
 2032         case KBBellDuration:
 2033             t = (INT16) *vlist;
 2034             vlist++;
 2035             if (t == -1)
 2036                 t = defaultKeyboardControl.bell_duration;
 2037             else if (t < 0) {
 2038                 client->errorValue = t;
 2039                 return BadValue;
 2040             }
 2041             ctrl.bell_duration = t;
 2042             break;
 2043         case KBLed:
 2044             led = (CARD8) *vlist;
 2045             vlist++;
 2046             if (led < 1 || led > 32) {
 2047                 client->errorValue = led;
 2048                 return BadValue;
 2049             }
 2050             if (!(mask & KBLedMode))
 2051                 return BadMatch;
 2052             break;
 2053         case KBLedMode:
 2054             t = (CARD8) *vlist;
 2055             vlist++;
 2056             if (t == LedModeOff) {
 2057                 if (led == DO_ALL)
 2058                     ctrl.leds = 0x0;
 2059                 else
 2060                     ctrl.leds &= ~(((Leds) (1)) << (led - 1));
 2061             }
 2062             else if (t == LedModeOn) {
 2063                 if (led == DO_ALL)
 2064                     ctrl.leds = ~0L;
 2065                 else
 2066                     ctrl.leds |= (((Leds) (1)) << (led - 1));
 2067             }
 2068             else {
 2069                 client->errorValue = t;
 2070                 return BadValue;
 2071             }
 2072 
 2073             XkbSetCauseCoreReq(&cause, X_ChangeKeyboardControl, client);
 2074             XkbSetIndicators(keybd, ((led == DO_ALL) ? ~0L : (1L << (led - 1))),
 2075                              ctrl.leds, &cause);
 2076             ctrl.leds = keybd->kbdfeed->ctrl.leds;
 2077 
 2078             break;
 2079         case KBKey:
 2080             key = (KeyCode) *vlist;
 2081             vlist++;
 2082             if ((KeyCode) key < keybd->key->xkbInfo->desc->min_key_code ||
 2083                 (KeyCode) key > keybd->key->xkbInfo->desc->max_key_code) {
 2084                 client->errorValue = key;
 2085                 return BadValue;
 2086             }
 2087             if (!(mask & KBAutoRepeatMode))
 2088                 return BadMatch;
 2089             break;
 2090         case KBAutoRepeatMode:
 2091             i = (key >> 3);
 2092             mask = (1 << (key & 7));
 2093             t = (CARD8) *vlist;
 2094             vlist++;
 2095             if (key != DO_ALL)
 2096                 XkbDisableComputedAutoRepeats(keybd, key);
 2097             if (t == AutoRepeatModeOff) {
 2098                 if (key == DO_ALL)
 2099                     ctrl.autoRepeat = FALSE;
 2100                 else
 2101                     ctrl.autoRepeats[i] &= ~mask;
 2102             }
 2103             else if (t == AutoRepeatModeOn) {
 2104                 if (key == DO_ALL)
 2105                     ctrl.autoRepeat = TRUE;
 2106                 else
 2107                     ctrl.autoRepeats[i] |= mask;
 2108             }
 2109             else if (t == AutoRepeatModeDefault) {
 2110                 if (key == DO_ALL)
 2111                     ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
 2112                 else
 2113                     ctrl.autoRepeats[i] =
 2114                         (ctrl.autoRepeats[i] & ~mask) |
 2115                         (defaultKeyboardControl.autoRepeats[i] & mask);
 2116             }
 2117             else {
 2118                 client->errorValue = t;
 2119                 return BadValue;
 2120             }
 2121             break;
 2122         default:
 2123             client->errorValue = mask;
 2124             return BadValue;
 2125         }
 2126     }
 2127     keybd->kbdfeed->ctrl = ctrl;
 2128 
 2129     /* The XKB RepeatKeys control and core protocol global autorepeat */
 2130     /* value are linked */
 2131     XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
 2132 
 2133     return Success;
 2134 
 2135 #undef DO_ALL
 2136 }
 2137 
 2138 /**
 2139  * Changes kbd control on the ClientPointer and all attached SDs.
 2140  */
 2141 int
 2142 ProcChangeKeyboardControl(ClientPtr client)
 2143 {
 2144     XID *vlist;
 2145     BITS32 vmask;
 2146     int ret = Success, error = Success;
 2147     DeviceIntPtr pDev = NULL, keyboard;
 2148 
 2149     REQUEST(xChangeKeyboardControlReq);
 2150 
 2151     REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
 2152 
 2153     vmask = stuff->mask;
 2154     vlist = (XID *) &stuff[1];
 2155 
 2156     if (client->req_len !=
 2157         (sizeof(xChangeKeyboardControlReq) >> 2) + Ones(vmask))
 2158         return BadLength;
 2159 
 2160     keyboard = PickKeyboard(client);
 2161 
 2162     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
 2163         if ((pDev == keyboard ||
 2164              (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
 2165             && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
 2166             ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
 2167             if (ret != Success)
 2168                 return ret;
 2169         }
 2170     }
 2171 
 2172     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
 2173         if ((pDev == keyboard ||
 2174              (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
 2175             && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
 2176             ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
 2177             if (ret != Success)
 2178                 error = ret;
 2179         }
 2180     }
 2181 
 2182     return error;
 2183 }
 2184 
 2185 int
 2186 ProcGetKeyboardControl(ClientPtr client)
 2187 {
 2188     int rc, i;
 2189     DeviceIntPtr kbd = PickKeyboard(client);
 2190     KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
 2191     xGetKeyboardControlReply rep;
 2192 
 2193     REQUEST_SIZE_MATCH(xReq);
 2194 
 2195     rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
 2196     if (rc != Success)
 2197         return rc;
 2198 
 2199     rep = (xGetKeyboardControlReply) {
 2200         .type = X_Reply,
 2201         .globalAutoRepeat = ctrl->autoRepeat,
 2202         .sequenceNumber = client->sequence,
 2203         .length = 5,
 2204         .ledMask = ctrl->leds,
 2205         .keyClickPercent = ctrl->click,
 2206         .bellPercent = ctrl->bell,
 2207         .bellPitch = ctrl->bell_pitch,
 2208         .bellDuration = ctrl->bell_duration
 2209     };
 2210     for (i = 0; i < 32; i++)
 2211         rep.map[i] = ctrl->autoRepeats[i];
 2212     WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
 2213     return Success;
 2214 }
 2215 
 2216 int
 2217 ProcBell(ClientPtr client)
 2218 {
 2219     DeviceIntPtr dev, keybd = PickKeyboard(client);
 2220     int base = keybd->kbdfeed->ctrl.bell;
 2221     int newpercent;
 2222     int rc;
 2223 
 2224     REQUEST(xBellReq);
 2225     REQUEST_SIZE_MATCH(xBellReq);
 2226 
 2227     if (stuff->percent < -100 || stuff->percent > 100) {
 2228         client->errorValue = stuff->percent;
 2229         return BadValue;
 2230     }
 2231 
 2232     newpercent = (base * stuff->percent) / 100;
 2233     if (stuff->percent < 0)
 2234         newpercent = base + newpercent;
 2235     else
 2236         newpercent = base - newpercent + stuff->percent;
 2237 
 2238     for (dev = inputInfo.devices; dev; dev = dev->next) {
 2239         if ((dev == keybd ||
 2240              (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) &&
 2241             ((dev->kbdfeed && dev->kbdfeed->BellProc) || dev->xkb_interest)) {
 2242 
 2243             rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess);
 2244             if (rc != Success)
 2245                 return rc;
 2246             XkbHandleBell(FALSE, FALSE, dev, newpercent,
 2247                           &dev->kbdfeed->ctrl, 0, None, NULL, client);
 2248         }
 2249     }
 2250 
 2251     return Success;
 2252 }
 2253 
 2254 int
 2255 ProcChangePointerControl(ClientPtr client)
 2256 {
 2257     DeviceIntPtr dev, mouse = PickPointer(client);
 2258     PtrCtrl ctrl;               /* might get BadValue part way through */
 2259     int rc;
 2260 
 2261     REQUEST(xChangePointerControlReq);
 2262     REQUEST_SIZE_MATCH(xChangePointerControlReq);
 2263 
 2264     ctrl = mouse->ptrfeed->ctrl;
 2265     if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
 2266         client->errorValue = stuff->doAccel;
 2267         return BadValue;
 2268     }
 2269     if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
 2270         client->errorValue = stuff->doThresh;
 2271         return BadValue;
 2272     }
 2273     if (stuff->doAccel) {
 2274         if (stuff->accelNum == -1) {
 2275             ctrl.num = defaultPointerControl.num;
 2276         }
 2277         else if (stuff->accelNum < 0) {
 2278             client->errorValue = stuff->accelNum;
 2279             return BadValue;
 2280         }
 2281         else {
 2282             ctrl.num = stuff->accelNum;
 2283         }
 2284 
 2285         if (stuff->accelDenum == -1) {
 2286             ctrl.den = defaultPointerControl.den;
 2287         }
 2288         else if (stuff->accelDenum <= 0) {
 2289             client->errorValue = stuff->accelDenum;
 2290             return BadValue;
 2291         }
 2292         else {
 2293             ctrl.den = stuff->accelDenum;
 2294         }
 2295     }
 2296     if (stuff->doThresh) {
 2297         if (stuff->threshold == -1) {
 2298             ctrl.threshold = defaultPointerControl.threshold;
 2299         }
 2300         else if (stuff->threshold < 0) {
 2301             client->errorValue = stuff->threshold;
 2302             return BadValue;
 2303         }
 2304         else {
 2305             ctrl.threshold = stuff->threshold;
 2306         }
 2307     }
 2308 
 2309     for (dev = inputInfo.devices; dev; dev = dev->next) {
 2310         if ((dev == mouse ||
 2311              (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
 2312             dev->ptrfeed) {
 2313             rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
 2314             if (rc != Success)
 2315                 return rc;
 2316         }
 2317     }
 2318 
 2319     for (dev = inputInfo.devices; dev; dev = dev->next) {
 2320         if ((dev == mouse ||
 2321              (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
 2322             dev->ptrfeed) {
 2323             dev->ptrfeed->ctrl = ctrl;
 2324         }
 2325     }
 2326 
 2327     return Success;
 2328 }
 2329 
 2330 int
 2331 ProcGetPointerControl(ClientPtr client)
 2332 {
 2333     DeviceIntPtr ptr = PickPointer(client);
 2334     PtrCtrl *ctrl;
 2335     xGetPointerControlReply rep;
 2336     int rc;
 2337 
 2338     if (ptr->ptrfeed)
 2339         ctrl = &ptr->ptrfeed->ctrl;
 2340     else
 2341         ctrl = &defaultPointerControl;
 2342 
 2343     REQUEST_SIZE_MATCH(xReq);
 2344 
 2345     rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
 2346     if (rc != Success)
 2347         return rc;
 2348 
 2349     rep = (xGetPointerControlReply) {
 2350         .type = X_Reply,
 2351         .sequenceNumber = client->sequence,
 2352         .length = 0,
 2353         .accelNumerator = ctrl->num,
 2354         .accelDenominator = ctrl->den,
 2355         .threshold = ctrl->threshold
 2356     };
 2357     WriteReplyToClient(client, sizeof(xGenericReply), &rep);
 2358     return Success;
 2359 }
 2360 
 2361 void
 2362 MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
 2363 {
 2364     GrabPtr grab = dev->deviceGrab.grab;
 2365 
 2366     if ((grab && SameClient(grab, client) &&
 2367          ((grab->eventMask & PointerMotionHintMask) ||
 2368           (grab->ownerEvents &&
 2369            (EventMaskForClient(dev->valuator->motionHintWindow, client) &
 2370             PointerMotionHintMask)))) ||
 2371         (!grab &&
 2372          (EventMaskForClient(dev->valuator->motionHintWindow, client) &
 2373           PointerMotionHintMask)))
 2374         dev->valuator->motionHintWindow = NullWindow;
 2375 }
 2376 
 2377 int
 2378 ProcGetMotionEvents(ClientPtr client)
 2379 {
 2380     WindowPtr pWin;
 2381     xTimecoord *coords = (xTimecoord *) NULL;
 2382     xGetMotionEventsReply rep;
 2383     int i, count, xmin, xmax, ymin, ymax, rc;
 2384     unsigned long nEvents;
 2385     DeviceIntPtr mouse = PickPointer(client);
 2386     TimeStamp start, stop;
 2387 
 2388     REQUEST(xGetMotionEventsReq);
 2389     REQUEST_SIZE_MATCH(xGetMotionEventsReq);
 2390 
 2391     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
 2392     if (rc != Success)
 2393         return rc;
 2394     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
 2395     if (rc != Success)
 2396         return rc;
 2397 
 2398     UpdateCurrentTimeIf();
 2399     if (mouse->valuator->motionHintWindow)
 2400         MaybeStopHint(mouse, client);
 2401     rep = (xGetMotionEventsReply) {
 2402         .type = X_Reply,
 2403         .sequenceNumber = client->sequence
 2404     };
 2405     nEvents = 0;
 2406     start = ClientTimeToServerTime(stuff->start);
 2407     stop = ClientTimeToServerTime(stuff->stop);
 2408     if ((CompareTimeStamps(start, stop) != LATER) &&
 2409         (CompareTimeStamps(start, currentTime) != LATER) &&
 2410         mouse->valuator->numMotionEvents) {
 2411         if (CompareTimeStamps(stop, currentTime) == LATER)
 2412             stop = currentTime;
 2413         count = GetMotionHistory(mouse, &coords, start.milliseconds,
 2414                                  stop.milliseconds, pWin->drawable.pScreen,
 2415                                  TRUE);
 2416         xmin = pWin->drawable.x - wBorderWidth(pWin);
 2417         xmax = pWin->drawable.x + (int) pWin->drawable.width +
 2418             wBorderWidth(pWin);
 2419         ymin = pWin->drawable.y - wBorderWidth(pWin);
 2420         ymax = pWin->drawable.y + (int) pWin->drawable.height +
 2421             wBorderWidth(pWin);
 2422         for (i = 0; i < count; i++)
 2423             if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
 2424                 (ymin <= coords[i].y) && (coords[i].y < ymax)) {
 2425                 coords[nEvents].time = coords[i].time;
 2426                 coords[nEvents].x = coords[i].x - pWin->drawable.x;
 2427                 coords[nEvents].y = coords[i].y - pWin->drawable.y;
 2428                 nEvents++;
 2429             }
 2430     }
 2431     rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord));
 2432     rep.nEvents = nEvents;
 2433     WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
 2434     if (nEvents) {
 2435         client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
 2436         WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
 2437                                  (char *) coords);
 2438     }
 2439     free(coords);
 2440     return Success;
 2441 }
 2442 
 2443 int
 2444 ProcQueryKeymap(ClientPtr client)
 2445 {
 2446     xQueryKeymapReply rep;
 2447     int rc, i;
 2448     DeviceIntPtr keybd = PickKeyboard(client);
 2449     CARD8 *down = keybd->key->down;
 2450 
 2451     REQUEST_SIZE_MATCH(xReq);
 2452     rep = (xQueryKeymapReply) {
 2453         .type = X_Reply,
 2454         .sequenceNumber = client->sequence,
 2455         .length = 2
 2456     };
 2457 
 2458     rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
 2459     /* If rc is Success, we're allowed to copy out the keymap.
 2460      * If it's BadAccess, we leave it empty & lie to the client.
 2461      */
 2462     if (rc == Success) {
 2463         for (i = 0; i < 32; i++)
 2464             rep.map[i] = down[i];
 2465     }
 2466     else if (rc != BadAccess)
 2467         return rc;
 2468 
 2469     WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
 2470 
 2471     return Success;
 2472 }
 2473 
 2474 /**
 2475  * Recalculate the number of buttons for the master device. The number of
 2476  * buttons on the master device is equal to the number of buttons on the
 2477  * slave device with the highest number of buttons.
 2478  */
 2479 static void
 2480 RecalculateMasterButtons(DeviceIntPtr slave)
 2481 {
 2482     DeviceIntPtr dev, master;
 2483     int maxbuttons = 0;
 2484 
 2485     if (!slave->button || IsMaster(slave))
 2486         return;
 2487 
 2488     master = GetMaster(slave, MASTER_POINTER);
 2489     if (!master)
 2490         return;
 2491 
 2492     for (dev = inputInfo.devices; dev; dev = dev->next) {
 2493         if (IsMaster(dev) ||
 2494             GetMaster(dev, MASTER_ATTACHED) != master || !dev->button)
 2495             continue;
 2496 
 2497         maxbuttons = max(maxbuttons, dev->button->numButtons);
 2498     }
 2499 
 2500     if (master->button && master->button->numButtons != maxbuttons) {
 2501         int i;
 2502         DeviceChangedEvent event = {
 2503             .header = ET_Internal,
 2504             .type = ET_DeviceChanged,
 2505             .time = GetTimeInMillis(),
 2506             .deviceid = master->id,
 2507             .flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE,
 2508             .buttons.num_buttons = maxbuttons
 2509         };
 2510 
 2511         master->button->numButtons = maxbuttons;
 2512 
 2513         memcpy(&event.buttons.names, master->button->labels, maxbuttons *
 2514                sizeof(Atom));
 2515 
 2516         if (master->valuator) {
 2517             event.num_valuators = master->valuator->numAxes;
 2518             for (i = 0; i < event.num_valuators; i++) {
 2519                 event.valuators[i].min = master->valuator->axes[i].min_value;
 2520                 event.valuators[i].max = master->valuator->axes[i].max_value;
 2521                 event.valuators[i].resolution =
 2522                     master->valuator->axes[i].resolution;
 2523                 event.valuators[i].mode = master->valuator->axes[i].mode;
 2524                 event.valuators[i].name = master->valuator->axes[i].label;
 2525             }
 2526         }
 2527 
 2528         if (master->key) {
 2529             event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code;
 2530             event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code;
 2531         }
 2532 
 2533         XISendDeviceChangedEvent(master, &event);
 2534     }
 2535 }
 2536 
 2537 /**
 2538  * Generate release events for all keys/button currently down on this
 2539  * device.
 2540  */
 2541 void
 2542 ReleaseButtonsAndKeys(DeviceIntPtr dev)
 2543 {
 2544     InternalEvent *eventlist = InitEventList(GetMaximumEventsNum());
 2545     ButtonClassPtr b = dev->button;
 2546     KeyClassPtr k = dev->key;
 2547     int i, j, nevents;
 2548 
 2549     if (!eventlist)             /* no release events for you */
 2550         return;
 2551 
 2552     /* Release all buttons */
 2553     for (i = 0; b && i < b->numButtons; i++) {
 2554         if (BitIsOn(b->down, i)) {
 2555             nevents =
 2556                 GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
 2557             for (j = 0; j < nevents; j++)
 2558                 mieqProcessDeviceEvent(dev, &eventlist[j], NULL);
 2559         }
 2560     }
 2561 
 2562     /* Release all keys */
 2563     for (i = 0; k && i < MAP_LENGTH; i++) {
 2564         if (BitIsOn(k->down, i)) {
 2565             nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
 2566             for (j = 0; j < nevents; j++)
 2567                 mieqProcessDeviceEvent(dev, &eventlist[j], NULL);
 2568         }
 2569     }
 2570 
 2571     FreeEventList(eventlist, GetMaximumEventsNum());
 2572 }
 2573 
 2574 /**
 2575  * Attach device 'dev' to device 'master'.
 2576  * Client is set to the client that issued the request, or NULL if it comes
 2577  * from some internal automatic pairing.
 2578  *
 2579  * Master may be NULL to set the device floating.
 2580  *
 2581  * We don't allow multi-layer hierarchies right now. You can't attach a slave
 2582  * to another slave.
 2583  */
 2584 int
 2585 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 2586 {
 2587     ScreenPtr screen;
 2588 
 2589     if (!dev || IsMaster(dev))
 2590         return BadDevice;
 2591 
 2592     if (master && !IsMaster(master))    /* can't attach to slaves */
 2593         return BadDevice;
 2594 
 2595     /* set from floating to floating? */
 2596     if (IsFloating(dev) && !master && dev->enabled)
 2597         return Success;
 2598 
 2599     /* free the existing sprite. */
 2600     if (IsFloating(dev) && dev->spriteInfo->paired == dev) {
 2601         screen = miPointerGetScreen(dev);
 2602         screen->DeviceCursorCleanup(dev, screen);
 2603         free(dev->spriteInfo->sprite);
 2604     }
 2605 
 2606     dev->master = master;
 2607 
 2608     /* If device is set to floating, we need to create a sprite for it,
 2609      * otherwise things go bad. However, we don't want to render the cursor,
 2610      * so we reset spriteOwner.
 2611      * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
 2612      * alloc new memory but overwrite the previous one.
 2613      */
 2614     if (!master) {
 2615         WindowPtr currentRoot;
 2616 
 2617         if (dev->spriteInfo->sprite)
 2618             currentRoot = GetCurrentRootWindow(dev);
 2619         else                    /* new device auto-set to floating */
 2620             currentRoot = screenInfo.screens[0]->root;
 2621 
 2622         /* we need to init a fake sprite */
 2623         screen = currentRoot->drawable.pScreen;
 2624         screen->DeviceCursorInitialize(dev, screen);
 2625         dev->spriteInfo->sprite = NULL;
 2626         InitializeSprite(dev, currentRoot);
 2627         dev->spriteInfo->spriteOwner = FALSE;
 2628         dev->spriteInfo->paired = dev;
 2629     }
 2630     else {
 2631         dev->spriteInfo->sprite = master->spriteInfo->sprite;
 2632         dev->spriteInfo->paired = master;
 2633         dev->spriteInfo->spriteOwner = FALSE;
 2634 
 2635         XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
 2636         RecalculateMasterButtons(master);
 2637     }
 2638 
 2639     /* XXX: in theory, the MD should change back to its old, original
 2640      * classes when the last SD is detached. Thanks to the XTEST devices,
 2641      * we'll always have an SD attached until the MD is removed.
 2642      * So let's not worry about that.
 2643      */
 2644 
 2645     return Success;
 2646 }
 2647 
 2648 /**
 2649  * Return the device paired with the given device or NULL.
 2650  * Returns the device paired with the parent master if the given device is a
 2651  * slave device.
 2652  */
 2653 DeviceIntPtr
 2654 GetPairedDevice(DeviceIntPtr dev)
 2655 {
 2656     if (!IsMaster(dev) && !IsFloating(dev))
 2657         dev = GetMaster(dev, MASTER_ATTACHED);
 2658 
 2659     return dev->spriteInfo? dev->spriteInfo->paired: NULL;
 2660 }
 2661 
 2662 /**
 2663  * Returns the requested master for this device.
 2664  * The return values are:
 2665  * - MASTER_ATTACHED: the master for this device or NULL for a floating
 2666  *   slave.
 2667  * - MASTER_KEYBOARD: the master keyboard for this device or NULL for a
 2668  *   floating slave
 2669  * - MASTER_POINTER: the master pointer for this device or NULL for a
 2670  *   floating slave
 2671  * - POINTER_OR_FLOAT: the master pointer for this device or the device for
 2672  *   a floating slave
 2673  * - KEYBOARD_OR_FLOAT: the master keyboard for this device or the device for
 2674  *   a floating slave
 2675  *
 2676  * @param which ::MASTER_KEYBOARD or ::MASTER_POINTER, ::MASTER_ATTACHED,
 2677  * ::POINTER_OR_FLOAT or ::KEYBOARD_OR_FLOAT.
 2678  * @return The requested master device
 2679  */
 2680 DeviceIntPtr
 2681 GetMaster(DeviceIntPtr dev, int which)
 2682 {
 2683     DeviceIntPtr master;
 2684 
 2685     if (IsMaster(dev))
 2686         master = dev;
 2687     else {
 2688         master = dev->master;
 2689         if (!master &&
 2690             (which == POINTER_OR_FLOAT || which == KEYBOARD_OR_FLOAT))
 2691             return dev;
 2692     }
 2693 
 2694     if (master && which != MASTER_ATTACHED) {
 2695         if (which == MASTER_KEYBOARD || which == KEYBOARD_OR_FLOAT) {
 2696             if (master->type != MASTER_KEYBOARD)
 2697                 master = GetPairedDevice(master);
 2698         }
 2699         else {
 2700             if (master->type != MASTER_POINTER)
 2701                 master = GetPairedDevice(master);
 2702         }
 2703     }
 2704 
 2705     return master;
 2706 }
 2707 
 2708 /**
 2709  * Create a new device pair (== one pointer, one keyboard device).
 2710  * Only allocates the devices, you will need to call ActivateDevice() and
 2711  * EnableDevice() manually.
 2712  * Either a master or a slave device can be created depending on
 2713  * the value for master.
 2714  */
 2715 int
 2716 AllocDevicePair(ClientPtr client, const char *name,
 2717                 DeviceIntPtr *ptr,
 2718                 DeviceIntPtr *keybd,
 2719                 DeviceProc ptr_proc, DeviceProc keybd_proc, Bool master)
 2720 {
 2721     DeviceIntPtr pointer;
 2722     DeviceIntPtr keyboard;
 2723     char *dev_name;
 2724 
 2725     *ptr = *keybd = NULL;
 2726 
 2727     XkbInitPrivates();
 2728 
 2729     pointer = AddInputDevice(client, ptr_proc, TRUE);
 2730 
 2731     if (!pointer)
 2732         return BadAlloc;
 2733 
 2734     if (asprintf(&dev_name, "%s pointer", name) == -1) {
 2735         RemoveDevice(pointer, FALSE);
 2736 
 2737         return BadAlloc;
 2738     }
 2739     pointer->name = dev_name;
 2740 
 2741     pointer->public.processInputProc = ProcessOtherEvent;
 2742     pointer->public.realInputProc = ProcessOtherEvent;
 2743     XkbSetExtension(pointer, ProcessPointerEvent);
 2744     pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
 2745     pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
 2746     pointer->coreEvents = TRUE;
 2747     pointer->spriteInfo->spriteOwner = TRUE;
 2748 
 2749     pointer->lastSlave = NULL;
 2750     pointer->last.slave = NULL;
 2751     pointer->type = (master) ? MASTER_POINTER : SLAVE;
 2752 
 2753     keyboard = AddInputDevice(client, keybd_proc, TRUE);
 2754     if (!keyboard) {
 2755         RemoveDevice(pointer, FALSE);
 2756 
 2757         return BadAlloc;
 2758     }
 2759 
 2760     if (asprintf(&dev_name, "%s keyboard", name) == -1) {
 2761         RemoveDevice(keyboard, FALSE);
 2762         RemoveDevice(pointer, FALSE);
 2763 
 2764         return BadAlloc;
 2765     }
 2766     keyboard->name = dev_name;
 2767 
 2768     keyboard->public.processInputProc = ProcessOtherEvent;
 2769     keyboard->public.realInputProc = ProcessOtherEvent;
 2770     XkbSetExtension(keyboard, ProcessKeyboardEvent);
 2771     keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
 2772     keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
 2773     keyboard->coreEvents = TRUE;
 2774     keyboard->spriteInfo->spriteOwner = FALSE;
 2775 
 2776     keyboard->lastSlave = NULL;
 2777     keyboard->last.slave = NULL;
 2778     keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
 2779 
 2780     /* The ClassesRec stores the device classes currently not used. */
 2781     if (IsMaster(pointer)) {
 2782         pointer->unused_classes = calloc(1, sizeof(ClassesRec));
 2783         keyboard->unused_classes = calloc(1, sizeof(ClassesRec));
 2784     }
 2785 
 2786     *ptr = pointer;
 2787 
 2788     *keybd = keyboard;
 2789 
 2790     return Success;
 2791 }
 2792 
 2793 /**
 2794  * Return Relative or Absolute for the device.
 2795  */
 2796 int
 2797 valuator_get_mode(DeviceIntPtr dev, int axis)
 2798 {
 2799     return (dev->valuator->axes[axis].mode & DeviceMode);
 2800 }
 2801 
 2802 /**
 2803  * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then
 2804  * set the mode for all axes.
 2805  */
 2806 void
 2807 valuator_set_mode(DeviceIntPtr dev, int axis, int mode)
 2808 {
 2809     if (axis != VALUATOR_MODE_ALL_AXES)
 2810         dev->valuator->axes[axis].mode = mode;
 2811     else {
 2812         int i;
 2813 
 2814         for (i = 0; i < dev->valuator->numAxes; i++)
 2815             dev->valuator->axes[i].mode = mode;
 2816     }
 2817 }