Based on a proposal of tobhe@.
ok tobhe@
-/* $OpenBSD: mouse.c,v 1.20 2019/08/19 21:42:33 bru Exp $ */
+/* $OpenBSD: mouse.c,v 1.21 2023/07/02 21:44:04 bru Exp $ */
/* $NetBSD: mouse.c,v 1.3 1999/11/15 13:47:30 ad Exp $ */
/*-
{ "reverse_scrolling", &cfg_revscroll, FMT_CFG, FLG_NORDBACK },
/* touchpad-specific options: */
{ "tp.tapping", &cfg_tapping, FMT_CFG, FLG_NORDBACK },
+ { "tp.mtbuttons", &cfg_mtbuttons, FMT_CFG, FLG_NORDBACK },
{ "tp.scaling", &cfg_scaling, FMT_CFG, FLG_NORDBACK },
{ "tp.swapsides", &cfg_swapsides, FMT_CFG, FLG_NORDBACK },
{ "tp.disable", &cfg_disable, FMT_CFG, FLG_NORDBACK },
static int dev_index = -1;
+static struct wsmouse_parameters mtbtn_maxdist = {
+ (struct wsmouse_param[]) { { WSMOUSECFG_MTBTN_MAXDIST, 0 } }, 1
+};
+
void
mouse_init(int devfd, int devidx) {
if (f->format == FMT_CFG) {
f->flags &= ~FLG_DEAD;
}
+ /* Hide the 'mtbuttons' field if the feature is unavailable. */
+ if (mousecfg_get_field(&mtbtn_maxdist) ||
+ mtbtn_maxdist.params[0].value < 0) {
+ f = field_by_value(mouse_field_tab, &cfg_mtbuttons);
+ f->flags |= FLG_DEAD;
+ }
} else {
for (f = mouse_field_tab; f->name != NULL; f++)
if (f->format == FMT_CFG) {
-/* $OpenBSD: mousecfg.c,v 1.9 2021/03/03 19:44:37 bru Exp $ */
+/* $OpenBSD: mousecfg.c,v 1.10 2023/07/02 21:44:04 bru Exp $ */
/*
* Copyright (c) 2017 Ulf Brosziewski
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
-#define BASE_FIRST WSMOUSECFG_DX_SCALE
-#define BASE_LAST WSMOUSECFG_REVERSE_SCROLLING
-#define TP_FILTER_FIRST WSMOUSECFG_DX_MAX
-#define TP_FILTER_LAST WSMOUSECFG_SMOOTHING
-#define TP_FEATURES_FIRST WSMOUSECFG_SOFTBUTTONS
-#define TP_FEATURES_LAST WSMOUSECFG_DISABLE
-#define TP_SETUP_FIRST WSMOUSECFG_LEFT_EDGE
-#define TP_SETUP_LAST WSMOUSECFG_TAP_THREE_BTNMAP
-#define LOG_FIRST WSMOUSECFG_LOG_INPUT
-#define LOG_LAST WSMOUSECFG_LOG_EVENTS
-
-#define BASESIZE ((BASE_LAST - BASE_FIRST + 1) + (LOG_LAST - LOG_FIRST + 1))
-
-#define BUFSIZE (BASESIZE \
- + (TP_FILTER_LAST - TP_FILTER_FIRST + 1) \
- + (TP_FEATURES_LAST - TP_FEATURES_FIRST + 1) \
- + (TP_SETUP_LAST - TP_SETUP_FIRST + 1))
+#define BASESIZE ((WSMOUSECFG__FILTERS - WSMOUSECFG_DX_SCALE) \
+ + (WSMOUSECFG__DEBUG - WSMOUSECFG_LOG_INPUT))
static const int range[][2] = {
- { BASE_FIRST, BASE_LAST },
- { LOG_FIRST, LOG_LAST },
- { TP_FILTER_FIRST, TP_FILTER_LAST },
- { TP_FEATURES_FIRST, TP_FEATURES_LAST },
- { TP_SETUP_FIRST, TP_SETUP_LAST },
+ { WSMOUSECFG_DX_SCALE, WSMOUSECFG__FILTERS - 1 },
+ { WSMOUSECFG_LOG_INPUT, WSMOUSECFG__DEBUG - 1 },
+ { WSMOUSECFG_DX_MAX, WSMOUSECFG__TPFILTERS - 1 },
+ { WSMOUSECFG_SOFTBUTTONS, WSMOUSECFG__TPFEATURES - 1 },
+ { WSMOUSECFG_LEFT_EDGE, WSMOUSECFG__TPSETUP - 1 },
};
static const int touchpad_types[] = {
3
};
+struct wsmouse_parameters cfg_mtbuttons = {
+ (struct wsmouse_param[]) {
+ { WSMOUSECFG_MTBUTTONS, 0 }, },
+ 1
+};
+
struct wsmouse_parameters cfg_scaling = {
(struct wsmouse_param[]) {
{ WSMOUSECFG_DX_SCALE, 0 },
static int cfg_horiz_res;
static int cfg_vert_res;
-static struct wsmouse_param cfg_buffer[BUFSIZE];
+static struct wsmouse_param cfg_buffer[WSMOUSECFG_MAX];
int
}
if (cfg_touchpad) {
parameters.params = cfg_buffer + BASESIZE;
- parameters.nparams = BUFSIZE - BASESIZE;
+ parameters.nparams = WSMOUSECFG_MAX - BASESIZE;
if (ioctl(dev_fd, WSMOUSEIO_GETPARAMS, ¶meters))
cfg_touchpad = 0;
}
-/* $OpenBSD: mousecfg.h,v 1.4 2019/08/19 21:42:33 bru Exp $ */
+/* $OpenBSD: mousecfg.h,v 1.5 2023/07/02 21:44:04 bru Exp $ */
/*
* Copyright (c) 2017 Ulf Brosziewski
*/
extern struct wsmouse_parameters cfg_tapping;
+extern struct wsmouse_parameters cfg_mtbuttons;
extern struct wsmouse_parameters cfg_scaling;
extern struct wsmouse_parameters cfg_edges;
extern struct wsmouse_parameters cfg_swapsides;
-.\" $OpenBSD: wsmouse.4,v 1.22 2021/03/04 17:03:42 jmc Exp $
+.\" $OpenBSD: wsmouse.4,v 1.23 2023/07/02 21:44:04 bru Exp $
.\" $NetBSD: wsmouse.4,v 1.3 1999/12/06 14:52:08 augustss Exp $
.\"
.\" Copyright (c) 2018 Ulf Brosziewski <bru@openbsd.org>
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: March 4 2021 $
+.Dd $Mdocdate: July 2 2023 $
.Dt WSMOUSE 4
.Os
.Sh NAME
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.mtbuttons
+This feature is supported for some clickpads.
+If enabled, two-finger clicks - with the fingers side by side - generate
+left-button events, and three-finger clicks generate middle-button events.
.It Cm mouse.tp.scaling
The value is a scale coefficient that is applied to the relative
coordinates.
-/* $OpenBSD: aplhidev.c,v 1.11 2023/04/10 15:14:04 tobhe Exp $ */
+/* $OpenBSD: aplhidev.c,v 1.12 2023/07/02 21:44:04 bru Exp $ */
/*
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
* Copyright (c) 2013-2014 joshua stein <jcs@openbsd.org>
/* Use a constant, synaptics-compatible pressure value for now. */
#define DEFAULT_PRESSURE 40
+static struct wsmouse_param aplms_wsmousecfg[] = {
+ { WSMOUSECFG_MTBTN_MAXDIST, 0 }, /* 0: Compute a default value. */
+};
+
struct aplms_softc {
struct device sc_dev;
struct device *sc_wsmousedev;
hw->mt_slots = UBCMTP_MAX_FINGERS;
hw->flags = WSMOUSEHW_MT_TRACKING;
- return wsmouse_configure(sc->sc_wsmousedev, NULL, 0);
+ return wsmouse_configure(sc->sc_wsmousedev,
+ aplms_wsmousecfg, nitems(aplms_wsmousecfg));
}
void
-/* $OpenBSD: ubcmtp.c,v 1.24 2022/10/26 16:07:28 kn Exp $ */
+/* $OpenBSD: ubcmtp.c,v 1.25 2023/07/02 21:44:04 bru Exp $ */
/*
* Copyright (c) 2013-2014, joshua stein <jcs@openbsd.org>
},
};
+static struct wsmouse_param ubcmtp_wsmousecfg[] = {
+ { WSMOUSECFG_MTBTN_MAXDIST, 0 }, /* 0: Compute a default value. */
+};
+
struct ubcmtp_softc {
struct device sc_dev; /* base device */
hw->mt_slots = UBCMTP_MAX_FINGERS;
hw->flags = WSMOUSEHW_MT_TRACKING;
- return wsmouse_configure(sc->sc_wsmousedev, NULL, 0);
+ return wsmouse_configure(sc->sc_wsmousedev,
+ ubcmtp_wsmousecfg, nitems(ubcmtp_wsmousecfg));
}
int
-/* $OpenBSD: wsconsio.h,v 1.99 2023/04/20 19:28:31 jcs Exp $ */
+/* $OpenBSD: wsconsio.h,v 1.100 2023/07/02 21:44:04 bru Exp $ */
/* $NetBSD: wsconsio.h,v 1.74 2005/04/28 07:15:44 martin Exp $ */
/*
* WSMOUSEIO_SETPARAMS calls. Arbitrary subsets can be passed, provided
* that all keys are valid and that the number of key/value pairs doesn't
* exceed WSMOUSECFG_MAX.
+ *
+ * The keys are divided into various groups, which end with marker entries
+ * of the form WSMOUSECFG__*.
*/
enum wsmousecfg {
/*
WSMOUSECFG_REVERSE_SCROLLING,
/* reverse scroll directions */
+ WSMOUSECFG__FILTERS,
+
/*
* Coordinate handling, applying only in WSMOUSE_COMPAT mode.
*/
ture is not supported anymore. */
WSMOUSECFG_SMOOTHING, /* smoothing factor (0-7) */
+ WSMOUSECFG__TPFILTERS,
+
/*
* Touchpad features
*/
WSMOUSECFG_SWAPSIDES, /* invert soft-button/scroll areas */
WSMOUSECFG_DISABLE, /* disable all output except for
clicks in the top-button area */
+ WSMOUSECFG_MTBUTTONS, /* multi-touch buttons */
+
+ WSMOUSECFG__TPFEATURES,
/*
* Touchpad options
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 */
+ WSMOUSECFG_MTBTN_MAXDIST, /* MTBUTTONS: distance limit for
+ two-finger clicks */
+
+ WSMOUSECFG__TPSETUP,
/*
* Enable/Disable debug output.
*/
WSMOUSECFG_LOG_INPUT = 256,
WSMOUSECFG_LOG_EVENTS,
+
+ WSMOUSECFG__DEBUG,
};
-#define WSMOUSECFG_MAX 41 /* max size of param array per ioctl */
+
+#define WSMOUSECFG_MAX ((WSMOUSECFG__FILTERS - WSMOUSECFG_DX_SCALE) \
+ + (WSMOUSECFG__TPFILTERS - WSMOUSECFG_DX_MAX) \
+ + (WSMOUSECFG__TPFEATURES - WSMOUSECFG_SOFTBUTTONS) \
+ + (WSMOUSECFG__TPSETUP - WSMOUSECFG_LEFT_EDGE) \
+ + (WSMOUSECFG__DEBUG - WSMOUSECFG_LOG_INPUT))
struct wsmouse_param {
enum wsmousecfg key;
-/* $OpenBSD: wstpad.c,v 1.31 2022/06/09 22:17:18 bru Exp $ */
+/* $OpenBSD: wstpad.c,v 1.32 2023/07/02 21:44:04 bru Exp $ */
/*
* Copyright (c) 2015, 2016 Ulf Brosziewski
#define WSTPAD_HORIZSCROLL (1 << 5)
#define WSTPAD_SWAPSIDES (1 << 6)
#define WSTPAD_DISABLE (1 << 7)
+#define WSTPAD_MTBUTTONS (1 << 8)
#define WSTPAD_MT (1 << 31)
/* two-finger contacts */
int f2pressure;
int f2width;
+ /* MTBUTTONS: distance limit for two-finger clicks */
+ int mtbtn_maxdist;
} params;
/* handler state and configuration: */
return (btn != PRIMARYBTN ? btn : 0);
}
+int
+wstpad_mtbtn_contacts(struct wsmouseinput *input)
+{
+ struct wstpad *tp = input->tp;
+ struct tpad_touch *t;
+ int dx, dy, dist, limit;
+
+ if (tp->ignore != 0)
+ return (tp->contacts - 1);
+
+ if (tp->contacts == 2 && (t = get_2nd_touch(input)) != NULL) {
+ dx = abs(t->x - tp->t->x) << 12;
+ dy = abs(t->y - tp->t->y) * tp->ratio;
+ dist = (dx >= dy ? dx + 3 * dy / 8 : dy + 3 * dx / 8);
+ limit = tp->params.mtbtn_maxdist << 12;
+ if (input->mt.ptr_mask != 0)
+ limit = limit * 2 / 3;
+ if (dist > limit)
+ return (1);
+ }
+ return (tp->contacts);
+}
+
+u_int
+wstpad_get_mtbtn(struct wsmouseinput *input)
+{
+ int contacts = wstpad_mtbtn_contacts(input);
+ return (contacts == 2 ? RIGHTBTN : (contacts == 3 ? MIDDLEBTN : 0));
+}
+
+
void
wstpad_softbuttons(struct wsmouseinput *input, u_int *cmds, int hdlr)
{
}
if (tp->softbutton == 0 && PRIMARYBTN_CLICKED(tp)) {
- tp->softbutton = wstpad_get_sbtn(input, top);
+ tp->softbutton = ((tp->features & WSTPAD_MTBUTTONS)
+ ? wstpad_get_mtbtn(input) : wstpad_get_sbtn(input, top));
if (tp->softbutton)
*cmds |= 1 << SOFTBUTTON_DOWN;
}
tp->scroll.hdist = 4 * h_unit;
tp->scroll.vdist = 4 * v_unit;
tp->tap.maxdist = 4 * h_unit;
+
+ if (IS_MT(tp) && h_res > 1 && v_res > 1 &&
+ input->hw.hw_type == WSMOUSEHW_CLICKPAD &&
+ (width + h_res / 2) / h_res > 100 &&
+ (height + v_res / 2) / v_res > 60) {
+ tp->params.mtbtn_maxdist = h_res * 35;
+ } else {
+ tp->params.mtbtn_maxdist = -1; /* not available */
+ }
}
/* A touch with a flag set in this mask does not move the pointer. */
tp->edge.center_left = tp->edge.center - offset;
tp->edge.center_right = tp->edge.center + offset;
+ /*
+ * Make the MTBUTTONS configuration consistent. A non-negative 'maxdist'
+ * value makes the feature visible in wsconsctl. 0-values are replaced
+ * by a default (one fourth of the length of the touchpad diagonal).
+ */
+ if (tp->params.mtbtn_maxdist < 0) {
+ tp->features &= ~WSTPAD_MTBUTTONS;
+ } else if (tp->params.mtbtn_maxdist == 0) {
+ diag = isqrt(width * width + height * height);
+ tp->params.mtbtn_maxdist = diag / 4;
+ }
+
tp->handlers = 0;
- if (tp->features & WSTPAD_SOFTBUTTONS)
+ if (tp->features & (WSTPAD_SOFTBUTTONS | WSTPAD_MTBUTTONS))
tp->handlers |= 1 << SOFTBUTTON_HDLR;
if (tp->features & WSTPAD_TOPBUTTONS)
tp->handlers |= 1 << TOPBUTTON_HDLR;
-
if (tp->features & WSTPAD_TWOFINGERSCROLL)
tp->handlers |= 1 << F2SCROLL_HDLR;
else if (tp->features & WSTPAD_EDGESCROLL)
return (EINVAL);
switch (key) {
- case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_DISABLE:
+ case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_MTBUTTONS:
switch (key) {
case WSMOUSECFG_SOFTBUTTONS:
flag = WSTPAD_SOFTBUTTONS;
case WSMOUSECFG_DISABLE:
flag = WSTPAD_DISABLE;
break;
+ case WSMOUSECFG_MTBUTTONS:
+ flag = WSTPAD_MTBUTTONS;
+ break;
}
if (val)
tp->features |= flag;
case WSMOUSECFG_TAP_THREE_BTNMAP:
tp->tap.btnmap[2] = BTNMASK(val);
break;
+ case WSMOUSECFG_MTBTN_MAXDIST:
+ if (IS_MT(tp))
+ tp->params.mtbtn_maxdist = val;
+ break;
default:
return (ENOTSUP);
}
return (EINVAL);
switch (key) {
- case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_DISABLE:
+ case WSMOUSECFG_SOFTBUTTONS ... WSMOUSECFG_MTBUTTONS:
switch (key) {
case WSMOUSECFG_SOFTBUTTONS:
flag = WSTPAD_SOFTBUTTONS;
case WSMOUSECFG_DISABLE:
flag = WSTPAD_DISABLE;
break;
+ case WSMOUSECFG_MTBUTTONS:
+ flag = WSTPAD_MTBUTTONS;
+ break;
}
*pval = !!(tp->features & flag);
break;
case WSMOUSECFG_TAP_THREE_BTNMAP:
*pval = ffs(tp->tap.btnmap[2]);
break;
+ case WSMOUSECFG_MTBTN_MAXDIST:
+ *pval = tp->params.mtbtn_maxdist;
+ break;
default:
return (ENOTSUP);
}