1 /************************************************************ 2 3 Copyright 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in this Software without prior written authorization from The Open Group. 24 25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29 Permission to use, copy, modify, and distribute this software and its 30 documentation for any purpose and without fee is hereby granted, 31 provided that the above copyright notice appear in all copies and that 32 both that copyright notice and this permission notice appear in 33 supporting documentation, and that the name of Hewlett-Packard not be 34 used in advertising or publicity pertaining to distribution of the 35 software without specific, written prior permission. 36 37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43 SOFTWARE. 44 45 ********************************************************/ 46 47 /* 48 * Copyright 2010 Collabora Ltd. 49 * Copyright 2011 Red Hat, Inc. 50 * 51 * Permission is hereby granted, free of charge, to any person obtaining a 52 * copy of this software and associated documentation files (the "Software"), 53 * to deal in the Software without restriction, including without limitation 54 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 55 * and/or sell copies of the Software, and to permit persons to whom the 56 * Software is furnished to do so, subject to the following conditions: 57 * 58 * The above copyright notice and this permission notice (including the next 59 * paragraph) shall be included in all copies or substantial portions of the 60 * Software. 61 * 62 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 65 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 66 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 67 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 68 * DEALINGS IN THE SOFTWARE. 69 * 70 * Author: Daniel Stone <daniel (at) fooishbar.org> 71 */ 72 73 /******************************************************************** 74 * 75 * Routines to register and initialize extension input devices. 76 * This also contains ProcessOtherEvent, the routine called from DDX 77 * to route extension events. 78 * 79 */ 80 81 #ifdef HAVE_DIX_CONFIG_H 82 #include <dix-config.h> 83 #endif 84 85 #include "inputstr.h" 86 #include <X11/X.h> 87 #include <X11/Xproto.h> 88 #include <X11/extensions/XI.h> 89 #include <X11/extensions/XIproto.h> 90 #include <X11/extensions/XI2proto.h> 91 #include <X11/extensions/geproto.h> 92 #include "windowstr.h" 93 #include "miscstruct.h" 94 #include "region.h" 95 #include "exevents.h" 96 #include "extnsionst.h" 97 #include "exglobals.h" 98 #include "eventstr.h" 99 #include "dixevents.h" /* DeliverFocusedEvent */ 100 #include "dixgrabs.h" /* CreateGrab() */ 101 #include "scrnintstr.h" 102 #include "listdev.h" /* for CopySwapXXXClass */ 103 #include "xace.h" 104 #include "xiquerydevice.h" /* For List*Info */ 105 #include "eventconvert.h" 106 #include "eventstr.h" 107 #include "inpututils.h" 108 #include "mi.h" 109 110 #include <X11/extensions/XKBproto.h> 111 #include "xkbsrv.h" 112 113 #define WID(w) ((w) ? ((w)->drawable.id) : 0) 114 #define AllModifiersMask ( \ 115 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 116 Mod3Mask | Mod4Mask | Mod5Mask ) 117 #define AllButtonsMask ( \ 118 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 119 120 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , 121 Bool /* ignoreSelectedEvents */ 122 ); 123 static Bool MakeInputMasks(WindowPtr /* pWin */ 124 ); 125 126 /* 127 * Only let the given client know of core events which will affect its 128 * interpretation of input events, if the client's ClientPointer (or the 129 * paired keyboard) is the current device. 130 */ 131 int 132 XIShouldNotify(ClientPtr client, DeviceIntPtr dev) 133 { 134 DeviceIntPtr current_ptr = PickPointer(client); 135 DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT); 136 137 if (dev == current_kbd || dev == current_ptr) 138 return 1; 139 140 return 0; 141 } 142 143 Bool 144 IsPointerEvent(InternalEvent *event) 145 { 146 switch (event->any.type) { 147 case ET_ButtonPress: 148 case ET_ButtonRelease: 149 case ET_Motion: 150 /* XXX: enter/leave ?? */ 151 return TRUE; 152 default: 153 break; 154 } 155 return FALSE; 156 } 157 158 Bool 159 IsTouchEvent(InternalEvent *event) 160 { 161 switch (event->any.type) { 162 case ET_TouchBegin: 163 case ET_TouchUpdate: 164 case ET_TouchEnd: 165 return TRUE; 166 default: 167 break; 168 } 169 return FALSE; 170 } 171 172 Bool 173 IsGestureEvent(InternalEvent *event) 174 { 175 switch (event->any.type) { 176 case ET_GesturePinchBegin: 177 case ET_GesturePinchUpdate: 178 case ET_GesturePinchEnd: 179 case ET_GestureSwipeBegin: 180 case ET_GestureSwipeUpdate: 181 case ET_GestureSwipeEnd: 182 return TRUE; 183 default: 184 break; 185 } 186 return FALSE; 187 } 188 189 Bool 190 IsGestureBeginEvent(InternalEvent *event) 191 { 192 switch (event->any.type) { 193 case ET_GesturePinchBegin: 194 case ET_GestureSwipeBegin: 195 return TRUE; 196 default: 197 break; 198 } 199 return FALSE; 200 } 201 202 Bool 203 IsGestureEndEvent(InternalEvent *event) 204 { 205 switch (event->any.type) { 206 case ET_GesturePinchEnd: 207 case ET_GestureSwipeEnd: 208 return TRUE; 209 default: 210 break; 211 } 212 return FALSE; 213 } 214 215 /** 216 * @return the device matching the deviceid of the device set in the event, or 217 * NULL if the event is not an XInput event. 218 */ 219 DeviceIntPtr 220 XIGetDevice(xEvent *xE) 221 { 222 DeviceIntPtr pDev = NULL; 223 224 if (xE->u.u.type == DeviceButtonPress || 225 xE->u.u.type == DeviceButtonRelease || 226 xE->u.u.type == DeviceMotionNotify || 227 xE->u.u.type == ProximityIn || 228 xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) { 229 int rc; 230 int id; 231 232 id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS; 233 234 rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess); 235 if (rc != Success) 236 ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc); 237 } 238 return pDev; 239 } 240 241 /** 242 * Copy the device->key into master->key and send a mapping notify to the 243 * clients if appropriate. 244 * master->key needs to be allocated by the caller. 245 * 246 * Device is the slave device. If it is attached to a master device, we may 247 * need to send a mapping notify to the client because it causes the MD 248 * to change state. 249 * 250 * Mapping notify needs to be sent in the following cases: 251 * - different slave device on same master 252 * - different master 253 * 254 * XXX: They way how the code is we also send a map notify if the slave device 255 * stays the same, but the master changes. This isn't really necessary though. 256 * 257 * XXX: this gives you funny behaviour with the ClientPointer. When a 258 * MappingNotify is sent to the client, the client usually responds with a 259 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard 260 * mapping, regardless of which keyboard sent the last mapping notify request. 261 * So depending on the CP setting, your keyboard may change layout in each 262 * app... 263 * 264 * This code is basically the old SwitchCoreKeyboard. 265 */ 266 267 void 268 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) 269 { 270 KeyClassPtr mk = master->key; 271 272 if (device == master) 273 return; 274 275 mk->sourceid = device->id; 276 277 if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc)) 278 FatalError("Couldn't pivot keymap from device to core!\n"); 279 } 280 281 /** 282 * Copies the feedback classes from device "from" into device "to". Classes 283 * are duplicated (not just flipping the pointers). All feedback classes are 284 * linked lists, the full list is duplicated. 285 */ 286 static void 287 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) 288 { 289 ClassesPtr classes; 290 291 if (from->intfeed) { 292 IntegerFeedbackPtr *i, it; 293 294 if (!to->intfeed) { 295 classes = to->unused_classes; 296 to->intfeed = classes->intfeed; 297 classes->intfeed = NULL; 298 } 299 300 i = &to->intfeed; 301 for (it = from->intfeed; it; it = it->next) { 302 if (!(*i)) { 303 *i = calloc(1, sizeof(IntegerFeedbackClassRec)); 304 if (!(*i)) { 305 ErrorF("[Xi] Cannot alloc memory for class copy."); 306 return; 307 } 308 } 309 (*i)->CtrlProc = it->CtrlProc; 310 (*i)->ctrl = it->ctrl; 311 312 i = &(*i)->next; 313 } 314 } 315 else if (to->intfeed && !from->intfeed) { 316 classes = to->unused_classes; 317 classes->intfeed = to->intfeed; 318 to->intfeed = NULL; 319 } 320 321 if (from->stringfeed) { 322 StringFeedbackPtr *s, it; 323 324 if (!to->stringfeed) { 325 classes = to->unused_classes; 326 to->stringfeed = classes->stringfeed; 327 classes->stringfeed = NULL; 328 } 329 330 s = &to->stringfeed; 331 for (it = from->stringfeed; it; it = it->next) { 332 if (!(*s)) { 333 *s = calloc(1, sizeof(StringFeedbackClassRec)); 334 if (!(*s)) { 335 ErrorF("[Xi] Cannot alloc memory for class copy."); 336 return; 337 } 338 } 339 (*s)->CtrlProc = it->CtrlProc; 340 (*s)->ctrl = it->ctrl; 341 342 s = &(*s)->next; 343 } 344 } 345 else if (to->stringfeed && !from->stringfeed) { 346 classes = to->unused_classes; 347 classes->stringfeed = to->stringfeed; 348 to->stringfeed = NULL; 349 } 350 351 if (from->bell) { 352 BellFeedbackPtr *b, it; 353 354 if (!to->bell) { 355 classes = to->unused_classes; 356 to->bell = classes->bell; 357 classes->bell = NULL; 358 } 359 360 b = &to->bell; 361 for (it = from->bell; it; it = it->next) { 362 if (!(*b)) { 363 *b = calloc(1, sizeof(BellFeedbackClassRec)); 364 if (!(*b)) { 365 ErrorF("[Xi] Cannot alloc memory for class copy."); 366 return; 367 } 368 } 369 (*b)->BellProc = it->BellProc; 370 (*b)->CtrlProc = it->CtrlProc; 371 (*b)->ctrl = it->ctrl; 372 373 b = &(*b)->next; 374 } 375 } 376 else if (to->bell && !from->bell) { 377 classes = to->unused_classes; 378 classes->bell = to->bell; 379 to->bell = NULL; 380 } 381 382 if (from->leds) { 383 LedFeedbackPtr *l, it; 384 385 if (!to->leds) { 386 classes = to->unused_classes; 387 to->leds = classes->leds; 388 classes->leds = NULL; 389 } 390 391 l = &to->leds; 392 for (it = from->leds; it; it = it->next) { 393 if (!(*l)) { 394 *l = calloc(1, sizeof(LedFeedbackClassRec)); 395 if (!(*l)) { 396 ErrorF("[Xi] Cannot alloc memory for class copy."); 397 return; 398 } 399 } 400 (*l)->CtrlProc = it->CtrlProc; 401 (*l)->ctrl = it->ctrl; 402 if ((*l)->xkb_sli) 403 XkbFreeSrvLedInfo((*l)->xkb_sli); 404 (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l); 405 406 l = &(*l)->next; 407 } 408 } 409 else if (to->leds && !from->leds) { 410 classes = to->unused_classes; 411 classes->leds = to->leds; 412 to->leds = NULL; 413 } 414 } 415 416 static void 417 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to) 418 { 419 ClassesPtr classes; 420 421 /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the 422 * kbdfeed to be set up properly, so let's do the feedback classes first. 423 */ 424 if (from->kbdfeed) { 425 KbdFeedbackPtr *k, it; 426 427 if (!to->kbdfeed) { 428 classes = to->unused_classes; 429 430 to->kbdfeed = classes->kbdfeed; 431 if (!to->kbdfeed) 432 InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 433 classes->kbdfeed = NULL; 434 } 435 436 k = &to->kbdfeed; 437 for (it = from->kbdfeed; it; it = it->next) { 438 if (!(*k)) { 439 *k = calloc(1, sizeof(KbdFeedbackClassRec)); 440 if (!*k) { 441 ErrorF("[Xi] Cannot alloc memory for class copy."); 442 return; 443 } 444 } 445 (*k)->BellProc = it->BellProc; 446 (*k)->CtrlProc = it->CtrlProc; 447 (*k)->ctrl = it->ctrl; 448 if ((*k)->xkb_sli) 449 XkbFreeSrvLedInfo((*k)->xkb_sli); 450 (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); 451 452 k = &(*k)->next; 453 } 454 } 455 else if (to->kbdfeed && !from->kbdfeed) { 456 classes = to->unused_classes; 457 classes->kbdfeed = to->kbdfeed; 458 to->kbdfeed = NULL; 459 } 460 461 if (from->key) { 462 if (!to->key) { 463 classes = to->unused_classes; 464 to->key = classes->key; 465 if (!to->key) 466 InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 467 else 468 classes->key = NULL; 469 } 470 471 CopyKeyClass(from, to); 472 } 473 else if (to->key && !from->key) { 474 classes = to->unused_classes; 475 classes->key = to->key; 476 to->key = NULL; 477 } 478 479 /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps 480 * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo 481 * didn't update the pointers so we need to do it manually here. 482 */ 483 if (to->kbdfeed) { 484 KbdFeedbackPtr k; 485 486 for (k = to->kbdfeed; k; k = k->next) { 487 if (!k->xkb_sli) 488 continue; 489 if (k->xkb_sli->flags & XkbSLI_IsDefault) { 490 k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators; 491 k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps; 492 } 493 } 494 } 495 496 /* We can't just copy over the focus class. When an app sets the focus, 497 * it'll do so on the master device. Copying the SDs focus means losing 498 * the focus. 499 * So we only copy the focus class if the device didn't have one, 500 * otherwise we leave it as it is. 501 */ 502 if (from->focus) { 503 if (!to->focus) { 504 WindowPtr *oldTrace; 505 506 classes = to->unused_classes; 507 to->focus = classes->focus; 508 if (!to->focus) { 509 to->focus = calloc(1, sizeof(FocusClassRec)); 510 if (!to->focus) 511 FatalError("[Xi] no memory for class shift.\n"); 512 } 513 else 514 classes->focus = NULL; 515 516 oldTrace = to->focus->trace; 517 memcpy(to->focus, from->focus, sizeof(FocusClassRec)); 518 to->focus->trace = reallocarray(oldTrace, 519 to->focus->traceSize, 520 sizeof(WindowPtr)); 521 if (!to->focus->trace && to->focus->traceSize) 522 FatalError("[Xi] no memory for trace.\n"); 523 memcpy(to->focus->trace, from->focus->trace, 524 from->focus->traceSize * sizeof(WindowPtr)); 525 to->focus->sourceid = from->id; 526 } 527 } 528 else if (to->focus) { 529 classes = to->unused_classes; 530 classes->focus = to->focus; 531 to->focus = NULL; 532 } 533 534 } 535 536 /* FIXME: this should really be shared with the InitValuatorAxisClassRec and 537 * similar */ 538 static void 539 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) 540 { 541 ClassesPtr classes; 542 543 /* Feedback classes must be copied first */ 544 if (from->ptrfeed) { 545 PtrFeedbackPtr *p, it; 546 547 if (!to->ptrfeed) { 548 classes = to->unused_classes; 549 to->ptrfeed = classes->ptrfeed; 550 classes->ptrfeed = NULL; 551 } 552 553 p = &to->ptrfeed; 554 for (it = from->ptrfeed; it; it = it->next) { 555 if (!(*p)) { 556 *p = calloc(1, sizeof(PtrFeedbackClassRec)); 557 if (!*p) { 558 ErrorF("[Xi] Cannot alloc memory for class copy."); 559 return; 560 } 561 } 562 (*p)->CtrlProc = it->CtrlProc; 563 (*p)->ctrl = it->ctrl; 564 565 p = &(*p)->next; 566 } 567 } 568 else if (to->ptrfeed && !from->ptrfeed) { 569 classes = to->unused_classes; 570 classes->ptrfeed = to->ptrfeed; 571 to->ptrfeed = NULL; 572 } 573 574 if (from->valuator) { 575 ValuatorClassPtr v; 576 577 if (!to->valuator) { 578 classes = to->unused_classes; 579 to->valuator = classes->valuator; 580 if (to->valuator) 581 classes->valuator = NULL; 582 } 583 584 v = AllocValuatorClass(to->valuator, from->valuator->numAxes); 585 586 if (!v) 587 FatalError("[Xi] no memory for class shift.\n"); 588 589 to->valuator = v; 590 memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo)); 591 592 v->sourceid = from->id; 593 } 594 else if (to->valuator && !from->valuator) { 595 classes = to->unused_classes; 596 classes->valuator = to->valuator; 597 to->valuator = NULL; 598 } 599 600 if (from->button) { 601 if (!to->button) { 602 classes = to->unused_classes; 603 to->button = classes->button; 604 if (!to->button) { 605 to->button = calloc(1, sizeof(ButtonClassRec)); 606 if (!to->button) 607 FatalError("[Xi] no memory for class shift.\n"); 608 to->button->numButtons = from->button->numButtons; 609 } 610 else 611 classes->button = NULL; 612 } 613 614 if (from->button->xkb_acts) { 615 size_t maxbuttons = max(to->button->numButtons, from->button->numButtons); 616 to->button->xkb_acts = xnfreallocarray(to->button->xkb_acts, 617 maxbuttons, 618 sizeof(XkbAction)); 619 memset(to->button->xkb_acts, 0, maxbuttons * sizeof(XkbAction)); 620 memcpy(to->button->xkb_acts, from->button->xkb_acts, 621 from->button->numButtons * sizeof(XkbAction)); 622 } 623 else { 624 free(to->button->xkb_acts); 625 to->button->xkb_acts = NULL; 626 } 627 628 memcpy(to->button->labels, from->button->labels, 629 from->button->numButtons * sizeof(Atom)); 630 to->button->sourceid = from->id; 631 } 632 else if (to->button && !from->button) { 633 classes = to->unused_classes; 634 classes->button = to->button; 635 to->button = NULL; 636 } 637 638 if (from->proximity) { 639 if (!to->proximity) { 640 classes = to->unused_classes; 641 to->proximity = classes->proximity; 642 if (!to->proximity) { 643 to->proximity = calloc(1, sizeof(ProximityClassRec)); 644 if (!to->proximity) 645 FatalError("[Xi] no memory for class shift.\n"); 646 } 647 else 648 classes->proximity = NULL; 649 } 650 memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); 651 to->proximity->sourceid = from->id; 652 } 653 else if (to->proximity) { 654 classes = to->unused_classes; 655 classes->proximity = to->proximity; 656 to->proximity = NULL; 657 } 658 659 if (from->touch) { 660 TouchClassPtr t, f; 661 662 if (!to->touch) { 663 classes = to->unused_classes; 664 to->touch = classes->touch; 665 if (!to->touch) { 666 int i; 667 668 to->touch = calloc(1, sizeof(TouchClassRec)); 669 if (!to->touch) 670 FatalError("[Xi] no memory for class shift.\n"); 671 to->touch->num_touches = from->touch->num_touches; 672 to->touch->touches = calloc(to->touch->num_touches, 673 sizeof(TouchPointInfoRec)); 674 for (i = 0; i < to->touch->num_touches; i++) 675 TouchInitTouchPoint(to->touch, to->valuator, i); 676 if (!to->touch) 677 FatalError("[Xi] no memory for class shift.\n"); 678 } 679 else 680 classes->touch = NULL; 681 } 682 683 t = to->touch; 684 f = from->touch; 685 t->sourceid = f->sourceid; 686 t->max_touches = f->max_touches; 687 t->mode = f->mode; 688 t->buttonsDown = f->buttonsDown; 689 t->state = f->state; 690 t->motionMask = f->motionMask; 691 /* to->touches and to->num_touches are separate on the master, 692 * don't copy */ 693 } 694 /* Don't remove touch class if from->touch is non-existent. The to device 695 * may have an active touch grab, so we need to keep the touch class record 696 * around. */ 697 698 if (from->gesture) { 699 if (!to->gesture) { 700 classes = to->unused_classes; 701 to->gesture = classes->gesture; 702 if (!to->gesture) { 703 if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches)) 704 FatalError("[Xi] no memory for class shift.\n"); 705 } 706 else 707 classes->gesture = NULL; 708 } 709 710 to->gesture->sourceid = from->gesture->sourceid; 711 /* to->gesture->gesture is separate on the master, don't copy */ 712 } 713 /* Don't remove gesture class if from->gesture is non-existent. The to device 714 * may have an active gesture grab, so we need to keep the gesture class record 715 * around. */ 716 } 717 718 /** 719 * Copies the CONTENT of the classes of device from into the classes in device 720 * to. From and to are identical after finishing. 721 * 722 * If to does not have classes from currently has, the classes are stored in 723 * to's devPrivates system. Later, we recover it again from there if needed. 724 * Saves a few memory allocations. 725 */ 726 void 727 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, 728 DeviceChangedEvent *dce) 729 { 730 input_lock(); 731 732 /* generic feedback classes, not tied to pointer and/or keyboard */ 733 DeepCopyFeedbackClasses(from, to); 734 735 if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT)) 736 DeepCopyKeyboardClasses(from, to); 737 if ((dce->flags & DEVCHANGE_POINTER_EVENT)) 738 DeepCopyPointerClasses(from, to); 739 740 input_unlock(); 741 } 742 743 /** 744 * Send an XI2 DeviceChangedEvent to all interested clients. 745 */ 746 void 747 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce) 748 { 749 xXIDeviceChangedEvent *dcce; 750 int rc; 751 752 rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce); 753 if (rc != Success) { 754 ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc); 755 return; 756 } 757 758 /* we don't actually swap if there's a NullClient, swapping is done 759 * later when event is delivered. */ 760 SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1); 761 free(dcce); 762 } 763 764 static void 765 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) 766 { 767 DeviceIntPtr slave; 768 int rc; 769 770 /* For now, we don't have devices that change physically. */ 771 if (!IsMaster(device)) 772 return; 773 774 rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess); 775 776 if (rc != Success) 777 return; /* Device has disappeared */ 778 779 if (IsMaster(slave)) 780 return; 781 782 if (IsFloating(slave)) 783 return; /* set floating since the event */ 784 785 if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid) 786 return; /* not our slave anymore, don't care */ 787 788 /* FIXME: we probably need to send a DCE for the new slave now */ 789 790 device->public.devicePrivate = slave->public.devicePrivate; 791 792 /* FIXME: the classes may have changed since we generated the event. */ 793 DeepCopyDeviceClasses(slave, device, dce); 794 dce->deviceid = device->id; 795 XISendDeviceChangedEvent(device, dce); 796 } 797 798 /** 799 * Add state and motionMask to the filter for this event. The protocol 800 * supports some extra masks for motion when a button is down: 801 * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at 802 * least one button (or that specific button is down). These masks need to 803 * be added to the filters for core/XI motion events. 804 * 805 * @param device The device to update the mask for 806 * @param state The current button state mask 807 * @param motion_mask The motion mask (DeviceButtonMotionMask or 0) 808 */ 809 static void 810 UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state, 811 Mask motion_mask) 812 { 813 Mask mask; 814 815 mask = PointerMotionMask | state | motion_mask; 816 SetMaskForEvent(device->id, mask, DeviceMotionNotify); 817 SetMaskForEvent(device->id, mask, MotionNotify); 818 } 819 820 static void 821 IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down, 822 Mask *motion_mask, unsigned short *state) 823 { 824 if (dev->valuator) 825 dev->valuator->motionHintWindow = NullWindow; 826 827 (*buttons_down)++; 828 *motion_mask = DeviceButtonMotionMask; 829 if (dev->button->map[key] <= 5) 830 *state |= (Button1Mask >> 1) << dev->button->map[key]; 831 } 832 833 static void 834 DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down, 835 Mask *motion_mask, unsigned short *state) 836 { 837 if (dev->valuator) 838 dev->valuator->motionHintWindow = NullWindow; 839 840 if (*buttons_down >= 1 && !--(*buttons_down)) 841 *motion_mask = 0; 842 if (dev->button->map[key] <= 5) 843 *state &= ~((Button1Mask >> 1) << dev->button->map[key]); 844 } 845 846 /** 847 * Update the device state according to the data in the event. 848 * 849 * return values are 850 * DEFAULT ... process as normal 851 * DONT_PROCESS ... return immediately from caller 852 */ 853 #define DEFAULT 0 854 #define DONT_PROCESS 1 855 int 856 UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event) 857 { 858 int i; 859 int key = 0, last_valuator; 860 861 KeyClassPtr k = NULL; 862 ButtonClassPtr b = NULL; 863 ValuatorClassPtr v = NULL; 864 TouchClassPtr t = NULL; 865 866 /* This event is always the first we get, before the actual events with 867 * the data. However, the way how the DDX is set up, "device" will 868 * actually be the slave device that caused the event. 869 */ 870 switch (event->type) { 871 case ET_DeviceChanged: 872 ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event); 873 return DONT_PROCESS; /* event has been sent already */ 874 case ET_Motion: 875 case ET_ButtonPress: 876 case ET_ButtonRelease: 877 case ET_KeyPress: 878 case ET_KeyRelease: 879 case ET_ProximityIn: 880 case ET_ProximityOut: 881 case ET_TouchBegin: 882 case ET_TouchUpdate: 883 case ET_TouchEnd: 884 break; 885 default: 886 /* other events don't update the device */ 887 return DEFAULT; 888 } 889 890 k = device->key; 891 v = device->valuator; 892 b = device->button; 893 t = device->touch; 894 895 key = event->detail.key; 896 897 /* Update device axis */ 898 /* Check valuators first */ 899 last_valuator = -1; 900 for (i = 0; i < MAX_VALUATORS; i++) { 901 if (BitIsOn(&event->valuators.mask, i)) { 902 if (!v) { 903 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " 904 "Ignoring event.\n", device->name); 905 return DONT_PROCESS; 906 } 907 else if (v->numAxes < i) { 908 ErrorF("[Xi] Too many valuators reported for device '%s'. " 909 "Ignoring event.\n", device->name); 910 return DONT_PROCESS; 911 } 912 last_valuator = i; 913 } 914 } 915 916 for (i = 0; i <= last_valuator && i < v->numAxes; i++) { 917 /* XXX: Relative/Absolute mode */ 918 if (BitIsOn(&event->valuators.mask, i)) 919 v->axisVal[i] = event->valuators.data[i]; 920 } 921 922 if (event->type == ET_KeyPress) { 923 if (!k) 924 return DONT_PROCESS; 925 926 /* don't allow ddx to generate multiple downs, but repeats are okay */ 927 if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat) 928 return DONT_PROCESS; 929 930 if (device->valuator) 931 device->valuator->motionHintWindow = NullWindow; 932 set_key_down(device, key, KEY_PROCESSED); 933 } 934 else if (event->type == ET_KeyRelease) { 935 if (!k) 936 return DONT_PROCESS; 937 938 if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */ 939 return DONT_PROCESS; 940 if (device->valuator) 941 device->valuator->motionHintWindow = NullWindow; 942 set_key_up(device, key, KEY_PROCESSED); 943 } 944 else if (event->type == ET_ButtonPress) { 945 if (!b) 946 return DONT_PROCESS; 947 948 if (button_is_down(device, key, BUTTON_PROCESSED)) 949 return DONT_PROCESS; 950 951 set_button_down(device, key, BUTTON_PROCESSED); 952 953 if (!b->map[key]) 954 return DONT_PROCESS; 955 956 IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, 957 &b->state); 958 UpdateDeviceMotionMask(device, b->state, b->motionMask); 959 } 960 else if (event->type == ET_ButtonRelease) { 961 if (!b) 962 return DONT_PROCESS; 963 964 if (!button_is_down(device, key, BUTTON_PROCESSED)) 965 return DONT_PROCESS; 966 if (IsMaster(device)) { 967 DeviceIntPtr sd; 968 969 /* 970 * Leave the button down if any slave has the 971 * button still down. Note that this depends on the 972 * event being delivered through the slave first 973 */ 974 for (sd = inputInfo.devices; sd; sd = sd->next) { 975 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device) 976 continue; 977 if (!sd->button) 978 continue; 979 for (i = 1; i <= sd->button->numButtons; i++) 980 if (sd->button->map[i] == key && 981 button_is_down(sd, i, BUTTON_PROCESSED)) 982 return DONT_PROCESS; 983 } 984 } 985 set_button_up(device, key, BUTTON_PROCESSED); 986 if (!b->map[key]) 987 return DONT_PROCESS; 988 989 DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, 990 &b->state); 991 UpdateDeviceMotionMask(device, b->state, b->motionMask); 992 } 993 else if (event->type == ET_ProximityIn) 994 device->proximity->in_proximity = TRUE; 995 else if (event->type == ET_ProximityOut) 996 device->proximity->in_proximity = FALSE; 997 else if (event->type == ET_TouchBegin) { 998 BUG_RETURN_VAL(!b || !v, DONT_PROCESS); 999 BUG_RETURN_VAL(!t, DONT_PROCESS); 1000 1001 if (!b->map[key]) 1002 return DONT_PROCESS; 1003 1004 if (!(event->flags & TOUCH_POINTER_EMULATED) || 1005 (event->flags & TOUCH_REPLAYING)) 1006 return DONT_PROCESS; 1007 1008 IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, 1009 &t->state); 1010 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask); 1011 } 1012 else if (event->type == ET_TouchEnd) { 1013 BUG_RETURN_VAL(!b || !v, DONT_PROCESS); 1014 BUG_RETURN_VAL(!t, DONT_PROCESS); 1015 1016 if (t->buttonsDown <= 0 || !b->map[key]) 1017 return DONT_PROCESS; 1018 1019 if (!(event->flags & TOUCH_POINTER_EMULATED)) 1020 return DONT_PROCESS; 1021 1022 DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, 1023 &t->state); 1024 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask); 1025 } 1026 1027 return DEFAULT; 1028 } 1029 1030 /** 1031 * A client that does not have the TouchOwnership mask set may not receive a 1032 * TouchBegin event if there is at least one grab active. 1033 * 1034 * @return TRUE if the client selected for ownership events on the given 1035 * window for this device, FALSE otherwise 1036 */ 1037 static inline Bool 1038 TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, 1039 WindowPtr win) 1040 { 1041 InputClients *iclient; 1042 1043 nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) { 1044 if (rClient(iclient) != client) 1045 continue; 1046 1047 return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership); 1048 } 1049 1050 return FALSE; 1051 } 1052 1053 static void 1054 TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, 1055 XID resource) 1056 { 1057 int nev, i; 1058 InternalEvent *tel = InitEventList(GetMaximumEventsNum()); 1059 1060 nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0); 1061 for (i = 0; i < nev; i++) 1062 mieqProcessDeviceEvent(dev, tel + i, NULL); 1063 1064 FreeEventList(tel, GetMaximumEventsNum()); 1065 } 1066 1067 /** 1068 * Attempts to deliver a touch event to the given client. 1069 */ 1070 static Bool 1071 DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, 1072 GrabPtr grab, WindowPtr win, InternalEvent *ev) 1073 { 1074 int err; 1075 xEvent *xi2; 1076 Mask filter; 1077 Window child = DeepestSpriteWin(&ti->sprite)->drawable.id; 1078 1079 /* FIXME: owner event handling */ 1080 1081 /* If the client does not have the ownership mask set and is not 1082 * the current owner of the touch, only pretend we delivered */ 1083 if (!grab && ti->num_grabs != 0 && 1084 !TouchClientWantsOwnershipEvents(client, dev, win)) 1085 return TRUE; 1086 1087 /* If we fail here, we're going to leave a client hanging. */ 1088 err = EventToXI2(ev, &xi2); 1089 if (err != Success) 1090 FatalError("[Xi] %s: XI2 conversion failed in %s" 1091 " (%d)\n", dev->name, __func__, err); 1092 1093 FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE); 1094 filter = GetEventFilter(dev, xi2); 1095 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) 1096 return FALSE; 1097 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); 1098 free(xi2); 1099 1100 /* Returning the value from TryClientEvents isn't useful, since all our 1101 * resource-gone cleanups will update the delivery list anyway. */ 1102 return TRUE; 1103 } 1104 1105 static void 1106 ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) 1107 { 1108 ClientPtr client; 1109 XID error; 1110 GrabPtr grab = ti->listeners[0].grab; 1111 1112 BUG_RETURN(ti->listeners[0].type != TOUCH_LISTENER_GRAB && 1113 ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB); 1114 BUG_RETURN(!grab); 1115 1116 client = rClient(grab); 1117 1118 if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id, 1119 ti->listeners[0].window->drawable.id, &error) != Success) 1120 ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n"); 1121 } 1122 1123 /** 1124 * Find the oldest touch that still has a pointer emulation client. 1125 * 1126 * Pointer emulation can only be performed for the oldest touch. Otherwise, the 1127 * order of events seen by the client will be wrong. This function helps us find 1128 * the next touch to be emulated. 1129 * 1130 * @param dev The device to find touches for. 1131 */ 1132 static TouchPointInfoPtr 1133 FindOldestPointerEmulatedTouch(DeviceIntPtr dev) 1134 { 1135 TouchPointInfoPtr oldest = NULL; 1136 int i; 1137 1138 for (i = 0; i < dev->touch->num_touches; i++) { 1139 TouchPointInfoPtr ti = dev->touch->touches + i; 1140 int j; 1141 1142 if (!ti->active || !ti->emulate_pointer) 1143 continue; 1144 1145 for (j = 0; j < ti->num_listeners; j++) { 1146 if (ti->listeners[j].type == TOUCH_LISTENER_POINTER_GRAB || 1147 ti->listeners[j].type == TOUCH_LISTENER_POINTER_REGULAR) 1148 break; 1149 } 1150 if (j == ti->num_listeners) 1151 continue; 1152 1153 if (!oldest) { 1154 oldest = ti; 1155 continue; 1156 } 1157 1158 if (oldest->client_id - ti->client_id < UINT_MAX / 2) 1159 oldest = ti; 1160 } 1161 1162 return oldest; 1163 } 1164 1165 /** 1166 * If the current owner has rejected the event, deliver the 1167 * TouchOwnership/TouchBegin to the next item in the sprite stack. 1168 */ 1169 static void 1170 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, 1171 TouchOwnershipEvent *ev) 1172 { 1173 TouchListener *listener = &ti->listeners[0]; /* new owner */ 1174 int accepted_early = listener->state == TOUCH_LISTENER_EARLY_ACCEPT; 1175 1176 /* Deliver the ownership */ 1177 if (listener->state == TOUCH_LISTENER_AWAITING_OWNER || accepted_early) 1178 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 1179 listener->listener); 1180 else if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) { 1181 /* We can't punt to a pointer listener unless all older pointer 1182 * emulated touches have been seen already. */ 1183 if ((listener->type == TOUCH_LISTENER_POINTER_GRAB || 1184 listener->type == TOUCH_LISTENER_POINTER_REGULAR) && 1185 ti != FindOldestPointerEmulatedTouch(dev)) 1186 return; 1187 1188 TouchEventHistoryReplay(ti, dev, listener->listener); 1189 } 1190 1191 /* New owner has Begin/Update but not end. If touch is pending_finish, 1192 * emulate the TouchEnd now */ 1193 if (ti->pending_finish) { 1194 TouchEmitTouchEnd(dev, ti, 0, 0); 1195 1196 /* If the last owner is not a touch grab, finalise the touch, we 1197 won't get more correspondence on this. 1198 */ 1199 if (ti->num_listeners == 1 && 1200 (ti->num_grabs == 0 || 1201 listener->grab->grabtype != XI2 || 1202 !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) { 1203 TouchEndTouch(dev, ti); 1204 return; 1205 } 1206 } 1207 1208 if (accepted_early) 1209 ActivateEarlyAccept(dev, ti); 1210 } 1211 1212 /** 1213 * Check the oldest touch to see if it needs to be replayed to its pointer 1214 * owner. 1215 * 1216 * Touch event propagation is paused if it hits a pointer listener while an 1217 * older touch with a pointer listener is waiting on accept or reject. This 1218 * function will restart propagation of a paused touch if needed. 1219 * 1220 * @param dev The device to check touches for. 1221 */ 1222 static void 1223 CheckOldestTouch(DeviceIntPtr dev) 1224 { 1225 TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev); 1226 1227 if (oldest && oldest->listeners[0].state == TOUCH_LISTENER_AWAITING_BEGIN) 1228 TouchPuntToNextOwner(dev, oldest, NULL); 1229 } 1230 1231 /** 1232 * Process a touch rejection. 1233 * 1234 * @param sourcedev The source device of the touch sequence. 1235 * @param ti The touchpoint info record. 1236 * @param resource The resource of the client rejecting the touch. 1237 * @param ev TouchOwnership event to send. Set to NULL if no event should be 1238 * sent. 1239 */ 1240 void 1241 TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, 1242 TouchOwnershipEvent *ev) 1243 { 1244 Bool was_owner = (resource == ti->listeners[0].listener); 1245 int i; 1246 1247 /* Send a TouchEnd event to the resource being removed, but only if they 1248 * haven't received one yet already */ 1249 for (i = 0; i < ti->num_listeners; i++) { 1250 if (ti->listeners[i].listener == resource) { 1251 if (ti->listeners[i].state != TOUCH_LISTENER_HAS_END) 1252 TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); 1253 break; 1254 } 1255 } 1256 1257 /* Remove the resource from the listener list, updating 1258 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */ 1259 TouchRemoveListener(ti, resource); 1260 1261 /* If the current owner was removed and there are further listeners, deliver 1262 * the TouchOwnership or TouchBegin event to the new owner. */ 1263 if (ev && ti->num_listeners > 0 && was_owner) 1264 TouchPuntToNextOwner(sourcedev, ti, ev); 1265 else if (ti->num_listeners == 0) 1266 TouchEndTouch(sourcedev, ti); 1267 1268 CheckOldestTouch(sourcedev); 1269 } 1270 1271 /** 1272 * Processes a TouchOwnership event, indicating a grab has accepted the touch 1273 * it currently owns, or a grab or selection has been removed. Will generate 1274 * and send TouchEnd events to all clients removed from the delivery list, as 1275 * well as possibly sending the new TouchOwnership event. May end the 1276 * touchpoint if it is pending finish. 1277 */ 1278 static void 1279 ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev, 1280 DeviceIntPtr dev) 1281 { 1282 TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid); 1283 1284 if (!ti) { 1285 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 1286 dev->name, ev->type, ev->touchid); 1287 return; 1288 } 1289 1290 if (ev->reason == XIRejectTouch) 1291 TouchRejected(dev, ti, ev->resource, ev); 1292 else if (ev->reason == XIAcceptTouch) { 1293 int i; 1294 1295 1296 /* For pointer-emulated listeners that ungrabbed the active grab, 1297 * the state was forced to TOUCH_LISTENER_HAS_END. Still go 1298 * through the motions of ending the touch if the listener has 1299 * already seen the end. This ensures that the touch record is ended in 1300 * the server. 1301 */ 1302 if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END) 1303 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); 1304 1305 /* The touch owner has accepted the touch. Send TouchEnd events to 1306 * everyone else, and truncate the list of listeners. */ 1307 for (i = 1; i < ti->num_listeners; i++) 1308 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener); 1309 1310 while (ti->num_listeners > 1) 1311 TouchRemoveListener(ti, ti->listeners[1].listener); 1312 /* Owner accepted after receiving end */ 1313 if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END) 1314 TouchEndTouch(dev, ti); 1315 else 1316 ti->listeners[0].state = TOUCH_LISTENER_HAS_ACCEPTED; 1317 } 1318 else { /* this is the very first ownership event for a grab */ 1319 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource); 1320 } 1321 } 1322 1323 /** 1324 * Copy the event's valuator information into the touchpoint, we may need 1325 * this for emulated TouchEnd events. 1326 */ 1327 static void 1328 TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti) 1329 { 1330 int i; 1331 1332 for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++) 1333 if (BitIsOn(ev->valuators.mask, i)) 1334 valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]); 1335 } 1336 1337 /** 1338 * Given a touch event and a potential listener, retrieve info needed for 1339 * processing the event. 1340 * 1341 * @param dev The device generating the touch event. 1342 * @param ti The touch point info record for the touch event. 1343 * @param ev The touch event to process. 1344 * @param listener The touch event listener that may receive the touch event. 1345 * @param[out] client The client that should receive the touch event. 1346 * @param[out] win The window to deliver the event on. 1347 * @param[out] grab The grab to deliver the event through, if any. 1348 * @param[out] mask The XI 2.x event mask of the grab or selection, if any. 1349 * @return TRUE if an event should be delivered to the listener, FALSE 1350 * otherwise. 1351 */ 1352 static Bool 1353 RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti, 1354 InternalEvent *ev, TouchListener * listener, 1355 ClientPtr *client, WindowPtr *win, GrabPtr *grab, 1356 XI2Mask **mask) 1357 { 1358 int rc; 1359 InputClients *iclients = NULL; 1360 *mask = NULL; 1361 1362 if (listener->type == TOUCH_LISTENER_GRAB || 1363 listener->type == TOUCH_LISTENER_POINTER_GRAB) { 1364 *grab = listener->grab; 1365 1366 BUG_RETURN_VAL(!*grab, FALSE); 1367 1368 *client = rClient(*grab); 1369 *win = (*grab)->window; 1370 *mask = (*grab)->xi2mask; 1371 } 1372 else { 1373 rc = dixLookupResourceByType((void **) win, listener->listener, 1374 listener->resource_type, 1375 serverClient, DixSendAccess); 1376 if (rc != Success) 1377 return FALSE; 1378 1379 if (listener->level == XI2) { 1380 int evtype; 1381 1382 if (ti->emulate_pointer && 1383 listener->type == TOUCH_LISTENER_POINTER_REGULAR) 1384 evtype = GetXI2Type(TouchGetPointerEventType(ev)); 1385 else 1386 evtype = GetXI2Type(ev->any.type); 1387 1388 BUG_RETURN_VAL(!wOtherInputMasks(*win), FALSE); 1389 nt_list_for_each_entry(iclients, 1390 wOtherInputMasks(*win)->inputClients, next) 1391 if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 1392 break; 1393 1394 BUG_RETURN_VAL(!iclients, FALSE); 1395 1396 *mask = iclients->xi2mask; 1397 *client = rClient(iclients); 1398 } 1399 else if (listener->level == XI) { 1400 int xi_type = GetXIType(TouchGetPointerEventType(ev)); 1401 Mask xi_filter = event_get_filter_from_type(dev, xi_type); 1402 1403 BUG_RETURN_VAL(!wOtherInputMasks(*win), FALSE); 1404 nt_list_for_each_entry(iclients, 1405 wOtherInputMasks(*win)->inputClients, next) 1406 if (iclients->mask[dev->id] & xi_filter) 1407 break; 1408 BUG_RETURN_VAL(!iclients, FALSE); 1409 1410 *client = rClient(iclients); 1411 } 1412 else { 1413 int coretype = GetCoreType(TouchGetPointerEventType(ev)); 1414 Mask core_filter = event_get_filter_from_type(dev, coretype); 1415 OtherClients *oclients; 1416 1417 /* all others */ 1418 nt_list_for_each_entry(oclients, 1419 (OtherClients *) wOtherClients(*win), next) 1420 if (oclients->mask & core_filter) 1421 break; 1422 1423 /* if owner selected, oclients is NULL */ 1424 *client = oclients ? rClient(oclients) : wClient(*win); 1425 } 1426 1427 *grab = NULL; 1428 } 1429 1430 return TRUE; 1431 } 1432 1433 static int 1434 DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1435 InternalEvent *ev, TouchListener * listener, 1436 ClientPtr client, WindowPtr win, GrabPtr grab, 1437 XI2Mask *xi2mask) 1438 { 1439 InternalEvent motion, button; 1440 InternalEvent *ptrev = &motion; 1441 int nevents; 1442 DeviceIntPtr kbd; 1443 1444 /* There may be a pointer grab on the device */ 1445 if (!grab) { 1446 grab = dev->deviceGrab.grab; 1447 if (grab) { 1448 win = grab->window; 1449 xi2mask = grab->xi2mask; 1450 client = rClient(grab); 1451 } 1452 } 1453 1454 /* We don't deliver pointer events to non-owners */ 1455 if (!TouchResourceIsOwner(ti, listener->listener)) 1456 return !Success; 1457 1458 if (!ti->emulate_pointer) 1459 return !Success; 1460 1461 nevents = TouchConvertToPointerEvent(ev, &motion, &button); 1462 BUG_RETURN_VAL(nevents == 0, BadValue); 1463 1464 /* Note that here we deliver only part of the events that are generated by the touch event: 1465 * 1466 * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent) 1467 * TouchUpdate results in Motion 1468 * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent) 1469 */ 1470 if (nevents > 1) 1471 ptrev = &button; 1472 1473 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1474 event_set_state(dev, kbd, &ptrev->device_event); 1475 ptrev->device_event.corestate = event_get_corestate(dev, kbd); 1476 1477 if (grab) { 1478 /* this side-steps the usual activation mechanisms, but... */ 1479 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) 1480 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */ 1481 else { 1482 int deliveries = 0; 1483 1484 /* 'grab' is the passive grab, but if the grab isn't active, 1485 * don't deliver */ 1486 if (!dev->deviceGrab.grab) 1487 return !Success; 1488 1489 if (grab->ownerEvents) { 1490 WindowPtr focus = NullWindow; 1491 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1492 1493 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev); 1494 } 1495 1496 if (!deliveries) 1497 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); 1498 1499 /* We must accept the touch sequence once a pointer listener has 1500 * received one event past ButtonPress. */ 1501 if (deliveries && ev->any.type != ET_TouchBegin && 1502 !(ev->device_event.flags & TOUCH_CLIENT_ID)) 1503 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1504 1505 if (ev->any.type == ET_TouchEnd && 1506 ti->num_listeners == 1 && 1507 !dev->button->buttonsDown && 1508 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { 1509 (*dev->deviceGrab.DeactivateGrab) (dev); 1510 CheckOldestTouch(dev); 1511 return Success; 1512 } 1513 } 1514 } 1515 else { 1516 GrabPtr devgrab = dev->deviceGrab.grab; 1517 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1518 1519 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev); 1520 /* FIXME: bad hack 1521 * Implicit passive grab activated in response to this event. Store 1522 * the event. 1523 */ 1524 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { 1525 TouchListener *l; 1526 GrabPtr g; 1527 1528 devgrab = dev->deviceGrab.grab; 1529 g = AllocGrab(devgrab); 1530 BUG_WARN(!g); 1531 1532 CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev); 1533 1534 /* The listener array has a sequence of grabs and then one event 1535 * selection. Implicit grab activation occurs through delivering an 1536 * event selection. Thus, we update the last listener in the array. 1537 */ 1538 l = &ti->listeners[ti->num_listeners - 1]; 1539 l->listener = g->resource; 1540 l->grab = g; 1541 //l->resource_type = RT_NONE; 1542 1543 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) 1544 l->type = TOUCH_LISTENER_POINTER_GRAB; 1545 else 1546 l->type = TOUCH_LISTENER_GRAB; 1547 } 1548 1549 } 1550 if (ev->any.type == ET_TouchBegin) 1551 listener->state = TOUCH_LISTENER_IS_OWNER; 1552 else if (ev->any.type == ET_TouchEnd) 1553 listener->state = TOUCH_LISTENER_HAS_END; 1554 1555 return Success; 1556 } 1557 1558 static void 1559 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1560 InternalEvent *ev) 1561 { 1562 DeviceEvent motion; 1563 1564 if (ti->num_listeners) { 1565 ClientPtr client; 1566 WindowPtr win; 1567 GrabPtr grab; 1568 XI2Mask *mask; 1569 1570 if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR && 1571 ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB) 1572 return; 1573 1574 motion = ev->device_event; 1575 motion.type = ET_TouchUpdate; 1576 motion.detail.button = 0; 1577 1578 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion, 1579 &ti->listeners[0], &client, &win, &grab, 1580 &mask)) 1581 return; 1582 1583 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client, 1584 win, grab, mask); 1585 } 1586 else { 1587 InternalEvent button; 1588 int converted; 1589 1590 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button); 1591 1592 BUG_WARN(converted == 0); 1593 if (converted) 1594 ProcessOtherEvent((InternalEvent*)&motion, dev); 1595 } 1596 } 1597 1598 /** 1599 * Processes and delivers a TouchBegin, TouchUpdate, or a 1600 * TouchEnd event. 1601 * 1602 * Due to having rather different delivery semantics (see the Xi 2.2 protocol 1603 * spec for more information), this implements its own grab and event-selection 1604 * delivery logic. 1605 */ 1606 static void 1607 ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) 1608 { 1609 TouchClassPtr t = dev->touch; 1610 TouchPointInfoPtr ti; 1611 uint32_t touchid; 1612 int type = ev->any.type; 1613 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED); 1614 DeviceIntPtr kbd; 1615 1616 if (!t) 1617 return; 1618 1619 touchid = ev->device_event.touchid; 1620 1621 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) { 1622 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1623 emulate_pointer); 1624 } 1625 else 1626 ti = TouchFindByClientID(dev, touchid); 1627 1628 /* Active pointer grab */ 1629 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && 1630 (dev->deviceGrab.grab->grabtype == CORE || 1631 dev->deviceGrab.grab->grabtype == XI || 1632 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) 1633 { 1634 /* Active pointer grab on touch point and we get a TouchEnd - claim this 1635 * touchpoint accepted, otherwise clients waiting for ownership will 1636 * wait on this touchpoint until this client ungrabs, or the cows come 1637 * home, whichever is earlier */ 1638 if (ti && type == ET_TouchEnd) 1639 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1640 else if (!ti && type != ET_TouchBegin) { 1641 /* Under the following circumstances we create a new touch record for an 1642 * existing touch: 1643 * 1644 * - The touch may be pointer emulated 1645 * - An explicit grab is active on the device 1646 * - The grab is a pointer grab 1647 * 1648 * This allows for an explicit grab to receive pointer events for an already 1649 * active touch. 1650 */ 1651 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1652 emulate_pointer); 1653 if (!ti) { 1654 DebugF("[Xi] %s: Failed to create new dix record for explicitly " 1655 "grabbed touchpoint %d\n", 1656 dev->name, touchid); 1657 return; 1658 } 1659 1660 TouchBuildSprite(dev, ti, ev); 1661 TouchSetupListeners(dev, ti, ev); 1662 } 1663 } 1664 1665 if (!ti) { 1666 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 1667 dev->name, type, touchid); 1668 goto out; 1669 } 1670 1671 /* if emulate_pointer is set, emulate the motion event right 1672 * here, so we can ignore it for button event emulation. TouchUpdate 1673 * events which _only_ emulate motion just work normally */ 1674 if (emulate_pointer && (ev->any.type == ET_TouchBegin || 1675 (ev->any.type == ET_TouchEnd && ti->num_listeners > 0))) 1676 DeliverEmulatedMotionEvent(dev, ti, ev); 1677 1678 if (emulate_pointer && IsMaster(dev)) 1679 CheckMotion(&ev->device_event, dev); 1680 1681 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1682 event_set_state(NULL, kbd, &ev->device_event); 1683 ev->device_event.corestate = event_get_corestate(NULL, kbd); 1684 1685 /* Make sure we have a valid window trace for event delivery; must be 1686 * called after event type mutation. Touch end events are always processed 1687 * in order to end touch records. */ 1688 /* FIXME: check this */ 1689 if ((type == ET_TouchBegin && 1690 !(ev->device_event.flags & TOUCH_REPLAYING) && 1691 !TouchBuildSprite(dev, ti, ev)) || 1692 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) 1693 return; 1694 1695 TouchCopyValuatorData(&ev->device_event, ti); 1696 /* WARNING: the event type may change to TouchUpdate in 1697 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing 1698 * owner */ 1699 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource); 1700 if (ev->any.type == ET_TouchEnd) 1701 TouchEndTouch(dev, ti); 1702 1703 out: 1704 if (emulate_pointer) 1705 UpdateDeviceState(dev, &ev->device_event); 1706 } 1707 1708 static void 1709 ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev) 1710 { 1711 Mask filter; 1712 WindowPtr pWin; 1713 BarrierEvent *be = &e->barrier_event; 1714 xEvent *ev; 1715 int rc; 1716 GrabPtr grab = dev->deviceGrab.grab; 1717 1718 if (!IsMaster(dev)) 1719 return; 1720 1721 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success) 1722 return; 1723 1724 if (grab) 1725 be->flags |= XIBarrierDeviceIsGrabbed; 1726 1727 rc = EventToXI2(e, &ev); 1728 if (rc != Success) { 1729 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc); 1730 return; 1731 } 1732 1733 /* A client has a grab, deliver to this client if the grab_window is the 1734 barrier window. 1735 1736 Otherwise, deliver normally to the client. 1737 */ 1738 if (grab && 1739 CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) && 1740 grab->window->drawable.id == be->window) { 1741 DeliverGrabbedEvent(e, dev, FALSE); 1742 } else { 1743 filter = GetEventFilter(dev, ev); 1744 1745 DeliverEventsToWindow(dev, pWin, ev, 1, 1746 filter, NullGrab); 1747 } 1748 free(ev); 1749 } 1750 1751 static BOOL 1752 IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev) 1753 { 1754 GestureClassPtr g = dev->gesture; 1755 if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) { 1756 return TRUE; 1757 } 1758 return FALSE; 1759 } 1760 1761 /** 1762 * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}. 1763 * 1764 * Due to having rather different delivery semantics (see the Xi 2.4 protocol 1765 * spec for more information), this implements its own grab and event-selection 1766 * delivery logic. 1767 */ 1768 void 1769 ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev) 1770 { 1771 GestureInfoPtr gi; 1772 DeviceIntPtr kbd; 1773 Bool deactivateGestureGrab = FALSE; 1774 Bool delivered = FALSE; 1775 1776 if (!dev->gesture) 1777 return; 1778 1779 if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev)) 1780 return; 1781 1782 if (IsGestureBeginEvent(ev)) 1783 gi = GestureBeginGesture(dev, ev); 1784 else 1785 gi = GestureFindActiveByEventType(dev, ev->any.type); 1786 1787 if (!gi) { 1788 /* This may happen if gesture is no longer active or was never started. */ 1789 return; 1790 } 1791 1792 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1793 event_set_state_gesture(kbd, &ev->gesture_event); 1794 1795 if (IsGestureBeginEvent(ev)) 1796 GestureSetupListener(dev, gi, ev); 1797 1798 if (IsGestureEndEvent(ev) && 1799 dev->deviceGrab.grab && 1800 dev->deviceGrab.fromPassiveGrab && 1801 GrabIsGestureGrab(dev->deviceGrab.grab)) 1802 deactivateGestureGrab = TRUE; 1803 1804 delivered = DeliverGestureEventToOwner(dev, gi, ev); 1805 1806 if (delivered && !deactivateGestureGrab && 1807 (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev))) 1808 FreezeThisEventIfNeededForSyncGrab(dev, ev); 1809 1810 if (IsGestureEndEvent(ev)) 1811 GestureEndGesture(gi); 1812 1813 if (deactivateGestureGrab) 1814 (*dev->deviceGrab.DeactivateGrab) (dev); 1815 } 1816 1817 /** 1818 * Process DeviceEvents and DeviceChangedEvents. 1819 */ 1820 static void 1821 ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device) 1822 { 1823 GrabPtr grab; 1824 Bool deactivateDeviceGrab = FALSE; 1825 int key = 0, rootX, rootY; 1826 ButtonClassPtr b; 1827 int ret = 0; 1828 int corestate; 1829 DeviceIntPtr mouse = NULL, kbd = NULL; 1830 DeviceEvent *event = &ev->device_event; 1831 1832 if (IsPointerDevice(device)) { 1833 kbd = GetMaster(device, KEYBOARD_OR_FLOAT); 1834 mouse = device; 1835 if (!kbd->key) /* can happen with floating SDs */ 1836 kbd = NULL; 1837 } 1838 else { 1839 mouse = GetMaster(device, POINTER_OR_FLOAT); 1840 kbd = device; 1841 if (!mouse->valuator || !mouse->button) /* may be float. SDs */ 1842 mouse = NULL; 1843 } 1844 1845 corestate = event_get_corestate(mouse, kbd); 1846 event_set_state(mouse, kbd, event); 1847 1848 ret = UpdateDeviceState(device, event); 1849 if (ret == DONT_PROCESS) 1850 return; 1851 1852 b = device->button; 1853 1854 if (IsMaster(device) || IsFloating(device)) 1855 CheckMotion(event, device); 1856 1857 switch (event->type) { 1858 case ET_Motion: 1859 case ET_ButtonPress: 1860 case ET_ButtonRelease: 1861 case ET_KeyPress: 1862 case ET_KeyRelease: 1863 case ET_ProximityIn: 1864 case ET_ProximityOut: 1865 GetSpritePosition(device, &rootX, &rootY); 1866 event->root_x = rootX; 1867 event->root_y = rootY; 1868 NoticeEventTime((InternalEvent *) event, device); 1869 event->corestate = corestate; 1870 key = event->detail.key; 1871 break; 1872 default: 1873 break; 1874 } 1875 1876 /* send KeyPress and KeyRelease events to XACE plugins */ 1877 if (XaceHookIsSet(XACE_KEY_AVAIL) && 1878 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) { 1879 xEvent *core; 1880 int count; 1881 1882 if (EventToCore(ev, &core, &count) == Success && count > 0) { 1883 XaceHook(XACE_KEY_AVAIL, core, device, 0); 1884 free(core); 1885 } 1886 } 1887 1888 if (DeviceEventCallback && !syncEvents.playingEvents) { 1889 DeviceEventInfoRec eventinfo; 1890 SpritePtr pSprite = device->spriteInfo->sprite; 1891 1892 /* see comment in EnqueueEvents regarding the next three lines */ 1893 if (ev->any.type == ET_Motion) 1894 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 1895 1896 eventinfo.device = device; 1897 eventinfo.event = ev; 1898 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 1899 } 1900 1901 grab = device->deviceGrab.grab; 1902 1903 switch (event->type) { 1904 case ET_KeyPress: 1905 /* Don't deliver focus events (e.g. from KeymapNotify when running 1906 * nested) to clients. */ 1907 if (event->source_type == EVENT_SOURCE_FOCUS) 1908 return; 1909 if (!grab && CheckDeviceGrabs(device, ev, 0)) 1910 return; 1911 break; 1912 case ET_KeyRelease: 1913 if (grab && device->deviceGrab.fromPassiveGrab && 1914 (key == device->deviceGrab.activatingKey) && 1915 GrabIsKeyboardGrab(device->deviceGrab.grab)) 1916 deactivateDeviceGrab = TRUE; 1917 break; 1918 case ET_ButtonPress: 1919 if (b->map[key] == 0) /* there's no button 0 */ 1920 return; 1921 event->detail.button = b->map[key]; 1922 if (!grab && CheckDeviceGrabs(device, ev, 0)) { 1923 /* if a passive grab was activated, the event has been sent 1924 * already */ 1925 return; 1926 } 1927 break; 1928 case ET_ButtonRelease: 1929 if (b->map[key] == 0) /* there's no button 0 */ 1930 return; 1931 event->detail.button = b->map[key]; 1932 if (grab && !b->buttonsDown && 1933 device->deviceGrab.fromPassiveGrab && 1934 GrabIsPointerGrab(device->deviceGrab.grab)) 1935 deactivateDeviceGrab = TRUE; 1936 default: 1937 break; 1938 } 1939 1940 /* Don't deliver focus events (e.g. from KeymapNotify when running 1941 * nested) to clients. */ 1942 if (event->source_type != EVENT_SOURCE_FOCUS) { 1943 if (grab) 1944 DeliverGrabbedEvent((InternalEvent *) event, device, 1945 deactivateDeviceGrab); 1946 else if (device->focus && !IsPointerEvent(ev)) 1947 DeliverFocusedEvent(device, (InternalEvent *) event, 1948 GetSpriteWindow(device)); 1949 else 1950 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event, 1951 NullGrab, NullWindow, device); 1952 } 1953 1954 if (deactivateDeviceGrab == TRUE) { 1955 (*device->deviceGrab.DeactivateGrab) (device); 1956 1957 if (!IsMaster (device) && !IsFloating (device)) { 1958 int flags, num_events = 0; 1959 InternalEvent dce; 1960 1961 flags = (IsPointerDevice (device)) ? 1962 DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT; 1963 UpdateFromMaster (&dce, device, flags, &num_events); 1964 BUG_WARN(num_events > 1); 1965 1966 if (num_events == 1) 1967 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED), 1968 &dce.changed_event); 1969 } 1970 1971 } 1972 1973 event->detail.key = key; 1974 } 1975 1976 /** 1977 * Main device event processing function. 1978 * Called from when processing the events from the event queue. 1979 * 1980 */ 1981 void 1982 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) 1983 { 1984 verify_internal_event(ev); 1985 1986 switch (ev->any.type) { 1987 case ET_RawKeyPress: 1988 case ET_RawKeyRelease: 1989 case ET_RawButtonPress: 1990 case ET_RawButtonRelease: 1991 case ET_RawMotion: 1992 case ET_RawTouchBegin: 1993 case ET_RawTouchUpdate: 1994 case ET_RawTouchEnd: 1995 DeliverRawEvent(&ev->raw_event, device); 1996 break; 1997 case ET_TouchBegin: 1998 case ET_TouchUpdate: 1999 case ET_TouchEnd: 2000 ProcessTouchEvent(ev, device); 2001 break; 2002 case ET_TouchOwnership: 2003 /* TouchOwnership events are handled separately from the rest, as they 2004 * have more complex semantics. */ 2005 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device); 2006 break; 2007 case ET_BarrierHit: 2008 case ET_BarrierLeave: 2009 ProcessBarrierEvent(ev, device); 2010 break; 2011 case ET_GesturePinchBegin: 2012 case ET_GesturePinchUpdate: 2013 case ET_GesturePinchEnd: 2014 case ET_GestureSwipeBegin: 2015 case ET_GestureSwipeUpdate: 2016 case ET_GestureSwipeEnd: 2017 ProcessGestureEvent(ev, device); 2018 break; 2019 default: 2020 ProcessDeviceEvent(ev, device); 2021 break; 2022 } 2023 } 2024 2025 static int 2026 DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 2027 InternalEvent *ev, TouchListener * listener, 2028 ClientPtr client, WindowPtr win, GrabPtr grab, 2029 XI2Mask *xi2mask) 2030 { 2031 enum TouchListenerState state; 2032 int rc = Success; 2033 Bool has_ownershipmask; 2034 2035 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2036 listener->type == TOUCH_LISTENER_POINTER_GRAB) { 2037 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 2038 grab, xi2mask); 2039 if (rc == Success) { 2040 listener->state = TOUCH_LISTENER_IS_OWNER; 2041 /* async grabs cannot replay, so automatically accept this touch */ 2042 if (listener->type == TOUCH_LISTENER_POINTER_GRAB && 2043 dev->deviceGrab.grab && 2044 dev->deviceGrab.fromPassiveGrab && 2045 dev->deviceGrab.grab->pointerMode == GrabModeAsync) 2046 ActivateEarlyAccept(dev, ti); 2047 } 2048 goto out; 2049 } 2050 2051 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 2052 2053 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask) 2054 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2055 if (!TouchResourceIsOwner(ti, listener->listener)) { 2056 if (has_ownershipmask) 2057 state = TOUCH_LISTENER_AWAITING_OWNER; 2058 else 2059 state = TOUCH_LISTENER_AWAITING_BEGIN; 2060 } 2061 else { 2062 if (has_ownershipmask) 2063 TouchSendOwnershipEvent(dev, ti, 0, listener->listener); 2064 2065 if (listener->type == TOUCH_LISTENER_REGULAR) 2066 state = TOUCH_LISTENER_HAS_ACCEPTED; 2067 else 2068 state = TOUCH_LISTENER_IS_OWNER; 2069 } 2070 listener->state = state; 2071 2072 out: 2073 return rc; 2074 } 2075 2076 static int 2077 DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 2078 TouchListener * listener, ClientPtr client, 2079 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 2080 { 2081 int rc = Success; 2082 2083 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2084 listener->type == TOUCH_LISTENER_POINTER_GRAB) { 2085 /* Note: If the active grab was ungrabbed, we already changed the 2086 * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't 2087 * actually send the event. 2088 * This is part two of the hack in DeactivatePointerGrab 2089 */ 2090 if (listener->state != TOUCH_LISTENER_HAS_END) { 2091 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 2092 grab, xi2mask); 2093 2094 /* Once we send a TouchEnd to a legacy listener, we're already well 2095 * past the accepting/rejecting stage (can only happen on 2096 * GrabModeSync + replay. This listener now gets the end event, 2097 * and we can continue. 2098 */ 2099 if (rc == Success) 2100 listener->state = TOUCH_LISTENER_HAS_END; 2101 } 2102 goto out; 2103 } 2104 2105 /* A client is waiting for the begin, don't give it a TouchEnd */ 2106 if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) { 2107 listener->state = TOUCH_LISTENER_HAS_END; 2108 goto out; 2109 } 2110 2111 /* Event in response to reject */ 2112 if (ev->device_event.flags & TOUCH_REJECT || 2113 (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) { 2114 /* Touch has been rejected, or accepted by its owner which is not this listener */ 2115 if (listener->state != TOUCH_LISTENER_HAS_END) 2116 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2117 listener->state = TOUCH_LISTENER_HAS_END; 2118 } 2119 else if (TouchResourceIsOwner(ti, listener->listener)) { 2120 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT); 2121 2122 /* FIXME: what about early acceptance */ 2123 if (normal_end && listener->state != TOUCH_LISTENER_HAS_END) 2124 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2125 2126 if ((ti->num_listeners > 1 || 2127 (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) && 2128 (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { 2129 ev->any.type = ET_TouchUpdate; 2130 ev->device_event.flags |= TOUCH_PENDING_END; 2131 ti->pending_finish = TRUE; 2132 } 2133 2134 if (normal_end) 2135 listener->state = TOUCH_LISTENER_HAS_END; 2136 } 2137 2138 out: 2139 return rc; 2140 } 2141 2142 static int 2143 DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 2144 TouchListener * listener, ClientPtr client, 2145 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 2146 { 2147 Bool has_ownershipmask = FALSE; 2148 int rc = Success; 2149 2150 if (xi2mask) 2151 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 2152 2153 if (ev->any.type == ET_TouchOwnership) { 2154 ev->touch_ownership_event.deviceid = dev->id; 2155 if (!TouchResourceIsOwner(ti, listener->listener)) 2156 goto out; 2157 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2158 listener->state = TOUCH_LISTENER_IS_OWNER; 2159 } 2160 else 2161 ev->device_event.deviceid = dev->id; 2162 2163 if (ev->any.type == ET_TouchBegin) { 2164 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, 2165 xi2mask); 2166 } 2167 else if (ev->any.type == ET_TouchUpdate) { 2168 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2169 listener->type == TOUCH_LISTENER_POINTER_GRAB) 2170 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, 2171 xi2mask); 2172 else if (TouchResourceIsOwner(ti, listener->listener) || 2173 has_ownershipmask) 2174 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2175 } 2176 else if (ev->any.type == ET_TouchEnd) 2177 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, 2178 xi2mask); 2179 2180 out: 2181 return rc; 2182 } 2183 2184 /** 2185 * Delivers a touch events to all interested clients. For TouchBegin events, 2186 * will update ti->listeners, ti->num_listeners, and ti->num_grabs. 2187 * May also mutate ev (type and flags) upon successful delivery. If 2188 * @resource is non-zero, will only attempt delivery to the owner of that 2189 * resource. 2190 * 2191 * @return TRUE if the event was delivered at least once, FALSE otherwise 2192 */ 2193 void 2194 DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, 2195 InternalEvent *ev, XID resource) 2196 { 2197 int i; 2198 2199 if (ev->any.type == ET_TouchBegin && 2200 !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING))) 2201 TouchSetupListeners(dev, ti, ev); 2202 2203 TouchEventHistoryPush(ti, &ev->device_event); 2204 2205 for (i = 0; i < ti->num_listeners; i++) { 2206 GrabPtr grab = NULL; 2207 ClientPtr client; 2208 WindowPtr win; 2209 XI2Mask *mask; 2210 TouchListener *listener = &ti->listeners[i]; 2211 2212 if (resource && listener->listener != resource) 2213 continue; 2214 2215 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win, 2216 &grab, &mask)) 2217 continue; 2218 2219 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask); 2220 } 2221 } 2222 2223 /** 2224 * Attempts to deliver a gesture event to the given client. 2225 */ 2226 static Bool 2227 DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi, 2228 GrabPtr grab, WindowPtr win, InternalEvent *ev) 2229 { 2230 int err; 2231 xEvent *xi2; 2232 Mask filter; 2233 Window child = DeepestSpriteWin(&gi->sprite)->drawable.id; 2234 2235 /* If we fail here, we're going to leave a client hanging. */ 2236 err = EventToXI2(ev, &xi2); 2237 if (err != Success) 2238 FatalError("[Xi] %s: XI2 conversion failed in %s" 2239 " (%d)\n", dev->name, __func__, err); 2240 2241 FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE); 2242 filter = GetEventFilter(dev, xi2); 2243 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) 2244 return FALSE; 2245 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); 2246 free(xi2); 2247 2248 /* Returning the value from TryClientEvents isn't useful, since all our 2249 * resource-gone cleanups will update the delivery list anyway. */ 2250 return TRUE; 2251 } 2252 2253 /** 2254 * Given a gesture event and a potential listener, retrieve info needed for processing the event. 2255 * 2256 * @param dev The device generating the gesture event. 2257 * @param ev The gesture event to process. 2258 * @param listener The gesture event listener that may receive the gesture event. 2259 * @param[out] client The client that should receive the gesture event. 2260 * @param[out] win The window to deliver the event on. 2261 * @param[out] grab The grab to deliver the event through, if any. 2262 * @return TRUE if an event should be delivered to the listener, FALSE 2263 * otherwise. 2264 */ 2265 static Bool 2266 RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener, 2267 ClientPtr *client, WindowPtr *win, GrabPtr *grab) 2268 { 2269 int rc; 2270 int evtype; 2271 InputClients *iclients = NULL; 2272 *grab = NULL; 2273 2274 if (listener->type == GESTURE_LISTENER_GRAB || 2275 listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2276 *grab = listener->grab; 2277 2278 BUG_RETURN_VAL(!*grab, FALSE); 2279 2280 *client = rClient(*grab); 2281 *win = (*grab)->window; 2282 } 2283 else { 2284 rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type, 2285 serverClient, DixSendAccess); 2286 if (rc != Success) 2287 return FALSE; 2288 2289 /* note that we only will have XI2 listeners as 2290 listener->type == GESTURE_LISTENER_REGULAR */ 2291 evtype = GetXI2Type(ev->any.type); 2292 2293 BUG_RETURN_VAL(!wOtherInputMasks(*win), FALSE); 2294 nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next) 2295 if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 2296 break; 2297 2298 BUG_RETURN_VAL(!iclients, FALSE); 2299 2300 *client = rClient(iclients); 2301 } 2302 2303 return TRUE; 2304 } 2305 2306 /** 2307 * Delivers a gesture to the owner, if possible and needed. Returns whether 2308 * an event was delivered. 2309 */ 2310 Bool 2311 DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev) 2312 { 2313 GrabPtr grab = NULL; 2314 ClientPtr client; 2315 WindowPtr win; 2316 2317 if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2318 return 0; 2319 } 2320 2321 if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab)) 2322 return 0; 2323 2324 ev->gesture_event.deviceid = dev->id; 2325 2326 return DeliverOneGestureEvent(client, dev, gi, grab, win, ev); 2327 } 2328 2329 int 2330 InitProximityClassDeviceStruct(DeviceIntPtr dev) 2331 { 2332 ProximityClassPtr proxc; 2333 2334 BUG_RETURN_VAL(dev == NULL, FALSE); 2335 BUG_RETURN_VAL(dev->proximity != NULL, FALSE); 2336 2337 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec)); 2338 if (!proxc) 2339 return FALSE; 2340 proxc->sourceid = dev->id; 2341 proxc->in_proximity = TRUE; 2342 dev->proximity = proxc; 2343 return TRUE; 2344 } 2345 2346 /** 2347 * Initialise the device's valuators. The memory must already be allocated, 2348 * this function merely inits the matching axis (specified through axnum) to 2349 * sane values. 2350 * 2351 * It is a condition that (minval < maxval). 2352 * 2353 * @see InitValuatorClassDeviceStruct 2354 */ 2355 Bool 2356 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 2357 int maxval, int resolution, int min_res, int max_res, 2358 int mode) 2359 { 2360 AxisInfoPtr ax; 2361 2362 BUG_RETURN_VAL(dev == NULL, FALSE); 2363 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2364 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2365 BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE); 2366 2367 ax = dev->valuator->axes + axnum; 2368 2369 ax->min_value = minval; 2370 ax->max_value = maxval; 2371 ax->resolution = resolution; 2372 ax->min_resolution = min_res; 2373 ax->max_resolution = max_res; 2374 ax->label = label; 2375 ax->mode = mode; 2376 2377 if (mode & OutOfProximity) 2378 dev->proximity->in_proximity = FALSE; 2379 2380 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE); 2381 } 2382 2383 /** 2384 * Set the given axis number as a scrolling valuator. 2385 */ 2386 Bool 2387 SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, 2388 double increment, int flags) 2389 { 2390 AxisInfoPtr ax; 2391 int *current_ax; 2392 InternalEvent dce; 2393 DeviceIntPtr master; 2394 2395 BUG_RETURN_VAL(dev == NULL, FALSE); 2396 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2397 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2398 2399 switch (type) { 2400 case SCROLL_TYPE_VERTICAL: 2401 current_ax = &dev->valuator->v_scroll_axis; 2402 break; 2403 case SCROLL_TYPE_HORIZONTAL: 2404 current_ax = &dev->valuator->h_scroll_axis; 2405 break; 2406 case SCROLL_TYPE_NONE: 2407 ax = &dev->valuator->axes[axnum]; 2408 ax->scroll.type = type; 2409 return TRUE; 2410 default: 2411 return FALSE; 2412 } 2413 2414 if (increment == 0.0) 2415 return FALSE; 2416 2417 if (*current_ax != -1 && axnum != *current_ax) { 2418 ax = &dev->valuator->axes[*current_ax]; 2419 if (ax->scroll.type == type && 2420 (flags & SCROLL_FLAG_PREFERRED) && 2421 (ax->scroll.flags & SCROLL_FLAG_PREFERRED)) 2422 return FALSE; 2423 } 2424 *current_ax = axnum; 2425 2426 ax = &dev->valuator->axes[axnum]; 2427 ax->scroll.type = type; 2428 ax->scroll.increment = increment; 2429 ax->scroll.flags = flags; 2430 2431 master = GetMaster(dev, MASTER_ATTACHED); 2432 CreateClassesChangedEvent(&dce, master, dev, 2433 DEVCHANGE_POINTER_EVENT | 2434 DEVCHANGE_DEVICE_CHANGE); 2435 XISendDeviceChangedEvent(dev, &dce.changed_event); 2436 2437 /* if the current slave is us, update the master. If not, we'll update 2438 * whenever the next slave switch happens anyway. CMDC sends the event 2439 * for us */ 2440 if (master && master->lastSlave == dev) 2441 ChangeMasterDeviceClasses(master, &dce.changed_event); 2442 2443 return TRUE; 2444 } 2445 2446 int 2447 CheckGrabValues(ClientPtr client, GrabParameters *param) 2448 { 2449 if (param->grabtype != CORE && 2450 param->grabtype != XI && param->grabtype != XI2) { 2451 ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); 2452 return BadImplementation; 2453 } 2454 2455 if ((param->this_device_mode != GrabModeSync) && 2456 (param->this_device_mode != GrabModeAsync) && 2457 (param->this_device_mode != XIGrabModeTouch)) { 2458 client->errorValue = param->this_device_mode; 2459 return BadValue; 2460 } 2461 if ((param->other_devices_mode != GrabModeSync) && 2462 (param->other_devices_mode != GrabModeAsync) && 2463 (param->other_devices_mode != XIGrabModeTouch)) { 2464 client->errorValue = param->other_devices_mode; 2465 return BadValue; 2466 } 2467 2468 if (param->modifiers != AnyModifier && 2469 param->modifiers != XIAnyModifier && 2470 (param->modifiers & ~AllModifiersMask)) { 2471 client->errorValue = param->modifiers; 2472 return BadValue; 2473 } 2474 2475 if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { 2476 client->errorValue = param->ownerEvents; 2477 return BadValue; 2478 } 2479 return Success; 2480 } 2481 2482 int 2483 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2484 int button, GrabParameters *param, enum InputLevel grabtype, 2485 GrabMask *mask) 2486 { 2487 WindowPtr pWin, confineTo; 2488 CursorPtr cursor; 2489 GrabPtr grab; 2490 int rc, type = -1; 2491 Mask access_mode = DixGrabAccess; 2492 2493 rc = CheckGrabValues(client, param); 2494 if (rc != Success) 2495 return rc; 2496 if (param->confineTo == None) 2497 confineTo = NullWindow; 2498 else { 2499 rc = dixLookupWindow(&confineTo, param->confineTo, client, 2500 DixSetAttrAccess); 2501 if (rc != Success) 2502 return rc; 2503 } 2504 if (param->cursor == None) 2505 cursor = NullCursor; 2506 else { 2507 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2508 RT_CURSOR, client, DixUseAccess); 2509 if (rc != Success) { 2510 client->errorValue = param->cursor; 2511 return rc; 2512 } 2513 access_mode |= DixForceAccess; 2514 } 2515 if (param->this_device_mode == GrabModeSync || 2516 param->other_devices_mode == GrabModeSync) 2517 access_mode |= DixFreezeAccess; 2518 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2519 if (rc != Success) 2520 return rc; 2521 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2522 if (rc != Success) 2523 return rc; 2524 2525 if (grabtype == XI) 2526 type = DeviceButtonPress; 2527 else if (grabtype == XI2) 2528 type = XI_ButtonPress; 2529 2530 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2531 mask, param, type, button, confineTo, cursor); 2532 if (!grab) 2533 return BadAlloc; 2534 return AddPassiveGrabToList(client, grab); 2535 } 2536 2537 /** 2538 * Grab the given key. 2539 */ 2540 int 2541 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2542 int key, GrabParameters *param, enum InputLevel grabtype, 2543 GrabMask *mask) 2544 { 2545 WindowPtr pWin; 2546 GrabPtr grab; 2547 KeyClassPtr k = dev->key; 2548 Mask access_mode = DixGrabAccess; 2549 int rc, type = -1; 2550 2551 rc = CheckGrabValues(client, param); 2552 if (rc != Success) 2553 return rc; 2554 if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL) 2555 return BadMatch; 2556 if (grabtype == XI) { 2557 if ((key > k->xkbInfo->desc->max_key_code || 2558 key < k->xkbInfo->desc->min_key_code) 2559 && (key != AnyKey)) { 2560 client->errorValue = key; 2561 return BadValue; 2562 } 2563 type = DeviceKeyPress; 2564 } 2565 else if (grabtype == XI2) 2566 type = XI_KeyPress; 2567 2568 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2569 if (rc != Success) 2570 return rc; 2571 if (param->this_device_mode == GrabModeSync || 2572 param->other_devices_mode == GrabModeSync) 2573 access_mode |= DixFreezeAccess; 2574 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2575 if (rc != Success) 2576 return rc; 2577 2578 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2579 mask, param, type, key, NULL, NULL); 2580 if (!grab) 2581 return BadAlloc; 2582 return AddPassiveGrabToList(client, grab); 2583 } 2584 2585 /* Enter/FocusIn grab */ 2586 int 2587 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type, 2588 GrabParameters *param, GrabMask *mask) 2589 { 2590 WindowPtr pWin; 2591 CursorPtr cursor; 2592 GrabPtr grab; 2593 Mask access_mode = DixGrabAccess; 2594 int rc; 2595 2596 rc = CheckGrabValues(client, param); 2597 if (rc != Success) 2598 return rc; 2599 2600 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2601 if (rc != Success) 2602 return rc; 2603 if (param->cursor == None) 2604 cursor = NullCursor; 2605 else { 2606 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2607 RT_CURSOR, client, DixUseAccess); 2608 if (rc != Success) { 2609 client->errorValue = param->cursor; 2610 return rc; 2611 } 2612 access_mode |= DixForceAccess; 2613 } 2614 if (param->this_device_mode == GrabModeSync || 2615 param->other_devices_mode == GrabModeSync) 2616 access_mode |= DixFreezeAccess; 2617 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2618 if (rc != Success) 2619 return rc; 2620 2621 grab = CreateGrab(client->index, dev, dev, pWin, XI2, 2622 mask, param, 2623 (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0, 2624 NULL, cursor); 2625 2626 if (!grab) 2627 return BadAlloc; 2628 2629 return AddPassiveGrabToList(client, grab); 2630 } 2631 2632 /* Touch grab */ 2633 int 2634 GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev, 2635 int type, GrabParameters *param, GrabMask *mask) 2636 { 2637 WindowPtr pWin; 2638 GrabPtr grab; 2639 int rc; 2640 2641 rc = CheckGrabValues(client, param); 2642 if (rc != Success) 2643 return rc; 2644 2645 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2646 if (rc != Success) 2647 return rc; 2648 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess); 2649 if (rc != Success) 2650 return rc; 2651 2652 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2, 2653 mask, param, type, 0, NullWindow, NullCursor); 2654 if (!grab) 2655 return BadAlloc; 2656 2657 return AddPassiveGrabToList(client, grab); 2658 } 2659 2660 int 2661 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 2662 Mask mask, Mask exclusivemasks) 2663 { 2664 int mskidx = dev->id; 2665 int i, ret; 2666 Mask check; 2667 InputClientsPtr others; 2668 2669 check = (mask & exclusivemasks); 2670 if (wOtherInputMasks(pWin)) { 2671 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { 2672 /* It is illegal for two different clients to select on any of 2673 * the events for maskcheck. However, it is OK, for some client 2674 * to continue selecting on one of those events. 2675 */ 2676 for (others = wOtherInputMasks(pWin)->inputClients; others; 2677 others = others->next) { 2678 if (!SameClient(others, client) && (check & 2679 others->mask[mskidx])) 2680 return BadAccess; 2681 } 2682 } 2683 for (others = wOtherInputMasks(pWin)->inputClients; others; 2684 others = others->next) { 2685 if (SameClient(others, client)) { 2686 check = others->mask[mskidx]; 2687 others->mask[mskidx] = mask; 2688 if (mask == 0) { 2689 for (i = 0; i < EMASKSIZE; i++) 2690 if (i != mskidx && others->mask[i] != 0) 2691 break; 2692 if (i == EMASKSIZE) { 2693 RecalculateDeviceDeliverableEvents(pWin); 2694 if (ShouldFreeInputMasks(pWin, FALSE)) 2695 FreeResource(others->resource, RT_NONE); 2696 return Success; 2697 } 2698 } 2699 goto maskSet; 2700 } 2701 } 2702 } 2703 check = 0; 2704 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 2705 return ret; 2706 maskSet: 2707 if (dev->valuator) 2708 if ((dev->valuator->motionHintWindow == pWin) && 2709 (mask & DevicePointerMotionHintMask) && 2710 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) 2711 dev->valuator->motionHintWindow = NullWindow; 2712 RecalculateDeviceDeliverableEvents(pWin); 2713 return Success; 2714 } 2715 2716 static void 2717 FreeInputClient(InputClientsPtr * other) 2718 { 2719 xi2mask_free(&(*other)->xi2mask); 2720 free(*other); 2721 *other = NULL; 2722 } 2723 2724 static InputClientsPtr 2725 AllocInputClient(void) 2726 { 2727 return calloc(1, sizeof(InputClients)); 2728 } 2729 2730 int 2731 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 2732 { 2733 InputClientsPtr others; 2734 2735 if (!pWin->optional && !MakeWindowOptional(pWin)) 2736 return BadAlloc; 2737 others = AllocInputClient(); 2738 if (!others) 2739 return BadAlloc; 2740 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 2741 goto bail; 2742 others->xi2mask = xi2mask_new(); 2743 if (!others->xi2mask) 2744 goto bail; 2745 others->mask[mskidx] = mask; 2746 others->resource = FakeClientID(client->index); 2747 others->next = pWin->optional->inputMasks->inputClients; 2748 pWin->optional->inputMasks->inputClients = others; 2749 if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin)) 2750 goto bail; 2751 return Success; 2752 2753 bail: 2754 FreeInputClient(&others); 2755 return BadAlloc; 2756 } 2757 2758 static Bool 2759 MakeInputMasks(WindowPtr pWin) 2760 { 2761 struct _OtherInputMasks *imasks; 2762 2763 imasks = calloc(1, sizeof(struct _OtherInputMasks)); 2764 if (!imasks) 2765 return FALSE; 2766 imasks->xi2mask = xi2mask_new(); 2767 if (!imasks->xi2mask) { 2768 free(imasks); 2769 return FALSE; 2770 } 2771 pWin->optional->inputMasks = imasks; 2772 return TRUE; 2773 } 2774 2775 static void 2776 FreeInputMask(OtherInputMasks ** imask) 2777 { 2778 xi2mask_free(&(*imask)->xi2mask); 2779 free(*imask); 2780 *imask = NULL; 2781 } 2782 2783 #define XIPropagateMask (KeyPressMask | \ 2784 KeyReleaseMask | \ 2785 ButtonPressMask | \ 2786 ButtonReleaseMask | \ 2787 PointerMotionMask) 2788 2789 void 2790 RecalculateDeviceDeliverableEvents(WindowPtr pWin) 2791 { 2792 InputClientsPtr others; 2793 struct _OtherInputMasks *inputMasks; /* default: NULL */ 2794 WindowPtr pChild, tmp; 2795 int i; 2796 2797 pChild = pWin; 2798 while (1) { 2799 if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 2800 xi2mask_zero(inputMasks->xi2mask, -1); 2801 for (others = inputMasks->inputClients; others; 2802 others = others->next) { 2803 for (i = 0; i < EMASKSIZE; i++) 2804 inputMasks->inputEvents[i] |= others->mask[i]; 2805 xi2mask_merge(inputMasks->xi2mask, others->xi2mask); 2806 } 2807 for (i = 0; i < EMASKSIZE; i++) 2808 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 2809 for (tmp = pChild->parent; tmp; tmp = tmp->parent) 2810 if (wOtherInputMasks(tmp)) 2811 for (i = 0; i < EMASKSIZE; i++) 2812 inputMasks->deliverableEvents[i] |= 2813 (wOtherInputMasks(tmp)->deliverableEvents[i] 2814 & ~inputMasks->dontPropagateMask[i] & 2815 XIPropagateMask); 2816 } 2817 if (pChild->firstChild) { 2818 pChild = pChild->firstChild; 2819 continue; 2820 } 2821 while (!pChild->nextSib && (pChild != pWin)) 2822 pChild = pChild->parent; 2823 if (pChild == pWin) 2824 break; 2825 pChild = pChild->nextSib; 2826 } 2827 } 2828 2829 int 2830 InputClientGone(WindowPtr pWin, XID id) 2831 { 2832 InputClientsPtr other, prev; 2833 2834 if (!wOtherInputMasks(pWin)) 2835 return Success; 2836 prev = 0; 2837 for (other = wOtherInputMasks(pWin)->inputClients; other; 2838 other = other->next) { 2839 if (other->resource == id) { 2840 if (prev) { 2841 prev->next = other->next; 2842 FreeInputClient(&other); 2843 } 2844 else if (!(other->next)) { 2845 if (ShouldFreeInputMasks(pWin, TRUE)) { 2846 OtherInputMasks *mask = wOtherInputMasks(pWin); 2847 2848 mask->inputClients = other->next; 2849 FreeInputMask(&mask); 2850 pWin->optional->inputMasks = (OtherInputMasks *) NULL; 2851 CheckWindowOptionalNeed(pWin); 2852 FreeInputClient(&other); 2853 } 2854 else { 2855 other->resource = FakeClientID(0); 2856 if (!AddResource(other->resource, RT_INPUTCLIENT, 2857 (void *) pWin)) 2858 return BadAlloc; 2859 } 2860 } 2861 else { 2862 wOtherInputMasks(pWin)->inputClients = other->next; 2863 FreeInputClient(&other); 2864 } 2865 RecalculateDeviceDeliverableEvents(pWin); 2866 return Success; 2867 } 2868 prev = other; 2869 } 2870 FatalError("client not on device event list"); 2871 } 2872 2873 /** 2874 * Search for window in each touch trace for each device. Remove the window 2875 * and all its subwindows from the trace when found. The initial window 2876 * order is preserved. 2877 */ 2878 void 2879 WindowGone(WindowPtr win) 2880 { 2881 DeviceIntPtr dev; 2882 2883 for (dev = inputInfo.devices; dev; dev = dev->next) { 2884 TouchClassPtr t = dev->touch; 2885 int i; 2886 2887 if (!t) 2888 continue; 2889 2890 for (i = 0; i < t->num_touches; i++) { 2891 SpritePtr sprite = &t->touches[i].sprite; 2892 int j; 2893 2894 for (j = 0; j < sprite->spriteTraceGood; j++) { 2895 if (sprite->spriteTrace[j] == win) { 2896 sprite->spriteTraceGood = j; 2897 break; 2898 } 2899 } 2900 } 2901 } 2902 } 2903 2904 int 2905 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 2906 xEvent *ev, Mask mask, int count) 2907 { 2908 WindowPtr pWin; 2909 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 2910 WindowPtr spriteWin = GetSpriteWindow(d); 2911 2912 if (dest == PointerWindow) 2913 pWin = spriteWin; 2914 else if (dest == InputFocus) { 2915 WindowPtr inputFocus; 2916 2917 if (!d->focus) 2918 inputFocus = spriteWin; 2919 else 2920 inputFocus = d->focus->win; 2921 2922 if (inputFocus == FollowKeyboardWin) 2923 inputFocus = inputInfo.keyboard->focus->win; 2924 2925 if (inputFocus == NoneWin) 2926 return Success; 2927 2928 /* If the input focus is PointerRootWin, send the event to where 2929 * the pointer is if possible, then perhaps propagate up to root. */ 2930 if (inputFocus == PointerRootWin) 2931 inputFocus = GetCurrentRootWindow(d); 2932 2933 if (IsParent(inputFocus, spriteWin)) { 2934 effectiveFocus = inputFocus; 2935 pWin = spriteWin; 2936 } 2937 else 2938 effectiveFocus = pWin = inputFocus; 2939 } 2940 else 2941 dixLookupWindow(&pWin, dest, client, DixSendAccess); 2942 if (!pWin) 2943 return BadWindow; 2944 if ((propagate != xFalse) && (propagate != xTrue)) { 2945 client->errorValue = propagate; 2946 return BadValue; 2947 } 2948 ev->u.u.type |= 0x80; 2949 if (propagate) { 2950 for (; pWin; pWin = pWin->parent) { 2951 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) 2952 return Success; 2953 if (pWin == effectiveFocus) 2954 return Success; 2955 if (wOtherInputMasks(pWin)) 2956 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 2957 if (!mask) 2958 break; 2959 } 2960 } 2961 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) 2962 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); 2963 return Success; 2964 } 2965 2966 int 2967 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 2968 { 2969 int i; 2970 ButtonClassPtr b = dev->button; 2971 2972 if (b == NULL) 2973 return BadMatch; 2974 2975 if (nElts != b->numButtons) { 2976 client->errorValue = nElts; 2977 return BadValue; 2978 } 2979 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 2980 return BadValue; 2981 for (i = 0; i < nElts; i++) 2982 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 2983 return MappingBusy; 2984 for (i = 0; i < nElts; i++) 2985 b->map[i + 1] = map[i]; 2986 return Success; 2987 } 2988 2989 int 2990 ChangeKeyMapping(ClientPtr client, 2991 DeviceIntPtr dev, 2992 unsigned len, 2993 int type, 2994 KeyCode firstKeyCode, 2995 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 2996 { 2997 KeySymsRec keysyms; 2998 KeyClassPtr k = dev->key; 2999 3000 if (k == NULL) 3001 return BadMatch; 3002 3003 if (len != (keyCodes * keySymsPerKeyCode)) 3004 return BadLength; 3005 3006 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || 3007 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { 3008 client->errorValue = firstKeyCode; 3009 return BadValue; 3010 } 3011 if (keySymsPerKeyCode == 0) { 3012 client->errorValue = 0; 3013 return BadValue; 3014 } 3015 keysyms.minKeyCode = firstKeyCode; 3016 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 3017 keysyms.mapWidth = keySymsPerKeyCode; 3018 keysyms.map = map; 3019 3020 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, 3021 serverClient); 3022 3023 return Success; 3024 } 3025 3026 static void 3027 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 3028 { 3029 WindowPtr parent; 3030 3031 /* Deactivate any grabs performed on this window, before making 3032 * any input focus changes. 3033 * Deactivating a device grab should cause focus events. */ 3034 3035 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) 3036 (*dev->deviceGrab.DeactivateGrab) (dev); 3037 3038 /* If the focus window is a root window (ie. has no parent) 3039 * then don't delete the focus from it. */ 3040 3041 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 3042 int focusEventMode = NotifyNormal; 3043 3044 /* If a grab is in progress, then alter the mode of focus events. */ 3045 3046 if (dev->deviceGrab.grab) 3047 focusEventMode = NotifyWhileGrabbed; 3048 3049 switch (dev->focus->revert) { 3050 case RevertToNone: 3051 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 3052 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 3053 dev->focus->win = NoneWin; 3054 dev->focus->traceGood = 0; 3055 break; 3056 case RevertToParent: 3057 parent = pWin; 3058 do { 3059 parent = parent->parent; 3060 dev->focus->traceGood--; 3061 } 3062 while (!parent->realized); 3063 if (!ActivateFocusInGrab(dev, pWin, parent)) 3064 DoFocusEvents(dev, pWin, parent, focusEventMode); 3065 dev->focus->win = parent; 3066 dev->focus->revert = RevertToNone; 3067 break; 3068 case RevertToPointerRoot: 3069 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) 3070 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 3071 dev->focus->win = PointerRootWin; 3072 dev->focus->traceGood = 0; 3073 break; 3074 case RevertToFollowKeyboard: 3075 { 3076 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 3077 3078 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) 3079 kbd = inputInfo.keyboard; 3080 if (kbd->focus->win) { 3081 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) 3082 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); 3083 dev->focus->win = FollowKeyboardWin; 3084 dev->focus->traceGood = 0; 3085 } 3086 else { 3087 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 3088 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 3089 dev->focus->win = NoneWin; 3090 dev->focus->traceGood = 0; 3091 } 3092 } 3093 break; 3094 } 3095 } 3096 3097 if (dev->valuator) 3098 if (dev->valuator->motionHintWindow == pWin) 3099 dev->valuator->motionHintWindow = NullWindow; 3100 } 3101 3102 void 3103 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 3104 { 3105 int i; 3106 DeviceIntPtr dev; 3107 InputClientsPtr ic; 3108 struct _OtherInputMasks *inputMasks; 3109 3110 for (dev = inputInfo.devices; dev; dev = dev->next) { 3111 DeleteDeviceFromAnyExtEvents(pWin, dev); 3112 } 3113 3114 for (dev = inputInfo.off_devices; dev; dev = dev->next) 3115 DeleteDeviceFromAnyExtEvents(pWin, dev); 3116 3117 if (freeResources) 3118 while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 3119 ic = inputMasks->inputClients; 3120 for (i = 0; i < EMASKSIZE; i++) 3121 inputMasks->dontPropagateMask[i] = 0; 3122 FreeResource(ic->resource, RT_NONE); 3123 } 3124 } 3125 3126 int 3127 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask) 3128 { 3129 DeviceIntPtr dev; 3130 3131 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient, 3132 DixReadAccess); 3133 if (!dev) 3134 return 0; 3135 3136 if (pEvents->type == DeviceMotionNotify) { 3137 if (mask & DevicePointerMotionHintMask) { 3138 if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 3139 return 1; /* don't send, but pretend we did */ 3140 } 3141 pEvents->detail = NotifyHint; 3142 } 3143 else { 3144 pEvents->detail = NotifyNormal; 3145 } 3146 } 3147 return 0; 3148 } 3149 3150 void 3151 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 3152 deviceKeyButtonPointer *xE, GrabPtr grab, 3153 ClientPtr client, Mask deliveryMask) 3154 { 3155 DeviceIntPtr dev; 3156 3157 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, 3158 DixGrabAccess); 3159 if (!dev) 3160 return; 3161 3162 if (type == DeviceMotionNotify) 3163 dev->valuator->motionHintWindow = pWin; 3164 else if ((type == DeviceButtonPress) && (!grab) && 3165 (deliveryMask & DeviceButtonGrabMask)) { 3166 GrabPtr tempGrab; 3167 3168 tempGrab = AllocGrab(NULL); 3169 if (!tempGrab) 3170 return; 3171 3172 tempGrab->device = dev; 3173 tempGrab->resource = client->clientAsMask; 3174 tempGrab->window = pWin; 3175 tempGrab->ownerEvents = 3176 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 3177 tempGrab->eventMask = deliveryMask; 3178 tempGrab->keyboardMode = GrabModeAsync; 3179 tempGrab->pointerMode = GrabModeAsync; 3180 tempGrab->confineTo = NullWindow; 3181 tempGrab->cursor = NullCursor; 3182 tempGrab->next = NULL; 3183 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE); 3184 FreeGrab(tempGrab); 3185 } 3186 } 3187 3188 static Mask 3189 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 3190 { 3191 InputClientsPtr other; 3192 3193 if (!wOtherInputMasks(pWin)) 3194 return 0; 3195 for (other = wOtherInputMasks(pWin)->inputClients; other; 3196 other = other->next) { 3197 if (SameClient(other, client)) 3198 return other->mask[dev->id]; 3199 } 3200 return 0; 3201 } 3202 3203 void 3204 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 3205 { 3206 WindowPtr pWin; 3207 GrabPtr grab = dev->deviceGrab.grab; 3208 3209 pWin = dev->valuator->motionHintWindow; 3210 3211 if ((grab && SameClient(grab, client) && 3212 ((grab->eventMask & DevicePointerMotionHintMask) || 3213 (grab->ownerEvents && 3214 (DeviceEventMaskForClient(dev, pWin, client) & 3215 DevicePointerMotionHintMask)))) || 3216 (!grab && 3217 (DeviceEventMaskForClient(dev, pWin, client) & 3218 DevicePointerMotionHintMask))) 3219 dev->valuator->motionHintWindow = NullWindow; 3220 } 3221 3222 int 3223 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 3224 int maskndx) 3225 { 3226 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 3227 3228 if (mask & ~XIPropagateMask) { 3229 client->errorValue = mask; 3230 return BadValue; 3231 } 3232 3233 if (mask == 0) { 3234 if (inputMasks) 3235 inputMasks->dontPropagateMask[maskndx] = mask; 3236 } 3237 else { 3238 if (!inputMasks) { 3239 int ret = AddExtensionClient(pWin, client, 0, 0); 3240 3241 if (ret != Success) 3242 return ret; 3243 inputMasks = wOtherInputMasks(pWin); 3244 BUG_RETURN_VAL(!inputMasks, BadAlloc); 3245 } 3246 inputMasks->dontPropagateMask[maskndx] = mask; 3247 } 3248 RecalculateDeviceDeliverableEvents(pWin); 3249 if (inputMasks && ShouldFreeInputMasks(pWin, FALSE)) 3250 FreeResource(inputMasks->inputClients->resource, RT_NONE); 3251 return Success; 3252 } 3253 3254 Bool 3255 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 3256 { 3257 int i; 3258 Mask allInputEventMasks = 0; 3259 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 3260 3261 for (i = 0; i < EMASKSIZE; i++) 3262 allInputEventMasks |= inputMasks->dontPropagateMask[i]; 3263 if (!ignoreSelectedEvents) 3264 for (i = 0; i < EMASKSIZE; i++) 3265 allInputEventMasks |= inputMasks->inputEvents[i]; 3266 if (allInputEventMasks == 0) 3267 return TRUE; 3268 else 3269 return FALSE; 3270 } 3271 3272 /*********************************************************************** 3273 * 3274 * Walk through the window tree, finding all clients that want to know 3275 * about the Event. 3276 * 3277 */ 3278 3279 static void 3280 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 3281 xEvent *ev, int count) 3282 { 3283 WindowPtr p2; 3284 3285 while (p1) { 3286 p2 = p1->firstChild; 3287 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); 3288 FindInterestedChildren(dev, p2, mask, ev, count); 3289 p1 = p1->nextSib; 3290 } 3291 } 3292 3293 /*********************************************************************** 3294 * 3295 * Send an event to interested clients in all windows on all screens. 3296 * 3297 */ 3298 3299 void 3300 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count) 3301 { 3302 int i; 3303 WindowPtr pWin, p1; 3304 3305 for (i = 0; i < screenInfo.numScreens; i++) { 3306 pWin = screenInfo.screens[i]->root; 3307 if (!pWin) 3308 continue; 3309 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); 3310 p1 = pWin->firstChild; 3311 FindInterestedChildren(dev, p1, mask, ev, count); 3312 } 3313 } 3314 3315 /** 3316 * Set the XI2 mask for the given client on the given window. 3317 * @param dev The device to set the mask for. 3318 * @param win The window to set the mask on. 3319 * @param client The client setting the mask. 3320 * @param len Number of bytes in mask. 3321 * @param mask Event mask in the form of (1 << eventtype) 3322 */ 3323 int 3324 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 3325 unsigned int len, unsigned char *mask) 3326 { 3327 OtherInputMasks *masks; 3328 InputClientsPtr others = NULL; 3329 3330 masks = wOtherInputMasks(win); 3331 if (masks) { 3332 for (others = wOtherInputMasks(win)->inputClients; others; 3333 others = others->next) { 3334 if (SameClient(others, client)) { 3335 xi2mask_zero(others->xi2mask, dev->id); 3336 break; 3337 } 3338 } 3339 } 3340 3341 if (len && !others) { 3342 if (AddExtensionClient(win, client, 0, 0) != Success) 3343 return BadAlloc; 3344 BUG_RETURN_VAL(!wOtherInputMasks(win), BadAlloc); 3345 others = wOtherInputMasks(win)->inputClients; 3346 } 3347 3348 if (others) { 3349 xi2mask_zero(others->xi2mask, dev->id); 3350 len = min(len, xi2mask_mask_size(others->xi2mask)); 3351 } 3352 3353 if (len) { 3354 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len); 3355 } 3356 3357 RecalculateDeviceDeliverableEvents(win); 3358 3359 return Success; 3360 } 3361