~ubuntu-branches/ubuntu/vivid/xorg-server/vivid

« back to all changes in this revision

Viewing changes to Xi/exevents.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2013-08-14 10:52:17 UTC
  • mfrom: (1.1.58) (0.1.37 experimental)
  • Revision ID: package-import@ubuntu.com-20130814105217-qtjqao6bga20wwlt
Tags: 2:1.14.2.901-2ubuntu1
* Merge from released debian-experimental.
* Drop upstreamed prime patches.
* Refresh 228_autobind_gpu.patch.
* Pick up some more input fixes from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1036
1036
static void
1037
1037
ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1038
1038
{
1039
 
    int rc;
1040
1039
    ClientPtr client;
1041
1040
    XID error;
1042
 
 
1043
 
    rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
1044
 
                         DixSendAccess);
1045
 
    if (rc != Success) {
1046
 
        ErrorF("[Xi] Failed to lookup early accepting client.\n");
1047
 
        return;
1048
 
    }
 
1041
    GrabPtr grab = ti->listeners[0].grab;
 
1042
 
 
1043
    BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
 
1044
               ti->listeners[0].type != LISTENER_POINTER_GRAB);
 
1045
    BUG_RETURN(!grab);
 
1046
 
 
1047
    client = rClient(grab);
1049
1048
 
1050
1049
    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
1051
 
                          ti->listeners[0].window->drawable.id, &error) !=
1052
 
        Success)
 
1050
                          ti->listeners[0].window->drawable.id, &error) != Success)
1053
1051
        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1054
1052
}
1055
1053
 
1056
1054
/**
1057
 
 * Generate and deliver a TouchEnd event.
1058
 
 *
1059
 
 * @param dev The device to deliver the event for.
1060
 
 * @param ti The touch point record to deliver the event for.
1061
 
 * @param flags Internal event flags. The called does not need to provide
1062
 
 *        TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
1063
 
 *        they are set appropriately.
1064
 
 * @param resource The client resource to deliver to, or 0 for all clients.
1065
 
 */
1066
 
static void
1067
 
EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
1068
 
{
1069
 
    InternalEvent event;
1070
 
 
1071
 
    flags |= TOUCH_CLIENT_ID;
1072
 
    if (ti->emulate_pointer)
1073
 
        flags |= TOUCH_POINTER_EMULATED;
1074
 
    TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
1075
 
    GetDixTouchEnd(&event, dev, ti, flags);
1076
 
    DeliverTouchEvents(dev, ti, &event, resource);
1077
 
}
1078
 
 
1079
 
/**
1080
1055
 * Find the oldest touch that still has a pointer emulation client.
1081
1056
 *
1082
1057
 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1126
1101
TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1127
1102
                     TouchOwnershipEvent *ev)
1128
1103
{
 
1104
    TouchListener *listener = &ti->listeners[0]; /* new owner */
 
1105
    int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
 
1106
 
1129
1107
    /* Deliver the ownership */
1130
 
    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
1131
 
        ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
 
1108
    if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
1132
1109
        DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
1133
 
                           ti->listeners[0].listener);
1134
 
    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
 
1110
                           listener->listener);
 
1111
    else if (listener->state == LISTENER_AWAITING_BEGIN) {
1135
1112
        /* We can't punt to a pointer listener unless all older pointer
1136
1113
         * emulated touches have been seen already. */
1137
 
        if ((ti->listeners[0].type == LISTENER_POINTER_GRAB ||
1138
 
             ti->listeners[0].type == LISTENER_POINTER_REGULAR) &&
 
1114
        if ((listener->type == LISTENER_POINTER_GRAB ||
 
1115
             listener->type == LISTENER_POINTER_REGULAR) &&
1139
1116
            ti != FindOldestPointerEmulatedTouch(dev))
1140
1117
            return;
1141
1118
 
1142
 
        TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
1143
 
    }
1144
 
 
1145
 
    /* If we've just removed the last grab and the touch has physically
1146
 
     * ended, send a TouchEnd event too and finalise the touch. */
1147
 
    if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) {
1148
 
        EmitTouchEnd(dev, ti, 0, 0);
1149
 
        TouchEndTouch(dev, ti);
1150
 
        return;
1151
 
    }
1152
 
 
1153
 
    if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
 
1119
        TouchEventHistoryReplay(ti, dev, listener->listener);
 
1120
    }
 
