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>
This commit is contained in:
Patrick Curran
2010-07-23 17:28:01 -05:00
committed by Peter Hutterer
parent a6ca4d2523
commit 56655fd15f
6 changed files with 46 additions and 16 deletions

View File

@@ -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 */

View File

@@ -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"

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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},