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