diff options
-rw-r--r-- | Xi/exevents.c | 47 | ||||
-rw-r--r-- | Xi/xiallowev.c | 51 |
2 files changed, 72 insertions, 26 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index 1e43a5ccd..4f9d3e25f 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1042,7 +1042,7 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, xEvent *xi2 = NULL; Mask filter; WindowPtr win; - int i, j, err, deliveries; + int i, j, err, deliveries, ownerskipped = 0; ti->num_grabs = 0; for (i = 0; i < sprite->spriteTraceGood; i++) @@ -1090,6 +1090,14 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, continue; } + /* The owner does not need to see an owner accepted event. */ + if (ev->flags & XITouchOwnerAccepted && !ownerskipped) + { + ownerskipped = 1; + ev->flags &= ~XITouchOwner; + continue; + } + if (XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), win, (xEvent *) xi2, 1) != Success) continue; @@ -1098,11 +1106,33 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, if (deliveries > 0) { ti->num_grabs++; + + /* If this isn't the last listener of a TouchEnd event, notify + * other listeners of a pending finish. */ + if (ev->type == ET_TouchEnd && + ti->listeners[ti->num_listeners - 1] != grab->resource) + { + ev->type = ET_TouchMotion; + ev->flags |= XITouchPendingFinish; + ti->pending_finish = TRUE; + } + /* If we've made a delivery, the next one definitely won't be * to the owner. */ ev->flags &= ~XITouchOwner; if (ev->type == ET_TouchBegin) ti->listeners[ti->num_listeners++] = grab->resource; + else if (ev->type == ET_TouchMotion && + !(ev->flags & XITouchOwnerAccepted)) + { + /* These motion events with no valuators convey change of + * ownership. Only the new owner cares. */ + for (j = 0; j < sizeof(ev->valuators.mask); j++) + if (ev->valuators.mask[j] != 0) + break; + if (j == sizeof(ev->valuators.mask)) + break; + } } } @@ -1257,18 +1287,11 @@ ProcessTouchEvent(DeviceEvent *ev, DeviceIntPtr sourcedev) ti = &t->touches[touch]; sprite = &ti->sprite; - /* If we get a TouchEnd event but someone still has an open grab, just - * flip pending_finish and wait for ownership to settle. */ - if (ev->type == ET_TouchEnd && ti->num_grabs) - { - ev->type = ET_TouchMotion; - ev->flags |= XITouchPendingFinish; - ti->pending_finish = TRUE; - } - /* The first delivery we make will be to the owner, so set the owner flag - * here, and clear it once we've made a delivery. */ - ev->flags |= XITouchOwner; + * here, and clear it once we've made a delivery. Touch acceptance does not + * need to be sent to the owner. */ + if (!(ev->flags & XITouchOwnerAccepted)) + ev->flags |= XITouchOwner; /* Make sure we have a valid window trace for event delivery. */ if (!EnsureTouchSprite(sourcedev, ti, ev)) diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c index 93905fd67..793dc8778 100644 --- a/Xi/xiallowev.c +++ b/Xi/xiallowev.c @@ -169,16 +169,33 @@ ProcXIAllowTouchEvents(ClientPtr client) ti->emulate_pointer = FALSE; flags |= XITouchOwnerAccepted; - nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, flags); - if (nev == 0) - return BadAlloc; - for (i = 0; i < nev; i++) + + if (ti->pending_finish) + { + flags |= XITouchPendingFinish; + + /* The touch ended, so owner doesn't need another event */ + for (i = 0; i < ti->num_listeners - 1; i++) + ti->listeners[i] = ti->listeners[i + 1]; + ti->num_listeners--; + } + + if (ti->num_listeners > 0) { - ev = (DeviceEvent *)((events + i)->event); - mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL); + nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, flags); + if (nev == 0) + return BadAlloc; + for (i = 0; i < nev; i++) + { + ev = (DeviceEvent *)((events + i)->event); + mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL); + } } - ti->num_listeners = 1; + if (ti->pending_finish) + FinishTouchPoint(dev, stuff->touchid); + else + ti->num_listeners = 1; } else if (stuff->mode & XITouchOwnerReject) { @@ -192,15 +209,21 @@ ProcXIAllowTouchEvents(ClientPtr client) ti->listeners[i] = ti->listeners[i + 1]; ti->num_listeners--; - ProcessInputEvents(); - nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, 0); - if (nev == 0) - return BadAlloc; - for (i = 0; i < nev; i++) + if (ti->num_listeners > 0) { - ev = (DeviceEvent *)((events + i)->event); - mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL); + ProcessInputEvents(); + nev = GetTouchEvents(events, dev, stuff->touchid, mask, + ti->pending_finish, 0); + if (nev == 0) + return BadAlloc; + for (i = 0; i < nev; i++) + { + ev = (DeviceEvent *)((events + i)->event); + mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL); + } } + else + FinishTouchPoint(dev, stuff->touchid); } else { |