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