diff options
author | Patrick Curran <pjcurran@wisc.edu> | 2010-07-23 17:28:01 -0500 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2010-08-20 11:08:47 +1000 |
commit | 56655fd15f676fea143f3963e23b464b275b2e77 (patch) | |
tree | 133b0dc1342a1579f2b81420801290c67024d6a9 /src | |
parent | a6ca4d2523904b7ce49edc29ba408979bdf0d45e (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.c | 13 | ||||
-rw-r--r-- | src/synaptics.c | 34 | ||||
-rw-r--r-- | src/synapticsstr.h | 1 |
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 */ |