[PATCH] Feature: synaptic three-finger swipe action
Gabriele Mazzotta
gabriele.mzt at gmail.com
Sun Aug 17 05:14:36 PDT 2014
> 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
More information about the xorg-devel
mailing list