shithub: mousetrap

Download patch

ref: 11d352c22055fe42bfd77e044c2590bf1cb9a44f
author: kvik <[email protected]>
date: Thu May 7 11:59:30 EDT 2020

Begin the history

--- /dev/null
+++ b/README
@@ -1,0 +1,39 @@
+# mousetrap(1) — filter for mouse events
+
+`mousetrap(1)` is designed to be interposed between a `nusb/kb(4)` mouse
+driver and the mouse event destination `/dev/mousein`, which provides an
+opportunity to intercept the "raw" mouse events and transform them
+before delivery to the rest of the system.
+
+Example transformations include remapping and hooking up arbitrary
+actions to buttons, which is mainly useful for devices with more buttons
+than the *Plan 9* recognizes. Yet another example might be filtering the
+pointer movement of overly sensitive devices.
+
+If you plan on using this you are expected to modify the source code to
+suit your devices and needs.  Some example mappings are provided to
+help with this.
+
+## Usage
+
+`mousetrap(1)` can be installed into place, prior to running `nusb/kb(4)`
+using the `pipefile(1)` utility as follows:
+
+	pipefile -r 'mousetrap -m elecom' /dev/mousein
+	nusb/kb 9
+
+## TODO
+
+In the (near?) future `filterfs(4)` of some designation should be
+replace `pipefile(1)` as a more Plan9esque filtering solution.  Sigrid
+of 9front works on this: https://git.sr.ht/~ft/filterfs
+
+Figure out a satisfactory way to integrate this kind of device filtering
+with the *9front* boot mechanism.  Currently the `/sys/src/9/boot/nusbrc`
+has to be modified as per above and then a kernel has to be recompiled
+and installed for it to take effect.  We agree this kinds of sucks.
+
+A temporary workaround, if you can get away with it, is `kill(1)`ing
+the `nusb/kb` that got assigned to your device at boot and restarting
+it manually. How to do this one is left as an exercise for the brave
+reader. HINT: `/dev/usbevent`.
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+TARG=mousetrap
+OFILES=$TARG.$O
+BIN=$home/bin/$objtype
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/mousetrap.c
@@ -1,0 +1,138 @@
+#include <u.h>
+#include <libc.h>
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-m map]\n", argv0);
+	exits("usage");
+}
+
+enum {
+	Left = 0x01, Mid = 0x02, Right = 0x04,
+	Scrld = 0x08, Scrlu = 0x10,
+	Fwd = 0x20, Bwd = 0x40,
+	Fn1 = 0x80, Fn2 = 0x100, Fn3 = 0x200,
+};
+
+typedef struct Butt Butt;
+struct Butt {
+	int raw; int cooked;
+	int down;
+	void (*action)(void);
+};
+
+Butt identity[] = {
+	{Left, Left, 0, nil},
+	{Mid, Mid, 0, nil},
+	{Right, Right, 0, nil},
+	{Scrld, Scrld, 0, nil},
+	{Scrlu, Scrlu, 0, nil},
+	{-1, -1, -1, nil},
+};
+
+Butt huge[] = {
+	{Left, Left, 0, nil},
+	{Mid, Mid, 0, nil},
+	{Right, Mid, 0, nil},
+	{Scrld, Scrld, 0, nil},
+	{Scrlu, Scrlu, 0, nil},
+	{Fwd, Mid, 0, nil},
+	{Bwd, Left, 0, nil},
+	{Fn1, Mid, 0, nil},
+	{Fn2, Right, 0, nil},
+	{Fn3, Right, 0, nil},
+	{-1, -1, -1, nil},
+};
+
+Butt contour[] = {
+	{Left, Left, 0, nil},
+	{Mid, Mid, 0, nil},
+	{Right, Right, 0, nil},
+	{Scrld, Scrld, 0, nil},
+	{Scrlu, Scrlu, 0, nil},
+	{Fwd, Scrld, 0, nil},
+	{Bwd, Scrlu, 0, nil},
+	{-1, -1, -1, nil},
+};
+
+int
+parsein(int *x, int *y, int *b)
+{
+	int nr;
+	char buf[1+12+12+12+1];
+	char *p;
+	
+	if((nr = read(0, buf, sizeof buf)) < 0)
+		sysfatal("read: %r");
+	if(nr == 0)
+		return 0;
+	buf[nr] = 0;
+	
+	*x = strtol(buf+1, &p, 10);
+	if(p == nil)
+		sysfatal("x not a num");
+
+	*y = strtol(p, &p, 10);
+	if(p == nil)
+		sysfatal("y not a num");
+
+	*b = strtol(p, &p, 10);
+	if(p == nil)
+		sysfatal("b not a num");
+	
+	return nr;
+}
+
+static int
+buttonmap(Butt *m, int b)
+{
+	int r;
+	
+	for(r = 0; m->raw != -1; m++){
+		if(m->raw & b){
+			if(m->action != nil && m->down == 0)
+				m->action();
+			r |= m->cooked;
+			m->down = 1;
+		}else
+			m->down = 0;
+	}
+	return r;
+}
+
+void
+main(int argc, char **argv)
+{
+	int x, y, b;
+	char *mapn;
+	Butt *map;
+
+	mapn = "default";
+	ARGBEGIN{
+	case 'm':
+		mapn = EARGF(usage());
+		break;
+	default:
+		usage();
+	}ARGEND;
+
+	map = identity;
+	if(strncmp(mapn, "elecom", 6) == 0
+	|| strncmp(mapn, "huge", 4) == 0)
+		map = huge;
+	else if(strncmp(mapn, "contour", 7) == 0)
+		map = contour;
+	
+	x = y = b = 0;
+	for(;;){
+		if(parsein(&x, &y, &b) == 0)
+			break;
+		// x = scale(s, x);
+		// y = scale(s, y);
+		b = buttonmap(map, b);
+
+		fprint(1, "%s%11d %11d %11d", "m", x, y, b);
+	}
+	exits(nil);
+}