code: plan9front

Download patch

ref: 705885553cced0300ed72722b20bad405af2bdce
parent: ba66d8f69edd895682f2661524a1d07612cb9ba8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jan 1 13:37:08 EST 2023

mouse: Make /dev/mousein readable to get mouse status without blocking

There is currently no way to get the current mouse position
and button states without blocking.

--- a/sys/man/3/mouse
+++ b/sys/man/3/mouse
@@ -56,23 +56,30 @@
 .B mousein
 file are processed as if they were generated by the
 mouse hardware itself,
-as extra mouse events to be processed and passed back via
-the
+as extra mouse events to be processed and passed back via the
 .B mouse
 file.
+Reading the
+.B mousein
+file returns the current mouse status without waiting.
 The
 .B mousein
 file, which may be opened
-only by the host owner, is intended for controlling devices, such as USB mice,
+only by the host owner, is intended for controlling devices,
+such as USB mice and tablets,
 that are managed by user-level software.
 Each event should consist of
 the letter
 .B m
-followed by delta
-.IR x ,
-delta
-.IR y ,
+(for relative delta coordinates)
+or
+.B A
+(for absolute screen coordinates)
+followed by the
+.I x
 and
+.I y
+coordinates and
 .IR buttons
 as space-separated decimal numbers.
 .PP
--- a/sys/src/9/port/devmouse.c
+++ b/sys/src/9/port/devmouse.c
@@ -88,7 +88,7 @@
 	".",	{Qdir, 0, QTDIR},	0,			DMDIR|0555,
 	"cursor",	{Qcursor},	0,			0666,
 	"mouse",	{Qmouse},	0,			0666,
-	"mousein",	{Qmousein},	0,			0220,
+	"mousein",	{Qmousein},	0,			0660,
 	"mousectl",	{Qmousectl},	0,			0220,
 };
 
@@ -207,7 +207,9 @@
 		return;
 	switch((ulong)c->qid.path){
 	case Qmousein:
+		ilock(&mouse);
 		mouse.inbuttons &= ~((Mousestate*)c->aux)->buttons;
+		iunlock(&mouse);
 		free(c->aux);	/* Mousestate */
 		c->aux = nil;
 		return;
@@ -232,6 +234,7 @@
 	Cursor curs;
 	Mousestate m;
 	int b;
+	char t;
 
 	p = va;
 	switch((ulong)c->qid.path){
@@ -272,23 +275,39 @@
 			m = mouse.Mousestate;
 		iunlock(&mouse);
 
+		if(0){
+	case Qmousein:
+			if(offset != 0)
+				return 0;
+
+			ilock(&mouse);
+			m = mouse.Mousestate;
+			iunlock(&mouse);
+
+			t = 'm';
+		} else {
+			/* Qmouse */
+			mouse.lastcounter = m.counter;
+			if(mouse.resize){
+				mouse.resize = 0;
+				t = 'r';
+			} else {
+				t = 'm';
+			}
+		}
+
 		b = buttonmap[m.buttons&7];
 		/* put buttons 4 and 5 back in */
 		b |= m.buttons & (3<<3);
+
 		if (scrollswap)
 			if (b == 8)
 				b = 16;
 			else if (b == 16)
 				b = 8;
-		sprint(buf, "m%11d %11d %11d %11ld ",
-			m.xy.x, m.xy.y, b, m.msec);
 
-		mouse.lastcounter = m.counter;
-		if(mouse.resize){
-			mouse.resize = 0;
-			buf[0] = 'r';
-		}
-
+		snprint(buf, sizeof(buf), "%c%11d %11d %11d %11ld ",
+			t, m.xy.x, m.xy.y, b, m.msec);
 		if(n > 1+4*12)
 			n = 1+4*12;
 		memmove(va, buf, n);
@@ -446,8 +465,11 @@
 		m->msec = msec;
 		b ^= m->buttons;
 		m->buttons ^= b;
+
+		ilock(&mouse);
 		mouse.inbuttons = (m->buttons & b) | (mouse.inbuttons & ~b);
 		b = mouse.buttons & ~b;
+		iunlock(&mouse);
 
 		/* include wheel */
 		b &= ~(8|16);