xserver

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

devices.c (82602B)


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