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