xserver

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

touch.c (31340B)


      1 /*
      2  * Copyright © 2011 Collabra Ltd.
      3  * Copyright © 2011 Red Hat, Inc.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Author: Daniel Stone <daniel@fooishbar.org>
     25  */
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 
     31 #include "inputstr.h"
     32 #include "scrnintstr.h"
     33 #include "dixgrabs.h"
     34 
     35 #include "eventstr.h"
     36 #include "exevents.h"
     37 #include "exglobals.h"
     38 #include "inpututils.h"
     39 #include "eventconvert.h"
     40 #include "windowstr.h"
     41 #include "mi.h"
     42 
     43 #define TOUCH_HISTORY_SIZE 100
     44 
     45 Bool touchEmulatePointer = TRUE;
     46 
     47 /**
     48  * Some documentation about touch points:
     49  * The driver submits touch events with its own (unique) touch point ID.
     50  * The driver may re-use those IDs, the DDX doesn't care. It just passes on
     51  * the data to the DIX. In the server, the driver's ID is referred to as the
     52  * DDX id anyway.
     53  *
     54  * On a TouchBegin, we create a DDXTouchPointInfo that contains the DDX id
     55  * and the client ID that this touchpoint will have. The client ID is the
     56  * one visible on the protocol.
     57  *
     58  * TouchUpdate and TouchEnd will only be processed if there is an active
     59  * touchpoint with the same DDX id.
     60  *
     61  * The DDXTouchPointInfo struct is stored dev->last.touches. When the event
     62  * being processed, it becomes a TouchPointInfo in dev->touch-touches which
     63  * contains amongst other things the sprite trace and delivery information.
     64  */
     65 
     66 /**
     67  * Check which devices need a bigger touch event queue and grow their
     68  * last.touches by half its current size.
     69  *
     70  * @param client Always the serverClient
     71  * @param closure Always NULL
     72  *
     73  * @return Always True. If we fail to grow we probably will topple over soon
     74  * anyway and re-executing this won't help.
     75  */
     76 
     77 static Bool
     78 TouchResizeQueue(DeviceIntPtr dev)
     79 {
     80     DDXTouchPointInfoPtr tmp;
     81     size_t size;
     82 
     83     /* Grow sufficiently so we don't need to do it often */
     84     size = dev->last.num_touches + dev->last.num_touches / 2 + 1;
     85 
     86     tmp = reallocarray(dev->last.touches, size, sizeof(*dev->last.touches));
     87     if (tmp) {
     88         int j;
     89 
     90         dev->last.touches = tmp;
     91         for (j = dev->last.num_touches; j < size; j++)
     92             TouchInitDDXTouchPoint(dev, &dev->last.touches[j]);
     93         dev->last.num_touches = size;
     94         return TRUE;
     95     }
     96     return FALSE;
     97 }
     98 
     99 /**
    100  * Given the DDX-facing ID (which is _not_ DeviceEvent::detail.touch), find the
    101  * associated DDXTouchPointInfoRec.
    102  *
    103  * @param dev The device to create the touch point for
    104  * @param ddx_id Touch id assigned by the driver/ddx
    105  * @param create Create the touchpoint if it cannot be found
    106  */
    107 DDXTouchPointInfoPtr
    108 TouchFindByDDXID(DeviceIntPtr dev, uint32_t ddx_id, Bool create)
    109 {
    110     DDXTouchPointInfoPtr ti;
    111     int i;
    112 
    113     if (!dev->touch)
    114         return NULL;
    115 
    116     for (i = 0; i < dev->last.num_touches; i++) {
    117         ti = &dev->last.touches[i];
    118         if (ti->active && ti->ddx_id == ddx_id)
    119             return ti;
    120     }
    121 
    122     return create ? TouchBeginDDXTouch(dev, ddx_id) : NULL;
    123 }
    124 
    125 /**
    126  * Given a unique DDX ID for a touchpoint, create a touchpoint record and
    127  * return it.
    128  *
    129  * If no other touch points are active, mark new touchpoint for pointer
    130  * emulation.
    131  *
    132  * Returns NULL on failure (i.e. if another touch with that ID is already active,
    133  * allocation failure).
    134  */
    135 DDXTouchPointInfoPtr
    136 TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
    137 {
    138     static int next_client_id = 1;
    139     int i;
    140     TouchClassPtr t = dev->touch;
    141     DDXTouchPointInfoPtr ti = NULL;
    142     Bool emulate_pointer;
    143 
    144     if (!t)
    145         return NULL;
    146 
    147     emulate_pointer = touchEmulatePointer && (t->mode == XIDirectTouch);
    148 
    149     /* Look for another active touchpoint with the same DDX ID. DDX
    150      * touchpoints must be unique. */
    151     if (TouchFindByDDXID(dev, ddx_id, FALSE))
    152         return NULL;
    153 
    154     for (;;) {
    155         for (i = 0; i < dev->last.num_touches; i++) {
    156             /* Only emulate pointer events on the first touch */
    157             if (dev->last.touches[i].active)
    158                 emulate_pointer = FALSE;
    159             else if (!ti)           /* ti is now first non-active touch rec */
    160                 ti = &dev->last.touches[i];
    161 
    162             if (!emulate_pointer && ti)
    163                 break;
    164         }
    165         if (ti)
    166             break;
    167         if (!TouchResizeQueue(dev))
    168             break;
    169     }
    170 
    171     if (ti) {
    172         int client_id;
    173 
    174         ti->active = TRUE;
    175         ti->ddx_id = ddx_id;
    176         client_id = next_client_id;
    177         next_client_id++;
    178         if (next_client_id == 0)
    179             next_client_id = 1;
    180         ti->client_id = client_id;
    181         ti->emulate_pointer = emulate_pointer;
    182     }
    183     return ti;
    184 }
    185 
    186 void
    187 TouchEndDDXTouch(DeviceIntPtr dev, DDXTouchPointInfoPtr ti)
    188 {
    189     TouchClassPtr t = dev->touch;
    190 
    191     if (!t)
    192         return;
    193 
    194     ti->active = FALSE;
    195 }
    196 
    197 void
    198 TouchInitDDXTouchPoint(DeviceIntPtr dev, DDXTouchPointInfoPtr ddxtouch)
    199 {
    200     memset(ddxtouch, 0, sizeof(*ddxtouch));
    201     ddxtouch->valuators = valuator_mask_new(dev->valuator->numAxes);
    202 }
    203 
    204 Bool
    205 TouchInitTouchPoint(TouchClassPtr t, ValuatorClassPtr v, int index)
    206 {
    207     TouchPointInfoPtr ti;
    208 
    209     if (index >= t->num_touches)
    210         return FALSE;
    211     ti = &t->touches[index];
    212 
    213     memset(ti, 0, sizeof(*ti));
    214 
    215     ti->valuators = valuator_mask_new(v->numAxes);
    216     if (!ti->valuators)
    217         return FALSE;
    218 
    219     ti->sprite.spriteTrace = calloc(32, sizeof(*ti->sprite.spriteTrace));
    220     if (!ti->sprite.spriteTrace) {
    221         valuator_mask_free(&ti->valuators);
    222         return FALSE;
    223     }
    224     ti->sprite.spriteTraceSize = 32;
    225     ti->sprite.spriteTrace[0] = screenInfo.screens[0]->root;
    226     ti->sprite.hot.pScreen = screenInfo.screens[0];
    227     ti->sprite.hotPhys.pScreen = screenInfo.screens[0];
    228 
    229     ti->client_id = -1;
    230 
    231     return TRUE;
    232 }
    233 
    234 void
    235 TouchFreeTouchPoint(DeviceIntPtr device, int index)
    236 {
    237     TouchPointInfoPtr ti;
    238     int i;
    239 
    240     if (!device->touch || index >= device->touch->num_touches)
    241         return;
    242     ti = &device->touch->touches[index];
    243 
    244     if (ti->active)
    245         TouchEndTouch(device, ti);
    246 
    247     for (i = 0; i < ti->num_listeners; i++)
    248         TouchRemoveListener(ti, ti->listeners[0].listener);
    249 
    250     valuator_mask_free(&ti->valuators);
    251     free(ti->sprite.spriteTrace);
    252     ti->sprite.spriteTrace = NULL;
    253     free(ti->listeners);
    254     ti->listeners = NULL;
    255     free(ti->history);
    256     ti->history = NULL;
    257     ti->history_size = 0;
    258     ti->history_elements = 0;
    259 }
    260 
    261 /**
    262  * Given a client-facing ID (e.g. DeviceEvent::detail.touch), find the
    263  * associated TouchPointInfoRec.
    264  */
    265 TouchPointInfoPtr
    266 TouchFindByClientID(DeviceIntPtr dev, uint32_t client_id)
    267 {
    268     TouchClassPtr t = dev->touch;
    269     TouchPointInfoPtr ti;
    270     int i;
    271 
    272     if (!t)
    273         return NULL;
    274 
    275     for (i = 0; i < t->num_touches; i++) {
    276         ti = &t->touches[i];
    277         if (ti->active && ti->client_id == client_id)
    278             return ti;
    279     }
    280 
    281     return NULL;
    282 }
    283 
    284 /**
    285  * Given a unique ID for a touchpoint, create a touchpoint record in the
    286  * server.
    287  *
    288  * Returns NULL on failure (i.e. if another touch with that ID is already active,
    289  * allocation failure).
    290  */
    291 TouchPointInfoPtr
    292 TouchBeginTouch(DeviceIntPtr dev, int sourceid, uint32_t touchid,
    293                 Bool emulate_pointer)
    294 {
    295     int i;
    296     TouchClassPtr t = dev->touch;
    297     TouchPointInfoPtr ti;
    298     void *tmp;
    299 
    300     if (!t)
    301         return NULL;
    302 
    303     /* Look for another active touchpoint with the same client ID.  It's
    304      * technically legitimate for a touchpoint to still exist with the same
    305      * ID but only once the 32 bits wrap over and you've used up 4 billion
    306      * touch ids without lifting that one finger off once. In which case
    307      * you deserve a medal or something, but not error handling code. */
    308     if (TouchFindByClientID(dev, touchid))
    309         return NULL;
    310 
    311  try_find_touch:
    312     for (i = 0; i < t->num_touches; i++) {
    313         ti = &t->touches[i];
    314         if (!ti->active) {
    315             ti->active = TRUE;
    316             ti->client_id = touchid;
    317             ti->sourceid = sourceid;
    318             ti->emulate_pointer = emulate_pointer;
    319             return ti;
    320         }
    321     }
    322 
    323     /* If we get here, then we've run out of touches: enlarge dev->touch and
    324      * try again. */
    325     tmp = reallocarray(t->touches, t->num_touches + 1, sizeof(*ti));
    326     if (tmp) {
    327         t->touches = tmp;
    328         t->num_touches++;
    329         if (TouchInitTouchPoint(t, dev->valuator, t->num_touches - 1))
    330             goto try_find_touch;
    331     }
    332 
    333     return NULL;
    334 }
    335 
    336 /**
    337  * Releases a touchpoint for use: this must only be called after all events
    338  * related to that touchpoint have been sent and finalised.  Called from
    339  * ProcessTouchEvent and friends.  Not by you.
    340  */
    341 void
    342 TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
    343 {
    344     int i;
    345 
    346     if (ti->emulate_pointer) {
    347         GrabPtr grab;
    348 
    349         if ((grab = dev->deviceGrab.grab)) {
    350             if (dev->deviceGrab.fromPassiveGrab &&
    351                 !dev->button->buttonsDown &&
    352                 !dev->touch->buttonsDown && GrabIsPointerGrab(grab))
    353                 (*dev->deviceGrab.DeactivateGrab) (dev);
    354         }
    355     }
    356 
    357     for (i = 0; i < ti->num_listeners; i++)
    358         TouchRemoveListener(ti, ti->listeners[0].listener);
    359 
    360     ti->active = FALSE;
    361     ti->pending_finish = FALSE;
    362     ti->sprite.spriteTraceGood = 0;
    363     free(ti->listeners);
    364     ti->listeners = NULL;
    365     ti->num_listeners = 0;
    366     ti->num_grabs = 0;
    367     ti->client_id = 0;
    368 
    369     TouchEventHistoryFree(ti);
    370 
    371     valuator_mask_zero(ti->valuators);
    372 }
    373 
    374 /**
    375  * Allocate the event history for this touch pointer. Calling this on a
    376  * touchpoint that already has an event history does nothing but counts as
    377  * as success.
    378  *
    379  * @return TRUE on success, FALSE on allocation errors
    380  */
    381 Bool
    382 TouchEventHistoryAllocate(TouchPointInfoPtr ti)
    383 {
    384     if (ti->history)
    385         return TRUE;
    386 
    387     ti->history = calloc(TOUCH_HISTORY_SIZE, sizeof(*ti->history));
    388     ti->history_elements = 0;
    389     if (ti->history)
    390         ti->history_size = TOUCH_HISTORY_SIZE;
    391     return ti->history != NULL;
    392 }
    393 
    394 void
    395 TouchEventHistoryFree(TouchPointInfoPtr ti)
    396 {
    397     free(ti->history);
    398     ti->history = NULL;
    399     ti->history_size = 0;
    400     ti->history_elements = 0;
    401 }
    402 
    403 /**
    404  * Store the given event on the event history (if one exists)
    405  * A touch event history consists of one TouchBegin and several TouchUpdate
    406  * events (if applicable) but no TouchEnd event.
    407  * If more than one TouchBegin is pushed onto the stack, the push is
    408  * ignored, calling this function multiple times for the TouchBegin is
    409  * valid.
    410  */
    411 void
    412 TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev)
    413 {
    414     if (!ti->history)
    415         return;
    416 
    417     switch (ev->type) {
    418     case ET_TouchBegin:
    419         /* don't store the same touchbegin twice */
    420         if (ti->history_elements > 0)
    421             return;
    422         break;
    423     case ET_TouchUpdate:
    424         break;
    425     case ET_TouchEnd:
    426         return;                 /* no TouchEnd events in the history */
    427     default:
    428         return;
    429     }
    430 
    431     /* We only store real events in the history */
    432     if (ev->flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING))
    433         return;
    434 
    435     ti->history[ti->history_elements++] = *ev;
    436     /* FIXME: proper overflow fixes */
    437     if (ti->history_elements > ti->history_size - 1) {
    438         ti->history_elements = ti->history_size - 1;
    439         DebugF("source device %d: history size %zu overflowing for touch %u\n",
    440                ti->sourceid, ti->history_size, ti->client_id);
    441     }
    442 }
    443 
    444 void
    445 TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
    446 {
    447     int i;
    448 
    449     if (!ti->history)
    450         return;
    451 
    452     DeliverDeviceClassesChangedEvent(ti->sourceid, ti->history[0].time);
    453 
    454     for (i = 0; i < ti->history_elements; i++) {
    455         DeviceEvent *ev = &ti->history[i];
    456 
    457         ev->flags |= TOUCH_REPLAYING;
    458         ev->resource = resource;
    459         /* FIXME:
    460            We're replaying ti->history which contains the TouchBegin +
    461            all TouchUpdates for ti. This needs to be passed on to the next
    462            listener. If that is a touch listener, everything is dandy.
    463            If the TouchBegin however triggers a sync passive grab, the
    464            TouchUpdate events must be sent to EnqueueEvent so the events end
    465            up in syncEvents.pending to be forwarded correctly in a
    466            subsequent ComputeFreeze().
    467 
    468            However, if we just send them to EnqueueEvent the sync'ing device
    469            prevents handling of touch events for ownership listeners who
    470            want the events right here, right now.
    471          */
    472         dev->public.processInputProc((InternalEvent*)ev, dev);
    473     }
    474 }
    475 
    476 Bool
    477 TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
    478 {
    479     int i;
    480     TouchClassPtr t = dev->touch;
    481     SpritePtr srcsprite;
    482 
    483     /* All touches should have the same sprite trace, so find and reuse an
    484      * existing touch's sprite if possible, else use the device's sprite. */
    485     for (i = 0; i < t->num_touches; i++)
    486         if (!t->touches[i].pending_finish &&
    487             t->touches[i].sprite.spriteTraceGood > 0)
    488             break;
    489     if (i < t->num_touches)
    490         srcsprite = &t->touches[i].sprite;
    491     else if (dev->spriteInfo->sprite)
    492         srcsprite = dev->spriteInfo->sprite;
    493     else
    494         return FALSE;
    495 
    496     return CopySprite(srcsprite, sprite);
    497 }
    498 
    499 /**
    500  * Ensure a window trace is present in ti->sprite, constructing one for
    501  * TouchBegin events.
    502  */
    503 Bool
    504 TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
    505                  InternalEvent *ev)
    506 {
    507     TouchClassPtr t = sourcedev->touch;
    508     SpritePtr sprite = &ti->sprite;
    509 
    510     if (t->mode == XIDirectTouch) {
    511         /* Focus immediately under the touchpoint in direct touch mode.
    512          * XXX: Do we need to handle crossing screens here? */
    513         sprite->spriteTrace[0] =
    514             sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
    515         XYToWindow(sprite, ev->device_event.root_x, ev->device_event.root_y);
    516     }
    517     else if (!TouchBuildDependentSpriteTrace(sourcedev, sprite))
    518         return FALSE;
    519 
    520     if (sprite->spriteTraceGood <= 0)
    521         return FALSE;
    522 
    523     /* Mark which grabs/event selections we're delivering to: max one grab per
    524      * window plus the bottom-most event selection, plus any active grab. */
    525     ti->listeners = calloc(sprite->spriteTraceGood + 2, sizeof(*ti->listeners));
    526     if (!ti->listeners) {
    527         sprite->spriteTraceGood = 0;
    528         return FALSE;
    529     }
    530     ti->num_listeners = 0;
    531 
    532     return TRUE;
    533 }
    534 
    535 /**
    536  * Copy the touch event into the pointer_event, switching the required
    537  * fields to make it a correct pointer event.
    538  *
    539  * @param event The original touch event
    540  * @param[in] motion_event The respective motion event
    541  * @param[in] button_event The respective button event (if any)
    542  *
    543  * @returns The number of converted events.
    544  * @retval 0 An error occurred
    545  * @retval 1 only the motion event is valid
    546  * @retval 2 motion and button event are valid
    547  */
    548 int
    549 TouchConvertToPointerEvent(const InternalEvent *event,
    550                            InternalEvent *motion_event,
    551                            InternalEvent *button_event)
    552 {
    553     int ptrtype;
    554     int nevents = 0;
    555 
    556     BUG_RETURN_VAL(!event, 0);
    557     BUG_RETURN_VAL(!motion_event, 0);
    558 
    559     switch (event->any.type) {
    560     case ET_TouchUpdate:
    561         nevents = 1;
    562         break;
    563     case ET_TouchBegin:
    564         nevents = 2;            /* motion + press */
    565         ptrtype = ET_ButtonPress;
    566         break;
    567     case ET_TouchEnd:
    568         nevents = 2;            /* motion + release */
    569         ptrtype = ET_ButtonRelease;
    570         break;
    571     default:
    572         BUG_WARN_MSG(1, "Invalid event type %d\n", event->any.type);
    573         return 0;
    574     }
    575 
    576     BUG_WARN_MSG(!(event->device_event.flags & TOUCH_POINTER_EMULATED),
    577                  "Non-emulating touch event\n");
    578 
    579     motion_event->device_event = event->device_event;
    580     motion_event->any.type = ET_Motion;
    581     motion_event->device_event.detail.button = 0;
    582     motion_event->device_event.flags = XIPointerEmulated;
    583 
    584     if (nevents > 1) {
    585         BUG_RETURN_VAL(!button_event, 0);
    586         button_event->device_event = event->device_event;
    587         button_event->any.type = ptrtype;
    588         button_event->device_event.flags = XIPointerEmulated;
    589         /* detail is already correct */
    590     }
    591 
    592     return nevents;
    593 }
    594 
    595 /**
    596  * Return the corresponding pointer emulation internal event type for the given
    597  * touch event or 0 if no such event type exists.
    598  */
    599 int
    600 TouchGetPointerEventType(const InternalEvent *event)
    601 {
    602     int type = 0;
    603 
    604     switch (event->any.type) {
    605     case ET_TouchBegin:
    606         type = ET_ButtonPress;
    607         break;
    608     case ET_TouchUpdate:
    609         type = ET_Motion;
    610         break;
    611     case ET_TouchEnd:
    612         type = ET_ButtonRelease;
    613         break;
    614     default:
    615         break;
    616     }
    617     return type;
    618 }
    619 
    620 /**
    621  * @returns TRUE if the specified grab or selection is the current owner of
    622  * the touch sequence.
    623  */
    624 Bool
    625 TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource)
    626 {
    627     return (ti->listeners[0].listener == resource);
    628 }
    629 
    630 /**
    631  * Add the resource to this touch's listeners.
    632  */
    633 void
    634 TouchAddListener(TouchPointInfoPtr ti, XID resource, int resource_type,
    635                  enum InputLevel level, enum TouchListenerType type,
    636                  enum TouchListenerState state, WindowPtr window,
    637                  const GrabPtr grab)
    638 {
    639     GrabPtr g = NULL;
    640 
    641     /* We need a copy of the grab, not the grab itself since that may be
    642      * deleted by a UngrabButton request and leaves us with a dangling
    643      * pointer */
    644     if (grab)
    645         g = AllocGrab(grab);
    646 
    647     ti->listeners[ti->num_listeners].listener = resource;
    648     ti->listeners[ti->num_listeners].resource_type = resource_type;
    649     ti->listeners[ti->num_listeners].level = level;
    650     ti->listeners[ti->num_listeners].state = state;
    651     ti->listeners[ti->num_listeners].type = type;
    652     ti->listeners[ti->num_listeners].window = window;
    653     ti->listeners[ti->num_listeners].grab = g;
    654     if (grab)
    655         ti->num_grabs++;
    656     ti->num_listeners++;
    657 }
    658 
    659 /**
    660  * Remove the resource from this touch's listeners.
    661  *
    662  * @return TRUE if the resource was removed, FALSE if the resource was not
    663  * in the list
    664  */
    665 Bool
    666 TouchRemoveListener(TouchPointInfoPtr ti, XID resource)
    667 {
    668     int i;
    669 
    670     for (i = 0; i < ti->num_listeners; i++) {
    671         int j;
    672         TouchListener *listener = &ti->listeners[i];
    673 
    674         if (listener->listener != resource)
    675             continue;
    676 
    677         if (listener->grab) {
    678             FreeGrab(listener->grab);
    679             listener->grab = NULL;
    680             ti->num_grabs--;
    681         }
    682 
    683         for (j = i; j < ti->num_listeners - 1; j++)
    684             ti->listeners[j] = ti->listeners[j + 1];
    685         ti->num_listeners--;
    686         ti->listeners[ti->num_listeners].listener = 0;
    687         ti->listeners[ti->num_listeners].state = TOUCH_LISTENER_AWAITING_BEGIN;
    688 
    689         return TRUE;
    690     }
    691     return FALSE;
    692 }
    693 
    694 static void
    695 TouchAddGrabListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
    696                      InternalEvent *ev, GrabPtr grab)
    697 {
    698     enum TouchListenerType type = TOUCH_LISTENER_GRAB;
    699 
    700     /* FIXME: owner_events */
    701 
    702     if (grab->grabtype == XI2) {
    703         if (!xi2mask_isset(grab->xi2mask, dev, XI_TouchOwnership))
    704             TouchEventHistoryAllocate(ti);
    705         if (!xi2mask_isset(grab->xi2mask, dev, XI_TouchBegin))
    706             type = TOUCH_LISTENER_POINTER_GRAB;
    707     }
    708     else if (grab->grabtype == XI || grab->grabtype == CORE) {
    709         TouchEventHistoryAllocate(ti);
    710         type = TOUCH_LISTENER_POINTER_GRAB;
    711     }
    712 
    713     /* grab listeners are always RT_NONE since we keep the grab pointer */
    714     TouchAddListener(ti, grab->resource, RT_NONE, grab->grabtype,
    715                      type, TOUCH_LISTENER_AWAITING_BEGIN, grab->window, grab);
    716 }
    717 
    718 /**
    719  * Add one listener if there is a grab on the given window.
    720  */
    721 static void
    722 TouchAddPassiveGrabListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
    723                             WindowPtr win, InternalEvent *ev)
    724 {
    725     GrabPtr grab;
    726     Bool check_core = IsMaster(dev) && ti->emulate_pointer;
    727 
    728     /* FIXME: make CheckPassiveGrabsOnWindow only trigger on TouchBegin */
    729     grab = CheckPassiveGrabsOnWindow(win, dev, ev, check_core, FALSE);
    730     if (!grab)
    731         return;
    732 
    733     TouchAddGrabListener(dev, ti, ev, grab);
    734 }
    735 
    736 static Bool
    737 TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
    738                         WindowPtr win, InternalEvent *ev)
    739 {
    740     InputClients *iclients = NULL;
    741     OtherInputMasks *inputMasks = NULL;
    742     uint16_t evtype = 0;        /* may be event type or emulated event type */
    743     enum TouchListenerType type = TOUCH_LISTENER_REGULAR;
    744     int mask;
    745 
    746     evtype = GetXI2Type(ev->any.type);
    747     mask = EventIsDeliverable(dev, ev->any.type, win);
    748     if (!mask && !ti->emulate_pointer)
    749         return FALSE;
    750     else if (!mask) {           /* now try for pointer event */
    751         mask = EventIsDeliverable(dev, TouchGetPointerEventType(ev), win);
    752         if (mask) {
    753             evtype = GetXI2Type(TouchGetPointerEventType(ev));
    754             type = TOUCH_LISTENER_POINTER_REGULAR;
    755         }
    756     }
    757     if (!mask)
    758         return FALSE;
    759 
    760     inputMasks = wOtherInputMasks(win);
    761 
    762     if (mask & EVENT_XI2_MASK) {
    763         nt_list_for_each_entry(iclients, inputMasks->inputClients, next) {
    764             if (!xi2mask_isset(iclients->xi2mask, dev, evtype))
    765                 continue;
    766 
    767             if (!xi2mask_isset(iclients->xi2mask, dev, XI_TouchOwnership))
    768                 TouchEventHistoryAllocate(ti);
    769 
    770             TouchAddListener(ti, iclients->resource, RT_INPUTCLIENT, XI2,
    771                              type, TOUCH_LISTENER_AWAITING_BEGIN, win, NULL);
    772             return TRUE;
    773         }
    774     }
    775 
    776     if (mask & EVENT_XI1_MASK) {
    777         int xitype = GetXIType(TouchGetPointerEventType(ev));
    778         Mask xi_filter = event_get_filter_from_type(dev, xitype);
    779 
    780         nt_list_for_each_entry(iclients, inputMasks->inputClients, next) {
    781             if (!(iclients->mask[dev->id] & xi_filter))
    782                 continue;
    783 
    784             TouchEventHistoryAllocate(ti);
    785             TouchAddListener(ti, iclients->resource, RT_INPUTCLIENT, XI,
    786                              TOUCH_LISTENER_POINTER_REGULAR,
    787                              TOUCH_LISTENER_AWAITING_BEGIN,
    788                              win, NULL);
    789             return TRUE;
    790         }
    791     }
    792 
    793     if (mask & EVENT_CORE_MASK) {
    794         int coretype = GetCoreType(TouchGetPointerEventType(ev));
    795         Mask core_filter = event_get_filter_from_type(dev, coretype);
    796         OtherClients *oclients;
    797 
    798         /* window owner */
    799         if (IsMaster(dev) && (win->eventMask & core_filter)) {
    800             TouchEventHistoryAllocate(ti);
    801             TouchAddListener(ti, win->drawable.id, RT_WINDOW, CORE,
    802                              TOUCH_LISTENER_POINTER_REGULAR,
    803                              TOUCH_LISTENER_AWAITING_BEGIN,
    804                              win, NULL);
    805             return TRUE;
    806         }
    807 
    808         /* all others */
    809         nt_list_for_each_entry(oclients, wOtherClients(win), next) {
    810             if (!(oclients->mask & core_filter))
    811                 continue;
    812 
    813             TouchEventHistoryAllocate(ti);
    814             TouchAddListener(ti, oclients->resource, RT_OTHERCLIENT, CORE,
    815                              type, TOUCH_LISTENER_AWAITING_BEGIN, win, NULL);
    816             return TRUE;
    817         }
    818     }
    819 
    820     return FALSE;
    821 }
    822 
    823 static void
    824 TouchAddActiveGrabListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
    825                            InternalEvent *ev, GrabPtr grab)
    826 {
    827     if (!ti->emulate_pointer &&
    828         (grab->grabtype == CORE || grab->grabtype == XI))
    829         return;
    830 
    831     if (!ti->emulate_pointer &&
    832         grab->grabtype == XI2 &&
    833         !xi2mask_isset(grab->xi2mask, dev, XI_TouchBegin))
    834         return;
    835 
    836     TouchAddGrabListener(dev, ti, ev, grab);
    837 }
    838 
    839 void
    840 TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
    841 {
    842     int i;
    843     SpritePtr sprite = &ti->sprite;
    844     WindowPtr win;
    845 
    846     if (dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab)
    847         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
    848 
    849     /* We set up an active touch listener for existing touches, but not any
    850      * passive grab or regular listeners. */
    851     if (ev->any.type != ET_TouchBegin)
    852         return;
    853 
    854     /* First, find all grabbing clients from the root window down
    855      * to the deepest child window. */
    856     for (i = 0; i < sprite->spriteTraceGood; i++) {
    857         win = sprite->spriteTrace[i];
    858         TouchAddPassiveGrabListener(dev, ti, win, ev);
    859     }
    860 
    861     /* Find the first client with an applicable event selection,
    862      * going from deepest child window back up to the root window. */
    863     for (i = sprite->spriteTraceGood - 1; i >= 0; i--) {
    864         Bool delivered;
    865 
    866         win = sprite->spriteTrace[i];
    867         delivered = TouchAddRegularListener(dev, ti, win, ev);
    868         if (delivered)
    869             return;
    870     }
    871 }
    872 
    873 /**
    874  * Remove the touch pointer grab from the device. Called from
    875  * DeactivatePointerGrab()
    876  */
    877 void
    878 TouchRemovePointerGrab(DeviceIntPtr dev)
    879 {
    880     TouchPointInfoPtr ti;
    881     GrabPtr grab;
    882     InternalEvent *ev;
    883 
    884     if (!dev->touch)
    885         return;
    886 
    887     grab = dev->deviceGrab.grab;
    888     if (!grab)
    889         return;
    890 
    891     ev = dev->deviceGrab.sync.event;
    892     if (!IsTouchEvent(ev))
    893         return;
    894 
    895     ti = TouchFindByClientID(dev, ev->device_event.touchid);
    896     if (!ti)
    897         return;
    898 
    899     /* FIXME: missing a bit of code here... */
    900 }
    901 
    902 /* As touch grabs don't turn into active grabs with their own resources, we
    903  * need to walk all the touches and remove this grab from any delivery
    904  * lists. */
    905 void
    906 TouchListenerGone(XID resource)
    907 {
    908     TouchPointInfoPtr ti;
    909     DeviceIntPtr dev;
    910     InternalEvent *events = InitEventList(GetMaximumEventsNum());
    911     int i, j, k, nev;
    912 
    913     if (!events)
    914         FatalError("TouchListenerGone: couldn't allocate events\n");
    915 
    916     for (dev = inputInfo.devices; dev; dev = dev->next) {
    917         if (!dev->touch)
    918             continue;
    919 
    920         for (i = 0; i < dev->touch->num_touches; i++) {
    921             ti = &dev->touch->touches[i];
    922             if (!ti->active)
    923                 continue;
    924 
    925             for (j = 0; j < ti->num_listeners; j++) {
    926                 if (CLIENT_BITS(ti->listeners[j].listener) != resource)
    927                     continue;
    928 
    929                 nev = GetTouchOwnershipEvents(events, dev, ti, XIRejectTouch,
    930                                               ti->listeners[j].listener, 0);
    931                 for (k = 0; k < nev; k++)
    932                     mieqProcessDeviceEvent(dev, events + k, NULL);
    933 
    934                 break;
    935             }
    936         }
    937     }
    938 
    939     FreeEventList(events, GetMaximumEventsNum());
    940 }
    941 
    942 int
    943 TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
    944                           int mode)
    945 {
    946     InternalEvent *events;
    947     int nev;
    948     int i;
    949 
    950     BUG_RETURN_VAL(listener < 0, BadMatch);
    951     BUG_RETURN_VAL(listener >= ti->num_listeners, BadMatch);
    952 
    953     if (listener > 0) {
    954         if (mode == XIRejectTouch)
    955             TouchRejected(dev, ti, ti->listeners[listener].listener, NULL);
    956         else
    957             ti->listeners[listener].state = TOUCH_LISTENER_EARLY_ACCEPT;
    958 
    959         return Success;
    960     }
    961 
    962     events = InitEventList(GetMaximumEventsNum());
    963     BUG_RETURN_VAL_MSG(!events, BadAlloc, "Failed to allocate touch ownership events\n");
    964 
    965     nev = GetTouchOwnershipEvents(events, dev, ti, mode,
    966                                   ti->listeners[0].listener, 0);
    967     BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n");
    968 
    969     for (i = 0; i < nev; i++)
    970         mieqProcessDeviceEvent(dev, events + i, NULL);
    971 
    972     FreeEventList(events, GetMaximumEventsNum());
    973 
    974     return nev ? Success : BadMatch;
    975 }
    976 
    977 int
    978 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
    979                   uint32_t touchid, Window grab_window, XID *error)
    980 {
    981     TouchPointInfoPtr ti;
    982     int i;
    983 
    984     if (!dev->touch) {
    985         *error = dev->id;
    986         return BadDevice;
    987     }
    988 
    989     ti = TouchFindByClientID(dev, touchid);
    990     if (!ti) {
    991         *error = touchid;
    992         return BadValue;
    993     }
    994 
    995     for (i = 0; i < ti->num_listeners; i++) {
    996         if (CLIENT_ID(ti->listeners[i].listener) == client->index &&
    997             ti->listeners[i].window->drawable.id == grab_window)
    998             break;
    999     }
   1000     if (i == ti->num_listeners)
   1001         return BadAccess;
   1002 
   1003     return TouchListenerAcceptReject(dev, ti, i, mode);
   1004 }
   1005 
   1006 /**
   1007  * End physically active touches for a device.
   1008  */
   1009 void
   1010 TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
   1011 {
   1012     InternalEvent *eventlist = InitEventList(GetMaximumEventsNum());
   1013     int i;
   1014 
   1015     input_lock();
   1016     mieqProcessInputEvents();
   1017     for (i = 0; i < dev->last.num_touches; i++) {
   1018         DDXTouchPointInfoPtr ddxti = dev->last.touches + i;
   1019 
   1020         if (ddxti->active) {
   1021             int j;
   1022             int nevents = GetTouchEvents(eventlist, dev, ddxti->ddx_id,
   1023                                          XI_TouchEnd, 0, NULL);
   1024 
   1025             for (j = 0; j < nevents; j++)
   1026                 mieqProcessDeviceEvent(dev, eventlist + j, NULL);
   1027         }
   1028     }
   1029     input_unlock();
   1030 
   1031     FreeEventList(eventlist, GetMaximumEventsNum());
   1032 }
   1033 
   1034 /**
   1035  * Generate and deliver a TouchEnd event.
   1036  *
   1037  * @param dev The device to deliver the event for.
   1038  * @param ti The touch point record to deliver the event for.
   1039  * @param flags Internal event flags. The called does not need to provide
   1040  *        TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
   1041  *        they are set appropriately.
   1042  * @param resource The client resource to deliver to, or 0 for all clients.
   1043  */
   1044 void
   1045 TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
   1046 {
   1047     InternalEvent event;
   1048 
   1049     /* We're not processing a touch end for a frozen device */
   1050     if (dev->deviceGrab.sync.frozen)
   1051         return;
   1052 
   1053     flags |= TOUCH_CLIENT_ID;
   1054     if (ti->emulate_pointer)
   1055         flags |= TOUCH_POINTER_EMULATED;
   1056     DeliverDeviceClassesChangedEvent(ti->sourceid, GetTimeInMillis());
   1057     GetDixTouchEnd(&event, dev, ti, flags);
   1058     DeliverTouchEvents(dev, ti, &event, resource);
   1059     if (ti->num_grabs == 0)
   1060         UpdateDeviceState(dev, &event.device_event);
   1061 }
   1062 
   1063 void
   1064 TouchAcceptAndEnd(DeviceIntPtr dev, int touchid)
   1065 {
   1066     TouchPointInfoPtr ti = TouchFindByClientID(dev, touchid);
   1067     if (!ti)
   1068         return;
   1069 
   1070     TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
   1071     if (ti->pending_finish)
   1072         TouchEmitTouchEnd(dev, ti, 0, 0);
   1073     if (ti->num_listeners <= 1)
   1074         TouchEndTouch(dev, ti);
   1075 }