From: Patrick Curran <[email protected]>

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 <[email protected]>
Reviewed-by: Peter Hutterer <[email protected]>
Tested-by: Peter Hutterer <[email protected]>
Signed-off-by: Peter Hutterer <[email protected]>
---
 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

_______________________________________________
[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