diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2014-01-17 08:24:35 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-02-21 11:10:27 +1000 |
commit | 1bd4ca3b5af6e5ee98c7d7f153fd4ee643c29e1a (patch) | |
tree | b035dda9d5b0d3f1373f0f1608788213aca63be9 | |
parent | 90d93891be0dcc55d87c349ab438144ead818402 (diff) |
Revert "Purge scrollbuttons (repeat)"
This reverts commit 0903d99ada1755f11a2a5cbf89a345de896e18ec.
Scroll buttons are still present in some modern devices, e.g. the Fujitsu
Lifebook E782 and others in the series.
Conflicts:
include/synaptics.h
man/synaptics.man
src/synaptics.c
(cherry picked from commit e0069c154440305ece6def92a9813a9f8004b2fb)
-rw-r--r-- | man/synaptics.man | 49 | ||||
-rw-r--r-- | src/properties.c | 56 | ||||
-rw-r--r-- | src/synaptics.c | 122 | ||||
-rw-r--r-- | src/synapticsstr.h | 14 | ||||
-rw-r--r-- | tools/synclient.c | 7 |
5 files changed, 237 insertions, 11 deletions
diff --git a/man/synaptics.man b/man/synaptics.man index 079a5f8..7652404 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -198,6 +198,41 @@ Default: 0.5 percent of the diagonal or (in case of evdev) the appropriate The minimum vertical HW distance required to generate motion events. See \fBHorizHysteresis\fR. .TP +.BI "Option \*qUpDownScrolling\*q \*q" boolean \*q +If on, the up/down buttons generate button 4/5 events. +. +If off, the up button generates a double click and the down button +generates a button 2 event. This option is only available for touchpads with +physical scroll buttons. +Property: "Synaptics Button Scrolling" +.TP +.BI "Option \*qLeftRightScrolling\*q \*q" boolean \*q +If on, the left/right buttons generate button 6/7 events. +. +If off, the left/right buttons both generate button 2 events. +This option is only available for touchpads with physical scroll buttons. +Property: "Synaptics Button Scrolling" +.TP +.BI "Option \*qUpDownScrollRepeat\*q \*q" boolean \*q +If on, and the up/down buttons are used for scrolling +(\fBUpDownScrolling\fR), these buttons will send auto-repeating 4/5 events, +with the delay between repeats determined by \fBScrollButtonRepeat\fR. +This option is only available for touchpads with physical scroll buttons. +Property: "Synaptics Button Scrolling Repeat" +.TP +.BI "Option \*qLeftRightScrollRepeat\*q \*q" boolean \*q +If on, and the left/right buttons are used for scrolling +(\fBLeftRightScrolling\fR), these buttons will send auto-repeating 6/7 events, +with the delay between repeats determined by \fBScrollButtonRepeat\fR. +This option is only available for touchpads with physical scroll buttons. +Property: "Synaptics Button Scrolling Repeat" +.TP +.BI "Option \*qScrollButtonRepeat\*q \*q" integer \*q +The number of milliseconds between repeats of button events 4-7 from the +up/down/left/right scroll buttons. +This option is only available for touchpads with physical scroll buttons. +Property: "Synaptics Button Scrolling Time" +.TP .BI "Option \*qEmulateMidButtonTime\*q \*q" integer \*q Maximum time (in milliseconds) for middle button emulation. Property: "Synaptics Middle Button Timeout" @@ -733,6 +768,10 @@ FLOAT, 4 values, min, max, accel, <deprecated> 8 bit (BOOL), 2 values, updown, leftright. .TP 7 +.BI "Synaptics Button Scrolling Repeat" +8 bit (BOOL), 2 values, updown, leftright. + +.TP 7 .BI "Synaptics Button Scrolling Time" 32 bit. @@ -894,16 +933,6 @@ The following options are no longer part of the driver configuration: .TP .BI "Option \*qEdgeMotionUseAlways\*q \*q" boolean \*q .TP -.BI "Option \*qUpDownScrolling\*q \*q" boolean \*q -.TP -.BI "Option \*qLeftRightScrolling\*q \*q" boolean \*q -.TP -.BI "Option \*qUpDownScrollRepeat\*q \*q" boolean \*q -.TP -.BI "Option \*qLeftRightScrollRepeat\*q \*q" boolean \*q -.TP -.BI "Option \*qScrollButtonRepeat\*q \*q" integer \*q -.TP .BI "Option \*qCircularPad\*q \*q" boolean \*q .SH "AUTHORS" diff --git a/src/properties.c b/src/properties.c index 797f1da..0041544 100644 --- a/src/properties.c +++ b/src/properties.c @@ -68,6 +68,9 @@ Atom prop_speed = 0; Atom prop_edgemotion_pressure = 0; Atom prop_edgemotion_speed = 0; Atom prop_edgemotion_always = 0; +Atom prop_buttonscroll = 0; +Atom prop_buttonscroll_repeat = 0; +Atom prop_buttonscroll_time = 0; Atom prop_off = 0; Atom prop_lockdrags = 0; Atom prop_lockdrags_time = 0; @@ -247,6 +250,22 @@ InitDeviceProperties(InputInfoPtr pInfo) fvalues[3] = 0; prop_speed = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_SPEED, 4, fvalues); + if (priv->has_scrollbuttons) { + values[0] = para->updown_button_scrolling; + values[1] = para->leftright_button_scrolling; + prop_buttonscroll = + InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 2, values); + + values[0] = para->updown_button_repeat; + values[1] = para->leftright_button_repeat; + prop_buttonscroll_repeat = + InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 2, + values); + prop_buttonscroll_time = + InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING_TIME, 32, 1, + ¶->scroll_button_repeat); + } + prop_off = InitAtom(pInfo->dev, SYNAPTICS_PROP_OFF, 8, 1, ¶->touchpad_off); prop_lockdrags = @@ -518,6 +537,43 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, para->max_speed = speed[1]; para->accl = speed[2]; } + else if (property == prop_buttonscroll) { + BOOL *scroll; + + if (!priv->has_scrollbuttons) + return BadMatch; + + if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + scroll = (BOOL *) prop->data; + para->updown_button_scrolling = scroll[0]; + para->leftright_button_scrolling = scroll[1]; + + } + else if (property == prop_buttonscroll_repeat) { + BOOL *repeat; + + if (!priv->has_scrollbuttons) + return BadMatch; + + if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + repeat = (BOOL *) prop->data; + para->updown_button_repeat = repeat[0]; + para->leftright_button_repeat = repeat[1]; + } + else if (property == prop_buttonscroll_time) { + if (!priv->has_scrollbuttons) + return BadMatch; + + if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) + return BadMatch; + + para->scroll_button_repeat = *(INT32 *) prop->data; + + } else if (property == prop_off) { CARD8 off; diff --git a/src/synaptics.c b/src/synaptics.c index e391a98..493986d 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -669,6 +669,20 @@ set_default_parameters(InputInfoPtr pInfo) pars->scroll_twofinger_horiz = xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll); pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", TOUCHPAD_ON); + + if (priv->has_scrollbuttons) { + pars->updown_button_scrolling = + xf86SetBoolOption(opts, "UpDownScrolling", TRUE); + pars->leftright_button_scrolling = + xf86SetBoolOption(opts, "LeftRightScrolling", TRUE); + pars->updown_button_repeat = + xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE); + pars->leftright_button_repeat = + xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE); + } + pars->scroll_button_repeat = + xf86SetIntOption(opts, "ScrollButtonRepeat", 100); + pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE); pars->locked_drag_time = xf86SetIntOption(opts, "LockedDragTimeout", 5000); pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 0); @@ -818,6 +832,8 @@ SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) xf86ErrorFVerb(6, "port opened successfully\n"); /* initialize variables */ + priv->repeatButtons = 0; + priv->nextRepeat = 0; priv->count_packet_finger = 0; priv->tap_state = TS_START; priv->tap_button = 0; @@ -995,6 +1011,7 @@ SynapticsReset(SynapticsPrivate * priv) priv->circ_scroll_on = FALSE; priv->circ_scroll_vert = FALSE; priv->mid_emu_state = MBE_OFF; + priv->nextRepeat = 0; priv->lastButtons = 0; priv->prev_z = 0; priv->prevFingers = 0; @@ -2555,6 +2572,46 @@ handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw) } } +/* Adjust the hardware state according to the extra buttons (if the touchpad + * has any and not many touchpads do these days). These buttons are up/down + * tilt buttons and/or left/right buttons that then map into a specific + * function (or scrolling into). + */ +static Bool +adjust_state_from_scrollbuttons(const InputInfoPtr pInfo, + struct SynapticsHwState *hw) +{ + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); + SynapticsParameters *para = &priv->synpara; + Bool double_click = FALSE; + + if (!para->updown_button_scrolling) { + if (hw->down) { /* map down button to middle button */ + hw->middle = TRUE; + } + + if (hw->up) { /* up button generates double click */ + if (!priv->prev_up) + double_click = TRUE; + } + priv->prev_up = hw->up; + + /* reset up/down button events */ + hw->up = hw->down = FALSE; + } + + /* Left/right button scrolling, or middle clicks */ + if (!para->leftright_button_scrolling) { + if (hw->multi[2] || hw->multi[3]) + hw->middle = TRUE; + + /* reset left/right button events */ + hw->multi[2] = hw->multi[3] = FALSE; + } + + return double_click; +} + static void update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, struct SynapticsHwState *old, CARD32 now, int *delay) @@ -2634,6 +2691,66 @@ post_scroll_events(const InputInfoPtr pInfo) xf86PostMotionEventM(pInfo->dev, FALSE, priv->scroll_events_mask); } +static inline int +repeat_scrollbuttons(const InputInfoPtr pInfo, + const struct SynapticsHwState *hw, + int buttons, CARD32 now, int delay) +{ + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); + SynapticsParameters *para = &priv->synpara; + int repeat_delay, timeleft; + int rep_buttons = 0; + + if (para->updown_button_repeat) + rep_buttons |= (1 << (4 - 1)) | (1 << (5 - 1)); + if (para->leftright_button_repeat) + rep_buttons |= (1 << (6 - 1)) | (1 << (7 - 1)); + + /* Handle auto repeat buttons */ + repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX); + if (((hw->up || hw->down) && para->updown_button_repeat && + para->updown_button_scrolling) || + ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat && + para->leftright_button_scrolling)) { + priv->repeatButtons = buttons & rep_buttons; + if (!priv->nextRepeat) { + priv->nextRepeat = now + repeat_delay * 2; + } + } + else { + priv->repeatButtons = 0; + priv->nextRepeat = 0; + } + + if (priv->repeatButtons) { + timeleft = TIME_DIFF(priv->nextRepeat, now); + if (timeleft > 0) + delay = MIN(delay, timeleft); + if (timeleft <= 0) { + int change, id; + + change = priv->repeatButtons; + while (change) { + id = ffs(change); + change &= ~(1 << (id - 1)); + if (id == 4) + priv->scroll.delta_y -= para->scroll_dist_vert; + else if (id == 5) + priv->scroll.delta_y += para->scroll_dist_vert; + else if (id == 6) + priv->scroll.delta_x -= para->scroll_dist_horiz; + else if (id == 7) + priv->scroll.delta_x += para->scroll_dist_horiz; + } + + priv->nextRepeat = now + repeat_delay; + delay = MIN(delay, repeat_delay); + } + } + + return delay; +} + /* Update the open slots and number of active touches */ static void UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw) @@ -2830,6 +2947,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, /* these two just update hw->left, right, etc. */ update_hw_button_state(pInfo, hw, priv->old_hw_state, now, &delay); + if (priv->has_scrollbuttons) + double_click = adjust_state_from_scrollbuttons(pInfo, hw); /* now we know that these _coordinates_ aren't in the area. invalid are: x, y, z, numFingers, fingerWidth @@ -2921,6 +3040,9 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, 0, 0); } + if (priv->has_scrollbuttons) + delay = repeat_scrollbuttons(pInfo, hw, buttons, now, delay); + /* Process scroll events only if coordinates are * in the Synaptics Area */ diff --git a/src/synapticsstr.h b/src/synapticsstr.h index 3d6f756..3f66b14 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -55,6 +55,10 @@ #define SYNAPTICS_MAX_TOUCHES 10 #define SYN_MAX_BUTTONS 12 /* Max number of mouse buttons */ +/* Minimum and maximum values for scroll_button_repeat */ +#define SBR_MIN 10 +#define SBR_MAX 1000 + enum OffState { TOUCHPAD_ON = 0, TOUCHPAD_OFF = 1, @@ -168,6 +172,12 @@ typedef struct _SynapticsParameters { Bool scroll_twofinger_horiz; /* Enable/disable horizontal two-finger scrolling */ double min_speed, max_speed, accl; /* movement parameters */ + Bool updown_button_scrolling; /* Up/Down-Button scrolling or middle/double-click */ + Bool leftright_button_scrolling; /* Left/right-button scrolling, or two lots of middle button */ + Bool updown_button_repeat; /* If up/down button being used to scroll, auto-repeat? */ + Bool leftright_button_repeat; /* If left/right button being used to scroll, auto-repeat? */ + int scroll_button_repeat; /* time, in milliseconds, between scroll events being + * sent when holding down scroll buttons */ int touchpad_off; /* Switches the touchpad off * 0 : Not off * 1 : Off @@ -209,7 +219,7 @@ struct _SynapticsPrivateRec { const char *device; /* device node */ CARD32 timer_time; /* when timer last fired */ - OsTimerPtr timer; /* for tap processing, etc */ + OsTimerPtr timer; /* for up/down-button repeat, tap processing, etc */ struct CommData comm; @@ -254,6 +264,8 @@ struct _SynapticsPrivateRec { False: Generate horizontal events */ double frac_x, frac_y; /* absolute -> relative fraction */ enum MidButtonEmulation mid_emu_state; /* emulated 3rd button */ + int repeatButtons; /* buttons for repeat */ + int nextRepeat; /* Time when to trigger next auto repeat event */ int lastButtons; /* last state of the buttons */ int prev_z; /* previous z value, for palm detection */ int prevFingers; /* previous numFingers, for transition detection */ diff --git a/tools/synclient.c b/tools/synclient.c index bd7cb61..f999311 100644 --- a/tools/synclient.c +++ b/tools/synclient.c @@ -50,6 +50,8 @@ #endif #define SYN_MAX_BUTTONS 12 +#define SBR_MIN 10 +#define SBR_MAX 1000 union flong { /* Xlibs 64-bit property handling madness */ long l; @@ -98,6 +100,11 @@ static struct Parameter params[] = { {"MinSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 0}, {"MaxSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 1}, {"AccelFactor", PT_DOUBLE, 0, 1.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 2}, + {"UpDownScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 0}, + {"LeftRightScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 1}, + {"UpDownScrollRepeat", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 0}, + {"LeftRightScrollRepeat", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 1}, + {"ScrollButtonRepeat", PT_INT, SBR_MIN , SBR_MAX, SYNAPTICS_PROP_BUTTONSCROLLING_TIME, 32, 0}, {"TouchpadOff", PT_INT, 0, 2, SYNAPTICS_PROP_OFF, 8, 0}, {"LockedDrags", PT_BOOL, 0, 1, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 0}, {"LockedDragTimeout", PT_INT, 0, 30000, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 0}, |