From b1ba6288e21c5788c3a17828782da55f65f7d523 Mon Sep 17 00:00:00 2001 From: bru Date: Wed, 3 Mar 2021 19:44:37 +0000 Subject: [PATCH] Add a configurable button mapping for tap gestures on touchpads. Thanks to RJ Johnson for this work! ok mpi@ --- sbin/wsconsctl/mousecfg.c | 42 +++++++++++++++++++++++---- share/man/man4/wsmouse.4 | 29 +++++++++++++------ sys/dev/wscons/wsconsio.h | 8 +++-- sys/dev/wscons/wstpad.c | 61 +++++++++++++++++++++++++++------------ 4 files changed, 104 insertions(+), 36 deletions(-) diff --git a/sbin/wsconsctl/mousecfg.c b/sbin/wsconsctl/mousecfg.c index afa98cfb1ce..76a9984bd86 100644 --- a/sbin/wsconsctl/mousecfg.c +++ b/sbin/wsconsctl/mousecfg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mousecfg.c,v 1.8 2021/03/02 22:35:19 bru Exp $ */ +/* $OpenBSD: mousecfg.c,v 1.9 2021/03/03 19:44:37 bru Exp $ */ /* * Copyright (c) 2017 Ulf Brosziewski @@ -40,9 +40,9 @@ #define TP_FILTER_FIRST WSMOUSECFG_DX_MAX #define TP_FILTER_LAST WSMOUSECFG_SMOOTHING #define TP_FEATURES_FIRST WSMOUSECFG_SOFTBUTTONS -#define TP_FEATURES_LAST WSMOUSECFG_TAPPING +#define TP_FEATURES_LAST WSMOUSECFG_DISABLE #define TP_SETUP_FIRST WSMOUSECFG_LEFT_EDGE -#define TP_SETUP_LAST WSMOUSECFG_TAP_LOCKTIME +#define TP_SETUP_LAST WSMOUSECFG_TAP_THREE_BTNMAP #define LOG_FIRST WSMOUSECFG_LOG_INPUT #define LOG_LAST WSMOUSECFG_LOG_EVENTS @@ -71,8 +71,10 @@ static const int touchpad_types[] = { struct wsmouse_parameters cfg_tapping = { (struct wsmouse_param[]) { - { WSMOUSECFG_TAPPING, 0 }, }, - 1 + { WSMOUSECFG_TAP_ONE_BTNMAP, 0 }, + { WSMOUSECFG_TAP_TWO_BTNMAP, 0 }, + { WSMOUSECFG_TAP_THREE_BTNMAP, 0 }, }, + 3 }; struct wsmouse_parameters cfg_scaling = { @@ -267,6 +269,30 @@ set_percent(struct wsmouse_parameters *field, enum wsmousecfg key, float f) set_value(field, key, (int) ((f * 4096 + 50) / 100)); } +static int +set_tapping(struct wsmouse_parameters *field, char *tapping) +{ + int i1, i2, i3; + + switch (sscanf(tapping, "%d,%d,%d", &i1, &i2, &i3)) { + case 1: + if (i1 == 0) /* Disable */ + i2 = i3 = i1; + else { /* Enable with defaults */ + i1 = 1; /* Left click */ + i2 = 3; /* Right click */ + i3 = 2; /* Middle click */ + } + /* FALLTHROUGH */ + case 3: + set_value(field, WSMOUSECFG_TAP_ONE_BTNMAP, i1); + set_value(field, WSMOUSECFG_TAP_TWO_BTNMAP, i2); + set_value(field, WSMOUSECFG_TAP_THREE_BTNMAP, i3); + return (0); + } + return (-1); +} + static int set_edges(struct wsmouse_parameters *field, char *edges) { @@ -368,6 +394,12 @@ mousecfg_rd_field(struct wsmouse_parameters *field, char *val) return; } + if (field == &cfg_tapping) { + if (set_tapping(field, val)) + errx(1, "invalid input (tapping)"); + return; + } + if (field == &cfg_scaling) { if (sscanf(val, "%f", &f) == 1) { n = (int) (f * 4096); diff --git a/share/man/man4/wsmouse.4 b/share/man/man4/wsmouse.4 index b238b1bf7ef..7806ccfff07 100644 --- a/share/man/man4/wsmouse.4 +++ b/share/man/man4/wsmouse.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: wsmouse.4,v 1.20 2018/02/04 20:29:59 bru Exp $ +.\" $OpenBSD: wsmouse.4,v 1.21 2021/03/03 19:44:37 bru Exp $ .\" $NetBSD: wsmouse.4,v 1.3 1999/12/06 14:52:08 augustss Exp $ .\" .\" Copyright (c) 2018 Ulf Brosziewski @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: February 4 2018 $ +.Dd $Mdocdate: March 3 2021 $ .Dt WSMOUSE 4 .Os .Sh NAME @@ -87,13 +87,24 @@ is omitted, commands apply to .Pa /dev/wsmouse0 . .Bl -tag -width Ds .It Cm mouse.tp.tapping -Setting this parameter to a non-zero value enables tap gestures. -Contacts on the touchpad that are immediately released again -trigger click events. -One-finger, two-finger, and three-finger taps generate left-button, -right-button, and middle-button clicks, respectively. -If, within a short time interval, a second touch follows a one-finger -tap, the button-up event is not issued until that touch ends +Contacts on the touchpad that are immediately released again can +be mapped to mouse button clicks. This list of three parameters +configures these mappings, in the order: +.Bd -literal -offset indent +.Sm off +.Ar one-finger , two-finger , three-finger +.Sm on +.Ed +.Pp +Setting a parameter to a positive value enables that tap gesture +and maps it to the given mouse button. To disable all three tap +gestures at once, provide the single value of 0. Conversely, a +single non-zero value will enable one-finger, two-finger, and +three-finger tap gestures with their default mappings of left +button, right button, and middle button, respectively. If, within +a short time interval, a second touch follows a tap gesture +mapped to a left-button click, the button-up event is not issued +until that touch ends .Pq Dq tap-and-drag . .It Cm mouse.tp.scaling The value is a scale coefficient that is applied to the relative diff --git a/sys/dev/wscons/wsconsio.h b/sys/dev/wscons/wsconsio.h index 32ef4116521..7c3fc7ae73e 100644 --- a/sys/dev/wscons/wsconsio.h +++ b/sys/dev/wscons/wsconsio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsio.h,v 1.95 2020/10/01 17:28:14 kettenis Exp $ */ +/* $OpenBSD: wsconsio.h,v 1.96 2021/03/03 19:44:37 bru Exp $ */ /* $NetBSD: wsconsio.h,v 1.74 2005/04/28 07:15:44 martin Exp $ */ /* @@ -319,7 +319,6 @@ enum wsmousecfg { WSMOUSECFG_SWAPSIDES, /* invert soft-button/scroll areas */ WSMOUSECFG_DISABLE, /* disable all output except for clicks in the top-button area */ - WSMOUSECFG_TAPPING, /* enable tapping */ /* * Touchpad options @@ -338,6 +337,9 @@ enum wsmousecfg { the button-up-event (ms) */ WSMOUSECFG_TAP_LOCKTIME, /* time between a tap-and-drag action and the button-up-event (ms) */ + WSMOUSECFG_TAP_ONE_BTNMAP, /* one-finger tap button mapping */ + WSMOUSECFG_TAP_TWO_BTNMAP, /* two-finger tap button mapping */ + WSMOUSECFG_TAP_THREE_BTNMAP, /* three-finger tap button mapping */ /* * Enable/Disable debug output. @@ -345,7 +347,7 @@ enum wsmousecfg { WSMOUSECFG_LOG_INPUT = 256, WSMOUSECFG_LOG_EVENTS, }; -#define WSMOUSECFG_MAX 39 /* max size of param array per ioctl */ +#define WSMOUSECFG_MAX 41 /* max size of param array per ioctl */ struct wsmouse_param { enum wsmousecfg key; diff --git a/sys/dev/wscons/wstpad.c b/sys/dev/wscons/wstpad.c index f916cbba2e5..9e89bb04762 100644 --- a/sys/dev/wscons/wstpad.c +++ b/sys/dev/wscons/wstpad.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wstpad.c,v 1.26 2020/09/13 10:05:46 fcambus Exp $ */ +/* $OpenBSD: wstpad.c,v 1.27 2021/03/03 19:44:37 bru Exp $ */ /* * Copyright (c) 2015, 2016 Ulf Brosziewski @@ -33,9 +33,11 @@ #include #include -#define LEFTBTN (1 << 0) -#define MIDDLEBTN (1 << 1) -#define RIGHTBTN (1 << 2) +#define BTNMASK(n) ((n) > 0 && (n) <= 32 ? 1 << ((n) - 1) : 0) + +#define LEFTBTN BTNMASK(1) +#define MIDDLEBTN BTNMASK(2) +#define RIGHTBTN BTNMASK(3) #define PRIMARYBTN LEFTBTN @@ -57,6 +59,7 @@ #define TAP_MAXTIME_DEFAULT 180 #define TAP_CLICKTIME_DEFAULT 180 #define TAP_LOCKTIME_DEFAULT 0 +#define TAP_BTNMAP_SIZE 3 #define CLICKDELAY_MS 20 #define FREEZE_MS 100 @@ -147,7 +150,6 @@ struct tpad_touch { #define WSTPAD_HORIZSCROLL (1 << 5) #define WSTPAD_SWAPSIDES (1 << 6) #define WSTPAD_DISABLE (1 << 7) -#define WSTPAD_TAPPING (1 << 8) #define WSTPAD_MT (1 << 31) @@ -218,6 +220,7 @@ struct wstpad { struct timespec maxtime; int clicktime; int locktime; + u_int btnmap[TAP_BTNMAP_SIZE]; } tap; struct { @@ -722,7 +725,7 @@ tap_btn(struct wstpad *tp, int nmasked) { int n = tp->tap.contacts - nmasked; - return (n == 2 ? RIGHTBTN : (n == 3 ? MIDDLEBTN : LEFTBTN)); + return (n <= TAP_BTNMAP_SIZE ? tp->tap.btnmap[n - 1] : 0); } /* @@ -793,9 +796,13 @@ wstpad_tap(struct wsmouseinput *input, u_int *cmds) tp->tap.centered = 0; } if (tp->tap.state == TAP_LIFTED) { - *cmds |= 1 << TAPBUTTON_DOWN; - err = !timeout_add_msec(&tp->tap.to, - tp->tap.clicktime); + if (tp->tap.button != 0) { + *cmds |= 1 << TAPBUTTON_DOWN; + err = !timeout_add_msec(&tp->tap.to, + tp->tap.clicktime); + } else { + tp->tap.state = TAP_DETECT; + } } } break; @@ -1528,7 +1535,7 @@ int wstpad_configure(struct wsmouseinput *input) { struct wstpad *tp; - int width, height, diag, offset, h_res, v_res, h_unit, v_unit; + int width, height, diag, offset, h_res, v_res, h_unit, v_unit, i; width = abs(input->hw.x_max - input->hw.x_min); height = abs(input->hw.y_max - input->hw.y_min); @@ -1626,12 +1633,16 @@ wstpad_configure(struct wsmouseinput *input) else if (tp->features & WSTPAD_EDGESCROLL) tp->handlers |= 1 << EDGESCROLL_HDLR; - if (tp->features & WSTPAD_TAPPING) { + for (i = 0; i < TAP_BTNMAP_SIZE; i++) { + if (tp->tap.btnmap[i] == 0) + continue; + tp->tap.clicktime = imin(imax(tp->tap.clicktime, 80), 350); if (tp->tap.locktime) tp->tap.locktime = imin(imax(tp->tap.locktime, 150), 5000); tp->handlers |= 1 << TAP_HDLR; + break; } if (input->hw.hw_type == WSMOUSEHW_CLICKPAD) @@ -1669,7 +1680,7 @@ wstpad_set_param(struct wsmouseinput *input, int key, int val) return (EINVAL); switch (key) { - case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_TAPPING: + case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_DISABLE: switch (key) { case WSMOUSECFG_SOFTBUTTONS: flag = WSTPAD_SOFTBUTTONS; @@ -1695,9 +1706,6 @@ wstpad_set_param(struct wsmouseinput *input, int key, int val) case WSMOUSECFG_DISABLE: flag = WSTPAD_DISABLE; break; - case WSMOUSECFG_TAPPING: - flag = WSTPAD_TAPPING; - break; } if (val) tp->features |= flag; @@ -1740,6 +1748,15 @@ wstpad_set_param(struct wsmouseinput *input, int key, int val) case WSMOUSECFG_TAP_LOCKTIME: tp->tap.locktime = val; break; + case WSMOUSECFG_TAP_ONE_BTNMAP: + tp->tap.btnmap[0] = BTNMASK(val); + break; + case WSMOUSECFG_TAP_TWO_BTNMAP: + tp->tap.btnmap[1] = BTNMASK(val); + break; + case WSMOUSECFG_TAP_THREE_BTNMAP: + tp->tap.btnmap[2] = BTNMASK(val); + break; default: return (ENOTSUP); } @@ -1757,7 +1774,7 @@ wstpad_get_param(struct wsmouseinput *input, int key, int *pval) return (EINVAL); switch (key) { - case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_TAPPING: + case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_DISABLE: switch (key) { case WSMOUSECFG_SOFTBUTTONS: flag = WSTPAD_SOFTBUTTONS; @@ -1783,9 +1800,6 @@ wstpad_get_param(struct wsmouseinput *input, int key, int *pval) case WSMOUSECFG_DISABLE: flag = WSTPAD_DISABLE; break; - case WSMOUSECFG_TAPPING: - flag = WSTPAD_TAPPING; - break; } *pval = !!(tp->features & flag); break; @@ -1825,6 +1839,15 @@ wstpad_get_param(struct wsmouseinput *input, int key, int *pval) case WSMOUSECFG_TAP_LOCKTIME: *pval = tp->tap.locktime; break; + case WSMOUSECFG_TAP_ONE_BTNMAP: + *pval = ffs(tp->tap.btnmap[0]); + break; + case WSMOUSECFG_TAP_TWO_BTNMAP: + *pval = ffs(tp->tap.btnmap[1]); + break; + case WSMOUSECFG_TAP_THREE_BTNMAP: + *pval = ffs(tp->tap.btnmap[2]); + break; default: return (ENOTSUP); } -- 2.20.1