diff options
author | Peter Osterlund <petero2@telia.com> | 2005-01-06 02:25:20 +0100 |
---|---|---|
committer | Peter Osterlund <petero2@telia.com> | 2006-04-09 04:03:03 +0200 |
commit | d0754c4c39287af2c87aeb280d46f2325849b846 (patch) | |
tree | a71e5457276a52f006125b4f56b5b2c4b04ef583 | |
parent | 7ad9b2ce77ed704b4a2537de85d81b1aaa82efaa (diff) |
Implemented coasting, ie the ability to automatically
continue scrolling with the same speed in the same direction when the
finger leaves the touchpad.
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | synaptics.c | 85 | ||||
-rw-r--r-- | synaptics.h | 6 | ||||
-rw-r--r-- | synclient.c | 1 |
4 files changed, 100 insertions, 3 deletions
@@ -131,6 +131,7 @@ CircularPad Bool Instead of being a rectangle, the edge is the ellipse PalmDetect Bool If palm detection should be enabled PalmMinWidth Int Minimum width at which touch is considered a palm PalmMinZ Int Minimum finger pressure at which touch is considered a palm +CoastingSpeed Float Coasting threshold scrolling speed. 0 disables coasting. The LeftEdge, RightEdge, TopEdge and BottomEdge parameters are used to define the edge and corner areas of the touchpad. The parameters split @@ -223,6 +224,16 @@ together with vertical scrolling, hitting the upper or lower right corner will seamlessly switch over from vertical to circular scrolling. +Coasting is enabled by setting the CoastingSpeed parameter to a +non-zero value. When coasting is enabled, horizontal/vertical +scrolling can continue after the finger is released from the +lower/right edge of the touchpad. The driver computes the scrolling +speed corresponding to the finger speed immediately before the finger +leaves the touchpad. If this scrolling speed is larger than the +CoastingSpeed parameter (measured in scroll events per second), the +scrolling will continue with the same speed in the same direction +until the finger touches the touchpad again. + FAQ --- diff --git a/synaptics.c b/synaptics.c index c8ce0c1..fe6f5e1 100644 --- a/synaptics.c +++ b/synaptics.c @@ -394,6 +394,9 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) str_par = xf86FindOptionValue(local->options, "CircScrollDelta"); if ((!str_par) || (xf86sscanf(str_par, "%lf", &pars->scroll_dist_circ) != 1)) pars->scroll_dist_circ = 0.1; + str_par = xf86FindOptionValue(local->options, "CoastingSpeed"); + if ((!str_par) || (xf86sscanf(str_par, "%lf", &pars->coasting_speed) != 1)) + pars->coasting_speed = 0.0; if (pars->circular_trigger < 0 || pars->circular_trigger > 8) { xf86Msg(X_WARNING, "Unknown circular scrolling trigger, using 0 (edges)"); @@ -1274,15 +1277,51 @@ struct ScrollData { }; static void +start_coasting(SynapticsPrivate *priv, edge_type edge) +{ + SynapticsSHM *para = priv->synpara; + + if ((priv->scroll_packet_count > 3) && (para->coasting_speed > 0.0)) { + double pkt_time = (HIST(0).millis - HIST(3).millis) / 1000.0; + if (priv->vert_scroll_on || + (priv->circ_scroll_on && priv->circ_scroll_vert)) { + 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) { + double scrolls_per_sec = dy / pkt_time / sdelta; + if (fabs(scrolls_per_sec) >= para->coasting_speed) + priv->autoscroll_yspd = scrolls_per_sec; + } + } else { + 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) { + double scrolls_per_sec = dx / pkt_time / sdelta; + if (fabs(scrolls_per_sec) >= para->coasting_speed) + priv->autoscroll_xspd = scrolls_per_sec; + } + } + } + priv->scroll_packet_count = 0; + priv->autoscroll_y = 0.0; + priv->autoscroll_x = 0.0; +} + +static int HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw, edge_type edge, Bool finger, struct ScrollData *sd) { SynapticsSHM *para = priv->synpara; + Bool scroll_stop = FALSE; + int delay = 1000000000; sd->left = sd->right = sd->up = sd->down = 0; /* scroll detection */ if (finger && !priv->finger_flag) { + priv->autoscroll_xspd = 0; + priv->autoscroll_yspd = 0; + priv->scroll_packet_count = 0; if (para->circular_scrolling) { if ((para->circular_trigger == 0 && edge) || (para->circular_trigger == 1 && edge & TOP_EDGE) || @@ -1315,14 +1354,20 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw, if (priv->circ_scroll_on && !finger) { /* circular scroll locks in until finger is raised */ DBG(7, ErrorF("cicular scroll off\n")); - priv->circ_scroll_on = FALSE; + scroll_stop = TRUE; } if (priv->vert_scroll_on && (!(edge & RIGHT_EDGE) || !finger)) { DBG(7, ErrorF("vert edge scroll off\n")); - priv->vert_scroll_on = FALSE; + scroll_stop = TRUE; } if (priv->horiz_scroll_on && (!(edge & BOTTOM_EDGE) || !finger)) { DBG(7, ErrorF("horiz edge scroll off\n")); + scroll_stop = TRUE; + } + if (scroll_stop) { + start_coasting(priv, edge); + priv->circ_scroll_on = FALSE; + priv->vert_scroll_on = FALSE; priv->horiz_scroll_on = FALSE; } @@ -1348,6 +1393,9 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw, } } + if (priv->vert_scroll_on || priv->horiz_scroll_on || priv->circ_scroll_on) + priv->scroll_packet_count++; + if (priv->vert_scroll_on) { /* + = down, - = up */ int delta = para->scroll_dist_vert; @@ -1400,6 +1448,35 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw, } } } + + if (priv->autoscroll_yspd) { + double dtime = (hw->millis - HIST(0).millis) / 1000.0; + priv->autoscroll_y += priv->autoscroll_yspd * dtime; + delay = MIN(delay, 20); + while (priv->autoscroll_y > 1.0) { + sd->down++; + priv->autoscroll_y -= 1.0; + } + while (priv->autoscroll_y < -1.0) { + sd->up++; + priv->autoscroll_y += 1.0; + } + } + if (priv->autoscroll_xspd) { + double dtime = (hw->millis - HIST(0).millis) / 1000.0; + priv->autoscroll_x += priv->autoscroll_xspd * dtime; + delay = MIN(delay, 20); + while (priv->autoscroll_x > 1.0) { + sd->right++; + priv->autoscroll_x -= 1.0; + } + while (priv->autoscroll_x < -1.0) { + sd->left++; + priv->autoscroll_x += 1.0; + } + } + + return delay; } /* @@ -1497,7 +1574,9 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) if (timeleft > 0) delay = MIN(delay, timeleft); - HandleScrolling(priv, hw, edge, finger, &scroll); + timeleft = HandleScrolling(priv, hw, edge, finger, &scroll); + if (timeleft > 0) + delay = MIN(delay, timeleft); timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy); delay = MIN(delay, timeleft); diff --git a/synaptics.h b/synaptics.h index 7369b1b..75b3f00 100644 --- a/synaptics.h +++ b/synaptics.h @@ -81,6 +81,7 @@ typedef struct _SynapticsSHM Bool palm_detect; /* Enable Palm Detection */ int palm_min_width; /* Palm detection width */ int palm_min_z; /* Palm detection depth */ + double coasting_speed; /* Coasting threshold scrolling speed */ } SynapticsSHM; /* @@ -181,6 +182,11 @@ typedef struct _SynapticsPrivateRec Bool circ_scroll_on; /* scrolling flag */ Bool circ_scroll_vert; /* True: Generate vertical scroll events False: Generate horizontal events */ + double autoscroll_xspd; /* Horizontal coasting speed */ + double autoscroll_yspd; /* Vertical coasting speed */ + double autoscroll_x; /* Accumulated horizontal coasting scroll */ + double autoscroll_y; /* Accumulated vertical coasting scroll */ + int scroll_packet_count; /* Scroll duration */ double frac_x, frac_y; /* absolute -> relative fraction */ enum MidButtonEmulation mid_emu_state; /* emulated 3rd button */ int repeatButtons; /* buttons for repeat */ diff --git a/synclient.c b/synclient.c index 11093eb..d443212 100644 --- a/synclient.c +++ b/synclient.c @@ -89,6 +89,7 @@ static struct Parameter params[] = { DEFINE_PAR("PalmDetect", palm_detect, PT_BOOL, 0, 1), DEFINE_PAR("PalmMinWidth", palm_min_width, PT_INT, 0, 15), DEFINE_PAR("PalmMinZ", palm_min_z, PT_INT, 0, 255), + DEFINE_PAR("CoastingSpeed", coasting_speed, PT_DOUBLE, 0, 20), { 0, 0, 0, 0, 0 } }; |