summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Curran <pjcurran@wisc.edu>2010-07-23 17:28:01 -0500
committerPeter Hutterer <peter.hutterer@who-t.net>2010-08-20 11:08:47 +1000
commit56655fd15f676fea143f3963e23b464b275b2e77 (patch)
tree133b0dc1342a1579f2b81420801290c67024d6a9 /src
parenta6ca4d2523904b7ce49edc29ba408979bdf0d45e (diff)
Added "friction physics" so coasting can stop on its own.
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@wisc.edu> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Tested-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'src')
-rw-r--r--src/properties.c13
-rw-r--r--src/synaptics.c34
-rw-r--r--src/synapticsstr.h1
3 files changed, 35 insertions, 13 deletions
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 */