[PATCH synaptics 1/2] Added "friction physics" so coasting can stop on its own.

Peter Hutterer peter.hutterer at who-t.net
Thu Aug 19 18:13:57 PDT 2010


From: Patrick Curran <pjcurran at wisc.edu>

When you are coasting (but not corner coasting) you might want the
scrolling to slow down and stop on its own.  This also lets you
start coasting while using a two finger scroll.

Signed-off-by: Patrick Curran <pjcurran at wisc.edu>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Tested-by: Peter Hutterer <peter.hutterer at who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 include/synaptics-properties.h |    2 +-
 man/synaptics.man              |   11 +++++++++--
 src/properties.c               |   13 +++++++------
 src/synaptics.c                |   34 +++++++++++++++++++++++++++-------
 src/synapticsstr.h             |    1 +
 tools/synclient.c              |    1 +
 6 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
index cf330d8..9c6a2ee 100644
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -130,7 +130,7 @@
 /* 32 bit, 2 values, width, z */
 #define SYNAPTICS_PROP_PALM_DIMENSIONS "Synaptics Palm Dimensions"
 
-/* FLOAT */
+/* FLOAT, 2 values, speed, friction */
 #define SYNAPTICS_PROP_COASTING_SPEED "Synaptics Coasting Speed"
 
 /* 32 bit, 2 values, min, max */
diff --git a/man/synaptics.man b/man/synaptics.man
index 590a380..b268a23 100644
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -397,10 +397,17 @@ Minimum finger pressure at which touch is considered a palm. Property:
 "Synaptics Palm Dimensions"
 .TP
 .BI "Option \*qCoastingSpeed\*q \*q" float \*q
-Coasting threshold scrolling speed.
+Your finger needs to produce this many scrolls per second in order to start
+coasting.  The default is 20 which should prevent you from starting coasting
+unintentionally.
 .
 0 disables coasting. Property: "Synaptics Coasting Speed"
 .TP
+.BI "Option \*qCoastingFriction\*q \*q" float \*q
+Number of scrolls per second per second to decrease the coasting speed.  Default
+is 50.
+Property: "Synaptics Coasting Speed"
+.TP
 .BI "Option \*qSingleTapTimeout\*q \*q" integer \*q
 Timeout after a tap to recognize it as a single tap. Property: "Synaptics Tap
 Durations"
@@ -853,7 +860,7 @@ right, right + bottom, bottom, bottom + left, left, left  + top.
 
 .TP 7
 .BI "Synaptics Coasting Speed"
-FLOAT.
+FLOAT, 2 values, speed, friction.
 
 .TP 7
 .BI "Synaptics Pressure Motion"
diff --git a/src/properties.c b/src/properties.c
index b17089c..ee9a5a6 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -243,7 +243,8 @@ InitDeviceProperties(LocalDevicePtr local)
     prop_palm_dim = InitAtom(local->dev, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 2, values);
 
     fvalues[0] = para->coasting_speed;
-    prop_coastspeed = InitFloatAtom(local->dev, SYNAPTICS_PROP_COASTING_SPEED, 1, fvalues);
+    fvalues[1] = para->coasting_friction;
+    prop_coastspeed = InitFloatAtom(local->dev, SYNAPTICS_PROP_COASTING_SPEED, 2, fvalues);
 
     values[0] = para->press_motion_min_z;
     values[1] = para->press_motion_max_z;
@@ -600,14 +601,14 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
         para->palm_min_z     = dim[1];
     } else if (property == prop_coastspeed)
     {
-        float speed;
+        float *coast_speeds;
 
-        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+        if (prop->size != 2 || prop->format != 32 || prop->type != float_type)
             return BadMatch;
 
-        speed = *(float*)prop->data;
-        para->coasting_speed = speed;
-
+        coast_speeds = (float*)prop->data;
+        para->coasting_speed = coast_speeds[0];
+        para->coasting_friction = coast_speeds[1];
     } else if (property == prop_pressuremotion)
     {
         float *press;
diff --git a/src/synaptics.c b/src/synaptics.c
index 1184f30..7a800b5 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -576,6 +576,7 @@ static void set_default_parameters(LocalDevicePtr local)
     pars->trackstick_speed = xf86SetRealOption(opts, "TrackstickSpeed", 40);
     pars->scroll_dist_circ = xf86SetRealOption(opts, "CircScrollDelta", 0.1);
     pars->coasting_speed = xf86SetRealOption(opts, "CoastingSpeed", 0.0);
+    pars->coasting_friction = xf86SetRealOption(opts, "CoastingFriction", 50);
     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);
