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