1706f2543Smrg/************************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1987, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543Smrg
26706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27706f2543Smrg
28706f2543Smrg                        All Rights Reserved
29706f2543Smrg
30706f2543SmrgPermission to use, copy, modify, and distribute this software and its
31706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
32706f2543Smrgprovided that the above copyright notice appear in all copies and that
33706f2543Smrgboth that copyright notice and this permission notice appear in
34706f2543Smrgsupporting documentation, and that the name of Digital not be
35706f2543Smrgused in advertising or publicity pertaining to distribution of the
36706f2543Smrgsoftware without specific, written prior permission.
37706f2543Smrg
38706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44706f2543SmrgSOFTWARE.
45706f2543Smrg
46706f2543Smrg********************************************************/
47706f2543Smrg
48706f2543Smrg
49706f2543Smrg
50706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
51706f2543Smrg#include <dix-config.h>
52706f2543Smrg#endif
53706f2543Smrg
54706f2543Smrg#include <X11/X.h>
55706f2543Smrg#include "misc.h"
56706f2543Smrg#include "resource.h"
57706f2543Smrg#include <X11/Xproto.h>
58706f2543Smrg#include <X11/Xatom.h>
59706f2543Smrg#include "windowstr.h"
60706f2543Smrg#include "inputstr.h"
61706f2543Smrg#include "scrnintstr.h"
62706f2543Smrg#include "cursorstr.h"
63706f2543Smrg#include "dixstruct.h"
64706f2543Smrg#include "ptrveloc.h"
65706f2543Smrg#include "site.h"
66706f2543Smrg#include "xkbsrv.h"
67706f2543Smrg#include "privates.h"
68706f2543Smrg#include "xace.h"
69706f2543Smrg#include "mi.h"
70706f2543Smrg
71706f2543Smrg#include "dispatch.h"
72706f2543Smrg#include "swaprep.h"
73706f2543Smrg#include "dixevents.h"
74706f2543Smrg#include "mipointer.h"
75706f2543Smrg#include "eventstr.h"
76706f2543Smrg
77706f2543Smrg#include <X11/extensions/XI.h>
78706f2543Smrg#include <X11/extensions/XI2.h>
79706f2543Smrg#include <X11/extensions/XIproto.h>
80706f2543Smrg#include <math.h>
81706f2543Smrg#include <pixman.h>
82706f2543Smrg#include "exglobals.h"
83706f2543Smrg#include "exevents.h"
84706f2543Smrg#include "xiquerydevice.h" /* for SizeDeviceClasses */
85706f2543Smrg#include "xiproperty.h"
86706f2543Smrg#include "enterleave.h" /* for EnterWindow() */
87706f2543Smrg#include "xserver-properties.h"
88706f2543Smrg#include "xichangehierarchy.h" /* For XISendDeviceHierarchyEvent */
89706f2543Smrg
90706f2543Smrg/** @file
91706f2543Smrg * This file handles input device-related stuff.
92706f2543Smrg */
93706f2543Smrg
94706f2543Smrgstatic void RecalculateMasterButtons(DeviceIntPtr slave);
95706f2543Smrg
96706f2543Smrgstatic void
97706f2543SmrgDeviceSetTransform(DeviceIntPtr dev, float *transform)
98706f2543Smrg{
99706f2543Smrg    struct pixman_f_transform scale;
100706f2543Smrg    double sx, sy;
101706f2543Smrg    int x, y;
102706f2543Smrg
103706f2543Smrg    /**
104706f2543Smrg     * calculate combined transformation matrix:
105706f2543Smrg     *
106706f2543Smrg     * M = InvScale * Transform * Scale
107706f2543Smrg     *
108706f2543Smrg     * So we can later transform points using M * p
109706f2543Smrg     *
110706f2543Smrg     * Where:
111706f2543Smrg     *  Scale scales coordinates into 0..1 range
112706f2543Smrg     *  Transform is the user supplied (affine) transform
113706f2543Smrg     *  InvScale scales coordinates back up into their native range
114706f2543Smrg     */
115706f2543Smrg    sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value;
116706f2543Smrg    sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value;
117706f2543Smrg
118706f2543Smrg    /* invscale */
119706f2543Smrg    pixman_f_transform_init_scale(&scale, sx, sy);
120706f2543Smrg    scale.m[0][2] = dev->valuator->axes[0].min_value;
121706f2543Smrg    scale.m[1][2] = dev->valuator->axes[1].min_value;
122706f2543Smrg
123706f2543Smrg    /* transform */
124706f2543Smrg    for (y=0; y<3; y++)
125706f2543Smrg        for (x=0; x<3; x++)
126706f2543Smrg            dev->transform.m[y][x] = *transform++;
127706f2543Smrg
128706f2543Smrg    pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform);
129706f2543Smrg
130706f2543Smrg    /* scale */
131706f2543Smrg    pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
132706f2543Smrg    scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
133706f2543Smrg    scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;
134706f2543Smrg
135706f2543Smrg    pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale);
136706f2543Smrg}
137706f2543Smrg
138706f2543Smrg/**
139706f2543Smrg * DIX property handler.
140706f2543Smrg */
141706f2543Smrgstatic int
142706f2543SmrgDeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
143706f2543Smrg                  BOOL checkonly)
144706f2543Smrg{
145706f2543Smrg    if (property == XIGetKnownProperty(XI_PROP_ENABLED))
146706f2543Smrg    {
147706f2543Smrg        if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1)
148706f2543Smrg            return BadValue;
149706f2543Smrg
150706f2543Smrg        /* Don't allow disabling of VCP/VCK */
151706f2543Smrg        if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) &&
152706f2543Smrg            !(*(CARD8*)prop->data))
153706f2543Smrg            return BadAccess;
154706f2543Smrg
155706f2543Smrg        if (!checkonly)
156706f2543Smrg        {
157706f2543Smrg            if ((*((CARD8*)prop->data)) && !dev->enabled)
158706f2543Smrg                EnableDevice(dev, TRUE);
159706f2543Smrg            else if (!(*((CARD8*)prop->data)) && dev->enabled)
160706f2543Smrg                DisableDevice(dev, TRUE);
161706f2543Smrg        }
162706f2543Smrg    } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM))
163706f2543Smrg    {
164706f2543Smrg        float *f = (float*)prop->data;
165706f2543Smrg        int i;
166706f2543Smrg
167706f2543Smrg        if (prop->format != 32 || prop->size != 9 ||
168706f2543Smrg            prop->type != XIGetKnownProperty(XATOM_FLOAT))
169706f2543Smrg            return BadValue;
170706f2543Smrg
171706f2543Smrg        for (i=0; i<9; i++)
172706f2543Smrg            if (!isfinite(f[i]))
173706f2543Smrg                return BadValue;
174706f2543Smrg
175706f2543Smrg        if (!checkonly)
176706f2543Smrg            DeviceSetTransform(dev, f);
177706f2543Smrg    }
178706f2543Smrg
179706f2543Smrg    return Success;
180706f2543Smrg}
181706f2543Smrg
182706f2543Smrg/* Pair the keyboard to the pointer device. Keyboard events will follow the
183706f2543Smrg * pointer sprite. Only applicable for master devices.
184706f2543Smrg * If the client is set, the request to pair comes from some client. In this
185706f2543Smrg * case, we need to check for access. If the client is NULL, it's from an
186706f2543Smrg * internal automatic pairing, we must always permit this.
187706f2543Smrg */
188706f2543Smrgstatic int
189706f2543SmrgPairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
190706f2543Smrg{
191706f2543Smrg    if (!ptr)
192706f2543Smrg        return BadDevice;
193706f2543Smrg
194706f2543Smrg    /* Don't allow pairing for slave devices */
195706f2543Smrg    if (!IsMaster(ptr) || !IsMaster(kbd))
196706f2543Smrg        return BadDevice;
197706f2543Smrg
198706f2543Smrg    if (ptr->spriteInfo->paired)
199706f2543Smrg        return BadDevice;
200706f2543Smrg
201706f2543Smrg    if (kbd->spriteInfo->spriteOwner)
202706f2543Smrg    {
203706f2543Smrg        free(kbd->spriteInfo->sprite);
204706f2543Smrg        kbd->spriteInfo->sprite = NULL;
205706f2543Smrg        kbd->spriteInfo->spriteOwner = FALSE;
206706f2543Smrg    }
207706f2543Smrg
208706f2543Smrg    kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
209706f2543Smrg    kbd->spriteInfo->paired = ptr;
210706f2543Smrg    ptr->spriteInfo->paired = kbd;
211706f2543Smrg    return Success;
212706f2543Smrg}
213706f2543Smrg
214706f2543Smrg
215706f2543Smrg/**
216706f2543Smrg * Find and return the next unpaired MD pointer device.
217706f2543Smrg */
218706f2543Smrgstatic DeviceIntPtr
219706f2543SmrgNextFreePointerDevice(void)
220706f2543Smrg{
221706f2543Smrg    DeviceIntPtr dev;
222706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
223706f2543Smrg        if (IsMaster(dev) &&
224706f2543Smrg                dev->spriteInfo->spriteOwner &&
225706f2543Smrg                !dev->spriteInfo->paired)
226706f2543Smrg            return dev;
227706f2543Smrg    return NULL;
228706f2543Smrg}
229706f2543Smrg
230706f2543Smrg/**
231706f2543Smrg * Create a new input device and init it to sane values. The device is added
232706f2543Smrg * to the server's off_devices list.
233706f2543Smrg *
234706f2543Smrg * @param deviceProc Callback for device control function (switch dev on/off).
235706f2543Smrg * @return The newly created device.
236706f2543Smrg */
237706f2543SmrgDeviceIntPtr
238706f2543SmrgAddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
239706f2543Smrg{
240706f2543Smrg    DeviceIntPtr dev, *prev; /* not a typo */
241706f2543Smrg    DeviceIntPtr devtmp;
242706f2543Smrg    int devid;
243706f2543Smrg    char devind[MAXDEVICES];
244706f2543Smrg    BOOL enabled;
245706f2543Smrg    float transform[9];
246706f2543Smrg
247706f2543Smrg    /* Find next available id, 0 and 1 are reserved */
248706f2543Smrg    memset(devind, 0, sizeof(char)*MAXDEVICES);
249706f2543Smrg    for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
250706f2543Smrg	devind[devtmp->id]++;
251706f2543Smrg    for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
252706f2543Smrg	devind[devtmp->id]++;
253706f2543Smrg    for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++)
254706f2543Smrg	;
255706f2543Smrg
256706f2543Smrg    if (devid >= MAXDEVICES)
257706f2543Smrg	return (DeviceIntPtr)NULL;
258706f2543Smrg    dev =  _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
259706f2543Smrg					  sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
260706f2543Smrg					  offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE);
261706f2543Smrg    if (!dev)
262706f2543Smrg	return (DeviceIntPtr)NULL;
263706f2543Smrg    dev->id = devid;
264706f2543Smrg    dev->public.processInputProc = ProcessOtherEvent;
265706f2543Smrg    dev->public.realInputProc = ProcessOtherEvent;
266706f2543Smrg    dev->public.enqueueInputProc = EnqueueEvent;
267706f2543Smrg    dev->deviceProc = deviceProc;
268706f2543Smrg    dev->startup = autoStart;
269706f2543Smrg
270706f2543Smrg    /* device grab defaults */
271706f2543Smrg    dev->deviceGrab.grabTime = currentTime;
272706f2543Smrg    dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
273706f2543Smrg    dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
274706f2543Smrg
275706f2543Smrg    XkbSetExtension(dev, ProcessKeyboardEvent);
276706f2543Smrg
277706f2543Smrg    dev->coreEvents = TRUE;
278706f2543Smrg
279706f2543Smrg    /* sprite defaults */
280706f2543Smrg    dev->spriteInfo = (SpriteInfoPtr)&dev[1];
281706f2543Smrg
282706f2543Smrg    /*  security creation/labeling check
283706f2543Smrg     */
284706f2543Smrg    if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
285706f2543Smrg	free(dev);
286706f2543Smrg	return NULL;
287706f2543Smrg    }
288706f2543Smrg
289706f2543Smrg    inputInfo.numDevices++;
290706f2543Smrg
291706f2543Smrg    for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next)
292706f2543Smrg        ;
293706f2543Smrg    *prev = dev;
294706f2543Smrg    dev->next = NULL;
295706f2543Smrg
296706f2543Smrg    enabled = FALSE;
297706f2543Smrg    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
298706f2543Smrg                           XA_INTEGER, 8, PropModeReplace, 1, &enabled,
299706f2543Smrg                           FALSE);
300706f2543Smrg    XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE);
301706f2543Smrg
302706f2543Smrg    /* unity matrix */
303706f2543Smrg    memset(transform, 0, sizeof(transform));
304706f2543Smrg    transform[0] = transform[4] = transform[8] = 1.0f;
305706f2543Smrg
306706f2543Smrg    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
307706f2543Smrg                           XIGetKnownProperty(XATOM_FLOAT), 32,
308706f2543Smrg                           PropModeReplace, 9, transform, FALSE);
309706f2543Smrg    XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
310706f2543Smrg                                 FALSE);
311706f2543Smrg
312706f2543Smrg    XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
313706f2543Smrg
314706f2543Smrg    return dev;
315706f2543Smrg}
316706f2543Smrg
317706f2543Smrgvoid
318706f2543SmrgSendDevicePresenceEvent(int deviceid, int type)
319706f2543Smrg{
320706f2543Smrg    DeviceIntRec dummyDev;
321706f2543Smrg    devicePresenceNotify ev;
322706f2543Smrg
323706f2543Smrg    memset(&dummyDev, 0, sizeof(DeviceIntRec));
324706f2543Smrg    ev.type = DevicePresenceNotify;
325706f2543Smrg    ev.time = currentTime.milliseconds;
326706f2543Smrg    ev.devchange = type;
327706f2543Smrg    ev.deviceid = deviceid;
328706f2543Smrg    dummyDev.id = XIAllDevices;
329706f2543Smrg    SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
330706f2543Smrg                          (xEvent*)&ev, 1);
331706f2543Smrg}
332706f2543Smrg
333706f2543Smrg/**
334706f2543Smrg * Enable the device through the driver, add the device to the device list.
335706f2543Smrg * Switch device ON through the driver and push it onto the global device
336706f2543Smrg * list. Initialize the DIX sprite or pair the device. All clients are
337706f2543Smrg * notified about the device being enabled.
338706f2543Smrg *
339706f2543Smrg * A master pointer device needs to be enabled before a master keyboard
340706f2543Smrg * device.
341706f2543Smrg *
342706f2543Smrg * @param The device to be enabled.
343706f2543Smrg * @param sendevent True if an XI2 event should be sent.
344706f2543Smrg * @return TRUE on success or FALSE otherwise.
345706f2543Smrg */
346706f2543SmrgBool
347706f2543SmrgEnableDevice(DeviceIntPtr dev, BOOL sendevent)
348706f2543Smrg{
349706f2543Smrg    DeviceIntPtr *prev;
350706f2543Smrg    int ret;
351706f2543Smrg    DeviceIntPtr other;
352706f2543Smrg    BOOL enabled;
353706f2543Smrg    int flags[MAXDEVICES] = {0};
354706f2543Smrg
355706f2543Smrg    for (prev = &inputInfo.off_devices;
356706f2543Smrg	 *prev && (*prev != dev);
357706f2543Smrg	 prev = &(*prev)->next)
358706f2543Smrg	;
359706f2543Smrg
360706f2543Smrg    if (!dev->spriteInfo->sprite)
361706f2543Smrg    {
362706f2543Smrg        if (IsMaster(dev))
363706f2543Smrg        {
364706f2543Smrg            /* Sprites appear on first root window, so we can hardcode it */
365706f2543Smrg            if (dev->spriteInfo->spriteOwner)
366706f2543Smrg            {
367706f2543Smrg                InitializeSprite(dev, screenInfo.screens[0]->root);
368706f2543Smrg                                                 /* mode doesn't matter */
369706f2543Smrg                EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor);
370706f2543Smrg            }
371706f2543Smrg            else if ((other = NextFreePointerDevice()) == NULL)
372706f2543Smrg            {
373706f2543Smrg                ErrorF("[dix] cannot find pointer to pair with. "
374706f2543Smrg                       "This is a bug.\n");
375706f2543Smrg                return FALSE;
376706f2543Smrg            } else
377706f2543Smrg                PairDevices(NULL, other, dev);
378706f2543Smrg        } else
379706f2543Smrg        {
380706f2543Smrg            if (dev->coreEvents)
381706f2543Smrg                other = (IsPointerDevice(dev)) ? inputInfo.pointer :
382706f2543Smrg                    inputInfo.keyboard;
383706f2543Smrg            else
384706f2543Smrg                other = NULL; /* auto-float non-core devices */
385706f2543Smrg            AttachDevice(NULL, dev, other);
386706f2543Smrg        }
387706f2543Smrg    }
388706f2543Smrg
389706f2543Smrg    if ((*prev != dev) || !dev->inited ||
390706f2543Smrg	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
391706f2543Smrg        ErrorF("[dix] couldn't enable device %d\n", dev->id);
392706f2543Smrg	return FALSE;
393706f2543Smrg    }
394706f2543Smrg    dev->enabled = TRUE;
395706f2543Smrg    *prev = dev->next;
396706f2543Smrg
397706f2543Smrg    for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next)
398706f2543Smrg        ;
399706f2543Smrg    *prev = dev;
400706f2543Smrg    dev->next = NULL;
401706f2543Smrg
402706f2543Smrg    enabled = TRUE;
403706f2543Smrg    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
404706f2543Smrg                           XA_INTEGER, 8, PropModeReplace, 1, &enabled,
405706f2543Smrg                           TRUE);
406706f2543Smrg
407706f2543Smrg    SendDevicePresenceEvent(dev->id, DeviceEnabled);
408706f2543Smrg    if (sendevent)
409706f2543Smrg    {
410706f2543Smrg        flags[dev->id] |= XIDeviceEnabled;
411706f2543Smrg        XISendDeviceHierarchyEvent(flags);
412706f2543Smrg    }
413706f2543Smrg
414706f2543Smrg    RecalculateMasterButtons(dev);
415706f2543Smrg
416706f2543Smrg    return TRUE;
417706f2543Smrg}
418706f2543Smrg
419706f2543Smrg/**
420706f2543Smrg * Switch a device off through the driver and push it onto the off_devices
421706f2543Smrg * list. A device will not send events while disabled. All clients are
422706f2543Smrg * notified about the device being disabled.
423706f2543Smrg *
424706f2543Smrg * Master keyboard devices have to be disabled before master pointer devices
425706f2543Smrg * otherwise things turn bad.
426706f2543Smrg *
427706f2543Smrg * @param sendevent True if an XI2 event should be sent.
428706f2543Smrg * @return TRUE on success or FALSE otherwise.
429706f2543Smrg */
430706f2543SmrgBool
431706f2543SmrgDisableDevice(DeviceIntPtr dev, BOOL sendevent)
432706f2543Smrg{
433706f2543Smrg    DeviceIntPtr *prev, other;
434706f2543Smrg    BOOL enabled;
43591d321acSmrg    BOOL dev_in_devices_list = FALSE;
436706f2543Smrg    int flags[MAXDEVICES] = {0};
437706f2543Smrg
43891d321acSmrg    for (other = inputInfo.devices; other; other = other->next) {
43991d321acSmrg        if (other == dev) {
44091d321acSmrg            dev_in_devices_list = TRUE;
44191d321acSmrg            break;
44291d321acSmrg        }
44391d321acSmrg    }
44491d321acSmrg
44591d321acSmrg    if (!dev_in_devices_list)
446706f2543Smrg	return FALSE;
447706f2543Smrg
448706f2543Smrg    /* float attached devices */
449706f2543Smrg    if (IsMaster(dev))
450706f2543Smrg    {
451706f2543Smrg        for (other = inputInfo.devices; other; other = other->next)
452706f2543Smrg        {
453706f2543Smrg            if (other->u.master == dev)
454706f2543Smrg            {
455706f2543Smrg                AttachDevice(NULL, other, NULL);
456706f2543Smrg                flags[other->id] |= XISlaveDetached;
457706f2543Smrg            }
458706f2543Smrg        }
459706f2543Smrg    }
460706f2543Smrg    else
461706f2543Smrg    {
462706f2543Smrg        for (other = inputInfo.devices; other; other = other->next)
463706f2543Smrg        {
464706f2543Smrg	    if (IsMaster(other) && other->u.lastSlave == dev)
465706f2543Smrg		other->u.lastSlave = NULL;
466706f2543Smrg	}
467706f2543Smrg    }
468706f2543Smrg
469706f2543Smrg    if (IsMaster(dev) && dev->spriteInfo->sprite)
470706f2543Smrg    {
471706f2543Smrg        for (other = inputInfo.devices; other; other = other->next)
472706f2543Smrg        {
473706f2543Smrg            if (other->spriteInfo->paired == dev)
474706f2543Smrg            {
475706f2543Smrg                ErrorF("[dix] cannot disable device, still paired. "
476706f2543Smrg                        "This is a bug. \n");
477706f2543Smrg                return FALSE;
478706f2543Smrg            }
479706f2543Smrg        }
480dd8addeeSmrg
481dd8addeeSmrg        for (other = inputInfo.off_devices; other; other = other->next) {
482dd8addeeSmrg	    /*
483dd8addeeSmrg	     * XXXMRG, from newer GetMaster().  The GetMaster() with new
484dd8addeeSmrg	     * MASTER_ATTACHED avoids paired devices, and with this call
485dd8addeeSmrg	     * being !IsMaster() first, dev->u.master is the only answer
486dd8addeeSmrg	     * it can give.
487dd8addeeSmrg	     */
488dd8addeeSmrg            if (!IsMaster(other) && other->u.master == dev) {
489dd8addeeSmrg                AttachDevice(NULL, other, NULL);
490dd8addeeSmrg                flags[other->id] |= XISlaveDetached;
491dd8addeeSmrg            }
492dd8addeeSmrg        }
493706f2543Smrg    }
494706f2543Smrg
495706f2543Smrg    (void)(*dev->deviceProc)(dev, DEVICE_OFF);
496706f2543Smrg    dev->enabled = FALSE;
497706f2543Smrg
498706f2543Smrg    /* now that the device is disabled, we can reset the signal handler's
499706f2543Smrg     * last.slave */
500706f2543Smrg    OsBlockSignals();
501706f2543Smrg    for (other = inputInfo.devices; other; other = other->next)
502706f2543Smrg    {
503706f2543Smrg        if (other->last.slave == dev)
504706f2543Smrg            other->last.slave = NULL;
505706f2543Smrg    }
506706f2543Smrg    OsReleaseSignals();
507706f2543Smrg
508706f2543Smrg    LeaveWindow(dev);
509706f2543Smrg    SetFocusOut(dev);
510706f2543Smrg
51191d321acSmrg    for (prev = &inputInfo.devices;
51291d321acSmrg         *prev && (*prev != dev); prev = &(*prev)->next);
51391d321acSmrg
514706f2543Smrg    *prev = dev->next;
515706f2543Smrg    dev->next = inputInfo.off_devices;
516706f2543Smrg    inputInfo.off_devices = dev;
517706f2543Smrg
518706f2543Smrg    enabled = FALSE;
519706f2543Smrg    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
520706f2543Smrg                           XA_INTEGER, 8, PropModeReplace, 1, &enabled,
521706f2543Smrg                           TRUE);
522706f2543Smrg
523706f2543Smrg    SendDevicePresenceEvent(dev->id, DeviceDisabled);
524706f2543Smrg    if (sendevent)
525706f2543Smrg    {
526706f2543Smrg        flags[dev->id] = XIDeviceDisabled;
527706f2543Smrg        XISendDeviceHierarchyEvent(flags);
528706f2543Smrg    }
529706f2543Smrg
530706f2543Smrg    RecalculateMasterButtons(dev);
531706f2543Smrg
532706f2543Smrg    return TRUE;
533706f2543Smrg}
534706f2543Smrg
535706f2543Smrg/**
536706f2543Smrg * Initialise a new device through the driver and tell all clients about the
537706f2543Smrg * new device.
538706f2543Smrg *
539706f2543Smrg * Must be called before EnableDevice.
540706f2543Smrg * The device will NOT send events until it is enabled!
541706f2543Smrg *
542706f2543Smrg * @param sendevent True if an XI2 event should be sent.
543706f2543Smrg * @return Success or an error code on failure.
544706f2543Smrg */
545706f2543Smrgint
546706f2543SmrgActivateDevice(DeviceIntPtr dev, BOOL sendevent)
547706f2543Smrg{
548706f2543Smrg    int ret = Success;
549706f2543Smrg    ScreenPtr pScreen = screenInfo.screens[0];
550706f2543Smrg
551706f2543Smrg    if (!dev || !dev->deviceProc)
552706f2543Smrg        return BadImplementation;
553706f2543Smrg
554706f2543Smrg    ret = (*dev->deviceProc) (dev, DEVICE_INIT);
555706f2543Smrg    dev->inited = (ret == Success);
556706f2543Smrg    if (!dev->inited)
557706f2543Smrg        return ret;
558706f2543Smrg
559706f2543Smrg    /* Initialize memory for sprites. */
560706f2543Smrg    if (IsMaster(dev) && dev->spriteInfo->spriteOwner)
561706f2543Smrg        if (!pScreen->DeviceCursorInitialize(dev, pScreen))
562706f2543Smrg            ret = BadAlloc;
563706f2543Smrg
564706f2543Smrg    SendDevicePresenceEvent(dev->id, DeviceAdded);
565706f2543Smrg    if (sendevent)
566706f2543Smrg    {
567706f2543Smrg        int flags[MAXDEVICES] = {0};
568706f2543Smrg        flags[dev->id] = XISlaveAdded;
569706f2543Smrg        XISendDeviceHierarchyEvent(flags);
570706f2543Smrg    }
571706f2543Smrg    return ret;
572706f2543Smrg}
573706f2543Smrg
574706f2543Smrg/**
575706f2543Smrg * Ring the bell.
576706f2543Smrg * The actual task of ringing the bell is the job of the DDX.
577706f2543Smrg */
578706f2543Smrgstatic void
579706f2543SmrgCoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
580706f2543Smrg{
581706f2543Smrg    KeybdCtrl *ctrl = arg;
582706f2543Smrg
583706f2543Smrg    DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
584706f2543Smrg}
585706f2543Smrg
586706f2543Smrgstatic void
587706f2543SmrgCoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
588706f2543Smrg{
589706f2543Smrg    return;
590706f2543Smrg}
591706f2543Smrg
592706f2543Smrg/**
593706f2543Smrg * Device control function for the Virtual Core Keyboard.
594706f2543Smrg */
595706f2543Smrgint
596706f2543SmrgCoreKeyboardProc(DeviceIntPtr pDev, int what)
597706f2543Smrg{
598706f2543Smrg
599706f2543Smrg    switch (what) {
600706f2543Smrg    case DEVICE_INIT:
601706f2543Smrg        if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell,
602706f2543Smrg                                      CoreKeyboardCtl))
603706f2543Smrg        {
604706f2543Smrg            ErrorF("Keyboard initialization failed. This could be a missing "
605706f2543Smrg                   "or incorrect setup of xkeyboard-config.\n");
606706f2543Smrg            return BadValue;
607706f2543Smrg        }
608706f2543Smrg        return Success;
609706f2543Smrg
610706f2543Smrg    case DEVICE_ON:
611706f2543Smrg    case DEVICE_OFF:
612706f2543Smrg        return Success;
613706f2543Smrg
614706f2543Smrg    case DEVICE_CLOSE:
615706f2543Smrg        return Success;
616706f2543Smrg    }
617706f2543Smrg
618706f2543Smrg    return BadMatch;
619706f2543Smrg}
620706f2543Smrg
621706f2543Smrg/**
622706f2543Smrg * Device control function for the Virtual Core Pointer.
623706f2543Smrg */
624706f2543Smrgint
625706f2543SmrgCorePointerProc(DeviceIntPtr pDev, int what)
626706f2543Smrg{
627706f2543Smrg#define NBUTTONS 10
628706f2543Smrg#define NAXES 2
629706f2543Smrg    BYTE map[NBUTTONS + 1];
630706f2543Smrg    int i = 0;
631706f2543Smrg    Atom btn_labels[NBUTTONS] = {0};
632706f2543Smrg    Atom axes_labels[NAXES] = {0};
633706f2543Smrg
634706f2543Smrg    switch (what) {
635706f2543Smrg    case DEVICE_INIT:
636706f2543Smrg        for (i = 1; i <= NBUTTONS; i++)
637706f2543Smrg            map[i] = i;
638706f2543Smrg
639706f2543Smrg	btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
640706f2543Smrg	btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
641706f2543Smrg	btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
642706f2543Smrg	btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
643706f2543Smrg	btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
644706f2543Smrg	btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
645706f2543Smrg	btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
646706f2543Smrg	/* don't know about the rest */
647706f2543Smrg
648706f2543Smrg	axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
649706f2543Smrg	axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
650706f2543Smrg
651706f2543Smrg        if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels,
652706f2543Smrg                                (PtrCtrlProcPtr)NoopDDA,
653706f2543Smrg                                GetMotionHistorySize(), NAXES, axes_labels))
654706f2543Smrg        {
655706f2543Smrg            ErrorF("Could not initialize device '%s'. Out of memory.\n",
656706f2543Smrg                   pDev->name);
657706f2543Smrg            return BadAlloc; /* IPDS only fails on allocs */
658706f2543Smrg        }
659706f2543Smrg        pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
660706f2543Smrg        pDev->last.valuators[0] = pDev->valuator->axisVal[0];
661706f2543Smrg        pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
662706f2543Smrg        pDev->last.valuators[1] = pDev->valuator->axisVal[1];
663706f2543Smrg        break;
664706f2543Smrg
665706f2543Smrg    case DEVICE_CLOSE:
666706f2543Smrg        break;
667706f2543Smrg
668706f2543Smrg    default:
669706f2543Smrg        break;
670706f2543Smrg    }
671706f2543Smrg
672706f2543Smrg    return Success;
673706f2543Smrg
674706f2543Smrg#undef NBUTTONS
675706f2543Smrg#undef NAXES
676706f2543Smrg}
677706f2543Smrg
678706f2543Smrg/**
679706f2543Smrg * Initialise the two core devices, VCP and VCK (see events.c).
680706f2543Smrg * Both devices are not tied to physical devices, but guarantee that there is
681706f2543Smrg * always a keyboard and a pointer present and keep the protocol semantics.
682706f2543Smrg *
683706f2543Smrg * Note that the server MUST have two core devices at all times, even if there
684706f2543Smrg * is no physical device connected.
685706f2543Smrg */
686706f2543Smrgvoid
687706f2543SmrgInitCoreDevices(void)
688706f2543Smrg{
689706f2543Smrg    if (AllocDevicePair(serverClient, "Virtual core",
690706f2543Smrg                        &inputInfo.pointer, &inputInfo.keyboard,
691706f2543Smrg                        CorePointerProc, CoreKeyboardProc,
692706f2543Smrg                        TRUE) != Success)
693706f2543Smrg        FatalError("Failed to allocate core devices");
694706f2543Smrg
695706f2543Smrg    if (ActivateDevice(inputInfo.pointer, TRUE) != Success ||
696706f2543Smrg        ActivateDevice(inputInfo.keyboard, TRUE) != Success)
697706f2543Smrg        FatalError("Failed to activate core devices.");
698706f2543Smrg    if (!EnableDevice(inputInfo.pointer, TRUE) ||
699706f2543Smrg        !EnableDevice(inputInfo.keyboard, TRUE))
700706f2543Smrg        FatalError("Failed to enable core devices.");
701706f2543Smrg
702706f2543Smrg    InitXTestDevices();
703706f2543Smrg}
704706f2543Smrg
705706f2543Smrg/**
706706f2543Smrg * Activate all switched-off devices and then enable all those devices.
707706f2543Smrg *
708706f2543Smrg * Will return an error if no core keyboard or core pointer is present.
709706f2543Smrg * In theory this should never happen if you call InitCoreDevices() first.
710706f2543Smrg *
711706f2543Smrg * InitAndStartDevices needs to be called AFTER the windows are initialized.
712706f2543Smrg * Devices will start sending events after InitAndStartDevices() has
713706f2543Smrg * completed.
714706f2543Smrg *
715706f2543Smrg * @return Success or error code on failure.
716706f2543Smrg */
717706f2543Smrgint
718706f2543SmrgInitAndStartDevices(void)
719706f2543Smrg{
720706f2543Smrg    DeviceIntPtr dev, next;
721706f2543Smrg
722706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = dev->next) {
723706f2543Smrg        DebugF("(dix) initialising device %d\n", dev->id);
724706f2543Smrg        if (!dev->inited)
725706f2543Smrg            ActivateDevice(dev, TRUE);
726706f2543Smrg    }
727706f2543Smrg
728706f2543Smrg    /* enable real devices */
729706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = next)
730706f2543Smrg    {
731706f2543Smrg        DebugF("(dix) enabling device %d\n", dev->id);
732706f2543Smrg	next = dev->next;
733706f2543Smrg	if (dev->inited && dev->startup)
734706f2543Smrg	    EnableDevice(dev, TRUE);
735706f2543Smrg    }
736706f2543Smrg
737706f2543Smrg    return Success;
738706f2543Smrg}
739706f2543Smrg
740706f2543Smrg/**
741706f2543Smrg * Free the given device class and reset the pointer to NULL.
742706f2543Smrg */
743706f2543Smrgstatic void
744706f2543SmrgFreeDeviceClass(int type, pointer *class)
745706f2543Smrg{
746706f2543Smrg    if (!(*class))
747706f2543Smrg        return;
748706f2543Smrg
749706f2543Smrg    switch(type)
750706f2543Smrg    {
751706f2543Smrg        case KeyClass:
752706f2543Smrg            {
753706f2543Smrg                KeyClassPtr* k = (KeyClassPtr*)class;
754706f2543Smrg                if ((*k)->xkbInfo)
755706f2543Smrg                {
756706f2543Smrg                    XkbFreeInfo((*k)->xkbInfo);
757706f2543Smrg                    (*k)->xkbInfo = NULL;
758706f2543Smrg                }
759706f2543Smrg                free((*k));
760706f2543Smrg                break;
761706f2543Smrg            }
762706f2543Smrg        case ButtonClass:
763706f2543Smrg            {
764706f2543Smrg                ButtonClassPtr *b = (ButtonClassPtr*)class;
765706f2543Smrg                free((*b)->xkb_acts);
766706f2543Smrg                free((*b));
767706f2543Smrg                break;
768706f2543Smrg            }
769706f2543Smrg        case ValuatorClass:
770706f2543Smrg            {
771706f2543Smrg                ValuatorClassPtr *v = (ValuatorClassPtr*)class;
772706f2543Smrg
773706f2543Smrg                free((*v)->motion);
774706f2543Smrg                free((*v));
775706f2543Smrg                break;
776706f2543Smrg            }
777706f2543Smrg        case FocusClass:
778706f2543Smrg            {
779706f2543Smrg                FocusClassPtr *f = (FocusClassPtr*)class;
780706f2543Smrg                free((*f)->trace);
781706f2543Smrg                free((*f));
782706f2543Smrg                break;
783706f2543Smrg            }
784706f2543Smrg        case ProximityClass:
785706f2543Smrg            {
786706f2543Smrg                ProximityClassPtr *p = (ProximityClassPtr*)class;
787706f2543Smrg                free((*p));
788706f2543Smrg                break;
789706f2543Smrg            }
790706f2543Smrg    }
791706f2543Smrg    *class = NULL;
792706f2543Smrg}
793706f2543Smrg
794706f2543Smrgstatic void
795706f2543SmrgFreeFeedbackClass(int type, pointer *class)
796706f2543Smrg{
797706f2543Smrg    if (!(*class))
798706f2543Smrg        return;
799706f2543Smrg
800706f2543Smrg    switch(type)
801706f2543Smrg    {
802706f2543Smrg        case KbdFeedbackClass:
803706f2543Smrg            {
804706f2543Smrg                KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
805706f2543Smrg                KbdFeedbackPtr k, knext;
806706f2543Smrg                for (k = (*kbdfeed); k; k = knext) {
807706f2543Smrg                    knext = k->next;
808706f2543Smrg                    if (k->xkb_sli)
809706f2543Smrg                        XkbFreeSrvLedInfo(k->xkb_sli);
810706f2543Smrg                    free(k);
811706f2543Smrg                }
812706f2543Smrg                break;
813706f2543Smrg            }
814706f2543Smrg        case PtrFeedbackClass:
815706f2543Smrg            {
816706f2543Smrg                PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
817706f2543Smrg                PtrFeedbackPtr p, pnext;
818706f2543Smrg
819706f2543Smrg                for (p = (*ptrfeed); p; p = pnext) {
820706f2543Smrg                    pnext = p->next;
821706f2543Smrg                    free(p);
822706f2543Smrg                }
823706f2543Smrg                break;
824706f2543Smrg            }
825706f2543Smrg        case IntegerFeedbackClass:
826706f2543Smrg            {
827706f2543Smrg                IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
828706f2543Smrg                IntegerFeedbackPtr i, inext;
829706f2543Smrg
830706f2543Smrg                for (i = (*intfeed); i; i = inext) {
831706f2543Smrg                    inext = i->next;
832706f2543Smrg                    free(i);
833706f2543Smrg                }
834706f2543Smrg                break;
835706f2543Smrg            }
836706f2543Smrg        case StringFeedbackClass:
837706f2543Smrg            {
838706f2543Smrg                StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
839706f2543Smrg                StringFeedbackPtr s, snext;
840706f2543Smrg
841706f2543Smrg                for (s = (*stringfeed); s; s = snext) {
842706f2543Smrg                    snext = s->next;
843706f2543Smrg                    free(s->ctrl.symbols_supported);
844706f2543Smrg                    free(s->ctrl.symbols_displayed);
845706f2543Smrg                    free(s);
846706f2543Smrg                }
847706f2543Smrg                break;
848706f2543Smrg            }
849706f2543Smrg        case BellFeedbackClass:
850706f2543Smrg            {
851706f2543Smrg                BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
852706f2543Smrg                BellFeedbackPtr b, bnext;
853706f2543Smrg
854706f2543Smrg                for (b = (*bell); b; b = bnext) {
855706f2543Smrg                    bnext = b->next;
856706f2543Smrg                    free(b);
857706f2543Smrg                }
858706f2543Smrg                break;
859706f2543Smrg            }
860706f2543Smrg        case LedFeedbackClass:
861706f2543Smrg            {
862706f2543Smrg                LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
863706f2543Smrg                LedFeedbackPtr l, lnext;
864706f2543Smrg
865706f2543Smrg                for (l = (*leds); l; l = lnext) {
866706f2543Smrg                    lnext = l->next;
867706f2543Smrg                    if (l->xkb_sli)
868706f2543Smrg                        XkbFreeSrvLedInfo(l->xkb_sli);
869706f2543Smrg                    free(l);
870706f2543Smrg                }
871706f2543Smrg                break;
872706f2543Smrg            }
873706f2543Smrg    }
874706f2543Smrg    *class = NULL;
875706f2543Smrg}
876706f2543Smrg
877706f2543Smrgstatic void
878706f2543SmrgFreeAllDeviceClasses(ClassesPtr classes)
879706f2543Smrg{
880706f2543Smrg    if (!classes)
881706f2543Smrg        return;
882706f2543Smrg
883706f2543Smrg    FreeDeviceClass(KeyClass, (pointer)&classes->key);
884706f2543Smrg    FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
885706f2543Smrg    FreeDeviceClass(ButtonClass, (pointer)&classes->button);
886706f2543Smrg    FreeDeviceClass(FocusClass, (pointer)&classes->focus);
887706f2543Smrg    FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
888706f2543Smrg
889706f2543Smrg    FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
890706f2543Smrg    FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
891706f2543Smrg    FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
892706f2543Smrg    FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
893706f2543Smrg    FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
894706f2543Smrg    FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
895706f2543Smrg
896706f2543Smrg}
897706f2543Smrg
898706f2543Smrg/**
899706f2543Smrg * Close down a device and free all resources.
900706f2543Smrg * Once closed down, the driver will probably not expect you that you'll ever
901706f2543Smrg * enable it again and free associated structs. If you want the device to just
902706f2543Smrg * be disabled, DisableDevice().
903706f2543Smrg * Don't call this function directly, use RemoveDevice() instead.
904706f2543Smrg */
905706f2543Smrgstatic void
906706f2543SmrgCloseDevice(DeviceIntPtr dev)
907706f2543Smrg{
908706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
909706f2543Smrg    ClassesPtr classes;
910706f2543Smrg    int j;
911706f2543Smrg
912706f2543Smrg    if (!dev)
913706f2543Smrg        return;
914706f2543Smrg
915706f2543Smrg    XIDeleteAllDeviceProperties(dev);
916706f2543Smrg
917706f2543Smrg    if (dev->inited)
918706f2543Smrg	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
919706f2543Smrg
920706f2543Smrg    /* free sprite memory */
921706f2543Smrg    if (IsMaster(dev) && dev->spriteInfo->sprite)
922706f2543Smrg        screen->DeviceCursorCleanup(dev, screen);
923706f2543Smrg
924706f2543Smrg    /* free acceleration info */
925706f2543Smrg    if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
926706f2543Smrg	dev->valuator->accelScheme.AccelCleanupProc(dev);
927706f2543Smrg
928706f2543Smrg    while (dev->xkb_interest)
929706f2543Smrg	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
930706f2543Smrg
931706f2543Smrg    free(dev->name);
932706f2543Smrg
933706f2543Smrg    classes = (ClassesPtr)&dev->key;
934706f2543Smrg    FreeAllDeviceClasses(classes);
935706f2543Smrg
936706f2543Smrg    if (IsMaster(dev))
937706f2543Smrg    {
938706f2543Smrg        classes = dev->unused_classes;
939706f2543Smrg        FreeAllDeviceClasses(classes);
940706f2543Smrg	free(classes);
941706f2543Smrg    }
942706f2543Smrg
943706f2543Smrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
944706f2543Smrg	if (dev->spriteInfo->sprite->current)
945706f2543Smrg	    FreeCursor(dev->spriteInfo->sprite->current, None);
946706f2543Smrg        free(dev->spriteInfo->sprite->spriteTrace);
947706f2543Smrg        free(dev->spriteInfo->sprite);
948706f2543Smrg    }
949706f2543Smrg
950706f2543Smrg    /* a client may have the device set as client pointer */
951706f2543Smrg    for (j = 0; j < currentMaxClients; j++)
952706f2543Smrg    {
953706f2543Smrg        if (clients[j] && clients[j]->clientPtr == dev)
954706f2543Smrg        {
955706f2543Smrg            clients[j]->clientPtr = NULL;
956706f2543Smrg            clients[j]->clientPtr = PickPointer(clients[j]);
957706f2543Smrg        }
958706f2543Smrg    }
959706f2543Smrg
960706f2543Smrg    free(dev->deviceGrab.sync.event);
961706f2543Smrg    free(dev->config_info);     /* Allocated in xf86ActivateDevice. */
962706f2543Smrg    dev->config_info = NULL;
963706f2543Smrg    dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
964706f2543Smrg}
965706f2543Smrg
966706f2543Smrg/**
967706f2543Smrg * Shut down all devices of one list and free all resources.
968706f2543Smrg */
969706f2543Smrgstatic
970706f2543Smrgvoid
971706f2543SmrgCloseDeviceList(DeviceIntPtr *listHead)
972706f2543Smrg{
973706f2543Smrg    /* Used to mark devices that we tried to free */
974706f2543Smrg    Bool freedIds[MAXDEVICES];
975706f2543Smrg    DeviceIntPtr dev;
976706f2543Smrg    int i;
977706f2543Smrg
978706f2543Smrg    if (listHead == NULL)
979706f2543Smrg        return;
980706f2543Smrg
981706f2543Smrg    for (i = 0; i < MAXDEVICES; i++)
982706f2543Smrg        freedIds[i] = FALSE;
983706f2543Smrg
984706f2543Smrg    dev = *listHead;
985706f2543Smrg    while (dev != NULL)
986706f2543Smrg    {
987706f2543Smrg        freedIds[dev->id] = TRUE;
988706f2543Smrg        DeleteInputDeviceRequest(dev);
989706f2543Smrg
990706f2543Smrg        dev = *listHead;
991706f2543Smrg        while (dev != NULL && freedIds[dev->id])
992706f2543Smrg            dev = dev->next;
993706f2543Smrg    }
994706f2543Smrg}
995706f2543Smrg
996706f2543Smrg/**
997706f2543Smrg * Shut down all devices, free all resources, etc.
998706f2543Smrg * Only useful if you're shutting down the server!
999706f2543Smrg */
1000706f2543Smrgvoid
1001706f2543SmrgCloseDownDevices(void)
1002706f2543Smrg{
1003706f2543Smrg    DeviceIntPtr dev;
1004706f2543Smrg
1005706f2543Smrg    OsBlockSignals();
1006706f2543Smrg
1007706f2543Smrg    /* Float all SDs before closing them. Note that at this point resources
1008706f2543Smrg     * (e.g. cursors) have been freed already, so we can't just call
1009706f2543Smrg     * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
1010706f2543Smrg     * to NULL and pretend nothing happened.
1011706f2543Smrg     */
1012706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
1013706f2543Smrg    {
1014706f2543Smrg        if (!IsMaster(dev) && dev->u.master)
1015706f2543Smrg            dev->u.master = NULL;
1016706f2543Smrg    }
1017706f2543Smrg
1018dd8addeeSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next) {
1019dd8addeeSmrg	if (!IsMaster(dev) && dev->u.master)
1020dd8addeeSmrg            dev->u.master = NULL;
1021dd8addeeSmrg    }
1022dd8addeeSmrg
1023706f2543Smrg    CloseDeviceList(&inputInfo.devices);
1024706f2543Smrg    CloseDeviceList(&inputInfo.off_devices);
1025706f2543Smrg
1026706f2543Smrg    CloseDevice(inputInfo.pointer);
1027706f2543Smrg    CloseDevice(inputInfo.keyboard);
1028706f2543Smrg
1029706f2543Smrg    inputInfo.devices = NULL;
1030706f2543Smrg    inputInfo.off_devices = NULL;
1031706f2543Smrg    inputInfo.keyboard = NULL;
1032706f2543Smrg    inputInfo.pointer = NULL;
1033706f2543Smrg    XkbDeleteRulesDflts();
1034706f2543Smrg
1035706f2543Smrg    OsReleaseSignals();
1036706f2543Smrg}
1037706f2543Smrg
1038706f2543Smrg/**
1039706f2543Smrg * Remove the cursor sprite for all devices. This needs to be done before any
1040706f2543Smrg * resources are freed or any device is deleted.
1041706f2543Smrg */
1042706f2543Smrgvoid
1043706f2543SmrgUndisplayDevices(void)
1044706f2543Smrg{
1045706f2543Smrg    DeviceIntPtr dev;
1046706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
1047706f2543Smrg
1048706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
1049706f2543Smrg        screen->DisplayCursor(dev, screen, NullCursor);
1050706f2543Smrg}
1051706f2543Smrg
1052706f2543Smrg/**
1053706f2543Smrg * Remove a device from the device list, closes it and thus frees all
1054706f2543Smrg * resources.
1055706f2543Smrg * Removes both enabled and disabled devices and notifies all devices about
1056706f2543Smrg * the removal of the device.
1057706f2543Smrg *
1058706f2543Smrg * No PresenceNotify is sent for device that the client never saw. This can
1059706f2543Smrg * happen if a malloc fails during the addition of master devices. If
1060706f2543Smrg * dev->init is FALSE it means the client never received a DeviceAdded event,
1061706f2543Smrg * so let's not send a DeviceRemoved event either.
1062706f2543Smrg *
1063706f2543Smrg * @param sendevent True if an XI2 event should be sent.
1064706f2543Smrg */
1065706f2543Smrgint
1066706f2543SmrgRemoveDevice(DeviceIntPtr dev, BOOL sendevent)
1067706f2543Smrg{
1068706f2543Smrg    DeviceIntPtr prev,tmp,next;
1069706f2543Smrg    int ret = BadMatch;
1070706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
1071706f2543Smrg    int deviceid;
1072706f2543Smrg    int initialized;
1073706f2543Smrg    int flags[MAXDEVICES] = {0};
1074706f2543Smrg
1075706f2543Smrg    DebugF("(dix) removing device %d\n", dev->id);
1076706f2543Smrg
1077706f2543Smrg    if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
1078706f2543Smrg        return BadImplementation;
1079706f2543Smrg
1080706f2543Smrg    initialized = dev->inited;
1081706f2543Smrg    deviceid = dev->id;
1082706f2543Smrg
1083706f2543Smrg    if (initialized)
1084706f2543Smrg    {
1085706f2543Smrg        if (DevHasCursor(dev))
1086706f2543Smrg            screen->DisplayCursor(dev, screen, NullCursor);
1087706f2543Smrg
1088706f2543Smrg        DisableDevice(dev, sendevent);
1089706f2543Smrg        flags[dev->id] = XIDeviceDisabled;
1090706f2543Smrg    }
1091706f2543Smrg
1092706f2543Smrg    prev = NULL;
1093706f2543Smrg    for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
1094706f2543Smrg	next = tmp->next;
1095706f2543Smrg	if (tmp == dev) {
1096706f2543Smrg
1097706f2543Smrg	    if (prev==NULL)
1098706f2543Smrg		inputInfo.devices = next;
1099706f2543Smrg	    else
1100706f2543Smrg		prev->next = next;
1101706f2543Smrg
1102706f2543Smrg	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1103706f2543Smrg	    CloseDevice(tmp);
1104706f2543Smrg	    ret = Success;
1105706f2543Smrg	}
1106706f2543Smrg    }
1107706f2543Smrg
1108706f2543Smrg    prev = NULL;
1109706f2543Smrg    for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
1110706f2543Smrg	next = tmp->next;
1111706f2543Smrg	if (tmp == dev) {
1112706f2543Smrg	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1113706f2543Smrg	    CloseDevice(tmp);
1114706f2543Smrg
1115706f2543Smrg	    if (prev == NULL)
1116706f2543Smrg		inputInfo.off_devices = next;
1117706f2543Smrg	    else
1118706f2543Smrg		prev->next = next;
1119706f2543Smrg
1120706f2543Smrg            ret = Success;
1121706f2543Smrg	}
1122706f2543Smrg    }
1123706f2543Smrg
1124706f2543Smrg    if (ret == Success && initialized) {
1125706f2543Smrg        inputInfo.numDevices--;
1126706f2543Smrg        SendDevicePresenceEvent(deviceid, DeviceRemoved);
1127706f2543Smrg        if (sendevent)
1128706f2543Smrg            XISendDeviceHierarchyEvent(flags);
1129706f2543Smrg    }
1130706f2543Smrg
1131706f2543Smrg    return ret;
1132706f2543Smrg}
1133706f2543Smrg
1134706f2543Smrgint
1135706f2543SmrgNumMotionEvents(void)
1136706f2543Smrg{
1137706f2543Smrg    /* only called to fill data in initial connection reply.
1138706f2543Smrg     * VCP is ok here, it is the only fixed device we have. */
1139706f2543Smrg    return inputInfo.pointer->valuator->numMotionEvents;
1140706f2543Smrg}
1141706f2543Smrg
1142706f2543Smrgint
1143706f2543SmrgdixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode)
1144706f2543Smrg{
1145706f2543Smrg    DeviceIntPtr dev;
1146706f2543Smrg    int rc;
1147706f2543Smrg    *pDev = NULL;
1148706f2543Smrg
1149706f2543Smrg    for (dev=inputInfo.devices; dev; dev=dev->next) {
1150706f2543Smrg        if (dev->id == id)
1151706f2543Smrg            goto found;
1152706f2543Smrg    }
1153706f2543Smrg    for (dev=inputInfo.off_devices; dev; dev=dev->next) {
1154706f2543Smrg        if (dev->id == id)
1155706f2543Smrg	    goto found;
1156706f2543Smrg    }
1157706f2543Smrg    return BadDevice;
1158706f2543Smrg
1159706f2543Smrgfound:
1160706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1161706f2543Smrg    if (rc == Success)
1162706f2543Smrg	*pDev = dev;
1163706f2543Smrg    return rc;
1164706f2543Smrg}
1165706f2543Smrg
1166706f2543Smrgvoid
1167706f2543SmrgQueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
1168706f2543Smrg{
1169706f2543Smrg    if (inputInfo.keyboard) {
1170706f2543Smrg	*minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code;
1171706f2543Smrg	*maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code;
1172706f2543Smrg    }
1173706f2543Smrg}
1174706f2543Smrg
1175706f2543Smrg/* Notably, this function does not expand the destination's keycode range, or
1176706f2543Smrg * notify clients. */
1177706f2543SmrgBool
1178706f2543SmrgSetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
1179706f2543Smrg{
1180706f2543Smrg    int i, j;
1181706f2543Smrg    KeySym *tmp;
1182706f2543Smrg    int rowDif = src->minKeyCode - dst->minKeyCode;
1183706f2543Smrg
1184706f2543Smrg    /* if keysym map size changes, grow map first */
1185706f2543Smrg    if (src->mapWidth < dst->mapWidth) {
1186706f2543Smrg        for (i = src->minKeyCode; i <= src->maxKeyCode; i++) {
1187706f2543Smrg#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c))
1188706f2543Smrg#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c))
1189706f2543Smrg	    for (j = 0; j < src->mapWidth; j++)
1190706f2543Smrg		dst->map[DI(i, j)] = src->map[SI(i, j)];
1191706f2543Smrg	    for (j = src->mapWidth; j < dst->mapWidth; j++)
1192706f2543Smrg		dst->map[DI(i, j)] = NoSymbol;
1193706f2543Smrg#undef SI
1194706f2543Smrg#undef DI
1195706f2543Smrg	}
1196706f2543Smrg	return TRUE;
1197706f2543Smrg    }
1198706f2543Smrg    else if (src->mapWidth > dst->mapWidth) {
1199706f2543Smrg        i = sizeof(KeySym) * src->mapWidth *
1200706f2543Smrg             (dst->maxKeyCode - dst->minKeyCode + 1);
1201706f2543Smrg        tmp = calloc(sizeof(KeySym), i);
1202706f2543Smrg        if (!tmp)
1203706f2543Smrg            return FALSE;
1204706f2543Smrg
1205706f2543Smrg        if (dst->map) {
1206706f2543Smrg            for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
1207706f2543Smrg                memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth],
1208706f2543Smrg                        dst->mapWidth * sizeof(KeySym));
1209706f2543Smrg            free(dst->map);
1210706f2543Smrg        }
1211706f2543Smrg        dst->mapWidth = src->mapWidth;
1212706f2543Smrg        dst->map = tmp;
1213706f2543Smrg    }
1214706f2543Smrg    else if (!dst->map) {
1215706f2543Smrg        i = sizeof(KeySym) * src->mapWidth *
1216706f2543Smrg             (dst->maxKeyCode - dst->minKeyCode + 1);
1217706f2543Smrg        tmp = calloc(sizeof(KeySym), i);
1218706f2543Smrg        if (!tmp)
1219706f2543Smrg            return FALSE;
1220706f2543Smrg
1221706f2543Smrg        dst->map = tmp;
1222706f2543Smrg        dst->mapWidth = src->mapWidth;
1223706f2543Smrg    }
1224706f2543Smrg
1225706f2543Smrg    memmove(&dst->map[rowDif * dst->mapWidth], src->map,
1226706f2543Smrg            (src->maxKeyCode - src->minKeyCode + 1) *
1227706f2543Smrg            dst->mapWidth * sizeof(KeySym));
1228706f2543Smrg
1229706f2543Smrg    return TRUE;
1230706f2543Smrg}
1231706f2543Smrg
1232706f2543SmrgBool
1233706f2543SmrgInitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
1234706f2543Smrg                            CARD8 *map)
1235706f2543Smrg{
1236706f2543Smrg    ButtonClassPtr butc;
1237706f2543Smrg    int i;
1238706f2543Smrg
1239706f2543Smrg    butc = calloc(1, sizeof(ButtonClassRec));
1240706f2543Smrg    if (!butc)
1241706f2543Smrg	return FALSE;
1242706f2543Smrg    butc->numButtons = numButtons;
1243706f2543Smrg    butc->sourceid = dev->id;
1244706f2543Smrg    for (i = 1; i <= numButtons; i++)
1245706f2543Smrg	butc->map[i] = map[i];
1246706f2543Smrg    for (i = numButtons + 1; i < MAP_LENGTH; i++)
1247706f2543Smrg        butc->map[i] = i;
1248706f2543Smrg    memcpy(butc->labels, labels, numButtons * sizeof(Atom));
1249706f2543Smrg    dev->button = butc;
1250706f2543Smrg    return TRUE;
1251706f2543Smrg}
1252706f2543Smrg
1253706f2543Smrg/**
1254706f2543Smrg * Allocate a valuator class and set up the pointers for the axis values
1255706f2543Smrg * appropriately.
1256706f2543Smrg *
1257706f2543Smrg * @param src If non-NULL, the memory is reallocated from src. If NULL, the
1258706f2543Smrg * memory is calloc'd.
1259706f2543Smrg * @parma numAxes Number of axes to allocate.
1260706f2543Smrg * @return The allocated valuator struct.
1261706f2543Smrg */
1262706f2543SmrgValuatorClassPtr
1263706f2543SmrgAllocValuatorClass(ValuatorClassPtr src, int numAxes)
1264706f2543Smrg{
1265706f2543Smrg    ValuatorClassPtr v;
1266706f2543Smrg    /* force alignment with double */
1267706f2543Smrg    union align_u { ValuatorClassRec valc; double d; } *align;
1268706f2543Smrg    int size;
1269706f2543Smrg
1270706f2543Smrg    size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
1271706f2543Smrg    align = (union align_u *) realloc(src, size);
1272706f2543Smrg
1273706f2543Smrg    if (!align)
1274706f2543Smrg        return NULL;
1275706f2543Smrg
1276706f2543Smrg    if (!src)
1277706f2543Smrg        memset(align, 0, size);
1278706f2543Smrg
1279706f2543Smrg    v = &align->valc;
1280706f2543Smrg    v->numAxes = numAxes;
1281706f2543Smrg    v->axisVal = (double*)(align + 1);
1282706f2543Smrg    v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
1283706f2543Smrg
1284706f2543Smrg    return v;
1285706f2543Smrg}
1286706f2543Smrg
1287706f2543SmrgBool
1288706f2543SmrgInitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
1289706f2543Smrg                              int numMotionEvents, int mode)
1290706f2543Smrg{
1291706f2543Smrg    int i;
1292706f2543Smrg    ValuatorClassPtr valc;
1293706f2543Smrg
1294706f2543Smrg    if (!dev)
1295706f2543Smrg        return FALSE;
1296706f2543Smrg
1297706f2543Smrg    if (numAxes > MAX_VALUATORS)
1298706f2543Smrg    {
1299706f2543Smrg        LogMessage(X_WARNING,
1300706f2543Smrg                   "Device '%s' has %d axes, only using first %d.\n",
1301706f2543Smrg                   dev->name, numAxes, MAX_VALUATORS);
1302706f2543Smrg        numAxes = MAX_VALUATORS;
1303706f2543Smrg    }
1304706f2543Smrg
1305706f2543Smrg    valc = AllocValuatorClass(NULL, numAxes);
1306706f2543Smrg    if (!valc)
1307706f2543Smrg        return FALSE;
1308706f2543Smrg
1309706f2543Smrg    valc->sourceid = dev->id;
1310706f2543Smrg    valc->motion = NULL;
1311706f2543Smrg    valc->first_motion = 0;
1312706f2543Smrg    valc->last_motion = 0;
1313706f2543Smrg
1314706f2543Smrg    valc->numMotionEvents = numMotionEvents;
1315706f2543Smrg    valc->motionHintWindow = NullWindow;
1316706f2543Smrg
1317706f2543Smrg    if (mode & OutOfProximity)
1318706f2543Smrg        InitProximityClassDeviceStruct(dev);
1319706f2543Smrg
1320706f2543Smrg    dev->valuator = valc;
1321706f2543Smrg
1322706f2543Smrg    AllocateMotionHistory(dev);
1323706f2543Smrg
1324706f2543Smrg    for (i=0; i<numAxes; i++) {
1325706f2543Smrg        InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1326706f2543Smrg                               0, 0, 0, mode);
1327706f2543Smrg	valc->axisVal[i]=0;
1328706f2543Smrg    }
1329706f2543Smrg
1330706f2543Smrg    dev->last.numValuators = numAxes;
1331706f2543Smrg
1332706f2543Smrg    if (IsMaster(dev) || /* do not accelerate master or xtest devices */
1333706f2543Smrg        IsXTestDevice(dev, NULL))
1334706f2543Smrg	InitPointerAccelerationScheme(dev, PtrAccelNoOp);
1335706f2543Smrg    else
1336706f2543Smrg	InitPointerAccelerationScheme(dev, PtrAccelDefault);
1337706f2543Smrg    return TRUE;
1338706f2543Smrg}
1339706f2543Smrg
1340706f2543Smrg/* global list of acceleration schemes */
1341706f2543SmrgValuatorAccelerationRec pointerAccelerationScheme[] = {
1342706f2543Smrg    {PtrAccelNoOp,        NULL, NULL, NULL},
1343706f2543Smrg    {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
1344706f2543Smrg    {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
1345706f2543Smrg    {-1, NULL, NULL, NULL} /* terminator */
1346706f2543Smrg};
1347706f2543Smrg
1348706f2543Smrg/**
1349706f2543Smrg * install an acceleration scheme. returns TRUE on success, and should not
1350706f2543Smrg * change anything if unsuccessful.
1351706f2543Smrg */
1352706f2543SmrgBool
1353706f2543SmrgInitPointerAccelerationScheme(DeviceIntPtr dev,
1354706f2543Smrg                              int scheme)
1355706f2543Smrg{
1356706f2543Smrg    int x, i = -1;
1357706f2543Smrg    void* data = NULL;
1358706f2543Smrg    ValuatorClassPtr val;
1359706f2543Smrg
1360706f2543Smrg    val = dev->valuator;
1361706f2543Smrg
1362706f2543Smrg    if(!val)
1363706f2543Smrg	return FALSE;
1364706f2543Smrg
1365706f2543Smrg    if(IsMaster(dev) && scheme != PtrAccelNoOp)
1366706f2543Smrg        return FALSE;
1367706f2543Smrg
1368706f2543Smrg    for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
1369706f2543Smrg        if(pointerAccelerationScheme[x].number == scheme){
1370706f2543Smrg            i = x;
1371706f2543Smrg            break;
1372706f2543Smrg        }
1373706f2543Smrg    }
1374706f2543Smrg
1375706f2543Smrg    if(-1 == i)
1376706f2543Smrg        return FALSE;
1377706f2543Smrg
1378706f2543Smrg    if (val->accelScheme.AccelCleanupProc)
1379706f2543Smrg        val->accelScheme.AccelCleanupProc(dev);
1380706f2543Smrg
1381706f2543Smrg    /* init scheme-specific data */
1382706f2543Smrg    switch(scheme){
1383706f2543Smrg        case PtrAccelPredictable:
1384706f2543Smrg        {
1385706f2543Smrg            DeviceVelocityPtr s;
1386706f2543Smrg            s = malloc(sizeof(DeviceVelocityRec));
1387706f2543Smrg            if(!s)
1388706f2543Smrg        	return FALSE;
1389706f2543Smrg            InitVelocityData(s);
1390706f2543Smrg            data = s;
1391706f2543Smrg            break;
1392706f2543Smrg        }
1393706f2543Smrg        default:
1394706f2543Smrg            break;
1395706f2543Smrg    }
1396706f2543Smrg
1397706f2543Smrg    val->accelScheme = pointerAccelerationScheme[i];
1398706f2543Smrg    val->accelScheme.accelData = data;
1399706f2543Smrg
1400706f2543Smrg    /* post-init scheme */
1401706f2543Smrg    switch(scheme){
1402706f2543Smrg        case PtrAccelPredictable:
1403706f2543Smrg            InitializePredictableAccelerationProperties(dev);
1404706f2543Smrg            break;
1405706f2543Smrg
1406706f2543Smrg        default:
1407706f2543Smrg            break;
1408706f2543Smrg    }
1409706f2543Smrg
1410706f2543Smrg    return TRUE;
1411706f2543Smrg}
1412706f2543Smrg
1413706f2543SmrgBool
1414706f2543SmrgInitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
1415706f2543Smrg{
1416706f2543Smrg    AbsoluteClassPtr abs;
1417706f2543Smrg
1418706f2543Smrg    abs = malloc(sizeof(AbsoluteClassRec));
1419706f2543Smrg    if (!abs)
1420706f2543Smrg        return FALSE;
1421706f2543Smrg
1422706f2543Smrg    /* we don't do anything sensible with these, but should */
1423706f2543Smrg    abs->min_x = NO_AXIS_LIMITS;
1424706f2543Smrg    abs->min_y = NO_AXIS_LIMITS;
1425706f2543Smrg    abs->max_x = NO_AXIS_LIMITS;
1426706f2543Smrg    abs->max_y = NO_AXIS_LIMITS;
1427706f2543Smrg    abs->flip_x = 0;
1428706f2543Smrg    abs->flip_y = 0;
1429706f2543Smrg    abs->rotation = 0;
1430706f2543Smrg    abs->button_threshold = 0;
1431706f2543Smrg
1432706f2543Smrg    abs->offset_x = 0;
1433706f2543Smrg    abs->offset_y = 0;
1434706f2543Smrg    abs->width = NO_AXIS_LIMITS;
1435706f2543Smrg    abs->height = NO_AXIS_LIMITS;
1436706f2543Smrg    abs->following = 0;
1437706f2543Smrg    abs->screen = 0;
1438706f2543Smrg
1439706f2543Smrg    abs->sourceid = dev->id;
1440706f2543Smrg
1441706f2543Smrg    dev->absolute = abs;
1442706f2543Smrg
1443706f2543Smrg    return TRUE;
1444706f2543Smrg}
1445706f2543Smrg
1446706f2543SmrgBool
1447706f2543SmrgInitFocusClassDeviceStruct(DeviceIntPtr dev)
1448706f2543Smrg{
1449706f2543Smrg    FocusClassPtr focc;
1450706f2543Smrg
1451706f2543Smrg    focc = malloc(sizeof(FocusClassRec));
1452706f2543Smrg    if (!focc)
1453706f2543Smrg	return FALSE;
1454706f2543Smrg    focc->win = PointerRootWin;
1455706f2543Smrg    focc->revert = None;
1456706f2543Smrg    focc->time = currentTime;
1457706f2543Smrg    focc->trace = (WindowPtr *)NULL;
1458706f2543Smrg    focc->traceSize = 0;
1459706f2543Smrg    focc->traceGood = 0;
1460706f2543Smrg    focc->sourceid = dev->id;
1461706f2543Smrg    dev->focus = focc;
1462706f2543Smrg    return TRUE;
1463706f2543Smrg}
1464706f2543Smrg
1465706f2543SmrgBool
1466706f2543SmrgInitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
1467706f2543Smrg{
1468706f2543Smrg    PtrFeedbackPtr feedc;
1469706f2543Smrg
1470706f2543Smrg    feedc = malloc(sizeof(PtrFeedbackClassRec));
1471706f2543Smrg    if (!feedc)
1472706f2543Smrg	return FALSE;
1473706f2543Smrg    feedc->CtrlProc = controlProc;
1474706f2543Smrg    feedc->ctrl = defaultPointerControl;
1475706f2543Smrg    feedc->ctrl.id = 0;
1476706f2543Smrg    if ( (feedc->next = dev->ptrfeed) )
1477706f2543Smrg        feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
1478706f2543Smrg    dev->ptrfeed = feedc;
1479706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1480706f2543Smrg    return TRUE;
1481706f2543Smrg}
1482706f2543Smrg
1483706f2543Smrg
1484706f2543Smrgstatic LedCtrl defaultLedControl = {
1485706f2543Smrg	DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0};
1486706f2543Smrg
1487706f2543Smrgstatic BellCtrl defaultBellControl = {
1488706f2543Smrg	DEFAULT_BELL,
1489706f2543Smrg	DEFAULT_BELL_PITCH,
1490706f2543Smrg	DEFAULT_BELL_DURATION,
1491706f2543Smrg	0};
1492706f2543Smrg
1493706f2543Smrgstatic IntegerCtrl defaultIntegerControl = {
1494706f2543Smrg	DEFAULT_INT_RESOLUTION,
1495706f2543Smrg	DEFAULT_INT_MIN_VALUE,
1496706f2543Smrg	DEFAULT_INT_MAX_VALUE,
1497706f2543Smrg	DEFAULT_INT_DISPLAYED,
1498706f2543Smrg	0};
1499706f2543Smrg
1500706f2543SmrgBool
1501706f2543SmrgInitStringFeedbackClassDeviceStruct (
1502706f2543Smrg      DeviceIntPtr dev, StringCtrlProcPtr controlProc,
1503706f2543Smrg      int max_symbols, int num_symbols_supported, KeySym *symbols)
1504706f2543Smrg{
1505706f2543Smrg    int i;
1506706f2543Smrg    StringFeedbackPtr feedc;
1507706f2543Smrg
1508706f2543Smrg    feedc = malloc(sizeof(StringFeedbackClassRec));
1509706f2543Smrg    if (!feedc)
1510706f2543Smrg	return FALSE;
1511706f2543Smrg    feedc->CtrlProc = controlProc;
1512706f2543Smrg    feedc->ctrl.num_symbols_supported = num_symbols_supported;
1513706f2543Smrg    feedc->ctrl.num_symbols_displayed = 0;
1514706f2543Smrg    feedc->ctrl.max_symbols = max_symbols;
1515706f2543Smrg    feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported);
1516706f2543Smrg    feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols);
1517706f2543Smrg    if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
1518706f2543Smrg    {
1519706f2543Smrg	free(feedc->ctrl.symbols_supported);
1520706f2543Smrg	free(feedc->ctrl.symbols_displayed);
1521706f2543Smrg	free(feedc);
1522706f2543Smrg	return FALSE;
1523706f2543Smrg    }
1524706f2543Smrg    for (i=0; i<num_symbols_supported; i++)
1525706f2543Smrg	*(feedc->ctrl.symbols_supported+i) = *symbols++;
1526706f2543Smrg    for (i=0; i<max_symbols; i++)
1527706f2543Smrg	*(feedc->ctrl.symbols_displayed+i) = (KeySym) 0;
1528706f2543Smrg    feedc->ctrl.id = 0;
1529706f2543Smrg    if ( (feedc->next = dev->stringfeed) )
1530706f2543Smrg	feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
1531706f2543Smrg    dev->stringfeed = feedc;
1532706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1533706f2543Smrg    return TRUE;
1534706f2543Smrg}
1535706f2543Smrg
1536706f2543SmrgBool
1537706f2543SmrgInitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
1538706f2543Smrg                                   BellCtrlProcPtr controlProc)
1539706f2543Smrg{
1540706f2543Smrg    BellFeedbackPtr feedc;
1541706f2543Smrg
1542706f2543Smrg    feedc = malloc(sizeof(BellFeedbackClassRec));
1543706f2543Smrg    if (!feedc)
1544706f2543Smrg	return FALSE;
1545706f2543Smrg    feedc->CtrlProc = controlProc;
1546706f2543Smrg    feedc->BellProc = bellProc;
1547706f2543Smrg    feedc->ctrl = defaultBellControl;
1548706f2543Smrg    feedc->ctrl.id = 0;
1549706f2543Smrg    if ( (feedc->next = dev->bell) )
1550706f2543Smrg	feedc->ctrl.id = dev->bell->ctrl.id + 1;
1551706f2543Smrg    dev->bell = feedc;
1552706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1553706f2543Smrg    return TRUE;
1554706f2543Smrg}
1555706f2543Smrg
1556706f2543SmrgBool
1557706f2543SmrgInitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc)
1558706f2543Smrg{
1559706f2543Smrg    LedFeedbackPtr feedc;
1560706f2543Smrg
1561706f2543Smrg    feedc = malloc(sizeof(LedFeedbackClassRec));
1562706f2543Smrg    if (!feedc)
1563706f2543Smrg	return FALSE;
1564706f2543Smrg    feedc->CtrlProc = controlProc;
1565706f2543Smrg    feedc->ctrl = defaultLedControl;
1566706f2543Smrg    feedc->ctrl.id = 0;
1567706f2543Smrg    if ( (feedc->next = dev->leds) )
1568706f2543Smrg	feedc->ctrl.id = dev->leds->ctrl.id + 1;
1569706f2543Smrg    feedc->xkb_sli= NULL;
1570706f2543Smrg    dev->leds = feedc;
1571706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1572706f2543Smrg    return TRUE;
1573706f2543Smrg}
1574706f2543Smrg
1575706f2543SmrgBool
1576706f2543SmrgInitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc)
1577706f2543Smrg{
1578706f2543Smrg    IntegerFeedbackPtr feedc;
1579706f2543Smrg
1580706f2543Smrg    feedc = malloc(sizeof(IntegerFeedbackClassRec));
1581706f2543Smrg    if (!feedc)
1582706f2543Smrg	return FALSE;
1583706f2543Smrg    feedc->CtrlProc = controlProc;
1584706f2543Smrg    feedc->ctrl = defaultIntegerControl;
1585706f2543Smrg    feedc->ctrl.id = 0;
1586706f2543Smrg    if ( (feedc->next = dev->intfeed) )
1587706f2543Smrg	feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
1588706f2543Smrg    dev->intfeed = feedc;
1589706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1590706f2543Smrg    return TRUE;
1591706f2543Smrg}
1592706f2543Smrg
1593706f2543SmrgBool
1594706f2543SmrgInitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels,
1595706f2543Smrg                        PtrCtrlProcPtr controlProc, int numMotionEvents,
1596706f2543Smrg                        int numAxes, Atom *axes_labels)
1597706f2543Smrg{
1598706f2543Smrg    DeviceIntPtr dev = (DeviceIntPtr)device;
1599706f2543Smrg
1600706f2543Smrg    return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
1601706f2543Smrg	   InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
1602706f2543Smrg					 numMotionEvents, Relative) &&
1603706f2543Smrg	   InitPtrFeedbackClassDeviceStruct(dev, controlProc));
1604706f2543Smrg}
1605706f2543Smrg
1606706f2543Smrg/*
1607706f2543Smrg * Check if the given buffer contains elements between low (inclusive) and
1608706f2543Smrg * high (inclusive) only.
1609706f2543Smrg *
1610706f2543Smrg * @return TRUE if the device map is invalid, FALSE otherwise.
1611706f2543Smrg */
1612706f2543SmrgBool
1613706f2543SmrgBadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
1614706f2543Smrg{
1615706f2543Smrg    int i;
1616706f2543Smrg
1617706f2543Smrg    for (i = 0; i < length; i++)
1618706f2543Smrg	if (buff[i])		       /* only check non-zero elements */
1619706f2543Smrg	{
1620706f2543Smrg	    if ((low > buff[i]) || (high < buff[i]))
1621706f2543Smrg	    {
1622706f2543Smrg		*errval = buff[i];
1623706f2543Smrg		return TRUE;
1624706f2543Smrg	    }
1625706f2543Smrg	}
1626706f2543Smrg    return FALSE;
1627706f2543Smrg}
1628706f2543Smrg
1629706f2543Smrgint
1630706f2543SmrgProcSetModifierMapping(ClientPtr client)
1631706f2543Smrg{
1632706f2543Smrg    xSetModifierMappingReply rep;
1633706f2543Smrg    int rc;
1634706f2543Smrg    REQUEST(xSetModifierMappingReq);
1635706f2543Smrg    REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
1636706f2543Smrg
1637706f2543Smrg    if (client->req_len != ((stuff->numKeyPerModifier << 1) +
1638706f2543Smrg                bytes_to_int32(sizeof(xSetModifierMappingReq))))
1639706f2543Smrg	return BadLength;
1640706f2543Smrg
1641706f2543Smrg    rep.type = X_Reply;
1642706f2543Smrg    rep.length = 0;
1643706f2543Smrg    rep.sequenceNumber = client->sequence;
1644706f2543Smrg
1645706f2543Smrg    rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1],
1646706f2543Smrg                       stuff->numKeyPerModifier);
1647706f2543Smrg    if (rc == MappingFailed || rc == -1)
1648706f2543Smrg        return BadValue;
1649706f2543Smrg    if (rc != Success && rc != MappingSuccess && rc != MappingFailed &&
1650706f2543Smrg        rc != MappingBusy)
1651706f2543Smrg	return rc;
1652706f2543Smrg
1653706f2543Smrg    rep.success = rc;
1654706f2543Smrg
1655706f2543Smrg    WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
1656706f2543Smrg    return Success;
1657706f2543Smrg}
1658706f2543Smrg
1659706f2543Smrgint
1660706f2543SmrgProcGetModifierMapping(ClientPtr client)
1661706f2543Smrg{
1662706f2543Smrg    xGetModifierMappingReply rep;
1663706f2543Smrg    int max_keys_per_mod = 0;
1664706f2543Smrg    KeyCode *modkeymap = NULL;
1665706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
1666706f2543Smrg
1667706f2543Smrg    generate_modkeymap(client, PickKeyboard(client), &modkeymap,
1668706f2543Smrg                       &max_keys_per_mod);
1669706f2543Smrg
1670706f2543Smrg    memset(&rep, 0, sizeof(xGetModifierMappingReply));
1671706f2543Smrg    rep.type = X_Reply;
1672706f2543Smrg    rep.numKeyPerModifier = max_keys_per_mod;
1673706f2543Smrg    rep.sequenceNumber = client->sequence;
1674706f2543Smrg    /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */
1675706f2543Smrg    rep.length = max_keys_per_mod << 1;
1676706f2543Smrg
1677706f2543Smrg    WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
1678706f2543Smrg    (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap);
1679706f2543Smrg
1680706f2543Smrg    free(modkeymap);
1681706f2543Smrg
1682706f2543Smrg    return Success;
1683706f2543Smrg}
1684706f2543Smrg
1685706f2543Smrgint
1686706f2543SmrgProcChangeKeyboardMapping(ClientPtr client)
1687706f2543Smrg{
1688706f2543Smrg    REQUEST(xChangeKeyboardMappingReq);
1689706f2543Smrg    unsigned len;
1690706f2543Smrg    KeySymsRec keysyms;
1691706f2543Smrg    DeviceIntPtr pDev, tmp;
1692706f2543Smrg    int rc;
1693706f2543Smrg    REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
1694706f2543Smrg
1695706f2543Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq));
1696706f2543Smrg    if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
1697706f2543Smrg            return BadLength;
1698706f2543Smrg
1699706f2543Smrg    pDev = PickKeyboard(client);
1700706f2543Smrg
1701706f2543Smrg    if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) ||
1702706f2543Smrg	(stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) {
1703706f2543Smrg	    client->errorValue = stuff->firstKeyCode;
1704706f2543Smrg	    return BadValue;
1705706f2543Smrg
1706706f2543Smrg    }
1707706f2543Smrg    if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) >
1708706f2543Smrg          pDev->key->xkbInfo->desc->max_key_code) ||
1709706f2543Smrg        (stuff->keySymsPerKeyCode == 0)) {
1710706f2543Smrg	    client->errorValue = stuff->keySymsPerKeyCode;
1711706f2543Smrg	    return BadValue;
1712706f2543Smrg    }
1713706f2543Smrg
1714706f2543Smrg    keysyms.minKeyCode = stuff->firstKeyCode;
1715706f2543Smrg    keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
1716706f2543Smrg    keysyms.mapWidth = stuff->keySymsPerKeyCode;
1717706f2543Smrg    keysyms.map = (KeySym *) &stuff[1];
1718706f2543Smrg
1719706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1720706f2543Smrg    if (rc != Success)
1721706f2543Smrg        return rc;
1722706f2543Smrg
1723706f2543Smrg    XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode,
1724706f2543Smrg                          stuff->keyCodes, NULL, client);
1725706f2543Smrg
1726706f2543Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
1727706f2543Smrg        if (IsMaster(tmp) || tmp->u.master != pDev)
1728706f2543Smrg            continue;
1729706f2543Smrg        if (!tmp->key)
1730706f2543Smrg            continue;
1731706f2543Smrg
1732706f2543Smrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1733706f2543Smrg        if (rc != Success)
1734706f2543Smrg            continue;
1735706f2543Smrg
1736706f2543Smrg        XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode,
1737706f2543Smrg                              stuff->keyCodes, NULL, client);
1738706f2543Smrg    }
1739706f2543Smrg
1740706f2543Smrg    return Success;
1741706f2543Smrg}
1742706f2543Smrg
1743706f2543Smrgint
1744706f2543SmrgProcSetPointerMapping(ClientPtr client)
1745706f2543Smrg{
1746706f2543Smrg    BYTE *map;
1747706f2543Smrg    int ret;
1748706f2543Smrg    int i, j;
1749706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
1750706f2543Smrg    xSetPointerMappingReply rep;
1751706f2543Smrg    REQUEST(xSetPointerMappingReq);
1752706f2543Smrg    REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
1753706f2543Smrg
1754706f2543Smrg    if (client->req_len !=
1755706f2543Smrg            bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts))
1756706f2543Smrg	return BadLength;
1757706f2543Smrg    rep.type = X_Reply;
1758706f2543Smrg    rep.length = 0;
1759706f2543Smrg    rep.sequenceNumber = client->sequence;
1760706f2543Smrg    rep.success = MappingSuccess;
1761706f2543Smrg    map = (BYTE *)&stuff[1];
1762706f2543Smrg
1763706f2543Smrg    /* So we're bounded here by the number of core buttons.  This check
1764706f2543Smrg     * probably wants disabling through XFixes. */
1765706f2543Smrg    /* MPX: With ClientPointer, we can return the right number of buttons.
1766706f2543Smrg     * Let's just hope nobody changed ClientPointer between GetPointerMapping
1767706f2543Smrg     * and SetPointerMapping
1768706f2543Smrg     */
1769706f2543Smrg    if (stuff->nElts != ptr->button->numButtons) {
1770706f2543Smrg	client->errorValue = stuff->nElts;
1771706f2543Smrg	return BadValue;
1772706f2543Smrg    }
1773706f2543Smrg
1774706f2543Smrg    /* Core protocol specs don't allow for duplicate mappings; this check
1775706f2543Smrg     * almost certainly wants disabling through XFixes too. */
1776706f2543Smrg    for (i = 0; i < stuff->nElts; i++) {
1777706f2543Smrg        for (j = i + 1; j < stuff->nElts; j++) {
1778706f2543Smrg            if (map[i] && map[i] == map[j]) {
1779706f2543Smrg                client->errorValue = map[i];
1780706f2543Smrg                return BadValue;
1781706f2543Smrg            }
1782706f2543Smrg        }
1783706f2543Smrg    }
1784706f2543Smrg
1785706f2543Smrg    ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
1786706f2543Smrg    if (ret == MappingBusy)
1787706f2543Smrg        rep.success = ret;
1788706f2543Smrg    else if (ret == -1)
1789706f2543Smrg        return BadValue;
1790706f2543Smrg    else if (ret != Success)
1791706f2543Smrg        return ret;
1792706f2543Smrg
1793706f2543Smrg    WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
1794706f2543Smrg    return Success;
1795706f2543Smrg}
1796706f2543Smrg
1797706f2543Smrgint
1798706f2543SmrgProcGetKeyboardMapping(ClientPtr client)
1799706f2543Smrg{
1800706f2543Smrg    xGetKeyboardMappingReply rep;
1801706f2543Smrg    DeviceIntPtr kbd = PickKeyboard(client);
1802706f2543Smrg    XkbDescPtr xkb;
1803706f2543Smrg    KeySymsPtr syms;
1804706f2543Smrg    int rc;
1805706f2543Smrg    REQUEST(xGetKeyboardMappingReq);
1806706f2543Smrg    REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
1807706f2543Smrg
1808706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
1809706f2543Smrg    if (rc != Success)
1810706f2543Smrg	return rc;
1811706f2543Smrg
1812706f2543Smrg    xkb = kbd->key->xkbInfo->desc;
1813706f2543Smrg
1814706f2543Smrg    if ((stuff->firstKeyCode < xkb->min_key_code) ||
1815706f2543Smrg        (stuff->firstKeyCode > xkb->max_key_code)) {
1816706f2543Smrg	client->errorValue = stuff->firstKeyCode;
1817706f2543Smrg	return BadValue;
1818706f2543Smrg    }
1819706f2543Smrg    if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) {
1820706f2543Smrg	client->errorValue = stuff->count;
1821706f2543Smrg        return BadValue;
1822706f2543Smrg    }
1823706f2543Smrg
1824706f2543Smrg    syms = XkbGetCoreMap(kbd);
1825706f2543Smrg    if (!syms)
1826706f2543Smrg        return BadAlloc;
1827706f2543Smrg
1828706f2543Smrg    memset(&rep, 0, sizeof(xGetKeyboardMappingReply));
1829706f2543Smrg    rep.type = X_Reply;
1830706f2543Smrg    rep.sequenceNumber = client->sequence;
1831706f2543Smrg    rep.keySymsPerKeyCode = syms->mapWidth;
1832706f2543Smrg    /* length is a count of 4 byte quantities and KeySyms are 4 bytes */
1833706f2543Smrg    rep.length = syms->mapWidth * stuff->count;
1834706f2543Smrg    WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
1835706f2543Smrg    client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
1836706f2543Smrg    WriteSwappedDataToClient(client,
1837706f2543Smrg                             syms->mapWidth * stuff->count * sizeof(KeySym),
1838706f2543Smrg                             &syms->map[syms->mapWidth * (stuff->firstKeyCode -
1839706f2543Smrg                                                          syms->minKeyCode)]);
1840706f2543Smrg    free(syms->map);
1841706f2543Smrg    free(syms);
1842706f2543Smrg
1843706f2543Smrg    return Success;
1844706f2543Smrg}
1845706f2543Smrg
1846706f2543Smrgint
1847706f2543SmrgProcGetPointerMapping(ClientPtr client)
1848706f2543Smrg{
1849706f2543Smrg    xGetPointerMappingReply rep;
1850706f2543Smrg    /* Apps may get different values each time they call GetPointerMapping as
1851706f2543Smrg     * the ClientPointer could change. */
1852706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
1853706f2543Smrg    ButtonClassPtr butc = ptr->button;
1854706f2543Smrg    int rc;
1855706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
1856706f2543Smrg
1857706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
1858706f2543Smrg    if (rc != Success)
1859706f2543Smrg	return rc;
1860706f2543Smrg
1861706f2543Smrg    rep.type = X_Reply;
1862706f2543Smrg    rep.sequenceNumber = client->sequence;
1863706f2543Smrg    rep.nElts = (butc) ? butc->numButtons : 0;
1864706f2543Smrg    rep.length = ((unsigned)rep.nElts + (4-1))/4;
1865706f2543Smrg    WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
1866706f2543Smrg    if (butc)
1867706f2543Smrg        WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
1868706f2543Smrg    return Success;
1869706f2543Smrg}
1870706f2543Smrg
1871706f2543Smrgvoid
1872706f2543SmrgNoteLedState(DeviceIntPtr keybd, int led, Bool on)
1873706f2543Smrg{
1874706f2543Smrg    KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
1875706f2543Smrg    if (on)
1876706f2543Smrg	ctrl->leds |= ((Leds)1 << (led - 1));
1877706f2543Smrg    else
1878706f2543Smrg	ctrl->leds &= ~((Leds)1 << (led - 1));
1879706f2543Smrg}
1880706f2543Smrg
1881706f2543Smrgint
1882706f2543SmrgOnes(unsigned long mask)             /* HACKMEM 169 */
1883706f2543Smrg{
1884706f2543Smrg    unsigned long y;
1885706f2543Smrg
1886706f2543Smrg    y = (mask >> 1) &033333333333;
1887706f2543Smrg    y = mask - y - ((y >>1) & 033333333333);
1888706f2543Smrg    return (((y + (y >> 3)) & 030707070707) % 077);
1889706f2543Smrg}
1890706f2543Smrg
1891706f2543Smrgstatic int
1892706f2543SmrgDoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
1893706f2543Smrg                         BITS32 vmask)
1894706f2543Smrg{
1895706f2543Smrg#define DO_ALL    (-1)
1896706f2543Smrg    KeybdCtrl ctrl;
1897706f2543Smrg    int t;
1898706f2543Smrg    int led = DO_ALL;
1899706f2543Smrg    int key = DO_ALL;
1900706f2543Smrg    BITS32 index2;
1901706f2543Smrg    int mask = vmask, i;
1902706f2543Smrg    XkbEventCauseRec cause;
1903706f2543Smrg
1904706f2543Smrg    ctrl = keybd->kbdfeed->ctrl;
1905706f2543Smrg    while (vmask) {
1906706f2543Smrg	index2 = (BITS32) lowbit (vmask);
1907706f2543Smrg	vmask &= ~index2;
1908706f2543Smrg	switch (index2) {
1909706f2543Smrg	case KBKeyClickPercent:
1910706f2543Smrg	    t = (INT8)*vlist;
1911706f2543Smrg	    vlist++;
1912706f2543Smrg	    if (t == -1) {
1913706f2543Smrg		t = defaultKeyboardControl.click;
1914706f2543Smrg            }
1915706f2543Smrg	    else if (t < 0 || t > 100) {
1916706f2543Smrg		client->errorValue = t;
1917706f2543Smrg		return BadValue;
1918706f2543Smrg	    }
1919706f2543Smrg	    ctrl.click = t;
1920706f2543Smrg	    break;
1921706f2543Smrg	case KBBellPercent:
1922706f2543Smrg	    t = (INT8)*vlist;
1923706f2543Smrg	    vlist++;
1924706f2543Smrg	    if (t == -1) {
1925706f2543Smrg		t = defaultKeyboardControl.bell;
1926706f2543Smrg            }
1927706f2543Smrg	    else if (t < 0 || t > 100) {
1928706f2543Smrg		client->errorValue = t;
1929706f2543Smrg		return BadValue;
1930706f2543Smrg	    }
1931706f2543Smrg	    ctrl.bell = t;
1932706f2543Smrg	    break;
1933706f2543Smrg	case KBBellPitch:
1934706f2543Smrg	    t = (INT16)*vlist;
1935706f2543Smrg	    vlist++;
1936706f2543Smrg	    if (t == -1) {
1937706f2543Smrg		t = defaultKeyboardControl.bell_pitch;
1938706f2543Smrg            }
1939706f2543Smrg	    else if (t < 0) {
1940706f2543Smrg		client->errorValue = t;
1941706f2543Smrg		return BadValue;
1942706f2543Smrg	    }
1943706f2543Smrg	    ctrl.bell_pitch = t;
1944706f2543Smrg	    break;
1945706f2543Smrg	case KBBellDuration:
1946706f2543Smrg	    t = (INT16)*vlist;
1947706f2543Smrg	    vlist++;
1948706f2543Smrg	    if (t == -1)
1949706f2543Smrg		t = defaultKeyboardControl.bell_duration;
1950706f2543Smrg	    else if (t < 0) {
1951706f2543Smrg		client->errorValue = t;
1952706f2543Smrg		return BadValue;
1953706f2543Smrg	    }
1954706f2543Smrg	    ctrl.bell_duration = t;
1955706f2543Smrg	    break;
1956706f2543Smrg	case KBLed:
1957706f2543Smrg	    led = (CARD8)*vlist;
1958706f2543Smrg	    vlist++;
1959706f2543Smrg	    if (led < 1 || led > 32) {
1960706f2543Smrg		client->errorValue = led;
1961706f2543Smrg		return BadValue;
1962706f2543Smrg	    }
1963706f2543Smrg	    if (!(mask & KBLedMode))
1964706f2543Smrg		return BadMatch;
1965706f2543Smrg	    break;
1966706f2543Smrg	case KBLedMode:
1967706f2543Smrg	    t = (CARD8)*vlist;
1968706f2543Smrg	    vlist++;
1969706f2543Smrg	    if (t == LedModeOff) {
1970706f2543Smrg		if (led == DO_ALL)
1971706f2543Smrg		    ctrl.leds = 0x0;
1972706f2543Smrg		else
1973706f2543Smrg		    ctrl.leds &= ~(((Leds)(1)) << (led - 1));
1974706f2543Smrg	    }
1975706f2543Smrg	    else if (t == LedModeOn) {
1976706f2543Smrg		if (led == DO_ALL)
1977706f2543Smrg		    ctrl.leds = ~0L;
1978706f2543Smrg		else
1979706f2543Smrg		    ctrl.leds |= (((Leds)(1)) << (led - 1));
1980706f2543Smrg	    }
1981706f2543Smrg	    else {
1982706f2543Smrg		client->errorValue = t;
1983706f2543Smrg		return BadValue;
1984706f2543Smrg	    }
1985706f2543Smrg
1986706f2543Smrg            XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client);
1987706f2543Smrg            XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))),
1988706f2543Smrg 			     ctrl.leds, &cause);
1989706f2543Smrg            ctrl.leds = keybd->kbdfeed->ctrl.leds;
1990706f2543Smrg
1991706f2543Smrg	    break;
1992706f2543Smrg	case KBKey:
1993706f2543Smrg	    key = (KeyCode)*vlist;
1994706f2543Smrg	    vlist++;
1995706f2543Smrg	    if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code ||
1996706f2543Smrg		(KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) {
1997706f2543Smrg		client->errorValue = key;
1998706f2543Smrg		return BadValue;
1999706f2543Smrg	    }
2000706f2543Smrg	    if (!(mask & KBAutoRepeatMode))
2001706f2543Smrg		return BadMatch;
2002706f2543Smrg	    break;
2003706f2543Smrg	case KBAutoRepeatMode:
2004706f2543Smrg	    i = (key >> 3);
2005706f2543Smrg	    mask = (1 << (key & 7));
2006706f2543Smrg	    t = (CARD8)*vlist;
2007706f2543Smrg	    vlist++;
2008706f2543Smrg            if (key != DO_ALL)
2009706f2543Smrg                XkbDisableComputedAutoRepeats(keybd,key);
2010706f2543Smrg	    if (t == AutoRepeatModeOff) {
2011706f2543Smrg		if (key == DO_ALL)
2012706f2543Smrg		    ctrl.autoRepeat = FALSE;
2013706f2543Smrg		else
2014706f2543Smrg		    ctrl.autoRepeats[i] &= ~mask;
2015706f2543Smrg	    }
2016706f2543Smrg	    else if (t == AutoRepeatModeOn) {
2017706f2543Smrg		if (key == DO_ALL)
2018706f2543Smrg		    ctrl.autoRepeat = TRUE;
2019706f2543Smrg		else
2020706f2543Smrg		    ctrl.autoRepeats[i] |= mask;
2021706f2543Smrg	    }
2022706f2543Smrg	    else if (t == AutoRepeatModeDefault) {
2023706f2543Smrg		if (key == DO_ALL)
2024706f2543Smrg		    ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
2025706f2543Smrg		else
2026706f2543Smrg		    ctrl.autoRepeats[i] =
2027706f2543Smrg			    (ctrl.autoRepeats[i] & ~mask) |
2028706f2543Smrg			    (defaultKeyboardControl.autoRepeats[i] & mask);
2029706f2543Smrg	    }
2030706f2543Smrg	    else {
2031706f2543Smrg		client->errorValue = t;
2032706f2543Smrg		return BadValue;
2033706f2543Smrg	    }
2034706f2543Smrg	    break;
2035706f2543Smrg	default:
2036706f2543Smrg	    client->errorValue = mask;
2037706f2543Smrg	    return BadValue;
2038706f2543Smrg	}
2039706f2543Smrg    }
2040706f2543Smrg    keybd->kbdfeed->ctrl = ctrl;
2041706f2543Smrg
2042706f2543Smrg    /* The XKB RepeatKeys control and core protocol global autorepeat */
2043706f2543Smrg    /* value are linked	*/
2044706f2543Smrg    XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
2045706f2543Smrg
2046706f2543Smrg    return Success;
2047706f2543Smrg
2048706f2543Smrg#undef DO_ALL
2049706f2543Smrg}
2050706f2543Smrg
2051706f2543Smrg/**
2052706f2543Smrg * Changes kbd control on the ClientPointer and all attached SDs.
2053706f2543Smrg */
2054706f2543Smrgint
2055706f2543SmrgProcChangeKeyboardControl (ClientPtr client)
2056706f2543Smrg{
2057706f2543Smrg    XID *vlist;
2058706f2543Smrg    BITS32 vmask;
2059706f2543Smrg    int ret = Success, error = Success;
2060706f2543Smrg    DeviceIntPtr pDev = NULL, keyboard;
2061706f2543Smrg    REQUEST(xChangeKeyboardControlReq);
2062706f2543Smrg
2063706f2543Smrg    REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
2064706f2543Smrg
2065706f2543Smrg    vmask = stuff->mask;
2066706f2543Smrg    vlist = (XID *)&stuff[1];
2067706f2543Smrg
2068706f2543Smrg    if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask))
2069706f2543Smrg	return BadLength;
2070706f2543Smrg
2071706f2543Smrg    keyboard = PickKeyboard(client);
2072706f2543Smrg
2073706f2543Smrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2074706f2543Smrg        if ((pDev == keyboard ||
2075706f2543Smrg	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2076706f2543Smrg	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2077706f2543Smrg            ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
2078706f2543Smrg	    if (ret != Success)
2079706f2543Smrg                return ret;
2080706f2543Smrg        }
2081706f2543Smrg    }
2082706f2543Smrg
2083706f2543Smrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2084706f2543Smrg        if ((pDev == keyboard ||
2085706f2543Smrg	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2086706f2543Smrg	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2087706f2543Smrg            ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
2088706f2543Smrg            if (ret != Success)
2089706f2543Smrg                error = ret;
2090706f2543Smrg        }
2091706f2543Smrg    }
2092706f2543Smrg
2093706f2543Smrg    return error;
2094706f2543Smrg}
2095706f2543Smrg
2096706f2543Smrgint
2097706f2543SmrgProcGetKeyboardControl (ClientPtr client)
2098706f2543Smrg{
2099706f2543Smrg    int rc, i;
2100706f2543Smrg    DeviceIntPtr kbd = PickKeyboard(client);
2101706f2543Smrg    KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
2102706f2543Smrg    xGetKeyboardControlReply rep;
2103706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2104706f2543Smrg
2105706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
2106706f2543Smrg    if (rc != Success)
2107706f2543Smrg	return rc;
2108706f2543Smrg
2109706f2543Smrg    rep.type = X_Reply;
2110706f2543Smrg    rep.length = 5;
2111706f2543Smrg    rep.sequenceNumber = client->sequence;
2112706f2543Smrg    rep.globalAutoRepeat = ctrl->autoRepeat;
2113706f2543Smrg    rep.keyClickPercent = ctrl->click;
2114706f2543Smrg    rep.bellPercent = ctrl->bell;
2115706f2543Smrg    rep.bellPitch = ctrl->bell_pitch;
2116706f2543Smrg    rep.bellDuration = ctrl->bell_duration;
2117706f2543Smrg    rep.ledMask = ctrl->leds;
2118706f2543Smrg    for (i = 0; i < 32; i++)
2119706f2543Smrg	rep.map[i] = ctrl->autoRepeats[i];
2120706f2543Smrg    WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
2121706f2543Smrg    return Success;
2122706f2543Smrg}
2123706f2543Smrg
2124706f2543Smrgint
2125706f2543SmrgProcBell(ClientPtr client)
2126706f2543Smrg{
2127706f2543Smrg    DeviceIntPtr dev, keybd = PickKeyboard(client);
2128706f2543Smrg    int base = keybd->kbdfeed->ctrl.bell;
2129706f2543Smrg    int newpercent;
2130706f2543Smrg    int rc;
2131706f2543Smrg    REQUEST(xBellReq);
2132706f2543Smrg    REQUEST_SIZE_MATCH(xBellReq);
2133706f2543Smrg
2134706f2543Smrg    if (stuff->percent < -100 || stuff->percent > 100) {
2135706f2543Smrg	client->errorValue = stuff->percent;
2136706f2543Smrg	return BadValue;
2137706f2543Smrg    }
2138706f2543Smrg
2139706f2543Smrg    newpercent = (base * stuff->percent) / 100;
2140706f2543Smrg    if (stuff->percent < 0)
2141706f2543Smrg        newpercent = base + newpercent;
2142706f2543Smrg    else
2143706f2543Smrg	newpercent = base - newpercent + stuff->percent;
2144706f2543Smrg
2145706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2146706f2543Smrg        if ((dev == keybd ||
2147706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) &&
2148706f2543Smrg            dev->kbdfeed && dev->kbdfeed->BellProc) {
2149706f2543Smrg
2150706f2543Smrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess);
2151706f2543Smrg	    if (rc != Success)
2152706f2543Smrg		return rc;
2153706f2543Smrg            XkbHandleBell(FALSE, FALSE, dev, newpercent,
2154706f2543Smrg                          &dev->kbdfeed->ctrl, 0, None, NULL, client);
2155706f2543Smrg        }
2156706f2543Smrg    }
2157706f2543Smrg
2158706f2543Smrg    return Success;
2159706f2543Smrg}
2160706f2543Smrg
2161706f2543Smrgint
2162706f2543SmrgProcChangePointerControl(ClientPtr client)
2163706f2543Smrg{
2164706f2543Smrg    DeviceIntPtr dev, mouse = PickPointer(client);
2165706f2543Smrg    PtrCtrl ctrl;		/* might get BadValue part way through */
2166706f2543Smrg    int rc;
2167706f2543Smrg    REQUEST(xChangePointerControlReq);
2168706f2543Smrg    REQUEST_SIZE_MATCH(xChangePointerControlReq);
2169706f2543Smrg
2170706f2543Smrg    ctrl = mouse->ptrfeed->ctrl;
2171706f2543Smrg    if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
2172706f2543Smrg	client->errorValue = stuff->doAccel;
2173706f2543Smrg	return BadValue;
2174706f2543Smrg    }
2175706f2543Smrg    if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
2176706f2543Smrg	client->errorValue = stuff->doThresh;
2177706f2543Smrg	return BadValue;
2178706f2543Smrg    }
2179706f2543Smrg    if (stuff->doAccel) {
2180706f2543Smrg	if (stuff->accelNum == -1) {
2181706f2543Smrg	    ctrl.num = defaultPointerControl.num;
2182706f2543Smrg        }
2183706f2543Smrg	else if (stuff->accelNum < 0) {
2184706f2543Smrg	    client->errorValue = stuff->accelNum;
2185706f2543Smrg	    return BadValue;
2186706f2543Smrg	}
2187706f2543Smrg	else {
2188706f2543Smrg            ctrl.num = stuff->accelNum;
2189706f2543Smrg        }
2190706f2543Smrg
2191706f2543Smrg	if (stuff->accelDenum == -1) {
2192706f2543Smrg	    ctrl.den = defaultPointerControl.den;
2193706f2543Smrg        }
2194706f2543Smrg	else if (stuff->accelDenum <= 0) {
2195706f2543Smrg	    client->errorValue = stuff->accelDenum;
2196706f2543Smrg	    return BadValue;
2197706f2543Smrg	}
2198706f2543Smrg	else {
2199706f2543Smrg            ctrl.den = stuff->accelDenum;
2200706f2543Smrg        }
2201706f2543Smrg    }
2202706f2543Smrg    if (stuff->doThresh) {
2203706f2543Smrg	if (stuff->threshold == -1) {
2204706f2543Smrg	    ctrl.threshold = defaultPointerControl.threshold;
2205706f2543Smrg        }
2206706f2543Smrg	else if (stuff->threshold < 0) {
2207706f2543Smrg	    client->errorValue = stuff->threshold;
2208706f2543Smrg	    return BadValue;
2209706f2543Smrg	}
2210706f2543Smrg	else {
2211706f2543Smrg            ctrl.threshold = stuff->threshold;
2212706f2543Smrg        }
2213706f2543Smrg    }
2214706f2543Smrg
2215706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2216706f2543Smrg        if ((dev == mouse ||
2217706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2218706f2543Smrg            dev->ptrfeed) {
2219706f2543Smrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
2220706f2543Smrg	    if (rc != Success)
2221706f2543Smrg		return rc;
2222706f2543Smrg	}
2223706f2543Smrg    }
2224706f2543Smrg
2225706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2226706f2543Smrg        if ((dev == mouse ||
2227706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2228706f2543Smrg            dev->ptrfeed) {
2229706f2543Smrg            dev->ptrfeed->ctrl = ctrl;
2230706f2543Smrg        }
2231706f2543Smrg    }
2232706f2543Smrg
2233706f2543Smrg    return Success;
2234706f2543Smrg}
2235706f2543Smrg
2236706f2543Smrgint
2237706f2543SmrgProcGetPointerControl(ClientPtr client)
2238706f2543Smrg{
2239706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
2240706f2543Smrg    PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
2241706f2543Smrg    xGetPointerControlReply rep;
2242706f2543Smrg    int rc;
2243706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2244706f2543Smrg
2245706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
2246706f2543Smrg    if (rc != Success)
2247706f2543Smrg	return rc;
2248706f2543Smrg
2249706f2543Smrg    rep.type = X_Reply;
2250706f2543Smrg    rep.length = 0;
2251706f2543Smrg    rep.sequenceNumber = client->sequence;
2252706f2543Smrg    rep.threshold = ctrl->threshold;
2253706f2543Smrg    rep.accelNumerator = ctrl->num;
2254706f2543Smrg    rep.accelDenominator = ctrl->den;
2255706f2543Smrg    WriteReplyToClient(client, sizeof(xGenericReply), &rep);
2256706f2543Smrg    return Success;
2257706f2543Smrg}
2258706f2543Smrg
2259706f2543Smrgvoid
2260706f2543SmrgMaybeStopHint(DeviceIntPtr dev, ClientPtr client)
2261706f2543Smrg{
2262706f2543Smrg    GrabPtr grab = dev->deviceGrab.grab;
2263706f2543Smrg
2264706f2543Smrg    if ((grab && SameClient(grab, client) &&
2265706f2543Smrg	 ((grab->eventMask & PointerMotionHintMask) ||
2266706f2543Smrg	  (grab->ownerEvents &&
2267706f2543Smrg	   (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2268706f2543Smrg	    PointerMotionHintMask)))) ||
2269706f2543Smrg	(!grab &&
2270706f2543Smrg	 (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2271706f2543Smrg	  PointerMotionHintMask)))
2272706f2543Smrg	dev->valuator->motionHintWindow = NullWindow;
2273706f2543Smrg}
2274706f2543Smrg
2275706f2543Smrgint
2276706f2543SmrgProcGetMotionEvents(ClientPtr client)
2277706f2543Smrg{
2278706f2543Smrg    WindowPtr pWin;
2279706f2543Smrg    xTimecoord * coords = (xTimecoord *) NULL;
2280706f2543Smrg    xGetMotionEventsReply rep;
2281706f2543Smrg    int i, count, xmin, xmax, ymin, ymax, rc;
2282706f2543Smrg    unsigned long nEvents;
2283706f2543Smrg    DeviceIntPtr mouse = PickPointer(client);
2284706f2543Smrg    TimeStamp start, stop;
2285706f2543Smrg    REQUEST(xGetMotionEventsReq);
2286706f2543Smrg    REQUEST_SIZE_MATCH(xGetMotionEventsReq);
2287706f2543Smrg
2288706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2289706f2543Smrg    if (rc != Success)
2290706f2543Smrg	return rc;
2291706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
2292706f2543Smrg    if (rc != Success)
2293706f2543Smrg	return rc;
2294706f2543Smrg
2295706f2543Smrg    if (mouse->valuator->motionHintWindow)
2296706f2543Smrg	MaybeStopHint(mouse, client);
2297706f2543Smrg    rep.type = X_Reply;
2298706f2543Smrg    rep.sequenceNumber = client->sequence;
2299706f2543Smrg    nEvents = 0;
2300706f2543Smrg    start = ClientTimeToServerTime(stuff->start);
2301706f2543Smrg    stop = ClientTimeToServerTime(stuff->stop);
2302706f2543Smrg    if ((CompareTimeStamps(start, stop) != LATER) &&
2303706f2543Smrg	(CompareTimeStamps(start, currentTime) != LATER) &&
2304706f2543Smrg	mouse->valuator->numMotionEvents)
2305706f2543Smrg    {
2306706f2543Smrg	if (CompareTimeStamps(stop, currentTime) == LATER)
2307706f2543Smrg	    stop = currentTime;
2308706f2543Smrg	count = GetMotionHistory(mouse, &coords, start.milliseconds,
2309706f2543Smrg				 stop.milliseconds, pWin->drawable.pScreen,
2310706f2543Smrg                                 TRUE);
2311706f2543Smrg	xmin = pWin->drawable.x - wBorderWidth (pWin);
2312706f2543Smrg	xmax = pWin->drawable.x + (int)pWin->drawable.width +
2313706f2543Smrg		wBorderWidth (pWin);
2314706f2543Smrg	ymin = pWin->drawable.y - wBorderWidth (pWin);
2315706f2543Smrg	ymax = pWin->drawable.y + (int)pWin->drawable.height +
2316706f2543Smrg		wBorderWidth (pWin);
2317706f2543Smrg	for (i = 0; i < count; i++)
2318706f2543Smrg	    if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
2319706f2543Smrg		    (ymin <= coords[i].y) && (coords[i].y < ymax))
2320706f2543Smrg	    {
2321706f2543Smrg		coords[nEvents].time = coords[i].time;
2322706f2543Smrg		coords[nEvents].x = coords[i].x - pWin->drawable.x;
2323706f2543Smrg		coords[nEvents].y = coords[i].y - pWin->drawable.y;
2324706f2543Smrg		nEvents++;
2325706f2543Smrg	    }
2326706f2543Smrg    }
2327706f2543Smrg    rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord));
2328706f2543Smrg    rep.nEvents = nEvents;
2329706f2543Smrg    WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
2330706f2543Smrg    if (nEvents)
2331706f2543Smrg    {
2332706f2543Smrg	client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
2333706f2543Smrg	WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
2334706f2543Smrg				 (char *)coords);
2335706f2543Smrg    }
2336706f2543Smrg    free(coords);
2337706f2543Smrg    return Success;
2338706f2543Smrg}
2339706f2543Smrg
2340706f2543Smrgint
2341706f2543SmrgProcQueryKeymap(ClientPtr client)
2342706f2543Smrg{
2343706f2543Smrg    xQueryKeymapReply rep;
2344706f2543Smrg    int rc, i;
2345706f2543Smrg    DeviceIntPtr keybd = PickKeyboard(client);
2346706f2543Smrg    CARD8 *down = keybd->key->down;
2347706f2543Smrg
2348706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2349706f2543Smrg    rep.type = X_Reply;
2350706f2543Smrg    rep.sequenceNumber = client->sequence;
2351706f2543Smrg    rep.length = 2;
2352706f2543Smrg
2353706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
2354706f2543Smrg    if (rc != Success && rc != BadAccess)
2355706f2543Smrg	return rc;
2356706f2543Smrg
2357706f2543Smrg    for (i = 0; i<32; i++)
2358706f2543Smrg	rep.map[i] = down[i];
2359706f2543Smrg
2360706f2543Smrg    if (rc == BadAccess)
2361706f2543Smrg	memset(rep.map, 0, 32);
2362706f2543Smrg
2363706f2543Smrg    WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
2364706f2543Smrg
2365706f2543Smrg   return Success;
2366706f2543Smrg}
2367706f2543Smrg
2368706f2543Smrg
2369706f2543Smrg/**
2370706f2543Smrg * Recalculate the number of buttons for the master device. The number of
2371706f2543Smrg * buttons on the master device is equal to the number of buttons on the
2372706f2543Smrg * slave device with the highest number of buttons.
2373706f2543Smrg */
2374706f2543Smrgstatic void
2375706f2543SmrgRecalculateMasterButtons(DeviceIntPtr slave)
2376706f2543Smrg{
2377706f2543Smrg    DeviceIntPtr dev, master;
2378706f2543Smrg    int maxbuttons = 0;
2379706f2543Smrg
2380706f2543Smrg    if (!slave->button || IsMaster(slave))
2381706f2543Smrg        return;
2382706f2543Smrg
2383706f2543Smrg    master = GetMaster(slave, MASTER_POINTER);
2384706f2543Smrg    if (!master)
2385706f2543Smrg        return;
2386706f2543Smrg
2387706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
2388706f2543Smrg    {
2389706f2543Smrg        if (IsMaster(dev) ||
2390706f2543Smrg            dev->u.master != master ||
2391706f2543Smrg            !dev->button)
2392706f2543Smrg            continue;
2393706f2543Smrg
2394706f2543Smrg        maxbuttons = max(maxbuttons, dev->button->numButtons);
2395706f2543Smrg    }
2396706f2543Smrg
2397706f2543Smrg    if (master->button && master->button->numButtons != maxbuttons)
2398706f2543Smrg    {
2399706f2543Smrg        int i;
2400706f2543Smrg        DeviceChangedEvent event;
2401706f2543Smrg
2402706f2543Smrg        memset(&event, 0, sizeof(event));
2403706f2543Smrg
2404706f2543Smrg        master->button->numButtons = maxbuttons;
2405706f2543Smrg
2406706f2543Smrg        event.header = ET_Internal;
2407706f2543Smrg        event.type = ET_DeviceChanged;
2408706f2543Smrg        event.time = GetTimeInMillis();
2409706f2543Smrg        event.deviceid = master->id;
2410706f2543Smrg        event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE;
2411706f2543Smrg        event.buttons.num_buttons = maxbuttons;
2412706f2543Smrg        memcpy(&event.buttons.names, master->button->labels, maxbuttons *
2413706f2543Smrg                sizeof(Atom));
2414706f2543Smrg
2415706f2543Smrg        if (master->valuator)
2416706f2543Smrg        {
2417706f2543Smrg            event.num_valuators = master->valuator->numAxes;
2418706f2543Smrg            for (i = 0; i < event.num_valuators; i++)
2419706f2543Smrg            {
2420706f2543Smrg                event.valuators[i].min = master->valuator->axes[i].min_value;
2421706f2543Smrg                event.valuators[i].max = master->valuator->axes[i].max_value;
2422706f2543Smrg                event.valuators[i].resolution = master->valuator->axes[i].resolution;
2423706f2543Smrg                event.valuators[i].mode = master->valuator->axes[i].mode;
2424706f2543Smrg                event.valuators[i].name = master->valuator->axes[i].label;
2425706f2543Smrg            }
2426706f2543Smrg        }
2427706f2543Smrg
2428706f2543Smrg        if (master->key)
2429706f2543Smrg        {
2430706f2543Smrg            event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code;
2431706f2543Smrg            event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code;
2432706f2543Smrg        }
2433706f2543Smrg
2434706f2543Smrg        XISendDeviceChangedEvent(master, master, &event);
2435706f2543Smrg    }
2436706f2543Smrg}
2437706f2543Smrg
2438706f2543Smrg/**
2439706f2543Smrg * Generate release events for all keys/button currently down on this
2440706f2543Smrg * device.
2441706f2543Smrg */
2442706f2543Smrgvoid
2443706f2543SmrgReleaseButtonsAndKeys(DeviceIntPtr dev)
2444706f2543Smrg{
2445706f2543Smrg    EventListPtr        eventlist = InitEventList(GetMaximumEventsNum());
2446706f2543Smrg    ButtonClassPtr      b = dev->button;
2447706f2543Smrg    KeyClassPtr         k = dev->key;
2448706f2543Smrg    int                 i, j, nevents;
2449706f2543Smrg
2450706f2543Smrg    if (!eventlist) /* no release events for you */
2451706f2543Smrg        return;
2452706f2543Smrg
2453706f2543Smrg    /* Release all buttons */
2454706f2543Smrg    for (i = 0; b && i < b->numButtons; i++)
2455706f2543Smrg    {
2456706f2543Smrg        if (BitIsOn(b->down, i))
2457706f2543Smrg        {
2458706f2543Smrg            nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
2459706f2543Smrg            for (j = 0; j < nevents; j++)
2460706f2543Smrg                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2461706f2543Smrg        }
2462706f2543Smrg    }
2463706f2543Smrg
2464706f2543Smrg    /* Release all keys */
2465706f2543Smrg    for (i = 0; k && i < MAP_LENGTH; i++)
2466706f2543Smrg    {
2467706f2543Smrg        if (BitIsOn(k->down, i))
2468706f2543Smrg        {
2469706f2543Smrg            nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
2470706f2543Smrg            for (j = 0; j < nevents; j++)
2471706f2543Smrg                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2472706f2543Smrg        }
2473706f2543Smrg    }
2474706f2543Smrg
2475706f2543Smrg    FreeEventList(eventlist, GetMaximumEventsNum());
2476706f2543Smrg}
2477706f2543Smrg
2478706f2543Smrg/**
2479706f2543Smrg * Attach device 'dev' to device 'master'.
2480706f2543Smrg * Client is set to the client that issued the request, or NULL if it comes
2481706f2543Smrg * from some internal automatic pairing.
2482706f2543Smrg *
2483706f2543Smrg * Master may be NULL to set the device floating.
2484706f2543Smrg *
2485706f2543Smrg * We don't allow multi-layer hierarchies right now. You can't attach a slave
2486706f2543Smrg * to another slave.
2487706f2543Smrg */
2488706f2543Smrgint
2489706f2543SmrgAttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
2490706f2543Smrg{
2491706f2543Smrg    ScreenPtr screen;
2492706f2543Smrg    DeviceIntPtr oldmaster;
2493706f2543Smrg    if (!dev || IsMaster(dev))
2494706f2543Smrg        return BadDevice;
2495706f2543Smrg
2496706f2543Smrg    if (master && !IsMaster(master)) /* can't attach to slaves */
2497706f2543Smrg        return BadDevice;
2498706f2543Smrg
2499706f2543Smrg    /* set from floating to floating? */
2500706f2543Smrg    if (!dev->u.master && !master && dev->enabled)
2501706f2543Smrg        return Success;
2502706f2543Smrg
2503706f2543Smrg    /* free the existing sprite. */
2504706f2543Smrg    if (!dev->u.master && dev->spriteInfo->paired == dev)
2505706f2543Smrg    {
2506706f2543Smrg        screen = miPointerGetScreen(dev);
2507706f2543Smrg        screen->DeviceCursorCleanup(dev, screen);
2508706f2543Smrg        free(dev->spriteInfo->sprite);
2509706f2543Smrg    }
2510706f2543Smrg
2511706f2543Smrg    oldmaster = dev->u.master;
2512706f2543Smrg    dev->u.master = master;
2513706f2543Smrg
2514706f2543Smrg    /* If device is set to floating, we need to create a sprite for it,
2515706f2543Smrg     * otherwise things go bad. However, we don't want to render the cursor,
2516706f2543Smrg     * so we reset spriteOwner.
2517706f2543Smrg     * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
2518706f2543Smrg     * alloc new memory but overwrite the previous one.
2519706f2543Smrg     */
2520706f2543Smrg    if (!master)
2521706f2543Smrg    {
2522706f2543Smrg        WindowPtr currentRoot;
2523706f2543Smrg
2524706f2543Smrg        if (dev->spriteInfo->sprite)
2525706f2543Smrg            currentRoot = GetCurrentRootWindow(dev);
2526706f2543Smrg        else /* new device auto-set to floating */
2527706f2543Smrg            currentRoot = screenInfo.screens[0]->root;
2528706f2543Smrg
2529706f2543Smrg        /* we need to init a fake sprite */
2530706f2543Smrg        screen = currentRoot->drawable.pScreen;
2531706f2543Smrg        screen->DeviceCursorInitialize(dev, screen);
2532706f2543Smrg        dev->spriteInfo->sprite = NULL;
2533706f2543Smrg        InitializeSprite(dev, currentRoot);
2534706f2543Smrg        dev->spriteInfo->spriteOwner = FALSE;
2535706f2543Smrg        dev->spriteInfo->paired = dev;
2536706f2543Smrg    } else
2537706f2543Smrg    {
2538706f2543Smrg        dev->spriteInfo->sprite = master->spriteInfo->sprite;
2539706f2543Smrg        dev->spriteInfo->paired = master;
2540706f2543Smrg        dev->spriteInfo->spriteOwner = FALSE;
2541706f2543Smrg
2542706f2543Smrg        RecalculateMasterButtons(master);
2543706f2543Smrg    }
2544706f2543Smrg
2545706f2543Smrg    /* XXX: in theory, the MD should change back to its old, original
2546706f2543Smrg     * classes when the last SD is detached. Thanks to the XTEST devices,
2547706f2543Smrg     * we'll always have an SD attached until the MD is removed.
2548706f2543Smrg     * So let's not worry about that.
2549706f2543Smrg     */
2550706f2543Smrg
2551706f2543Smrg    return Success;
2552706f2543Smrg}
2553706f2543Smrg
2554706f2543Smrg/**
2555706f2543Smrg * Return the device paired with the given device or NULL.
2556706f2543Smrg * Returns the device paired with the parent master if the given device is a
2557706f2543Smrg * slave device.
2558706f2543Smrg */
2559706f2543SmrgDeviceIntPtr
2560706f2543SmrgGetPairedDevice(DeviceIntPtr dev)
2561706f2543Smrg{
2562706f2543Smrg    if (!IsMaster(dev) && dev->u.master)
2563706f2543Smrg        dev = dev->u.master;
2564706f2543Smrg
2565706f2543Smrg    return dev->spriteInfo->paired;
2566706f2543Smrg}
2567706f2543Smrg
2568706f2543Smrg
2569706f2543Smrg/**
2570706f2543Smrg * Returns the right master for the type of event needed. If the event is a
2571706f2543Smrg * keyboard event.
2572706f2543Smrg * This function may be called with a master device as argument. If so, the
2573706f2543Smrg * returned master is either the device itself or the paired master device.
2574706f2543Smrg * If dev is a floating slave device, NULL is returned.
2575706f2543Smrg *
2576706f2543Smrg * @type ::MASTER_KEYBOARD or ::MASTER_POINTER
2577706f2543Smrg */
2578706f2543SmrgDeviceIntPtr
2579706f2543SmrgGetMaster(DeviceIntPtr dev, int which)
2580706f2543Smrg{
2581706f2543Smrg    DeviceIntPtr master;
2582706f2543Smrg
2583706f2543Smrg    if (IsMaster(dev))
2584706f2543Smrg        master = dev;
2585706f2543Smrg    else
2586706f2543Smrg        master = dev->u.master;
2587706f2543Smrg
2588706f2543Smrg    if (master)
2589706f2543Smrg    {
2590706f2543Smrg        if (which == MASTER_KEYBOARD)
2591706f2543Smrg        {
2592706f2543Smrg            if (master->type != MASTER_KEYBOARD)
2593706f2543Smrg                master = GetPairedDevice(master);
2594706f2543Smrg        } else
2595706f2543Smrg        {
2596706f2543Smrg            if (master->type != MASTER_POINTER)
2597706f2543Smrg                master = GetPairedDevice(master);
2598706f2543Smrg        }
2599706f2543Smrg    }
2600706f2543Smrg
2601706f2543Smrg    return master;
2602706f2543Smrg}
2603706f2543Smrg
2604706f2543Smrg/**
2605706f2543Smrg * Create a new device pair (== one pointer, one keyboard device).
2606706f2543Smrg * Only allocates the devices, you will need to call ActivateDevice() and
2607706f2543Smrg * EnableDevice() manually.
2608706f2543Smrg * Either a master or a slave device can be created depending on
2609706f2543Smrg * the value for master.
2610706f2543Smrg */
2611706f2543Smrgint
2612706f2543SmrgAllocDevicePair (ClientPtr client, char* name,
2613706f2543Smrg                 DeviceIntPtr* ptr,
2614706f2543Smrg                 DeviceIntPtr* keybd,
2615706f2543Smrg                 DeviceProc ptr_proc,
2616706f2543Smrg                 DeviceProc keybd_proc,
2617706f2543Smrg                 Bool master)
2618706f2543Smrg{
2619706f2543Smrg    DeviceIntPtr pointer;
2620706f2543Smrg    DeviceIntPtr keyboard;
2621706f2543Smrg    *ptr = *keybd = NULL;
2622706f2543Smrg
2623706f2543Smrg    pointer = AddInputDevice(client, ptr_proc, TRUE);
2624706f2543Smrg    if (!pointer)
2625706f2543Smrg        return BadAlloc;
2626706f2543Smrg
2627706f2543Smrg    if (asprintf(&pointer->name, "%s pointer", name) == -1) {
2628706f2543Smrg        pointer->name = NULL;
2629706f2543Smrg        RemoveDevice(pointer, FALSE);
2630706f2543Smrg        return BadAlloc;
2631706f2543Smrg    }
2632706f2543Smrg
2633706f2543Smrg    pointer->public.processInputProc = ProcessOtherEvent;
2634706f2543Smrg    pointer->public.realInputProc = ProcessOtherEvent;
2635706f2543Smrg    XkbSetExtension(pointer, ProcessPointerEvent);
2636706f2543Smrg    pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
2637706f2543Smrg    pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
2638706f2543Smrg    pointer->coreEvents = TRUE;
2639706f2543Smrg    pointer->spriteInfo->spriteOwner = TRUE;
2640706f2543Smrg
2641706f2543Smrg    pointer->u.lastSlave = NULL;
2642706f2543Smrg    pointer->last.slave = NULL;
2643706f2543Smrg    pointer->type = (master) ? MASTER_POINTER : SLAVE;
2644706f2543Smrg
2645706f2543Smrg    keyboard = AddInputDevice(client, keybd_proc, TRUE);
2646706f2543Smrg    if (!keyboard)
2647706f2543Smrg    {
2648706f2543Smrg        RemoveDevice(pointer, FALSE);
2649706f2543Smrg        return BadAlloc;
2650706f2543Smrg    }
2651706f2543Smrg
2652706f2543Smrg    if (asprintf(&keyboard->name, "%s keyboard", name) == -1) {
2653706f2543Smrg        keyboard->name = NULL;
2654706f2543Smrg        RemoveDevice(keyboard, FALSE);
2655706f2543Smrg        RemoveDevice(pointer, FALSE);
2656706f2543Smrg        return BadAlloc;
2657706f2543Smrg    }
2658706f2543Smrg
2659706f2543Smrg    keyboard->public.processInputProc = ProcessOtherEvent;
2660706f2543Smrg    keyboard->public.realInputProc = ProcessOtherEvent;
2661706f2543Smrg    XkbSetExtension(keyboard, ProcessKeyboardEvent);
2662706f2543Smrg    keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
2663706f2543Smrg    keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
2664706f2543Smrg    keyboard->coreEvents = TRUE;
2665706f2543Smrg    keyboard->spriteInfo->spriteOwner = FALSE;
2666706f2543Smrg
2667706f2543Smrg    keyboard->u.lastSlave = NULL;
2668706f2543Smrg    keyboard->last.slave = NULL;
2669706f2543Smrg    keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
2670706f2543Smrg
2671706f2543Smrg    /* The ClassesRec stores the device classes currently not used. */
2672706f2543Smrg    pointer->unused_classes = calloc(1, sizeof(ClassesRec));
2673706f2543Smrg    keyboard->unused_classes = calloc(1, sizeof(ClassesRec));
2674706f2543Smrg
2675706f2543Smrg    *ptr = pointer;
2676706f2543Smrg    *keybd = keyboard;
2677706f2543Smrg
2678706f2543Smrg    return Success;
2679706f2543Smrg}
2680706f2543Smrg
2681706f2543Smrg/**
2682706f2543Smrg * Return Relative or Absolute for the device.
2683706f2543Smrg */
2684706f2543Smrgint valuator_get_mode(DeviceIntPtr dev, int axis)
2685706f2543Smrg{
2686706f2543Smrg    return (dev->valuator->axes[axis].mode & DeviceMode);
2687706f2543Smrg}
2688706f2543Smrg
2689706f2543Smrg/**
2690706f2543Smrg * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then
2691706f2543Smrg * set the mode for all axes.
2692706f2543Smrg */
2693706f2543Smrgvoid valuator_set_mode(DeviceIntPtr dev, int axis, int mode)
2694706f2543Smrg{
2695706f2543Smrg    if (axis != VALUATOR_MODE_ALL_AXES)
2696706f2543Smrg        dev->valuator->axes[axis].mode = mode;
2697706f2543Smrg    else {
2698706f2543Smrg        int i;
2699706f2543Smrg        for (i = 0; i < dev->valuator->numAxes; i++)
2700706f2543Smrg            dev->valuator->axes[i].mode = mode;
2701706f2543Smrg    }
2702706f2543Smrg}
2703