[PATCH 06/10] Create a new dix touch record for an emulated touch with no listeners

Peter Hutterer peter.hutterer at who-t.net
Tue Apr 17 23:33:18 PDT 2012


On Tue, Apr 17, 2012 at 04:33:25PM -0700, Chase Douglas wrote:
> As a special case, if a pointer emulated touch has no listeners and the
> device is explicitly grabbed for pointer events, create a new dix touch
> record for the grab only.

this should include "and the touch is still physically down".

Cheers,
  Peter
 
> This allows for clients to "hand off" grabs. For example, when dragging
> a window under compiz the window decorator sees the button press and
> then ungrabs the implicit grab. It then tells compiz to grab the device,
> and compiz then moves the window with the pointer motion. This is racy,
> but is allowed by the input protocol for pointer events when there are
> no other clients with a grab on the device.
> 
> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
> ---
>  Xi/exevents.c |   28 ++++++++++++++++++++++++++++
>  dix/touch.c   |    5 +++++
>  2 files changed, 33 insertions(+), 0 deletions(-)
> 
> diff --git a/Xi/exevents.c b/Xi/exevents.c
> index ae3652b..c8bd222 100644
> --- a/Xi/exevents.c
> +++ b/Xi/exevents.c
> @@ -1610,6 +1610,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
>      else
>          ti = TouchFindByClientID(dev, touchid);
>  
> +    /* Under the following circumstances we create a new touch record for an
> +     * existing touch:
> +     *
> +     * - The touch may be pointer emulated
> +     * - An explicit grab is active on the device
> +     * - The grab is a pointer grab
> +     *
> +     * This allows for an explicit grab to receive pointer events for an already
> +     * active touch.
> +     */
> +    if (!ti && type != ET_TouchBegin && emulate_pointer &&
> +        dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
> +        (dev->deviceGrab.grab->grabtype == CORE ||
> +         dev->deviceGrab.grab->grabtype == XI ||
> +         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
> +        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
> +                             emulate_pointer);
> +        if (!ti) {
> +            DebugF("[Xi] %s: Failed to create new dix record for explicitly "
> +                   "grabbed touchpoint %d\n",
> +                   dev->name, type, touchid);
> +            return;
> +        }
> +
> +        TouchBuildSprite(dev, ti, ev);
> +        TouchSetupListeners(dev, ti, ev);
> +    }
> +
>      if (!ti) {
>          DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
>                 dev->name, type, touchid);
> diff --git a/dix/touch.c b/dix/touch.c
> index af32103..9f849b7 100644
> --- a/dix/touch.c
> +++ b/dix/touch.c
> @@ -852,6 +852,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
>      if (dev->deviceGrab.grab)
>          TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
>  
> +    /* We set up an active touch listener for existing touches, but not any
> +     * passive grab or regular listeners. */
> +    if (ev->any.type != ET_TouchBegin)
> +        return;
> +
>      /* First, find all grabbing clients from the root window down
>       * to the deepest child window. */
>      for (i = 0; i < sprite->spriteTraceGood; i++) {
> -- 
> 1.7.9.1
> 


More information about the xorg-devel mailing list