exevents.c revision 25da500f
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 *grab = NULL; 1297 1298 if (listener->type == LISTENER_GRAB || 1299 listener->type == LISTENER_POINTER_GRAB) { 1300 *grab = listener->grab; 1301 1302 BUG_RETURN_VAL(!*grab, FALSE); 1303 } 1304 else if (ti->emulate_pointer && dev->deviceGrab.grab && 1305 !dev->deviceGrab.fromPassiveGrab) { 1306 /* There may be an active pointer grab on the device */ 1307 *grab = dev->deviceGrab.grab; 1308 } 1309 1310 if (*grab) { 1311 *client = rClient(*grab); 1312 *win = (*grab)->window; 1313 *mask = (*grab)->xi2mask; 1314 } 1315 else { 1316 rc = dixLookupResourceByType((void **) win, listener->listener, 1317 listener->resource_type, 1318 serverClient, DixSendAccess); 1319 if (rc != Success) 1320 return FALSE; 1321 1322 if (listener->level == XI2) { 1323 int evtype; 1324 1325 if (ti->emulate_pointer && 1326 listener->type == LISTENER_POINTER_REGULAR) 1327 evtype = GetXI2Type(TouchGetPointerEventType(ev)); 1328 else 1329 evtype = GetXI2Type(ev->any.type); 1330 1331 nt_list_for_each_entry(iclients, 1332 wOtherInputMasks(*win)->inputClients, next) 1333 if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 1334 break; 1335 1336 BUG_RETURN_VAL(!iclients, FALSE); 1337 1338 *mask = iclients->xi2mask; 1339 *client = rClient(iclients); 1340 } 1341 else if (listener->level == XI) { 1342 int xi_type = GetXIType(TouchGetPointerEventType(ev)); 1343 Mask xi_filter = event_get_filter_from_type(dev, xi_type); 1344 1345 nt_list_for_each_entry(iclients, 1346 wOtherInputMasks(*win)->inputClients, next) 1347 if (iclients->mask[dev->id] & xi_filter) 1348 break; 1349 BUG_RETURN_VAL(!iclients, FALSE); 1350 1351 *client = rClient(iclients); 1352 } 1353 else { 1354 int coretype = GetCoreType(TouchGetPointerEventType(ev)); 1355 Mask core_filter = event_get_filter_from_type(dev, coretype); 1356 OtherClients *oclients; 1357 1358 /* all others */ 1359 nt_list_for_each_entry(oclients, 1360 (OtherClients *) wOtherClients(*win), next) 1361 if (oclients->mask & core_filter) 1362 break; 1363 1364 /* if owner selected, oclients is NULL */ 1365 *client = oclients ? rClient(oclients) : wClient(*win); 1366 } 1367 } 1368 1369 return TRUE; 1370} 1371 1372static int 1373DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1374 InternalEvent *ev, TouchListener * listener, 1375 ClientPtr client, WindowPtr win, GrabPtr grab, 1376 XI2Mask *xi2mask) 1377{ 1378 InternalEvent motion, button; 1379 InternalEvent *ptrev = &motion; 1380 int nevents; 1381 DeviceIntPtr kbd; 1382 1383 /* We don't deliver pointer events to non-owners */ 1384 if (!TouchResourceIsOwner(ti, listener->listener)) 1385 return !Success; 1386 1387 if (!ti->emulate_pointer) 1388 return !Success; 1389 1390 nevents = TouchConvertToPointerEvent(ev, &motion, &button); 1391 BUG_RETURN_VAL(nevents == 0, BadValue); 1392 1393 if (nevents > 1) 1394 ptrev = &button; 1395 1396 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1397 event_set_state(dev, kbd, &ptrev->device_event); 1398 ptrev->device_event.corestate = event_get_corestate(dev, kbd); 1399 1400 if (grab) { 1401 /* this side-steps the usual activation mechanisms, but... */ 1402 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) 1403 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */ 1404 else { 1405 int deliveries = 0; 1406 1407 /* 'grab' is the passive grab, but if the grab isn't active, 1408 * don't deliver */ 1409 if (!dev->deviceGrab.grab) 1410 return !Success; 1411 1412 if (grab->ownerEvents) { 1413 WindowPtr focus = NullWindow; 1414 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1415 1416 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev); 1417 } 1418 1419 if (!deliveries) 1420 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); 1421 1422 /* We must accept the touch sequence once a pointer listener has 1423 * received one event past ButtonPress. */ 1424 if (deliveries && ev->any.type != ET_TouchBegin && 1425 !(ev->device_event.flags & TOUCH_CLIENT_ID)) 1426 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1427 1428 if (ev->any.type == ET_TouchEnd && 1429 ti->num_listeners == 1 && 1430 !dev->button->buttonsDown && 1431 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { 1432 (*dev->deviceGrab.DeactivateGrab) (dev); 1433 CheckOldestTouch(dev); 1434 return Success; 1435 } 1436 } 1437 } 1438 else { 1439 GrabPtr devgrab = dev->deviceGrab.grab; 1440 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 1441 1442 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev); 1443 /* FIXME: bad hack 1444 * Implicit passive grab activated in response to this event. Store 1445 * the event. 1446 */ 1447 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { 1448 TouchListener *l; 1449 GrabPtr g; 1450 1451 devgrab = dev->deviceGrab.grab; 1452 g = AllocGrab(devgrab); 1453 BUG_WARN(!g); 1454 1455 *dev->deviceGrab.sync.event = ev->device_event; 1456 1457 /* The listener array has a sequence of grabs and then one event 1458 * selection. Implicit grab activation occurs through delivering an 1459 * event selection. Thus, we update the last listener in the array. 1460 */ 1461 l = &ti->listeners[ti->num_listeners - 1]; 1462 l->listener = g->resource; 1463 l->grab = g; 1464 //l->resource_type = RT_NONE; 1465 1466 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) 1467 l->type = LISTENER_POINTER_GRAB; 1468 else 1469 l->type = LISTENER_GRAB; 1470 } 1471 1472 } 1473 if (ev->any.type == ET_TouchBegin) 1474 listener->state = LISTENER_IS_OWNER; 1475 else if (ev->any.type == ET_TouchEnd) 1476 listener->state = LISTENER_HAS_END; 1477 1478 return Success; 1479} 1480 1481static void 1482DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1483 InternalEvent *ev) 1484{ 1485 DeviceEvent motion; 1486 1487 if (ti->num_listeners) { 1488 ClientPtr client; 1489 WindowPtr win; 1490 GrabPtr grab; 1491 XI2Mask *mask; 1492 1493 if (ti->listeners[0].type != LISTENER_POINTER_REGULAR && 1494 ti->listeners[0].type != LISTENER_POINTER_GRAB) 1495 return; 1496 1497 motion = ev->device_event; 1498 motion.type = ET_TouchUpdate; 1499 motion.detail.button = 0; 1500 1501 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion, 1502 &ti->listeners[0], &client, &win, &grab, 1503 &mask)) 1504 return; 1505 1506 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client, 1507 win, grab, mask); 1508 } 1509 else { 1510 InternalEvent button; 1511 int converted; 1512 1513 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button); 1514 1515 BUG_WARN(converted == 0); 1516 if (converted) 1517 ProcessOtherEvent((InternalEvent*)&motion, dev); 1518 } 1519} 1520 1521/** 1522 * Processes and delivers a TouchBegin, TouchUpdate, or a 1523 * TouchEnd event. 1524 * 1525 * Due to having rather different delivery semantics (see the Xi 2.2 protocol 1526 * spec for more information), this implements its own grab and event-selection 1527 * delivery logic. 1528 */ 1529static void 1530ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) 1531{ 1532 TouchClassPtr t = dev->touch; 1533 TouchPointInfoPtr ti; 1534 uint32_t touchid; 1535 int type = ev->any.type; 1536 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED); 1537 DeviceIntPtr kbd; 1538 1539 if (!t) 1540 return; 1541 1542 touchid = ev->device_event.touchid; 1543 1544 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) { 1545 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1546 emulate_pointer); 1547 } 1548 else 1549 ti = TouchFindByClientID(dev, touchid); 1550 1551 /* Active pointer grab */ 1552 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && 1553 (dev->deviceGrab.grab->grabtype == CORE || 1554 dev->deviceGrab.grab->grabtype == XI || 1555 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) 1556 { 1557 /* Active pointer grab on touch point and we get a TouchEnd - claim this 1558 * touchpoint accepted, otherwise clients waiting for ownership will 1559 * wait on this touchpoint until this client ungrabs, or the cows come 1560 * home, whichever is earlier */ 1561 if (ti && type == ET_TouchEnd) 1562 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 1563 else if (!ti && type != ET_TouchBegin) { 1564 /* Under the following circumstances we create a new touch record for an 1565 * existing touch: 1566 * 1567 * - The touch may be pointer emulated 1568 * - An explicit grab is active on the device 1569 * - The grab is a pointer grab 1570 * 1571 * This allows for an explicit grab to receive pointer events for an already 1572 * active touch. 1573 */ 1574 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 1575 emulate_pointer); 1576 if (!ti) { 1577 DebugF("[Xi] %s: Failed to create new dix record for explicitly " 1578 "grabbed touchpoint %d\n", 1579 dev->name, touchid); 1580 return; 1581 } 1582 1583 TouchBuildSprite(dev, ti, ev); 1584 TouchSetupListeners(dev, ti, ev); 1585 } 1586 } 1587 1588 if (!ti) { 1589 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 1590 dev->name, type, touchid); 1591 goto out; 1592 } 1593 1594 /* if emulate_pointer is set, emulate the motion event right 1595 * here, so we can ignore it for button event emulation. TouchUpdate 1596 * events which _only_ emulate motion just work normally */ 1597 if (emulate_pointer && ev->any.type != ET_TouchUpdate) 1598 DeliverEmulatedMotionEvent(dev, ti, ev); 1599 1600 if (emulate_pointer && IsMaster(dev)) 1601 CheckMotion(&ev->device_event, dev); 1602 1603 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1604 event_set_state(NULL, kbd, &ev->device_event); 1605 ev->device_event.corestate = event_get_corestate(NULL, kbd); 1606 1607 /* Make sure we have a valid window trace for event delivery; must be 1608 * called after event type mutation. Touch end events are always processed 1609 * in order to end touch records. */ 1610 /* FIXME: check this */ 1611 if ((type == ET_TouchBegin && 1612 !(ev->device_event.flags & TOUCH_REPLAYING) && 1613 !TouchBuildSprite(dev, ti, ev)) || 1614 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) 1615 return; 1616 1617 TouchCopyValuatorData(&ev->device_event, ti); 1618 /* WARNING: the event type may change to TouchUpdate in 1619 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing 1620 * owner */ 1621 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource); 1622 if (ev->any.type == ET_TouchEnd) 1623 TouchEndTouch(dev, ti); 1624 1625 out: 1626 if (emulate_pointer) 1627 UpdateDeviceState(dev, &ev->device_event); 1628} 1629 1630static void 1631ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev) 1632{ 1633 Mask filter; 1634 WindowPtr pWin; 1635 BarrierEvent *be = &e->barrier_event; 1636 xEvent *ev; 1637 int rc; 1638 GrabPtr grab = dev->deviceGrab.grab; 1639 1640 if (!IsMaster(dev)) 1641 return; 1642 1643 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success) 1644 return; 1645 1646 if (grab) 1647 be->flags |= XIBarrierDeviceIsGrabbed; 1648 1649 rc = EventToXI2(e, &ev); 1650 if (rc != Success) { 1651 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc); 1652 return; 1653 } 1654 1655 /* A client has a grab, deliver to this client if the grab_window is the 1656 barrier window. 1657 1658 Otherwise, deliver normally to the client. 1659 */ 1660 if (grab && 1661 CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) && 1662 grab->window->drawable.id == be->window) { 1663 DeliverGrabbedEvent(e, dev, FALSE); 1664 } else { 1665 filter = GetEventFilter(dev, ev); 1666 1667 DeliverEventsToWindow(dev, pWin, ev, 1, 1668 filter, NullGrab); 1669 } 1670 free(ev); 1671} 1672 1673/** 1674 * Process DeviceEvents and DeviceChangedEvents. 1675 */ 1676static void 1677ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device) 1678{ 1679 GrabPtr grab; 1680 Bool deactivateDeviceGrab = FALSE; 1681 int key = 0, rootX, rootY; 1682 ButtonClassPtr b; 1683 int ret = 0; 1684 int corestate; 1685 DeviceIntPtr mouse = NULL, kbd = NULL; 1686 DeviceEvent *event = &ev->device_event; 1687 1688 if (IsPointerDevice(device)) { 1689 kbd = GetMaster(device, KEYBOARD_OR_FLOAT); 1690 mouse = device; 1691 if (!kbd->key) /* can happen with floating SDs */ 1692 kbd = NULL; 1693 } 1694 else { 1695 mouse = GetMaster(device, POINTER_OR_FLOAT); 1696 kbd = device; 1697 if (!mouse->valuator || !mouse->button) /* may be float. SDs */ 1698 mouse = NULL; 1699 } 1700 1701 corestate = event_get_corestate(mouse, kbd); 1702 event_set_state(mouse, kbd, event); 1703 1704 ret = UpdateDeviceState(device, event); 1705 if (ret == DONT_PROCESS) 1706 return; 1707 1708 b = device->button; 1709 1710 if (IsMaster(device) || IsFloating(device)) 1711 CheckMotion(event, device); 1712 1713 switch (event->type) { 1714 case ET_Motion: 1715 case ET_ButtonPress: 1716 case ET_ButtonRelease: 1717 case ET_KeyPress: 1718 case ET_KeyRelease: 1719 case ET_ProximityIn: 1720 case ET_ProximityOut: 1721 GetSpritePosition(device, &rootX, &rootY); 1722 event->root_x = rootX; 1723 event->root_y = rootY; 1724 NoticeEventTime((InternalEvent *) event, device); 1725 event->corestate = corestate; 1726 key = event->detail.key; 1727 break; 1728 default: 1729 break; 1730 } 1731 1732 /* send KeyPress and KeyRelease events to XACE plugins */ 1733 if (XaceHookIsSet(XACE_KEY_AVAIL) && 1734 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) { 1735 xEvent *core; 1736 int count; 1737 1738 if (EventToCore(ev, &core, &count) == Success && count > 0) { 1739 XaceHook(XACE_KEY_AVAIL, core, device, 0); 1740 free(core); 1741 } 1742 } 1743 1744 if (DeviceEventCallback && !syncEvents.playingEvents) { 1745 DeviceEventInfoRec eventinfo; 1746 SpritePtr pSprite = device->spriteInfo->sprite; 1747 1748 /* see comment in EnqueueEvents regarding the next three lines */ 1749 if (ev->any.type == ET_Motion) 1750 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 1751 1752 eventinfo.device = device; 1753 eventinfo.event = ev; 1754 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 1755 } 1756 1757 grab = device->deviceGrab.grab; 1758 1759 switch (event->type) { 1760 case ET_KeyPress: 1761 /* Don't deliver focus events (e.g. from KeymapNotify when running 1762 * nested) to clients. */ 1763 if (event->source_type == EVENT_SOURCE_FOCUS) 1764 return; 1765 if (!grab && CheckDeviceGrabs(device, event, 0)) 1766 return; 1767 break; 1768 case ET_KeyRelease: 1769 if (grab && device->deviceGrab.fromPassiveGrab && 1770 (key == device->deviceGrab.activatingKey) && 1771 GrabIsKeyboardGrab(device->deviceGrab.grab)) 1772 deactivateDeviceGrab = TRUE; 1773 break; 1774 case ET_ButtonPress: 1775 if (b->map[key] == 0) /* there's no button 0 */ 1776 return; 1777 event->detail.button = b->map[key]; 1778 if (!grab && CheckDeviceGrabs(device, event, 0)) { 1779 /* if a passive grab was activated, the event has been sent 1780 * already */ 1781 return; 1782 } 1783 break; 1784 case ET_ButtonRelease: 1785 if (b->map[key] == 0) /* there's no button 0 */ 1786 return; 1787 event->detail.button = b->map[key]; 1788 if (grab && !b->buttonsDown && 1789 device->deviceGrab.fromPassiveGrab && 1790 GrabIsPointerGrab(device->deviceGrab.grab)) 1791 deactivateDeviceGrab = TRUE; 1792 default: 1793 break; 1794 } 1795 1796 /* Don't deliver focus events (e.g. from KeymapNotify when running 1797 * nested) to clients. */ 1798 if (event->source_type != EVENT_SOURCE_FOCUS) { 1799 if (grab) 1800 DeliverGrabbedEvent((InternalEvent *) event, device, 1801 deactivateDeviceGrab); 1802 else if (device->focus && !IsPointerEvent(ev)) 1803 DeliverFocusedEvent(device, (InternalEvent *) event, 1804 GetSpriteWindow(device)); 1805 else 1806 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event, 1807 NullGrab, NullWindow, device); 1808 } 1809 1810 if (deactivateDeviceGrab == TRUE) { 1811 (*device->deviceGrab.DeactivateGrab) (device); 1812 1813 if (!IsMaster (device) && !IsFloating (device)) { 1814 int flags, num_events = 0; 1815 InternalEvent dce; 1816 1817 flags = (IsPointerDevice (device)) ? 1818 DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT; 1819 UpdateFromMaster (&dce, device, flags, &num_events); 1820 BUG_WARN(num_events > 1); 1821 1822 if (num_events == 1) 1823 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED), 1824 &dce.changed_event); 1825 } 1826 1827 } 1828 1829 event->detail.key = key; 1830} 1831 1832/** 1833 * Main device event processing function. 1834 * Called from when processing the events from the event queue. 1835 * 1836 */ 1837void 1838ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) 1839{ 1840 verify_internal_event(ev); 1841 1842 switch (ev->any.type) { 1843 case ET_RawKeyPress: 1844 case ET_RawKeyRelease: 1845 case ET_RawButtonPress: 1846 case ET_RawButtonRelease: 1847 case ET_RawMotion: 1848 case ET_RawTouchBegin: 1849 case ET_RawTouchUpdate: 1850 case ET_RawTouchEnd: 1851 DeliverRawEvent(&ev->raw_event, device); 1852 break; 1853 case ET_TouchBegin: 1854 case ET_TouchUpdate: 1855 case ET_TouchEnd: 1856 ProcessTouchEvent(ev, device); 1857 break; 1858 case ET_TouchOwnership: 1859 /* TouchOwnership events are handled separately from the rest, as they 1860 * have more complex semantics. */ 1861 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device); 1862 break; 1863 case ET_BarrierHit: 1864 case ET_BarrierLeave: 1865 ProcessBarrierEvent(ev, device); 1866 break; 1867 default: 1868 ProcessDeviceEvent(ev, device); 1869 break; 1870 } 1871} 1872 1873static int 1874DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 1875 InternalEvent *ev, TouchListener * listener, 1876 ClientPtr client, WindowPtr win, GrabPtr grab, 1877 XI2Mask *xi2mask) 1878{ 1879 enum TouchListenerState state; 1880 int rc = Success; 1881 Bool has_ownershipmask; 1882 1883 if (listener->type == LISTENER_POINTER_REGULAR || 1884 listener->type == LISTENER_POINTER_GRAB) { 1885 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 1886 grab, xi2mask); 1887 if (rc == Success) { 1888 listener->state = LISTENER_IS_OWNER; 1889 /* async grabs cannot replay, so automatically accept this touch */ 1890 if (listener->type == LISTENER_POINTER_GRAB && 1891 dev->deviceGrab.grab && 1892 dev->deviceGrab.fromPassiveGrab && 1893 dev->deviceGrab.grab->pointerMode == GrabModeAsync) 1894 ActivateEarlyAccept(dev, ti); 1895 } 1896 goto out; 1897 } 1898 1899 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 1900 1901 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask) 1902 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 1903 if (!TouchResourceIsOwner(ti, listener->listener)) { 1904 if (has_ownershipmask) 1905 state = LISTENER_AWAITING_OWNER; 1906 else 1907 state = LISTENER_AWAITING_BEGIN; 1908 } 1909 else { 1910 if (has_ownershipmask) 1911 TouchSendOwnershipEvent(dev, ti, 0, listener->listener); 1912 1913 if (listener->type == LISTENER_REGULAR) 1914 state = LISTENER_HAS_ACCEPTED; 1915 else 1916 state = LISTENER_IS_OWNER; 1917 } 1918 listener->state = state; 1919 1920 out: 1921 return rc; 1922} 1923 1924static int 1925DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 1926 TouchListener * listener, ClientPtr client, 1927 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 1928{ 1929 int rc = Success; 1930 1931 if (listener->type == LISTENER_POINTER_REGULAR || 1932 listener->type == LISTENER_POINTER_GRAB) { 1933 /* Note: If the active grab was ungrabbed, we already changed the 1934 * state to LISTENER_HAS_END but still get here. So we mustn't 1935 * actually send the event. 1936 * This is part two of the hack in DeactivatePointerGrab 1937 */ 1938 if (listener->state != LISTENER_HAS_END) { 1939 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 1940 grab, xi2mask); 1941 1942 /* Once we send a TouchEnd to a legacy listener, we're already well 1943 * past the accepting/rejecting stage (can only happen on 1944 * GrabModeSync + replay. This listener now gets the end event, 1945 * and we can continue. 1946 */ 1947 if (rc == Success) 1948 listener->state = LISTENER_HAS_END; 1949 } 1950 goto out; 1951 } 1952 1953 /* A client is waiting for the begin, don't give it a TouchEnd */ 1954 if (listener->state == LISTENER_AWAITING_BEGIN) { 1955 listener->state = LISTENER_HAS_END; 1956 goto out; 1957 } 1958 1959 /* Event in response to reject */ 1960 if (ev->device_event.flags & TOUCH_REJECT || 1961 (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) { 1962 /* Touch has been rejected, or accepted by its owner which is not this listener */ 1963 if (listener->state != LISTENER_HAS_END) 1964 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 1965 listener->state = LISTENER_HAS_END; 1966 } 1967 else if (TouchResourceIsOwner(ti, listener->listener)) { 1968 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT); 1969 1970 /* FIXME: what about early acceptance */ 1971 if (normal_end && listener->state != LISTENER_HAS_END) 1972 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 1973 1974 if ((ti->num_listeners > 1 || 1975 (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) && 1976 (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { 1977 ev->any.type = ET_TouchUpdate; 1978 ev->device_event.flags |= TOUCH_PENDING_END; 1979 ti->pending_finish = TRUE; 1980 } 1981 1982 if (normal_end) 1983 listener->state = LISTENER_HAS_END; 1984 } 1985 1986 out: 1987 return rc; 1988} 1989 1990static int 1991DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 1992 TouchListener * listener, ClientPtr client, 1993 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 1994{ 1995 Bool has_ownershipmask = FALSE; 1996 int rc = Success; 1997 1998 if (xi2mask) 1999 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 2000 2001 if (ev->any.type == ET_TouchOwnership) { 2002 ev->touch_ownership_event.deviceid = dev->id; 2003 if (!TouchResourceIsOwner(ti, listener->listener)) 2004 goto out; 2005 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2006 listener->state = LISTENER_IS_OWNER; 2007 } 2008 else 2009 ev->device_event.deviceid = dev->id; 2010 2011 if (ev->any.type == ET_TouchBegin) { 2012 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, 2013 xi2mask); 2014 } 2015 else if (ev->any.type == ET_TouchUpdate) { 2016 if (listener->type == LISTENER_POINTER_REGULAR || 2017 listener->type == LISTENER_POINTER_GRAB) 2018 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, 2019 xi2mask); 2020 else if (TouchResourceIsOwner(ti, listener->listener) || 2021 has_ownershipmask) 2022 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2023 } 2024 else if (ev->any.type == ET_TouchEnd) 2025 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, 2026 xi2mask); 2027 2028 out: 2029 return rc; 2030} 2031 2032/** 2033 * Delivers a touch events to all interested clients. For TouchBegin events, 2034 * will update ti->listeners, ti->num_listeners, and ti->num_grabs. 2035 * May also mutate ev (type and flags) upon successful delivery. If 2036 * @resource is non-zero, will only attempt delivery to the owner of that 2037 * resource. 2038 * 2039 * @return TRUE if the event was delivered at least once, FALSE otherwise 2040 */ 2041void 2042DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, 2043 InternalEvent *ev, XID resource) 2044{ 2045 int i; 2046 2047 if (ev->any.type == ET_TouchBegin && 2048 !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING))) 2049 TouchSetupListeners(dev, ti, ev); 2050 2051 TouchEventHistoryPush(ti, &ev->device_event); 2052 2053 for (i = 0; i < ti->num_listeners; i++) { 2054 GrabPtr grab = NULL; 2055 ClientPtr client; 2056 WindowPtr win; 2057 XI2Mask *mask; 2058 TouchListener *listener = &ti->listeners[i]; 2059 2060 if (resource && listener->listener != resource) 2061 continue; 2062 2063 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win, 2064 &grab, &mask)) 2065 continue; 2066 2067 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask); 2068 } 2069} 2070 2071int 2072InitProximityClassDeviceStruct(DeviceIntPtr dev) 2073{ 2074 ProximityClassPtr proxc; 2075 2076 BUG_RETURN_VAL(dev == NULL, FALSE); 2077 BUG_RETURN_VAL(dev->proximity != NULL, FALSE); 2078 2079 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec)); 2080 if (!proxc) 2081 return FALSE; 2082 proxc->sourceid = dev->id; 2083 proxc->in_proximity = TRUE; 2084 dev->proximity = proxc; 2085 return TRUE; 2086} 2087 2088/** 2089 * Initialise the device's valuators. The memory must already be allocated, 2090 * this function merely inits the matching axis (specified through axnum) to 2091 * sane values. 2092 * 2093 * It is a condition that (minval < maxval). 2094 * 2095 * @see InitValuatorClassDeviceStruct 2096 */ 2097Bool 2098InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 2099 int maxval, int resolution, int min_res, int max_res, 2100 int mode) 2101{ 2102 AxisInfoPtr ax; 2103 2104 BUG_RETURN_VAL(dev == NULL, FALSE); 2105 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2106 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2107 BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE); 2108 2109 ax = dev->valuator->axes + axnum; 2110 2111 ax->min_value = minval; 2112 ax->max_value = maxval; 2113 ax->resolution = resolution; 2114 ax->min_resolution = min_res; 2115 ax->max_resolution = max_res; 2116 ax->label = label; 2117 ax->mode = mode; 2118 2119 if (mode & OutOfProximity) 2120 dev->proximity->in_proximity = FALSE; 2121 2122 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE); 2123} 2124 2125/** 2126 * Set the given axis number as a scrolling valuator. 2127 */ 2128Bool 2129SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, 2130 double increment, int flags) 2131{ 2132 AxisInfoPtr ax; 2133 int *current_ax; 2134 InternalEvent dce; 2135 DeviceIntPtr master; 2136 2137 BUG_RETURN_VAL(dev == NULL, FALSE); 2138 BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 2139 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 2140 2141 switch (type) { 2142 case SCROLL_TYPE_VERTICAL: 2143 current_ax = &dev->valuator->v_scroll_axis; 2144 break; 2145 case SCROLL_TYPE_HORIZONTAL: 2146 current_ax = &dev->valuator->h_scroll_axis; 2147 break; 2148 case SCROLL_TYPE_NONE: 2149 ax = &dev->valuator->axes[axnum]; 2150 ax->scroll.type = type; 2151 return TRUE; 2152 default: 2153 return FALSE; 2154 } 2155 2156 if (increment == 0.0) 2157 return FALSE; 2158 2159 if (*current_ax != -1 && axnum != *current_ax) { 2160 ax = &dev->valuator->axes[*current_ax]; 2161 if (ax->scroll.type == type && 2162 (flags & SCROLL_FLAG_PREFERRED) && 2163 (ax->scroll.flags & SCROLL_FLAG_PREFERRED)) 2164 return FALSE; 2165 } 2166 *current_ax = axnum; 2167 2168 ax = &dev->valuator->axes[axnum]; 2169 ax->scroll.type = type; 2170 ax->scroll.increment = increment; 2171 ax->scroll.flags = flags; 2172 2173 master = GetMaster(dev, MASTER_ATTACHED); 2174 CreateClassesChangedEvent(&dce, master, dev, 2175 DEVCHANGE_POINTER_EVENT | 2176 DEVCHANGE_DEVICE_CHANGE); 2177 XISendDeviceChangedEvent(dev, &dce.changed_event); 2178 2179 /* if the current slave is us, update the master. If not, we'll update 2180 * whenever the next slave switch happens anyway. CMDC sends the event 2181 * for us */ 2182 if (master && master->lastSlave == dev) 2183 ChangeMasterDeviceClasses(master, &dce.changed_event); 2184 2185 return TRUE; 2186} 2187 2188int 2189CheckGrabValues(ClientPtr client, GrabParameters *param) 2190{ 2191 if (param->grabtype != CORE && 2192 param->grabtype != XI && param->grabtype != XI2) { 2193 ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); 2194 return BadImplementation; 2195 } 2196 2197 if ((param->this_device_mode != GrabModeSync) && 2198 (param->this_device_mode != GrabModeAsync) && 2199 (param->this_device_mode != XIGrabModeTouch)) { 2200 client->errorValue = param->this_device_mode; 2201 return BadValue; 2202 } 2203 if ((param->other_devices_mode != GrabModeSync) && 2204 (param->other_devices_mode != GrabModeAsync) && 2205 (param->other_devices_mode != XIGrabModeTouch)) { 2206 client->errorValue = param->other_devices_mode; 2207 return BadValue; 2208 } 2209 2210 if (param->modifiers != AnyModifier && 2211 param->modifiers != XIAnyModifier && 2212 (param->modifiers & ~AllModifiersMask)) { 2213 client->errorValue = param->modifiers; 2214 return BadValue; 2215 } 2216 2217 if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { 2218 client->errorValue = param->ownerEvents; 2219 return BadValue; 2220 } 2221 return Success; 2222} 2223 2224int 2225GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2226 int button, GrabParameters *param, enum InputLevel grabtype, 2227 GrabMask *mask) 2228{ 2229 WindowPtr pWin, confineTo; 2230 CursorPtr cursor; 2231 GrabPtr grab; 2232 int rc, type = -1; 2233 Mask access_mode = DixGrabAccess; 2234 2235 rc = CheckGrabValues(client, param); 2236 if (rc != Success) 2237 return rc; 2238 if (param->confineTo == None) 2239 confineTo = NullWindow; 2240 else { 2241 rc = dixLookupWindow(&confineTo, param->confineTo, client, 2242 DixSetAttrAccess); 2243 if (rc != Success) 2244 return rc; 2245 } 2246 if (param->cursor == None) 2247 cursor = NullCursor; 2248 else { 2249 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2250 RT_CURSOR, client, DixUseAccess); 2251 if (rc != Success) { 2252 client->errorValue = param->cursor; 2253 return rc; 2254 } 2255 access_mode |= DixForceAccess; 2256 } 2257 if (param->this_device_mode == GrabModeSync || 2258 param->other_devices_mode == GrabModeSync) 2259 access_mode |= DixFreezeAccess; 2260 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2261 if (rc != Success) 2262 return rc; 2263 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2264 if (rc != Success) 2265 return rc; 2266 2267 if (grabtype == XI) 2268 type = DeviceButtonPress; 2269 else if (grabtype == XI2) 2270 type = XI_ButtonPress; 2271 2272 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2273 mask, param, type, button, confineTo, cursor); 2274 if (!grab) 2275 return BadAlloc; 2276 return AddPassiveGrabToList(client, grab); 2277} 2278 2279/** 2280 * Grab the given key. 2281 */ 2282int 2283GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 2284 int key, GrabParameters *param, enum InputLevel grabtype, 2285 GrabMask *mask) 2286{ 2287 WindowPtr pWin; 2288 GrabPtr grab; 2289 KeyClassPtr k = dev->key; 2290 Mask access_mode = DixGrabAccess; 2291 int rc, type = -1; 2292 2293 rc = CheckGrabValues(client, param); 2294 if (rc != Success) 2295 return rc; 2296 if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL) 2297 return BadMatch; 2298 if (grabtype == XI) { 2299 if ((key > k->xkbInfo->desc->max_key_code || 2300 key < k->xkbInfo->desc->min_key_code) 2301 && (key != AnyKey)) { 2302 client->errorValue = key; 2303 return BadValue; 2304 } 2305 type = DeviceKeyPress; 2306 } 2307 else if (grabtype == XI2) 2308 type = XI_KeyPress; 2309 2310 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2311 if (rc != Success) 2312 return rc; 2313 if (param->this_device_mode == GrabModeSync || 2314 param->other_devices_mode == GrabModeSync) 2315 access_mode |= DixFreezeAccess; 2316 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2317 if (rc != Success) 2318 return rc; 2319 2320 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 2321 mask, param, type, key, NULL, NULL); 2322 if (!grab) 2323 return BadAlloc; 2324 return AddPassiveGrabToList(client, grab); 2325} 2326 2327/* Enter/FocusIn grab */ 2328int 2329GrabWindow(ClientPtr client, DeviceIntPtr dev, int type, 2330 GrabParameters *param, GrabMask *mask) 2331{ 2332 WindowPtr pWin; 2333 CursorPtr cursor; 2334 GrabPtr grab; 2335 Mask access_mode = DixGrabAccess; 2336 int rc; 2337 2338 rc = CheckGrabValues(client, param); 2339 if (rc != Success) 2340 return rc; 2341 2342 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2343 if (rc != Success) 2344 return rc; 2345 if (param->cursor == None) 2346 cursor = NullCursor; 2347 else { 2348 rc = dixLookupResourceByType((void **) &cursor, param->cursor, 2349 RT_CURSOR, client, DixUseAccess); 2350 if (rc != Success) { 2351 client->errorValue = param->cursor; 2352 return rc; 2353 } 2354 access_mode |= DixForceAccess; 2355 } 2356 if (param->this_device_mode == GrabModeSync || 2357 param->other_devices_mode == GrabModeSync) 2358 access_mode |= DixFreezeAccess; 2359 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 2360 if (rc != Success) 2361 return rc; 2362 2363 grab = CreateGrab(client->index, dev, dev, pWin, XI2, 2364 mask, param, 2365 (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0, 2366 NULL, cursor); 2367 2368 if (!grab) 2369 return BadAlloc; 2370 2371 return AddPassiveGrabToList(client, grab); 2372} 2373 2374/* Touch grab */ 2375int 2376GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev, 2377 GrabParameters *param, GrabMask *mask) 2378{ 2379 WindowPtr pWin; 2380 GrabPtr grab; 2381 int rc; 2382 2383 rc = CheckGrabValues(client, param); 2384 if (rc != Success) 2385 return rc; 2386 2387 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 2388 if (rc != Success) 2389 return rc; 2390 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess); 2391 if (rc != Success) 2392 return rc; 2393 2394 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2, 2395 mask, param, XI_TouchBegin, 0, NullWindow, NullCursor); 2396 if (!grab) 2397 return BadAlloc; 2398 2399 return AddPassiveGrabToList(client, grab); 2400} 2401 2402int 2403SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 2404 Mask mask, Mask exclusivemasks) 2405{ 2406 int mskidx = dev->id; 2407 int i, ret; 2408 Mask check; 2409 InputClientsPtr others; 2410 2411 check = (mask & exclusivemasks); 2412 if (wOtherInputMasks(pWin)) { 2413 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { 2414 /* It is illegal for two different clients to select on any of 2415 * the events for maskcheck. However, it is OK, for some client 2416 * to continue selecting on one of those events. 2417 */ 2418 for (others = wOtherInputMasks(pWin)->inputClients; others; 2419 others = others->next) { 2420 if (!SameClient(others, client) && (check & 2421 others->mask[mskidx])) 2422 return BadAccess; 2423 } 2424 } 2425 for (others = wOtherInputMasks(pWin)->inputClients; others; 2426 others = others->next) { 2427 if (SameClient(others, client)) { 2428 check = others->mask[mskidx]; 2429 others->mask[mskidx] = mask; 2430 if (mask == 0) { 2431 for (i = 0; i < EMASKSIZE; i++) 2432 if (i != mskidx && others->mask[i] != 0) 2433 break; 2434 if (i == EMASKSIZE) { 2435 RecalculateDeviceDeliverableEvents(pWin); 2436 if (ShouldFreeInputMasks(pWin, FALSE)) 2437 FreeResource(others->resource, RT_NONE); 2438 return Success; 2439 } 2440 } 2441 goto maskSet; 2442 } 2443 } 2444 } 2445 check = 0; 2446 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 2447 return ret; 2448 maskSet: 2449 if (dev->valuator) 2450 if ((dev->valuator->motionHintWindow == pWin) && 2451 (mask & DevicePointerMotionHintMask) && 2452 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) 2453 dev->valuator->motionHintWindow = NullWindow; 2454 RecalculateDeviceDeliverableEvents(pWin); 2455 return Success; 2456} 2457 2458static void 2459FreeInputClient(InputClientsPtr * other) 2460{ 2461 xi2mask_free(&(*other)->xi2mask); 2462 free(*other); 2463 *other = NULL; 2464} 2465 2466static InputClientsPtr 2467AllocInputClient(void) 2468{ 2469 return calloc(1, sizeof(InputClients)); 2470} 2471 2472int 2473AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 2474{ 2475 InputClientsPtr others; 2476 2477 if (!pWin->optional && !MakeWindowOptional(pWin)) 2478 return BadAlloc; 2479 others = AllocInputClient(); 2480 if (!others) 2481 return BadAlloc; 2482 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 2483 goto bail; 2484 others->xi2mask = xi2mask_new(); 2485 if (!others->xi2mask) 2486 goto bail; 2487 others->mask[mskidx] = mask; 2488 others->resource = FakeClientID(client->index); 2489 others->next = pWin->optional->inputMasks->inputClients; 2490 pWin->optional->inputMasks->inputClients = others; 2491 if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin)) 2492 goto bail; 2493 return Success; 2494 2495 bail: 2496 FreeInputClient(&others); 2497 return BadAlloc; 2498} 2499 2500static Bool 2501MakeInputMasks(WindowPtr pWin) 2502{ 2503 struct _OtherInputMasks *imasks; 2504 2505 imasks = calloc(1, sizeof(struct _OtherInputMasks)); 2506 if (!imasks) 2507 return FALSE; 2508 imasks->xi2mask = xi2mask_new(); 2509 if (!imasks->xi2mask) { 2510 free(imasks); 2511 return FALSE; 2512 } 2513 pWin->optional->inputMasks = imasks; 2514 return TRUE; 2515} 2516 2517static void 2518FreeInputMask(OtherInputMasks ** imask) 2519{ 2520 xi2mask_free(&(*imask)->xi2mask); 2521 free(*imask); 2522 *imask = NULL; 2523} 2524 2525void 2526RecalculateDeviceDeliverableEvents(WindowPtr pWin) 2527{ 2528 InputClientsPtr others; 2529 struct _OtherInputMasks *inputMasks; /* default: NULL */ 2530 WindowPtr pChild, tmp; 2531 int i; 2532 2533 pChild = pWin; 2534 while (1) { 2535 if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 2536 xi2mask_zero(inputMasks->xi2mask, -1); 2537 for (others = inputMasks->inputClients; others; 2538 others = others->next) { 2539 for (i = 0; i < EMASKSIZE; i++) 2540 inputMasks->inputEvents[i] |= others->mask[i]; 2541 xi2mask_merge(inputMasks->xi2mask, others->xi2mask); 2542 } 2543 for (i = 0; i < EMASKSIZE; i++) 2544 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 2545 for (tmp = pChild->parent; tmp; tmp = tmp->parent) 2546 if (wOtherInputMasks(tmp)) 2547 for (i = 0; i < EMASKSIZE; i++) 2548 inputMasks->deliverableEvents[i] |= 2549 (wOtherInputMasks(tmp)->deliverableEvents[i] 2550 & ~inputMasks->dontPropagateMask[i] & 2551 PropagateMask[i]); 2552 } 2553 if (pChild->firstChild) { 2554 pChild = pChild->firstChild; 2555 continue; 2556 } 2557 while (!pChild->nextSib && (pChild != pWin)) 2558 pChild = pChild->parent; 2559 if (pChild == pWin) 2560 break; 2561 pChild = pChild->nextSib; 2562 } 2563} 2564 2565int 2566InputClientGone(WindowPtr pWin, XID id) 2567{ 2568 InputClientsPtr other, prev; 2569 2570 if (!wOtherInputMasks(pWin)) 2571 return Success; 2572 prev = 0; 2573 for (other = wOtherInputMasks(pWin)->inputClients; other; 2574 other = other->next) { 2575 if (other->resource == id) { 2576 if (prev) { 2577 prev->next = other->next; 2578 FreeInputClient(&other); 2579 } 2580 else if (!(other->next)) { 2581 if (ShouldFreeInputMasks(pWin, TRUE)) { 2582 OtherInputMasks *mask = wOtherInputMasks(pWin); 2583 2584 mask->inputClients = other->next; 2585 FreeInputMask(&mask); 2586 pWin->optional->inputMasks = (OtherInputMasks *) NULL; 2587 CheckWindowOptionalNeed(pWin); 2588 FreeInputClient(&other); 2589 } 2590 else { 2591 other->resource = FakeClientID(0); 2592 if (!AddResource(other->resource, RT_INPUTCLIENT, 2593 (void *) pWin)) 2594 return BadAlloc; 2595 } 2596 } 2597 else { 2598 wOtherInputMasks(pWin)->inputClients = other->next; 2599 FreeInputClient(&other); 2600 } 2601 RecalculateDeviceDeliverableEvents(pWin); 2602 return Success; 2603 } 2604 prev = other; 2605 } 2606 FatalError("client not on device event list"); 2607} 2608 2609/** 2610 * Search for window in each touch trace for each device. Remove the window 2611 * and all its subwindows from the trace when found. The initial window 2612 * order is preserved. 2613 */ 2614void 2615WindowGone(WindowPtr win) 2616{ 2617 DeviceIntPtr dev; 2618 2619 for (dev = inputInfo.devices; dev; dev = dev->next) { 2620 TouchClassPtr t = dev->touch; 2621 int i; 2622 2623 if (!t) 2624 continue; 2625 2626 for (i = 0; i < t->num_touches; i++) { 2627 SpritePtr sprite = &t->touches[i].sprite; 2628 int j; 2629 2630 for (j = 0; j < sprite->spriteTraceGood; j++) { 2631 if (sprite->spriteTrace[j] == win) { 2632 sprite->spriteTraceGood = j; 2633 break; 2634 } 2635 } 2636 } 2637 } 2638} 2639 2640int 2641SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 2642 xEvent *ev, Mask mask, int count) 2643{ 2644 WindowPtr pWin; 2645 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 2646 WindowPtr spriteWin = GetSpriteWindow(d); 2647 2648 if (dest == PointerWindow) 2649 pWin = spriteWin; 2650 else if (dest == InputFocus) { 2651 WindowPtr inputFocus; 2652 2653 if (!d->focus) 2654 inputFocus = spriteWin; 2655 else 2656 inputFocus = d->focus->win; 2657 2658 if (inputFocus == FollowKeyboardWin) 2659 inputFocus = inputInfo.keyboard->focus->win; 2660 2661 if (inputFocus == NoneWin) 2662 return Success; 2663 2664 /* If the input focus is PointerRootWin, send the event to where 2665 * the pointer is if possible, then perhaps propogate up to root. */ 2666 if (inputFocus == PointerRootWin) 2667 inputFocus = GetCurrentRootWindow(d); 2668 2669 if (IsParent(inputFocus, spriteWin)) { 2670 effectiveFocus = inputFocus; 2671 pWin = spriteWin; 2672 } 2673 else 2674 effectiveFocus = pWin = inputFocus; 2675 } 2676 else 2677 dixLookupWindow(&pWin, dest, client, DixSendAccess); 2678 if (!pWin) 2679 return BadWindow; 2680 if ((propagate != xFalse) && (propagate != xTrue)) { 2681 client->errorValue = propagate; 2682 return BadValue; 2683 } 2684 ev->u.u.type |= 0x80; 2685 if (propagate) { 2686 for (; pWin; pWin = pWin->parent) { 2687 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) 2688 return Success; 2689 if (pWin == effectiveFocus) 2690 return Success; 2691 if (wOtherInputMasks(pWin)) 2692 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 2693 if (!mask) 2694 break; 2695 } 2696 } 2697 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) 2698 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); 2699 return Success; 2700} 2701 2702int 2703SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 2704{ 2705 int i; 2706 ButtonClassPtr b = dev->button; 2707 2708 if (b == NULL) 2709 return BadMatch; 2710 2711 if (nElts != b->numButtons) { 2712 client->errorValue = nElts; 2713 return BadValue; 2714 } 2715 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 2716 return BadValue; 2717 for (i = 0; i < nElts; i++) 2718 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 2719 return MappingBusy; 2720 for (i = 0; i < nElts; i++) 2721 b->map[i + 1] = map[i]; 2722 return Success; 2723} 2724 2725int 2726ChangeKeyMapping(ClientPtr client, 2727 DeviceIntPtr dev, 2728 unsigned len, 2729 int type, 2730 KeyCode firstKeyCode, 2731 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 2732{ 2733 KeySymsRec keysyms; 2734 KeyClassPtr k = dev->key; 2735 2736 if (k == NULL) 2737 return BadMatch; 2738 2739 if (len != (keyCodes * keySymsPerKeyCode)) 2740 return BadLength; 2741 2742 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || 2743 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { 2744 client->errorValue = firstKeyCode; 2745 return BadValue; 2746 } 2747 if (keySymsPerKeyCode == 0) { 2748 client->errorValue = 0; 2749 return BadValue; 2750 } 2751 keysyms.minKeyCode = firstKeyCode; 2752 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 2753 keysyms.mapWidth = keySymsPerKeyCode; 2754 keysyms.map = map; 2755 2756 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, 2757 serverClient); 2758 2759 return Success; 2760} 2761 2762static void 2763DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 2764{ 2765 WindowPtr parent; 2766 2767 /* Deactivate any grabs performed on this window, before making 2768 * any input focus changes. 2769 * Deactivating a device grab should cause focus events. */ 2770 2771 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) 2772 (*dev->deviceGrab.DeactivateGrab) (dev); 2773 2774 /* If the focus window is a root window (ie. has no parent) 2775 * then don't delete the focus from it. */ 2776 2777 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 2778 int focusEventMode = NotifyNormal; 2779 2780 /* If a grab is in progress, then alter the mode of focus events. */ 2781 2782 if (dev->deviceGrab.grab) 2783 focusEventMode = NotifyWhileGrabbed; 2784 2785 switch (dev->focus->revert) { 2786 case RevertToNone: 2787 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 2788 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 2789 dev->focus->win = NoneWin; 2790 dev->focus->traceGood = 0; 2791 break; 2792 case RevertToParent: 2793 parent = pWin; 2794 do { 2795 parent = parent->parent; 2796 dev->focus->traceGood--; 2797 } 2798 while (!parent->realized); 2799 if (!ActivateFocusInGrab(dev, pWin, parent)) 2800 DoFocusEvents(dev, pWin, parent, focusEventMode); 2801 dev->focus->win = parent; 2802 dev->focus->revert = RevertToNone; 2803 break; 2804 case RevertToPointerRoot: 2805 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) 2806 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 2807 dev->focus->win = PointerRootWin; 2808 dev->focus->traceGood = 0; 2809 break; 2810 case RevertToFollowKeyboard: 2811 { 2812 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 2813 2814 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) 2815 kbd = inputInfo.keyboard; 2816 if (kbd->focus->win) { 2817 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) 2818 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); 2819 dev->focus->win = FollowKeyboardWin; 2820 dev->focus->traceGood = 0; 2821 } 2822 else { 2823 if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 2824 DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 2825 dev->focus->win = NoneWin; 2826 dev->focus->traceGood = 0; 2827 } 2828 } 2829 break; 2830 } 2831 } 2832 2833 if (dev->valuator) 2834 if (dev->valuator->motionHintWindow == pWin) 2835 dev->valuator->motionHintWindow = NullWindow; 2836} 2837 2838void 2839DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 2840{ 2841 int i; 2842 DeviceIntPtr dev; 2843 InputClientsPtr ic; 2844 struct _OtherInputMasks *inputMasks; 2845 2846 for (dev = inputInfo.devices; dev; dev = dev->next) { 2847 DeleteDeviceFromAnyExtEvents(pWin, dev); 2848 } 2849 2850 for (dev = inputInfo.off_devices; dev; dev = dev->next) 2851 DeleteDeviceFromAnyExtEvents(pWin, dev); 2852 2853 if (freeResources) 2854 while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 2855 ic = inputMasks->inputClients; 2856 for (i = 0; i < EMASKSIZE; i++) 2857 inputMasks->dontPropagateMask[i] = 0; 2858 FreeResource(ic->resource, RT_NONE); 2859 } 2860} 2861 2862int 2863MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask) 2864{ 2865 DeviceIntPtr dev; 2866 2867 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient, 2868 DixReadAccess); 2869 if (!dev) 2870 return 0; 2871 2872 if (pEvents->type == DeviceMotionNotify) { 2873 if (mask & DevicePointerMotionHintMask) { 2874 if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 2875 return 1; /* don't send, but pretend we did */ 2876 } 2877 pEvents->detail = NotifyHint; 2878 } 2879 else { 2880 pEvents->detail = NotifyNormal; 2881 } 2882 } 2883 return 0; 2884} 2885 2886void 2887CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 2888 deviceKeyButtonPointer *xE, GrabPtr grab, 2889 ClientPtr client, Mask deliveryMask) 2890{ 2891 DeviceIntPtr dev; 2892 2893 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, 2894 DixGrabAccess); 2895 if (!dev) 2896 return; 2897 2898 if (type == DeviceMotionNotify) 2899 dev->valuator->motionHintWindow = pWin; 2900 else if ((type == DeviceButtonPress) && (!grab) && 2901 (deliveryMask & DeviceButtonGrabMask)) { 2902 GrabPtr tempGrab; 2903 2904 tempGrab = AllocGrab(NULL); 2905 if (!tempGrab) 2906 return; 2907 2908 tempGrab->device = dev; 2909 tempGrab->resource = client->clientAsMask; 2910 tempGrab->window = pWin; 2911 tempGrab->ownerEvents = 2912 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 2913 tempGrab->eventMask = deliveryMask; 2914 tempGrab->keyboardMode = GrabModeAsync; 2915 tempGrab->pointerMode = GrabModeAsync; 2916 tempGrab->confineTo = NullWindow; 2917 tempGrab->cursor = NullCursor; 2918 tempGrab->next = NULL; 2919 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE); 2920 FreeGrab(tempGrab); 2921 } 2922} 2923 2924static Mask 2925DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 2926{ 2927 InputClientsPtr other; 2928 2929 if (!wOtherInputMasks(pWin)) 2930 return 0; 2931 for (other = wOtherInputMasks(pWin)->inputClients; other; 2932 other = other->next) { 2933 if (SameClient(other, client)) 2934 return other->mask[dev->id]; 2935 } 2936 return 0; 2937} 2938 2939void 2940MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 2941{ 2942 WindowPtr pWin; 2943 GrabPtr grab = dev->deviceGrab.grab; 2944 2945 pWin = dev->valuator->motionHintWindow; 2946 2947 if ((grab && SameClient(grab, client) && 2948 ((grab->eventMask & DevicePointerMotionHintMask) || 2949 (grab->ownerEvents && 2950 (DeviceEventMaskForClient(dev, pWin, client) & 2951 DevicePointerMotionHintMask)))) || 2952 (!grab && 2953 (DeviceEventMaskForClient(dev, pWin, client) & 2954 DevicePointerMotionHintMask))) 2955 dev->valuator->motionHintWindow = NullWindow; 2956} 2957 2958int 2959DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 2960 int maskndx) 2961{ 2962 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2963 2964 if (mask & ~PropagateMask[maskndx]) { 2965 client->errorValue = mask; 2966 return BadValue; 2967 } 2968 2969 if (mask == 0) { 2970 if (inputMasks) 2971 inputMasks->dontPropagateMask[maskndx] = mask; 2972 } 2973 else { 2974 if (!inputMasks) 2975 AddExtensionClient(pWin, client, 0, 0); 2976 inputMasks = wOtherInputMasks(pWin); 2977 inputMasks->dontPropagateMask[maskndx] = mask; 2978 } 2979 RecalculateDeviceDeliverableEvents(pWin); 2980 if (ShouldFreeInputMasks(pWin, FALSE)) 2981 FreeResource(inputMasks->inputClients->resource, RT_NONE); 2982 return Success; 2983} 2984 2985Bool 2986ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 2987{ 2988 int i; 2989 Mask allInputEventMasks = 0; 2990 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2991 2992 for (i = 0; i < EMASKSIZE; i++) 2993 allInputEventMasks |= inputMasks->dontPropagateMask[i]; 2994 if (!ignoreSelectedEvents) 2995 for (i = 0; i < EMASKSIZE; i++) 2996 allInputEventMasks |= inputMasks->inputEvents[i]; 2997 if (allInputEventMasks == 0) 2998 return TRUE; 2999 else 3000 return FALSE; 3001} 3002 3003/*********************************************************************** 3004 * 3005 * Walk through the window tree, finding all clients that want to know 3006 * about the Event. 3007 * 3008 */ 3009 3010static void 3011FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 3012 xEvent *ev, int count) 3013{ 3014 WindowPtr p2; 3015 3016 while (p1) { 3017 p2 = p1->firstChild; 3018 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); 3019 FindInterestedChildren(dev, p2, mask, ev, count); 3020 p1 = p1->nextSib; 3021 } 3022} 3023 3024/*********************************************************************** 3025 * 3026 * Send an event to interested clients in all windows on all screens. 3027 * 3028 */ 3029 3030void 3031SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count) 3032{ 3033 int i; 3034 WindowPtr pWin, p1; 3035 3036 for (i = 0; i < screenInfo.numScreens; i++) { 3037 pWin = screenInfo.screens[i]->root; 3038 if (!pWin) 3039 continue; 3040 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); 3041 p1 = pWin->firstChild; 3042 FindInterestedChildren(dev, p1, mask, ev, count); 3043 } 3044} 3045 3046/** 3047 * Set the XI2 mask for the given client on the given window. 3048 * @param dev The device to set the mask for. 3049 * @param win The window to set the mask on. 3050 * @param client The client setting the mask. 3051 * @param len Number of bytes in mask. 3052 * @param mask Event mask in the form of (1 << eventtype) 3053 */ 3054int 3055XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 3056 unsigned int len, unsigned char *mask) 3057{ 3058 OtherInputMasks *masks; 3059 InputClientsPtr others = NULL; 3060 3061 masks = wOtherInputMasks(win); 3062 if (masks) { 3063 for (others = wOtherInputMasks(win)->inputClients; others; 3064 others = others->next) { 3065 if (SameClient(others, client)) { 3066 xi2mask_zero(others->xi2mask, dev->id); 3067 break; 3068 } 3069 } 3070 } 3071 3072 if (len && !others) { 3073 if (AddExtensionClient(win, client, 0, 0) != Success) 3074 return BadAlloc; 3075 others = wOtherInputMasks(win)->inputClients; 3076 } 3077 3078 if (others) { 3079 xi2mask_zero(others->xi2mask, dev->id); 3080 len = min(len, xi2mask_mask_size(others->xi2mask)); 3081 } 3082 3083 if (len) { 3084 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len); 3085 } 3086 3087 RecalculateDeviceDeliverableEvents(win); 3088 3089 return Success; 3090} 3091