xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

exevents.c (106653B)


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