Re: synaptics touchpad doesn't click

From: Takashi Iwai
Date: Wed Dec 16 2009 - 02:16:27 EST


At Wed, 16 Dec 2009 07:50:54 +0100,
I wrote:
>
> At Tue, 15 Dec 2009 18:59:34 -0800,
> Dmitry Torokhov wrote:
> >
> > On Tue, Dec 15, 2009 at 06:05:06PM -0700, Alex Chiang wrote:
> > > * Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>:
> > > >
> > > > The updated patch is below.
> > > >
> > > > --
> > > > Dmitry
> > >
> > > Should I test this one or wait one more iteration to address
> > > Takashi's last comments?
> > >
> >
> > Actually I think we took the wrong direction with the original patch and
> > we should do what other buttonless devices (bcm5974) do: report touchpad
> > click as left button and have Synaptics X driver provide enhanced
> > support. This way we can have both modes (ClickZones and ClickButtons)
> > and users will get to chose (provided that someone takes time to add
> > that support to Synaptics driver of course ;) ).
>
> My concern is, still, how would you identify this device. Will you
> extend also some ioctls to expose caps and extcaps? Otherwise it's
> difficult to identify this device automatically from the user-space.
>
> The user-space can know that it's button-less, yes. But, how can it
> know whether the device should be emulated via ClickZone?
> We can use a driver option to x11 synaptics driver for that, as I
> already sent you another patch. However, the driver option is
> nowadays not preferred because xorg.conf is being dead on new
> systems...

FWIW, the patch below is to add clickpad feature to x11 synaptics driver
1.1.3. It's almost straightforward conversion from my kernel patch.
(The vertical coordinate had to be flipped, though.)


Takashi

---
---
include/synaptics-properties.h | 3 ++
include/synaptics.h | 1
man/synaptics.man | 5 ++++
src/synaptics.c | 42 +++++++++++++++++++++++++++++++++++++++++
src/synapticsstr.h | 1
tools/synclient.c | 2 +
6 files changed, 54 insertions(+)

--- a/include/synaptics.h
+++ b/include/synaptics.h
@@ -134,6 +134,7 @@
double press_motion_min_factor; /* factor applied on speed when finger pressure is at minimum */
double press_motion_max_factor; /* factor applied on speed when finger pressure is at minimum */
Bool grab_event_device; /* grab event device for exclusive use? */
+ Bool clickpad; /* clickpad mode */
} SynapticsSHM;

/*
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -499,6 +499,7 @@
pars->press_motion_min_factor = xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0);
pars->press_motion_max_factor = xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0);
pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", TRUE);
+ pars->clickpad = xf86SetBoolOption(opts, "Clickpad", FALSE);

/* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
if (pars->top_edge > pars->bottom_edge) {
@@ -1902,6 +1903,44 @@
}
}

+/* left and right clickpad button ranges;
+ * the gap between them is interpreted as a middle-button click
+ */
+#define CLICKPAD_LEFT_BTN_X(p) \
+ (((p)->maxx - (p)->minx) * 2 / 5 + (p)->minx)
+#define CLICKPAD_RIGHT_BTN_X(p) \
+ (((p)->maxx - (p)->minx) * 3 / 5 + (p)->minx)
+
+static void
+MangleClickpad(SynapticsPrivate *priv, struct SynapticsHwState *hw)
+{
+ SynapticsSHM *para = priv->synpara;
+
+ /* clickpad mode reports Y over YMAX as a button area */
+ if (hw->y > priv->maxy) {
+ /* clickpad reports only the middle button, and we need
+ * to fake left/right buttons depending on the touch position
+ */
+ if (hw->left || hw->middle || hw->right) { /* clicked? */
+ hw->left = hw->middle = hw->right = 0;
+ if (hw->x < CLICKPAD_LEFT_BTN_X(priv));
+ hw->left = 1;
+ else if (hw->x > CLICKPAD_RIGHT_BTN_X(priv))
+ hw->right = 1;
+ else
+ hw->middle = 1;
+ }
+ /* don't move pointer in the button area */
+ hw->x = para->x;
+ hw->y = para->y;
+ hw->z = 0;
+ } else if (hw->left || hw->middle || hw->right) {
+ /* dragging */
+ hw->left = para->left;
+ hw->right = para->right;
+ hw->middle = para->middle;
+ }
+}

/*
* React on changes in the hardware state. This function is called every time
@@ -1924,6 +1963,9 @@
int timeleft;
int i;

+ if (para->clickpad)
+ MangleClickpad(priv, hw);
+
/* update hardware state in shared memory */
para->x = hw->x;
para->y = hw->y;
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -154,6 +154,7 @@
Bool has_pressure; /* device reports pressure */

enum TouchpadModel model; /* The detected model */
+ Bool clickpad; /* clickpad mode */
} SynapticsPrivate;

#endif /* _SYNAPTICSSTR_H_ */
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -411,6 +411,11 @@
.
This can be achieved by switching to a text console and then switching
back to X.
+.TP 7
+.BI "Option \*qClickpad\*q \*q" boolean \*q
+Supports Clickpad. The driver handles a middle-button click in the
+special low area as left/right/middle buttons according to the position.
+This mode works only with evdev protocol.
.
.
.LP
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -209,6 +209,8 @@
SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1),
DEFINE_PAR("GrabEventDevice", grab_event_device, PT_BOOL, 0, 1,
SYNAPTICS_PROP_GRAB, 8, 0),
+ DEFINE_PAR("Clickpad", clickpad, PT_BOOL, 0, 1,
+ SYNAPTICS_PROP_CLICKPAD, 8, 0),
{ NULL, 0, 0, 0, 0 }
};

--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -142,4 +142,7 @@
/* 8 bit (BOOL) */
#define SYNAPTICS_PROP_GRAB "Synaptics Grab Event Device"

+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_CLICKPAD "Synaptics Clickpad Mode"
+
#endif /* _SYNAPTICS_PROPERTIES_H_ */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/