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