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