devices.c revision 91d321ac
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        }
480706f2543Smrg    }
481706f2543Smrg
482706f2543Smrg    (void)(*dev->deviceProc)(dev, DEVICE_OFF);
483706f2543Smrg    dev->enabled = FALSE;
484706f2543Smrg
485706f2543Smrg    /* now that the device is disabled, we can reset the signal handler's
486706f2543Smrg     * last.slave */
487706f2543Smrg    OsBlockSignals();
488706f2543Smrg    for (other = inputInfo.devices; other; other = other->next)
489706f2543Smrg    {
490706f2543Smrg        if (other->last.slave == dev)
491706f2543Smrg            other->last.slave = NULL;
492706f2543Smrg    }
493706f2543Smrg    OsReleaseSignals();
494706f2543Smrg
495706f2543Smrg    LeaveWindow(dev);
496706f2543Smrg    SetFocusOut(dev);
497706f2543Smrg
49891d321acSmrg    for (prev = &inputInfo.devices;
49991d321acSmrg         *prev && (*prev != dev); prev = &(*prev)->next);
50091d321acSmrg
501706f2543Smrg    *prev = dev->next;
502706f2543Smrg    dev->next = inputInfo.off_devices;
503706f2543Smrg    inputInfo.off_devices = dev;
504706f2543Smrg
505706f2543Smrg    enabled = FALSE;
506706f2543Smrg    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
507706f2543Smrg                           XA_INTEGER, 8, PropModeReplace, 1, &enabled,
508706f2543Smrg                           TRUE);
509706f2543Smrg
510706f2543Smrg    SendDevicePresenceEvent(dev->id, DeviceDisabled);
511706f2543Smrg    if (sendevent)
512706f2543Smrg    {
513706f2543Smrg        flags[dev->id] = XIDeviceDisabled;
514706f2543Smrg        XISendDeviceHierarchyEvent(flags);
515706f2543Smrg    }
516706f2543Smrg
517706f2543Smrg    RecalculateMasterButtons(dev);
518706f2543Smrg
519706f2543Smrg    return TRUE;
520706f2543Smrg}
521706f2543Smrg
522706f2543Smrg/**
523706f2543Smrg * Initialise a new device through the driver and tell all clients about the
524706f2543Smrg * new device.
525706f2543Smrg *
526706f2543Smrg * Must be called before EnableDevice.
527706f2543Smrg * The device will NOT send events until it is enabled!
528706f2543Smrg *
529706f2543Smrg * @param sendevent True if an XI2 event should be sent.
530706f2543Smrg * @return Success or an error code on failure.
531706f2543Smrg */
532706f2543Smrgint
533706f2543SmrgActivateDevice(DeviceIntPtr dev, BOOL sendevent)
534706f2543Smrg{
535706f2543Smrg    int ret = Success;
536706f2543Smrg    ScreenPtr pScreen = screenInfo.screens[0];
537706f2543Smrg
538706f2543Smrg    if (!dev || !dev->deviceProc)
539706f2543Smrg        return BadImplementation;
540706f2543Smrg
541706f2543Smrg    ret = (*dev->deviceProc) (dev, DEVICE_INIT);
542706f2543Smrg    dev->inited = (ret == Success);
543706f2543Smrg    if (!dev->inited)
544706f2543Smrg        return ret;
545706f2543Smrg
546706f2543Smrg    /* Initialize memory for sprites. */
547706f2543Smrg    if (IsMaster(dev) && dev->spriteInfo->spriteOwner)
548706f2543Smrg        if (!pScreen->DeviceCursorInitialize(dev, pScreen))
549706f2543Smrg            ret = BadAlloc;
550706f2543Smrg
551706f2543Smrg    SendDevicePresenceEvent(dev->id, DeviceAdded);
552706f2543Smrg    if (sendevent)
553706f2543Smrg    {
554706f2543Smrg        int flags[MAXDEVICES] = {0};
555706f2543Smrg        flags[dev->id] = XISlaveAdded;
556706f2543Smrg        XISendDeviceHierarchyEvent(flags);
557706f2543Smrg    }
558706f2543Smrg    return ret;
559706f2543Smrg}
560706f2543Smrg
561706f2543Smrg/**
562706f2543Smrg * Ring the bell.
563706f2543Smrg * The actual task of ringing the bell is the job of the DDX.
564706f2543Smrg */
565706f2543Smrgstatic void
566706f2543SmrgCoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
567706f2543Smrg{
568706f2543Smrg    KeybdCtrl *ctrl = arg;
569706f2543Smrg
570706f2543Smrg    DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
571706f2543Smrg}
572706f2543Smrg
573706f2543Smrgstatic void
574706f2543SmrgCoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
575706f2543Smrg{
576706f2543Smrg    return;
577706f2543Smrg}
578706f2543Smrg
579706f2543Smrg/**
580706f2543Smrg * Device control function for the Virtual Core Keyboard.
581706f2543Smrg */
582706f2543Smrgint
583706f2543SmrgCoreKeyboardProc(DeviceIntPtr pDev, int what)
584706f2543Smrg{
585706f2543Smrg
586706f2543Smrg    switch (what) {
587706f2543Smrg    case DEVICE_INIT:
588706f2543Smrg        if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell,
589706f2543Smrg                                      CoreKeyboardCtl))
590706f2543Smrg        {
591706f2543Smrg            ErrorF("Keyboard initialization failed. This could be a missing "
592706f2543Smrg                   "or incorrect setup of xkeyboard-config.\n");
593706f2543Smrg            return BadValue;
594706f2543Smrg        }
595706f2543Smrg        return Success;
596706f2543Smrg
597706f2543Smrg    case DEVICE_ON:
598706f2543Smrg    case DEVICE_OFF:
599706f2543Smrg        return Success;
600706f2543Smrg
601706f2543Smrg    case DEVICE_CLOSE:
602706f2543Smrg        return Success;
603706f2543Smrg    }
604706f2543Smrg
605706f2543Smrg    return BadMatch;
606706f2543Smrg}
607706f2543Smrg
608706f2543Smrg/**
609706f2543Smrg * Device control function for the Virtual Core Pointer.
610706f2543Smrg */
611706f2543Smrgint
612706f2543SmrgCorePointerProc(DeviceIntPtr pDev, int what)
613706f2543Smrg{
614706f2543Smrg#define NBUTTONS 10
615706f2543Smrg#define NAXES 2
616706f2543Smrg    BYTE map[NBUTTONS + 1];
617706f2543Smrg    int i = 0;
618706f2543Smrg    Atom btn_labels[NBUTTONS] = {0};
619706f2543Smrg    Atom axes_labels[NAXES] = {0};
620706f2543Smrg
621706f2543Smrg    switch (what) {
622706f2543Smrg    case DEVICE_INIT:
623706f2543Smrg        for (i = 1; i <= NBUTTONS; i++)
624706f2543Smrg            map[i] = i;
625706f2543Smrg
626706f2543Smrg	btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
627706f2543Smrg	btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
628706f2543Smrg	btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
629706f2543Smrg	btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
630706f2543Smrg	btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
631706f2543Smrg	btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
632706f2543Smrg	btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
633706f2543Smrg	/* don't know about the rest */
634706f2543Smrg
635706f2543Smrg	axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
636706f2543Smrg	axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
637706f2543Smrg
638706f2543Smrg        if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels,
639706f2543Smrg                                (PtrCtrlProcPtr)NoopDDA,
640706f2543Smrg                                GetMotionHistorySize(), NAXES, axes_labels))
641706f2543Smrg        {
642706f2543Smrg            ErrorF("Could not initialize device '%s'. Out of memory.\n",
643706f2543Smrg                   pDev->name);
644706f2543Smrg            return BadAlloc; /* IPDS only fails on allocs */
645706f2543Smrg        }
646706f2543Smrg        pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
647706f2543Smrg        pDev->last.valuators[0] = pDev->valuator->axisVal[0];
648706f2543Smrg        pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
649706f2543Smrg        pDev->last.valuators[1] = pDev->valuator->axisVal[1];
650706f2543Smrg        break;
651706f2543Smrg
652706f2543Smrg    case DEVICE_CLOSE:
653706f2543Smrg        break;
654706f2543Smrg
655706f2543Smrg    default:
656706f2543Smrg        break;
657706f2543Smrg    }
658706f2543Smrg
659706f2543Smrg    return Success;
660706f2543Smrg
661706f2543Smrg#undef NBUTTONS
662706f2543Smrg#undef NAXES
663706f2543Smrg}
664706f2543Smrg
665706f2543Smrg/**
666706f2543Smrg * Initialise the two core devices, VCP and VCK (see events.c).
667706f2543Smrg * Both devices are not tied to physical devices, but guarantee that there is
668706f2543Smrg * always a keyboard and a pointer present and keep the protocol semantics.
669706f2543Smrg *
670706f2543Smrg * Note that the server MUST have two core devices at all times, even if there
671706f2543Smrg * is no physical device connected.
672706f2543Smrg */
673706f2543Smrgvoid
674706f2543SmrgInitCoreDevices(void)
675706f2543Smrg{
676706f2543Smrg    if (AllocDevicePair(serverClient, "Virtual core",
677706f2543Smrg                        &inputInfo.pointer, &inputInfo.keyboard,
678706f2543Smrg                        CorePointerProc, CoreKeyboardProc,
679706f2543Smrg                        TRUE) != Success)
680706f2543Smrg        FatalError("Failed to allocate core devices");
681706f2543Smrg
682706f2543Smrg    if (ActivateDevice(inputInfo.pointer, TRUE) != Success ||
683706f2543Smrg        ActivateDevice(inputInfo.keyboard, TRUE) != Success)
684706f2543Smrg        FatalError("Failed to activate core devices.");
685706f2543Smrg    if (!EnableDevice(inputInfo.pointer, TRUE) ||
686706f2543Smrg        !EnableDevice(inputInfo.keyboard, TRUE))
687706f2543Smrg        FatalError("Failed to enable core devices.");
688706f2543Smrg
689706f2543Smrg    InitXTestDevices();
690706f2543Smrg}
691706f2543Smrg
692706f2543Smrg/**
693706f2543Smrg * Activate all switched-off devices and then enable all those devices.
694706f2543Smrg *
695706f2543Smrg * Will return an error if no core keyboard or core pointer is present.
696706f2543Smrg * In theory this should never happen if you call InitCoreDevices() first.
697706f2543Smrg *
698706f2543Smrg * InitAndStartDevices needs to be called AFTER the windows are initialized.
699706f2543Smrg * Devices will start sending events after InitAndStartDevices() has
700706f2543Smrg * completed.
701706f2543Smrg *
702706f2543Smrg * @return Success or error code on failure.
703706f2543Smrg */
704706f2543Smrgint
705706f2543SmrgInitAndStartDevices(void)
706706f2543Smrg{
707706f2543Smrg    DeviceIntPtr dev, next;
708706f2543Smrg
709706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = dev->next) {
710706f2543Smrg        DebugF("(dix) initialising device %d\n", dev->id);
711706f2543Smrg        if (!dev->inited)
712706f2543Smrg            ActivateDevice(dev, TRUE);
713706f2543Smrg    }
714706f2543Smrg
715706f2543Smrg    /* enable real devices */
716706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = next)
717706f2543Smrg    {
718706f2543Smrg        DebugF("(dix) enabling device %d\n", dev->id);
719706f2543Smrg	next = dev->next;
720706f2543Smrg	if (dev->inited && dev->startup)
721706f2543Smrg	    EnableDevice(dev, TRUE);
722706f2543Smrg    }
723706f2543Smrg
724706f2543Smrg    return Success;
725706f2543Smrg}
726706f2543Smrg
727706f2543Smrg/**
728706f2543Smrg * Free the given device class and reset the pointer to NULL.
729706f2543Smrg */
730706f2543Smrgstatic void
731706f2543SmrgFreeDeviceClass(int type, pointer *class)
732706f2543Smrg{
733706f2543Smrg    if (!(*class))
734706f2543Smrg        return;
735706f2543Smrg
736706f2543Smrg    switch(type)
737706f2543Smrg    {
738706f2543Smrg        case KeyClass:
739706f2543Smrg            {
740706f2543Smrg                KeyClassPtr* k = (KeyClassPtr*)class;
741706f2543Smrg                if ((*k)->xkbInfo)
742706f2543Smrg                {
743706f2543Smrg                    XkbFreeInfo((*k)->xkbInfo);
744706f2543Smrg                    (*k)->xkbInfo = NULL;
745706f2543Smrg                }
746706f2543Smrg                free((*k));
747706f2543Smrg                break;
748706f2543Smrg            }
749706f2543Smrg        case ButtonClass:
750706f2543Smrg            {
751706f2543Smrg                ButtonClassPtr *b = (ButtonClassPtr*)class;
752706f2543Smrg                free((*b)->xkb_acts);
753706f2543Smrg                free((*b));
754706f2543Smrg                break;
755706f2543Smrg            }
756706f2543Smrg        case ValuatorClass:
757706f2543Smrg            {
758706f2543Smrg                ValuatorClassPtr *v = (ValuatorClassPtr*)class;
759706f2543Smrg
760706f2543Smrg                free((*v)->motion);
761706f2543Smrg                free((*v));
762706f2543Smrg                break;
763706f2543Smrg            }
764706f2543Smrg        case FocusClass:
765706f2543Smrg            {
766706f2543Smrg                FocusClassPtr *f = (FocusClassPtr*)class;
767706f2543Smrg                free((*f)->trace);
768706f2543Smrg                free((*f));
769706f2543Smrg                break;
770706f2543Smrg            }
771706f2543Smrg        case ProximityClass:
772706f2543Smrg            {
773706f2543Smrg                ProximityClassPtr *p = (ProximityClassPtr*)class;
774706f2543Smrg                free((*p));
775706f2543Smrg                break;
776706f2543Smrg            }
777706f2543Smrg    }
778706f2543Smrg    *class = NULL;
779706f2543Smrg}
780706f2543Smrg
781706f2543Smrgstatic void
782706f2543SmrgFreeFeedbackClass(int type, pointer *class)
783706f2543Smrg{
784706f2543Smrg    if (!(*class))
785706f2543Smrg        return;
786706f2543Smrg
787706f2543Smrg    switch(type)
788706f2543Smrg    {
789706f2543Smrg        case KbdFeedbackClass:
790706f2543Smrg            {
791706f2543Smrg                KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
792706f2543Smrg                KbdFeedbackPtr k, knext;
793706f2543Smrg                for (k = (*kbdfeed); k; k = knext) {
794706f2543Smrg                    knext = k->next;
795706f2543Smrg                    if (k->xkb_sli)
796706f2543Smrg                        XkbFreeSrvLedInfo(k->xkb_sli);
797706f2543Smrg                    free(k);
798706f2543Smrg                }
799706f2543Smrg                break;
800706f2543Smrg            }
801706f2543Smrg        case PtrFeedbackClass:
802706f2543Smrg            {
803706f2543Smrg                PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
804706f2543Smrg                PtrFeedbackPtr p, pnext;
805706f2543Smrg
806706f2543Smrg                for (p = (*ptrfeed); p; p = pnext) {
807706f2543Smrg                    pnext = p->next;
808706f2543Smrg                    free(p);
809706f2543Smrg                }
810706f2543Smrg                break;
811706f2543Smrg            }
812706f2543Smrg        case IntegerFeedbackClass:
813706f2543Smrg            {
814706f2543Smrg                IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
815706f2543Smrg                IntegerFeedbackPtr i, inext;
816706f2543Smrg
817706f2543Smrg                for (i = (*intfeed); i; i = inext) {
818706f2543Smrg                    inext = i->next;
819706f2543Smrg                    free(i);
820706f2543Smrg                }
821706f2543Smrg                break;
822706f2543Smrg            }
823706f2543Smrg        case StringFeedbackClass:
824706f2543Smrg            {
825706f2543Smrg                StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
826706f2543Smrg                StringFeedbackPtr s, snext;
827706f2543Smrg
828706f2543Smrg                for (s = (*stringfeed); s; s = snext) {
829706f2543Smrg                    snext = s->next;
830706f2543Smrg                    free(s->ctrl.symbols_supported);
831706f2543Smrg                    free(s->ctrl.symbols_displayed);
832706f2543Smrg                    free(s);
833706f2543Smrg                }
834706f2543Smrg                break;
835706f2543Smrg            }
836706f2543Smrg        case BellFeedbackClass:
837706f2543Smrg            {
838706f2543Smrg                BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
839706f2543Smrg                BellFeedbackPtr b, bnext;
840706f2543Smrg
841706f2543Smrg                for (b = (*bell); b; b = bnext) {
842706f2543Smrg                    bnext = b->next;
843706f2543Smrg                    free(b);
844706f2543Smrg                }
845706f2543Smrg                break;
846706f2543Smrg            }
847706f2543Smrg        case LedFeedbackClass:
848706f2543Smrg            {
849706f2543Smrg                LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
850706f2543Smrg                LedFeedbackPtr l, lnext;
851706f2543Smrg
852706f2543Smrg                for (l = (*leds); l; l = lnext) {
853706f2543Smrg                    lnext = l->next;
854706f2543Smrg                    if (l->xkb_sli)
855706f2543Smrg                        XkbFreeSrvLedInfo(l->xkb_sli);
856706f2543Smrg                    free(l);
857706f2543Smrg                }
858706f2543Smrg                break;
859706f2543Smrg            }
860706f2543Smrg    }
861706f2543Smrg    *class = NULL;
862706f2543Smrg}
863706f2543Smrg
864706f2543Smrgstatic void
865706f2543SmrgFreeAllDeviceClasses(ClassesPtr classes)
866706f2543Smrg{
867706f2543Smrg    if (!classes)
868706f2543Smrg        return;
869706f2543Smrg
870706f2543Smrg    FreeDeviceClass(KeyClass, (pointer)&classes->key);
871706f2543Smrg    FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
872706f2543Smrg    FreeDeviceClass(ButtonClass, (pointer)&classes->button);
873706f2543Smrg    FreeDeviceClass(FocusClass, (pointer)&classes->focus);
874706f2543Smrg    FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
875706f2543Smrg
876706f2543Smrg    FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
877706f2543Smrg    FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
878706f2543Smrg    FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
879706f2543Smrg    FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
880706f2543Smrg    FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
881706f2543Smrg    FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
882706f2543Smrg
883706f2543Smrg}
884706f2543Smrg
885706f2543Smrg/**
886706f2543Smrg * Close down a device and free all resources.
887706f2543Smrg * Once closed down, the driver will probably not expect you that you'll ever
888706f2543Smrg * enable it again and free associated structs. If you want the device to just
889706f2543Smrg * be disabled, DisableDevice().
890706f2543Smrg * Don't call this function directly, use RemoveDevice() instead.
891706f2543Smrg */
892706f2543Smrgstatic void
893706f2543SmrgCloseDevice(DeviceIntPtr dev)
894706f2543Smrg{
895706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
896706f2543Smrg    ClassesPtr classes;
897706f2543Smrg    int j;
898706f2543Smrg
899706f2543Smrg    if (!dev)
900706f2543Smrg        return;
901706f2543Smrg
902706f2543Smrg    XIDeleteAllDeviceProperties(dev);
903706f2543Smrg
904706f2543Smrg    if (dev->inited)
905706f2543Smrg	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
906706f2543Smrg
907706f2543Smrg    /* free sprite memory */
908706f2543Smrg    if (IsMaster(dev) && dev->spriteInfo->sprite)
909706f2543Smrg        screen->DeviceCursorCleanup(dev, screen);
910706f2543Smrg
911706f2543Smrg    /* free acceleration info */
912706f2543Smrg    if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
913706f2543Smrg	dev->valuator->accelScheme.AccelCleanupProc(dev);
914706f2543Smrg
915706f2543Smrg    while (dev->xkb_interest)
916706f2543Smrg	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
917706f2543Smrg
918706f2543Smrg    free(dev->name);
919706f2543Smrg
920706f2543Smrg    classes = (ClassesPtr)&dev->key;
921706f2543Smrg    FreeAllDeviceClasses(classes);
922706f2543Smrg
923706f2543Smrg    if (IsMaster(dev))
924706f2543Smrg    {
925706f2543Smrg        classes = dev->unused_classes;
926706f2543Smrg        FreeAllDeviceClasses(classes);
927706f2543Smrg	free(classes);
928706f2543Smrg    }
929706f2543Smrg
930706f2543Smrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
931706f2543Smrg	if (dev->spriteInfo->sprite->current)
932706f2543Smrg	    FreeCursor(dev->spriteInfo->sprite->current, None);
933706f2543Smrg        free(dev->spriteInfo->sprite->spriteTrace);
934706f2543Smrg        free(dev->spriteInfo->sprite);
935706f2543Smrg    }
936706f2543Smrg
937706f2543Smrg    /* a client may have the device set as client pointer */
938706f2543Smrg    for (j = 0; j < currentMaxClients; j++)
939706f2543Smrg    {
940706f2543Smrg        if (clients[j] && clients[j]->clientPtr == dev)
941706f2543Smrg        {
942706f2543Smrg            clients[j]->clientPtr = NULL;
943706f2543Smrg            clients[j]->clientPtr = PickPointer(clients[j]);
944706f2543Smrg        }
945706f2543Smrg    }
946706f2543Smrg
947706f2543Smrg    free(dev->deviceGrab.sync.event);
948706f2543Smrg    free(dev->config_info);     /* Allocated in xf86ActivateDevice. */
949706f2543Smrg    dev->config_info = NULL;
950706f2543Smrg    dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
951706f2543Smrg}
952706f2543Smrg
953706f2543Smrg/**
954706f2543Smrg * Shut down all devices of one list and free all resources.
955706f2543Smrg */
956706f2543Smrgstatic
957706f2543Smrgvoid
958706f2543SmrgCloseDeviceList(DeviceIntPtr *listHead)
959706f2543Smrg{
960706f2543Smrg    /* Used to mark devices that we tried to free */
961706f2543Smrg    Bool freedIds[MAXDEVICES];
962706f2543Smrg    DeviceIntPtr dev;
963706f2543Smrg    int i;
964706f2543Smrg
965706f2543Smrg    if (listHead == NULL)
966706f2543Smrg        return;
967706f2543Smrg
968706f2543Smrg    for (i = 0; i < MAXDEVICES; i++)
969706f2543Smrg        freedIds[i] = FALSE;
970706f2543Smrg
971706f2543Smrg    dev = *listHead;
972706f2543Smrg    while (dev != NULL)
973706f2543Smrg    {
974706f2543Smrg        freedIds[dev->id] = TRUE;
975706f2543Smrg        DeleteInputDeviceRequest(dev);
976706f2543Smrg
977706f2543Smrg        dev = *listHead;
978706f2543Smrg        while (dev != NULL && freedIds[dev->id])
979706f2543Smrg            dev = dev->next;
980706f2543Smrg    }
981706f2543Smrg}
982706f2543Smrg
983706f2543Smrg/**
984706f2543Smrg * Shut down all devices, free all resources, etc.
985706f2543Smrg * Only useful if you're shutting down the server!
986706f2543Smrg */
987706f2543Smrgvoid
988706f2543SmrgCloseDownDevices(void)
989706f2543Smrg{
990706f2543Smrg    DeviceIntPtr dev;
991706f2543Smrg
992706f2543Smrg    OsBlockSignals();
993706f2543Smrg
994706f2543Smrg    /* Float all SDs before closing them. Note that at this point resources
995706f2543Smrg     * (e.g. cursors) have been freed already, so we can't just call
996706f2543Smrg     * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
997706f2543Smrg     * to NULL and pretend nothing happened.
998706f2543Smrg     */
999706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
1000706f2543Smrg    {
1001706f2543Smrg        if (!IsMaster(dev) && dev->u.master)
1002706f2543Smrg            dev->u.master = NULL;
1003706f2543Smrg    }
1004706f2543Smrg
1005706f2543Smrg    CloseDeviceList(&inputInfo.devices);
1006706f2543Smrg    CloseDeviceList(&inputInfo.off_devices);
1007706f2543Smrg
1008706f2543Smrg    CloseDevice(inputInfo.pointer);
1009706f2543Smrg    CloseDevice(inputInfo.keyboard);
1010706f2543Smrg
1011706f2543Smrg    inputInfo.devices = NULL;
1012706f2543Smrg    inputInfo.off_devices = NULL;
1013706f2543Smrg    inputInfo.keyboard = NULL;
1014706f2543Smrg    inputInfo.pointer = NULL;
1015706f2543Smrg    XkbDeleteRulesDflts();
1016706f2543Smrg
1017706f2543Smrg    OsReleaseSignals();
1018706f2543Smrg}
1019706f2543Smrg
1020706f2543Smrg/**
1021706f2543Smrg * Remove the cursor sprite for all devices. This needs to be done before any
1022706f2543Smrg * resources are freed or any device is deleted.
1023706f2543Smrg */
1024706f2543Smrgvoid
1025706f2543SmrgUndisplayDevices(void)
1026706f2543Smrg{
1027706f2543Smrg    DeviceIntPtr dev;
1028706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
1029706f2543Smrg
1030706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
1031706f2543Smrg        screen->DisplayCursor(dev, screen, NullCursor);
1032706f2543Smrg}
1033706f2543Smrg
1034706f2543Smrg/**
1035706f2543Smrg * Remove a device from the device list, closes it and thus frees all
1036706f2543Smrg * resources.
1037706f2543Smrg * Removes both enabled and disabled devices and notifies all devices about
1038706f2543Smrg * the removal of the device.
1039706f2543Smrg *
1040706f2543Smrg * No PresenceNotify is sent for device that the client never saw. This can
1041706f2543Smrg * happen if a malloc fails during the addition of master devices. If
1042706f2543Smrg * dev->init is FALSE it means the client never received a DeviceAdded event,
1043706f2543Smrg * so let's not send a DeviceRemoved event either.
1044706f2543Smrg *
1045706f2543Smrg * @param sendevent True if an XI2 event should be sent.
1046706f2543Smrg */
1047706f2543Smrgint
1048706f2543SmrgRemoveDevice(DeviceIntPtr dev, BOOL sendevent)
1049706f2543Smrg{
1050706f2543Smrg    DeviceIntPtr prev,tmp,next;
1051706f2543Smrg    int ret = BadMatch;
1052706f2543Smrg    ScreenPtr screen = screenInfo.screens[0];
1053706f2543Smrg    int deviceid;
1054706f2543Smrg    int initialized;
1055706f2543Smrg    int flags[MAXDEVICES] = {0};
1056706f2543Smrg
1057706f2543Smrg    DebugF("(dix) removing device %d\n", dev->id);
1058706f2543Smrg
1059706f2543Smrg    if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
1060706f2543Smrg        return BadImplementation;
1061706f2543Smrg
1062706f2543Smrg    initialized = dev->inited;
1063706f2543Smrg    deviceid = dev->id;
1064706f2543Smrg
1065706f2543Smrg    if (initialized)
1066706f2543Smrg    {
1067706f2543Smrg        if (DevHasCursor(dev))
1068706f2543Smrg            screen->DisplayCursor(dev, screen, NullCursor);
1069706f2543Smrg
1070706f2543Smrg        DisableDevice(dev, sendevent);
1071706f2543Smrg        flags[dev->id] = XIDeviceDisabled;
1072706f2543Smrg    }
1073706f2543Smrg
1074706f2543Smrg    prev = NULL;
1075706f2543Smrg    for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
1076706f2543Smrg	next = tmp->next;
1077706f2543Smrg	if (tmp == dev) {
1078706f2543Smrg
1079706f2543Smrg	    if (prev==NULL)
1080706f2543Smrg		inputInfo.devices = next;
1081706f2543Smrg	    else
1082706f2543Smrg		prev->next = next;
1083706f2543Smrg
1084706f2543Smrg	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1085706f2543Smrg	    CloseDevice(tmp);
1086706f2543Smrg	    ret = Success;
1087706f2543Smrg	}
1088706f2543Smrg    }
1089706f2543Smrg
1090706f2543Smrg    prev = NULL;
1091706f2543Smrg    for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
1092706f2543Smrg	next = tmp->next;
1093706f2543Smrg	if (tmp == dev) {
1094706f2543Smrg	    flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
1095706f2543Smrg	    CloseDevice(tmp);
1096706f2543Smrg
1097706f2543Smrg	    if (prev == NULL)
1098706f2543Smrg		inputInfo.off_devices = next;
1099706f2543Smrg	    else
1100706f2543Smrg		prev->next = next;
1101706f2543Smrg
1102706f2543Smrg            ret = Success;
1103706f2543Smrg	}
1104706f2543Smrg    }
1105706f2543Smrg
1106706f2543Smrg    if (ret == Success && initialized) {
1107706f2543Smrg        inputInfo.numDevices--;
1108706f2543Smrg        SendDevicePresenceEvent(deviceid, DeviceRemoved);
1109706f2543Smrg        if (sendevent)
1110706f2543Smrg            XISendDeviceHierarchyEvent(flags);
1111706f2543Smrg    }
1112706f2543Smrg
1113706f2543Smrg    return ret;
1114706f2543Smrg}
1115706f2543Smrg
1116706f2543Smrgint
1117706f2543SmrgNumMotionEvents(void)
1118706f2543Smrg{
1119706f2543Smrg    /* only called to fill data in initial connection reply.
1120706f2543Smrg     * VCP is ok here, it is the only fixed device we have. */
1121706f2543Smrg    return inputInfo.pointer->valuator->numMotionEvents;
1122706f2543Smrg}
1123706f2543Smrg
1124706f2543Smrgint
1125706f2543SmrgdixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode)
1126706f2543Smrg{
1127706f2543Smrg    DeviceIntPtr dev;
1128706f2543Smrg    int rc;
1129706f2543Smrg    *pDev = NULL;
1130706f2543Smrg
1131706f2543Smrg    for (dev=inputInfo.devices; dev; dev=dev->next) {
1132706f2543Smrg        if (dev->id == id)
1133706f2543Smrg            goto found;
1134706f2543Smrg    }
1135706f2543Smrg    for (dev=inputInfo.off_devices; dev; dev=dev->next) {
1136706f2543Smrg        if (dev->id == id)
1137706f2543Smrg	    goto found;
1138706f2543Smrg    }
1139706f2543Smrg    return BadDevice;
1140706f2543Smrg
1141706f2543Smrgfound:
1142706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1143706f2543Smrg    if (rc == Success)
1144706f2543Smrg	*pDev = dev;
1145706f2543Smrg    return rc;
1146706f2543Smrg}
1147706f2543Smrg
1148706f2543Smrgvoid
1149706f2543SmrgQueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
1150706f2543Smrg{
1151706f2543Smrg    if (inputInfo.keyboard) {
1152706f2543Smrg	*minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code;
1153706f2543Smrg	*maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code;
1154706f2543Smrg    }
1155706f2543Smrg}
1156706f2543Smrg
1157706f2543Smrg/* Notably, this function does not expand the destination's keycode range, or
1158706f2543Smrg * notify clients. */
1159706f2543SmrgBool
1160706f2543SmrgSetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
1161706f2543Smrg{
1162706f2543Smrg    int i, j;
1163706f2543Smrg    KeySym *tmp;
1164706f2543Smrg    int rowDif = src->minKeyCode - dst->minKeyCode;
1165706f2543Smrg
1166706f2543Smrg    /* if keysym map size changes, grow map first */
1167706f2543Smrg    if (src->mapWidth < dst->mapWidth) {
1168706f2543Smrg        for (i = src->minKeyCode; i <= src->maxKeyCode; i++) {
1169706f2543Smrg#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c))
1170706f2543Smrg#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c))
1171706f2543Smrg	    for (j = 0; j < src->mapWidth; j++)
1172706f2543Smrg		dst->map[DI(i, j)] = src->map[SI(i, j)];
1173706f2543Smrg	    for (j = src->mapWidth; j < dst->mapWidth; j++)
1174706f2543Smrg		dst->map[DI(i, j)] = NoSymbol;
1175706f2543Smrg#undef SI
1176706f2543Smrg#undef DI
1177706f2543Smrg	}
1178706f2543Smrg	return TRUE;
1179706f2543Smrg    }
1180706f2543Smrg    else if (src->mapWidth > dst->mapWidth) {
1181706f2543Smrg        i = sizeof(KeySym) * src->mapWidth *
1182706f2543Smrg             (dst->maxKeyCode - dst->minKeyCode + 1);
1183706f2543Smrg        tmp = calloc(sizeof(KeySym), i);
1184706f2543Smrg        if (!tmp)
1185706f2543Smrg            return FALSE;
1186706f2543Smrg
1187706f2543Smrg        if (dst->map) {
1188706f2543Smrg            for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
1189706f2543Smrg                memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth],
1190706f2543Smrg                        dst->mapWidth * sizeof(KeySym));
1191706f2543Smrg            free(dst->map);
1192706f2543Smrg        }
1193706f2543Smrg        dst->mapWidth = src->mapWidth;
1194706f2543Smrg        dst->map = tmp;
1195706f2543Smrg    }
1196706f2543Smrg    else if (!dst->map) {
1197706f2543Smrg        i = sizeof(KeySym) * src->mapWidth *
1198706f2543Smrg             (dst->maxKeyCode - dst->minKeyCode + 1);
1199706f2543Smrg        tmp = calloc(sizeof(KeySym), i);
1200706f2543Smrg        if (!tmp)
1201706f2543Smrg            return FALSE;
1202706f2543Smrg
1203706f2543Smrg        dst->map = tmp;
1204706f2543Smrg        dst->mapWidth = src->mapWidth;
1205706f2543Smrg    }
1206706f2543Smrg
1207706f2543Smrg    memmove(&dst->map[rowDif * dst->mapWidth], src->map,
1208706f2543Smrg            (src->maxKeyCode - src->minKeyCode + 1) *
1209706f2543Smrg            dst->mapWidth * sizeof(KeySym));
1210706f2543Smrg
1211706f2543Smrg    return TRUE;
1212706f2543Smrg}
1213706f2543Smrg
1214706f2543SmrgBool
1215706f2543SmrgInitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
1216706f2543Smrg                            CARD8 *map)
1217706f2543Smrg{
1218706f2543Smrg    ButtonClassPtr butc;
1219706f2543Smrg    int i;
1220706f2543Smrg
1221706f2543Smrg    butc = calloc(1, sizeof(ButtonClassRec));
1222706f2543Smrg    if (!butc)
1223706f2543Smrg	return FALSE;
1224706f2543Smrg    butc->numButtons = numButtons;
1225706f2543Smrg    butc->sourceid = dev->id;
1226706f2543Smrg    for (i = 1; i <= numButtons; i++)
1227706f2543Smrg	butc->map[i] = map[i];
1228706f2543Smrg    for (i = numButtons + 1; i < MAP_LENGTH; i++)
1229706f2543Smrg        butc->map[i] = i;
1230706f2543Smrg    memcpy(butc->labels, labels, numButtons * sizeof(Atom));
1231706f2543Smrg    dev->button = butc;
1232706f2543Smrg    return TRUE;
1233706f2543Smrg}
1234706f2543Smrg
1235706f2543Smrg/**
1236706f2543Smrg * Allocate a valuator class and set up the pointers for the axis values
1237706f2543Smrg * appropriately.
1238706f2543Smrg *
1239706f2543Smrg * @param src If non-NULL, the memory is reallocated from src. If NULL, the
1240706f2543Smrg * memory is calloc'd.
1241706f2543Smrg * @parma numAxes Number of axes to allocate.
1242706f2543Smrg * @return The allocated valuator struct.
1243706f2543Smrg */
1244706f2543SmrgValuatorClassPtr
1245706f2543SmrgAllocValuatorClass(ValuatorClassPtr src, int numAxes)
1246706f2543Smrg{
1247706f2543Smrg    ValuatorClassPtr v;
1248706f2543Smrg    /* force alignment with double */
1249706f2543Smrg    union align_u { ValuatorClassRec valc; double d; } *align;
1250706f2543Smrg    int size;
1251706f2543Smrg
1252706f2543Smrg    size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
1253706f2543Smrg    align = (union align_u *) realloc(src, size);
1254706f2543Smrg
1255706f2543Smrg    if (!align)
1256706f2543Smrg        return NULL;
1257706f2543Smrg
1258706f2543Smrg    if (!src)
1259706f2543Smrg        memset(align, 0, size);
1260706f2543Smrg
1261706f2543Smrg    v = &align->valc;
1262706f2543Smrg    v->numAxes = numAxes;
1263706f2543Smrg    v->axisVal = (double*)(align + 1);
1264706f2543Smrg    v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
1265706f2543Smrg
1266706f2543Smrg    return v;
1267706f2543Smrg}
1268706f2543Smrg
1269706f2543SmrgBool
1270706f2543SmrgInitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
1271706f2543Smrg                              int numMotionEvents, int mode)
1272706f2543Smrg{
1273706f2543Smrg    int i;
1274706f2543Smrg    ValuatorClassPtr valc;
1275706f2543Smrg
1276706f2543Smrg    if (!dev)
1277706f2543Smrg        return FALSE;
1278706f2543Smrg
1279706f2543Smrg    if (numAxes > MAX_VALUATORS)
1280706f2543Smrg    {
1281706f2543Smrg        LogMessage(X_WARNING,
1282706f2543Smrg                   "Device '%s' has %d axes, only using first %d.\n",
1283706f2543Smrg                   dev->name, numAxes, MAX_VALUATORS);
1284706f2543Smrg        numAxes = MAX_VALUATORS;
1285706f2543Smrg    }
1286706f2543Smrg
1287706f2543Smrg    valc = AllocValuatorClass(NULL, numAxes);
1288706f2543Smrg    if (!valc)
1289706f2543Smrg        return FALSE;
1290706f2543Smrg
1291706f2543Smrg    valc->sourceid = dev->id;
1292706f2543Smrg    valc->motion = NULL;
1293706f2543Smrg    valc->first_motion = 0;
1294706f2543Smrg    valc->last_motion = 0;
1295706f2543Smrg
1296706f2543Smrg    valc->numMotionEvents = numMotionEvents;
1297706f2543Smrg    valc->motionHintWindow = NullWindow;
1298706f2543Smrg
1299706f2543Smrg    if (mode & OutOfProximity)
1300706f2543Smrg        InitProximityClassDeviceStruct(dev);
1301706f2543Smrg
1302706f2543Smrg    dev->valuator = valc;
1303706f2543Smrg
1304706f2543Smrg    AllocateMotionHistory(dev);
1305706f2543Smrg
1306706f2543Smrg    for (i=0; i<numAxes; i++) {
1307706f2543Smrg        InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1308706f2543Smrg                               0, 0, 0, mode);
1309706f2543Smrg	valc->axisVal[i]=0;
1310706f2543Smrg    }
1311706f2543Smrg
1312706f2543Smrg    dev->last.numValuators = numAxes;
1313706f2543Smrg
1314706f2543Smrg    if (IsMaster(dev) || /* do not accelerate master or xtest devices */
1315706f2543Smrg        IsXTestDevice(dev, NULL))
1316706f2543Smrg	InitPointerAccelerationScheme(dev, PtrAccelNoOp);
1317706f2543Smrg    else
1318706f2543Smrg	InitPointerAccelerationScheme(dev, PtrAccelDefault);
1319706f2543Smrg    return TRUE;
1320706f2543Smrg}
1321706f2543Smrg
1322706f2543Smrg/* global list of acceleration schemes */
1323706f2543SmrgValuatorAccelerationRec pointerAccelerationScheme[] = {
1324706f2543Smrg    {PtrAccelNoOp,        NULL, NULL, NULL},
1325706f2543Smrg    {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
1326706f2543Smrg    {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
1327706f2543Smrg    {-1, NULL, NULL, NULL} /* terminator */
1328706f2543Smrg};
1329706f2543Smrg
1330706f2543Smrg/**
1331706f2543Smrg * install an acceleration scheme. returns TRUE on success, and should not
1332706f2543Smrg * change anything if unsuccessful.
1333706f2543Smrg */
1334706f2543SmrgBool
1335706f2543SmrgInitPointerAccelerationScheme(DeviceIntPtr dev,
1336706f2543Smrg                              int scheme)
1337706f2543Smrg{
1338706f2543Smrg    int x, i = -1;
1339706f2543Smrg    void* data = NULL;
1340706f2543Smrg    ValuatorClassPtr val;
1341706f2543Smrg
1342706f2543Smrg    val = dev->valuator;
1343706f2543Smrg
1344706f2543Smrg    if(!val)
1345706f2543Smrg	return FALSE;
1346706f2543Smrg
1347706f2543Smrg    if(IsMaster(dev) && scheme != PtrAccelNoOp)
1348706f2543Smrg        return FALSE;
1349706f2543Smrg
1350706f2543Smrg    for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
1351706f2543Smrg        if(pointerAccelerationScheme[x].number == scheme){
1352706f2543Smrg            i = x;
1353706f2543Smrg            break;
1354706f2543Smrg        }
1355706f2543Smrg    }
1356706f2543Smrg
1357706f2543Smrg    if(-1 == i)
1358706f2543Smrg        return FALSE;
1359706f2543Smrg
1360706f2543Smrg    if (val->accelScheme.AccelCleanupProc)
1361706f2543Smrg        val->accelScheme.AccelCleanupProc(dev);
1362706f2543Smrg
1363706f2543Smrg    /* init scheme-specific data */
1364706f2543Smrg    switch(scheme){
1365706f2543Smrg        case PtrAccelPredictable:
1366706f2543Smrg        {
1367706f2543Smrg            DeviceVelocityPtr s;
1368706f2543Smrg            s = malloc(sizeof(DeviceVelocityRec));
1369706f2543Smrg            if(!s)
1370706f2543Smrg        	return FALSE;
1371706f2543Smrg            InitVelocityData(s);
1372706f2543Smrg            data = s;
1373706f2543Smrg            break;
1374706f2543Smrg        }
1375706f2543Smrg        default:
1376706f2543Smrg            break;
1377706f2543Smrg    }
1378706f2543Smrg
1379706f2543Smrg    val->accelScheme = pointerAccelerationScheme[i];
1380706f2543Smrg    val->accelScheme.accelData = data;
1381706f2543Smrg
1382706f2543Smrg    /* post-init scheme */
1383706f2543Smrg    switch(scheme){
1384706f2543Smrg        case PtrAccelPredictable:
1385706f2543Smrg            InitializePredictableAccelerationProperties(dev);
1386706f2543Smrg            break;
1387706f2543Smrg
1388706f2543Smrg        default:
1389706f2543Smrg            break;
1390706f2543Smrg    }
1391706f2543Smrg
1392706f2543Smrg    return TRUE;
1393706f2543Smrg}
1394706f2543Smrg
1395706f2543SmrgBool
1396706f2543SmrgInitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
1397706f2543Smrg{
1398706f2543Smrg    AbsoluteClassPtr abs;
1399706f2543Smrg
1400706f2543Smrg    abs = malloc(sizeof(AbsoluteClassRec));
1401706f2543Smrg    if (!abs)
1402706f2543Smrg        return FALSE;
1403706f2543Smrg
1404706f2543Smrg    /* we don't do anything sensible with these, but should */
1405706f2543Smrg    abs->min_x = NO_AXIS_LIMITS;
1406706f2543Smrg    abs->min_y = NO_AXIS_LIMITS;
1407706f2543Smrg    abs->max_x = NO_AXIS_LIMITS;
1408706f2543Smrg    abs->max_y = NO_AXIS_LIMITS;
1409706f2543Smrg    abs->flip_x = 0;
1410706f2543Smrg    abs->flip_y = 0;
1411706f2543Smrg    abs->rotation = 0;
1412706f2543Smrg    abs->button_threshold = 0;
1413706f2543Smrg
1414706f2543Smrg    abs->offset_x = 0;
1415706f2543Smrg    abs->offset_y = 0;
1416706f2543Smrg    abs->width = NO_AXIS_LIMITS;
1417706f2543Smrg    abs->height = NO_AXIS_LIMITS;
1418706f2543Smrg    abs->following = 0;
1419706f2543Smrg    abs->screen = 0;
1420706f2543Smrg
1421706f2543Smrg    abs->sourceid = dev->id;
1422706f2543Smrg
1423706f2543Smrg    dev->absolute = abs;
1424706f2543Smrg
1425706f2543Smrg    return TRUE;
1426706f2543Smrg}
1427706f2543Smrg
1428706f2543SmrgBool
1429706f2543SmrgInitFocusClassDeviceStruct(DeviceIntPtr dev)
1430706f2543Smrg{
1431706f2543Smrg    FocusClassPtr focc;
1432706f2543Smrg
1433706f2543Smrg    focc = malloc(sizeof(FocusClassRec));
1434706f2543Smrg    if (!focc)
1435706f2543Smrg	return FALSE;
1436706f2543Smrg    focc->win = PointerRootWin;
1437706f2543Smrg    focc->revert = None;
1438706f2543Smrg    focc->time = currentTime;
1439706f2543Smrg    focc->trace = (WindowPtr *)NULL;
1440706f2543Smrg    focc->traceSize = 0;
1441706f2543Smrg    focc->traceGood = 0;
1442706f2543Smrg    focc->sourceid = dev->id;
1443706f2543Smrg    dev->focus = focc;
1444706f2543Smrg    return TRUE;
1445706f2543Smrg}
1446706f2543Smrg
1447706f2543SmrgBool
1448706f2543SmrgInitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
1449706f2543Smrg{
1450706f2543Smrg    PtrFeedbackPtr feedc;
1451706f2543Smrg
1452706f2543Smrg    feedc = malloc(sizeof(PtrFeedbackClassRec));
1453706f2543Smrg    if (!feedc)
1454706f2543Smrg	return FALSE;
1455706f2543Smrg    feedc->CtrlProc = controlProc;
1456706f2543Smrg    feedc->ctrl = defaultPointerControl;
1457706f2543Smrg    feedc->ctrl.id = 0;
1458706f2543Smrg    if ( (feedc->next = dev->ptrfeed) )
1459706f2543Smrg        feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
1460706f2543Smrg    dev->ptrfeed = feedc;
1461706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1462706f2543Smrg    return TRUE;
1463706f2543Smrg}
1464706f2543Smrg
1465706f2543Smrg
1466706f2543Smrgstatic LedCtrl defaultLedControl = {
1467706f2543Smrg	DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0};
1468706f2543Smrg
1469706f2543Smrgstatic BellCtrl defaultBellControl = {
1470706f2543Smrg	DEFAULT_BELL,
1471706f2543Smrg	DEFAULT_BELL_PITCH,
1472706f2543Smrg	DEFAULT_BELL_DURATION,
1473706f2543Smrg	0};
1474706f2543Smrg
1475706f2543Smrgstatic IntegerCtrl defaultIntegerControl = {
1476706f2543Smrg	DEFAULT_INT_RESOLUTION,
1477706f2543Smrg	DEFAULT_INT_MIN_VALUE,
1478706f2543Smrg	DEFAULT_INT_MAX_VALUE,
1479706f2543Smrg	DEFAULT_INT_DISPLAYED,
1480706f2543Smrg	0};
1481706f2543Smrg
1482706f2543SmrgBool
1483706f2543SmrgInitStringFeedbackClassDeviceStruct (
1484706f2543Smrg      DeviceIntPtr dev, StringCtrlProcPtr controlProc,
1485706f2543Smrg      int max_symbols, int num_symbols_supported, KeySym *symbols)
1486706f2543Smrg{
1487706f2543Smrg    int i;
1488706f2543Smrg    StringFeedbackPtr feedc;
1489706f2543Smrg
1490706f2543Smrg    feedc = malloc(sizeof(StringFeedbackClassRec));
1491706f2543Smrg    if (!feedc)
1492706f2543Smrg	return FALSE;
1493706f2543Smrg    feedc->CtrlProc = controlProc;
1494706f2543Smrg    feedc->ctrl.num_symbols_supported = num_symbols_supported;
1495706f2543Smrg    feedc->ctrl.num_symbols_displayed = 0;
1496706f2543Smrg    feedc->ctrl.max_symbols = max_symbols;
1497706f2543Smrg    feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported);
1498706f2543Smrg    feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols);
1499706f2543Smrg    if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
1500706f2543Smrg    {
1501706f2543Smrg	free(feedc->ctrl.symbols_supported);
1502706f2543Smrg	free(feedc->ctrl.symbols_displayed);
1503706f2543Smrg	free(feedc);
1504706f2543Smrg	return FALSE;
1505706f2543Smrg    }
1506706f2543Smrg    for (i=0; i<num_symbols_supported; i++)
1507706f2543Smrg	*(feedc->ctrl.symbols_supported+i) = *symbols++;
1508706f2543Smrg    for (i=0; i<max_symbols; i++)
1509706f2543Smrg	*(feedc->ctrl.symbols_displayed+i) = (KeySym) 0;
1510706f2543Smrg    feedc->ctrl.id = 0;
1511706f2543Smrg    if ( (feedc->next = dev->stringfeed) )
1512706f2543Smrg	feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
1513706f2543Smrg    dev->stringfeed = feedc;
1514706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1515706f2543Smrg    return TRUE;
1516706f2543Smrg}
1517706f2543Smrg
1518706f2543SmrgBool
1519706f2543SmrgInitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
1520706f2543Smrg                                   BellCtrlProcPtr controlProc)
1521706f2543Smrg{
1522706f2543Smrg    BellFeedbackPtr feedc;
1523706f2543Smrg
1524706f2543Smrg    feedc = malloc(sizeof(BellFeedbackClassRec));
1525706f2543Smrg    if (!feedc)
1526706f2543Smrg	return FALSE;
1527706f2543Smrg    feedc->CtrlProc = controlProc;
1528706f2543Smrg    feedc->BellProc = bellProc;
1529706f2543Smrg    feedc->ctrl = defaultBellControl;
1530706f2543Smrg    feedc->ctrl.id = 0;
1531706f2543Smrg    if ( (feedc->next = dev->bell) )
1532706f2543Smrg	feedc->ctrl.id = dev->bell->ctrl.id + 1;
1533706f2543Smrg    dev->bell = feedc;
1534706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1535706f2543Smrg    return TRUE;
1536706f2543Smrg}
1537706f2543Smrg
1538706f2543SmrgBool
1539706f2543SmrgInitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc)
1540706f2543Smrg{
1541706f2543Smrg    LedFeedbackPtr feedc;
1542706f2543Smrg
1543706f2543Smrg    feedc = malloc(sizeof(LedFeedbackClassRec));
1544706f2543Smrg    if (!feedc)
1545706f2543Smrg	return FALSE;
1546706f2543Smrg    feedc->CtrlProc = controlProc;
1547706f2543Smrg    feedc->ctrl = defaultLedControl;
1548706f2543Smrg    feedc->ctrl.id = 0;
1549706f2543Smrg    if ( (feedc->next = dev->leds) )
1550706f2543Smrg	feedc->ctrl.id = dev->leds->ctrl.id + 1;
1551706f2543Smrg    feedc->xkb_sli= NULL;
1552706f2543Smrg    dev->leds = feedc;
1553706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1554706f2543Smrg    return TRUE;
1555706f2543Smrg}
1556706f2543Smrg
1557706f2543SmrgBool
1558706f2543SmrgInitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc)
1559706f2543Smrg{
1560706f2543Smrg    IntegerFeedbackPtr feedc;
1561706f2543Smrg
1562706f2543Smrg    feedc = malloc(sizeof(IntegerFeedbackClassRec));
1563706f2543Smrg    if (!feedc)
1564706f2543Smrg	return FALSE;
1565706f2543Smrg    feedc->CtrlProc = controlProc;
1566706f2543Smrg    feedc->ctrl = defaultIntegerControl;
1567706f2543Smrg    feedc->ctrl.id = 0;
1568706f2543Smrg    if ( (feedc->next = dev->intfeed) )
1569706f2543Smrg	feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
1570706f2543Smrg    dev->intfeed = feedc;
1571706f2543Smrg    (*controlProc)(dev, &feedc->ctrl);
1572706f2543Smrg    return TRUE;
1573706f2543Smrg}
1574706f2543Smrg
1575706f2543SmrgBool
1576706f2543SmrgInitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels,
1577706f2543Smrg                        PtrCtrlProcPtr controlProc, int numMotionEvents,
1578706f2543Smrg                        int numAxes, Atom *axes_labels)
1579706f2543Smrg{
1580706f2543Smrg    DeviceIntPtr dev = (DeviceIntPtr)device;
1581706f2543Smrg
1582706f2543Smrg    return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
1583706f2543Smrg	   InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
1584706f2543Smrg					 numMotionEvents, Relative) &&
1585706f2543Smrg	   InitPtrFeedbackClassDeviceStruct(dev, controlProc));
1586706f2543Smrg}
1587706f2543Smrg
1588706f2543Smrg/*
1589706f2543Smrg * Check if the given buffer contains elements between low (inclusive) and
1590706f2543Smrg * high (inclusive) only.
1591706f2543Smrg *
1592706f2543Smrg * @return TRUE if the device map is invalid, FALSE otherwise.
1593706f2543Smrg */
1594706f2543SmrgBool
1595706f2543SmrgBadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
1596706f2543Smrg{
1597706f2543Smrg    int i;
1598706f2543Smrg
1599706f2543Smrg    for (i = 0; i < length; i++)
1600706f2543Smrg	if (buff[i])		       /* only check non-zero elements */
1601706f2543Smrg	{
1602706f2543Smrg	    if ((low > buff[i]) || (high < buff[i]))
1603706f2543Smrg	    {
1604706f2543Smrg		*errval = buff[i];
1605706f2543Smrg		return TRUE;
1606706f2543Smrg	    }
1607706f2543Smrg	}
1608706f2543Smrg    return FALSE;
1609706f2543Smrg}
1610706f2543Smrg
1611706f2543Smrgint
1612706f2543SmrgProcSetModifierMapping(ClientPtr client)
1613706f2543Smrg{
1614706f2543Smrg    xSetModifierMappingReply rep;
1615706f2543Smrg    int rc;
1616706f2543Smrg    REQUEST(xSetModifierMappingReq);
1617706f2543Smrg    REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
1618706f2543Smrg
1619706f2543Smrg    if (client->req_len != ((stuff->numKeyPerModifier << 1) +
1620706f2543Smrg                bytes_to_int32(sizeof(xSetModifierMappingReq))))
1621706f2543Smrg	return BadLength;
1622706f2543Smrg
1623706f2543Smrg    rep.type = X_Reply;
1624706f2543Smrg    rep.length = 0;
1625706f2543Smrg    rep.sequenceNumber = client->sequence;
1626706f2543Smrg
1627706f2543Smrg    rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1],
1628706f2543Smrg                       stuff->numKeyPerModifier);
1629706f2543Smrg    if (rc == MappingFailed || rc == -1)
1630706f2543Smrg        return BadValue;
1631706f2543Smrg    if (rc != Success && rc != MappingSuccess && rc != MappingFailed &&
1632706f2543Smrg        rc != MappingBusy)
1633706f2543Smrg	return rc;
1634706f2543Smrg
1635706f2543Smrg    rep.success = rc;
1636706f2543Smrg
1637706f2543Smrg    WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
1638706f2543Smrg    return Success;
1639706f2543Smrg}
1640706f2543Smrg
1641706f2543Smrgint
1642706f2543SmrgProcGetModifierMapping(ClientPtr client)
1643706f2543Smrg{
1644706f2543Smrg    xGetModifierMappingReply rep;
1645706f2543Smrg    int max_keys_per_mod = 0;
1646706f2543Smrg    KeyCode *modkeymap = NULL;
1647706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
1648706f2543Smrg
1649706f2543Smrg    generate_modkeymap(client, PickKeyboard(client), &modkeymap,
1650706f2543Smrg                       &max_keys_per_mod);
1651706f2543Smrg
1652706f2543Smrg    memset(&rep, 0, sizeof(xGetModifierMappingReply));
1653706f2543Smrg    rep.type = X_Reply;
1654706f2543Smrg    rep.numKeyPerModifier = max_keys_per_mod;
1655706f2543Smrg    rep.sequenceNumber = client->sequence;
1656706f2543Smrg    /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */
1657706f2543Smrg    rep.length = max_keys_per_mod << 1;
1658706f2543Smrg
1659706f2543Smrg    WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
1660706f2543Smrg    (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap);
1661706f2543Smrg
1662706f2543Smrg    free(modkeymap);
1663706f2543Smrg
1664706f2543Smrg    return Success;
1665706f2543Smrg}
1666706f2543Smrg
1667706f2543Smrgint
1668706f2543SmrgProcChangeKeyboardMapping(ClientPtr client)
1669706f2543Smrg{
1670706f2543Smrg    REQUEST(xChangeKeyboardMappingReq);
1671706f2543Smrg    unsigned len;
1672706f2543Smrg    KeySymsRec keysyms;
1673706f2543Smrg    DeviceIntPtr pDev, tmp;
1674706f2543Smrg    int rc;
1675706f2543Smrg    REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
1676706f2543Smrg
1677706f2543Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq));
1678706f2543Smrg    if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
1679706f2543Smrg            return BadLength;
1680706f2543Smrg
1681706f2543Smrg    pDev = PickKeyboard(client);
1682706f2543Smrg
1683706f2543Smrg    if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) ||
1684706f2543Smrg	(stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) {
1685706f2543Smrg	    client->errorValue = stuff->firstKeyCode;
1686706f2543Smrg	    return BadValue;
1687706f2543Smrg
1688706f2543Smrg    }
1689706f2543Smrg    if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) >
1690706f2543Smrg          pDev->key->xkbInfo->desc->max_key_code) ||
1691706f2543Smrg        (stuff->keySymsPerKeyCode == 0)) {
1692706f2543Smrg	    client->errorValue = stuff->keySymsPerKeyCode;
1693706f2543Smrg	    return BadValue;
1694706f2543Smrg    }
1695706f2543Smrg
1696706f2543Smrg    keysyms.minKeyCode = stuff->firstKeyCode;
1697706f2543Smrg    keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
1698706f2543Smrg    keysyms.mapWidth = stuff->keySymsPerKeyCode;
1699706f2543Smrg    keysyms.map = (KeySym *) &stuff[1];
1700706f2543Smrg
1701706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1702706f2543Smrg    if (rc != Success)
1703706f2543Smrg        return rc;
1704706f2543Smrg
1705706f2543Smrg    XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode,
1706706f2543Smrg                          stuff->keyCodes, NULL, client);
1707706f2543Smrg
1708706f2543Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
1709706f2543Smrg        if (IsMaster(tmp) || tmp->u.master != pDev)
1710706f2543Smrg            continue;
1711706f2543Smrg        if (!tmp->key)
1712706f2543Smrg            continue;
1713706f2543Smrg
1714706f2543Smrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
1715706f2543Smrg        if (rc != Success)
1716706f2543Smrg            continue;
1717706f2543Smrg
1718706f2543Smrg        XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode,
1719706f2543Smrg                              stuff->keyCodes, NULL, client);
1720706f2543Smrg    }
1721706f2543Smrg
1722706f2543Smrg    return Success;
1723706f2543Smrg}
1724706f2543Smrg
1725706f2543Smrgint
1726706f2543SmrgProcSetPointerMapping(ClientPtr client)
1727706f2543Smrg{
1728706f2543Smrg    BYTE *map;
1729706f2543Smrg    int ret;
1730706f2543Smrg    int i, j;
1731706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
1732706f2543Smrg    xSetPointerMappingReply rep;
1733706f2543Smrg    REQUEST(xSetPointerMappingReq);
1734706f2543Smrg    REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
1735706f2543Smrg
1736706f2543Smrg    if (client->req_len !=
1737706f2543Smrg            bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts))
1738706f2543Smrg	return BadLength;
1739706f2543Smrg    rep.type = X_Reply;
1740706f2543Smrg    rep.length = 0;
1741706f2543Smrg    rep.sequenceNumber = client->sequence;
1742706f2543Smrg    rep.success = MappingSuccess;
1743706f2543Smrg    map = (BYTE *)&stuff[1];
1744706f2543Smrg
1745706f2543Smrg    /* So we're bounded here by the number of core buttons.  This check
1746706f2543Smrg     * probably wants disabling through XFixes. */
1747706f2543Smrg    /* MPX: With ClientPointer, we can return the right number of buttons.
1748706f2543Smrg     * Let's just hope nobody changed ClientPointer between GetPointerMapping
1749706f2543Smrg     * and SetPointerMapping
1750706f2543Smrg     */
1751706f2543Smrg    if (stuff->nElts != ptr->button->numButtons) {
1752706f2543Smrg	client->errorValue = stuff->nElts;
1753706f2543Smrg	return BadValue;
1754706f2543Smrg    }
1755706f2543Smrg
1756706f2543Smrg    /* Core protocol specs don't allow for duplicate mappings; this check
1757706f2543Smrg     * almost certainly wants disabling through XFixes too. */
1758706f2543Smrg    for (i = 0; i < stuff->nElts; i++) {
1759706f2543Smrg        for (j = i + 1; j < stuff->nElts; j++) {
1760706f2543Smrg            if (map[i] && map[i] == map[j]) {
1761706f2543Smrg                client->errorValue = map[i];
1762706f2543Smrg                return BadValue;
1763706f2543Smrg            }
1764706f2543Smrg        }
1765706f2543Smrg    }
1766706f2543Smrg
1767706f2543Smrg    ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
1768706f2543Smrg    if (ret == MappingBusy)
1769706f2543Smrg        rep.success = ret;
1770706f2543Smrg    else if (ret == -1)
1771706f2543Smrg        return BadValue;
1772706f2543Smrg    else if (ret != Success)
1773706f2543Smrg        return ret;
1774706f2543Smrg
1775706f2543Smrg    WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
1776706f2543Smrg    return Success;
1777706f2543Smrg}
1778706f2543Smrg
1779706f2543Smrgint
1780706f2543SmrgProcGetKeyboardMapping(ClientPtr client)
1781706f2543Smrg{
1782706f2543Smrg    xGetKeyboardMappingReply rep;
1783706f2543Smrg    DeviceIntPtr kbd = PickKeyboard(client);
1784706f2543Smrg    XkbDescPtr xkb;
1785706f2543Smrg    KeySymsPtr syms;
1786706f2543Smrg    int rc;
1787706f2543Smrg    REQUEST(xGetKeyboardMappingReq);
1788706f2543Smrg    REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
1789706f2543Smrg
1790706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
1791706f2543Smrg    if (rc != Success)
1792706f2543Smrg	return rc;
1793706f2543Smrg
1794706f2543Smrg    xkb = kbd->key->xkbInfo->desc;
1795706f2543Smrg
1796706f2543Smrg    if ((stuff->firstKeyCode < xkb->min_key_code) ||
1797706f2543Smrg        (stuff->firstKeyCode > xkb->max_key_code)) {
1798706f2543Smrg	client->errorValue = stuff->firstKeyCode;
1799706f2543Smrg	return BadValue;
1800706f2543Smrg    }
1801706f2543Smrg    if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) {
1802706f2543Smrg	client->errorValue = stuff->count;
1803706f2543Smrg        return BadValue;
1804706f2543Smrg    }
1805706f2543Smrg
1806706f2543Smrg    syms = XkbGetCoreMap(kbd);
1807706f2543Smrg    if (!syms)
1808706f2543Smrg        return BadAlloc;
1809706f2543Smrg
1810706f2543Smrg    memset(&rep, 0, sizeof(xGetKeyboardMappingReply));
1811706f2543Smrg    rep.type = X_Reply;
1812706f2543Smrg    rep.sequenceNumber = client->sequence;
1813706f2543Smrg    rep.keySymsPerKeyCode = syms->mapWidth;
1814706f2543Smrg    /* length is a count of 4 byte quantities and KeySyms are 4 bytes */
1815706f2543Smrg    rep.length = syms->mapWidth * stuff->count;
1816706f2543Smrg    WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
1817706f2543Smrg    client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
1818706f2543Smrg    WriteSwappedDataToClient(client,
1819706f2543Smrg                             syms->mapWidth * stuff->count * sizeof(KeySym),
1820706f2543Smrg                             &syms->map[syms->mapWidth * (stuff->firstKeyCode -
1821706f2543Smrg                                                          syms->minKeyCode)]);
1822706f2543Smrg    free(syms->map);
1823706f2543Smrg    free(syms);
1824706f2543Smrg
1825706f2543Smrg    return Success;
1826706f2543Smrg}
1827706f2543Smrg
1828706f2543Smrgint
1829706f2543SmrgProcGetPointerMapping(ClientPtr client)
1830706f2543Smrg{
1831706f2543Smrg    xGetPointerMappingReply rep;
1832706f2543Smrg    /* Apps may get different values each time they call GetPointerMapping as
1833706f2543Smrg     * the ClientPointer could change. */
1834706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
1835706f2543Smrg    ButtonClassPtr butc = ptr->button;
1836706f2543Smrg    int rc;
1837706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
1838706f2543Smrg
1839706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
1840706f2543Smrg    if (rc != Success)
1841706f2543Smrg	return rc;
1842706f2543Smrg
1843706f2543Smrg    rep.type = X_Reply;
1844706f2543Smrg    rep.sequenceNumber = client->sequence;
1845706f2543Smrg    rep.nElts = (butc) ? butc->numButtons : 0;
1846706f2543Smrg    rep.length = ((unsigned)rep.nElts + (4-1))/4;
1847706f2543Smrg    WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
1848706f2543Smrg    if (butc)
1849706f2543Smrg        WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
1850706f2543Smrg    return Success;
1851706f2543Smrg}
1852706f2543Smrg
1853706f2543Smrgvoid
1854706f2543SmrgNoteLedState(DeviceIntPtr keybd, int led, Bool on)
1855706f2543Smrg{
1856706f2543Smrg    KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
1857706f2543Smrg    if (on)
1858706f2543Smrg	ctrl->leds |= ((Leds)1 << (led - 1));
1859706f2543Smrg    else
1860706f2543Smrg	ctrl->leds &= ~((Leds)1 << (led - 1));
1861706f2543Smrg}
1862706f2543Smrg
1863706f2543Smrgint
1864706f2543SmrgOnes(unsigned long mask)             /* HACKMEM 169 */
1865706f2543Smrg{
1866706f2543Smrg    unsigned long y;
1867706f2543Smrg
1868706f2543Smrg    y = (mask >> 1) &033333333333;
1869706f2543Smrg    y = mask - y - ((y >>1) & 033333333333);
1870706f2543Smrg    return (((y + (y >> 3)) & 030707070707) % 077);
1871706f2543Smrg}
1872706f2543Smrg
1873706f2543Smrgstatic int
1874706f2543SmrgDoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
1875706f2543Smrg                         BITS32 vmask)
1876706f2543Smrg{
1877706f2543Smrg#define DO_ALL    (-1)
1878706f2543Smrg    KeybdCtrl ctrl;
1879706f2543Smrg    int t;
1880706f2543Smrg    int led = DO_ALL;
1881706f2543Smrg    int key = DO_ALL;
1882706f2543Smrg    BITS32 index2;
1883706f2543Smrg    int mask = vmask, i;
1884706f2543Smrg    XkbEventCauseRec cause;
1885706f2543Smrg
1886706f2543Smrg    ctrl = keybd->kbdfeed->ctrl;
1887706f2543Smrg    while (vmask) {
1888706f2543Smrg	index2 = (BITS32) lowbit (vmask);
1889706f2543Smrg	vmask &= ~index2;
1890706f2543Smrg	switch (index2) {
1891706f2543Smrg	case KBKeyClickPercent:
1892706f2543Smrg	    t = (INT8)*vlist;
1893706f2543Smrg	    vlist++;
1894706f2543Smrg	    if (t == -1) {
1895706f2543Smrg		t = defaultKeyboardControl.click;
1896706f2543Smrg            }
1897706f2543Smrg	    else if (t < 0 || t > 100) {
1898706f2543Smrg		client->errorValue = t;
1899706f2543Smrg		return BadValue;
1900706f2543Smrg	    }
1901706f2543Smrg	    ctrl.click = t;
1902706f2543Smrg	    break;
1903706f2543Smrg	case KBBellPercent:
1904706f2543Smrg	    t = (INT8)*vlist;
1905706f2543Smrg	    vlist++;
1906706f2543Smrg	    if (t == -1) {
1907706f2543Smrg		t = defaultKeyboardControl.bell;
1908706f2543Smrg            }
1909706f2543Smrg	    else if (t < 0 || t > 100) {
1910706f2543Smrg		client->errorValue = t;
1911706f2543Smrg		return BadValue;
1912706f2543Smrg	    }
1913706f2543Smrg	    ctrl.bell = t;
1914706f2543Smrg	    break;
1915706f2543Smrg	case KBBellPitch:
1916706f2543Smrg	    t = (INT16)*vlist;
1917706f2543Smrg	    vlist++;
1918706f2543Smrg	    if (t == -1) {
1919706f2543Smrg		t = defaultKeyboardControl.bell_pitch;
1920706f2543Smrg            }
1921706f2543Smrg	    else if (t < 0) {
1922706f2543Smrg		client->errorValue = t;
1923706f2543Smrg		return BadValue;
1924706f2543Smrg	    }
1925706f2543Smrg	    ctrl.bell_pitch = t;
1926706f2543Smrg	    break;
1927706f2543Smrg	case KBBellDuration:
1928706f2543Smrg	    t = (INT16)*vlist;
1929706f2543Smrg	    vlist++;
1930706f2543Smrg	    if (t == -1)
1931706f2543Smrg		t = defaultKeyboardControl.bell_duration;
1932706f2543Smrg	    else if (t < 0) {
1933706f2543Smrg		client->errorValue = t;
1934706f2543Smrg		return BadValue;
1935706f2543Smrg	    }
1936706f2543Smrg	    ctrl.bell_duration = t;
1937706f2543Smrg	    break;
1938706f2543Smrg	case KBLed:
1939706f2543Smrg	    led = (CARD8)*vlist;
1940706f2543Smrg	    vlist++;
1941706f2543Smrg	    if (led < 1 || led > 32) {
1942706f2543Smrg		client->errorValue = led;
1943706f2543Smrg		return BadValue;
1944706f2543Smrg	    }
1945706f2543Smrg	    if (!(mask & KBLedMode))
1946706f2543Smrg		return BadMatch;
1947706f2543Smrg	    break;
1948706f2543Smrg	case KBLedMode:
1949706f2543Smrg	    t = (CARD8)*vlist;
1950706f2543Smrg	    vlist++;
1951706f2543Smrg	    if (t == LedModeOff) {
1952706f2543Smrg		if (led == DO_ALL)
1953706f2543Smrg		    ctrl.leds = 0x0;
1954706f2543Smrg		else
1955706f2543Smrg		    ctrl.leds &= ~(((Leds)(1)) << (led - 1));
1956706f2543Smrg	    }
1957706f2543Smrg	    else if (t == LedModeOn) {
1958706f2543Smrg		if (led == DO_ALL)
1959706f2543Smrg		    ctrl.leds = ~0L;
1960706f2543Smrg		else
1961706f2543Smrg		    ctrl.leds |= (((Leds)(1)) << (led - 1));
1962706f2543Smrg	    }
1963706f2543Smrg	    else {
1964706f2543Smrg		client->errorValue = t;
1965706f2543Smrg		return BadValue;
1966706f2543Smrg	    }
1967706f2543Smrg
1968706f2543Smrg            XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client);
1969706f2543Smrg            XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))),
1970706f2543Smrg 			     ctrl.leds, &cause);
1971706f2543Smrg            ctrl.leds = keybd->kbdfeed->ctrl.leds;
1972706f2543Smrg
1973706f2543Smrg	    break;
1974706f2543Smrg	case KBKey:
1975706f2543Smrg	    key = (KeyCode)*vlist;
1976706f2543Smrg	    vlist++;
1977706f2543Smrg	    if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code ||
1978706f2543Smrg		(KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) {
1979706f2543Smrg		client->errorValue = key;
1980706f2543Smrg		return BadValue;
1981706f2543Smrg	    }
1982706f2543Smrg	    if (!(mask & KBAutoRepeatMode))
1983706f2543Smrg		return BadMatch;
1984706f2543Smrg	    break;
1985706f2543Smrg	case KBAutoRepeatMode:
1986706f2543Smrg	    i = (key >> 3);
1987706f2543Smrg	    mask = (1 << (key & 7));
1988706f2543Smrg	    t = (CARD8)*vlist;
1989706f2543Smrg	    vlist++;
1990706f2543Smrg            if (key != DO_ALL)
1991706f2543Smrg                XkbDisableComputedAutoRepeats(keybd,key);
1992706f2543Smrg	    if (t == AutoRepeatModeOff) {
1993706f2543Smrg		if (key == DO_ALL)
1994706f2543Smrg		    ctrl.autoRepeat = FALSE;
1995706f2543Smrg		else
1996706f2543Smrg		    ctrl.autoRepeats[i] &= ~mask;
1997706f2543Smrg	    }
1998706f2543Smrg	    else if (t == AutoRepeatModeOn) {
1999706f2543Smrg		if (key == DO_ALL)
2000706f2543Smrg		    ctrl.autoRepeat = TRUE;
2001706f2543Smrg		else
2002706f2543Smrg		    ctrl.autoRepeats[i] |= mask;
2003706f2543Smrg	    }
2004706f2543Smrg	    else if (t == AutoRepeatModeDefault) {
2005706f2543Smrg		if (key == DO_ALL)
2006706f2543Smrg		    ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
2007706f2543Smrg		else
2008706f2543Smrg		    ctrl.autoRepeats[i] =
2009706f2543Smrg			    (ctrl.autoRepeats[i] & ~mask) |
2010706f2543Smrg			    (defaultKeyboardControl.autoRepeats[i] & mask);
2011706f2543Smrg	    }
2012706f2543Smrg	    else {
2013706f2543Smrg		client->errorValue = t;
2014706f2543Smrg		return BadValue;
2015706f2543Smrg	    }
2016706f2543Smrg	    break;
2017706f2543Smrg	default:
2018706f2543Smrg	    client->errorValue = mask;
2019706f2543Smrg	    return BadValue;
2020706f2543Smrg	}
2021706f2543Smrg    }
2022706f2543Smrg    keybd->kbdfeed->ctrl = ctrl;
2023706f2543Smrg
2024706f2543Smrg    /* The XKB RepeatKeys control and core protocol global autorepeat */
2025706f2543Smrg    /* value are linked	*/
2026706f2543Smrg    XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
2027706f2543Smrg
2028706f2543Smrg    return Success;
2029706f2543Smrg
2030706f2543Smrg#undef DO_ALL
2031706f2543Smrg}
2032706f2543Smrg
2033706f2543Smrg/**
2034706f2543Smrg * Changes kbd control on the ClientPointer and all attached SDs.
2035706f2543Smrg */
2036706f2543Smrgint
2037706f2543SmrgProcChangeKeyboardControl (ClientPtr client)
2038706f2543Smrg{
2039706f2543Smrg    XID *vlist;
2040706f2543Smrg    BITS32 vmask;
2041706f2543Smrg    int ret = Success, error = Success;
2042706f2543Smrg    DeviceIntPtr pDev = NULL, keyboard;
2043706f2543Smrg    REQUEST(xChangeKeyboardControlReq);
2044706f2543Smrg
2045706f2543Smrg    REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
2046706f2543Smrg
2047706f2543Smrg    vmask = stuff->mask;
2048706f2543Smrg    vlist = (XID *)&stuff[1];
2049706f2543Smrg
2050706f2543Smrg    if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask))
2051706f2543Smrg	return BadLength;
2052706f2543Smrg
2053706f2543Smrg    keyboard = PickKeyboard(client);
2054706f2543Smrg
2055706f2543Smrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2056706f2543Smrg        if ((pDev == keyboard ||
2057706f2543Smrg	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2058706f2543Smrg	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2059706f2543Smrg            ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
2060706f2543Smrg	    if (ret != Success)
2061706f2543Smrg                return ret;
2062706f2543Smrg        }
2063706f2543Smrg    }
2064706f2543Smrg
2065706f2543Smrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
2066706f2543Smrg        if ((pDev == keyboard ||
2067706f2543Smrg	     (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
2068706f2543Smrg	    && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
2069706f2543Smrg            ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
2070706f2543Smrg            if (ret != Success)
2071706f2543Smrg                error = ret;
2072706f2543Smrg        }
2073706f2543Smrg    }
2074706f2543Smrg
2075706f2543Smrg    return error;
2076706f2543Smrg}
2077706f2543Smrg
2078706f2543Smrgint
2079706f2543SmrgProcGetKeyboardControl (ClientPtr client)
2080706f2543Smrg{
2081706f2543Smrg    int rc, i;
2082706f2543Smrg    DeviceIntPtr kbd = PickKeyboard(client);
2083706f2543Smrg    KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
2084706f2543Smrg    xGetKeyboardControlReply rep;
2085706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2086706f2543Smrg
2087706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
2088706f2543Smrg    if (rc != Success)
2089706f2543Smrg	return rc;
2090706f2543Smrg
2091706f2543Smrg    rep.type = X_Reply;
2092706f2543Smrg    rep.length = 5;
2093706f2543Smrg    rep.sequenceNumber = client->sequence;
2094706f2543Smrg    rep.globalAutoRepeat = ctrl->autoRepeat;
2095706f2543Smrg    rep.keyClickPercent = ctrl->click;
2096706f2543Smrg    rep.bellPercent = ctrl->bell;
2097706f2543Smrg    rep.bellPitch = ctrl->bell_pitch;
2098706f2543Smrg    rep.bellDuration = ctrl->bell_duration;
2099706f2543Smrg    rep.ledMask = ctrl->leds;
2100706f2543Smrg    for (i = 0; i < 32; i++)
2101706f2543Smrg	rep.map[i] = ctrl->autoRepeats[i];
2102706f2543Smrg    WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
2103706f2543Smrg    return Success;
2104706f2543Smrg}
2105706f2543Smrg
2106706f2543Smrgint
2107706f2543SmrgProcBell(ClientPtr client)
2108706f2543Smrg{
2109706f2543Smrg    DeviceIntPtr dev, keybd = PickKeyboard(client);
2110706f2543Smrg    int base = keybd->kbdfeed->ctrl.bell;
2111706f2543Smrg    int newpercent;
2112706f2543Smrg    int rc;
2113706f2543Smrg    REQUEST(xBellReq);
2114706f2543Smrg    REQUEST_SIZE_MATCH(xBellReq);
2115706f2543Smrg
2116706f2543Smrg    if (stuff->percent < -100 || stuff->percent > 100) {
2117706f2543Smrg	client->errorValue = stuff->percent;
2118706f2543Smrg	return BadValue;
2119706f2543Smrg    }
2120706f2543Smrg
2121706f2543Smrg    newpercent = (base * stuff->percent) / 100;
2122706f2543Smrg    if (stuff->percent < 0)
2123706f2543Smrg        newpercent = base + newpercent;
2124706f2543Smrg    else
2125706f2543Smrg	newpercent = base - newpercent + stuff->percent;
2126706f2543Smrg
2127706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2128706f2543Smrg        if ((dev == keybd ||
2129706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) &&
2130706f2543Smrg            dev->kbdfeed && dev->kbdfeed->BellProc) {
2131706f2543Smrg
2132706f2543Smrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess);
2133706f2543Smrg	    if (rc != Success)
2134706f2543Smrg		return rc;
2135706f2543Smrg            XkbHandleBell(FALSE, FALSE, dev, newpercent,
2136706f2543Smrg                          &dev->kbdfeed->ctrl, 0, None, NULL, client);
2137706f2543Smrg        }
2138706f2543Smrg    }
2139706f2543Smrg
2140706f2543Smrg    return Success;
2141706f2543Smrg}
2142706f2543Smrg
2143706f2543Smrgint
2144706f2543SmrgProcChangePointerControl(ClientPtr client)
2145706f2543Smrg{
2146706f2543Smrg    DeviceIntPtr dev, mouse = PickPointer(client);
2147706f2543Smrg    PtrCtrl ctrl;		/* might get BadValue part way through */
2148706f2543Smrg    int rc;
2149706f2543Smrg    REQUEST(xChangePointerControlReq);
2150706f2543Smrg    REQUEST_SIZE_MATCH(xChangePointerControlReq);
2151706f2543Smrg
2152706f2543Smrg    ctrl = mouse->ptrfeed->ctrl;
2153706f2543Smrg    if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
2154706f2543Smrg	client->errorValue = stuff->doAccel;
2155706f2543Smrg	return BadValue;
2156706f2543Smrg    }
2157706f2543Smrg    if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
2158706f2543Smrg	client->errorValue = stuff->doThresh;
2159706f2543Smrg	return BadValue;
2160706f2543Smrg    }
2161706f2543Smrg    if (stuff->doAccel) {
2162706f2543Smrg	if (stuff->accelNum == -1) {
2163706f2543Smrg	    ctrl.num = defaultPointerControl.num;
2164706f2543Smrg        }
2165706f2543Smrg	else if (stuff->accelNum < 0) {
2166706f2543Smrg	    client->errorValue = stuff->accelNum;
2167706f2543Smrg	    return BadValue;
2168706f2543Smrg	}
2169706f2543Smrg	else {
2170706f2543Smrg            ctrl.num = stuff->accelNum;
2171706f2543Smrg        }
2172706f2543Smrg
2173706f2543Smrg	if (stuff->accelDenum == -1) {
2174706f2543Smrg	    ctrl.den = defaultPointerControl.den;
2175706f2543Smrg        }
2176706f2543Smrg	else if (stuff->accelDenum <= 0) {
2177706f2543Smrg	    client->errorValue = stuff->accelDenum;
2178706f2543Smrg	    return BadValue;
2179706f2543Smrg	}
2180706f2543Smrg	else {
2181706f2543Smrg            ctrl.den = stuff->accelDenum;
2182706f2543Smrg        }
2183706f2543Smrg    }
2184706f2543Smrg    if (stuff->doThresh) {
2185706f2543Smrg	if (stuff->threshold == -1) {
2186706f2543Smrg	    ctrl.threshold = defaultPointerControl.threshold;
2187706f2543Smrg        }
2188706f2543Smrg	else if (stuff->threshold < 0) {
2189706f2543Smrg	    client->errorValue = stuff->threshold;
2190706f2543Smrg	    return BadValue;
2191706f2543Smrg	}
2192706f2543Smrg	else {
2193706f2543Smrg            ctrl.threshold = stuff->threshold;
2194706f2543Smrg        }
2195706f2543Smrg    }
2196706f2543Smrg
2197706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2198706f2543Smrg        if ((dev == mouse ||
2199706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2200706f2543Smrg            dev->ptrfeed) {
2201706f2543Smrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
2202706f2543Smrg	    if (rc != Success)
2203706f2543Smrg		return rc;
2204706f2543Smrg	}
2205706f2543Smrg    }
2206706f2543Smrg
2207706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
2208706f2543Smrg        if ((dev == mouse ||
2209706f2543Smrg	     (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
2210706f2543Smrg            dev->ptrfeed) {
2211706f2543Smrg            dev->ptrfeed->ctrl = ctrl;
2212706f2543Smrg        }
2213706f2543Smrg    }
2214706f2543Smrg
2215706f2543Smrg    return Success;
2216706f2543Smrg}
2217706f2543Smrg
2218706f2543Smrgint
2219706f2543SmrgProcGetPointerControl(ClientPtr client)
2220706f2543Smrg{
2221706f2543Smrg    DeviceIntPtr ptr = PickPointer(client);
2222706f2543Smrg    PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
2223706f2543Smrg    xGetPointerControlReply rep;
2224706f2543Smrg    int rc;
2225706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2226706f2543Smrg
2227706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
2228706f2543Smrg    if (rc != Success)
2229706f2543Smrg	return rc;
2230706f2543Smrg
2231706f2543Smrg    rep.type = X_Reply;
2232706f2543Smrg    rep.length = 0;
2233706f2543Smrg    rep.sequenceNumber = client->sequence;
2234706f2543Smrg    rep.threshold = ctrl->threshold;
2235706f2543Smrg    rep.accelNumerator = ctrl->num;
2236706f2543Smrg    rep.accelDenominator = ctrl->den;
2237706f2543Smrg    WriteReplyToClient(client, sizeof(xGenericReply), &rep);
2238706f2543Smrg    return Success;
2239706f2543Smrg}
2240706f2543Smrg
2241706f2543Smrgvoid
2242706f2543SmrgMaybeStopHint(DeviceIntPtr dev, ClientPtr client)
2243706f2543Smrg{
2244706f2543Smrg    GrabPtr grab = dev->deviceGrab.grab;
2245706f2543Smrg
2246706f2543Smrg    if ((grab && SameClient(grab, client) &&
2247706f2543Smrg	 ((grab->eventMask & PointerMotionHintMask) ||
2248706f2543Smrg	  (grab->ownerEvents &&
2249706f2543Smrg	   (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2250706f2543Smrg	    PointerMotionHintMask)))) ||
2251706f2543Smrg	(!grab &&
2252706f2543Smrg	 (EventMaskForClient(dev->valuator->motionHintWindow, client) &
2253706f2543Smrg	  PointerMotionHintMask)))
2254706f2543Smrg	dev->valuator->motionHintWindow = NullWindow;
2255706f2543Smrg}
2256706f2543Smrg
2257706f2543Smrgint
2258706f2543SmrgProcGetMotionEvents(ClientPtr client)
2259706f2543Smrg{
2260706f2543Smrg    WindowPtr pWin;
2261706f2543Smrg    xTimecoord * coords = (xTimecoord *) NULL;
2262706f2543Smrg    xGetMotionEventsReply rep;
2263706f2543Smrg    int i, count, xmin, xmax, ymin, ymax, rc;
2264706f2543Smrg    unsigned long nEvents;
2265706f2543Smrg    DeviceIntPtr mouse = PickPointer(client);
2266706f2543Smrg    TimeStamp start, stop;
2267706f2543Smrg    REQUEST(xGetMotionEventsReq);
2268706f2543Smrg    REQUEST_SIZE_MATCH(xGetMotionEventsReq);
2269706f2543Smrg
2270706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2271706f2543Smrg    if (rc != Success)
2272706f2543Smrg	return rc;
2273706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
2274706f2543Smrg    if (rc != Success)
2275706f2543Smrg	return rc;
2276706f2543Smrg
2277706f2543Smrg    if (mouse->valuator->motionHintWindow)
2278706f2543Smrg	MaybeStopHint(mouse, client);
2279706f2543Smrg    rep.type = X_Reply;
2280706f2543Smrg    rep.sequenceNumber = client->sequence;
2281706f2543Smrg    nEvents = 0;
2282706f2543Smrg    start = ClientTimeToServerTime(stuff->start);
2283706f2543Smrg    stop = ClientTimeToServerTime(stuff->stop);
2284706f2543Smrg    if ((CompareTimeStamps(start, stop) != LATER) &&
2285706f2543Smrg	(CompareTimeStamps(start, currentTime) != LATER) &&
2286706f2543Smrg	mouse->valuator->numMotionEvents)
2287706f2543Smrg    {
2288706f2543Smrg	if (CompareTimeStamps(stop, currentTime) == LATER)
2289706f2543Smrg	    stop = currentTime;
2290706f2543Smrg	count = GetMotionHistory(mouse, &coords, start.milliseconds,
2291706f2543Smrg				 stop.milliseconds, pWin->drawable.pScreen,
2292706f2543Smrg                                 TRUE);
2293706f2543Smrg	xmin = pWin->drawable.x - wBorderWidth (pWin);
2294706f2543Smrg	xmax = pWin->drawable.x + (int)pWin->drawable.width +
2295706f2543Smrg		wBorderWidth (pWin);
2296706f2543Smrg	ymin = pWin->drawable.y - wBorderWidth (pWin);
2297706f2543Smrg	ymax = pWin->drawable.y + (int)pWin->drawable.height +
2298706f2543Smrg		wBorderWidth (pWin);
2299706f2543Smrg	for (i = 0; i < count; i++)
2300706f2543Smrg	    if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
2301706f2543Smrg		    (ymin <= coords[i].y) && (coords[i].y < ymax))
2302706f2543Smrg	    {
2303706f2543Smrg		coords[nEvents].time = coords[i].time;
2304706f2543Smrg		coords[nEvents].x = coords[i].x - pWin->drawable.x;
2305706f2543Smrg		coords[nEvents].y = coords[i].y - pWin->drawable.y;
2306706f2543Smrg		nEvents++;
2307706f2543Smrg	    }
2308706f2543Smrg    }
2309706f2543Smrg    rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord));
2310706f2543Smrg    rep.nEvents = nEvents;
2311706f2543Smrg    WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
2312706f2543Smrg    if (nEvents)
2313706f2543Smrg    {
2314706f2543Smrg	client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
2315706f2543Smrg	WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
2316706f2543Smrg				 (char *)coords);
2317706f2543Smrg    }
2318706f2543Smrg    free(coords);
2319706f2543Smrg    return Success;
2320706f2543Smrg}
2321706f2543Smrg
2322706f2543Smrgint
2323706f2543SmrgProcQueryKeymap(ClientPtr client)
2324706f2543Smrg{
2325706f2543Smrg    xQueryKeymapReply rep;
2326706f2543Smrg    int rc, i;
2327706f2543Smrg    DeviceIntPtr keybd = PickKeyboard(client);
2328706f2543Smrg    CARD8 *down = keybd->key->down;
2329706f2543Smrg
2330706f2543Smrg    REQUEST_SIZE_MATCH(xReq);
2331706f2543Smrg    rep.type = X_Reply;
2332706f2543Smrg    rep.sequenceNumber = client->sequence;
2333706f2543Smrg    rep.length = 2;
2334706f2543Smrg
2335706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
2336706f2543Smrg    if (rc != Success && rc != BadAccess)
2337706f2543Smrg	return rc;
2338706f2543Smrg
2339706f2543Smrg    for (i = 0; i<32; i++)
2340706f2543Smrg	rep.map[i] = down[i];
2341706f2543Smrg
2342706f2543Smrg    if (rc == BadAccess)
2343706f2543Smrg	memset(rep.map, 0, 32);
2344706f2543Smrg
2345706f2543Smrg    WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
2346706f2543Smrg
2347706f2543Smrg   return Success;
2348706f2543Smrg}
2349706f2543Smrg
2350706f2543Smrg
2351706f2543Smrg/**
2352706f2543Smrg * Recalculate the number of buttons for the master device. The number of
2353706f2543Smrg * buttons on the master device is equal to the number of buttons on the
2354706f2543Smrg * slave device with the highest number of buttons.
2355706f2543Smrg */
2356706f2543Smrgstatic void
2357706f2543SmrgRecalculateMasterButtons(DeviceIntPtr slave)
2358706f2543Smrg{
2359706f2543Smrg    DeviceIntPtr dev, master;
2360706f2543Smrg    int maxbuttons = 0;
2361706f2543Smrg
2362706f2543Smrg    if (!slave->button || IsMaster(slave))
2363706f2543Smrg        return;
2364706f2543Smrg
2365706f2543Smrg    master = GetMaster(slave, MASTER_POINTER);
2366706f2543Smrg    if (!master)
2367706f2543Smrg        return;
2368706f2543Smrg
2369706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next)
2370706f2543Smrg    {
2371706f2543Smrg        if (IsMaster(dev) ||
2372706f2543Smrg            dev->u.master != master ||
2373706f2543Smrg            !dev->button)
2374706f2543Smrg            continue;
2375706f2543Smrg
2376706f2543Smrg        maxbuttons = max(maxbuttons, dev->button->numButtons);
2377706f2543Smrg    }
2378706f2543Smrg
2379706f2543Smrg    if (master->button && master->button->numButtons != maxbuttons)
2380706f2543Smrg    {
2381706f2543Smrg        int i;
2382706f2543Smrg        DeviceChangedEvent event;
2383706f2543Smrg
2384706f2543Smrg        memset(&event, 0, sizeof(event));
2385706f2543Smrg
2386706f2543Smrg        master->button->numButtons = maxbuttons;
2387706f2543Smrg
2388706f2543Smrg        event.header = ET_Internal;
2389706f2543Smrg        event.type = ET_DeviceChanged;
2390706f2543Smrg        event.time = GetTimeInMillis();
2391706f2543Smrg        event.deviceid = master->id;
2392706f2543Smrg        event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE;
2393706f2543Smrg        event.buttons.num_buttons = maxbuttons;
2394706f2543Smrg        memcpy(&event.buttons.names, master->button->labels, maxbuttons *
2395706f2543Smrg                sizeof(Atom));
2396706f2543Smrg
2397706f2543Smrg        if (master->valuator)
2398706f2543Smrg        {
2399706f2543Smrg            event.num_valuators = master->valuator->numAxes;
2400706f2543Smrg            for (i = 0; i < event.num_valuators; i++)
2401706f2543Smrg            {
2402706f2543Smrg                event.valuators[i].min = master->valuator->axes[i].min_value;
2403706f2543Smrg                event.valuators[i].max = master->valuator->axes[i].max_value;
2404706f2543Smrg                event.valuators[i].resolution = master->valuator->axes[i].resolution;
2405706f2543Smrg                event.valuators[i].mode = master->valuator->axes[i].mode;
2406706f2543Smrg                event.valuators[i].name = master->valuator->axes[i].label;
2407706f2543Smrg            }
2408706f2543Smrg        }
2409706f2543Smrg
2410706f2543Smrg        if (master->key)
2411706f2543Smrg        {
2412706f2543Smrg            event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code;
2413706f2543Smrg            event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code;
2414706f2543Smrg        }
2415706f2543Smrg
2416706f2543Smrg        XISendDeviceChangedEvent(master, master, &event);
2417706f2543Smrg    }
2418706f2543Smrg}
2419706f2543Smrg
2420706f2543Smrg/**
2421706f2543Smrg * Generate release events for all keys/button currently down on this
2422706f2543Smrg * device.
2423706f2543Smrg */
2424706f2543Smrgvoid
2425706f2543SmrgReleaseButtonsAndKeys(DeviceIntPtr dev)
2426706f2543Smrg{
2427706f2543Smrg    EventListPtr        eventlist = InitEventList(GetMaximumEventsNum());
2428706f2543Smrg    ButtonClassPtr      b = dev->button;
2429706f2543Smrg    KeyClassPtr         k = dev->key;
2430706f2543Smrg    int                 i, j, nevents;
2431706f2543Smrg
2432706f2543Smrg    if (!eventlist) /* no release events for you */
2433706f2543Smrg        return;
2434706f2543Smrg
2435706f2543Smrg    /* Release all buttons */
2436706f2543Smrg    for (i = 0; b && i < b->numButtons; i++)
2437706f2543Smrg    {
2438706f2543Smrg        if (BitIsOn(b->down, i))
2439706f2543Smrg        {
2440706f2543Smrg            nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
2441706f2543Smrg            for (j = 0; j < nevents; j++)
2442706f2543Smrg                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2443706f2543Smrg        }
2444706f2543Smrg    }
2445706f2543Smrg
2446706f2543Smrg    /* Release all keys */
2447706f2543Smrg    for (i = 0; k && i < MAP_LENGTH; i++)
2448706f2543Smrg    {
2449706f2543Smrg        if (BitIsOn(k->down, i))
2450706f2543Smrg        {
2451706f2543Smrg            nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
2452706f2543Smrg            for (j = 0; j < nevents; j++)
2453706f2543Smrg                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
2454706f2543Smrg        }
2455706f2543Smrg    }
2456706f2543Smrg
2457706f2543Smrg    FreeEventList(eventlist, GetMaximumEventsNum());
2458706f2543Smrg}
2459706f2543Smrg
2460706f2543Smrg/**
2461706f2543Smrg * Attach device 'dev' to device 'master'.
2462706f2543Smrg * Client is set to the client that issued the request, or NULL if it comes
2463706f2543Smrg * from some internal automatic pairing.
2464706f2543Smrg *
2465706f2543Smrg * Master may be NULL to set the device floating.
2466706f2543Smrg *
2467706f2543Smrg * We don't allow multi-layer hierarchies right now. You can't attach a slave
2468706f2543Smrg * to another slave.
2469706f2543Smrg */
2470706f2543Smrgint
2471706f2543SmrgAttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
2472706f2543Smrg{
2473706f2543Smrg    ScreenPtr screen;
2474706f2543Smrg    DeviceIntPtr oldmaster;
2475706f2543Smrg    if (!dev || IsMaster(dev))
2476706f2543Smrg        return BadDevice;
2477706f2543Smrg
2478706f2543Smrg    if (master && !IsMaster(master)) /* can't attach to slaves */
2479706f2543Smrg        return BadDevice;
2480706f2543Smrg
2481706f2543Smrg    /* set from floating to floating? */
2482706f2543Smrg    if (!dev->u.master && !master && dev->enabled)
2483706f2543Smrg        return Success;
2484706f2543Smrg
2485706f2543Smrg    /* free the existing sprite. */
2486706f2543Smrg    if (!dev->u.master && dev->spriteInfo->paired == dev)
2487706f2543Smrg    {
2488706f2543Smrg        screen = miPointerGetScreen(dev);
2489706f2543Smrg        screen->DeviceCursorCleanup(dev, screen);
2490706f2543Smrg        free(dev->spriteInfo->sprite);
2491706f2543Smrg    }
2492706f2543Smrg
2493706f2543Smrg    oldmaster = dev->u.master;
2494706f2543Smrg    dev->u.master = master;
2495706f2543Smrg
2496706f2543Smrg    /* If device is set to floating, we need to create a sprite for it,
2497706f2543Smrg     * otherwise things go bad. However, we don't want to render the cursor,
2498706f2543Smrg     * so we reset spriteOwner.
2499706f2543Smrg     * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
2500706f2543Smrg     * alloc new memory but overwrite the previous one.
2501706f2543Smrg     */
2502706f2543Smrg    if (!master)
2503706f2543Smrg    {
2504706f2543Smrg        WindowPtr currentRoot;
2505706f2543Smrg
2506706f2543Smrg        if (dev->spriteInfo->sprite)
2507706f2543Smrg            currentRoot = GetCurrentRootWindow(dev);
2508706f2543Smrg        else /* new device auto-set to floating */
2509706f2543Smrg            currentRoot = screenInfo.screens[0]->root;
2510706f2543Smrg
2511706f2543Smrg        /* we need to init a fake sprite */
2512706f2543Smrg        screen = currentRoot->drawable.pScreen;
2513706f2543Smrg        screen->DeviceCursorInitialize(dev, screen);
2514706f2543Smrg        dev->spriteInfo->sprite = NULL;
2515706f2543Smrg        InitializeSprite(dev, currentRoot);
2516706f2543Smrg        dev->spriteInfo->spriteOwner = FALSE;
2517706f2543Smrg        dev->spriteInfo->paired = dev;
2518706f2543Smrg    } else
2519706f2543Smrg    {
2520706f2543Smrg        dev->spriteInfo->sprite = master->spriteInfo->sprite;
2521706f2543Smrg        dev->spriteInfo->paired = master;
2522706f2543Smrg        dev->spriteInfo->spriteOwner = FALSE;
2523706f2543Smrg
2524706f2543Smrg        RecalculateMasterButtons(master);
2525706f2543Smrg    }
2526706f2543Smrg
2527706f2543Smrg    /* XXX: in theory, the MD should change back to its old, original
2528706f2543Smrg     * classes when the last SD is detached. Thanks to the XTEST devices,
2529706f2543Smrg     * we'll always have an SD attached until the MD is removed.
2530706f2543Smrg     * So let's not worry about that.
2531706f2543Smrg     */
2532706f2543Smrg
2533706f2543Smrg    return Success;
2534706f2543Smrg}
2535706f2543Smrg
2536706f2543Smrg/**
2537706f2543Smrg * Return the device paired with the given device or NULL.
2538706f2543Smrg * Returns the device paired with the parent master if the given device is a
2539706f2543Smrg * slave device.
2540706f2543Smrg */
2541706f2543SmrgDeviceIntPtr
2542706f2543SmrgGetPairedDevice(DeviceIntPtr dev)
2543706f2543Smrg{
2544706f2543Smrg    if (!IsMaster(dev) && dev->u.master)
2545706f2543Smrg        dev = dev->u.master;
2546706f2543Smrg
2547706f2543Smrg    return dev->spriteInfo->paired;
2548706f2543Smrg}
2549706f2543Smrg
2550706f2543Smrg
2551706f2543Smrg/**
2552706f2543Smrg * Returns the right master for the type of event needed. If the event is a
2553706f2543Smrg * keyboard event.
2554706f2543Smrg * This function may be called with a master device as argument. If so, the
2555706f2543Smrg * returned master is either the device itself or the paired master device.
2556706f2543Smrg * If dev is a floating slave device, NULL is returned.
2557706f2543Smrg *
2558706f2543Smrg * @type ::MASTER_KEYBOARD or ::MASTER_POINTER
2559706f2543Smrg */
2560706f2543SmrgDeviceIntPtr
2561706f2543SmrgGetMaster(DeviceIntPtr dev, int which)
2562706f2543Smrg{
2563706f2543Smrg    DeviceIntPtr master;
2564706f2543Smrg
2565706f2543Smrg    if (IsMaster(dev))
2566706f2543Smrg        master = dev;
2567706f2543Smrg    else
2568706f2543Smrg        master = dev->u.master;
2569706f2543Smrg
2570706f2543Smrg    if (master)
2571706f2543Smrg    {
2572706f2543Smrg        if (which == MASTER_KEYBOARD)
2573706f2543Smrg        {
2574706f2543Smrg            if (master->type != MASTER_KEYBOARD)
2575706f2543Smrg                master = GetPairedDevice(master);
2576706f2543Smrg        } else
2577706f2543Smrg        {
2578706f2543Smrg            if (master->type != MASTER_POINTER)
2579706f2543Smrg                master = GetPairedDevice(master);
2580706f2543Smrg        }
2581706f2543Smrg    }
2582706f2543Smrg
2583706f2543Smrg    return master;
2584706f2543Smrg}
2585706f2543Smrg
2586706f2543Smrg/**
2587706f2543Smrg * Create a new device pair (== one pointer, one keyboard device).
2588706f2543Smrg * Only allocates the devices, you will need to call ActivateDevice() and
2589706f2543Smrg * EnableDevice() manually.
2590706f2543Smrg * Either a master or a slave device can be created depending on
2591706f2543Smrg * the value for master.
2592706f2543Smrg */
2593706f2543Smrgint
2594706f2543SmrgAllocDevicePair (ClientPtr client, char* name,
2595706f2543Smrg                 DeviceIntPtr* ptr,
2596706f2543Smrg                 DeviceIntPtr* keybd,
2597706f2543Smrg                 DeviceProc ptr_proc,
2598706f2543Smrg                 DeviceProc keybd_proc,
2599706f2543Smrg                 Bool master)
2600706f2543Smrg{
2601706f2543Smrg    DeviceIntPtr pointer;
2602706f2543Smrg    DeviceIntPtr keyboard;
2603706f2543Smrg    *ptr = *keybd = NULL;
2604706f2543Smrg
2605706f2543Smrg    pointer = AddInputDevice(client, ptr_proc, TRUE);
2606706f2543Smrg    if (!pointer)
2607706f2543Smrg        return BadAlloc;
2608706f2543Smrg
2609706f2543Smrg    if (asprintf(&pointer->name, "%s pointer", name) == -1) {
2610706f2543Smrg        pointer->name = NULL;
2611706f2543Smrg        RemoveDevice(pointer, FALSE);
2612706f2543Smrg        return BadAlloc;
2613706f2543Smrg    }
2614706f2543Smrg
2615706f2543Smrg    pointer->public.processInputProc = ProcessOtherEvent;
2616706f2543Smrg    pointer->public.realInputProc = ProcessOtherEvent;
2617706f2543Smrg    XkbSetExtension(pointer, ProcessPointerEvent);
2618706f2543Smrg    pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
2619706f2543Smrg    pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
2620706f2543Smrg    pointer->coreEvents = TRUE;
2621706f2543Smrg    pointer->spriteInfo->spriteOwner = TRUE;
2622706f2543Smrg
2623706f2543Smrg    pointer->u.lastSlave = NULL;
2624706f2543Smrg    pointer->last.slave = NULL;
2625706f2543Smrg    pointer->type = (master) ? MASTER_POINTER : SLAVE;
2626706f2543Smrg
2627706f2543Smrg    keyboard = AddInputDevice(client, keybd_proc, TRUE);
2628706f2543Smrg    if (!keyboard)
2629706f2543Smrg    {
2630706f2543Smrg        RemoveDevice(pointer, FALSE);
2631706f2543Smrg        return BadAlloc;
2632706f2543Smrg    }
2633706f2543Smrg
2634706f2543Smrg    if (asprintf(&keyboard->name, "%s keyboard", name) == -1) {
2635706f2543Smrg        keyboard->name = NULL;
2636706f2543Smrg        RemoveDevice(keyboard, FALSE);
2637706f2543Smrg        RemoveDevice(pointer, FALSE);
2638706f2543Smrg        return BadAlloc;
2639706f2543Smrg    }
2640706f2543Smrg
2641706f2543Smrg    keyboard->public.processInputProc = ProcessOtherEvent;
2642706f2543Smrg    keyboard->public.realInputProc = ProcessOtherEvent;
2643706f2543Smrg    XkbSetExtension(keyboard, ProcessKeyboardEvent);
2644706f2543Smrg    keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
2645706f2543Smrg    keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
2646706f2543Smrg    keyboard->coreEvents = TRUE;
2647706f2543Smrg    keyboard->spriteInfo->spriteOwner = FALSE;
2648706f2543Smrg
2649706f2543Smrg    keyboard->u.lastSlave = NULL;
2650706f2543Smrg    keyboard->last.slave = NULL;
2651706f2543Smrg    keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
2652706f2543Smrg
2653706f2543Smrg    /* The ClassesRec stores the device classes currently not used. */
2654706f2543Smrg    pointer->unused_classes = calloc(1, sizeof(ClassesRec));
2655706f2543Smrg    keyboard->unused_classes = calloc(1, sizeof(ClassesRec));
2656706f2543Smrg
2657706f2543Smrg    *ptr = pointer;
2658706f2543Smrg    *keybd = keyboard;
2659706f2543Smrg
2660706f2543Smrg    return Success;
2661706f2543Smrg}
2662706f2543Smrg
2663706f2543Smrg/**
2664706f2543Smrg * Return Relative or Absolute for the device.
2665706f2543Smrg */
2666706f2543Smrgint valuator_get_mode(DeviceIntPtr dev, int axis)
2667706f2543Smrg{
2668706f2543Smrg    return (dev->valuator->axes[axis].mode & DeviceMode);
2669706f2543Smrg}
2670706f2543Smrg
2671706f2543Smrg/**
2672706f2543Smrg * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then
2673706f2543Smrg * set the mode for all axes.
2674706f2543Smrg */
2675706f2543Smrgvoid valuator_set_mode(DeviceIntPtr dev, int axis, int mode)
2676706f2543Smrg{
2677706f2543Smrg    if (axis != VALUATOR_MODE_ALL_AXES)
2678706f2543Smrg        dev->valuator->axes[axis].mode = mode;
2679706f2543Smrg    else {
2680706f2543Smrg        int i;
2681706f2543Smrg        for (i = 0; i < dev->valuator->numAxes; i++)
2682706f2543Smrg            dev->valuator->axes[i].mode = mode;
2683706f2543Smrg    }
2684706f2543Smrg}
2685