[PATCH v3] Add Clickpad support

Peter Hutterer peter.hutterer at who-t.net
Thu Apr 29 00:03:59 PDT 2010


On Fri, Apr 23, 2010 at 05:39:04PM +0200, Takashi Iwai wrote:
> This patch adds the support for Synaptics Clickpad devices.
> It requires the change in Linux kernel synaptics input driver, found in
> 	https://patchwork.kernel.org/patch/92435/
> The kernel patch is already included in linux-input GIT tree, which
> will hit Linus tree sooner or later.
> 
> When the kernel driver sets only the left-button bit evbit and no
> multi-finger is possible, Clickpad mode is activated.  In this mode,
> the bottom touch area is used as button emulations.  Clicking at the
> bottom-left, bottom-center and bottom-right zone corresponds to a left,
> center and right click.
> 
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> ---
> 
> v2->v3: Fix the mis-detection of Clickpad device with double-tap feature
>         (e.g. MacBook)
>         Fix one forgotten spacing issue Peter suggested
> 
>  src/eventcomm.c    |    6 ++++
>  src/synaptics.c    |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/synapticsstr.h |    2 +
>  3 files changed, 79 insertions(+), 1 deletions(-)
> 
> diff --git a/src/eventcomm.c b/src/eventcomm.c
> index d00d810..6b44778 100644
> --- a/src/eventcomm.c
> +++ b/src/eventcomm.c
> @@ -252,6 +252,12 @@ event_query_axis_ranges(LocalDevicePtr local)
>  	if ((priv->has_triple = (TEST_BIT(BTN_TOOL_TRIPLETAP, keybits) != 0)))
>  	   strcat(buf, " triple");
>  	xf86Msg(X_INFO, "%s: buttons:%s\n", local->name, buf);
> +
> +	/* clickpad device reports only the single left button mask */
> +	if (priv->has_left && !priv->has_right && !priv->has_middle && !priv->has_double) {
> +	    priv->is_clickpad = TRUE;
> +	    xf86Msg(X_INFO, "%s: is Clickpad device\n", local->name);
> +	}
>      }
>  }
>  
> diff --git a/src/synaptics.c b/src/synaptics.c
> index 091dbe1..554f7a3 100644
> --- a/src/synaptics.c
> +++ b/src/synaptics.c
> @@ -457,6 +457,18 @@ static void set_default_parameters(LocalDevicePtr local)
>          vertResolution = priv->resy;
>      }
>  
> +    /* Clickpad mode -- bottom area is used as buttons */
> +    if (priv->is_clickpad) {
> +	int button_bottom;
> +	/* Clickpad devices usually the button area at the bottom, and
> +	 * its size seems ca. 20% of the touchpad height no matter how
> +	 * large the pad is.
> +	 */
> +	button_bottom = priv->maxy - (abs(priv->maxy - priv->miny) * 20) / 100;
> +	if (button_bottom < b && button_bottom >= t)
> +	    b = button_bottom;
> +    }
> +
>      /* set the parameters */
>      pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l);
>      pars->right_edge = xf86SetIntOption(opts, "RightEdge", r);
> @@ -2052,6 +2064,59 @@ HandleClickWithFingers(SynapticsParameters *para, struct SynapticsHwState *hw)
>      }
>  }
>  
> +/* clickpad event handling */
> +static void
> +HandleClickpad(LocalDevicePtr local, struct SynapticsHwState *hw, edge_type edge)
> +{
> +    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
> +    SynapticsParameters *para = &priv->synpara;
> +
> +    if (edge & BOTTOM_EDGE) {
> +	/* button area */
> +	int width = priv->maxx - priv->minx;
> +	int left_button_x, right_button_x;
> +
> +	/* left and right clickpad button ranges;
> +	 * the gap between them is interpreted as a middle-button click
> +	 */
> +	left_button_x = width * 2 / 5 + priv->minx;
> +	right_button_x = width * 3 / 5 + priv->minx;
> +
> +	/* clickpad reports only one button, and we need
> +	 * to fake left/right buttons depending on the touch position
> +	 */
> +	if (hw->left) { /* clicked? */
> +	    hw->left = 0;
> +	    if (hw->x < left_button_x)
> +		hw->left = 1;
> +	    else if (hw->x > right_button_x)
> +		hw->right = 1;
> +	    else
> +		hw->middle = 1;
> +	}
> +
> +	/* Don't move pointer position in the button area during clicked,
> +	 * except for horiz/vert scrolling is enabled.
> +	 *
> +	 * The synaptics driver tends to be pretty sensitive.  This hack
> +	 * is to avoid that the pointer moves slightly and misses the
> +	 * poistion you aimed to click.
> +	 *
> +	 * Also, when the pointer movement is reported, the dragging
> +	 * (with a sort of multi-touching) doesn't work well, too.
> +	 */
> +	if (hw->left || !(para->scroll_edge_horiz ||
> +			  ((edge & RIGHT_EDGE) && para->scroll_edge_vert)))
> +	    hw->z = 0; /* don't move pointer */
> +
> +    } else if (hw->left) {
> +	/* dragging */
> +	hw->left = priv->prev_hw.left;
> +	hw->right = priv->prev_hw.right;
> +	hw->middle = priv->prev_hw.middle;
> +    }
> +    priv->prev_hw = *hw;
> +}
>  
>  /*
>   * React on changes in the hardware state. This function is called every time
> @@ -2102,6 +2167,12 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
>      if (para->touchpad_off == 1)
>  	return delay;
>  
> +    edge = edge_detection(priv, hw->x, hw->y);
> +
> +    /* Clickpad handling for button area */
> +    if (priv->is_clickpad)
> +	HandleClickpad(local, hw, edge);
> +
>      /* Treat the first two multi buttons as up/down for now. */
>      hw->up |= hw->multi[0];
>      hw->down |= hw->multi[1];
> @@ -2152,7 +2223,6 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
>  	hw->multi[2] = hw->multi[3] = FALSE;
>      }
>  
> -    edge = edge_detection(priv, hw->x, hw->y);
>      inside_active_area = is_inside_active_area(priv, hw->x, hw->y);
>  
>      finger = SynapticsDetectFinger(priv, hw);
> diff --git a/src/synapticsstr.h b/src/synapticsstr.h
> index bd19c79..05e43d3 100644
> --- a/src/synapticsstr.h
> +++ b/src/synapticsstr.h
> @@ -232,6 +232,8 @@ typedef struct _SynapticsPrivateRec
>      Bool has_double;			/* double click detected for this device */
>      Bool has_triple;			/* triple click detected for this device */
>      Bool has_pressure;			/* device reports pressure */
> +    Bool is_clickpad;			/* is Clickpad device (one-button) */
> +    struct SynapticsHwState prev_hw;	/* previous h/w state (for clickpad) */
>  
>      enum TouchpadModel model;          /* The detected model */
>  } SynapticsPrivate;
> -- 
> 1.7.0.4

can you send me a man page update for this change as well? Just so something
is in the man page informing the user what ClickPad in the log means. I'll
squash it on top of this one then.

Cheers,
  Peter


More information about the xorg-devel mailing list