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