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