1121
 
 
1122
    /* New owner has Begin/Update but not end. If touch is pending_finish,
 
1123
     * emulate the TouchEnd now */
 
1124
    if (ti->pending_finish) {
 
1125
        TouchEmitTouchEnd(dev, ti, 0, 0);
 
1126
 
 
1127
        /* If the last owner is not a touch grab, finalise the touch, we
 
1128
           won't get more correspondence on this.
 
1129
         */
 
1130
        if (ti->num_listeners == 1 &&
 
1131
            (ti->num_grabs == 0 ||
 
1132
             listener->grab->grabtype != XI2 ||
 
1133
             !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
 
1134
            TouchEndTouch(dev, ti);
 
1135
            return;
 
1136
        }
 
1137
    }
 
1138
 
 
1139
    if (accepted_early)
1154
1140
        ActivateEarlyAccept(dev, ti);
1155
1141
}
1156
1142
 
1194
1180
    for (i = 0; i < ti->num_listeners; i++) {
1195
1181
        if (ti->listeners[i].listener == resource) {
1196
1182
            if (ti->listeners[i].state != LISTENER_HAS_END)
1197
 
                EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
 
1183
                TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
1198
1184
            break;
1199
1185
        }
1200
1186
    }
1237
1223
    else if (ev->reason == XIAcceptTouch) {
1238
1224
        int i;
1239
1225
 
1240
 
        /* Go through the motions of ending the touch if the listener has
 
1226
 
 
1227
        /* For pointer-emulated listeners that ungrabbed the active grab,
 
1228
         * the state was forced to LISTENER_HAS_END. Still go
 
1229
         * through the motions of ending the touch if the listener has
1241
1230
         * already seen the end. This ensures that the touch record is ended in
1242
 
         * the server. */
 
1231
         * the server.
 
1232
         */
1243
1233
        if (ti->listeners[0].state == LISTENER_HAS_END)
1244
 
            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
 
1234
            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
1245
1235
 
1246
1236
        /* The touch owner has accepted the touch.  Send TouchEnd events to
1247
1237
         * everyone else, and truncate the list of listeners. */
1248
1238
        for (i = 1; i < ti->num_listeners; i++)
1249
 
            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
 
1239
            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
1250
1240
 
1251
1241
        while (ti->num_listeners > 1)
1252
1242
            TouchRemoveListener(ti, ti->listeners[1].listener);
1383
1373
 
1384
1374
    /* We don't deliver pointer events to non-owners */
1385
1375
    if (!TouchResourceIsOwner(ti, listener->listener))
1386
 
        return Success;
 
1376
        return !Success;
1387
1377
 
1388
1378
    nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1389
1379
    BUG_RETURN_VAL(nevents == 0, BadValue);
1405
1395
            /* 'grab' is the passive grab, but if the grab isn't active,
1406
1396
             * don't deliver */
1407
1397
            if (!dev->deviceGrab.grab)
1408
 
                return Success;
 
1398
                return !Success;
1409
1399
 
1410
1400
            if (grab->ownerEvents) {
1411
1401
                WindowPtr focus = NullWindow;
1415
1405
            }
1416
1406
 
1417
1407
            if (!deliveries)
1418
 
                DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
 
1408
                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1419
1409
 
1420
1410
            /* We must accept the touch sequence once a pointer listener has
1421
1411
             * received one event past ButtonPress. */
1423
1413
                !(ev->device_event.flags & TOUCH_CLIENT_ID))
1424
1414
                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1425
1415
 
