summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2014-01-17 08:24:35 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-02-21 11:10:27 +1000
commit1bd4ca3b5af6e5ee98c7d7f153fd4ee643c29e1a (patch)
treeb035dda9d5b0d3f1373f0f1608788213aca63be9
parent90d93891be0dcc55d87c349ab438144ead818402 (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.man49
-rw-r--r--src/properties.c56
-rw-r--r--src/synaptics.c122
-rw-r--r--src/synapticsstr.h14
-rw-r--r--tools/synclient.c7
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,
+ &para->scroll_button_repeat);
+ }
+
prop_off =
InitAtom(pInfo->dev, SYNAPTICS_PROP_OFF, 8, 1, &para->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},