From dd8f92781f5c8aa8067a74b9c57646412d6a250d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sun, 29 Dec 2013 11:05:06 -0500 Subject: [PATCH synaptics] Add another third state to TouchpadOff for disabling all but button clicks On a new set of laptops like the Lenovo T440 the trackstick does not have physical buttons. Instead, the touchpad's top edge is supposed to acts software button area. To avoid spurious cursor jumps when the trackstick is in use and the finger is resting on the touchpad, add another mode that disables motion events. Enabled by syndaemon with -t click-only, the default stays unchanged. No specific integration with the traditional disable-while-typing is needed. On such touchpads, disabling motion events is sufficient to avoid spurious events and we don't want to stop HW buttons to send events. Note that this only adds the new state to the driver and to syndaemon, there is nothing hooked up otherwise to actually monitor the trackstick. Special note for syndaemon: optional arguments are a GNU extension, so work around it by messing with an optstring starting with ":" which allows us to manually parse the options. Original version of this patch by John Pham Signed-off-by: Peter Hutterer --- man/synaptics.man | 1 + man/syndaemon.man | 8 +++++--- src/properties.c | 2 +- src/synaptics.c | 13 ++++++++++--- src/synapticsstr.h | 2 ++ tools/synclient.c | 2 +- tools/syndaemon.c | 33 ++++++++++++++++++++++++++------- 7 files changed, 46 insertions(+), 15 deletions(-) diff --git a/man/synaptics.man b/man/synaptics.man index 079a5f8..d9423be 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -228,6 +228,7 @@ l l. 0 Touchpad is enabled 1 Touchpad is switched off 2 Only tapping and scrolling is switched off +3 Only cursor movement is switched off .TE Property: "Synaptics Off" .TP diff --git a/man/syndaemon.man b/man/syndaemon.man index 87691d8..30ea20b 100644 --- a/man/syndaemon.man +++ b/man/syndaemon.man @@ -45,9 +45,11 @@ A pid file will only be created if the program is started in daemon mode. .LP .TP -\fB\-t\fP -Only disable tapping and scrolling, not mouse movements, in response -to keyboard activity. +\fB\-t\fP [off|tapping|click-only] + Disable state. "off" for disabling the touchpad entirely, "tapping" for + disabling tapping and scrolling only, "click-only" for disabling + everything but physical clicks. The default if this option is missing is + "off". If this option is given without a mode it defaults to "tapping". .LP .TP \fB\-k\fP diff --git a/src/properties.c b/src/properties.c index 797f1da..4623f42 100644 --- a/src/properties.c +++ b/src/properties.c @@ -526,7 +526,7 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, off = *(CARD8 *) prop->data; - if (off > 2) + if (off > 3) return BadValue; para->touchpad_off = off; diff --git a/src/synaptics.c b/src/synaptics.c index 5b95d9d..b9e49c1 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -1659,7 +1659,8 @@ SelectTapButton(SynapticsPrivate * priv, enum EdgeType edge) { enum TapEvent tap; - if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) { + if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF || + priv->synpara.touchpad_off == TOUCHPAD_CLICK_ONLY) { priv->tap_button = 0; return; } @@ -2198,7 +2199,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_CLICK_ONLY) || + (priv->finger_state == FS_BLOCKED)) { stop_coasting(priv); priv->circ_scroll_on = FALSE; priv->vert_scroll_edge_on = FALSE; @@ -2697,6 +2700,9 @@ HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw) Bool restart_touches = FALSE; int i; + if (para->touchpad_off == TOUCHPAD_CLICK_ONLY) + goto out; + if (para->click_action[F3_CLICK1] || para->tap_action[F3_TAP]) min_touches = 4; else if (para->click_action[F2_CLICK1] || para->tap_action[F2_TAP] || @@ -2920,7 +2926,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, } /* Post events */ - if (finger >= FS_TOUCHED && (dx || dy)) + if (finger >= FS_TOUCHED && (dx || dy) && + (para->touchpad_off != TOUCHPAD_CLICK_ONLY)) 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 3d6f756..0d4d8b5 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -59,6 +59,7 @@ enum OffState { TOUCHPAD_ON = 0, TOUCHPAD_OFF = 1, TOUCHPAD_TAP_OFF = 2, + TOUCHPAD_CLICK_ONLY = 3 }; enum TapEvent { @@ -172,6 +173,7 @@ typedef struct _SynapticsParameters { * 0 : Not off * 1 : Off * 2 : Only tapping and scrolling off + * 3 : All but physical clicks off */ Bool locked_drags; /* Enable locked drags */ int locked_drag_time; /* timeout for locked drags */ diff --git a/tools/synclient.c b/tools/synclient.c index bd7cb61..ce156db 100644 --- a/tools/synclient.c +++ b/tools/synclient.c @@ -98,7 +98,7 @@ static struct Parameter params[] = { {"MinSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 0}, {"MaxSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 1}, {"AccelFactor", PT_DOUBLE, 0, 1.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 2}, - {"TouchpadOff", PT_INT, 0, 2, SYNAPTICS_PROP_OFF, 8, 0}, + {"TouchpadOff", PT_INT, 0, 3, SYNAPTICS_PROP_OFF, 8, 0}, {"LockedDrags", PT_BOOL, 0, 1, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 0}, {"LockedDragTimeout", PT_INT, 0, 30000, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 0}, {"RTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 0}, diff --git a/tools/syndaemon.c b/tools/syndaemon.c index 29e75f5..b181d16 100644 --- a/tools/syndaemon.c +++ b/tools/syndaemon.c @@ -50,7 +50,8 @@ enum TouchpadState { TouchpadOn = 0, TouchpadOff = 1, - TappingOff = 2 + TappingOff = 2, + ClickOnly = 3 }; static Bool pad_disabled @@ -73,7 +74,7 @@ static void usage(void) { fprintf(stderr, - "Usage: syndaemon [-i idle-time] [-m poll-delay] [-d] [-t] [-k]\n"); + "Usage: syndaemon [-i idle-time] [-m poll-delay] [-d] [-t [off|tapping|click-only]] [-k]\n"); fprintf(stderr, " -i How many seconds to wait after the last key press before\n"); fprintf(stderr, " enabling the touchpad. (default is 2.0s)\n"); @@ -82,7 +83,10 @@ usage(void) fprintf(stderr, " -d Start as a daemon, i.e. in the background.\n"); fprintf(stderr, " -p Create a pid file with the specified name.\n"); fprintf(stderr, - " -t Only disable tapping and scrolling, not mouse movements.\n"); + " -t Disable state.\n" + " 'off' for disabling the touchpad entirely, \n" + " 'tapping' for disabling tapping and scrolling only,\n" + " 'click-only' for disabling everything but physical clicks.\n"); fprintf(stderr, " -k Ignore modifier keys when monitoring keyboard activity.\n"); fprintf(stderr, " -K Like -k but also ignore Modifier+Key combos.\n"); @@ -547,7 +551,7 @@ main(int argc, char *argv[]) int use_xrecord = 0; /* Parse command line parameters */ - while ((c = getopt(argc, argv, "i:m:dtp:kKR?v")) != EOF) { + while ((c = getopt(argc, argv, ":i:m:dp:kKR?v")) != EOF) { switch (c) { case 'i': idle_time = atof(optarg); @@ -558,9 +562,6 @@ main(int argc, char *argv[]) case 'd': background = 1; break; - case 't': - disable_state = TappingOff; - break; case 'p': pid_file = optarg; break; @@ -578,6 +579,24 @@ main(int argc, char *argv[]) verbose = 1; break; case '?': + if (optopt != 't') + usage(); + else { + if (optind < argc) { + if (argv[optind][0] == '-') + disable_state = TappingOff; + else if (strcmp(argv[optind], "off") == 0) + disable_state = TouchpadOff; + else if (strcmp(argv[optind], "tapping") == 0) + disable_state = TappingOff; + else if (strcmp(argv[optind], "click-only") == 0) + disable_state = ClickOnly; + else + usage(); + } else + disable_state = TappingOff; + } + break; default: usage(); break; -- 1.8.4.2