1426
 
            if (ev->any.type == ET_TouchEnd &&
1427
 
                !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
 
1416
            if (deliveries && ev->any.type == ET_TouchEnd &&
1428
1417
                !dev->button->buttonsDown &&
1429
1418
                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1430
1419
                (*dev->deviceGrab.DeactivateGrab) (dev);
1443
1432
         */
1444
1433
        if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1445
1434
            TouchListener *l;
 
1435
            GrabPtr g;
1446
1436
 
1447
1437
            devgrab = dev->deviceGrab.grab;
 
1438
            g = AllocGrab(devgrab);
 
1439
            BUG_WARN(!g);
1448
1440
 
1449
1441
            *dev->deviceGrab.sync.event = ev->device_event;
1450
1442
 
1453
1445
             * event selection. Thus, we update the last listener in the array.
1454
1446
             */
1455
1447
            l = &ti->listeners[ti->num_listeners - 1];
1456
 
            l->listener = devgrab->resource;
1457
 
            l->grab = devgrab;
 
1448
            l->listener = g->resource;
 
1449
            l->grab = g;
1458
1450
            //l->resource_type = RT_NONE;
1459
1451
 
1460
1452
            if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
1545
1537
 
1546
1538
    touchid = ev->device_event.touchid;
1547
1539
 
1548
 
    if (type == ET_TouchBegin) {
 
1540
    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
1549
1541
        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1550
1542
                             emulate_pointer);
1551
1543
    }
1612
1604
     * called after event type mutation. Touch end events are always processed
1613
1605
     * in order to end touch records. */
1614
1606
    /* FIXME: check this */
1615
 
    if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
 
1607
    if ((type == ET_TouchBegin &&
 
1608
         !(ev->device_event.flags & TOUCH_REPLAYING) &&
 
1609
         !TouchBuildSprite(dev, ti, ev)) ||
1616
1610
        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1617
1611
        return;
1618
1612
 
1620
1614
    /* WARNING: the event type may change to TouchUpdate in
1621
1615
     * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1622
1616
     * owner */
1623
 
    DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
 
1617
    DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1624
1618
    if (ev->any.type == ET_TouchEnd)
1625
1619
        TouchEndTouch(dev, ti);
1626
1620
 
1848
1842
        listener->type == LISTENER_POINTER_GRAB) {
1849
1843
        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1850
1844
                                       grab, xi2mask);
 
1845
        if (rc == Success) {
 
1846
            listener->state = LISTENER_IS_OWNER;
 
1847
            /* async grabs cannot replay, so automatically accept this touch */
 
1848
            if (dev->deviceGrab.grab &&
 
1849
                dev->deviceGrab.fromPassiveGrab &&
 
1850
                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
 
1851
                ActivateEarlyAccept(dev, ti);
 
1852
        }
1851
1853
        goto out;
1852
1854
    }
1853
1855
 
1865
1867
        if (has_ownershipmask)
1866
1868
            TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1867
1869
 
1868
 
        if (!has_ownershipmask || listener->type == LISTENER_REGULAR)
 
1870
        if (listener->type == LISTENER_REGULAR)
1869
1871
            state = LISTENER_HAS_ACCEPTED;
1870
1872
        else
1871
1873
            state = LISTENER_IS_OWNER;
1885
1887
 
1886
1888
    if (listener->type == LISTENER_POINTER_REGULAR ||
1887
1889
        listener->type == LISTENER_POINTER_GRAB) {
1888
 
        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1889
 
                                       grab, xi2mask);
 
1890
        /* Note: If the active grab was ungrabbed, we already changed the
 
1891
         * state to LISTENER_HAS_END but still get here. So we mustn't
 
1892
         * actually send the event.
 
1893
         * This is part two of the hack in DeactivatePointerGrab
 
1894
         */
 
1895
        if (listener->state != LISTENER_HAS_END) {
 
1896
            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
 
1897
                                           grab, xi2mask);
1890
1898
 
1891
 
        if (ti->num_listeners > 1) {
1892
 
            ev->any.type = ET_TouchUpdate;
1893
 
            ev->device_event.flags |= TOUCH_PENDING_END;
1894
 
            if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
1895
 
                ti->pending_finish = TRUE;
 
1899
             /* Once we send a TouchEnd to a legacy listener, we're already well
 
1900
              * past the accepting/rejecting stage (can only happen on
 
1901
              * GrabModeSync + replay. This listener now gets the end event,
 
1902
              * and we can continue.
 
1903
              */
 
1904
            if (rc == Success)
 
1905
                listener->state = LISTENER_HAS_END;
1896
1906
        }
1897
 
 
1898
1907
        goto out;
1899
1908
    }
1900
1909
 
1918
1927
            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1919
1928
 
1920
1929
        if ((ti->num_listeners > 1 ||
1921
 
             listener->state != LISTENER_HAS_ACCEPTED) &&
 
1930
             (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1922
1931
            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
1923
1932
            ev->any.type = ET_TouchUpdate;
1924
1933
            ev->device_event.flags |= TOUCH_PENDING_END;
2849
2858
             (deliveryMask & DeviceButtonGrabMask)) {
2850
2859
        GrabPtr tempGrab;
2851
2860
 
2852
 
        tempGrab = AllocGrab();
 
2861
        tempGrab = AllocGrab(NULL);
2853
2862
        if (!tempGrab)
2854
2863
            return;
2855
2864