@@ -1817,20 +1818,21 @@ start_coasting(SynapticsPrivate *priv, struct SynapticsHwState *hw, edge_type ed
 
     if ((priv->scroll_packet_count > 3) && (para->coasting_speed > 0.0)) {
 	double pkt_time = (HIST(0).millis - HIST(3).millis) / 1000.0;
-	if (vertical) {
+	if (para->scroll_twofinger_vert || vertical) {
 	    double dy = estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
 	    int sdelta = para->scroll_dist_vert;
-	    if ((edge & RIGHT_EDGE) && pkt_time > 0 && sdelta > 0) {
+	    if ((para->scroll_twofinger_vert || (edge & RIGHT_EDGE)) && pkt_time > 0 && sdelta > 0) {
 		double scrolls_per_sec = dy / pkt_time / sdelta;
 		if (fabs(scrolls_per_sec) >= para->coasting_speed) {
 		    priv->autoscroll_yspd = scrolls_per_sec;
 		    priv->autoscroll_y = (hw->y - priv->scroll_y) / (double)sdelta;
 		}
 	    }
-	} else {
+	}
+	if (para->scroll_twofinger_horiz || !vertical){
 	    double dx = estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
 	    int sdelta = para->scroll_dist_horiz;
-	    if ((edge & BOTTOM_EDGE) && pkt_time > 0 && sdelta > 0) {
+	    if ((para->scroll_twofinger_horiz || (edge & BOTTOM_EDGE)) && pkt_time > 0 && sdelta > 0) {
 		double scrolls_per_sec = dx / pkt_time / sdelta;
 		if (fabs(scrolls_per_sec) >= para->coasting_speed) {
 		    priv->autoscroll_xspd = scrolls_per_sec;
@@ -1926,8 +1928,10 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	}
     }
     {
-	Bool oldv = priv->vert_scroll_edge_on || (priv->circ_scroll_on && priv->circ_scroll_vert);
-	Bool oldh = priv->horiz_scroll_edge_on || (priv->circ_scroll_on && !priv->circ_scroll_vert);
+	Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on ||
+	              (priv->circ_scroll_on && priv->circ_scroll_vert);
+	Bool oldh = priv->horiz_scroll_twofinger_on || priv->horiz_scroll_edge_on ||
+	              (priv->circ_scroll_on && !priv->circ_scroll_vert);
 	if (priv->circ_scroll_on && !finger) {
 	    /* circular scroll locks in until finger is raised */
 	    DBG(7, "cicular scroll off\n");
@@ -1968,7 +1972,8 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	 * and are no longer scrolling, then start coasting */
 	if ((oldv || oldh) && !para->scroll_edge_corner &&
 	    !(priv->circ_scroll_on || priv->vert_scroll_edge_on ||
-	      priv->horiz_scroll_edge_on)) {
+	      priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on ||
+	      priv->vert_scroll_twofinger_on)) {
 	    start_coasting(priv, hw, edge, oldv);
 	}
     }
@@ -2075,6 +2080,7 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 
     if (priv->autoscroll_yspd) {
 	double dtime = (hw->millis - HIST(0).millis) / 1000.0;
+	double ddy = para->coasting_friction * dtime;
 	priv->autoscroll_y += priv->autoscroll_yspd * dtime;
 	delay = MIN(delay, 20);
 	while (priv->autoscroll_y > 1.0) {
@@ -2085,9 +2091,17 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	    sd->up++;
 	    priv->autoscroll_y += 1.0;
 	}
+	if (abs(priv->autoscroll_yspd) < ddy) {
+	    priv->autoscroll_yspd = 0;
+	    priv->scroll_packet_count = 0;
+	} else {
+	    priv->autoscroll_yspd += (priv->autoscroll_yspd < 0 ? ddy : -1*ddy);
+	}
     }
+
     if (priv->autoscroll_xspd) {
 	double dtime = (hw->millis - HIST(0).millis) / 1000.0;
+	double ddx = para->coasting_friction * dtime;
 	priv->autoscroll_x += priv->autoscroll_xspd * dtime;
 	delay = MIN(delay, 20);
 	while (priv->autoscroll_x > 1.0) {
@@ -2098,6 +2112,12 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	    sd->left++;
 	    priv->autoscroll_x += 1.0;
 	}
+	if (abs(priv->autoscroll_xspd) < ddx) {
+	    priv->autoscroll_xspd = 0;
+	    priv->scroll_packet_count = 0;
+	} else {
+	    priv->autoscroll_xspd += (priv->autoscroll_xspd < 0 ? ddx : -1*ddx);
+	}
     }
 
     return delay;
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index caa0476..658721c 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -150,6 +150,7 @@ typedef struct _SynapticsParameters
     int palm_min_width;			    /* Palm detection width */
     int palm_min_z;			    /* Palm detection depth */
     double coasting_speed;		    /* Coasting threshold scrolling speed */
+    double coasting_friction;		    /* Number of scrolls per second per second to change coasting speed */
     int press_motion_min_z;		    /* finger pressure at which minimum pressure motion factor is applied */
     int press_motion_max_z;		    /* finger pressure at which maximum pressure motion factor is applied */
     double press_motion_min_factor;	    /* factor applied on speed when finger pressure is at minimum */
diff --git a/tools/synclient.c b/tools/synclient.c
index d5bfdf0..e7be499 100644
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -132,6 +132,7 @@ static struct Parameter params[] = {
     {"PalmMinWidth",          PT_INT,    0, 15,    SYNAPTICS_PROP_PALM_DIMENSIONS,	32,	0},
     {"PalmMinZ",              PT_INT,    0, 255,   SYNAPTICS_PROP_PALM_DIMENSIONS,	32,	1},
     {"CoastingSpeed",         PT_DOUBLE, 0, 20,    SYNAPTICS_PROP_COASTING_SPEED,	0 /* float*/,	0},
+    {"CoastingFriction",      PT_DOUBLE, 0, 255,   SYNAPTICS_PROP_COASTING_SPEED,	0 /* float*/,	1},
     {"PressureMotionMinZ",    PT_INT,    1, 255,   SYNAPTICS_PROP_PRESSURE_MOTION,	32,	0},
     {"PressureMotionMaxZ",    PT_INT,    1, 255,   SYNAPTICS_PROP_PRESSURE_MOTION,	32,	1},
     {"PressureMotionMinFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR,	0 /*float*/,	0},
-- 
1.7.2.1



More information about the xorg-devel mailing list