At Thu, 29 Apr 2010 17:03:59 +1000,
Peter Hutterer wrote:
> 
> 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 <[email protected]>
> > ---
> > 
> > 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.

OK, I'll update in the next week after I back from my vacation.


thanks,

Takashi
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to