1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Hewlett-Packard not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45********************************************************/ 46 47/* 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@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 120Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , 121 Bool /* ignoreSelectedEvents */ 122 ); 123static 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 */ 131int 132XIShouldNotify(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 143Bool 144IsPointerEvent(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 158Bool 159IsTouchEvent(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 172Bool 173IsGestureEvent(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 189Bool 190IsGestureBeginEvent(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 202Bool 203IsGestureEndEvent(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 */ 219DeviceIntPtr 220XIGetDevice(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 267void 268CopyKeyClass(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 */ 286static void 287DeepCopyFeedbackClasses(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 416static void 417DeepCopyKeyboardClasses(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 */ 538static void 539DeepCopyPointerClasses(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 */ 726void 727DeepCopyDeviceClasses(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 */ 746void 747XISendDeviceChangedEvent(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 764static void 765ChangeMasterDeviceClasses(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 */ 809static void 810UpdateDeviceMotionMask(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 820static void 821IncreaseButtonCount(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 833static void 834DecreaseButtonCount(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 855int 856UpdateDeviceState(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 */ 1037static inline Bool 1038TouchClientWantsOwnershipEvents(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 1053static void 1054TouchSendOwnershipEvent(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 */ 1070static Bool 1071DeliverOneTouchEvent(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 1105static void 1106ActivateEarlyAccept(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 */ 1132static TouchPointInfoPtr 1133FindOldestPointerEmulatedTouch(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 */ 1169static void 1170TouchPuntToNextOwner(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 */ 1222static void 1223CheckOldestTouch(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 */ 1240void 1241TouchRejected(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 */ 1278static void 1279ProcessTouchOwnershipEvent(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 */ 1327static void 1328TouchCopyValuatorData(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 */ 1352static Bool 1353RetrieveTouchDeliveryData(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 nt_list_for_each_entry(iclients, 1389 wOtherInputMasks(*win)->inputClients, next) 1390 if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 1391 break; 1392 1393 BUG_RETURN_VAL(!iclients, FALSE); 1394 1395 *mask = iclients->xi2mask; 1396 *client = rClient(iclients); 1397 } 1398 else if (listener->level == XI) { 1399 int xi_type = GetXIType(TouchGetPointerEventType(ev)); 1400 Mask xi_filter = event_get_filter_from_type(dev, xi_type); 1401 1402 nt_list_for_each_entry(iclients, 1403 wOtherInputMasks(*win)->inputClients, next) 1404 if (iclients->mask[dev->id] & xi_filter) 1405 break; 1406 BUG_RETURN_VAL(!iclients, FALSE); 1407 1408 *client = rClient(iclients); 1409 } 1410 else { 1411 int coretype = GetCoreType(TouchGetPointerEventType(ev)); 1412 Mask core_filter = event_get_filter_from_type(dev, coretype); 1413 OtherClients *oclients; 1414 1415 /* all others */ 1416 nt_list_for_each_entry(oclients, 1417 (OtherClients *) wOtherClients(*win), next) 1418 if (oclients->mask & core_filter) 1419 break; 1420 1421 /* if owner selected, oclients is NULL */ 1422 *client = oclients ? rClient(oclients) : wClient(*win); 1423 } 1424 1425 *grab = NULL; 1426 } 1427 1428 return TRUE; 1429} 1430 1431static int 1432DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1433 InternalEvent *ev, TouchListener * listener, 1434 ClientPtr client, WindowPtr win, GrabPtr grab, 1435 XI2Mask *xi2mask) 1436{ 1437 InternalEvent motion, button; 1438 InternalEvent *ptrev = &motion; 1439 int nevents; 1440 DeviceIntPtr kbd; 1441 1442 /* There may be a pointer grab on the device */ 1443 if (!grab) { 1444 grab = dev->deviceGrab.grab; 1445 if (grab) { 1446 win = grab->window; 1447 xi2mask = grab->xi2mask; 1448 client = rClient(grab); 1449 } 1450 } 1451 1452 /* We don't deliver pointer events to non-owners */ 1453 if (!TouchResourceIsOwner(ti, listener->listener)) 1454 return !Success; 1455 1456 if (!ti->emulate_pointer) 1457 return !Success; 1458 1459 nevents = TouchConvertToPointerEvent(ev, &motion, &button); 1460 BUG_RETURN_VAL(nevents == 0, BadValue); 1461 1462 /* Note that here we deliver only part of the events that are generated by the touch event: 1463 * 1464 * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent) 1465 * TouchUpdate results in Motion 1466 * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent) 1467 */ 1468 if (nevents > 1) 1469 ptrev = &button; 1470 1471 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1472 event_set_state(dev, kbd, &ptrev->device_event); 1473 ptrev->device_event.corestate = event_get_corestate(dev, kbd); 1474 1475 if (grab) { 1476 /* this side-steps the usual activation mechanisms, but... */ 1477 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) 1478 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */ 1479 else { 1480 int deliveries = 0; 1481 1482 /* 'grab' is the passive grab, but if the grab isn't active, 1483 * don't deliver */ 1484 if (!dev->deviceGrab.grab) 1485 return !Success; 1486 1487 if (grab->ownerEvents) { 1488 WindowPtr focus = NullWindow; 1489 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1490 1491 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev); 1492 } 1493 1494 if (!deliveries) 1495 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); 1496 1497 /* We must accept the touch sequence once a pointer listener has 1498 * received one event past ButtonPress. */ 1499 if (deliveries && ev->any.type != ET_TouchBegin && 1500 !(ev->device_event.flags & TOUCH_CLIENT_ID)) 1501 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1502 1503 if (ev->any.type == ET_TouchEnd && 1504 ti->num_listeners == 1 && 1505 !dev->button->buttonsDown && 1506 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { 1507 (*dev->deviceGrab.DeactivateGrab) (dev); 1508 CheckOldestTouch(dev); 1509 return Success; 1510 } 1511 } 1512 } 1513 else { 1514 GrabPtr devgrab = dev->deviceGrab.grab; 1515 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1516 1517 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev); 1518 /* FIXME: bad hack 1519 * Implicit passive grab activated in response to this event. Store 1520 * the event. 1521 */ 1522 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { 1523 TouchListener *l; 1524 GrabPtr g; 1525 1526 devgrab = dev->deviceGrab.grab; 1527 g = AllocGrab(devgrab); 1528 BUG_WARN(!g); 1529 1530 CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev); 1531 1532 /* The listener array has a sequence of grabs and then one event 1533 * selection. Implicit grab activation occurs through delivering an 1534 * event selection. Thus, we update the last listener in the array. 1535 */ 1536 l = &ti->listeners[ti->num_listeners - 1]; 1537 l->listener = g->resource; 1538 l->grab = g; 1539 //l->resource_type = RT_NONE; 1540 1541 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) 1542 l->type = TOUCH_LISTENER_POINTER_GRAB; 1543 else 1544 l->type = TOUCH_LISTENER_GRAB; 1545 } 1546 1547 } 1548 if (ev->any.type == ET_TouchBegin) 1549 listener->state = TOUCH_LISTENER_IS_OWNER; 1550 else if (ev->any.type == ET_TouchEnd) 1551 listener->state = TOUCH_LISTENER_HAS_END; 1552 1553 return Success; 1554} 1555 1556static void 1557DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1558 InternalEvent *ev) 1559{ 1560 DeviceEvent motion; 1561 1562 if (ti->num_listeners) { 1563 ClientPtr client; 1564 WindowPtr win; 1565 GrabPtr grab; 1566 XI2Mask *mask; 1567 1568 if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR && 1569 ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB) 1570 return; 1571 1572 motion = ev->device_event; 1573 motion.type = ET_TouchUpdate; 1574 motion.detail.button = 0; 1575 1576 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion, 1577 &ti->listeners[0], &client, &win, &grab, 1578 &mask)) 1579 return; 1580 1581 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client, 1582 win, grab, mask); 1583 } 1584 else { 1585 InternalEvent button; 1586 int converted; 1587 1588 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button); 1589 1590 BUG_WARN(converted == 0); 1591 if (converted) 1592 ProcessOtherEvent((InternalEvent*)&motion, dev); 1593 } 1594} 1595 1596/** 1597 * Processes and delivers a TouchBegin, TouchUpdate, or a 1598 * TouchEnd event. 1599 * 1600 * Due to having rather different delivery semantics (see the Xi 2.2 protocol 1601 * spec for more information), this implements its own grab and event-selection 1602 * delivery logic. 1603 */ 1604static void 1605ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) 1606{ 1607 TouchClassPtr t = dev->touch; 1608 TouchPointInfoPtr ti; 1609 uint32_t touchid; 1610 int type = ev->any.type; 1611 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED); 1612 DeviceIntPtr kbd; 1613 1614 if (!t) 1615 return; 1616 1617 touchid = ev->device_event.touchid; 1618 1619 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) { 1620 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1621 emulate_pointer); 1622 } 1623 else 1624 ti = TouchFindByClientID(dev, touchid); 1625 1626 /* Active pointer grab */ 1627 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && 1628 (dev->deviceGrab.grab->grabtype == CORE || 1629 dev->deviceGrab.grab->grabtype == XI || 1630 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) 1631 { 1632 /* Active pointer grab on touch point and we get a TouchEnd - claim this 1633 * touchpoint accepted, otherwise clients waiting for ownership will 1634 * wait on this touchpoint until this client ungrabs, or the cows come 1635 * home, whichever is earlier */ 1636 if (ti && type == ET_TouchEnd) 1637 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1638 else if (!ti && type != ET_TouchBegin) { 1639 /* Under the following circumstances we create a new touch record for an 1640 * existing touch: 1641 * 1642 * - The touch may be pointer emulated 1643 * - An explicit grab is active on the device 1644 * - The grab is a pointer grab 1645 * 1646 * This allows for an explicit grab to receive pointer events for an already 1647 * active touch. 1648 */ 1649 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1650 emulate_pointer); 1651 if (!ti) { 1652 DebugF("[Xi] %s: Failed to create new dix record for explicitly " 1653 "grabbed touchpoint %d\n", 1654 dev->name, touchid); 1655 return; 1656 } 1657 1658 TouchBuildSprite(dev, ti, ev); 1659 TouchSetupListeners(dev, ti, ev); 1660 } 1661 } 1662 1663 if (!ti) { 1664 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 1665 dev->name, type, touchid); 1666 goto out; 1667 } 1668 1669 /* if emulate_pointer is set, emulate the motion event right 1670 * here, so we can ignore it for button event emulation. TouchUpdate 1671 * events which _only_ emulate motion just work normally */ 1672 if (emulate_pointer && (ev->any.type == ET_TouchBegin || 1673 (ev->any.type == ET_TouchEnd && ti->num_listeners > 0))) 1674 DeliverEmulatedMotionEvent(dev, ti, ev); 1675 1676 if (emulate_pointer && IsMaster(dev)) 1677 CheckMotion(&ev->device_event, dev); 1678 1679 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1680 event_set_state(NULL, kbd, &ev->device_event); 1681 ev->device_event.corestate = event_get_corestate(NULL, kbd); 1682 1683 /* Make sure we have a valid window trace for event delivery; must be 1684 * called after event type mutation. Touch end events are always processed 1685 * in order to end touch records. */ 1686 /* FIXME: check this */ 1687 if ((type == ET_TouchBegin && 1688 !(ev->device_event.flags & TOUCH_REPLAYING) && 1689 !TouchBuildSprite(dev, ti, ev)) || 1690 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) 1691 return; 1692 1693 TouchCopyValuatorData(&ev->device_event, ti); 1694 /* WARNING: the event type may change to TouchUpdate in 1695 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing 1696 * owner */ 1697 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource); 1698 if (ev->any.type == ET_TouchEnd) 1699 TouchEndTouch(dev, ti); 1700 1701 out: 1702 if (emulate_pointer) 1703 UpdateDeviceState(dev, &ev->device_event); 1704} 1705 1706static void 1707ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev) 1708{ 1709 Mask filter; 1710 WindowPtr pWin; 1711 BarrierEvent *be = &e->barrier_event; 1712 xEvent *ev; 1713 int rc; 1714 GrabPtr grab = dev->deviceGrab.grab; 1715 1716 if (!IsMaster(dev)) 1717 return; 1718 1719 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success) 1720 return; 1721 1722 if (grab) 1723 be->flags |= XIBarrierDeviceIsGrabbed; 1724 1725 rc = EventToXI2(e, &ev); 1726 if (rc != Success) { 1727 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc); 1728 return; 1729 } 1730 1731 /* A client has a grab, deliver to this client if the grab_window is the 1732 barrier window. 1733 1734 Otherwise, deliver normally to the client. 1735 */ 1736 if (grab && 1737 CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) && 1738 grab->window->drawable.id == be->window) { 1739 DeliverGrabbedEvent(e, dev, FALSE); 1740 } else { 1741 filter = GetEventFilter(dev, ev); 1742 1743 DeliverEventsToWindow(dev, pWin, ev, 1, 1744 filter, NullGrab); 1745 } 1746 free(ev); 1747} 1748 1749static BOOL 1750IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev) 1751{ 1752 GestureClassPtr g = dev->gesture; 1753 if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) { 1754 return TRUE; 1755 } 1756 return FALSE; 1757} 1758 1759/** 1760 * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}. 1761 * 1762 * Due to having rather different delivery semantics (see the Xi 2.4 protocol 1763 * spec for more information), this implements its own grab and event-selection 1764 * delivery logic. 1765 */ 1766void 1767ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev) 1768{ 1769 GestureInfoPtr gi; 1770 DeviceIntPtr kbd; 1771 Bool deactivateGestureGrab = FALSE; 1772 Bool delivered = FALSE; 1773 1774 if (!dev->gesture) 1775 return; 1776 1777 if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev)) 1778 return; 1779 1780 if (IsGestureBeginEvent(ev)) 1781 gi = GestureBeginGesture(dev, ev); 1782 else 1783 gi = GestureFindActiveByEventType(dev, ev->any.type); 1784 1785 if (!gi) { 1786 /* This may happen if gesture is no longer active or was never started. */ 1787 return; 1788 } 1789 1790 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1791 event_set_state_gesture(kbd, &ev->gesture_event); 1792 1793 if (IsGestureBeginEvent(ev)) 1794 GestureSetupListener(dev, gi, ev); 1795 1796 if (IsGestureEndEvent(ev) && 1797 dev->deviceGrab.grab && 1798 dev->deviceGrab.fromPassiveGrab && 1799 GrabIsGestureGrab(dev->deviceGrab.grab)) 1800 deactivateGestureGrab = TRUE; 1801 1802 delivered = DeliverGestureEventToOwner(dev, gi, ev); 1803 1804 if (delivered && !deactivateGestureGrab && 1805 (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev))) 1806 FreezeThisEventIfNeededForSyncGrab(dev, ev); 1807 1808 if (IsGestureEndEvent(ev)) 1809 GestureEndGesture(gi); 1810 1811 if (deactivateGestureGrab) 1812 (*dev->deviceGrab.DeactivateGrab) (dev); 1813} 1814 1815/** 1816 * Process DeviceEvents and DeviceChangedEvents. 1817 */ 1818static void 1819ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device) 1820{ 1821 GrabPtr grab; 1822 Bool deactivateDeviceGrab = FALSE; 1823 int key = 0, rootX, rootY; 1824 ButtonClassPtr b; 1825 int ret = 0; 1826 int corestate; 1827 DeviceIntPtr mouse = NULL, kbd = NULL; 1828 DeviceEvent *event = &ev->device_event; 1829 1830 if (IsPointerDevice(device)) { 1831 kbd = GetMaster(device, KEYBOARD_OR_FLOAT); 1832 mouse = device; 1833 if (!kbd->key) /* can happen with floating SDs */ 1834 kbd = NULL; 1835 } 1836 else { 1837 mouse = GetMaster(device, POINTER_OR_FLOAT); 1838 kbd = device; 1839 if (!mouse->valuator || !mouse->button) /* may be float. SDs */ 1840 mouse = NULL; 1841 } 1842 1843 corestate = event_get_corestate(mouse, kbd); 1844 event_set_state(mouse, kbd, event); 1845 1846 ret = UpdateDeviceState(device, event); 1847 if (ret == DONT_PROCESS) 1848 return; 1849 1850 b = device->button; 1851 1852 if (IsMaster(device) || IsFloating(device)) 1853 CheckMotion(event, device); 1854 1855 switch (event->type) { 1856 case ET_Motion: 1857 case ET_ButtonPress: 1858 case ET_ButtonRelease: 1859 case ET_KeyPress: 1860 case ET_KeyRelease: 1861 case ET_ProximityIn: 1862 case ET_ProximityOut: 1863 GetSpritePosition(device, &rootX, &rootY); 1864 event->root_x = rootX; 1865 event->root_y = rootY; 1866 NoticeEventTime((InternalEvent *) event, device); 1867 event->corestate = corestate; 1868 key = event->detail.key; 1869 break; 1870 default: 1871 break; 1872 } 1873 1874 /* send KeyPress and KeyRelease events to XACE plugins */ 1875 if (XaceHookIsSet(XACE_KEY_AVAIL) && 1876 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) { 1877 xEvent *core; 1878 int count; 1879 1880 if (EventToCore(ev, &core, &count) == Success && count > 0) { 1881 XaceHook(XACE_KEY_AVAIL, core, device, 0); 1882 free(core); 1883 } 1884 } 1885 1886 if (DeviceEventCallback && !syncEvents.playingEvents) { 1887 DeviceEventInfoRec eventinfo; 1888 SpritePtr pSprite = device->spriteInfo->sprite; 1889 1890 /* see comment in EnqueueEvents regarding the next three lines */ 1891 if (ev->any.type == ET_Motion) 1892 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 1893 1894 eventinfo.device = device; 1895 eventinfo.event = ev; 1896 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 1897 } 1898 1899 grab = device->deviceGrab.grab; 1900 1901 switch (event->type) { 1902 case ET_KeyPress: 1903 /* Don't deliver focus events (e.g. from KeymapNotify when running 1904 * nested) to clients. */ 1905 if (event->source_type == EVENT_SOURCE_FOCUS) 1906 return; 1907 if (!grab && CheckDeviceGrabs(device, ev, 0)) 1908 return; 1909 break; 1910 case ET_KeyRelease: 1911 if (grab && device->deviceGrab.fromPassiveGrab && 1912 (key == device->deviceGrab.activatingKey) && 1913 GrabIsKeyboardGrab(device->deviceGrab.grab)) 1914 deactivateDeviceGrab = TRUE; 1915 break; 1916 case ET_ButtonPress: 1917 if (b->map[key] == 0) /* there's no button 0 */ 1918 return; 1919 event->detail.button = b->map[key]; 1920 if (!grab && CheckDeviceGrabs(device, ev, 0)) { 1921 /* if a passive grab was activated, the event has been sent 1922 * already */ 1923 return; 1924 } 1925 break; 1926 case ET_ButtonRelease: 1927 if (b->map[key] == 0) /* there's no button 0 */ 1928 return; 1929 event->detail.button = b->map[key]; 1930 if (grab && !b->buttonsDown && 1931 device->deviceGrab.fromPassiveGrab && 1932 GrabIsPointerGrab(device->deviceGrab.grab)) 1933 deactivateDeviceGrab = TRUE; 1934 default: 1935 break; 1936 } 1937 1938 /* Don't deliver focus events (e.g. from KeymapNotify when running 1939 * nested) to clients. */ 1940 if (event->source_type != EVENT_SOURCE_FOCUS) { 1941 if (grab) 1942 DeliverGrabbedEvent((InternalEvent *) event, device, 1943 deactivateDeviceGrab); 1944 else if (device->focus && !IsPointerEvent(ev)) 1945 DeliverFocusedEvent(device, (InternalEvent *) event, 1946 GetSpriteWindow(device)); 1947 else 1948 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event, 1949 NullGrab, NullWindow, device); 1950 } 1951 1952 if (deactivateDeviceGrab == TRUE) { 1953 (*device->deviceGrab.DeactivateGrab) (device); 1954 1955 if (!IsMaster (device) && !IsFloating (device)) { 1956 int flags, num_events = 0; 1957 InternalEvent dce; 1958 1959 flags = (IsPointerDevice (device)) ? 1960 DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT; 1961 UpdateFromMaster (&dce, device, flags, &num_events); 1962 BUG_WARN(num_events > 1); 1963 1964 if (num_events == 1) 1965 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED), 1966 &dce.changed_event); 1967 } 1968 1969 } 1970 1971 event->detail.key = key; 1972} 1973 1974/** 1975 * Main device event processing function. 1976 * Called from when processing the events from the event queue. 1977 * 1978 */ 1979void 1980ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) 1981{ 1982 verify_internal_event(ev); 1983 1984 switch (ev->any.type) { 1985 case ET_RawKeyPress: 1986 case ET_RawKeyRelease: 1987 case ET_RawButtonPress: 1988 case ET_RawButtonRelease: 1989 case ET_RawMotion: 1990 case ET_RawTouchBegin: 1991 case ET_RawTouchUpdate: 1992 case ET_RawTouchEnd: 1993 DeliverRawEvent(&ev->raw_event, device); 1994 break; 1995 case ET_TouchBegin: 1996 case ET_TouchUpdate: 1997 case ET_TouchEnd: 1998 ProcessTouchEvent(ev, device); 1999 break; 2000 case ET_TouchOwnership: 2001 /* TouchOwnership events are handled separately from the rest, as they 2002 * have more complex semantics. */ 2003 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device); 2004 break; 2005 case ET_BarrierHit: 2006 case ET_BarrierLeave: 2007 ProcessBarrierEvent(ev, device); 2008 break; 2009 case ET_GesturePinchBegin: 2010 case ET_GesturePinchUpdate: 2011 case ET_GesturePinchEnd: 2012 case ET_GestureSwipeBegin: 2013 case ET_GestureSwipeUpdate: 2014 case ET_GestureSwipeEnd: 2015 ProcessGestureEvent(ev, device); 2016 break; 2017 default: 2018 ProcessDeviceEvent(ev, device); 2019 break; 2020 } 2021} 2022 2023static int 2024DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 2025 InternalEvent *ev, TouchListener * listener, 2026 ClientPtr client, WindowPtr win, GrabPtr grab, 2027 XI2Mask *xi2mask) 2028{ 2029 enum TouchListenerState state; 2030 int rc = Success; 2031 Bool has_ownershipmask; 2032 2033 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2034 listener->type == TOUCH_LISTENER_POINTER_GRAB) { 2035 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 2036 grab, xi2mask); 2037 if (rc == Success) { 2038 listener->state = TOUCH_LISTENER_IS_OWNER; 2039 /* async grabs cannot replay, so automatically accept this touch */ 2040 if (listener->type == TOUCH_LISTENER_POINTER_GRAB && 2041 dev->deviceGrab.grab && 2042 dev->deviceGrab.fromPassiveGrab && 2043 dev->deviceGrab.grab->pointerMode == GrabModeAsync) 2044 ActivateEarlyAccept(dev, ti); 2045 } 2046 goto out; 2047 } 2048 2049 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 2050 2051 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask) 2052 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2053 if (!TouchResourceIsOwner(ti, listener->listener)) { 2054 if (has_ownershipmask) 2055 state = TOUCH_LISTENER_AWAITING_OWNER; 2056 else 2057 state = TOUCH_LISTENER_AWAITING_BEGIN; 2058 } 2059 else { 2060 if (has_ownershipmask) 2061 TouchSendOwnershipEvent(dev, ti, 0, listener->listener); 2062 2063 if (listener->type == TOUCH_LISTENER_REGULAR) 2064 state = TOUCH_LISTENER_HAS_ACCEPTED; 2065 else 2066 state = TOUCH_LISTENER_IS_OWNER; 2067 } 2068 listener->state = state; 2069 2070 out: 2071 return rc; 2072} 2073 2074static int 2075DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 2076 TouchListener * listener, ClientPtr client, 2077 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 2078{ 2079 int rc = Success; 2080 2081 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2082 listener->type == TOUCH_LISTENER_POINTER_GRAB) { 2083 /* Note: If the active grab was ungrabbed, we already changed the 2084 * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't 2085 * actually send the event. 2086 * This is part two of the hack in DeactivatePointerGrab 2087 */ 2088 if (listener->state != TOUCH_LISTENER_HAS_END) { 2089 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 2090 grab, xi2mask); 2091 2092 /* Once we send a TouchEnd to a legacy listener, we're already well 2093 * past the accepting/rejecting stage (can only happen on 2094 * GrabModeSync + replay. This listener now gets the end event, 2095 * and we can continue. 2096 */ 2097 if (rc == Success) 2098 listener->state = TOUCH_LISTENER_HAS_END; 2099 } 2100 goto out; 2101 } 2102 2103 /* A client is waiting for the begin, don't give it a TouchEnd */ 2104 if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) { 2105 listener->state = TOUCH_LISTENER_HAS_END; 2106 goto out; 2107 } 2108 2109 /* Event in response to reject */ 2110 if (ev->device_event.flags & TOUCH_REJECT || 2111 (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) { 2112 /* Touch has been rejected, or accepted by its owner which is not this listener */ 2113 if (listener->state != TOUCH_LISTENER_HAS_END) 2114 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2115 listener->state = TOUCH_LISTENER_HAS_END; 2116 } 2117 else if (TouchResourceIsOwner(ti, listener->listener)) { 2118 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT); 2119 2120 /* FIXME: what about early acceptance */ 2121 if (normal_end && listener->state != TOUCH_LISTENER_HAS_END) 2122 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2123 2124 if ((ti->num_listeners > 1 || 2125 (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) && 2126 (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { 2127 ev->any.type = ET_TouchUpdate; 2128 ev->device_event.flags |= TOUCH_PENDING_END; 2129 ti->pending_finish = TRUE; 2130 } 2131 2132 if (normal_end) 2133 listener->state = TOUCH_LISTENER_HAS_END; 2134 } 2135 2136 out: 2137 return rc; 2138} 2139 2140static int 2141DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 2142 TouchListener * listener, ClientPtr client, 2143 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 2144{ 2145 Bool has_ownershipmask = FALSE; 2146 int rc = Success; 2147 2148 if (xi2mask) 2149 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 2150 2151 if (ev->any.type == ET_TouchOwnership) { 2152 ev->touch_ownership_event.deviceid = dev->id; 2153 if (!TouchResourceIsOwner(ti, listener->listener)) 2154 goto out; 2155 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2156 listener->state = TOUCH_LISTENER_IS_OWNER; 2157 } 2158 else 2159 ev->device_event.deviceid = dev->id; 2160 2161 if (ev->any.type == ET_TouchBegin) { 2162 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, 2163 xi2mask); 2164 } 2165 else if (ev->any.type == ET_TouchUpdate) { 2166 if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2167 listener->type == TOUCH_LISTENER_POINTER_GRAB) 2168 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, 2169 xi2mask); 2170 else if (TouchResourceIsOwner(ti, listener->listener) || 2171 has_ownershipmask) 2172 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2173 } 2174 else if (ev->any.type == ET_TouchEnd) 2175 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, 2176 xi2mask); 2177 2178 out: 2179 return rc; 2180} 2181 2182/** 2183 * Delivers a touch events to all interested clients. For TouchBegin events, 2184 * will update ti->listeners, ti->num_listeners, and ti->num_grabs. 2185 * May also mutate ev (type and flags) upon successful delivery. If 2186 * @resource is non-zero, will only attempt delivery to the owner of that 2187 * resource. 2188 * 2189 * @return TRUE if the event was delivered at least once, FALSE otherwise 2190 */ 2191void 2192DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, 2193 InternalEvent *ev, XID resource) 2194{ 2195 int i; 2196 2197 if (ev->any.type == ET_TouchBegin && 2198 !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING))) 2199 TouchSetupListeners(dev, ti, ev); 2200 2201 TouchEventHistoryPush(ti, &ev->device_event); 2202 2203 for (i = 0; i < ti->num_listeners; i++) { 2204 GrabPtr grab = NULL; 2205 ClientPtr client; 2206 WindowPtr win; 2207 XI2Mask *mask; 2208 TouchListener *listener = &ti->listeners[i]; 2209 2210 if (resource && listener->listener != resource) 2211 continue; 2212 2213 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win, 2214 &grab, &mask)) 2215 continue; 2216 2217 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask); 2218 } 2219} 2220 2221/** 2222 * Attempts to deliver a gesture event to the given client. 2223 */ 2224static Bool 2225DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi, 2226 GrabPtr grab, WindowPtr win, InternalEvent *ev) 2227{ 2228 int err; 2229 xEvent *xi2; 2230 Mask filter; 2231 Window child = DeepestSpriteWin(&gi->sprite)->drawable.id; 2232 2233 /* If we fail here, we're going to leave a client hanging. */ 2234 err = EventToXI2(ev, &xi2); 2235 if (err != Success) 2236 FatalError("[Xi] %s: XI2 conversion failed in %s" 2237 " (%d)\n", dev->name, __func__, err); 2238 2239 FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE); 2240 filter = GetEventFilter(dev, xi2); 2241 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) 2242 return FALSE; 2243 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); 2244 free(xi2); 2245 2246 /* Returning the value from TryClientEvents isn't useful, since all our 2247 * resource-gone cleanups will update the delivery list anyway. */ 2248 return TRUE; 2249} 2250 2251/** 2252 * Given a gesture event and a potential listener, retrieve info needed for processing the event. 2253 * 2254 * @param dev The device generating the gesture event. 2255 * @param ev The gesture event to process. 2256 * @param listener The gesture event listener that may receive the gesture event. 2257 * @param[out] client The client that should receive the gesture event. 2258 * @param[out] win The window to deliver the event on. 2259 * @param[out] grab The grab to deliver the event through, if any. 2260 * @return TRUE if an event should be delivered to the listener, FALSE 2261 * otherwise. 2262 */ 2263static Bool 2264RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener, 2265 ClientPtr *client, WindowPtr *win, GrabPtr *grab) 2266{ 2267 int rc; 2268 int evtype; 2269 InputClients *iclients = NULL; 2270 *grab = NULL; 2271 2272 if (listener->type == GESTURE_LISTENER_GRAB || 2273 listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2274 *grab = listener->grab; 2275 2276 BUG_RETURN_VAL(!*grab, FALSE); 2277 2278 *client = rClient(*grab); 2279 *win = (*grab)->window; 2280 } 2281 else { 2282 rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type, 2283 serverClient, DixSendAccess); 2284 if (rc != Success) 2285 return FALSE; 2286 2287 /* note that we only will have XI2 listeners as 2288 listener->type == GESTURE_LISTENER_REGULAR */ 2289 evtype = GetXI2Type(ev->any.type); 2290 2291 nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next) 2292 if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 2293 break; 2294 2295 BUG_RETURN_VAL(!iclients, FALSE); 2296 2297 *client = rClient(iclients); 2298 } 2299 2300 return TRUE; 2301} 2302 2303/** 2304 * Delivers a gesture to the owner, if possible and needed. Returns whether 2305 * an event was delivered. 2306 */ 2307Bool 2308DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev) 2309{ 2310 GrabPtr grab = NULL; 2311 ClientPtr client; 2312 WindowPtr win; 2313 2314 if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2315 return 0; 2316 } 2317 2318 if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab)) 2319 return 0; 2320 2321 ev->gesture_event.deviceid = dev->id; 2322 2323 return DeliverOneGestureEvent(client, dev, gi, grab, win, ev); 2324} 2325 2326int 2327InitProximityClassDeviceStruct(DeviceIntPtr dev) 2328{ 2329 ProximityClassPtr proxc; 2330 2331 BUG_RETURN_VAL(dev == NULL, FALSE); 2332 BUG_RETURN_VAL(dev->proximity != NULL, FALSE); 2333 2334 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec)); 2335 if (!proxc) 2336 return FALSE; 2337 proxc->sourceid = dev->id; 2338 proxc->in_proximity = TRUE; 2339 dev->proximity = proxc; 2340 return TRUE; 2341} 2342 2343/** 2344 * Initialise the device's valuators. The memory must already be allocated, 2345 * this function merely inits the matching axis (specified through axnum) to 2346 * sane values. 2347 * 2348 * It is a condition that (minval < maxval). 2349 * 2350 * @see InitValuatorClassDeviceStruct 2351 */ 2352Bool 2353InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 2354 int maxval, int resolution, int min_res, int max_res, 2355 int mode) 2356{ 2357 AxisInfoPtr ax; 2358 2359 BUG_RETURN_VAL(dev == NULL, FALSE); 2360 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2361 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2362 BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE); 2363 2364 ax = dev->valuator->axes + axnum; 2365 2366 ax->min_value = minval; 2367 ax->max_value = maxval; 2368 ax->resolution = resolution; 2369 ax->min_resolution = min_res; 2370 ax->max_resolution = max_res; 2371 ax->label = label; 2372 ax->mode = mode; 2373 2374 if (mode & OutOfProximity) 2375 dev->proximity->in_proximity = FALSE; 2376 2377 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE); 2378} 2379 2380/** 2381 * Set the given axis number as a scrolling valuator. 2382 */ 2383Bool 2384SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, 2385 double increment, int flags) 2386{ 2387 AxisInfoPtr ax; 2388 int *current_ax; 2389 InternalEvent dce; 2390 DeviceIntPtr master; 2391 2392 BUG_RETURN_VAL(dev == NULL, FALSE); 2393 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2394 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2395 2396 switch (type) { 2397 case SCROLL_TYPE_VERTICAL: 2398 current_ax = &dev->valuator->v_scroll_axis; 2399 break; 2400 case SCROLL_TYPE_HORIZONTAL: 2401 current_ax = &dev->valuator->h_scroll_axis; 2402 break; 2403 case SCROLL_TYPE_NONE: 2404 ax = &dev->valuator->axes[axnum]; 2405 ax->scroll.type = type; 2406 return TRUE; 2407 default: 2408 return FALSE; 2409 } 2410 2411 if (increment == 0.0) 2412 return FALSE; 2413 2414 if (*current_ax != -1 && axnum != *current_ax) { 2415 ax = &dev->valuator->axes[*current_ax]; 2416 if (ax->scroll.type == type && 2417 (flags & SCROLL_FLAG_PREFERRED) && 2418 (ax->scroll.flags & SCROLL_FLAG_PREFERRED)) 2419 return FALSE; 2420 } 2421 *current_ax = axnum; 2422 2423 ax = &dev->valuator->axes[axnum]; 2424 ax->scroll.type = type; 2425 ax->scroll.increment = increment; 2426 ax->scroll.flags = flags; 2427 2428 master = GetMaster(dev, MASTER_ATTACHED); 2429 CreateClassesChangedEvent(&dce, master, dev, 2430 DEVCHANGE_POINTER_EVENT | 2431 DEVCHANGE_DEVICE_CHANGE); 2432 XISendDeviceChangedEvent(dev, &dce.changed_event); 2433 2434 /* if the current slave is us, update the master. If not, we'll update 2435 * whenever the next slave switch happens anyway. CMDC sends the event 2436 * for us */ 2437 if (master && master->lastSlave == dev) 2438 ChangeMasterDeviceClasses(master, &dce.changed_event); 2439 2440 return TRUE; 2441} 2442 2443int 2444CheckGrabValues(ClientPtr client, GrabParameters *param) 2445{ 2446 if (param->grabtype != CORE && 2447 param->grabtype != XI && param->grabtype != XI2) { 2448 ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); 2449 return BadImplementation; 2450 } 2451 2452 if ((param->this_device_mode != GrabModeSync) && 2453 (param->this_device_mode != GrabModeAsync) && 2454 (param->this_device_mode != XIGrabModeTouch)) { 2455 client->errorValue = param->this_device_mode; 2456 return BadValue; 2457 } 2458 if ((param->other_devices_mode != GrabModeSync) && 2459 (param->other_devices_mode != GrabModeAsync) && 2460 (param->other_devices_mode != XIGrabModeTouch)) { 2461 client->errorValue = param->other_devices_mode; 2462 return BadValue; 2463 } 2464 2465 if (param->modifiers != AnyModifier && 2466 param->modifiers != XIAnyModifier && 2467 (param->modifiers & ~AllModifiersMask)) { 2468 client->errorValue = param->modifiers; 2469 return BadValue; 2470 } 2471 2472 if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { 2473 client->errorValue = param->ownerEvents; 2474 return BadValue; 2475 } 2476 return Success; 2477} 2478 2479int 2480GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2481 int button, GrabParameters *param, enum InputLevel grabtype, 2482 GrabMask *mask) 2483{ 2484 WindowPtr pWin, confineTo; 2485 CursorPtr cursor; 2486 GrabPtr grab; 2487 int rc, type = -1; 2488 Mask access_mode = DixGrabAccess; 2489 2490 rc = CheckGrabValues(client, param); 2491 if (rc != Success) 2492 return rc; 2493 if (param->confineTo == None) 2494 confineTo = NullWindow; 2495 else { 2496 rc = dixLookupWindow(&confineTo, param->confineTo, client, 2497 DixSetAttrAccess); 2498 if (rc != Success) 2499 return rc; 2500 } 2501 if (param->cursor == None) 2502 cursor = NullCursor; 2503 else { 2504 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2505 RT_CURSOR, client, DixUseAccess); 2506 if (rc != Success) { 2507 client->errorValue = param->cursor; 2508 return rc; 2509 } 2510 access_mode |= DixForceAccess; 2511 } 2512 if (param->this_device_mode == GrabModeSync || 2513 param->other_devices_mode == GrabModeSync) 2514 access_mode |= DixFreezeAccess; 2515 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2516 if (rc != Success) 2517 return rc; 2518 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2519 if (rc != Success) 2520 return rc; 2521 2522 if (grabtype == XI) 2523 type = DeviceButtonPress; 2524 else if (grabtype == XI2) 2525 type = XI_ButtonPress; 2526 2527 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2528 mask, param, type, button, confineTo, cursor); 2529 if (!grab) 2530 return BadAlloc; 2531 return AddPassiveGrabToList(client, grab); 2532} 2533 2534/** 2535 * Grab the given key. 2536 */ 2537int 2538GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2539 int key, GrabParameters *param, enum InputLevel grabtype, 2540 GrabMask *mask) 2541{ 2542 WindowPtr pWin; 2543 GrabPtr grab; 2544 KeyClassPtr k = dev->key; 2545 Mask access_mode = DixGrabAccess; 2546 int rc, type = -1; 2547 2548 rc = CheckGrabValues(client, param); 2549 if (rc != Success) 2550 return rc; 2551 if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL) 2552 return BadMatch; 2553 if (grabtype == XI) { 2554 if ((key > k->xkbInfo->desc->max_key_code || 2555 key < k->xkbInfo->desc->min_key_code) 2556 && (key != AnyKey)) { 2557 client->errorValue = key; 2558 return BadValue; 2559 } 2560 type = DeviceKeyPress; 2561 } 2562 else if (grabtype == XI2) 2563 type = XI_KeyPress; 2564 2565 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2566 if (rc != Success) 2567 return rc; 2568 if (param->this_device_mode == GrabModeSync || 2569 param->other_devices_mode == GrabModeSync) 2570 access_mode |= DixFreezeAccess; 2571 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2572 if (rc != Success) 2573 return rc; 2574 2575 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2576 mask, param, type, key, NULL, NULL); 2577 if (!grab) 2578 return BadAlloc; 2579 return AddPassiveGrabToList(client, grab); 2580} 2581 2582/* Enter/FocusIn grab */ 2583int 2584GrabWindow(ClientPtr client, DeviceIntPtr dev, int type, 2585 GrabParameters *param, GrabMask *mask) 2586{ 2587 WindowPtr pWin; 2588 CursorPtr cursor; 2589 GrabPtr grab; 2590 Mask access_mode = DixGrabAccess; 2591 int rc; 2592 2593 rc = CheckGrabValues(client, param); 2594 if (rc != Success) 2595 return rc; 2596 2597 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2598 if (rc != Success) 2599 return rc; 2600 if (param->cursor == None) 2601 cursor = NullCursor; 2602 else { 2603 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2604 RT_CURSOR, client, DixUseAccess); 2605 if (rc != Success) { 2606 client->errorValue = param->cursor; 2607 return rc; 2608 } 2609 access_mode |= DixForceAccess; 2610 } 2611 if (param->this_device_mode == GrabModeSync || 2612 param->other_devices_mode == GrabModeSync) 2613 access_mode |= DixFreezeAccess; 2614 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2615 if (rc != Success) 2616 return rc; 2617 2618 grab = CreateGrab(client->index, dev, dev, pWin, XI2, 2619 mask, param, 2620 (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0, 2621 NULL, cursor); 2622 2623 if (!grab) 2624 return BadAlloc; 2625 2626 return AddPassiveGrabToList(client, grab); 2627} 2628 2629/* Touch grab */ 2630int 2631GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev, 2632 int type, GrabParameters *param, GrabMask *mask) 2633{ 2634 WindowPtr pWin; 2635 GrabPtr grab; 2636 int rc; 2637 2638 rc = CheckGrabValues(client, param); 2639 if (rc != Success) 2640 return rc; 2641 2642 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2643 if (rc != Success) 2644 return rc; 2645 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess); 2646 if (rc != Success) 2647 return rc; 2648 2649 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2, 2650 mask, param, type, 0, NullWindow, NullCursor); 2651 if (!grab) 2652 return BadAlloc; 2653 2654 return AddPassiveGrabToList(client, grab); 2655} 2656 2657int 2658SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 2659 Mask mask, Mask exclusivemasks) 2660{ 2661 int mskidx = dev->id; 2662 int i, ret; 2663 Mask check; 2664 InputClientsPtr others; 2665 2666 check = (mask & exclusivemasks); 2667 if (wOtherInputMasks(pWin)) { 2668 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { 2669 /* It is illegal for two different clients to select on any of 2670 * the events for maskcheck. However, it is OK, for some client 2671 * to continue selecting on one of those events. 2672 */ 2673 for (others = wOtherInputMasks(pWin)->inputClients; others; 2674 others = others->next) { 2675 if (!SameClient(others, client) && (check & 2676 others->mask[mskidx])) 2677 return BadAccess; 2678 } 2679 } 2680 for (others = wOtherInputMasks(pWin)->inputClients; others; 2681 others = others->next) { 2682 if (SameClient(others, client)) { 2683 check = others->mask[mskidx]; 2684 others->mask[mskidx] = mask; 2685 if (mask == 0) { 2686 for (i = 0; i < EMASKSIZE; i++) 2687 if (i != mskidx && others->mask[i] != 0) 2688 break; 2689 if (i == EMASKSIZE) { 2690 RecalculateDeviceDeliverableEvents(pWin); 2691 if (ShouldFreeInputMasks(pWin, FALSE)) 2692 FreeResource(others->resource, RT_NONE); 2693 return Success; 2694 } 2695 } 2696 goto maskSet; 2697 } 2698 } 2699 } 2700 check = 0; 2701 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 2702 return ret; 2703 maskSet: 2704 if (dev->valuator) 2705 if ((dev->valuator->motionHintWindow == pWin) && 2706 (mask & DevicePointerMotionHintMask) && 2707 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) 2708 dev->valuator->motionHintWindow = NullWindow; 2709 RecalculateDeviceDeliverableEvents(pWin); 2710 return Success; 2711} 2712 2713static void 2714FreeInputClient(InputClientsPtr * other) 2715{ 2716 xi2mask_free(&(*other)->xi2mask); 2717 free(*other); 2718 *other = NULL; 2719} 2720 2721static InputClientsPtr 2722AllocInputClient(void) 2723{ 2724 return calloc(1, sizeof(InputClients)); 2725} 2726 2727int 2728AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 2729{ 2730 InputClientsPtr others; 2731 2732 if (!pWin->optional && !MakeWindowOptional(pWin)) 2733 return BadAlloc; 2734 others = AllocInputClient(); 2735 if (!others) 2736 return BadAlloc; 2737 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 2738 goto bail; 2739 others->xi2mask = xi2mask_new(); 2740 if (!others->xi2mask) 2741 goto bail; 2742 others->mask[mskidx] = mask; 2743 others->resource = FakeClientID(client->index); 2744 others->next = pWin->optional->inputMasks->inputClients; 2745 pWin->optional->inputMasks->inputClients = others; 2746 if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin)) 2747 goto bail; 2748 return Success; 2749 2750 bail: 2751 FreeInputClient(&others); 2752 return BadAlloc; 2753} 2754 2755static Bool 2756MakeInputMasks(WindowPtr pWin) 2757{ 2758 struct _OtherInputMasks *imasks; 2759 2760 imasks = calloc(1, sizeof(struct _OtherInputMasks)); 2761 if (!imasks) 2762 return FALSE; 2763 imasks->xi2mask = xi2mask_new(); 2764 if (!imasks->xi2mask) { 2765 free(imasks); 2766 return FALSE; 2767 } 2768 pWin->optional->inputMasks = imasks; 2769 return TRUE; 2770} 2771 2772static void 2773FreeInputMask(OtherInputMasks ** imask) 2774{ 2775 xi2mask_free(&(*imask)->xi2mask); 2776 free(*imask); 2777 *imask = NULL; 2778} 2779 2780#define XIPropagateMask (KeyPressMask | \ 2781 KeyReleaseMask | \ 2782 ButtonPressMask | \ 2783 ButtonReleaseMask | \ 2784 PointerMotionMask) 2785 2786void 2787RecalculateDeviceDeliverableEvents(WindowPtr pWin) 2788{ 2789 InputClientsPtr others; 2790 struct _OtherInputMasks *inputMasks; /* default: NULL */ 2791 WindowPtr pChild, tmp; 2792 int i; 2793 2794 pChild = pWin; 2795 while (1) { 2796 if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 2797 xi2mask_zero(inputMasks->xi2mask, -1); 2798 for (others = inputMasks->inputClients; others; 2799 others = others->next) { 2800 for (i = 0; i < EMASKSIZE; i++) 2801 inputMasks->inputEvents[i] |= others->mask[i]; 2802 xi2mask_merge(inputMasks->xi2mask, others->xi2mask); 2803 } 2804 for (i = 0; i < EMASKSIZE; i++) 2805 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 2806 for (tmp = pChild->parent; tmp; tmp = tmp->parent) 2807 if (wOtherInputMasks(tmp)) 2808 for (i = 0; i < EMASKSIZE; i++) 2809 inputMasks->deliverableEvents[i] |= 2810 (wOtherInputMasks(tmp)->deliverableEvents[i] 2811 & ~inputMasks->dontPropagateMask[i] & 2812 XIPropagateMask); 2813 } 2814 if (pChild->firstChild) { 2815 pChild = pChild->firstChild; 2816 continue; 2817 } 2818 while (!pChild->nextSib && (pChild != pWin)) 2819 pChild = pChild->parent; 2820 if (pChild == pWin) 2821 break; 2822 pChild = pChild->nextSib; 2823 } 2824} 2825 2826int 2827InputClientGone(WindowPtr pWin, XID id) 2828{ 2829 InputClientsPtr other, prev; 2830 2831 if (!wOtherInputMasks(pWin)) 2832 return Success; 2833 prev = 0; 2834 for (other = wOtherInputMasks(pWin)->inputClients; other; 2835 other = other->next) { 2836 if (other->resource == id) { 2837 if (prev) { 2838 prev->next = other->next; 2839 FreeInputClient(&other); 2840 } 2841 else if (!(other->next)) { 2842 if (ShouldFreeInputMasks(pWin, TRUE)) { 2843 OtherInputMasks *mask = wOtherInputMasks(pWin); 2844 2845 mask->inputClients = other->next; 2846 FreeInputMask(&mask); 2847 pWin->optional->inputMasks = (OtherInputMasks *) NULL; 2848 CheckWindowOptionalNeed(pWin); 2849 FreeInputClient(&other); 2850 } 2851 else { 2852 other->resource = FakeClientID(0); 2853 if (!AddResource(other->resource, RT_INPUTCLIENT, 2854 (void *) pWin)) 2855 return BadAlloc; 2856 } 2857 } 2858 else { 2859 wOtherInputMasks(pWin)->inputClients = other->next; 2860 FreeInputClient(&other); 2861 } 2862 RecalculateDeviceDeliverableEvents(pWin); 2863 return Success; 2864 } 2865 prev = other; 2866 } 2867 FatalError("client not on device event list"); 2868} 2869 2870/** 2871 * Search for window in each touch trace for each device. Remove the window 2872 * and all its subwindows from the trace when found. The initial window 2873 * order is preserved. 2874 */ 2875void 2876WindowGone(WindowPtr win) 2877{ 2878 DeviceIntPtr dev; 2879 2880 for (dev = inputInfo.devices; dev; dev = dev->next) { 2881 TouchClassPtr t = dev->touch; 2882 int i; 2883 2884 if (!t) 2885 continue; 2886 2887 for (i = 0; i < t->num_touches; i++) { 2888 SpritePtr sprite = &t->touches[i].sprite; 2889 int j; 2890 2891 for (j = 0; j < sprite->spriteTraceGood; j++) { 2892 if (sprite->spriteTrace[j] == win) { 2893 sprite->spriteTraceGood = j; 2894 break; 2895 } 2896 } 2897 } 2898 } 2899} 2900 2901int 2902SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 2903 xEvent *ev, Mask mask, int count) 2904{ 2905 WindowPtr pWin; 2906 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 2907 WindowPtr spriteWin = GetSpriteWindow(d); 2908 2909 if (dest == PointerWindow) 2910 pWin = spriteWin; 2911 else if (dest == InputFocus) { 2912 WindowPtr inputFocus; 2913 2914 if (!d->focus) 2915 inputFocus = spriteWin; 2916 else 2917 inputFocus = d->focus->win; 2918 2919 if (inputFocus == FollowKeyboardWin) 2920 inputFocus = inputInfo.keyboard->focus->win; 2921 2922 if (inputFocus == NoneWin) 2923 return Success; 2924 2925 /* If the input focus is PointerRootWin, send the event to where 2926 * the pointer is if possible, then perhaps propagate up to root. */ 2927 if (inputFocus == PointerRootWin) 2928 inputFocus = GetCurrentRootWindow(d); 2929 2930 if (IsParent(inputFocus, spriteWin)) { 2931 effectiveFocus = inputFocus; 2932 pWin = spriteWin; 2933 } 2934 else 2935 effectiveFocus = pWin = inputFocus; 2936 } 2937 else 2938 dixLookupWindow(&pWin, dest, client, DixSendAccess); 2939 if (!pWin) 2940 return BadWindow; 2941 if ((propagate != xFalse) && (propagate != xTrue)) { 2942 client->errorValue = propagate; 2943 return BadValue; 2944 } 2945 ev->u.u.type |= 0x80; 2946 if (propagate) { 2947 for (; pWin; pWin = pWin->parent) { 2948 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) 2949 return Success; 2950 if (pWin == effectiveFocus) 2951 return Success; 2952 if (wOtherInputMasks(pWin)) 2953 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 2954 if (!mask) 2955 break; 2956 } 2957 } 2958 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) 2959 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); 2960 return Success; 2961} 2962 2963int 2964SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 2965{ 2966 int i; 2967 ButtonClassPtr b = dev->button; 2968 2969 if (b == NULL) 2970 return BadMatch; 2971 2972 if (nElts != b->numButtons) { 2973 client->errorValue = nElts; 2974 return BadValue; 2975 } 2976 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 2977 return BadValue; 2978 for (i = 0; i < nElts; i++) 2979 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 2980 return MappingBusy; 2981 for (i = 0; i < nElts; i++) 2982 b->map[i + 1] = map[i]; 2983 return Success; 2984} 2985 2986int 2987ChangeKeyMapping(ClientPtr client, 2988 DeviceIntPtr dev, 2989 unsigned len, 2990 int type, 2991 KeyCode firstKeyCode, 2992 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 2993{ 2994 KeySymsRec keysyms; 2995 KeyClassPtr k = dev->key; 2996 2997 if (k == NULL) 2998 return BadMatch; 2999 3000 if (len != (keyCodes * keySymsPerKeyCode)) 3001 return BadLength; 3002 3003 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || 3004 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { 3005 client->errorValue = firstKeyCode; 3006 return BadValue; 3007 } 3008 if (keySymsPerKeyCode == 0) { 3009 client->errorValue = 0; 3010 return BadValue; 3011 } 3012 keysyms.minKeyCode = firstKeyCode; 3013 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 3014 keysyms.mapWidth = keySymsPerKeyCode; 3015 keysyms.map = map; 3016 3017 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, 3018 serverClient); 3019 3020 return Success; 3021} 3022 3023static void 3024DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 3025{ 3026 WindowPtr parent; 3027 3028 /* Deactivate any grabs performed on this window, before making 3029 * any input focus changes. 3030 * Deactivating a device grab should cause focus events. */ 3031 3032 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) 3033 (*dev->deviceGrab.DeactivateGrab) (dev); 3034 3035 /* If the focus window is a root window (ie. has no parent) 3036 * then don't delete the focus from it. */ 3037 3038 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 3039 int focusEventMode = NotifyNormal; 3040 3041 /* If a grab is in progress, then alter the mode of focus events. */ 3042 3043 if (dev->deviceGrab.grab) 3044 focusEventMode = NotifyWhileGrabbed; 3045 3046 switch (dev->focus->revert) { 3047 case RevertToNone: 3048 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 3049 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 3050 dev->focus->win = NoneWin; 3051 dev->focus->traceGood = 0; 3052 break; 3053 case RevertToParent: 3054 parent = pWin; 3055 do { 3056 parent = parent->parent; 3057 dev->focus->traceGood--; 3058 } 3059 while (!parent->realized); 3060 if (!ActivateFocusInGrab(dev, pWin, parent)) 3061 DoFocusEvents(dev, pWin, parent, focusEventMode); 3062 dev->focus->win = parent; 3063 dev->focus->revert = RevertToNone; 3064 break; 3065 case RevertToPointerRoot: 3066 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) 3067 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 3068 dev->focus->win = PointerRootWin; 3069 dev->focus->traceGood = 0; 3070 break; 3071 case RevertToFollowKeyboard: 3072 { 3073 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 3074 3075 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) 3076 kbd = inputInfo.keyboard; 3077 if (kbd->focus->win) { 3078 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) 3079 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); 3080 dev->focus->win = FollowKeyboardWin; 3081 dev->focus->traceGood = 0; 3082 } 3083 else { 3084 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 3085 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 3086 dev->focus->win = NoneWin; 3087 dev->focus->traceGood = 0; 3088 } 3089 } 3090 break; 3091 } 3092 } 3093 3094 if (dev->valuator) 3095 if (dev->valuator->motionHintWindow == pWin) 3096 dev->valuator->motionHintWindow = NullWindow; 3097} 3098 3099void 3100DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 3101{ 3102 int i; 3103 DeviceIntPtr dev; 3104 InputClientsPtr ic; 3105 struct _OtherInputMasks *inputMasks; 3106 3107 for (dev = inputInfo.devices; dev; dev = dev->next) { 3108 DeleteDeviceFromAnyExtEvents(pWin, dev); 3109 } 3110 3111 for (dev = inputInfo.off_devices; dev; dev = dev->next) 3112 DeleteDeviceFromAnyExtEvents(pWin, dev); 3113 3114 if (freeResources) 3115 while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 3116 ic = inputMasks->inputClients; 3117 for (i = 0; i < EMASKSIZE; i++) 3118 inputMasks->dontPropagateMask[i] = 0; 3119 FreeResource(ic->resource, RT_NONE); 3120 } 3121} 3122 3123int 3124MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask) 3125{ 3126 DeviceIntPtr dev; 3127 3128 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient, 3129 DixReadAccess); 3130 if (!dev) 3131 return 0; 3132 3133 if (pEvents->type == DeviceMotionNotify) { 3134 if (mask & DevicePointerMotionHintMask) { 3135 if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 3136 return 1; /* don't send, but pretend we did */ 3137 } 3138 pEvents->detail = NotifyHint; 3139 } 3140 else { 3141 pEvents->detail = NotifyNormal; 3142 } 3143 } 3144 return 0; 3145} 3146 3147void 3148CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 3149 deviceKeyButtonPointer *xE, GrabPtr grab, 3150 ClientPtr client, Mask deliveryMask) 3151{ 3152 DeviceIntPtr dev; 3153 3154 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, 3155 DixGrabAccess); 3156 if (!dev) 3157 return; 3158 3159 if (type == DeviceMotionNotify) 3160 dev->valuator->motionHintWindow = pWin; 3161 else if ((type == DeviceButtonPress) && (!grab) && 3162 (deliveryMask & DeviceButtonGrabMask)) { 3163 GrabPtr tempGrab; 3164 3165 tempGrab = AllocGrab(NULL); 3166 if (!tempGrab) 3167 return; 3168 3169 tempGrab->device = dev; 3170 tempGrab->resource = client->clientAsMask; 3171 tempGrab->window = pWin; 3172 tempGrab->ownerEvents = 3173 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 3174 tempGrab->eventMask = deliveryMask; 3175 tempGrab->keyboardMode = GrabModeAsync; 3176 tempGrab->pointerMode = GrabModeAsync; 3177 tempGrab->confineTo = NullWindow; 3178 tempGrab->cursor = NullCursor; 3179 tempGrab->next = NULL; 3180 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE); 3181 FreeGrab(tempGrab); 3182 } 3183} 3184 3185static Mask 3186DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 3187{ 3188 InputClientsPtr other; 3189 3190 if (!wOtherInputMasks(pWin)) 3191 return 0; 3192 for (other = wOtherInputMasks(pWin)->inputClients; other; 3193 other = other->next) { 3194 if (SameClient(other, client)) 3195 return other->mask[dev->id]; 3196 } 3197 return 0; 3198} 3199 3200void 3201MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 3202{ 3203 WindowPtr pWin; 3204 GrabPtr grab = dev->deviceGrab.grab; 3205 3206 pWin = dev->valuator->motionHintWindow; 3207 3208 if ((grab && SameClient(grab, client) && 3209 ((grab->eventMask & DevicePointerMotionHintMask) || 3210 (grab->ownerEvents && 3211 (DeviceEventMaskForClient(dev, pWin, client) & 3212 DevicePointerMotionHintMask)))) || 3213 (!grab && 3214 (DeviceEventMaskForClient(dev, pWin, client) & 3215 DevicePointerMotionHintMask))) 3216 dev->valuator->motionHintWindow = NullWindow; 3217} 3218 3219int 3220DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 3221 int maskndx) 3222{ 3223 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 3224 3225 if (mask & ~XIPropagateMask) { 3226 client->errorValue = mask; 3227 return BadValue; 3228 } 3229 3230 if (mask == 0) { 3231 if (inputMasks) 3232 inputMasks->dontPropagateMask[maskndx] = mask; 3233 } 3234 else { 3235 if (!inputMasks) 3236 AddExtensionClient(pWin, client, 0, 0); 3237 inputMasks = wOtherInputMasks(pWin); 3238 inputMasks->dontPropagateMask[maskndx] = mask; 3239 } 3240 RecalculateDeviceDeliverableEvents(pWin); 3241 if (ShouldFreeInputMasks(pWin, FALSE)) 3242 FreeResource(inputMasks->inputClients->resource, RT_NONE); 3243 return Success; 3244} 3245 3246Bool 3247ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 3248{ 3249 int i; 3250 Mask allInputEventMasks = 0; 3251 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 3252 3253 for (i = 0; i < EMASKSIZE; i++) 3254 allInputEventMasks |= inputMasks->dontPropagateMask[i]; 3255 if (!ignoreSelectedEvents) 3256 for (i = 0; i < EMASKSIZE; i++) 3257 allInputEventMasks |= inputMasks->inputEvents[i]; 3258 if (allInputEventMasks == 0) 3259 return TRUE; 3260 else 3261 return FALSE; 3262} 3263 3264/*********************************************************************** 3265 * 3266 * Walk through the window tree, finding all clients that want to know 3267 * about the Event. 3268 * 3269 */ 3270 3271static void 3272FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 3273 xEvent *ev, int count) 3274{ 3275 WindowPtr p2; 3276 3277 while (p1) { 3278 p2 = p1->firstChild; 3279 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); 3280 FindInterestedChildren(dev, p2, mask, ev, count); 3281 p1 = p1->nextSib; 3282 } 3283} 3284 3285/*********************************************************************** 3286 * 3287 * Send an event to interested clients in all windows on all screens. 3288 * 3289 */ 3290 3291void 3292SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count) 3293{ 3294 int i; 3295 WindowPtr pWin, p1; 3296 3297 for (i = 0; i < screenInfo.numScreens; i++) { 3298 pWin = screenInfo.screens[i]->root; 3299 if (!pWin) 3300 continue; 3301 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); 3302 p1 = pWin->firstChild; 3303 FindInterestedChildren(dev, p1, mask, ev, count); 3304 } 3305} 3306 3307/** 3308 * Set the XI2 mask for the given client on the given window. 3309 * @param dev The device to set the mask for. 3310 * @param win The window to set the mask on. 3311 * @param client The client setting the mask. 3312 * @param len Number of bytes in mask. 3313 * @param mask Event mask in the form of (1 << eventtype) 3314 */ 3315int 3316XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 3317 unsigned int len, unsigned char *mask) 3318{ 3319 OtherInputMasks *masks; 3320 InputClientsPtr others = NULL; 3321 3322 masks = wOtherInputMasks(win); 3323 if (masks) { 3324 for (others = wOtherInputMasks(win)->inputClients; others; 3325 others = others->next) { 3326 if (SameClient(others, client)) { 3327 xi2mask_zero(others->xi2mask, dev->id); 3328 break; 3329 } 3330 } 3331 } 3332 3333 if (len && !others) { 3334 if (AddExtensionClient(win, client, 0, 0) != Success) 3335 return BadAlloc; 3336 others = wOtherInputMasks(win)->inputClients; 3337 } 3338 3339 if (others) { 3340 xi2mask_zero(others->xi2mask, dev->id); 3341 len = min(len, xi2mask_mask_size(others->xi2mask)); 3342 } 3343 3344 if (len) { 3345 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len); 3346 } 3347 3348 RecalculateDeviceDeliverableEvents(win); 3349 3350 return Success; 3351} 3352