[PATCH 10/18] Add multi-touch support

Takashi Iwai tiwai at suse.de
Tue Oct 12 23:12:12 PDT 2010


At Wed, 13 Oct 2010 14:25:16 +1000,
Peter Hutterer wrote:
> 
> On Fri, Oct 08, 2010 at 07:22:34PM +0200, Takashi Iwai wrote:
> > Signed-off-by: Takashi Iwai <tiwai at suse.de>
> > ---
> >  src/eventcomm.c    |   56 +++++++++++++++++++--
> >  src/synaptics.c    |  136 ++++++++++++++++++++++++++++++++++++++++++++++++----
> >  src/synapticsstr.h |   12 +++++
> >  src/synproto.h     |    6 ++
> >  4 files changed, 196 insertions(+), 14 deletions(-)
> > 
> > diff --git a/src/eventcomm.c b/src/eventcomm.c
> > index 76ff69d..5969448 100644
> > --- a/src/eventcomm.c
> > +++ b/src/eventcomm.c
> > @@ -53,6 +53,17 @@
> >  
> >  #define SYNAPTICS_LED_SYS_FILE	"/sys/class/leds/psmouse::synaptics/brightness"
> >  
> > +#ifndef SYN_MT_REPORT
> > +#define SYN_MT_REPORT		2
> > +#endif
> > +#ifndef ABS_MT_POSITION_X
> > +#define ABS_MT_POSITION_X	0x35
> > +#define ABS_MT_POSITION_Y	0x36
> > +#endif
> > +#ifndef ABS_MT_PRESSURE
> > +#define ABS_MT_PRESSURE		0x3a
> > +#endif
> > +
> >  /*****************************************************************************
> >   *	Function Definitions
> >   ****************************************************************************/
> > @@ -168,6 +179,22 @@ event_query_info(InputInfoPtr pInfo)
> >      }
> >  }
> >  
> > +static void event_query_multi_touch(LocalDevicePtr local)
> > +{
> > +    SynapticsPrivate *priv = (SynapticsPrivate *)local->private;
> > +    unsigned long absbits[NBITS(ABS_MAX)] = {0};
> > +    int rc;
> > +
> > +    priv->can_multi_touch = FALSE;
> 
> has_multitouch would be more in line with the has_left, has_right, etc.
> 
> > +    if (priv->model != MODEL_SYNAPTICS)
> > +	return;
> > +    SYSCALL(rc = ioctl(local->fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
> > +    if (rc >= 0 && TEST_BIT(ABS_MT_POSITION_X, absbits)) {
> > +	priv->can_multi_touch = TRUE;
> > +	xf86Msg(X_INFO, "%s: supports multi-touch finger detection\n", local->name);
> > +    }
> > +}
> > +
> 
> I think we should just rely on MT_SLOTS here and wrap devices that don't do
> it with mtdev. It'll likely make the code simpler (especially in regards to
> tracking the primary) and I can blame Henrik if the tracking doesn't work ;)

Hm, synaptics devices don't track individual points (MT type A), thus
MT_SLOTS can't be used.


> >  static void
> >  event_query_clickpad(LocalDevicePtr local)
> >  {
> > @@ -175,7 +202,7 @@ event_query_clickpad(LocalDevicePtr local)
> >  
> >      /* clickpad device reports only the single left button mask */
> >      if (priv->has_left && !priv->has_right && !priv->has_middle &&
> > -	!priv->has_double &&
> > +	(!priv->has_double || priv->can_multi_touch) &&
> >  	priv->model == MODEL_SYNAPTICS) {
> >  	priv->is_clickpad = TRUE;
> >  	/* enable right/middle button caps; otherwise gnome-settings-daemon
> > @@ -383,21 +410,27 @@ EventReadHwState(InputInfoPtr pInfo,
> >  	switch (ev.type) {
> >  	case EV_SYN:
> >  	    switch (ev.code) {
> > +	    case SYN_MT_REPORT:
> > +		hw->multi_touch_count++;
> > +		break;
> >  	    case SYN_REPORT:
> >  		if (comm->oneFinger)
> > -		    hw->numFingers = 1;
> > +		    hw->numFingers = hw->multi_touch_count ? hw->multi_touch_count : 1;
> >  		else if (comm->twoFingers)
> >  		    hw->numFingers = 2;
> >  		else if (comm->threeFingers)
> >  		    hw->numFingers = 3;
> >  		else
> >  		    hw->numFingers = 0;
> > +		hw->multi_touch = hw->multi_touch_count;
> > +		hw->multi_touch_count = 0;
> >  		/* if the coord is out of range, we filter it out */
> >  		if (priv->is_clickpad && hw->z > 0 && (hw->x < minx || hw->x > maxx || hw->y < miny || hw->y > maxy))
> >  			return FALSE;
> >  		*hwRet = *hw;
> >  		return TRUE;
> >  	    }
> > +	    break;
> >  	case EV_KEY:
> >  	    v = (ev.value ? TRUE : FALSE);
> >  	    switch (ev.code) {
> > @@ -458,13 +491,25 @@ EventReadHwState(InputInfoPtr pInfo,
> >  	case EV_ABS:
> >  	    switch (ev.code) {
> >  	    case ABS_X:
> > -		hw->x = ev.value;
> > +	    case ABS_MT_POSITION_X:
> > +		if (hw->multi_touch_count)
> > +		    hw->multi_touch_x = ev.value;
> > +		else
> > +		    hw->x = ev.value;
> 
> if I read this correctly this patch doesn't add multi-touch support but only
> two-finger support, otherwise you'd be overwriting the value after the
> second finger.

The odd thing is that there is no third finger tracking.  Synaptics devices
track up to two finger points although it can detect number of fingers up to
three.

So, in my code, I only put the primary and the rest fingers for simplicity
(so that hw->{x,y,z} notions remain).

> a different alternative to this would be to buffer all MT events in a
> hw->mt[touchpoint] array of structs and then transfer the first to
> hw->x/y/z at the end of HandleState/EV_SYN. it would greatly reduce the
> number of if (multitouch) and improve readability.

Sounds good.


> but aside from this, this patch needs to be split into the actual MT
> handling and the clickpad-related area handling. as for gestures in the
> driver - see my other email.

Splitting would be easy.


thanks,

Takashi


More information about the xorg-devel mailing list