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