summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Milone <alberto.milone@canonical.com>2009-07-16 12:08:08 +0200
committerPeter Hutterer <peter.hutterer@who-t.net>2009-07-17 10:42:31 +1000
commit7179a0eb11a842d9d5a420f5702a411b0dc217a2 (patch)
tree86133842e0ba038c7cc4fab5c8aa7095d932aff7
parent0c3fbceb1b2a18f92166fe75c44b5aaada693c4b (diff)
Add active area outside of which movements, scrolling, tapping are ignored.
On some touchpads physical buttons are located under the touchpad surface. As a result, when users try to perform a click, by pressing that part of the surface of the touchpad, they get a click, a movement, a tap and (in some cases) a scroll, which can make clicks quite inaccurate. The "Synaptics Area" property can be used to define the edges of the active area of the touchpad so that all movement, scrolling and tapping which take place outside of this area will be ignored. This property is disabled by default. Fixes xorg bug #21613. Signed-off-by: Alberto Milone <alberto.milone@canonical.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r--include/synaptics-properties.h3
-rw-r--r--man/synaptics.man37
-rw-r--r--src/properties.c20
-rw-r--r--src/synaptics.c81
-rw-r--r--src/synapticsstr.h1
-rw-r--r--tools/synclient.c4
6 files changed, 129 insertions, 17 deletions
diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
index 3153d73..cf330d8 100644
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -152,4 +152,7 @@
/* 32 bit unsigned, 2 values, vertical, horizontal in units/millimeter */
#define SYNAPTICS_PROP_RESOLUTION "Synaptics Pad Resolution"
+/* 32 bit, 4 values, left, right, top, bottom */
+#define SYNAPTICS_PROP_AREA "Synaptics Area"
+
#endif /* _SYNAPTICS_PROPERTIES_H_ */
diff --git a/man/synaptics.man b/man/synaptics.man
index a69c3c4..9d30a20 100644
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -481,6 +481,34 @@ A good way to find appropriate edge parameters is to enable the
SHMConfig option and run "synclient \-m 1" to see the x/y coordinates
corresponding to different positions on the touchpad.
.
+.TP
+.BI "Option \*qAreaLeftEdge\*q \*q" boolean \*q
+Ignore movements, scrolling and tapping which take place left of this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaLeftEdge option to any integer value other than zero. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaRightEdge\*q \*q" boolean \*q
+Ignore movements, scrolling and tapping which take place right of this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaRightEdge option to any integer value other than zero. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaTopEdge\*q \*q" boolean \*q
+Ignore movements, scrolling and tapping which take place above this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaTopEdge option to any integer value other than zero. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaBottomEdge\*q \*q" boolean \*q
+Ignore movements, scrolling and tapping which take place below this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaBottomEdge option to any integer value other than zero. Property: "Synaptics Area"
+.
.LP
A tap event happens when the finger is touched and released in a time
interval shorter than MaxTapTime, and the touch and release
@@ -821,6 +849,15 @@ FLOAT, 2 values, min, max.
8 bit (BOOL), 1 value, tap-and-drag.
.TP 7
+.BI "Synaptics Area"
+The AreaLeftEdge, AreaRightEdge, AreaTopEdge and AreaBottomEdge parameters are used to
+define the edges of the active area of the touchpad. All movements, scrolling and tapping
+which take place outside of this area will be ignored. This property is disabled by
+default.
+
+32 bit, 4 values, left, right, top, bottom. 0 disables an element.
+
+.TP 7
.BI "Synaptics Capabilities"
This read-only property expresses the physical capability of the touchpad,
most notably whether the touchpad hardware supports multi-finger tapping and
diff --git a/src/properties.c b/src/properties.c
index 43bcabb..d03ea6e 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -83,6 +83,7 @@ Atom prop_grab = 0;
Atom prop_gestures = 0;
Atom prop_capabilities = 0;
Atom prop_resolution = 0;
+Atom prop_area = 0;
static Atom
InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
@@ -268,6 +269,11 @@ InitDeviceProperties(LocalDevicePtr local)
values[1] = para->resolution_horiz;
prop_resolution = InitAtom(local->dev, SYNAPTICS_PROP_RESOLUTION, 32, 2, values);
+ values[0] = para->area_left_edge;
+ values[1] = para->area_right_edge;
+ values[2] = para->area_top_edge;
+ values[3] = para->area_bottom_edge;
+ prop_area = InitAtom(local->dev, SYNAPTICS_PROP_AREA, 32, 4, values);
}
int
@@ -622,6 +628,20 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
{
/* read-only */
return BadValue;
+ } else if (property == prop_area)
+ {
+ INT32 *area;
+ if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ area = (INT32*)prop->data;
+ if ((((area[0] != 0) && (area[1] != 0)) && (area[0] > area[1]) ) || (((area[2] != 0) && (area[3] != 0)) && (area[2] > area[3])))
+ return BadValue;
+
+ para->area_left_edge = area[0];
+ para->area_right_edge = area[1];
+ para->area_top_edge = area[2];
+ para->area_bottom_edge = area[3];
}
return Success;
diff --git a/src/synaptics.c b/src/synaptics.c
index d95aa30..dc833c5 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -465,6 +465,11 @@ static void set_default_parameters(LocalDevicePtr local)
pars->top_edge = xf86SetIntOption(opts, "TopEdge", t);
pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", b);
+ pars->area_top_edge = xf86SetIntOption(opts, "AreaTopEdge", 0);
+ pars->area_bottom_edge = xf86SetIntOption(opts, "AreaBottomEdge", 0);
+ pars->area_left_edge = xf86SetIntOption(opts, "AreaLeftEdge", 0);
+ pars->area_right_edge = xf86SetIntOption(opts, "AreaRightEdge", 0);
+
pars->finger_low = xf86SetIntOption(opts, "FingerLow", fingerLow);
pars->finger_high = xf86SetIntOption(opts, "FingerHigh", fingerHigh);
pars->finger_press = xf86SetIntOption(opts, "FingerPress", fingerPress);
@@ -1079,6 +1084,29 @@ propertyTimerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
}
#endif
+/* Checks whether coordinates are in the Synaptics Area
+ * or not. If no Synaptics Area is defined (i.e. if
+ * priv->synpara.area_{left|right|top|bottom}_edge are
+ * all set to zero), the function returns TRUE.
+ */
+static Bool
+is_inside_active_area(SynapticsPrivate *priv, int x, int y)
+{
+ Bool inside_area = TRUE;
+
+ if ((priv->synpara.area_left_edge != 0) && (x < priv->synpara.area_left_edge))
+ inside_area = FALSE;
+ else if ((priv->synpara.area_right_edge != 0) && (x > priv->synpara.area_right_edge))
+ inside_area = FALSE;
+
+ if ((priv->synpara.area_top_edge != 0) && (y < priv->synpara.area_top_edge))
+ inside_area = FALSE;
+ else if ((priv->synpara.area_bottom_edge != 0) && (y > priv->synpara.area_bottom_edge))
+ inside_area = FALSE;
+
+ return inside_area;
+}
+
static CARD32
timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
{
@@ -1427,7 +1455,7 @@ GetTimeOut(SynapticsPrivate *priv)
static int
HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
- edge_type edge, enum FingerState finger)
+ edge_type edge, enum FingerState finger, Bool inside_active_area)
{
SynapticsParameters *para = &priv->synpara;
Bool touch, release, is_timeout, move;
@@ -1478,6 +1506,10 @@ HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
goto restart;
} else if (release) {
SelectTapButton(priv, edge);
+ /* Disable taps outside of the active area */
+ if (!inside_active_area) {
+ priv->tap_button = 0;
+ }
SetTapState(priv, TS_2A, hw->millis);
}
break;
@@ -2092,6 +2124,7 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
int delay = 1000000000;
int timeleft;
int i;
+ Bool inside_active_area;
/* update hardware state in shared memory */
if (shm)
@@ -2231,11 +2264,12 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
}
edge = edge_detection(priv, hw->x, hw->y);
+ inside_active_area = is_inside_active_area(priv, hw->x, hw->y);
finger = SynapticsDetectFinger(priv, hw);
/* tap and drag detection */
- timeleft = HandleTapProcessing(priv, hw, edge, finger);
+ timeleft = HandleTapProcessing(priv, hw, edge, finger, inside_active_area);
if (timeleft > 0)
delay = MIN(delay, timeleft);
@@ -2278,6 +2312,13 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
}
/* Post events */
+
+ /* Process movements only if coordinates are
+ * in the Synaptics Area
+ */
+ if (!inside_active_area)
+ dx = dy = 0;
+
if (dx || dy)
xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy);
@@ -2300,22 +2341,28 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
xf86PostButtonEvent(local->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0);
}
- while (scroll.up-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 4, !hw->up, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 4, hw->up, 0, 0);
- }
- while (scroll.down-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 5, !hw->down, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 5, hw->down, 0, 0);
- }
- while (scroll.left-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 6, TRUE, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 6, FALSE, 0, 0);
- }
- while (scroll.right-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 7, TRUE, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 7, FALSE, 0, 0);
+ /* Process scroll events only if coordinates are
+ * in the Synaptics Area
+ */
+ if (inside_active_area) {
+ while (scroll.up-- > 0) {
+ xf86PostButtonEvent(local->dev, FALSE, 4, !hw->up, 0, 0);
+ xf86PostButtonEvent(local->dev, FALSE, 4, hw->up, 0, 0);
+ }
+ while (scroll.down-- > 0) {
+ xf86PostButtonEvent(local->dev, FALSE, 5, !hw->down, 0, 0);
+ xf86PostButtonEvent(local->dev, FALSE, 5, hw->down, 0, 0);
+ }
+ while (scroll.left-- > 0) {
+ xf86PostButtonEvent(local->dev, FALSE, 6, TRUE, 0, 0);
+ xf86PostButtonEvent(local->dev, FALSE, 6, FALSE, 0, 0);
+ }
+ while (scroll.right-- > 0) {
+ xf86PostButtonEvent(local->dev, FALSE, 7, TRUE, 0, 0);
+ xf86PostButtonEvent(local->dev, FALSE, 7, FALSE, 0, 0);
+ }
}
+
if (double_click) {
int i;
for (i = 0; i < 2; i++) {
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index 8348e72..f2bf7d4 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -166,6 +166,7 @@ typedef struct _SynapticsParameters
Bool tap_and_drag_gesture; /* Switches the tap-and-drag gesture on/off */
unsigned int resolution_horiz; /* horizontal resolution of touchpad in units/mm */
unsigned int resolution_vert; /* vertical resolution of touchpad in units/mm */
+ int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
} SynapticsParameters;
diff --git a/tools/synclient.c b/tools/synclient.c
index eed0c79..032b129 100644
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -139,6 +139,10 @@ static struct Parameter params[] = {
{"PressureMotionMaxFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1},
{"GrabEventDevice", PT_BOOL, 0, 1, SYNAPTICS_PROP_GRAB, 8, 0},
{"TapAndDragGesture", PT_BOOL, 0, 1, SYNAPTICS_PROP_GESTURES, 8, 0},
+ {"AreaLeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 0},
+ {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1},
+ {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2},
+ {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3},
{ NULL, 0, 0, 0, 0 }
};