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