devices.c revision 65b04b38
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    /* Float all SDs before closing them. Note that at this point resources
986     * (e.g. cursors) have been freed already, so we can't just call
987     * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
988     * to NULL and pretend nothing happened.
989     */
990    for (dev = inputInfo.devices; dev; dev = dev->next)
991    {
992        if (!IsMaster(dev) && dev->u.master)
993            dev->u.master = NULL;
994    }
995
996    CloseDeviceList(&inputInfo.devices);
997    CloseDeviceList(&inputInfo.off_devices);
998
999    CloseDevice(inputInfo.pointer);
1000    CloseDevice(inputInfo.keyboard);
1001
1002    inputInfo.devices = NULL;
1003    inputInfo.off_devices = NULL;
1004    inputInfo.keyboard = NULL;
1005    inputInfo.pointer = NULL;
1006    XkbDeleteRulesDflts();
1007}
1008
1009/**
1010 * Remove the cursor sprite for all devices. This needs to be done before any
1011 * resources are freed or any device is deleted.
1012 */
1013void
1014UndisplayDevices(void)
1015{
1016    DeviceIntPtr dev;
1017    ScreenPtr screen = screenInfo.screens[0];
1018
1019    for (dev = inputInfo.devices; dev; dev = dev->next)
1020        screen->DisplayCursor(dev, screen, NullCursor);
1021}
1022
1023/**
1024 * Remove a device from the device list, closes it and thus frees all
1025 * resources.
1026 * Removes both enabled and disabled devices and notifies all devices about
1027 * the removal of the device.
1028 *
1029 * No PresenceNotify is sent for device that the client never saw. This can
1030 * happen if a malloc fails during the addition of master devices. If
1031 * dev->init is FALSE it means the client never received a DeviceAdded event,
1032 * so let's not send a DeviceRemoved event either.
1033 *
1034 * @param sendevent True if an XI2 event should be sent.
1035 */
1036int
1037RemoveDevice(DeviceIntPtr dev, BOOL sendevent)
1038{
1039    DeviceIntPtr prev,tmp,next;
1040    int ret = BadMatch;
1041    ScreenPtr screen = screenInfo.screens[0];
1042    int deviceid;
1043    int initialized;
1044    int flags[MAXDEVICES] = {0};
1045
1046    DebugF("(dix) removing device %d\n", dev->id);
1047
1048    if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
1049        return BadImplementation;
1050
1051    initialized = dev->inited;
1052    deviceid = dev->id;
1053
1054    if (initialized)
1055    {
1056        if (DevHasCursor(dev))
1057            screen->DisplayCursor(dev, screen, NullCursor);
1058
1059        DisableDevice(dev, sendevent);
1060        flags[dev->id] = XIDeviceDisabled;
1061    }
1062
1063    prev = NULL;
1064    for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
1065	next = tmp->next;
1066	if (tmp == dev) {
1067
1068	    if (prev==NULL)
1069		inputInfo.devices = next;
1070	    else
1071		prev->next = next;
1072
1073	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1074	    CloseDevice(tmp);
1075	    ret = Success;
1076	}
1077    }
1078
1079    prev = NULL;
1080    for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
1081	next = tmp->next;
1082	if (tmp == dev) {
1083	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1084	    CloseDevice(tmp);
1085
1086	    if (prev == NULL)
1087		inputInfo.off_devices = next;
1088	    else
1089		prev->next = next;
1090
1091            ret = Success;
1092	}
1093    }
1094
1095    if (ret == Success && initialized) {
1096        inputInfo.numDevices--;
1097        SendDevicePresenceEvent(deviceid, DeviceRemoved);
1098        if (sendevent)
1099            XISendDeviceHierarchyEvent(flags);
1100    }
1101
1102    return ret;
1103}
1104
1105int
1106NumMotionEvents(void)
1107{
1108    /* only called to fill data in initial connection reply.
1109     * VCP is ok here, it is the only fixed device we have. */
1110    return inputInfo.pointer->valuator->numMotionEvents;
1111}
1112
1113int
1114dixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode)
1115{
1116    DeviceIntPtr dev;
1117    int rc;
1118    *pDev = NULL;
1119
1120    for (dev=inputInfo.devices; dev; dev=dev->next) {
1121        if (dev->id == id)
1122            goto found;
1123    }
1124    for (dev=inputInfo.off_devices; dev; dev=dev->next) {
1125        if (dev->id == id)
1126	    goto found;
1127    }
1128    return BadDevice;
1129
1130found:
1131    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1132    if (rc == Success)
1133	*pDev = dev;
1134    return rc;
1135}
1136
1137void
1138QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
1139{
1140    if (inputInfo.keyboard) {
1141	*minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code;
1142	*maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code;
1143    }
1144}
1145
1146/* Notably, this function does not expand the destination's keycode range, or
1147 * notify clients. */
1148Bool
1149SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
1150{
1151    int i, j;
1152    KeySym *tmp;
1153    int rowDif = src->minKeyCode - dst->minKeyCode;
1154
1155    /* if keysym map size changes, grow map first */
1156    if (src->mapWidth < dst->mapWidth) {
1157        for (i = src->minKeyCode; i <= src->maxKeyCode; i++) {
1158#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c))
1159#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c))
1160	    for (j = 0; j < src->mapWidth; j++)
1161		dst->map[DI(i, j)] = src->map[SI(i, j)];
1162	    for (j = src->mapWidth; j < dst->mapWidth; j++)
1163		dst->map[DI(i, j)] = NoSymbol;
1164#undef SI
1165#undef DI
1166	}
1167	return TRUE;
1168    }
1169    else if (src->mapWidth > dst->mapWidth) {
1170        i = sizeof(KeySym) * src->mapWidth *
1171             (dst->maxKeyCode - dst->minKeyCode + 1);
1172        tmp = calloc(sizeof(KeySym), i);
1173        if (!tmp)
1174            return FALSE;
1175
1176        if (dst->map) {
1177            for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
1178                memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth],
1179                        dst->mapWidth * sizeof(KeySym));
1180            free(dst->map);
1181        }
1182        dst->mapWidth = src->mapWidth;
1183        dst->map = tmp;
1184    }
1185    else if (!dst->map) {
1186        i = sizeof(KeySym) * src->mapWidth *
1187             (dst->maxKeyCode - dst->minKeyCode + 1);
1188        tmp = calloc(sizeof(KeySym), i);
1189        if (!tmp)
1190            return FALSE;
1191
1192        dst->map = tmp;
1193        dst->mapWidth = src->mapWidth;
1194    }
1195
1196    memmove(&dst->map[rowDif * dst->mapWidth], src->map,
1197            (src->maxKeyCode - src->minKeyCode + 1) *
1198            dst->mapWidth * sizeof(KeySym));
1199
1200    return TRUE;
1201}
1202
1203Bool
1204InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
1205                            CARD8 *map)
1206{
1207    ButtonClassPtr butc;
1208    int i;
1209
1210    butc = calloc(1, sizeof(ButtonClassRec));
1211    if (!butc)
1212	return FALSE;
1213    butc->numButtons = numButtons;
1214    butc->sourceid = dev->id;
1215    for (i = 1; i <= numButtons; i++)
1216	butc->map[i] = map[i];
1217    for (i = numButtons + 1; i < MAP_LENGTH; i++)
1218        butc->map[i] = i;
1219    memcpy(butc->labels, labels, numButtons * sizeof(Atom));
1220    dev->button = butc;
1221    return TRUE;
1222}
1223
1224/**
1225 * Allocate a valuator class and set up the pointers for the axis values
1226 * appropriately.
1227 *
1228 * @param src If non-NULL, the memory is reallocated from src. If NULL, the
1229 * memory is calloc'd.
1230 * @parma numAxes Number of axes to allocate.
1231 * @return The allocated valuator struct.
1232 */
1233ValuatorClassPtr
1234AllocValuatorClass(ValuatorClassPtr src, int numAxes)
1235{
1236    ValuatorClassPtr v;
1237    /* force alignment with double */
1238    union align_u { ValuatorClassRec valc; double d; } *align;
1239    int size;
1240
1241    size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
1242    align = (union align_u *) realloc(src, size);
1243
1244    if (!align)
1245        return NULL;
1246
1247    if (!src)
1248        memset(align, 0, size);
1249
1250    v = &align->valc;
1251    v->numAxes = numAxes;
1252    v->axisVal = (double*)(align + 1);
1253    v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
1254
1255    return v;
1256}
1257
1258Bool
1259InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
1260                              int numMotionEvents, int mode)
1261{
1262    int i;
1263    ValuatorClassPtr valc;
1264
1265    if (!dev)
1266        return FALSE;
1267
1268    if (numAxes > MAX_VALUATORS)
1269    {
1270        LogMessage(X_WARNING,
1271                   "Device '%s' has %d axes, only using first %d.\n",
1272                   dev->name, numAxes, MAX_VALUATORS);
1273        numAxes = MAX_VALUATORS;
1274    }
1275
1276    valc = AllocValuatorClass(NULL, numAxes);
1277    if (!valc)
1278        return FALSE;
1279
1280    valc->sourceid = dev->id;
1281    valc->motion = NULL;
1282    valc->first_motion = 0;
1283    valc->last_motion = 0;
1284
1285    valc->numMotionEvents = numMotionEvents;
1286    valc->motionHintWindow = NullWindow;
1287
1288    if (mode & OutOfProximity)
1289        InitProximityClassDeviceStruct(dev);
1290
1291    dev->valuator = valc;
1292
1293    AllocateMotionHistory(dev);
1294
1295    for (i=0; i<numAxes; i++) {
1296        InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1297                               0, 0, 0, mode);
1298	valc->axisVal[i]=0;
1299    }
1300
1301    dev->last.numValuators = numAxes;
1302
1303    if (IsMaster(dev) || /* do not accelerate master or xtest devices */
1304        IsXTestDevice(dev, NULL))
1305	InitPointerAccelerationScheme(dev, PtrAccelNoOp);
1306    else
1307	InitPointerAccelerationScheme(dev, PtrAccelDefault);
1308    return TRUE;
1309}
1310
1311/* global list of acceleration schemes */
1312ValuatorAccelerationRec pointerAccelerationScheme[] = {
1313    {PtrAccelNoOp,        NULL, NULL, NULL},
1314    {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
1315    {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
1316    {-1, NULL, NULL, NULL} /* terminator */
1317};
1318
1319/**
1320 * install an acceleration scheme. returns TRUE on success, and should not
1321 * change anything if unsuccessful.
1322 */
1323Bool
1324InitPointerAccelerationScheme(DeviceIntPtr dev,
1325                              int scheme)
1326{
1327    int x, i = -1;
1328    void* data = NULL;
1329    ValuatorClassPtr val;
1330
1331    val = dev->valuator;
1332
1333    if(!val)
1334	return FALSE;
1335
1336    if(IsMaster(dev) && scheme != PtrAccelNoOp)
1337        return FALSE;
1338
1339    for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
1340        if(pointerAccelerationScheme[x].number == scheme){
1341            i = x;
1342            break;
1343        }
1344    }
1345
1346    if(-1 == i)
1347        return FALSE;
1348
1349    if (val->accelScheme.AccelCleanupProc)
1350        val->accelScheme.AccelCleanupProc(dev);
1351
1352    /* init scheme-specific data */
1353    switch(scheme){
1354        case PtrAccelPredictable:
1355        {
1356            DeviceVelocityPtr s;
1357            s = malloc(sizeof(DeviceVelocityRec));
1358            if(!s)
1359        	return FALSE;
1360            InitVelocityData(s);
1361            data = s;
1362            break;
1363        }
1364        default:
1365            break;
1366    }
1367
1368    val->accelScheme = pointerAccelerationScheme[i];
1369    val->accelScheme.accelData = data;
1370
1371    /* post-init scheme */
1372    switch(scheme){
1373        case PtrAccelPredictable:
1374            InitializePredictableAccelerationProperties(dev);
1375            break;
1376
1377        default:
1378            break;
1379    }
1380
1381    return TRUE;
1382}
1383
1384Bool
1385InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
1386{
1387    AbsoluteClassPtr abs;
1388
1389    abs = malloc(sizeof(AbsoluteClassRec));
1390    if (!abs)
1391        return FALSE;
1392
1393    /* we don't do anything sensible with these, but should */
1394    abs->min_x = NO_AXIS_LIMITS;
1395    abs->min_y = NO_AXIS_LIMITS;
1396    abs->max_x = NO_AXIS_LIMITS;
1397    abs->max_y = NO_AXIS_LIMITS;
1398    abs->flip_x = 0;
1399    abs->flip_y = 0;
1400    abs->rotation = 0;
1401    abs->button_threshold = 0;
1402
1403    abs->offset_x = 0;
1404    abs->offset_y = 0;
1405    abs->width = NO_AXIS_LIMITS;
1406    abs->height = NO_AXIS_LIMITS;
1407    abs->following = 0;
1408    abs->screen = 0;
1409
1410    abs->sourceid = dev->id;
1411
1412    dev->absolute = abs;
1413
1414    return TRUE;
1415}
1416
1417Bool
1418InitFocusClassDeviceStruct(DeviceIntPtr dev)
1419{
1420    FocusClassPtr focc;
1421
1422    focc = malloc(sizeof(FocusClassRec));
1423    if (!focc)
1424	return FALSE;
1425    focc->win = PointerRootWin;
1426    focc->revert = None;
1427    focc->time = currentTime;
1428    focc->trace = (WindowPtr *)NULL;
1429    focc->traceSize = 0;
1430    focc->traceGood = 0;
1431    focc->sourceid = dev->id;
1432    dev->focus = focc;
1433    return TRUE;
1434}
1435
1436Bool
1437InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
1438{
1439    PtrFeedbackPtr feedc;
1440
1441    feedc = malloc(sizeof(PtrFeedbackClassRec));
1442    if (!feedc)
1443	return FALSE;
1444    feedc->CtrlProc = controlProc;
1445    feedc->ctrl = defaultPointerControl;
1446    feedc->ctrl.id = 0;
1447    if ( (feedc->next = dev->ptrfeed) )
1448        feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
1449    dev->ptrfeed = feedc;
1450    (*controlProc)(dev, &feedc->ctrl);
1451    return TRUE;
1452}
1453
1454
1455static LedCtrl defaultLedControl = {
1456	DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0};
1457
1458static BellCtrl defaultBellControl = {
1459	DEFAULT_BELL,
1460	DEFAULT_BELL_PITCH,
1461	DEFAULT_BELL_DURATION,
1462	0};
1463
1464static IntegerCtrl defaultIntegerControl = {
1465	DEFAULT_INT_RESOLUTION,
1466	DEFAULT_INT_MIN_VALUE,
1467	DEFAULT_INT_MAX_VALUE,
1468	DEFAULT_INT_DISPLAYED,
1469	0};
1470
1471Bool
1472InitStringFeedbackClassDeviceStruct (
1473      DeviceIntPtr dev, StringCtrlProcPtr controlProc,
1474      int max_symbols, int num_symbols_supported, KeySym *symbols)
1475{
1476    int i;
1477    StringFeedbackPtr feedc;
1478
1479    feedc = malloc(sizeof(StringFeedbackClassRec));
1480    if (!feedc)
1481	return FALSE;
1482    feedc->CtrlProc = controlProc;
1483    feedc->ctrl.num_symbols_supported = num_symbols_supported;
1484    feedc->ctrl.num_symbols_displayed = 0;
1485    feedc->ctrl.max_symbols = max_symbols;
1486    feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported);
1487    feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols);
1488    if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
1489    {
1490	free(feedc->ctrl.symbols_supported);
1491	free(feedc->ctrl.symbols_displayed);
1492	free(feedc);
1493	return FALSE;
1494    }
1495    for (i=0; i<num_symbols_supported; i++)
1496	*(feedc->ctrl.symbols_supported+i) = *symbols++;
1497    for (i=0; i<max_symbols; i++)
1498	*(feedc->ctrl.symbols_displayed+i) = (KeySym) 0;
1499    feedc->ctrl.id = 0;
1500    if ( (feedc->next = dev->stringfeed) )
1501	feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
1502    dev->stringfeed = feedc;
1503    (*controlProc)(dev, &feedc->ctrl);
1504    return TRUE;
1505}
1506
1507Bool
1508InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
1509                                   BellCtrlProcPtr controlProc)
1510{
1511    BellFeedbackPtr feedc;
1512
1513    feedc = malloc(sizeof(BellFeedbackClassRec));
1514    if (!feedc)
1515	return FALSE;
1516    feedc->CtrlProc = controlProc;
1517    feedc->BellProc = bellProc;
1518    feedc->ctrl = defaultBellControl;
1519    feedc->ctrl.id = 0;
1520    if ( (feedc->next = dev->bell) )
1521	feedc->ctrl.id = dev->bell->ctrl.id + 1;
1522    dev->bell = feedc;
1523    (*controlProc)(dev, &feedc->ctrl);
1524    return TRUE;
1525}
1526
1527Bool
1528InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc)
1529{
1530    LedFeedbackPtr feedc;
1531
1532    feedc = malloc(sizeof(LedFeedbackClassRec));
1533    if (!feedc)
1534	return FALSE;
1535    feedc->CtrlProc = controlProc;
1536    feedc->ctrl = defaultLedControl;
1537    feedc->ctrl.id = 0;
1538    if ( (feedc->next = dev->leds) )
1539	feedc->ctrl.id = dev->leds->ctrl.id + 1;
1540    feedc->xkb_sli= NULL;
1541    dev->leds = feedc;
1542    (*controlProc)(dev, &feedc->ctrl);
1543    return TRUE;
1544}
1545
1546Bool
1547InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc)
1548{
1549    IntegerFeedbackPtr feedc;
1550
1551    feedc = malloc(sizeof(IntegerFeedbackClassRec));
1552    if (!feedc)
1553	return FALSE;
1554    feedc->CtrlProc = controlProc;
1555    feedc->ctrl = defaultIntegerControl;
1556    feedc->ctrl.id = 0;
1557    if ( (feedc->next = dev->intfeed) )
1558	feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
1559    dev->intfeed = feedc;
1560    (*controlProc)(dev, &feedc->ctrl);
1561    return TRUE;
1562}
1563
1564Bool
1565InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels,
1566                        PtrCtrlProcPtr controlProc, int numMotionEvents,
1567                        int numAxes, Atom *axes_labels)
1568{
1569    DeviceIntPtr dev = (DeviceIntPtr)device;
1570
1571    return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
1572	   InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
1573					 numMotionEvents, Relative) &&
1574	   InitPtrFeedbackClassDeviceStruct(dev, controlProc));
1575}
1576
1577/*
1578 * Check if the given buffer contains elements between low (inclusive) and
1579 * high (inclusive) only.
1580 *
1581 * @return TRUE if the device map is invalid, FALSE otherwise.
1582 */
1583Bool
1584BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
1585{
1586    int i;
1587
1588    for (i = 0; i < length; i++)
1589	if (buff[i])		       /* only check non-zero elements */
1590	{
1591	    if ((low > buff[i]) || (high < buff[i]))
1592	    {
1593		*errval = buff[i];
1594		return TRUE;
1595	    }
1596	}
1597    return FALSE;
1598}
1599
1600int
1601ProcSetModifierMapping(ClientPtr client)
1602{
1603    xSetModifierMappingReply rep;
1604    int rc;
1605    REQUEST(xSetModifierMappingReq);
1606    REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
1607
1608    if (client->req_len != ((stuff->numKeyPerModifier << 1) +
1609                bytes_to_int32(sizeof(xSetModifierMappingReq))))
1610	return BadLength;
1611
1612    rep.type = X_Reply;
1613    rep.length = 0;
1614    rep.sequenceNumber = client->sequence;
1615
1616    rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1],
1617                       stuff->numKeyPerModifier);
1618    if (rc == MappingFailed || rc == -1)
1619        return BadValue;
1620    if (rc != Success && rc != MappingSuccess && rc != MappingFailed &&
1621        rc != MappingBusy)
1622	return rc;
1623
1624    rep.success = rc;
1625
1626    WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
1627    return Success;
1628}
1629
1630int
1631ProcGetModifierMapping(ClientPtr client)
1632{
1633    xGetModifierMappingReply rep;
1634    int max_keys_per_mod = 0;
1635    KeyCode *modkeymap = NULL;
1636    REQUEST_SIZE_MATCH(xReq);
1637
1638    generate_modkeymap(client, PickKeyboard(client), &modkeymap,
1639                       &max_keys_per_mod);
1640
1641    memset(&rep, 0, sizeof(xGetModifierMappingReply));
1642    rep.type = X_Reply;
1643    rep.numKeyPerModifier = max_keys_per_mod;
1644    rep.sequenceNumber = client->sequence;
1645    /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */
1646    rep.length = max_keys_per_mod << 1;
1647
1648    WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
1649    (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap);
1650
1651    free(modkeymap);
1652
1653    return Success;
1654}
1655
1656int
1657ProcChangeKeyboardMapping(ClientPtr client)
1658{
1659    REQUEST(xChangeKeyboardMappingReq);
1660    unsigned len;
1661    KeySymsRec keysyms;
1662    DeviceIntPtr pDev, tmp;
1663    int rc;
1664    REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
1665
1666    len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq));
1667    if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
1668            return BadLength;
1669
1670    pDev = PickKeyboard(client);
1671
1672    if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) ||
1673	(stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) {
1674	    client->errorValue = stuff->firstKeyCode;
1675	    return BadValue;
1676
1677    }
1678    if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) >
1679          pDev->key->xkbInfo->desc->max_key_code) ||
1680        (stuff->keySymsPerKeyCode == 0)) {
1681	    client->errorValue = stuff->keySymsPerKeyCode;
1682	    return BadValue;
1683    }
1684
1685    keysyms.minKeyCode = stuff->firstKeyCode;
1686    keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
1687    keysyms.mapWidth = stuff->keySymsPerKeyCode;
1688    keysyms.map = (KeySym *) &stuff[1];
1689
1690    rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1691    if (rc != Success)
1692        return rc;
1693
1694    XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode,
1695                          stuff->keyCodes, NULL, client);
1696
1697    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
1698        if (IsMaster(tmp) || tmp->u.master != pDev)
1699            continue;
1700        if (!tmp->key)
1701            continue;
1702
1703        rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1704        if (rc != Success)
1705            continue;
1706
1707        XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode,
1708                              stuff->keyCodes, NULL, client);
1709    }
1710
1711    return Success;
1712}
1713
1714int
1715ProcSetPointerMapping(ClientPtr client)
1716{
1717    BYTE *map;
1718    int ret;
1719    int i, j;
1720    DeviceIntPtr ptr = PickPointer(client);
1721    xSetPointerMappingReply rep;
1722    REQUEST(xSetPointerMappingReq);
1723    REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
1724
1725    if (client->req_len !=
1726            bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts))
1727	return BadLength;
1728    rep.type = X_Reply;
1729    rep.length = 0;
1730    rep.sequenceNumber = client->sequence;
1731    rep.success = MappingSuccess;
1732    map = (BYTE *)&stuff[1];
1733
1734    /* So we're bounded here by the number of core buttons.  This check
1735     * probably wants disabling through XFixes. */
1736    /* MPX: With ClientPointer, we can return the right number of buttons.
1737     * Let's just hope nobody changed ClientPointer between GetPointerMapping
1738     * and SetPointerMapping
1739     */
1740    if (stuff->nElts != ptr->button->numButtons) {
1741	client->errorValue = stuff->nElts;
1742	return BadValue;
1743    }
1744
1745    /* Core protocol specs don't allow for duplicate mappings; this check
1746     * almost certainly wants disabling through XFixes too. */
1747    for (i = 0; i < stuff->nElts; i++) {
1748        for (j = i + 1; j < stuff->nElts; j++) {
1749            if (map[i] && map[i] == map[j]) {
1750                client->errorValue = map[i];
1751                return BadValue;
1752            }
1753        }
1754    }
1755
1756    ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
1757    if (ret == MappingBusy)
1758        rep.success = ret;
1759    else if (ret == -1)
1760        return BadValue;
1761    else if (ret != Success)
1762        return ret;
1763
1764    WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
1765    return Success;
1766}
1767
1768int
1769ProcGetKeyboardMapping(ClientPtr client)
1770{
1771    xGetKeyboardMappingReply rep;
1772    DeviceIntPtr kbd = PickKeyboard(client);
1773    XkbDescPtr xkb;
1774    KeySymsPtr syms;
1775    int rc;
1776    REQUEST(xGetKeyboardMappingReq);
1777    REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
1778
1779    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
1780    if (rc != Success)
1781	return rc;
1782
1783    xkb = kbd->key->xkbInfo->desc;
1784
1785    if ((stuff->firstKeyCode < xkb->min_key_code) ||
1786        (stuff->firstKeyCode > xkb->max_key_code)) {
1787	client->errorValue = stuff->firstKeyCode;
1788	return BadValue;
1789    }
1790    if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) {
1791	client->errorValue = stuff->count;
1792        return BadValue;
1793    }
1794
1795    syms = XkbGetCoreMap(kbd);
1796    if (!syms)
1797        return BadAlloc;
1798
1799    memset(&rep, 0, sizeof(xGetKeyboardMappingReply));
1800    rep.type = X_Reply;
1801    rep.sequenceNumber = client->sequence;
1802    rep.keySymsPerKeyCode = syms->mapWidth;
1803    /* length is a count of 4 byte quantities and KeySyms are 4 bytes */
1804    rep.length = syms->mapWidth * stuff->count;
1805    WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
1806    client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
1807    WriteSwappedDataToClient(client,
1808                             syms->mapWidth * stuff->count * sizeof(KeySym),
1809                             &syms->map[syms->mapWidth * (stuff->firstKeyCode -
1810                                                          syms->minKeyCode)]);
1811    free(syms->map);
1812    free(syms);
1813
1814    return Success;
1815}
1816
1817int
1818ProcGetPointerMapping(ClientPtr client)
1819{
1820    xGetPointerMappingReply rep;
1821    /* Apps may get different values each time they call GetPointerMapping as
1822     * the ClientPointer could change. */
1823    DeviceIntPtr ptr = PickPointer(client);
1824    ButtonClassPtr butc = ptr->button;
1825    int rc;
1826    REQUEST_SIZE_MATCH(xReq);
1827
1828    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
1829    if (rc != Success)
1830	return rc;
1831
1832    rep.type = X_Reply;
1833    rep.sequenceNumber = client->sequence;
1834    rep.nElts = (butc) ? butc->numButtons : 0;
1835    rep.length = ((unsigned)rep.nElts + (4-1))/4;
1836    WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
1837    if (butc)
1838        WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
1839    return Success;
1840}
1841
1842void
1843NoteLedState(DeviceIntPtr keybd, int led, Bool on)
1844{
1845    KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
1846    if (on)
1847	ctrl->leds |= ((Leds)1 << (led - 1));
1848    else
1849	ctrl->leds &= ~((Leds)1 << (led - 1));
1850}
1851
1852int
1853Ones(unsigned long mask)             /* HACKMEM 169 */
1854{
1855    unsigned long y;
1856
1857    y = (mask >> 1) &033333333333;
1858    y = mask - y - ((y >>1) & 033333333333);
1859    return (((y + (y >> 3)) & 030707070707) % 077);
1860}
1861
1862static int
1863DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
1864                         BITS32 vmask)
1865{
1866#define DO_ALL    (-1)
1867    KeybdCtrl ctrl;
1868    int t;
1869    int led = DO_ALL;
1870    int key = DO_ALL;
1871    BITS32 index2;
1872    int mask = vmask, i;
1873    XkbEventCauseRec cause;
1874
1875    ctrl = keybd->kbdfeed->ctrl;
1876    while (vmask) {
1877	index2 = (BITS32) lowbit (vmask);
1878	vmask &= ~index2;
1879	switch (index2) {
1880	case KBKeyClickPercent:
1881	    t = (INT8)*vlist;
1882	    vlist++;
1883	    if (t == -1) {
1884		t = defaultKeyboardControl.click;
1885            }
1886	    else if (t < 0 || t > 100) {
1887		client->errorValue = t;
1888		return BadValue;
1889	    }
1890	    ctrl.click = t;
1891	    break;
1892	case KBBellPercent:
1893	    t = (INT8)*vlist;
1894	    vlist++;
1895	    if (t == -1) {
1896		t = defaultKeyboardControl.bell;
1897            }
1898	    else if (t < 0 || t > 100) {
1899		client->errorValue = t;
1900		return BadValue;
1901	    }
1902	    ctrl.bell = t;
1903	    break;
1904	case KBBellPitch:
1905	    t = (INT16)*vlist;
1906	    vlist++;
1907	    if (t == -1) {
1908		t = defaultKeyboardControl.bell_pitch;
1909            }
1910	    else if (t < 0) {
1911		client->errorValue = t;
1912		return BadValue;
1913	    }
1914	    ctrl.bell_pitch = t;
1915	    break;
1916	case KBBellDuration:
1917	    t = (INT16)*vlist;
1918	    vlist++;
1919	    if (t == -1)
1920		t = defaultKeyboardControl.bell_duration;
1921	    else if (t < 0) {
1922		client->errorValue = t;
1923		return BadValue;
1924	    }
1925	    ctrl.bell_duration = t;
1926	    break;
1927	case KBLed:
1928	    led = (CARD8)*vlist;
1929	    vlist++;
1930	    if (led < 1 || led > 32) {
1931		client->errorValue = led;
1932		return BadValue;
1933	    }
1934	    if (!(mask & KBLedMode))
1935		return BadMatch;
1936	    break;
1937	case KBLedMode:
1938	    t = (CARD8)*vlist;
1939	    vlist++;
1940	    if (t == LedModeOff) {
1941		if (led == DO_ALL)
1942		    ctrl.leds = 0x0;
1943		else
1944		    ctrl.leds &= ~(((Leds)(1)) << (led - 1));
1945	    }
1946	    else if (t == LedModeOn) {
1947		if (led == DO_ALL)
1948		    ctrl.leds = ~0L;
1949		else
1950		    ctrl.leds |= (((Leds)(1)) << (led - 1));
1951	    }
1952	    else {
1953		client->errorValue = t;
1954		return BadValue;
1955	    }
1956
1957            XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client);
1958            XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))),
1959 			     ctrl.leds, &cause);
1960            ctrl.leds = keybd->kbdfeed->ctrl.leds;
1961
1962	    break;
1963	case KBKey:
1964	    key = (KeyCode)*vlist;
1965	    vlist++;
1966	    if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code ||
1967		(KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) {
1968		client->errorValue = key;
1969		return BadValue;
1970	    }
1971	    if (!(mask & KBAutoRepeatMode))
1972		return BadMatch;
1973	    break;
1974	case KBAutoRepeatMode:
1975	    i = (key >> 3);
1976	    mask = (1 << (key & 7));
1977	    t = (CARD8)*vlist;
1978	    vlist++;
1979            if (key != DO_ALL)
1980                XkbDisableComputedAutoRepeats(keybd,key);
1981	    if (t == AutoRepeatModeOff) {
1982		if (key == DO_ALL)
1983		    ctrl.autoRepeat = FALSE;
1984		else
1985		    ctrl.autoRepeats[i] &= ~mask;
1986	    }
1987	    else if (t == AutoRepeatModeOn) {
1988		if (key == DO_ALL)
1989		    ctrl.autoRepeat = TRUE;
1990		else
1991		    ctrl.autoRepeats[i] |= mask;
1992	    }
1993	    else if (t == AutoRepeatModeDefault) {
1994		if (key == DO_ALL)
1995		    ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
1996		else
1997		    ctrl.autoRepeats[i] =
1998			    (ctrl.autoRepeats[i] & ~mask) |
1999			    (defaultKeyboardControl.autoRepeats[i] & mask);
2000	    }
2001	    else {
2002		client->errorValue = t;
2003		return BadValue;
2004	    }
2005	    break;
2006	default:
2007	    client->errorValue = mask;
2008	    return BadValue;
2009	}
2010    }
2011    keybd->kbdfeed->ctrl = ctrl;
2012
2013    /* The XKB RepeatKeys control and core protocol global autorepeat */
2014    /* value are linked	*/
2015    XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
2016
2017    return Success;
2018
2019#undef DO_ALL
2020}
2021
2022/**
2023 * Changes kbd control on the ClientPointer and all attached SDs.
2024 */
2025int
2026ProcChangeKeyboardControl (ClientPtr client)
2027{
2028    XID *vlist;
2029    BITS32 vmask;
2030    int ret = Success, error = Success;
2031    DeviceIntPtr pDev = NULL, keyboard;
2032    REQUEST(xChangeKeyboardControlReq);
2033
2034    REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
2035
2036    vmask = stuff->mask;
2037    vlist = (XID *)&stuff[1];
2038
2039    if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask))
2040	return BadLength;
2041
2042    keyboard = PickKeyboard(client);
2043
2044    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2045        if ((pDev == keyboard ||
2046	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2047	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2048            ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
2049	    if (ret != Success)
2050                return ret;
2051        }
2052    }
2053
2054    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2055        if ((pDev == keyboard ||
2056	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2057	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2058            ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
2059            if (ret != Success)
2060                error = ret;
2061        }
2062    }
2063
2064    return error;
2065}
2066
2067int
2068ProcGetKeyboardControl (ClientPtr client)
2069{
2070    int rc, i;
2071    DeviceIntPtr kbd = PickKeyboard(client);
2072    KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
2073    xGetKeyboardControlReply rep;
2074    REQUEST_SIZE_MATCH(xReq);
2075
2076    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
2077    if (rc != Success)
2078	return rc;
2079
2080    rep.type = X_Reply;
2081    rep.length = 5;
2082    rep.sequenceNumber = client->sequence;
2083    rep.globalAutoRepeat = ctrl->autoRepeat;
2084    rep.keyClickPercent = ctrl->click;
2085    rep.bellPercent = ctrl->bell;
2086    rep.bellPitch = ctrl->bell_pitch;
2087    rep.bellDuration = ctrl->bell_duration;
2088    rep.ledMask = ctrl->leds;
2089    for (i = 0; i < 32; i++)
2090	rep.map[i] = ctrl->autoRepeats[i];
2091    WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
2092    return Success;
2093}
2094
2095int
2096ProcBell(ClientPtr client)
2097{
2098    DeviceIntPtr dev, keybd = PickKeyboard(client);
2099    int base = keybd->kbdfeed->ctrl.bell;
2100    int newpercent;
2101    int rc;
2102    REQUEST(xBellReq);
2103    REQUEST_SIZE_MATCH(xBellReq);
2104
2105    if (stuff->percent < -100 || stuff->percent > 100) {
2106	client->errorValue = stuff->percent;
2107	return BadValue;
2108    }
2109
2110    newpercent = (base * stuff->percent) / 100;
2111    if (stuff->percent < 0)
2112        newpercent = base + newpercent;
2113    else
2114	newpercent = base - newpercent + stuff->percent;
2115
2116    for (dev = inputInfo.devices; dev; dev = dev->next) {
2117        if ((dev == keybd ||
2118	     (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) &&
2119            dev->kbdfeed && dev->kbdfeed->BellProc) {
2120
2121	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess);
2122	    if (rc != Success)
2123		return rc;
2124            XkbHandleBell(FALSE, FALSE, dev, newpercent,
2125                          &dev->kbdfeed->ctrl, 0, None, NULL, client);
2126        }
2127    }
2128
2129    return Success;
2130}
2131
2132int
2133ProcChangePointerControl(ClientPtr client)
2134{
2135    DeviceIntPtr dev, mouse = PickPointer(client);
2136    PtrCtrl ctrl;		/* might get BadValue part way through */
2137    int rc;
2138    REQUEST(xChangePointerControlReq);
2139    REQUEST_SIZE_MATCH(xChangePointerControlReq);
2140
2141    ctrl = mouse->ptrfeed->ctrl;
2142    if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
2143	client->errorValue = stuff->doAccel;
2144	return BadValue;
2145    }
2146    if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
2147	client->errorValue = stuff->doThresh;
2148	return BadValue;
2149    }
2150    if (stuff->doAccel) {
2151	if (stuff->accelNum == -1) {
2152	    ctrl.num = defaultPointerControl.num;
2153        }
2154	else if (stuff->accelNum < 0) {
2155	    client->errorValue = stuff->accelNum;
2156	    return BadValue;
2157	}
2158	else {
2159            ctrl.num = stuff->accelNum;
2160        }
2161
2162	if (stuff->accelDenum == -1) {
2163	    ctrl.den = defaultPointerControl.den;
2164        }
2165	else if (stuff->accelDenum <= 0) {
2166	    client->errorValue = stuff->accelDenum;
2167	    return BadValue;
2168	}
2169	else {
2170            ctrl.den = stuff->accelDenum;
2171        }
2172    }
2173    if (stuff->doThresh) {
2174	if (stuff->threshold == -1) {
2175	    ctrl.threshold = defaultPointerControl.threshold;
2176        }
2177	else if (stuff->threshold < 0) {
2178	    client->errorValue = stuff->threshold;
2179	    return BadValue;
2180	}
2181	else {
2182            ctrl.threshold = stuff->threshold;
2183        }
2184    }
2185
2186    for (dev = inputInfo.devices; dev; dev = dev->next) {
2187        if ((dev == mouse ||
2188	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2189            dev->ptrfeed) {
2190	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
2191	    if (rc != Success)
2192		return rc;
2193	}
2194    }
2195
2196    for (dev = inputInfo.devices; dev; dev = dev->next) {
2197        if ((dev == mouse ||
2198	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2199            dev->ptrfeed) {
2200            dev->ptrfeed->ctrl = ctrl;
2201        }
2202    }
2203
2204    return Success;
2205}
2206
2207int
2208ProcGetPointerControl(ClientPtr client)
2209{
2210    DeviceIntPtr ptr = PickPointer(client);
2211    PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
2212    xGetPointerControlReply rep;
2213    int rc;
2214    REQUEST_SIZE_MATCH(xReq);
2215
2216    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
2217    if (rc != Success)
2218	return rc;
2219
2220    rep.type = X_Reply;
2221    rep.length = 0;
2222    rep.sequenceNumber = client->sequence;
2223    rep.threshold = ctrl->threshold;
2224    rep.accelNumerator = ctrl->num;
2225    rep.accelDenominator = ctrl->den;
2226    WriteReplyToClient(client, sizeof(xGenericReply), &rep);
2227    return Success;
2228}
2229
2230void
2231MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
2232{
2233    GrabPtr grab = dev->deviceGrab.grab;
2234
2235    if ((grab && SameClient(grab, client) &&
2236	 ((grab->eventMask & PointerMotionHintMask) ||
2237	  (grab->ownerEvents &&
2238	   (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2239	    PointerMotionHintMask)))) ||
2240	(!grab &&
2241	 (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2242	  PointerMotionHintMask)))
2243	dev->valuator->motionHintWindow = NullWindow;
2244}
2245
2246int
2247ProcGetMotionEvents(ClientPtr client)
2248{
2249    WindowPtr pWin;
2250    xTimecoord * coords = (xTimecoord *) NULL;
2251    xGetMotionEventsReply rep;
2252    int i, count, xmin, xmax, ymin, ymax, rc;
2253    unsigned long nEvents;
2254    DeviceIntPtr mouse = PickPointer(client);
2255    TimeStamp start, stop;
2256    REQUEST(xGetMotionEventsReq);
2257    REQUEST_SIZE_MATCH(xGetMotionEventsReq);
2258
2259    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2260    if (rc != Success)
2261	return rc;
2262    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
2263    if (rc != Success)
2264	return rc;
2265
2266    if (mouse->valuator->motionHintWindow)
2267	MaybeStopHint(mouse, client);
2268    rep.type = X_Reply;
2269    rep.sequenceNumber = client->sequence;
2270    nEvents = 0;
2271    start = ClientTimeToServerTime(stuff->start);
2272    stop = ClientTimeToServerTime(stuff->stop);
2273    if ((CompareTimeStamps(start, stop) != LATER) &&
2274	(CompareTimeStamps(start, currentTime) != LATER) &&
2275	mouse->valuator->numMotionEvents)
2276    {
2277	if (CompareTimeStamps(stop, currentTime) == LATER)
2278	    stop = currentTime;
2279	count = GetMotionHistory(mouse, &coords, start.milliseconds,
2280				 stop.milliseconds, pWin->drawable.pScreen,
2281                                 TRUE);
2282	xmin = pWin->drawable.x - wBorderWidth (pWin);
2283	xmax = pWin->drawable.x + (int)pWin->drawable.width +
2284		wBorderWidth (pWin);
2285	ymin = pWin->drawable.y - wBorderWidth (pWin);
2286	ymax = pWin->drawable.y + (int)pWin->drawable.height +
2287		wBorderWidth (pWin);
2288	for (i = 0; i < count; i++)
2289	    if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
2290		    (ymin <= coords[i].y) && (coords[i].y < ymax))
2291	    {
2292		coords[nEvents].time = coords[i].time;
2293		coords[nEvents].x = coords[i].x - pWin->drawable.x;
2294		coords[nEvents].y = coords[i].y - pWin->drawable.y;
2295		nEvents++;
2296	    }
2297    }
2298    rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord));
2299    rep.nEvents = nEvents;
2300    WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
2301    if (nEvents)
2302    {
2303	client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
2304	WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
2305				 (char *)coords);
2306    }
2307    free(coords);
2308    return Success;
2309}
2310
2311int
2312ProcQueryKeymap(ClientPtr client)
2313{
2314    xQueryKeymapReply rep;
2315    int rc, i;
2316    DeviceIntPtr keybd = PickKeyboard(client);
2317    CARD8 *down = keybd->key->down;
2318
2319    REQUEST_SIZE_MATCH(xReq);
2320    rep.type = X_Reply;
2321    rep.sequenceNumber = client->sequence;
2322    rep.length = 2;
2323
2324    rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
2325    if (rc != Success && rc != BadAccess)
2326	return rc;
2327
2328    for (i = 0; i<32; i++)
2329	rep.map[i] = down[i];
2330
2331    if (rc == BadAccess)
2332	memset(rep.map, 0, 32);
2333
2334    WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
2335
2336   return Success;
2337}
2338
2339
2340/**
2341 * Recalculate the number of buttons for the master device. The number of
2342 * buttons on the master device is equal to the number of buttons on the
2343 * slave device with the highest number of buttons.
2344 */
2345static void
2346RecalculateMasterButtons(DeviceIntPtr slave)
2347{
2348    DeviceIntPtr dev, master;
2349    int maxbuttons = 0;
2350
2351    if (!slave->button || IsMaster(slave))
2352        return;
2353
2354    master = GetMaster(slave, MASTER_POINTER);
2355    if (!master)
2356        return;
2357
2358    for (dev = inputInfo.devices; dev; dev = dev->next)
2359    {
2360        if (IsMaster(dev) ||
2361            dev->u.master != master ||
2362            !dev->button)
2363            continue;
2364
2365        maxbuttons = max(maxbuttons, dev->button->numButtons);
2366    }
2367
2368    if (master->button && master->button->numButtons != maxbuttons)
2369    {
2370        int i;
2371        DeviceChangedEvent event;
2372
2373        memset(&event, 0, sizeof(event));
2374
2375        master->button->numButtons = maxbuttons;
2376
2377        event.header = ET_Internal;
2378        event.type = ET_DeviceChanged;
2379        event.time = GetTimeInMillis();
2380        event.deviceid = master->id;
2381        event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE;
2382        event.buttons.num_buttons = maxbuttons;
2383        memcpy(&event.buttons.names, master->button->labels, maxbuttons *
2384                sizeof(Atom));
2385
2386        if (master->valuator)
2387        {
2388            event.num_valuators = master->valuator->numAxes;
2389            for (i = 0; i < event.num_valuators; i++)
2390            {
2391                event.valuators[i].min = master->valuator->axes[i].min_value;
2392                event.valuators[i].max = master->valuator->axes[i].max_value;
2393                event.valuators[i].resolution = master->valuator->axes[i].resolution;
2394                event.valuators[i].mode = master->valuator->axes[i].mode;
2395                event.valuators[i].name = master->valuator->axes[i].label;
2396            }
2397        }
2398
2399        if (master->key)
2400        {
2401            event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code;
2402            event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code;
2403        }
2404
2405        XISendDeviceChangedEvent(master, master, &event);
2406    }
2407}
2408
2409/**
2410 * Generate release events for all keys/button currently down on this
2411 * device.
2412 */
2413void
2414ReleaseButtonsAndKeys(DeviceIntPtr dev)
2415{
2416    EventListPtr        eventlist = InitEventList(GetMaximumEventsNum());
2417    ButtonClassPtr      b = dev->button;
2418    KeyClassPtr         k = dev->key;
2419    int                 i, j, nevents;
2420
2421    if (!eventlist) /* no release events for you */
2422        return;
2423
2424    /* Release all buttons */
2425    for (i = 0; b && i < b->numButtons; i++)
2426    {
2427        if (BitIsOn(b->down, i))
2428        {
2429            nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
2430            for (j = 0; j < nevents; j++)
2431                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2432        }
2433    }
2434
2435    /* Release all keys */
2436    for (i = 0; k && i < MAP_LENGTH; i++)
2437    {
2438        if (BitIsOn(k->down, i))
2439        {
2440            nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
2441            for (j = 0; j < nevents; j++)
2442                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2443        }
2444    }
2445
2446    FreeEventList(eventlist, GetMaximumEventsNum());
2447}
2448
2449/**
2450 * Attach device 'dev' to device 'master'.
2451 * Client is set to the client that issued the request, or NULL if it comes
2452 * from some internal automatic pairing.
2453 *
2454 * Master may be NULL to set the device floating.
2455 *
2456 * We don't allow multi-layer hierarchies right now. You can't attach a slave
2457 * to another slave.
2458 */
2459int
2460AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
2461{
2462    ScreenPtr screen;
2463    DeviceIntPtr oldmaster;
2464    if (!dev || IsMaster(dev))
2465        return BadDevice;
2466
2467    if (master && !IsMaster(master)) /* can't attach to slaves */
2468        return BadDevice;
2469
2470    /* set from floating to floating? */
2471    if (!dev->u.master && !master && dev->enabled)
2472        return Success;
2473
2474    /* free the existing sprite. */
2475    if (!dev->u.master && dev->spriteInfo->paired == dev)
2476    {
2477        screen = miPointerGetScreen(dev);
2478        screen->DeviceCursorCleanup(dev, screen);
2479        free(dev->spriteInfo->sprite);
2480    }
2481
2482    oldmaster = dev->u.master;
2483    dev->u.master = master;
2484
2485    /* If device is set to floating, we need to create a sprite for it,
2486     * otherwise things go bad. However, we don't want to render the cursor,
2487     * so we reset spriteOwner.
2488     * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
2489     * alloc new memory but overwrite the previous one.
2490     */
2491    if (!master)
2492    {
2493        WindowPtr currentRoot;
2494
2495        if (dev->spriteInfo->sprite)
2496            currentRoot = GetCurrentRootWindow(dev);
2497        else /* new device auto-set to floating */
2498            currentRoot = screenInfo.screens[0]->root;
2499
2500        /* we need to init a fake sprite */
2501        screen = currentRoot->drawable.pScreen;
2502        screen->DeviceCursorInitialize(dev, screen);
2503        dev->spriteInfo->sprite = NULL;
2504        InitializeSprite(dev, currentRoot);
2505        dev->spriteInfo->spriteOwner = FALSE;
2506        dev->spriteInfo->paired = dev;
2507    } else
2508    {
2509        dev->spriteInfo->sprite = master->spriteInfo->sprite;
2510        dev->spriteInfo->paired = master;
2511        dev->spriteInfo->spriteOwner = FALSE;
2512
2513        RecalculateMasterButtons(master);
2514    }
2515
2516    /* XXX: in theory, the MD should change back to its old, original
2517     * classes when the last SD is detached. Thanks to the XTEST devices,
2518     * we'll always have an SD attached until the MD is removed.
2519     * So let's not worry about that.
2520     */
2521
2522    return Success;
2523}
2524
2525/**
2526 * Return the device paired with the given device or NULL.
2527 * Returns the device paired with the parent master if the given device is a
2528 * slave device.
2529 */
2530DeviceIntPtr
2531GetPairedDevice(DeviceIntPtr dev)
2532{
2533    if (!IsMaster(dev) && dev->u.master)
2534        dev = dev->u.master;
2535
2536    return dev->spriteInfo->paired;
2537}
2538
2539
2540/**
2541 * Returns the right master for the type of event needed. If the event is a
2542 * keyboard event.
2543 * This function may be called with a master device as argument. If so, the
2544 * returned master is either the device itself or the paired master device.
2545 * If dev is a floating slave device, NULL is returned.
2546 *
2547 * @type ::MASTER_KEYBOARD or ::MASTER_POINTER
2548 */
2549DeviceIntPtr
2550GetMaster(DeviceIntPtr dev, int which)
2551{
2552    DeviceIntPtr master;
2553
2554    if (IsMaster(dev))
2555        master = dev;
2556    else
2557        master = dev->u.master;
2558
2559    if (master)
2560    {
2561        if (which == MASTER_KEYBOARD)
2562        {
2563            if (master->type != MASTER_KEYBOARD)
2564                master = GetPairedDevice(master);
2565        } else
2566        {
2567            if (master->type != MASTER_POINTER)
2568                master = GetPairedDevice(master);
2569        }
2570    }
2571
2572    return master;
2573}
2574
2575/**
2576 * Create a new device pair (== one pointer, one keyboard device).
2577 * Only allocates the devices, you will need to call ActivateDevice() and
2578 * EnableDevice() manually.
2579 * Either a master or a slave device can be created depending on
2580 * the value for master.
2581 */
2582int
2583AllocDevicePair (ClientPtr client, char* name,
2584                 DeviceIntPtr* ptr,
2585                 DeviceIntPtr* keybd,
2586                 DeviceProc ptr_proc,
2587                 DeviceProc keybd_proc,
2588                 Bool master)
2589{
2590    DeviceIntPtr pointer;
2591    DeviceIntPtr keyboard;
2592    *ptr = *keybd = NULL;
2593
2594    pointer = AddInputDevice(client, ptr_proc, TRUE);
2595    if (!pointer)
2596        return BadAlloc;
2597
2598    if (asprintf(&pointer->name, "%s pointer", name) == -1) {
2599        pointer->name = NULL;
2600        RemoveDevice(pointer, FALSE);
2601        return BadAlloc;
2602    }
2603
2604    pointer->public.processInputProc = ProcessOtherEvent;
2605    pointer->public.realInputProc = ProcessOtherEvent;
2606    XkbSetExtension(pointer, ProcessPointerEvent);
2607    pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
2608    pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
2609    pointer->coreEvents = TRUE;
2610    pointer->spriteInfo->spriteOwner = TRUE;
2611
2612    pointer->u.lastSlave = NULL;
2613    pointer->last.slave = NULL;
2614    pointer->type = (master) ? MASTER_POINTER : SLAVE;
2615
2616    keyboard = AddInputDevice(client, keybd_proc, TRUE);
2617    if (!keyboard)
2618    {
2619        RemoveDevice(pointer, FALSE);
2620        return BadAlloc;
2621    }
2622
2623    if (asprintf(&keyboard->name, "%s keyboard", name) == -1) {
2624        keyboard->name = NULL;
2625        RemoveDevice(keyboard, FALSE);
2626        RemoveDevice(pointer, FALSE);
2627        return BadAlloc;
2628    }
2629
2630    keyboard->public.processInputProc = ProcessOtherEvent;
2631    keyboard->public.realInputProc = ProcessOtherEvent;
2632    XkbSetExtension(keyboard, ProcessKeyboardEvent);
2633    keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
2634    keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
2635    keyboard->coreEvents = TRUE;
2636    keyboard->spriteInfo->spriteOwner = FALSE;
2637
2638    keyboard->u.lastSlave = NULL;
2639    keyboard->last.slave = NULL;
2640    keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
2641
2642    /* The ClassesRec stores the device classes currently not used. */
2643    pointer->unused_classes = calloc(1, sizeof(ClassesRec));
2644    keyboard->unused_classes = calloc(1, sizeof(ClassesRec));
2645
2646    *ptr = pointer;
2647    *keybd = keyboard;
2648
2649    return Success;
2650}
2651
2652/**
2653 * Return Relative or Absolute for the device.
2654 */
2655int valuator_get_mode(DeviceIntPtr dev, int axis)
2656{
2657    return (dev->valuator->axes[axis].mode & DeviceMode);
2658}
2659
2660/**
2661 * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then
2662 * set the mode for all axes.
2663 */
2664void valuator_set_mode(DeviceIntPtr dev, int axis, int mode)
2665{
2666    if (axis != VALUATOR_MODE_ALL_AXES)
2667        dev->valuator->axes[axis].mode = mode;
2668    else {
2669        int i;
2670        for (i = 0; i < dev->valuator->numAxes; i++)
2671            dev->valuator->axes[i].mode = mode;
2672    }
2673}
2674