[PATCH 10/18] Add multi-touch support

Peter Hutterer peter.hutterer at who-t.net
Wed Oct 13 21:54:47 PDT 2010


On Wed, Oct 13, 2010 at 08:12:12AM +0200, Takashi Iwai wrote:
> 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.

hence the suggestion to wrap through mtdev, which does the tracking for us.
 
> > >  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.

oh, I didn't know this. that should go into a comment and the commit message
then. Though a few touchpads support up to 4 fingers, isn't it (Henrik,
what about the apple touchpads?)
and either way, keeping it generic from the start saves us some unexpected
pain later.

Cheers,
  Peter


More information about the xorg-devel mailing list