> When touchpad can report more then 2 active fingers, we can generate > action based on swipe gesture. It includes upward, downward, to the > left and to the right swipes. To all of those gestures can be assigned > one button event. By default (internal driver default) swipes are > disabled (assigned button 0). The swipe length (hand displacement) > required for triggering button event can be set independently for > horizontal and vertical movement. There is also possibility for > triggering repeatable events during swipe handling, however it is > disabled by default. > > The most preferable button assignment is button 8, 9, 10 and 11 for to > the left, to the right, upward and downward swipes respectively. Such a > configuration provides browser history navigation (e.g. Firefox) with > horizontal swipes. Button 10 and 11 are not used, though. > > Added Synaptic driver options: > * SwipeUpButton, SwipeDownButton, SwipeLeftButton, SwipeRightButton > * HorizSwipeThreshold, VertSwipeThreshold > * SingleSwipe > > This changes was developed on Samsung NP530U3C with ETPS/2 Elantech > Touchpad, which can report up to three-finger touch. Patch is generated > for driver version 1.7.1 (which is marked as stable in Gentoo linux > distribution). If it is required I can try to test this patch for > latest master commit, however as for now I didn't want to break my box > by switching to the unstable (as marked by Gentoo portage team) driver > version.
Hi, I've been using this patch for quite a while, thanks for it. I noticed that there's partial support to four-finger gestures. Since my touchpad can track four fingers (five actually), I decided to complete the code. This is a squashed commit with all the changes I made (it depends on http://lists.x.org/archives/xorg-devel/2014-August/043571.html) --- src/eventcomm.c | 8 +++++- src/properties.c | 8 +++--- src/synaptics.c | 72 ++++++++++++++++++++++++++++++++++-------------------- src/synapticsstr.h | 4 +-- src/synproto.h | 1 + tools/synclient.c | 12 ++++++--- 6 files changed, 69 insertions(+), 36 deletions(-) diff --git a/src/eventcomm.c b/src/eventcomm.c index de17841..35a8b91 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -647,6 +647,8 @@ count_fingers(InputInfoPtr pInfo, const struct CommData *comm) fingers = 2; else if (comm->threeFingers) fingers = 3; + else if (comm->fourFingers) + fingers = 4; if (priv->has_touch && proto_data->num_touches > fingers) fingers = proto_data->num_touches; @@ -678,7 +680,8 @@ EventReadHwState(InputInfoPtr pInfo, /* Reset cumulative values if buttons were not previously pressed and no * two-finger scrolling is ongoing, or no finger was previously present. */ if (((!hw->left && !hw->right && !hw->middle) && - !(priv->vert_scroll_twofinger_on || priv->vert_scroll_twofinger_on)) || + !(priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on || + priv->swipe.threefinger_on || priv->swipe.fourfinger_on)) || hw->z < para->finger_low) { hw->cumulative_dx = hw->x; hw->cumulative_dy = hw->y; @@ -747,6 +750,9 @@ EventReadHwState(InputInfoPtr pInfo, case BTN_TOOL_TRIPLETAP: comm->threeFingers = v; break; + case BTN_TOOL_QUADTAP: + comm->fourFingers = v; + break; case BTN_TOUCH: if (!priv->has_pressure) hw->z = v ? para->finger_high + 1 : 0; diff --git a/src/properties.c b/src/properties.c index cb89e7b..ac2d8f0 100644 --- a/src/properties.c +++ b/src/properties.c @@ -320,9 +320,9 @@ InitDeviceProperties(InputInfoPtr pInfo) InitAtom(pInfo->dev, SYNAPTICS_PROP_CIRCULAR_PAD, 8, 1, ¶->circular_pad); - memcpy(values, para->swipe_action, MAX_SWIPE * sizeof(int)); + memcpy(values, para->swipe_action, 2 * MAX_SWIPE * sizeof(int)); prop_swipeaction = - InitAtom(pInfo->dev, SYNAPTICS_PROP_SWIPE_ACTION, 8, MAX_SWIPE, values); + InitAtom(pInfo->dev, SYNAPTICS_PROP_SWIPE_ACTION, 8, 2 * MAX_SWIPE, values); values[0] = para->swipe_threshold_x; values[1] = para->swipe_threshold_y; prop_swipethreshold = @@ -719,7 +719,9 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, action = (CARD8 *) prop->data; for (i = 0; i < MAX_SWIPE; i++) - para->swipe_action[i] = action[i]; + para->swipe_action[0][i] = action[i]; + for (i = 0; i < MAX_SWIPE; i++) + para->swipe_action[1][i] = action[MAX_SWIPE + i]; } else if (property == prop_swipethreshold) { INT32 *swipe_thresholds; diff --git a/src/synaptics.c b/src/synaptics.c index a84536b..0cf1a07 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -741,14 +741,22 @@ set_default_parameters(InputInfoPtr pInfo) xf86SetBoolOption(opts, "CircularScrolling", FALSE); pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0); pars->circular_pad = xf86SetBoolOption(opts, "CircularPad", FALSE); - pars->swipe_action[UP_SWIPE] = - xf86SetIntOption(opts, "SwipeUpButton", 0); - pars->swipe_action[DOWN_SWIPE] = - xf86SetIntOption(opts, "SwipeDownButton", 0); - pars->swipe_action[LEFT_SWIPE] = - xf86SetIntOption(opts, "SwipeLeftButton", 0); - pars->swipe_action[RIGHT_SWIPE] = - xf86SetIntOption(opts, "SwipeRightButton", 0); + pars->swipe_action[0][UP_SWIPE] = + xf86SetIntOption(opts, "SwipeThreeUpButton", 0); + pars->swipe_action[0][DOWN_SWIPE] = + xf86SetIntOption(opts, "SwipeThreeDownButton", 0); + pars->swipe_action[0][LEFT_SWIPE] = + xf86SetIntOption(opts, "SwipeThreeLeftButton", 0); + pars->swipe_action[0][RIGHT_SWIPE] = + xf86SetIntOption(opts, "SwipeThreeRightButton", 0); + pars->swipe_action[1][UP_SWIPE] = + xf86SetIntOption(opts, "SwipeFourUpButton", 0); + pars->swipe_action[1][DOWN_SWIPE] = + xf86SetIntOption(opts, "SwipeFourDownButton", 0); + pars->swipe_action[1][LEFT_SWIPE] = + xf86SetIntOption(opts, "SwipeFourLeftButton", 0); + pars->swipe_action[1][RIGHT_SWIPE] = + xf86SetIntOption(opts, "SwipeFourRightButton", 0); pars->swipe_threshold_x = xf86SetIntOption(opts, "HorizSwipeThreshold", horizSwipeThreshold); pars->swipe_threshold_y = @@ -1976,16 +1984,15 @@ HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw, touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED; release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED; - /* TODO: better way to determine how many fingers was actually used - * for gesture - there could be up to 5 fingers (or 6 ?) */ move = (finger >= FS_TOUCHED && (priv->tap_max_fingers <= - (priv->swipe.threefinger_on ? 3 : - ((priv->horiz_scroll_twofinger_on || - priv->vert_scroll_twofinger_on) ? 2 : 1))) && - (priv->prevFingers == hw->numFingers && - ((abs(hw->x - priv->touch_on.x) >= para->tap_move) || - (abs(hw->y - priv->touch_on.y) >= para->tap_move)))); + (priv->swipe.fourfinger_on ? 4 : + (priv->swipe.threefinger_on ? 3 : + ((priv->horiz_scroll_twofinger_on || + priv->vert_scroll_twofinger_on) ? 2 : 1))) && + (priv->prevFingers == hw->numFingers && + ((abs(hw->x - priv->touch_on.x) >= para->tap_move) || + (abs(hw->y - priv->touch_on.y) >= para->tap_move))))); press = (hw->left || hw->right || hw->middle); if (touch) { @@ -2658,7 +2665,8 @@ HandleSwipe(SynapticsPrivate *priv, struct SynapticsHwState *hw, Bool finger) return; } - if (priv->swipe.threefinger_on || priv->swipe.fourfinger_on) { + if ((priv->swipe.threefinger_on && hw->numFingers == 3) || + (priv->swipe.fourfinger_on && hw->numFingers == 4)) { /* swipe was activated, accumulate delta */ priv->swipe.delta_x += hw->x - priv->swipe.last_x; priv->swipe.delta_y += hw->y - priv->swipe.last_y; @@ -2978,37 +2986,48 @@ static void post_swipe_events(const InputInfoPtr pInfo) { SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); SynapticsParameters *para = &priv->synpara; + int i = 0; /* there is no need to go any further if those conditions are not met */ if (!(priv->swipe.threefinger_on || priv->swipe.fourfinger_on) || (priv->swipe.posted && para->single_swipe)) return; + if (priv->swipe.fourfinger_on) + i = 1; + /* swipes are intrinsically related - one big if stack */ - if (para->swipe_action[UP_SWIPE] && + if (para->swipe_action[i][UP_SWIPE] && priv->swipe.delta_y < -para->swipe_threshold_y) { - post_button_click(pInfo, para->swipe_action[UP_SWIPE]); + post_button_click(pInfo, para->swipe_action[i][UP_SWIPE]); priv->swipe.posted = TRUE; priv->swipe.delta_y = 0; } - else if (para->swipe_action[DOWN_SWIPE] && + else if (para->swipe_action[i][DOWN_SWIPE] && priv->swipe.delta_y > para->swipe_threshold_y) { - post_button_click(pInfo, para->swipe_action[DOWN_SWIPE]); + post_button_click(pInfo, para->swipe_action[i][DOWN_SWIPE]); priv->swipe.posted = TRUE; priv->swipe.delta_y = 0; } - else if (para->swipe_action[LEFT_SWIPE] && + else if (para->swipe_action[i][LEFT_SWIPE] && priv->swipe.delta_x < -para->swipe_threshold_x) { - post_button_click(pInfo, para->swipe_action[LEFT_SWIPE]); + post_button_click(pInfo, para->swipe_action[i][LEFT_SWIPE]); priv->swipe.posted = TRUE; priv->swipe.delta_x = 0; } - else if (para->swipe_action[RIGHT_SWIPE] && + else if (para->swipe_action[i][RIGHT_SWIPE] && priv->swipe.delta_x > para->swipe_threshold_x) { - post_button_click(pInfo, para->swipe_action[RIGHT_SWIPE]); + post_button_click(pInfo, para->swipe_action[i][RIGHT_SWIPE]); priv->swipe.posted = TRUE; priv->swipe.delta_x = 0; } + /* In case no button is defined for a specific gesture. */ + else if (abs(priv->swipe.delta_x) > para->swipe_threshold_x) { + priv->swipe.delta_x = 0; + } + else if (abs(priv->swipe.delta_y) > para->swipe_threshold_y) { + priv->swipe.delta_y = 0; + } } /* Update the open slots and number of active touches */ @@ -3191,7 +3210,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, * is ongoing, use cumulative relative touch movements for motion */ if (para->clickpad && ((priv->lastButtons & 7) || - (priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on)) && + (priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on || + priv->swipe.threefinger_on || priv->swipe.fourfinger_on)) && priv->last_button_area != TOP_BUTTON_AREA) { hw->x = hw->cumulative_dx; hw->y = hw->cumulative_dy; diff --git a/src/synapticsstr.h b/src/synapticsstr.h index 553226c..c63e261 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -214,7 +214,7 @@ typedef struct _SynapticsParameters { int locked_drag_time; /* timeout for locked drags */ int tap_action[MAX_TAP]; /* Button to report on tap events */ int click_action[MAX_CLICK]; /* Button to report on click with fingers */ - int swipe_action[MAX_SWIPE]; /* Button to report on swipe action */ + int swipe_action[2][MAX_SWIPE]; /* Button to report on swipe action */ int swipe_threshold_x; /* Threshold for horizontal swipe event */ int swipe_threshold_y; /* Threshold for vertical swipe event */ Bool single_swipe; /* Allow only one action per swipe */ @@ -280,7 +280,7 @@ struct _SynapticsPrivateRec { double delta_y; /* accumulated vert swipe delta */ Bool posted; /* indicate that event was posted */ Bool threefinger_on; /* swipe event with three fingers */ - Bool fourfinger_on; /* XXX: ?? swipe event with four fingers */ + Bool fourfinger_on; /* swipe event with four fingers */ } swipe; int count_packet_finger; /* packet counter with finger on the touchpad */ int button_delay_millis; /* button delay for 3rd button emulation */ diff --git a/src/synproto.h b/src/synproto.h index c52838c..7e9f8bd 100644 --- a/src/synproto.h +++ b/src/synproto.h @@ -93,6 +93,7 @@ struct CommData { Bool oneFinger; Bool twoFingers; Bool threeFingers; + Bool fourFingers; }; struct _SynapticsParameters; diff --git a/tools/synclient.c b/tools/synclient.c index 94dad62..ef61259 100644 --- a/tools/synclient.c +++ b/tools/synclient.c @@ -122,10 +122,14 @@ static struct Parameter params[] = { {"CircScrollDelta", PT_DOUBLE, .01, 3, SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST, 0 /* float */, 0}, {"CircScrollTrigger", PT_INT, 0, 8, SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER, 8, 0}, {"CircularPad", PT_BOOL, 0, 1, SYNAPTICS_PROP_CIRCULAR_PAD, 8, 0}, - {"SwipeUpButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 0}, - {"SwipeDownButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 1}, - {"SwipeLeftButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 2}, - {"SwipeRightButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 3}, + {"SwipeThreeUpButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 0}, + {"SwipeThreeDownButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 1}, + {"SwipeThreeLeftButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 2}, + {"SwipeThreeRightButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 3}, + {"SwipeFourUpButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 4}, + {"SwipeFourDownButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 5}, + {"SwipeFourLeftButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 6}, + {"SwipeFourRightButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_SWIPE_ACTION, 8, 7}, {"HorizSwipeThreshold", PT_INT, 0, 10000, SYNAPTICS_PROP_SWIPE_THRESHOLD, 32, 0}, {"VertSwipeThreshold", PT_INT, 0, 10000, SYNAPTICS_PROP_SWIPE_THRESHOLD, 32, 1}, {"SingleSwipe", PT_BOOL, 0, 1, SYNAPTICS_PROP_SINGLE_SWIPE, 8, 0}, -- 2.1.0 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
