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