[PATCH] dix: when ungrabbing an active grab, accept pointer grabs (#66720)

Jasper St. Pierre jstpierre at mecheye.net
Wed Jul 10 14:27:55 PDT 2013


This fixes the crash and makes pointer-emulated touch work properly on my
Chromebook.

Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>


On Tue, Jul 9, 2013 at 7:01 PM, Peter Hutterer <peter.hutterer at who-t.net>wrote:

> Ungrabbing a device during an active touch grab rejects the grab.
> Ungrabbing
> a device during an active pointer grab accepts the grab.
>
> Rejection is not really an option for a pointer-emulated grab, if a client
> has a button mask on the window it would get a ButtonPress emulated after
> UngrabDevice. That is against the core grab behaviour.
>
> X.Org Bug 66720 <http://bugs.freedesktop.org/show_bug.cgi?id=66720>
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  Xi/exevents.c | 33 ++++++++++++++++++++++-----------
>  dix/events.c  | 11 +++++++++--
>  2 files changed, 31 insertions(+), 13 deletions(-)
>
> diff --git a/Xi/exevents.c b/Xi/exevents.c
> index 2bbc6f0..fd4b80c 100644
> --- a/Xi/exevents.c
> +++ b/Xi/exevents.c
> @@ -1223,9 +1223,13 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
>      else if (ev->reason == XIAcceptTouch) {
>          int i;
>
> -        /* Go through the motions of ending the touch if the listener has
> +
> +        /* For pointer-emulated listeners that ungrabbed the active grab,
> +         * the state was forced to LISTENER_HAS_END. Still go
> +         * through the motions of ending the touch if the listener has
>           * already seen the end. This ensures that the touch record is
> ended in
> -         * the server. */
> +         * the server.
> +         */
>          if (ti->listeners[0].state == LISTENER_HAS_END)
>              TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT,
> ti->listeners[0].listener);
>
> @@ -1883,16 +1887,23 @@ DeliverTouchEndEvent(DeviceIntPtr dev,
> TouchPointInfoPtr ti, InternalEvent *ev,
>
>      if (listener->type == LISTENER_POINTER_REGULAR ||
>          listener->type == LISTENER_POINTER_GRAB) {
> -        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
> -                                       grab, xi2mask);
> +        /* Note: If the active grab was ungrabbed, we already changed the
> +         * state to LISTENER_HAS_END but still get here. So we mustn't
> +         * actually send the event.
> +         * This is part two of the hack in DeactivatePointerGrab
> +         */
> +        if (listener->state != LISTENER_HAS_END) {
> +            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client,
> win,
> +                                           grab, xi2mask);
>
> -         /* Once we send a TouchEnd to a legacy listener, we're already
> well
> -          * past the accepting/rejecting stage (can only happen on
> -          * GrabModeSync + replay. This listener now gets the end event,
> -          * and we can continue.
> -          */
> -        if (rc == Success)
> -            listener->state = LISTENER_HAS_END;
> +             /* Once we send a TouchEnd to a legacy listener, we're
> already well
> +              * past the accepting/rejecting stage (can only happen on
> +              * GrabModeSync + replay. This listener now gets the end
> event,
> +              * and we can continue.
> +              */
> +            if (rc == Success)
> +                listener->state = LISTENER_HAS_END;
> +        }
>          goto out;
>      }
>
> diff --git a/dix/events.c b/dix/events.c
> index e5db348..03b2d2e 100644
> --- a/dix/events.c
> +++ b/dix/events.c
> @@ -1522,13 +1522,20 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
>      for (i = 0; !wasPassive && mouse->touch && i <
> mouse->touch->num_touches; i++) {
>          TouchPointInfoPtr ti = mouse->touch->touches + i;
>          if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
> +            int mode = XIRejectTouch;
>              /* Rejecting will generate a TouchEnd, but we must not
>                 emulate a ButtonRelease here. So pretend the listener
>                 already has the end event */
>              if (grab->grabtype == CORE || grab->grabtype == XI ||
> -                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask,
> mouse, XI_TouchBegin))
> +                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask,
> mouse, XI_TouchBegin)) {
> +                mode = XIAcceptTouch;
> +                /* NOTE: we set the state here, but
> +                 * ProcessTouchOwnershipEvent() will still call
> +                 * TouchEmitTouchEnd for this listener. The other half of
> +                 * this hack is in DeliverTouchEndEvent */
>                  ti->listeners[0].state = LISTENER_HAS_END;
> -            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
> +            }
> +            TouchListenerAcceptReject(mouse, ti, 0, mode);
>          }
>      }
>
> --
> 1.8.2.1
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>



-- 
  Jasper
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.x.org/archives/xorg-devel/attachments/20130710/2059d7fc/attachment.html>


More information about the xorg-devel mailing list