File xf86-input-synaptics-add-clickpad-support.diff of Package xorg-x11-driver-input
From 40041cd6ece0a73ac2c4ab99c14a79500089dd64 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 13 Apr 2010 17:25:23 +0200
Subject: [PATCH 1/7] Add Clickpad support
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 2.6.34.
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@suse.de>
---
src/eventcomm.c | 6 +++++
src/synaptics.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/synapticsstr.h | 2 +
3 files changed, 66 insertions(+)
--- a/src/eventcomm.c
+++ b/src/eventcomm.c
@@ -269,6 +269,12 @@
}
xf86Msg(X_PROBED, "%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_PROBED, "%s: is Clickpad device\n", local->name);
+ }
}
}
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -510,6 +510,18 @@
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);
@@ -518,6 +530,10 @@
pars->area_top_edge = set_percent_option(opts, "AreaTopEdge", height, priv->miny);
pars->area_bottom_edge = set_percent_option(opts, "AreaBottomEdge", height, priv->miny);
+ /* in clickpad mode, we don't want to sense the button area as default */
+ if (pars->area_bottom_edge == 0 && priv->is_clickpad)
+ pars->area_bottom_edge = b;
+
pars->area_left_edge = set_percent_option(opts, "AreaLeftEdge", width, priv->minx);
pars->area_right_edge = set_percent_option(opts, "AreaRightEdge", width, priv->minx);
@@ -1064,6 +1080,44 @@
return Success;
}
+/* clickpad event handling */
+static void
+handle_clickpad(LocalDevicePtr local, struct SynapticsHwState *hw)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
+ SynapticsParameters *para = &priv->synpara;
+
+ if (hw->left) { /* clicked? */
+ if (hw->y > para->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
+ */
+ 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;
+ } else {
+ /* dragging */
+ hw->left = priv->prev_hw.left;
+ hw->right = priv->prev_hw.right;
+ hw->middle = priv->prev_hw.middle;
+ }
+ }
+ priv->prev_hw = *hw;
+}
/*
* Convert from absolute X/Y coordinates to a coordinate system where
@@ -2230,6 +2284,10 @@
SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
SynapticsParameters *para = &priv->synpara;
+ /* Clickpad handling for button area */
+ if (priv->is_clickpad)
+ handle_clickpad(local, hw);
+
/* Treat the first two multi buttons as up/down for now. */
hw->up |= hw->multi[0];
hw->down |= hw->multi[1];
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -235,6 +235,8 @@
Bool has_pressure; /* device reports pressure */
Bool has_width; /* device reports finger width */
Bool has_scrollbuttons; /* device has physical scrollbuttons */
+ 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;