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