diff options
Diffstat (limited to 'xorg-server/Xi/exevents.c')
-rw-r--r-- | xorg-server/Xi/exevents.c | 160 |
1 files changed, 86 insertions, 74 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 92edae3e3..a6819c8c2 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -1090,20 +1090,71 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, return TRUE; } +static void +ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) +{ + int rc; + ClientPtr client; + XID error; + + rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient, + DixSendAccess); + if (rc != Success) + { + ErrorF("[Xi] Failed to lookup early accepting client.\n"); + return; + } + + if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id, + ti->listeners[0].window->drawable.id, &error) != + Success) + ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n"); +} + /** - * If the current owner has rejected the event, deliver the - * TouchOwnership/TouchBegin to the next item in the sprite stack. + * Generate and deliver a TouchEnd event. + * + * @param dev The device to deliver the event for. + * @param ti The touch point record to deliver the event for. + * @param flags Internal event flags. The called does not need to provide + * TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure + * they are set appropriately. + * @param resource The client resource to deliver to, or 0 for all clients. */ static void -TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, - TouchOwnershipEvent *ev) +EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) { InternalEvent *tel = InitEventList(GetMaximumEventsNum()); ValuatorMask *mask = valuator_mask_new(2); int i, nev; + valuator_mask_set_double(mask, 0, + valuator_mask_get_double(ti->valuators, 0)); + valuator_mask_set_double(mask, 1, + valuator_mask_get_double(ti->valuators, 1)); + + flags |= TOUCH_CLIENT_ID; + if (ti->emulate_pointer) + flags |= TOUCH_POINTER_EMULATED; + nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask); + for (i = 0; i < nev; i++) + DeliverTouchEvents(dev, ti, tel + i, resource); + + valuator_mask_free(&mask); + FreeEventList(tel, GetMaximumEventsNum()); +} + +/** + * If the current owner has rejected the event, deliver the + * TouchOwnership/TouchBegin to the next item in the sprite stack. + */ +static void +TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + TouchOwnershipEvent *ev) +{ /* Deliver the ownership */ - if (ti->listeners[0].state == LISTENER_AWAITING_OWNER) + if (ti->listeners[0].state == LISTENER_AWAITING_OWNER || + ti->listeners[0].state == LISTENER_EARLY_ACCEPT) DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener); else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener); @@ -1113,52 +1164,41 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) { - int flags; - valuator_mask_set_double(mask, 0, - valuator_mask_get_double(ti->valuators, 0)); - valuator_mask_set_double(mask, 1, - valuator_mask_get_double(ti->valuators, 1)); - - flags = TOUCH_CLIENT_ID; - if (ti->emulate_pointer) - flags |= TOUCH_POINTER_EMULATED; - nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask); - for (i = 0; i < nev; i++) - DeliverTouchEvents(dev, ti, tel + i, 0); + EmitTouchEnd(dev, ti, 0, 0); TouchEndTouch(dev, ti); } - valuator_mask_free(&mask); - FreeEventList(tel, GetMaximumEventsNum()); + if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT) + ActivateEarlyAccept(dev, ti); } -static void -TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, - TouchOwnershipEvent *ev) +/** + * Process a touch rejection. + * + * @param sourcedev The source device of the touch sequence. + * @param ti The touchpoint info record. + * @param resource The resource of the client rejecting the touch. + * @param ev TouchOwnership event to send. Set to NULL if no event should be + * sent. + */ +void +TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, + TouchOwnershipEvent *ev) { - InternalEvent *tel = InitEventList(GetMaximumEventsNum()); - ValuatorMask *mask = valuator_mask_new(2); - Bool was_owner = (ev->resource == ti->listeners[0].listener); + Bool was_owner = (resource == ti->listeners[0].listener); void *grab; - int nev, i; - + int i; /* Send a TouchEnd event to the resource being removed, but only if they * haven't received one yet already */ - if (ti->listeners[0].state != LISTENER_HAS_END) + for (i = 0; i < ti->num_listeners; i++) { - int flags; - valuator_mask_set_double(mask, 0, - valuator_mask_get_double(ti->valuators, 0)); - valuator_mask_set_double(mask, 1, - valuator_mask_get_double(ti->valuators, 1)); - - flags = TOUCH_CLIENT_ID|TOUCH_REJECT; - if (ti->emulate_pointer) - flags |= TOUCH_POINTER_EMULATED; - nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask); - for (i = 0; i < nev; i++) - DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource); + if (ti->listeners[i].listener == resource) + { + if (ti->listeners[i].state != LISTENER_HAS_END) + EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); + break; + } } /* If there are no other listeners left, and the touchpoint is pending @@ -1166,26 +1206,22 @@ TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, if (ti->num_listeners == 1 && ti->pending_finish) { TouchEndTouch(sourcedev, ti); - goto out; + return; } /* Remove the resource from the listener list, updating * ti->num_listeners, as well as ti->num_grabs if it was a grab. */ - if (TouchRemoveListener(ti, ev->resource)) + if (TouchRemoveListener(ti, resource)) { - if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB, + if (dixLookupResourceByType(&grab, resource, RT_PASSIVEGRAB, serverClient, DixGetAttrAccess) == Success) ti->num_grabs--; } /* If the current owner was removed and there are further listeners, deliver * the TouchOwnership or TouchBegin event to the new owner. */ - if (ti->num_listeners > 0 && was_owner) + if (ev && ti->num_listeners > 0 && was_owner) TouchPuntToNextOwner(sourcedev, ti, ev); - -out: - FreeEventList(tel, GetMaximumEventsNum()); - valuator_mask_free(&mask); } /** @@ -1201,35 +1237,11 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, { if (ev->reason == XIRejectTouch) - TouchEventRejected(dev, ti, ev); + TouchRejected(dev, ti, ev->resource, ev); else if (ev->reason == XIAcceptTouch) { - int flags; - int nev, i; - ValuatorMask *mask; - - InternalEvent *tel = InitEventList(GetMaximumEventsNum()); - - mask = valuator_mask_new(dev->valuator->numAxes); - valuator_mask_set_double(mask, 0, - valuator_mask_get_double(ti->valuators, 0)); - valuator_mask_set_double(mask, 1, - valuator_mask_get_double(ti->valuators, 1)); - - /* FIXME: what about early acceptance? a client may accept before it - * owns the touch. */ - /* The touch owner has accepted the touch. Send TouchEnd events to * everyone else, and truncate the list of listeners. */ - flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID; - if (ti->emulate_pointer) - flags |= TOUCH_POINTER_EMULATED; - nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, - flags, mask); - for (i = 0; i < nev; i++) - DeliverTouchEvents(dev, ti, tel + i, 0); - - FreeEventList(tel, GetMaximumEventsNum()); - valuator_mask_free(&mask); + EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0); while (ti->num_listeners > 1) TouchRemoveListener(ti, ti->listeners[1].listener); |