From e94010751a728b827c521b3499751775c3e7b691 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 29 2014 20:34:27 +0000 Subject: import xorg-x11-drv-synaptics-1.7.1-10.el7_0.1 --- diff --git a/SOURCES/0001-Avoid-erroneously-handling-two-touchpoints-in-the-sa.patch b/SOURCES/0001-Avoid-erroneously-handling-two-touchpoints-in-the-sa.patch new file mode 100644 index 0000000..392a1be --- /dev/null +++ b/SOURCES/0001-Avoid-erroneously-handling-two-touchpoints-in-the-sa.patch @@ -0,0 +1,113 @@ +From 662a51761e4f4a64cd1dcdf489ad0ccb708185f2 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 20 Mar 2014 11:51:17 +1000 +Subject: [PATCH synaptics 01/14] Avoid erroneously handling two touchpoints in + the same slot + +If a slot's ABS_MT_TRACKING_ID event was received during SYN_DROPPED, the +driver isn't aware that a touchpoint has started or ended in that slot. When +the next ABS_MT_TRACKING_ID event arrives, the driver would unconditionally +close or open a new touchpoint. This could lead to two or more touchpoints +being opened in the same slot, the first of which is never terminated. +Or it could lead to a touchpoint being terminated that was never opened. + +The event sequences that trigger this are: + ABS_MT_TRACKING_ID 83 + ABS_MT_TRACKING_ID -1 + SYN_DROPPED // new touchpoint started here + ABS_MT_TRACKING_ID -1 + +and + + ABS_MT_TRACKING_ID 83 + SYN_DROPPED // touchpoint ended here + ABS_MT_TRACKING_ID 84 + ABS_MT_TRACKING_ID -1 + +We don't properly handle SYN_DROPPED, but we can avoid this by only starting a +new touchpoint when we transition between -1 and a valid tracking ID. + +Signed-off-by: Peter Hutterer +--- + src/eventcomm.c | 34 +++++++++++++++++++++++++++++++++- + 1 file changed, 33 insertions(+), 1 deletion(-) + +diff --git a/src/eventcomm.c b/src/eventcomm.c +index 258a538..3c2883e 100644 +--- a/src/eventcomm.c ++++ b/src/eventcomm.c +@@ -76,6 +76,7 @@ struct eventcomm_proto_data { + int cur_slot; + ValuatorMask **last_mt_vals; + int num_touches; ++ int *tracking_ids; + }; + + struct eventcomm_proto_data * +@@ -125,6 +126,9 @@ UninitializeTouch(InputInfoPtr pInfo) + mtdev_close_delete(proto_data->mtdev); + proto_data->mtdev = NULL; + proto_data->num_touches = 0; ++ ++ free(proto_data->tracking_ids); ++ proto_data->tracking_ids = NULL; + } + + static void +@@ -156,9 +160,18 @@ InitializeTouch(InputInfoPtr pInfo) + return; + } + ++ proto_data->tracking_ids = calloc(priv->num_slots, sizeof(int)); ++ if (!proto_data->tracking_ids) { ++ xf86IDrvMsg(pInfo, X_WARNING, "failed to allocate tracking ID array\n"); ++ UninitializeTouch(pInfo); ++ return; ++ } ++ + for (i = 0; i < priv->num_slots; i++) { + int j; + ++ proto_data->tracking_ids[i] = -1; ++ + proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes); + if (!proto_data->last_mt_vals[i]) { + xf86IDrvMsg(pInfo, X_WARNING, +@@ -554,7 +567,24 @@ EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw, + if (hw->slot_state[slot_index] == SLOTSTATE_OPEN_EMPTY) + hw->slot_state[slot_index] = SLOTSTATE_UPDATE; + if (ev->code == ABS_MT_TRACKING_ID) { +- if (ev->value >= 0) { ++ int old_tracking_id = proto_data->tracking_ids[slot_index]; ++ ++ /* We don't have proper SYN_DROPPED handling in ++ synaptics < 1.8. This is a poor man's version that covers the ++ worst bug we're seeing: touch points starting/stopping during ++ SYN_DROPPED. There can only be one touchpoint per slot, ++ identified by the tracking ID. Make sure that we only ever ++ have a single touch point open per slot. ++ */ ++ if (ev->value != -1 && old_tracking_id != -1) { ++ /* Our touch terminated during SYN_DROPPED, now we have a ++ new touch starting in the same slot but ours is still ++ open. Do nothing, just continue with the old touch */ ++ } else if (ev->value == -1 && old_tracking_id == -1) { ++ /* A new touch started during SYN_DROPPED, now we have that ++ touch terminating. Do nothing, we don't have that touch ++ open */ ++ } else if (ev->value >= 0) { + hw->slot_state[slot_index] = SLOTSTATE_OPEN; + proto_data->num_touches++; + valuator_mask_copy(hw->mt_mask[slot_index], +@@ -564,6 +594,8 @@ EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw, + hw->slot_state[slot_index] = SLOTSTATE_CLOSE; + proto_data->num_touches--; + } ++ ++ proto_data->tracking_ids[slot_index] = ev->value; + } + else { + ValuatorMask *mask = proto_data->last_mt_vals[slot_index]; +-- +1.9.3 + diff --git a/SOURCES/0002-Allow-using-the-entire-touchpad-for-motions-started-.patch b/SOURCES/0002-Allow-using-the-entire-touchpad-for-motions-started-.patch new file mode 100644 index 0000000..aff83ba --- /dev/null +++ b/SOURCES/0002-Allow-using-the-entire-touchpad-for-motions-started-.patch @@ -0,0 +1,125 @@ +From bbb1f0e58d80d975e9aae42384ce12054ca8896c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 19 Feb 2014 18:30:35 +0100 +Subject: [PATCH synaptics 02/14] Allow using the entire touchpad for motions + started inside the active area + +synaptics offers an option to make parts of the touchpad insensitive. This +is ie useful to do palm avoidance rather then palm detection (which may be +unreliable) by disabling an area of 15% on the right and left side of the +touchpad. + +Currently a motion which has started inside the active area, stops as soon +as it moves outside of the active area. + +If a motion started inside the active area and thus has already generated some +move events, this makes no sense. If the user moves outside of the active +area in this case, this is very likely because the user wants to continue +the motion. + +This commit allows such motions to continue normally. + +I would like to thank Juerd Waalboer for the basic idea, some coding and lots +of testing for this fix. + +Cc: Juerd Waalboer +Reported-by: Juerd Waalboer +Tested-by: Juerd Waalboer +Signed-off-by: Hans de Goede +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +(cherry picked from commit 945acfc261707be78cbc5438c22b061e20076004) +(cherry picked from commit 75b6fd13cfc0e8c8b1ca17626b5316a83359e353) +--- + man/synaptics.man | 15 ++++++++------- + src/synaptics.c | 11 ++++++----- + 2 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/man/synaptics.man b/man/synaptics.man +index 079a5f8..93c0627 100644 +--- a/man/synaptics.man ++++ b/man/synaptics.man +@@ -399,7 +399,7 @@ Property: "Synaptics Pad Resolution" + . + .TP + .BI "Option \*qAreaLeftEdge\*q \*q" integer \*q +-Ignore movements, scrolling and tapping which take place left of this edge. ++Ignore movements, scrolling and tapping which start left of this edge. + . + The option is disabled by default and can be enabled by setting the + AreaLeftEdge option to any integer value other than zero. If supported by the +@@ -408,7 +408,7 @@ the total width of the touchpad. Property: "Synaptics Area" + . + .TP + .BI "Option \*qAreaRightEdge\*q \*q" integer \*q +-Ignore movements, scrolling and tapping which take place right of this edge. ++Ignore movements, scrolling and tapping which start right of this edge. + . + The option is disabled by default and can be enabled by setting the + AreaRightEdge option to any integer value other than zero. If supported by the +@@ -417,7 +417,7 @@ the total width of the touchpad. Property: "Synaptics Area" + . + .TP + .BI "Option \*qAreaTopEdge\*q \*q" integer \*q +-Ignore movements, scrolling and tapping which take place above this edge. ++Ignore movements, scrolling and tapping which start above this edge. + . + The option is disabled by default and can be enabled by setting the + AreaTopEdge option to any integer value other than zero. If supported by the +@@ -426,7 +426,7 @@ the total height of the touchpad. Property: "Synaptics Area" + . + .TP + .BI "Option \*qAreaBottomEdge\*q \*q" integer \*q +-Ignore movements, scrolling and tapping which take place below this edge. ++Ignore movements, scrolling and tapping which start below this edge. + . + The option is disabled by default and can be enabled by setting the + AreaBottomEdge option to any integer value other than zero. If supported by the +@@ -490,9 +490,10 @@ the touchpad. + .PP + The perceived physical edges may be adjusted with the AreaLeftEdge, + AreaRightEdge, AreaTopEdge, and AreaBottomEdge options. If these values are +-set to something other than the physical edges, input in the space between +-the area edge and the respective physical edge is ignored. Note that this +-reduces the available space on the touchpad. ++set to something other than the physical edges, input that starts in the ++space between the area edge and the respective physical edge is ignored. ++Note that this reduces the available space on the touchpad to start motions ++in. + .SS Tapping + A tap event happens when the finger is touched and released in a time + interval shorter than MaxTapTime, and the touch and release +diff --git a/src/synaptics.c b/src/synaptics.c +index e391a98..bc4f24c 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -1362,6 +1362,11 @@ is_inside_active_area(SynapticsPrivate * priv, int x, int y) + { + Bool inside_area = TRUE; + ++ /* If a finger is down, then it must have started inside the active_area, ++ allow the motion to complete using the entire area */ ++ if (priv->finger_state >= FS_TOUCHED) ++ return TRUE; ++ + if ((priv->synpara.area_left_edge != 0) && + (x < priv->synpara.area_left_edge)) + inside_area = FALSE; +@@ -2835,13 +2840,9 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + invalid are: x, y, z, numFingers, fingerWidth + valid are: millis, left/right/middle/up/down/etc. + */ +- if (!inside_active_area) { ++ if (!inside_active_area) + reset_hw_state(hw); + +- /* FIXME: if finger accidentally moves into the area and doesn't +- * really release, the finger should remain down. */ +- } +- + /* no edge or finger detection outside of area */ + if (inside_active_area) { + edge = edge_detection(priv, hw->x, hw->y); +-- +1.9.3 + diff --git a/SOURCES/0003-Add-secondary-top-software-buttons-area.patch b/SOURCES/0003-Add-secondary-top-software-buttons-area.patch new file mode 100644 index 0000000..ea5a597 --- /dev/null +++ b/SOURCES/0003-Add-secondary-top-software-buttons-area.patch @@ -0,0 +1,187 @@ +From 62774df2797abee123fd0a9960a5fb147753773e Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Thu, 20 Feb 2014 13:13:18 -0500 +Subject: [PATCH synaptics 03/14] Add secondary (top) software buttons area + +New generation of laptops with trackstick do not have physical buttons +associated with the trackstick, but instead rely on software buttons at +the top of the clickpad. +Adding a secondary software button area for this purpose. +As we're likely detecting the devices that need it based on udev tags +and MatchTag configuration items, this area doesn't need to be exposed +through properties. So static configuration is fine. + +Signed-off-by: Benjamin Tissoires +Reviewed-by: Peter Hutterer + +[couple of man-page additions and rewrites] + +Signed-off-by: Peter Hutterer +(cherry picked from commit 402cc872570b58b8420e7973d0706f3b2a2aaf91) +(cherry picked from commit 13fc982c670e992060fd33a116fbc6eb32cdba25) +--- + man/synaptics.man | 18 ++++++++++++++++++ + src/synaptics.c | 47 ++++++++++++++++++++++++++++++++++++++++------- + src/synapticsstr.h | 2 +- + 3 files changed, 59 insertions(+), 8 deletions(-) + +diff --git a/man/synaptics.man b/man/synaptics.man +index 93c0627..a80aaad 100644 +--- a/man/synaptics.man ++++ b/man/synaptics.man +@@ -447,6 +447,18 @@ soft button areas. Button areas may not overlap, however it is permitted for two + buttons to share an edge value. + Property: "Synaptics Soft Button Areas" + . ++.TP ++.BI "Option \*qSecondarySoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q ++This option is only available on ClickPad devices. ++Enable secondary soft button click area support on ClickPad devices (usually on ++top of the device). ++For the allowed values for this option, see ++.B Option \*qSoftButtonAreas\*q. ++Primary and secondary soft button areas must not overlap each other. If they do, ++the behavior of the driver is undefined. ++No property associated, this option must be set in the ++__xconfigfile__(__filemansuffix__). ++. + + .SH CONFIGURATION DETAILS + .SS Area handling +@@ -669,6 +681,12 @@ ClickPads provide software emulated buttons through + These buttons enable areas on the touchpad to perform as right or middle + mouse button. When the user performs a click within a defined soft button + area, a right or middle click is performed. ++.LP ++Some laptops, most notably the Lenovo T440, T540 and x240 series, provide a ++pointing stick without physical buttons. On those laptops, the top of the ++touchpad acts as software-emulated button area. This area can be configured ++with ++.B Option SecondarySoftButtonAreas. + + .SH "DEVICE PROPERTIES" + Synaptics 1.0 and higher support input device properties if the driver is +diff --git a/src/synaptics.c b/src/synaptics.c +index bc4f24c..7405194 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -452,7 +452,7 @@ SynapticsIsSoftButtonAreasValid(int *values) + } + + static void +-set_softbutton_areas_option(InputInfoPtr pInfo) ++set_softbutton_areas_option(InputInfoPtr pInfo, char *option_name, int offset) + { + SynapticsPrivate *priv = pInfo->private; + SynapticsParameters *pars = &priv->synpara; +@@ -467,7 +467,7 @@ set_softbutton_areas_option(InputInfoPtr pInfo) + if (!pars->clickpad) + return; + +- option_string = xf86SetStrOption(pInfo->options, "SoftButtonAreas", NULL); ++ option_string = xf86SetStrOption(pInfo->options, option_name, NULL); + if (!option_string) + return; + +@@ -512,8 +512,8 @@ set_softbutton_areas_option(InputInfoPtr pInfo) + if (!SynapticsIsSoftButtonAreasValid(values)) + goto fail; + +- memcpy(pars->softbutton_areas[0], values, 4 * sizeof(int)); +- memcpy(pars->softbutton_areas[1], values + 4, 4 * sizeof(int)); ++ memcpy(pars->softbutton_areas[offset], values, 4 * sizeof(int)); ++ memcpy(pars->softbutton_areas[offset + 1], values + 4, 4 * sizeof(int)); + + free(option_string); + +@@ -521,12 +521,24 @@ set_softbutton_areas_option(InputInfoPtr pInfo) + + fail: + xf86IDrvMsg(pInfo, X_ERROR, +- "invalid SoftButtonAreas value '%s', keeping defaults\n", +- option_string); ++ "invalid %s value '%s', keeping defaults\n", ++ option_name, option_string); + free(option_string); + } + + static void ++set_primary_softbutton_areas_option(InputInfoPtr pInfo) ++{ ++ set_softbutton_areas_option(pInfo, "SoftButtonAreas", 0); ++} ++ ++static void ++set_secondary_softbutton_areas_option(InputInfoPtr pInfo) ++{ ++ set_softbutton_areas_option(pInfo, "SecondarySoftButtonAreas", 2); ++} ++ ++static void + set_default_parameters(InputInfoPtr pInfo) + { + SynapticsPrivate *priv = pInfo->private; /* read-only */ +@@ -724,7 +736,8 @@ set_default_parameters(InputInfoPtr pInfo) + "TopEdge is bigger than BottomEdge. Fixing.\n"); + } + +- set_softbutton_areas_option(pInfo); ++ set_primary_softbutton_areas_option(pInfo); ++ set_secondary_softbutton_areas_option(pInfo); + } + + static double +@@ -1429,6 +1442,18 @@ is_inside_middlebutton_area(SynapticsParameters * para, int x, int y) + return is_inside_button_area(para, 1, x, y); + } + ++static Bool ++is_inside_sec_rightbutton_area(SynapticsParameters * para, int x, int y) ++{ ++ return is_inside_button_area(para, 2, x, y); ++} ++ ++static Bool ++is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y) ++{ ++ return is_inside_button_area(para, 3, x, y); ++} ++ + static CARD32 + timerFunc(OsTimerPtr timer, CARD32 now, pointer arg) + { +@@ -2584,10 +2609,18 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, + hw->left = 0; + hw->right = 1; + } ++ else if (is_inside_sec_rightbutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->right = 1; ++ } + else if (is_inside_middlebutton_area(para, hw->x, hw->y)) { + hw->left = 0; + hw->middle = 1; + } ++ else if (is_inside_sec_middlebutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->middle = 1; ++ } + } + else if (hw->left) { + hw->left = old->left; +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index 3d6f756..ead54d4 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -194,7 +194,7 @@ typedef struct _SynapticsParameters { + unsigned int resolution_horiz; /* horizontal resolution of touchpad in units/mm */ + unsigned int resolution_vert; /* vertical resolution of touchpad in units/mm */ + int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */ +- int softbutton_areas[2][4]; /* soft button area coordinates, 0 => right, 1 => middle button */ ++ int softbutton_areas[4][4]; /* soft button area coordinates, 0 => right, 1 => middle , 2 => secondary right, 3 => secondary middle button */ + int hyst_x, hyst_y; /* x and y width of hysteresis box */ + } SynapticsParameters; + +-- +1.9.3 + diff --git a/SOURCES/0004-Add-an-enum-for-the-different-soft_button_areas.patch b/SOURCES/0004-Add-an-enum-for-the-different-soft_button_areas.patch new file mode 100644 index 0000000..14be348 --- /dev/null +++ b/SOURCES/0004-Add-an-enum-for-the-different-soft_button_areas.patch @@ -0,0 +1,107 @@ +From 37afc8ee5640e22d6eab5379ee97ded8ad680aaf Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:39 +0100 +Subject: [PATCH synaptics 04/14] Add an enum for the different + soft_button_areas + +While at it also move the enum for the soft button edges out of +is_inside_button_area() so that it can be used elsewhere too. + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +(cherry picked from commit 840670508e0150ae11ae744c676253c7fba332dc) +(cherry picked from commit 59bb2aaaac728bfbf92600314782ff2db506c91e) +--- + src/synaptics.c | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/src/synaptics.c b/src/synaptics.c +index 7405194..7ba8b0f 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -89,6 +89,22 @@ enum EdgeType { + LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE + }; + ++enum SoftButtonAreas { ++ BOTTOM_BUTTON_AREA = 0, ++ BOTTOM_RIGHT_BUTTON_AREA = 0, ++ BOTTOM_MIDDLE_BUTTON_AREA = 1, ++ TOP_BUTTON_AREA = 2, ++ TOP_RIGHT_BUTTON_AREA = 2, ++ TOP_MIDDLE_BUTTON_AREA = 3 ++}; ++ ++enum SoftButtonAreaEdges { ++ LEFT = 0, ++ RIGHT = 1, ++ TOP = 2, ++ BOTTOM = 3 ++}; ++ + /* + * We expect to be receiving a steady 80 packets/sec (which gives 40 + * reports/sec with more than one finger on the pad, as Advanced Gesture Mode +@@ -529,13 +545,13 @@ set_softbutton_areas_option(InputInfoPtr pInfo, char *option_name, int offset) + static void + set_primary_softbutton_areas_option(InputInfoPtr pInfo) + { +- set_softbutton_areas_option(pInfo, "SoftButtonAreas", 0); ++ set_softbutton_areas_option(pInfo, "SoftButtonAreas", BOTTOM_BUTTON_AREA); + } + + static void + set_secondary_softbutton_areas_option(InputInfoPtr pInfo) + { +- set_softbutton_areas_option(pInfo, "SecondarySoftButtonAreas", 2); ++ set_softbutton_areas_option(pInfo, "SecondarySoftButtonAreas", TOP_BUTTON_AREA); + } + + static void +@@ -1401,13 +1417,6 @@ is_inside_button_area(SynapticsParameters * para, int which, int x, int y) + { + Bool inside_area = TRUE; + +- enum { +- LEFT = 0, +- RIGHT = 1, +- TOP = 2, +- BOTTOM = 3 +- }; +- + if (para->softbutton_areas[which][LEFT] == 0 && + para->softbutton_areas[which][RIGHT] == 0 && + para->softbutton_areas[which][TOP] == 0 && +@@ -1433,25 +1442,25 @@ is_inside_button_area(SynapticsParameters * para, int which, int x, int y) + static Bool + is_inside_rightbutton_area(SynapticsParameters * para, int x, int y) + { +- return is_inside_button_area(para, 0, x, y); ++ return is_inside_button_area(para, BOTTOM_RIGHT_BUTTON_AREA, x, y); + } + + static Bool + is_inside_middlebutton_area(SynapticsParameters * para, int x, int y) + { +- return is_inside_button_area(para, 1, x, y); ++ return is_inside_button_area(para, BOTTOM_MIDDLE_BUTTON_AREA, x, y); + } + + static Bool + is_inside_sec_rightbutton_area(SynapticsParameters * para, int x, int y) + { +- return is_inside_button_area(para, 2, x, y); ++ return is_inside_button_area(para, TOP_RIGHT_BUTTON_AREA, x, y); + } + + static Bool + is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y) + { +- return is_inside_button_area(para, 3, x, y); ++ return is_inside_button_area(para, TOP_MIDDLE_BUTTON_AREA, x, y); + } + + static CARD32 +-- +1.9.3 + diff --git a/SOURCES/0005-Get-rid-of-old_hw_state.patch b/SOURCES/0005-Get-rid-of-old_hw_state.patch new file mode 100644 index 0000000..ed75cbb --- /dev/null +++ b/SOURCES/0005-Get-rid-of-old_hw_state.patch @@ -0,0 +1,162 @@ +From 2f9c49aeee5963c381e8d145583f3326fd7fe4df Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:40 +0100 +Subject: [PATCH synaptics 05/14] Get rid of old_hw_state + +We only use it to store button state which we already have in +priv->lastButtons. + +While at it also properly indent the code block checking the various +soft button areas. + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +(cherry picked from commit effeee86c1c286cd09ab750efc4932790dd560dd) +(cherry picked from commit f712eb7c41436c3f84a0d244be879c5c118788c5) + +Conflicts: + src/synaptics.c + +Conflict result from 1bd4ca3b5af6e5ee98c7d7f153fd4ee643c29e1a + Revert "Purge scrollbuttons (repeat)" +in upstream 1.7 branch but not here +--- + src/synaptics.c | 58 ++++++++++++++++++++++-------------------------------- + src/synapticsstr.h | 1 - + 2 files changed, 23 insertions(+), 36 deletions(-) + +diff --git a/src/synaptics.c b/src/synaptics.c +index 7ba8b0f..5a2c160 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -1003,7 +1003,6 @@ SynapticsReset(SynapticsPrivate * priv) + { + SynapticsResetHwState(priv->hwState); + SynapticsResetHwState(priv->local_hw_state); +- SynapticsResetHwState(priv->old_hw_state); + SynapticsResetHwState(priv->comm.hwState); + + memset(priv->move_hist, 0, sizeof(priv->move_hist)); +@@ -1072,7 +1071,6 @@ DeviceClose(DeviceIntPtr dev) + free(priv->touch_axes); + priv->touch_axes = NULL; + SynapticsHwStateFree(&priv->hwState); +- SynapticsHwStateFree(&priv->old_hw_state); + SynapticsHwStateFree(&priv->local_hw_state); + SynapticsHwStateFree(&priv->comm.hwState); + return RetValue; +@@ -1318,10 +1316,6 @@ DeviceInit(DeviceIntPtr dev) + if (!priv->hwState) + goto fail; + +- priv->old_hw_state = SynapticsHwStateAlloc(priv); +- if (!priv->old_hw_state) +- goto fail; +- + priv->local_hw_state = SynapticsHwStateAlloc(priv); + if (!priv->local_hw_state) + goto fail; +@@ -2596,7 +2590,7 @@ handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw) + + static void + update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, +- struct SynapticsHwState *old, CARD32 now, int *delay) ++ CARD32 now, int *delay) + { + SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); + SynapticsParameters *para = &priv->synpara; +@@ -2612,39 +2606,36 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, + * the soft button instead. */ + if (para->clickpad) { + /* hw->left is down, but no other buttons were already down */ +- if (!old->left && !old->right && !old->middle && +- hw->left && !hw->right && !hw->middle) { +- if (is_inside_rightbutton_area(para, hw->x, hw->y)) { +- hw->left = 0; +- hw->right = 1; +- } +- else if (is_inside_sec_rightbutton_area(para, hw->x, hw->y)) { +- hw->left = 0; +- hw->right = 1; +- } +- else if (is_inside_middlebutton_area(para, hw->x, hw->y)) { +- hw->left = 0; +- hw->middle = 1; +- } +- else if (is_inside_sec_middlebutton_area(para, hw->x, hw->y)) { +- hw->left = 0; +- hw->middle = 1; +- } ++ if (!(priv->lastButtons & 7) && hw->left && !hw->right && !hw->middle) { ++ if (is_inside_rightbutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->right = 1; ++ } ++ else if (is_inside_sec_rightbutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->right = 1; ++ } ++ else if (is_inside_middlebutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->middle = 1; ++ } ++ else if (is_inside_sec_middlebutton_area(para, hw->x, hw->y)) { ++ hw->left = 0; ++ hw->middle = 1; ++ } + } + else if (hw->left) { +- hw->left = old->left; +- hw->right = old->right; +- hw->middle = old->middle; ++ hw->left = (priv->lastButtons & 1) ? 1 : 0; ++ hw->middle = (priv->lastButtons & 2) ? 1 : 0; ++ hw->right = (priv->lastButtons & 4) ? 1 : 0; + } + } + + /* Fingers emulate other buttons. ClickFinger can only be + triggered on transition, when left is pressed + */ +- if (hw->left && !old->left && !old->middle && !old->right && +- hw->numFingers >= 1) { ++ if (hw->left && !(priv->lastButtons & 7) && hw->numFingers >= 1) + handle_clickfinger(priv, hw); +- } + + /* Two finger emulation */ + if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z && +@@ -2876,7 +2867,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + inside_active_area = is_inside_active_area(priv, hw->x, hw->y); + + /* these two just update hw->left, right, etc. */ +- update_hw_button_state(pInfo, hw, priv->old_hw_state, now, &delay); ++ update_hw_button_state(pInfo, hw, now, &delay); + + /* now we know that these _coordinates_ aren't in the area. + invalid are: x, y, z, numFingers, fingerWidth +@@ -2988,9 +2979,6 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + if (inside_active_area) + store_history(priv, hw->x, hw->y, hw->millis); + +- /* Save logical state for transition comparisons */ +- SynapticsCopyHwState(priv->old_hw_state, hw); +- + return delay; + } + +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index ead54d4..a028b20 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -205,7 +205,6 @@ struct _SynapticsPrivateRec { + void *proto_data; /* protocol-specific data */ + + struct SynapticsHwState *hwState; +- struct SynapticsHwState *old_hw_state; /* previous logical hw state */ + + const char *device; /* device node */ + CARD32 timer_time; /* when timer last fired */ +-- +1.9.3 + diff --git a/SOURCES/0006-Don-t-report-motion-inside-soft-button-areas.patch b/SOURCES/0006-Don-t-report-motion-inside-soft-button-areas.patch new file mode 100644 index 0000000..2ecd6dc --- /dev/null +++ b/SOURCES/0006-Don-t-report-motion-inside-soft-button-areas.patch @@ -0,0 +1,155 @@ +From c0b19a1469a3f2ad4dd3a8a5ef1bebef59e5b4be Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:41 +0100 +Subject: [PATCH synaptics 06/14] Don't report motion inside soft-button areas + +Unless the motion has started outside the soft-button area. + +Note that we must start reporting motions regardless of whether we think we're +in the button area or not as soon as we've switched to using cumulative +coordinates, since then the coordinates are no longer absolute. + +This fixes the reporting of unintended motion just before a click in a soft +button area which sometimes causes mis-clicks. + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +(cherry picked from commit 3adaf4623845dce54129b6474f4f8f2966f9bc47) +Signed-off-by: Peter Hutterer + +Conflicts: + src/synaptics.c + +(cherry picked from commit 6d6bfcbf8763d967b8f3805cfe035324aba53e77) +--- + src/synaptics.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- + src/synapticsstr.h | 1 + + 2 files changed, 66 insertions(+), 1 deletion(-) + +diff --git a/src/synaptics.c b/src/synaptics.c +index 5a2c160..d24dda8 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -1012,6 +1012,7 @@ SynapticsReset(SynapticsPrivate * priv) + priv->count_packet_finger = 0; + priv->finger_state = FS_UNTOUCHED; + priv->last_motion_millis = 0; ++ priv->inside_button_area = FALSE; + priv->tap_state = TS_START; + priv->tap_button = 0; + priv->tap_button_state = TBS_BUTTON_UP; +@@ -1457,6 +1458,56 @@ is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y) + return is_inside_button_area(para, TOP_MIDDLE_BUTTON_AREA, x, y); + } + ++static Bool ++is_inside_top_or_bottom_button_area(SynapticsParameters * para, int offset, ++ int x, int y) ++{ ++ Bool inside_area = TRUE; ++ Bool right_valid, middle_valid; ++ int top, bottom; ++ ++ /* We don't have a left button area, so we only check the y axis */ ++ right_valid = para->softbutton_areas[offset][TOP] || ++ para->softbutton_areas[offset][BOTTOM]; ++ middle_valid = para->softbutton_areas[offset + 1][TOP] || ++ para->softbutton_areas[offset + 1][BOTTOM]; ++ ++ if (!right_valid && !middle_valid) ++ return FALSE; ++ ++ /* Check both buttons are horizontally aligned */ ++ if (right_valid && middle_valid && ( ++ para->softbutton_areas[offset][TOP] != ++ para->softbutton_areas[offset + 1][TOP] || ++ para->softbutton_areas[offset][BOTTOM] != ++ para->softbutton_areas[offset + 1][BOTTOM])) ++ return FALSE; ++ ++ if (right_valid) { ++ top = para->softbutton_areas[offset][TOP]; ++ bottom = para->softbutton_areas[offset][BOTTOM]; ++ } ++ else { ++ top = para->softbutton_areas[offset + 1][TOP]; ++ bottom = para->softbutton_areas[offset + 1][BOTTOM]; ++ } ++ ++ if (top && y < top) ++ inside_area = FALSE; ++ else if (bottom && y > bottom) ++ inside_area = FALSE; ++ ++ return inside_area; ++} ++ ++static Bool ++is_inside_anybutton_area(SynapticsParameters * para, int x, int y) ++{ ++ return ++ is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y) || ++ is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y); ++} ++ + static CARD32 + timerFunc(OsTimerPtr timer, CARD32 now, pointer arg) + { +@@ -2832,6 +2883,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + int delay = 1000000000; + int timeleft; + Bool inside_active_area; ++ Bool using_cumulative_coords = FALSE; ++ Bool ignore_motion; + + /* If touchpad is switched off, we skip the whole thing and return delay */ + if (para->touchpad_off == TOUCHPAD_OFF) { +@@ -2857,6 +2910,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + if (para->clickpad && (hw->left || hw->right || hw->middle)) { + hw->x = hw->cumulative_dx; + hw->y = hw->cumulative_dy; ++ using_cumulative_coords = TRUE; + } + + /* apply hysteresis before doing anything serious. This cancels +@@ -2866,6 +2920,16 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + + inside_active_area = is_inside_active_area(priv, hw->x, hw->y); + ++ /* Ignore motion *starting* inside softbuttonareas */ ++ if (priv->finger_state < FS_TOUCHED) ++ priv->inside_button_area = is_inside_anybutton_area(para, hw->x, hw->y); ++ /* If we already have a finger down, clear inside_button_area if it goes ++ outside of the softbuttonareas */ ++ else if (priv->inside_button_area && !is_inside_anybutton_area(para, hw->x, hw->y)) ++ priv->inside_button_area = FALSE; ++ ++ ignore_motion = !using_cumulative_coords && priv->inside_button_area; ++ + /* these two just update hw->left, right, etc. */ + update_hw_button_state(pInfo, hw, now, &delay); + +@@ -2935,7 +2999,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + } + + /* Post events */ +- if (finger >= FS_TOUCHED && (dx || dy)) ++ if (finger >= FS_TOUCHED && (dx || dy) && !ignore_motion) + xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); + + if (priv->mid_emu_state == MBE_LEFT_CLICK) { +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index a028b20..1c5d573 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -236,6 +236,7 @@ struct _SynapticsPrivateRec { + Bool prev_up; /* Previous up button value, for double click emulation */ + enum FingerState finger_state; /* previous finger state */ + CARD32 last_motion_millis; /* time of the last motion */ ++ Bool inside_button_area; /* Inside button area (ignore motion) */ + + enum TapState tap_state; /* State of tap processing */ + int tap_max_fingers; /* Max number of fingers seen since entering start state */ +-- +1.9.3 + diff --git a/SOURCES/0007-Ignore-motion-the-first-X-ms-after-a-clickpad-click.patch b/SOURCES/0007-Ignore-motion-the-first-X-ms-after-a-clickpad-click.patch new file mode 100644 index 0000000..85fc37d --- /dev/null +++ b/SOURCES/0007-Ignore-motion-the-first-X-ms-after-a-clickpad-click.patch @@ -0,0 +1,89 @@ +From 4c408433a2c9565bd3df6d167cfedf4eb4a3c9eb Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:42 +0100 +Subject: [PATCH synaptics 07/14] Ignore motion the first X ms after a clickpad + click + +This fixes my #1 anoyance with clickpads, where 2 out of 3 clicks turn into +a click + drag unless I hold my finger really really still. + +Signed-off-by: Hans de Goede + +Replaced property with a hardcoded 100ms. This is not something that we should +expose as property, we should find a delay that works best and live with it. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 71652fe1f0800b081ba5602e9edda22a8d8d628e) +(cherry picked from commit db920ba696d7870b1b074ae2daff1e93a7296b99) +--- + src/synaptics.c | 12 ++++++++++++ + src/synapticsstr.h | 2 ++ + 2 files changed, 14 insertions(+) + +diff --git a/src/synaptics.c b/src/synaptics.c +index d24dda8..f289b35 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -675,6 +675,7 @@ set_default_parameters(InputInfoPtr pInfo) + pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180); + pars->click_time = xf86SetIntOption(opts, "ClickTime", 100); + pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad); /* Probed */ ++ pars->clickpad_ignore_motion_time = 100; /* ms */ + /* middle mouse button emulation on a clickpad? nah, you're joking */ + middle_button_timeout = pars->clickpad ? 0 : 75; + pars->emulate_mid_button_time = +@@ -1012,6 +1013,7 @@ SynapticsReset(SynapticsPrivate * priv) + priv->count_packet_finger = 0; + priv->finger_state = FS_UNTOUCHED; + priv->last_motion_millis = 0; ++ priv->clickpad_click_millis = 0; + priv->inside_button_area = FALSE; + priv->tap_state = TS_START; + priv->tap_button = 0; +@@ -2674,6 +2676,7 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, + hw->left = 0; + hw->middle = 1; + } ++ priv->clickpad_click_millis = now; + } + else if (hw->left) { + hw->left = (priv->lastButtons & 1) ? 1 : 0; +@@ -2933,6 +2936,15 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + /* these two just update hw->left, right, etc. */ + update_hw_button_state(pInfo, hw, now, &delay); + ++ /* Ignore motion the first X ms after a clickpad click */ ++ if (priv->clickpad_click_millis) { ++ if(TIME_DIFF(priv->clickpad_click_millis + ++ para->clickpad_ignore_motion_time, now) > 0) ++ ignore_motion = TRUE; ++ else ++ priv->clickpad_click_millis = 0; ++ } ++ + /* now we know that these _coordinates_ aren't in the area. + invalid are: x, y, z, numFingers, fingerWidth + valid are: millis, left/right/middle/up/down/etc. +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index 1c5d573..a21ce00 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -155,6 +155,7 @@ typedef struct _SynapticsParameters { + int tap_time_2; /* max. tapping time for double taps */ + int click_time; /* The duration of a single click */ + Bool clickpad; /* Device is a has integrated buttons */ ++ int clickpad_ignore_motion_time; /* Ignore motion for X ms after a click */ + int emulate_mid_button_time; /* Max time between left and right button presses to + emulate a middle button press. */ + int emulate_twofinger_z; /* pressure threshold to emulate two finger touch (for Alps) */ +@@ -237,6 +238,7 @@ struct _SynapticsPrivateRec { + enum FingerState finger_state; /* previous finger state */ + CARD32 last_motion_millis; /* time of the last motion */ + Bool inside_button_area; /* Inside button area (ignore motion) */ ++ int clickpad_click_millis; /* Time of last clickpad click */ + + enum TapState tap_state; /* State of tap processing */ + int tap_max_fingers; /* Max number of fingers seen since entering start state */ +-- +1.9.3 + diff --git a/SOURCES/0008-On-button-down-update-cumulative-to-current-x-and-y-.patch b/SOURCES/0008-On-button-down-update-cumulative-to-current-x-and-y-.patch new file mode 100644 index 0000000..623443c --- /dev/null +++ b/SOURCES/0008-On-button-down-update-cumulative-to-current-x-and-y-.patch @@ -0,0 +1,64 @@ +From 511eda7024caaab10d4e7f701bcd1eedd0329cab Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:43 +0100 +Subject: [PATCH synaptics 08/14] On button down update cumulative to current x + and y, instead of previous + +When a button click and new coordinates get reported in one go we sync the +cumulative coordinates to the old x and y, rather then the newly reported ones. + +This keeping of the old coordinates causes the following issue: +-touch the touchpad in its right click area +-let go of the touchpad +-rapidly click in the left click area (or middle area), so that the + new location and the click get reported in one syn (may require some + practicing with evemu-record to reproduce) +-the driver registers the click as a right click because it uses the + old coordinates from the cumulative coordinates to determine the + click location + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +(cherry picked from commit 743c45b9cfd057d00c37dab1cfca4b6202fb2642) +(cherry picked from commit ad834529c3fb63ced0ed74efb6c382d1761467c8) +--- + src/eventcomm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/eventcomm.c b/src/eventcomm.c +index 3c2883e..1534b7c 100644 +--- a/src/eventcomm.c ++++ b/src/eventcomm.c +@@ -660,6 +660,7 @@ EventReadHwState(InputInfoPtr pInfo, + SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; + SynapticsParameters *para = &priv->synpara; + struct eventcomm_proto_data *proto_data = priv->proto_data; ++ Bool sync_cumulative = FALSE; + + SynapticsResetTouchHwState(hw, FALSE); + +@@ -667,6 +668,7 @@ EventReadHwState(InputInfoPtr pInfo, + if (!hw->left && !hw->right && !hw->middle) { + hw->cumulative_dx = hw->x; + hw->cumulative_dy = hw->y; ++ sync_cumulative = TRUE; + } + + while (SynapticsReadEvent(pInfo, &ev)) { +@@ -742,9 +744,13 @@ EventReadHwState(InputInfoPtr pInfo, + switch (ev.code) { + case ABS_X: + hw->x = apply_st_scaling(proto_data, ev.value, 0); ++ if (sync_cumulative) ++ hw->cumulative_dx = hw->x; + break; + case ABS_Y: + hw->y = apply_st_scaling(proto_data, ev.value, 1); ++ if (sync_cumulative) ++ hw->cumulative_dy = hw->y; + break; + case ABS_PRESSURE: + hw->z = ev.value; +-- +1.9.3 + diff --git a/SOURCES/0009-Wait-for-new-coordinates-on-a-clickpad-click-before-.patch b/SOURCES/0009-Wait-for-new-coordinates-on-a-clickpad-click-before-.patch new file mode 100644 index 0000000..b146757 --- /dev/null +++ b/SOURCES/0009-Wait-for-new-coordinates-on-a-clickpad-click-before-.patch @@ -0,0 +1,114 @@ +From 8adbeacd1a140e4f1c203dde0c60d488dbec1d26 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 21 Feb 2014 10:31:44 +0100 +Subject: [PATCH synaptics 09/14] Wait for *new* coordinates on a clickpad + click before reporting the click + +It is possible for a click to get reported before any related touch events +get reported, here is the relevant part of an evemu-record session on a T440s: + +E: 3.985585 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +E: 3.997419 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1 +E: 3.997419 0001 014a 0000 # EV_KEY / BTN_TOUCH 0 +E: 3.997419 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0 +E: 3.997419 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0 +E: 3.997419 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +E: 5.117881 0001 0110 0001 # EV_KEY / BTN_LEFT 1 +E: 5.117881 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +E: 5.133422 0003 0039 0187 # EV_ABS / ABS_MT_TRACKING_ID 187 +E: 5.133422 0003 0035 3098 # EV_ABS / ABS_MT_POSITION_X 3098 +E: 5.133422 0003 0036 3282 # EV_ABS / ABS_MT_POSITION_Y 3282 +E: 5.133422 0003 003a 0046 # EV_ABS / ABS_MT_PRESSURE 46 +E: 5.133422 0001 014a 0001 # EV_KEY / BTN_TOUCH 1 +E: 5.133422 0003 0000 3102 # EV_ABS / ABS_X 3102 +E: 5.133422 0003 0001 3282 # EV_ABS / ABS_Y 3282 +E: 5.133422 0003 0018 0046 # EV_ABS / ABS_PRESSURE 46 +E: 5.133422 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1 +E: 5.133422 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- + +Notice the BTN_LEFT event all by itself! + +If this happens, it may lead to the following problem scenario: +-touch the touchpad in its right click area +-let go of the touchpad +-rapidly click in the middle area, so that BTN_LEFT gets reported before the + new coordinates (such as seen in the trace above, this may require some + practicing with evemu-record to reproduce) +-the driver registers the click as a right click because it uses the + old coordinates from the cumulative coordinates to determine the + click location + +This commit fixes this by: +1) Resetting the cumulative coordinates not only when no button is pressed, + but also when there is no finger touching the touchpad, so that when + we do get a touch the cumulative coordinates start at the right place +2) Delaying processing the BTN_LEFT down transition if there is no finger + touching the touchpad + +This approach has one downside, if we wrongly identify a touchpad as +a clickpad, then the left button won't work unless the user touches the +touchpad while clicking the left button. + +If we want we can fix this by doing something like this: +1) Making update_hw_button_state return a delay; and +2) Tracking that we've delayed BTN_LEFT down transition processing; and +3) When we've delayed BTN_LEFT down transition return a small delay value; and +4) If when we're called again we still don't have a finger down, just + treat the click as a BTN_LEFT + +But this is not worth the trouble IMHO, the proper thing to do in this +scenario is to fix the mis-identification of the touchpad as a clickpad. + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +(cherry picked from commit bbe4c56c4998a90b478581a4d93717251d8e05be) +(cherry picked from commit eb3af31c597ed6dc1bef31f39a5f6c9d586713ae) +--- + src/eventcomm.c | 5 +++-- + src/synaptics.c | 7 +++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/eventcomm.c b/src/eventcomm.c +index 1534b7c..4550ef2 100644 +--- a/src/eventcomm.c ++++ b/src/eventcomm.c +@@ -664,8 +664,9 @@ EventReadHwState(InputInfoPtr pInfo, + + SynapticsResetTouchHwState(hw, FALSE); + +- /* Reset cumulative values if buttons were not previously pressed */ +- if (!hw->left && !hw->right && !hw->middle) { ++ /* Reset cumulative values if buttons were not previously pressed, ++ * or no finger was previously present. */ ++ if ((!hw->left && !hw->right && !hw->middle) || hw->z < para->finger_low) { + hw->cumulative_dx = hw->x; + hw->cumulative_dy = hw->y; + sync_cumulative = TRUE; +diff --git a/src/synaptics.c b/src/synaptics.c +index f289b35..7a39df9 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -2660,6 +2660,12 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, + if (para->clickpad) { + /* hw->left is down, but no other buttons were already down */ + if (!(priv->lastButtons & 7) && hw->left && !hw->right && !hw->middle) { ++ /* If the finger down event is delayed, the x and y ++ * coordinates are stale so we delay processing the click */ ++ if (hw->z < para->finger_low) { ++ hw->left = 0; ++ goto out; ++ } + if (is_inside_rightbutton_area(para, hw->x, hw->y)) { + hw->left = 0; + hw->right = 1; +@@ -2691,6 +2697,7 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, + if (hw->left && !(priv->lastButtons & 7) && hw->numFingers >= 1) + handle_clickfinger(priv, hw); + ++out: + /* Two finger emulation */ + if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z && + hw->fingerWidth >= para->emulate_twofinger_w) { +-- +1.9.3 + diff --git a/SOURCES/0010-Add-property-support-for-secondary-top-software-butt.patch b/SOURCES/0010-Add-property-support-for-secondary-top-software-butt.patch new file mode 100644 index 0000000..8719d48 --- /dev/null +++ b/SOURCES/0010-Add-property-support-for-secondary-top-software-butt.patch @@ -0,0 +1,187 @@ +From 275c00454e2329b55ac1d377702825a4ab01b450 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 10 Mar 2014 09:07:59 +1000 +Subject: [PATCH synaptics 10/14] Add property support for secondary (top) + software buttons + +This was originally intended as a fixed xorg.conf option only (and still +largely is seen as such). Secondary software button are required only on a specific series +of touchpads and should be pre-configured by the system and/or the +distribution. As such, the property will not be initialized if it is not set +in the xorg.conf and will thus not respond to runtime changes. + +Exposing the property in this way gives clients a chance of detecting if a top +software button area is present and thus adjust their behaviour accordingly. + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +(cherry picked from commit 66240dc329683f0141c1e11590ea2c3d8ca25788) +(cherry picked from commit 1e08fbf8a71b5958ac1765c889b5101e62fad20f) +--- + include/synaptics-properties.h | 3 +++ + man/synaptics.man | 3 ++- + src/properties.c | 48 +++++++++++++++++++++++++++++++++--------- + src/synaptics.c | 16 -------------- + src/synapticsstr.h | 16 ++++++++++++++ + 5 files changed, 59 insertions(+), 27 deletions(-) + +diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h +index b717880..5207a09 100644 +--- a/include/synaptics-properties.h ++++ b/include/synaptics-properties.h +@@ -149,6 +149,9 @@ + /* 32 bit, 4 values, left, right, top, buttom */ + #define SYNAPTICS_PROP_SOFTBUTTON_AREAS "Synaptics Soft Button Areas" + ++/* 32 bit, 4 values, left, right, top, buttom */ ++#define SYNAPTICS_PROP_SECONDARY_SOFTBUTTON_AREAS "Synaptics Secondary Soft Button Areas" ++ + /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */ + #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation" + +diff --git a/man/synaptics.man b/man/synaptics.man +index a80aaad..88009f6 100644 +--- a/man/synaptics.man ++++ b/man/synaptics.man +@@ -456,7 +456,8 @@ For the allowed values for this option, see + .B Option \*qSoftButtonAreas\*q. + Primary and secondary soft button areas must not overlap each other. If they do, + the behavior of the driver is undefined. +-No property associated, this option must be set in the ++Property: "Synaptics Secondary Soft Button Areas". This property is only ++initialized if the option is set in the + __xconfigfile__(__filemansuffix__). + . + +diff --git a/src/properties.c b/src/properties.c +index dd88fc7..278114a 100644 +--- a/src/properties.c ++++ b/src/properties.c +@@ -88,6 +88,7 @@ Atom prop_capabilities = 0; + Atom prop_resolution = 0; + Atom prop_area = 0; + Atom prop_softbutton_areas = 0; ++Atom prop_secondary_softbutton_areas = 0; + Atom prop_noise_cancellation = 0; + Atom prop_product_id = 0; + Atom prop_device_node = 0; +@@ -161,16 +162,30 @@ InitSoftButtonProperty(InputInfoPtr pInfo) + SynapticsParameters *para = &priv->synpara; + int values[8]; + +- values[0] = para->softbutton_areas[0][0]; +- values[1] = para->softbutton_areas[0][1]; +- values[2] = para->softbutton_areas[0][2]; +- values[3] = para->softbutton_areas[0][3]; +- values[4] = para->softbutton_areas[1][0]; +- values[5] = para->softbutton_areas[1][1]; +- values[6] = para->softbutton_areas[1][2]; +- values[7] = para->softbutton_areas[1][3]; ++ values[0] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][LEFT]; ++ values[1] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][RIGHT]; ++ values[2] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][TOP]; ++ values[3] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][BOTTOM]; ++ values[4] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][LEFT]; ++ values[5] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][RIGHT]; ++ values[6] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][TOP]; ++ values[7] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][BOTTOM]; + prop_softbutton_areas = + InitAtom(pInfo->dev, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 8, values); ++ ++ values[0] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][LEFT]; ++ values[1] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][RIGHT]; ++ values[2] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][TOP]; ++ values[3] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][BOTTOM]; ++ values[4] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][LEFT]; ++ values[5] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][RIGHT]; ++ values[6] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][TOP]; ++ values[7] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][BOTTOM]; ++ ++ if (values[0] || values[1] || values[2] || values[4] || ++ values[5] || values[6] || values[7]) ++ prop_secondary_softbutton_areas = ++ InitAtom(pInfo->dev, SYNAPTICS_PROP_SECONDARY_SOFTBUTTON_AREAS, 32, 8, values); + } + + void +@@ -690,8 +705,21 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, + if (!SynapticsIsSoftButtonAreasValid(areas)) + return BadValue; + +- memcpy(para->softbutton_areas[0], areas, 4 * sizeof(int)); +- memcpy(para->softbutton_areas[1], areas + 4, 4 * sizeof(int)); ++ memcpy(para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA], areas, 4 * sizeof(int)); ++ memcpy(para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA], areas + 4, 4 * sizeof(int)); ++ } ++ else if (property == prop_secondary_softbutton_areas) { ++ int *areas; ++ ++ if (prop->size != 8 || prop->format != 32 || prop->type != XA_INTEGER) ++ return BadMatch; ++ ++ areas = (int *) prop->data; ++ if (!SynapticsIsSoftButtonAreasValid(areas)) ++ return BadValue; ++ ++ memcpy(para->softbutton_areas[TOP_RIGHT_BUTTON_AREA], areas, 4 * sizeof(int)); ++ memcpy(para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA], areas + 4, 4 * sizeof(int)); + } + else if (property == prop_noise_cancellation) { + INT32 *hyst; +diff --git a/src/synaptics.c b/src/synaptics.c +index 7a39df9..4592f69 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -89,22 +89,6 @@ enum EdgeType { + LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE + }; + +-enum SoftButtonAreas { +- BOTTOM_BUTTON_AREA = 0, +- BOTTOM_RIGHT_BUTTON_AREA = 0, +- BOTTOM_MIDDLE_BUTTON_AREA = 1, +- TOP_BUTTON_AREA = 2, +- TOP_RIGHT_BUTTON_AREA = 2, +- TOP_MIDDLE_BUTTON_AREA = 3 +-}; +- +-enum SoftButtonAreaEdges { +- LEFT = 0, +- RIGHT = 1, +- TOP = 2, +- BOTTOM = 3 +-}; +- + /* + * We expect to be receiving a steady 80 packets/sec (which gives 40 + * reports/sec with more than one finger on the pad, as Advanced Gesture Mode +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index a21ce00..3a9f88c 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -145,6 +145,22 @@ enum TouchpadModel { + MODEL_UNIBODY_MACBOOK + }; + ++enum SoftButtonAreas { ++ BOTTOM_BUTTON_AREA = 0, ++ BOTTOM_RIGHT_BUTTON_AREA = 0, ++ BOTTOM_MIDDLE_BUTTON_AREA = 1, ++ TOP_BUTTON_AREA = 2, ++ TOP_RIGHT_BUTTON_AREA = 2, ++ TOP_MIDDLE_BUTTON_AREA = 3 ++}; ++ ++enum SoftButtonAreaEdges { ++ LEFT = 0, ++ RIGHT = 1, ++ TOP = 2, ++ BOTTOM = 3 ++}; ++ + typedef struct _SynapticsParameters { + /* Parameter data */ + int left_edge, right_edge, top_edge, bottom_edge; /* edge coordinates absolute */ +-- +1.9.3 + diff --git a/SOURCES/0011-Replace-is_inside_anybutton_area-with-current_button.patch b/SOURCES/0011-Replace-is_inside_anybutton_area-with-current_button.patch new file mode 100644 index 0000000..87443af --- /dev/null +++ b/SOURCES/0011-Replace-is_inside_anybutton_area-with-current_button.patch @@ -0,0 +1,94 @@ +From cd2a67253fe8b29b87dd12168186020d196cdd93 Mon Sep 17 00:00:00 2001 +From: Stephen Chandler Paul +Date: Mon, 10 Mar 2014 18:25:20 -0400 +Subject: [PATCH synaptics 11/14] Replace is_inside_anybutton_area with + current_button_area + +Signed-off-by: Stephen Chandler Paul +Signed-off-by: Peter Hutterer +(cherry picked from commit 9a419ba01c53a38b4b601f4415801fca29a2b4e2) +(cherry picked from commit 8732f7b5c16aaba1df4b2429804d02c2742bdf59) +--- + src/synaptics.c | 27 ++++++++++++++++----------- + src/synapticsstr.h | 3 ++- + 2 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/src/synaptics.c b/src/synaptics.c +index 4592f69..c3bda7b 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -998,7 +998,7 @@ SynapticsReset(SynapticsPrivate * priv) + priv->finger_state = FS_UNTOUCHED; + priv->last_motion_millis = 0; + priv->clickpad_click_millis = 0; +- priv->inside_button_area = FALSE; ++ priv->last_button_area = NO_BUTTON_AREA; + priv->tap_state = TS_START; + priv->tap_button = 0; + priv->tap_button_state = TBS_BUTTON_UP; +@@ -1486,12 +1486,15 @@ is_inside_top_or_bottom_button_area(SynapticsParameters * para, int offset, + return inside_area; + } + +-static Bool +-is_inside_anybutton_area(SynapticsParameters * para, int x, int y) ++static enum SoftButtonAreas ++current_button_area(SynapticsParameters * para, int x, int y) + { +- return +- is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y) || +- is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y); ++ if (is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y)) ++ return BOTTOM_BUTTON_AREA; ++ else if (is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y)) ++ return TOP_BUTTON_AREA; ++ else ++ return NO_BUTTON_AREA; + } + + static CARD32 +@@ -2916,13 +2919,15 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + + /* Ignore motion *starting* inside softbuttonareas */ + if (priv->finger_state < FS_TOUCHED) +- priv->inside_button_area = is_inside_anybutton_area(para, hw->x, hw->y); +- /* If we already have a finger down, clear inside_button_area if it goes ++ priv->last_button_area = current_button_area(para, hw->x, hw->y); ++ /* If we already have a finger down, clear last_button_area if it goes + outside of the softbuttonareas */ +- else if (priv->inside_button_area && !is_inside_anybutton_area(para, hw->x, hw->y)) +- priv->inside_button_area = FALSE; ++ else if (priv->last_button_area != NO_BUTTON_AREA && ++ current_button_area(para, hw->x, hw->y) == NO_BUTTON_AREA) ++ priv->last_button_area = NO_BUTTON_AREA; + +- ignore_motion = !using_cumulative_coords && priv->inside_button_area; ++ ignore_motion = ++ !using_cumulative_coords && priv->last_button_area != NO_BUTTON_AREA; + + /* these two just update hw->left, right, etc. */ + update_hw_button_state(pInfo, hw, now, &delay); +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index 3a9f88c..1622123 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -146,6 +146,7 @@ enum TouchpadModel { + }; + + enum SoftButtonAreas { ++ NO_BUTTON_AREA = -1, + BOTTOM_BUTTON_AREA = 0, + BOTTOM_RIGHT_BUTTON_AREA = 0, + BOTTOM_MIDDLE_BUTTON_AREA = 1, +@@ -253,7 +254,7 @@ struct _SynapticsPrivateRec { + Bool prev_up; /* Previous up button value, for double click emulation */ + enum FingerState finger_state; /* previous finger state */ + CARD32 last_motion_millis; /* time of the last motion */ +- Bool inside_button_area; /* Inside button area (ignore motion) */ ++ enum SoftButtonAreas last_button_area; /* Last button area we were in */ + int clickpad_click_millis; /* Time of last clickpad click */ + + enum TapState tap_state; /* State of tap processing */ +-- +1.9.3 + diff --git a/SOURCES/0012-Don-t-allow-any-type-of-movement-starting-in-the-top.patch b/SOURCES/0012-Don-t-allow-any-type-of-movement-starting-in-the-top.patch new file mode 100644 index 0000000..f6a5660 --- /dev/null +++ b/SOURCES/0012-Don-t-allow-any-type-of-movement-starting-in-the-top.patch @@ -0,0 +1,37 @@ +From 5a2ed1e91a488b8009ce6cb870cea3205d73bdaf Mon Sep 17 00:00:00 2001 +From: Stephen Chandler Paul +Date: Mon, 10 Mar 2014 18:33:20 -0400 +Subject: [PATCH synaptics 12/14] Don't allow any type of movement starting in + the top softbutton area + +Clicking in the top soft button area causes the trackpad to begin +registering motion, even if the finger never leaves the top soft button +area. We don't want this kind of behavior for the top soft button area, +since it makes clicking and dragging items much more difficult when +using a pointing stick. + +Signed-off-by: Stephen Chandler Paul +Signed-off-by: Peter Hutterer +(cherry picked from commit b40a5255fe73f7f95c8ff7145dd91605f3430119) +(cherry picked from commit ed84731b72692c648b48d00b84bb680446e265b6) +--- + src/synaptics.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/synaptics.c b/src/synaptics.c +index c3bda7b..512ca8d 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -2904,7 +2904,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + + /* If a physical button is pressed on a clickpad, use cumulative relative + * touch movements for motion */ +- if (para->clickpad && (hw->left || hw->right || hw->middle)) { ++ if (para->clickpad && (priv->lastButtons & 7) && ++ priv->last_button_area != TOP_BUTTON_AREA) { + hw->x = hw->cumulative_dx; + hw->y = hw->cumulative_dy; + using_cumulative_coords = TRUE; +-- +1.9.3 + diff --git a/SOURCES/0013-If-the-touchpad-is-in-TOUCHPAD_OFF-mode-allow-physic.patch b/SOURCES/0013-If-the-touchpad-is-in-TOUCHPAD_OFF-mode-allow-physic.patch new file mode 100644 index 0000000..f97074a --- /dev/null +++ b/SOURCES/0013-If-the-touchpad-is-in-TOUCHPAD_OFF-mode-allow-physic.patch @@ -0,0 +1,101 @@ +From ba4964d28a428525331baf99bf91b3a4ede26bce Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 17 Mar 2014 14:55:37 +1000 +Subject: [PATCH synaptics 13/14] If the touchpad is in TOUCHPAD_OFF mode, + allow physical clicks + +Enabling clicks in off mode also allows for the new Lenovo *40 series to use +the top software buttons while the touchpad is disabled. This benefits those +that usually disable touchpads altogether but still need the buttons for the +trackstick. + +This changes existing behaviour, but TouchpadOff was always intended to stop +erroneous events while typing. Physical button presses are hard to trigger +accidentally. On the touchpads that TouchpadOff concept was originally +designed for the buttons are nowhere near the keyboard and are physically +separated from the touchpad anyway. On Clickpads, triggering a physical +click requires more force than accidentally touching the surface. + +https://bugs.freedesktop.org/show_bug.cgi?id=76156 + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +(cherry picked from commit dc5474964d4ec73b5c324961026e1037bb344946) +(cherry picked from commit 11b2814c17c17cc43cf1b22f56998b100e59cf04) +--- + man/synaptics.man | 7 ++++++- + src/synaptics.c | 17 +++++++---------- + 2 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/man/synaptics.man b/man/synaptics.man +index 88009f6..86eb663 100644 +--- a/man/synaptics.man ++++ b/man/synaptics.man +@@ -226,9 +226,14 @@ Valid values are: + .TS + l l. + 0 Touchpad is enabled +-1 Touchpad is switched off ++1 Touchpad is switched off (physical clicks still work) + 2 Only tapping and scrolling is switched off + .TE ++When the touchpad is switched off, button events caused by a physical ++button press are still interpreted. On a ClickPad, this includes ++software-emulated middle and right buttons as defined by ++the SoftButtonAreas setting. ++.TP + Property: "Synaptics Off" + .TP + .BI "Option \*qLockedDrags\*q \*q" boolean \*q +diff --git a/src/synaptics.c b/src/synaptics.c +index 512ca8d..78adfaf 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -1856,7 +1856,8 @@ HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw, + enum EdgeType edge; + int delay = 1000000000; + +- if (priv->finger_state == FS_BLOCKED) ++ if (para->touchpad_off == TOUCHPAD_OFF || ++ priv->finger_state == FS_BLOCKED) + return delay; + + touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED; +@@ -2274,7 +2275,9 @@ HandleScrolling(SynapticsPrivate * priv, struct SynapticsHwState *hw, + SynapticsParameters *para = &priv->synpara; + int delay = 1000000000; + +- if ((priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) || (priv->finger_state == FS_BLOCKED)) { ++ if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF || ++ priv->synpara.touchpad_off == TOUCHPAD_OFF || ++ priv->finger_state == FS_BLOCKED) { + stop_coasting(priv); + priv->circ_scroll_on = FALSE; + priv->vert_scroll_edge_on = FALSE; +@@ -2883,12 +2886,6 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + Bool using_cumulative_coords = FALSE; + Bool ignore_motion; + +- /* If touchpad is switched off, we skip the whole thing and return delay */ +- if (para->touchpad_off == TOUCHPAD_OFF) { +- UpdateTouchState(pInfo, hw); +- return delay; +- } +- + /* We need both and x/y, the driver can't handle just one of the two + * yet. But since it's possible to hit a phys button on non-clickpads + * without ever getting motion data first, we must continue with 0/0 for +@@ -2927,8 +2924,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, + current_button_area(para, hw->x, hw->y) == NO_BUTTON_AREA) + priv->last_button_area = NO_BUTTON_AREA; + +- ignore_motion = +- !using_cumulative_coords && priv->last_button_area != NO_BUTTON_AREA; ++ ignore_motion = para->touchpad_off == TOUCHPAD_OFF || ++ (!using_cumulative_coords && priv->last_button_area != NO_BUTTON_AREA); + + /* these two just update hw->left, right, etc. */ + update_hw_button_state(pInfo, hw, now, &delay); +-- +1.9.3 + diff --git a/SOURCES/0014-Add-support-for-INPUT_PROP_TOPBUTTONPAD.patch b/SOURCES/0014-Add-support-for-INPUT_PROP_TOPBUTTONPAD.patch new file mode 100644 index 0000000..c70f726 --- /dev/null +++ b/SOURCES/0014-Add-support-for-INPUT_PROP_TOPBUTTONPAD.patch @@ -0,0 +1,198 @@ +From e5539482f204cfa8cd053a1afed05a622f7f03dc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Apr 2014 18:58:11 +0200 +Subject: [PATCH synaptics 14/14] Add support for INPUT_PROP_TOPBUTTONPAD + +Add a HasSecondaryButtons boolean config option which defaults to true for +devices with the INPUT_PROP_TOPBUTTONPAD and false for all other devices. + +Only parse the SecondarySoftButtonAreas when this option is true, effectively +disabling the top buttons when it is false. Likewise, only initialize the +SecondarySoftButtonAreas property if we enable support for it. + +This means that it is now safe to always set a SecondarySoftButtonAreas +default in 50-synaptics.conf, and that he section which was intended for +use with future pnp-id matching can be dropped, as that is now all handled +in the kernel. + +While at also remove the comment about disabling the bottom edge area, as that +is now done automatically. + +Signed-off-by: Hans de Goede +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +(cherry picked from commit 7bf27568417691e772e715f8fc6c30ea7ec892d6) + +Conflicts: + src/eventcomm.c + +(cherry picked from commit fa54c5b8fcf75531b2d6c6bb6879b3414e5c7792) +--- + conf/50-synaptics.conf | 9 ++++----- + man/synaptics.man | 29 +++++++++++++++++++++++------ + src/eventcomm.c | 8 ++++++++ + src/properties.c | 3 +++ + src/synaptics.c | 7 ++++++- + src/synapticsstr.h | 1 + + 6 files changed, 45 insertions(+), 12 deletions(-) + +diff --git a/conf/50-synaptics.conf b/conf/50-synaptics.conf +index dd16ca2..a3145b8 100644 +--- a/conf/50-synaptics.conf ++++ b/conf/50-synaptics.conf +@@ -25,16 +25,15 @@ Section "InputClass" + Option "Ignore" "on" + EndSection + +-# This option enables the bottom right corner to be a right button on +-# non-synaptics clickpads. ++# This option enables the bottom right corner to be a right button on clickpads ++# and the right and middle top areas to be right / middle buttons on clickpads ++# with a top button area. + # This option is only interpreted by clickpads. + Section "InputClass" + Identifier "Default clickpad buttons" + MatchDriver "synaptics" + Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0" +-# To disable the bottom edge area so the buttons only work as buttons, +-# not for movement, set the AreaBottomEdge +-# Option "AreaBottomEdge" "82%" ++ Option "SecondarySoftButtonAreas" "58% 0 0 8% 42% 58% 0 8%" + EndSection + + # This option disables software buttons on Apple touchpads. +diff --git a/man/synaptics.man b/man/synaptics.man +index 86eb663..e35ab6c 100644 +--- a/man/synaptics.man ++++ b/man/synaptics.man +@@ -453,17 +453,28 @@ buttons to share an edge value. + Property: "Synaptics Soft Button Areas" + . + .TP +-.BI "Option \*qSecondarySoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q ++.BI "Option \*qHasSecondarySoftButtons\*q \*q" boolean \*q + This option is only available on ClickPad devices. +-Enable secondary soft button click area support on ClickPad devices (usually on ++Enable the secondary software button area support. The exact area must be ++set in option \*qSecondarySoftButtonAreas\*q. See ++.B ClickPad support ++for more details. ++. ++.TP ++.BI "Option \*qSecondarySoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q ++This option is only available on ClickPad devices and only if ++.B Option \*qHasSecondarySoftButtons\*q ++is enabled. ++Define the secondary soft button click areas on ClickPad devices (usually on + top of the device). + For the allowed values for this option, see + .B Option \*qSoftButtonAreas\*q. + Primary and secondary soft button areas must not overlap each other. If they do, + the behavior of the driver is undefined. + Property: "Synaptics Secondary Soft Button Areas". This property is only +-initialized if the option is set in the +-__xconfigfile__(__filemansuffix__). ++initialized if ++.B Option \*qHasSecondarySoftButtons\*q ++is enabled and this option is set in the __xconfigfile__(__filemansuffix__). + . + + .SH CONFIGURATION DETAILS +@@ -690,9 +701,15 @@ area, a right or middle click is performed. + .LP + Some laptops, most notably the Lenovo T440, T540 and x240 series, provide a + pointing stick without physical buttons. On those laptops, the top of the +-touchpad acts as software-emulated button area. This area can be configured ++touchpad acts as software-emulated button area. This area can be enabled + with +-.B Option SecondarySoftButtonAreas. ++.B Option \*qHasSecondarySoftButtons\*q ++and configured ++with ++.B Option \*qSecondarySoftButtonAreas\*q. ++On some platforms, this option ++will be set automatically if the kernel detects a matching device. On Linux, ++the device must have the INPUT_PROP_TOPBUTTONPAD property set. + + .SH "DEVICE PROPERTIES" + Synaptics 1.0 and higher support input device properties if the driver is +diff --git a/src/eventcomm.c b/src/eventcomm.c +index 4550ef2..a66c6b0 100644 +--- a/src/eventcomm.c ++++ b/src/eventcomm.c +@@ -50,6 +50,9 @@ + #ifndef INPUT_PROP_SEMI_MT + #define INPUT_PROP_SEMI_MT 0x03 + #endif ++#ifndef INPUT_PROP_TOPBUTTONPAD ++#define INPUT_PROP_TOPBUTTONPAD 0x04 ++#endif + + #define SYSCALL(call) while (((call) == -1) && (errno == EINTR)) + +@@ -802,6 +805,11 @@ event_query_touch(InputInfoPtr pInfo) + xf86IDrvMsg(pInfo, X_INFO, "found clickpad property\n"); + para->clickpad = TRUE; + } ++ ++ if (rc>= 0 && BitIsOn(&prop, INPUT_PROP_TOPBUTTONPAD)) { ++ xf86IDrvMsg(pInfo, X_INFO, "found top buttonpad property\n"); ++ para->has_secondary_buttons = TRUE; ++ } + #endif + + mtdev = mtdev_new_open(pInfo->fd); +diff --git a/src/properties.c b/src/properties.c +index 278114a..b3e09c0 100644 +--- a/src/properties.c ++++ b/src/properties.c +@@ -173,6 +173,9 @@ InitSoftButtonProperty(InputInfoPtr pInfo) + prop_softbutton_areas = + InitAtom(pInfo->dev, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 8, values); + ++ if (!para->has_secondary_buttons) ++ return; ++ + values[0] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][LEFT]; + values[1] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][RIGHT]; + values[2] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][TOP]; +diff --git a/src/synaptics.c b/src/synaptics.c +index 78adfaf..68705e7 100644 +--- a/src/synaptics.c ++++ b/src/synaptics.c +@@ -659,6 +659,10 @@ set_default_parameters(InputInfoPtr pInfo) + pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180); + pars->click_time = xf86SetIntOption(opts, "ClickTime", 100); + pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad); /* Probed */ ++ if (pars->clickpad) ++ pars->has_secondary_buttons = xf86SetBoolOption(opts, ++ "HasSecondarySoftButtons", ++ pars->has_secondary_buttons); + pars->clickpad_ignore_motion_time = 100; /* ms */ + /* middle mouse button emulation on a clickpad? nah, you're joking */ + middle_button_timeout = pars->clickpad ? 0 : 75; +@@ -738,7 +742,8 @@ set_default_parameters(InputInfoPtr pInfo) + } + + set_primary_softbutton_areas_option(pInfo); +- set_secondary_softbutton_areas_option(pInfo); ++ if (pars->has_secondary_buttons) ++ set_secondary_softbutton_areas_option(pInfo); + } + + static double +diff --git a/src/synapticsstr.h b/src/synapticsstr.h +index 1622123..4226f06 100644 +--- a/src/synapticsstr.h ++++ b/src/synapticsstr.h +@@ -172,6 +172,7 @@ typedef struct _SynapticsParameters { + int tap_time_2; /* max. tapping time for double taps */ + int click_time; /* The duration of a single click */ + Bool clickpad; /* Device is a has integrated buttons */ ++ Bool has_secondary_buttons; /* Device has a top soft-button area */ + int clickpad_ignore_motion_time; /* Ignore motion for X ms after a click */ + int emulate_mid_button_time; /* Max time between left and right button presses to + emulate a middle button press. */ +-- +1.9.3 + diff --git a/SOURCES/50-synaptics.conf b/SOURCES/50-synaptics.conf index 7f022bc..c9fdfea 100644 --- a/SOURCES/50-synaptics.conf +++ b/SOURCES/50-synaptics.conf @@ -12,6 +12,7 @@ Section "InputClass" Identifier "Default clickpad buttons" MatchDriver "synaptics" Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0" + Option "SecondarySoftButtonAreas" "58% 0 0 8% 42% 58% 0 8%" EndSection # This option disables software buttons on Apple touchpads. diff --git a/SPECS/xorg-x11-drv-synaptics.spec b/SPECS/xorg-x11-drv-synaptics.spec index 58bab28..e8479da 100644 --- a/SPECS/xorg-x11-drv-synaptics.spec +++ b/SPECS/xorg-x11-drv-synaptics.spec @@ -8,7 +8,7 @@ Name: xorg-x11-drv-synaptics Summary: Xorg X11 Synaptics touchpad input driver Version: 1.7.1 -Release: 10%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Release: 10%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}.1 URL: http://www.x.org License: MIT Group: User Interface/X Hardware Support @@ -26,6 +26,22 @@ Source4: 70-touchpad-quirks.rules Patch01: 0001-Disable-driver-scaling-for-input-ABI-19.2.patch Patch02: 0001-Fix-ABI-detection-for-in-driver-scaling.patch +# Bug 1093050 - Improve Responsiveness on Touchpads for Lenovo T440s/T540p/etc +Patch04: 0001-Avoid-erroneously-handling-two-touchpoints-in-the-sa.patch +Patch05: 0002-Allow-using-the-entire-touchpad-for-motions-started-.patch +Patch06: 0003-Add-secondary-top-software-buttons-area.patch +Patch07: 0004-Add-an-enum-for-the-different-soft_button_areas.patch +Patch08: 0005-Get-rid-of-old_hw_state.patch +Patch09: 0006-Don-t-report-motion-inside-soft-button-areas.patch +Patch10: 0007-Ignore-motion-the-first-X-ms-after-a-clickpad-click.patch +Patch11: 0008-On-button-down-update-cumulative-to-current-x-and-y-.patch +Patch12: 0009-Wait-for-new-coordinates-on-a-clickpad-click-before-.patch +Patch13: 0010-Add-property-support-for-secondary-top-software-butt.patch +Patch14: 0011-Replace-is_inside_anybutton_area-with-current_button.patch +Patch15: 0012-Don-t-allow-any-type-of-movement-starting-in-the-top.patch +Patch16: 0013-If-the-touchpad-is-in-TOUCHPAD_OFF-mode-allow-physic.patch +Patch17: 0014-Add-support-for-INPUT_PROP_TOPBUTTONPAD.patch + ExcludeArch: s390 s390x BuildRequires: autoconf automake libtool pkgconfig @@ -85,6 +101,20 @@ Features: %setup -q -n %{tarball}-%{?gitdate:%{gitdate}}%{!?gitdate:%{version}} %patch01 -p1 %patch02 -p1 +%patch04 -p1 +%patch05 -p1 +%patch06 -p1 +%patch07 -p1 +%patch08 -p1 +%patch09 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 %build autoreconf -v --install --force || exit 1 @@ -140,6 +170,9 @@ Development files for the Synaptics TouchPad for X.Org. %changelog +* Wed Jul 23 2014 Peter Hutterer 1.7.1-10.1 +- Add support for secondary software button areas (#1122130) + * Wed Jan 15 2014 Adam Jackson - 1.7.1-10 - 1.15 ABI rebuild