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