code: plan9front

Download patch

ref: 8906ad7c15744271d0f6a41ae2f590a8bc31bf21
parent: 4df168d98fb7b73e50d702b70ceffcaddfe8203c
author: Jacob Moody <moody@posixcafe.org>
date: Sun Aug 14 22:59:49 EDT 2022

rio: add /dev/kbdtap

--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -18,6 +18,7 @@
 	Qwindow,
 	Qwsys,		/* directory of window directories */
 	Qwsysdir,		/* window directory, child of wsys */
+	Qtap,
 
 	QMAX,
 };
@@ -40,6 +41,7 @@
 typedef	struct	Wctlmesg Wctlmesg;
 typedef	struct	Window Window;
 typedef	struct	Xfid Xfid;
+typedef struct	Tapmesg Tapmesg;
 
 enum
 {
@@ -117,8 +119,20 @@
 	ulong	lastcounter;	/* serial no. of last mouse event sent to client */
 	int	lastb;	/* last button state we received */
 	uchar	qfull;	/* filled the queue; no more recording until client comes back */	
-};	
+};
 
+enum{
+	Fon = 'b',
+	Foff = 'e',
+	Freset = 'r',
+};
+
+struct Tapmesg
+{
+	char type;
+	char *s;
+};
+
 struct Window
 {
 	Ref;
@@ -313,6 +327,8 @@
 int		snarffd;
 int		gotscreen;
 int		servekbd;
+Channel	*fromtap; 	/* input from kbd tap program to window */
+Channel *totap; 	/* our keyboard input to tap program */
 Window	*input;
 QLock	all;			/* BUG */
 Filsys	*filsys;
--- a/sys/src/cmd/rio/fsys.c
+++ b/sys/src/cmd/rio/fsys.c
@@ -37,6 +37,7 @@
 	{ "wctl",		QTFILE,	Qwctl,		0600 },
 	{ "window",	QTFILE,	Qwindow,		0400 },
 	{ "wsys",		QTDIR,	Qwsys,		0500|DMDIR },
+	{ "kbdtap",	QTFILE,	Qtap,	0660 },
 	{ nil, }
 };
 
@@ -115,6 +116,16 @@
 	return 0;
 }
 
+void
+toggletap(char mode)
+{
+	Tapmesg m;
+
+	m.type = mode;
+	m.s = nil;
+	send(fromtap, &m);
+}
+
 Filsys*
 filsysinit(Channel *cxfidalloc)
 {
@@ -506,7 +517,9 @@
 	}
 	if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
 		goto Deny;
-		
+
+	if(FILE(f->qid) == Qtap)
+		toggletap(Fon);
 	sendp(x->c, xfidopen);
 	return nil;
 
@@ -616,6 +629,8 @@
 	if(f->open){
 		f->busy = FALSE;
 		f->open = FALSE;
+		if(FILE(f->qid) == Qtap)
+			toggletap(Foff);
 		sendp(x->c, xfidclose);
 		return nil;
 	}
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -199,6 +199,9 @@
 	kbdchan = initkbd();
 	if(kbdchan == nil)
 		error("can't find keyboard");
+	totap = chancreate(sizeof(char*), 0);
+	fromtap = chancreate(sizeof(Tapmesg), 0);
+
 	wscreen = allocscreen(screen, background, 0);
 	if(wscreen == nil)
 		error("can't allocate screen");
@@ -340,15 +343,64 @@
 keyboardthread(void*)
 {
 	char *s;
+	Tapmesg m;
+	Channel *out;
+	int mode;
+	enum { Kdev, Ktap, NALT};
+	enum { Mnorm, Mfilt };
 
-	threadsetname("keyboardthread");
+	threadsetname("keyboardthread");	
 
-	while(s = recvp(kbdchan)){
-		if(*s == 'k' || *s == 'K')
-			shiftdown = utfrune(s+1, Kshift) != nil;
-		if(input == nil || sendp(input->ck, s) <= 0)
-			free(s);
-	}
+	static Alt alts[NALT+1];
+	alts[Kdev].c = kbdchan;
+	alts[Kdev].v = &s;
+	alts[Kdev].op = CHANRCV;
+	alts[Ktap].c = fromtap;
+	alts[Ktap].v = &m;
+	alts[Ktap].op = CHANRCV;
+	alts[NALT].op = CHANEND;
+
+	out = nil;
+	mode = Mnorm;
+	for(;;)
+		switch(alt(alts)){
+		case Ktap:
+			switch(m.type){
+			case 'K': case 'k': case 'c':
+				break;
+			case Freset:
+				if(mode != Mfilt)
+					continue;
+				s = smprint("%c", m.type);
+				goto Send;
+			case Foff:
+				mode = Mnorm;
+				continue;
+			case Fon:
+				mode = Mfilt;
+				continue;
+			default:
+				continue;
+			}
+			s = smprint("%c%s", m.type, m.s);
+			out = input == nil ? nil : input->ck;
+			goto Send;
+		case Kdev:
+			switch(mode){
+			case Mnorm:
+				out = input == nil ? nil : input->ck;
+				break;
+			case Mfilt:
+				out = totap;
+				break;
+			}
+		Send:
+			if(*s == 'k' || *s == 'K')
+				shiftdown = utfrune(s+1, Kshift) != nil;
+			if(out == nil || sendp(out, s) <= 0)
+				free(s);
+			break;
+		}
 }
 
 int
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -81,6 +81,7 @@
 wcurrent(Window *w)
 {
 	Channel *c;
+	Tapmesg m;
 
 	if(input == nil){
 		input = w;
@@ -88,6 +89,9 @@
 	}
 	if(w == input)
 		return;
+	m.type = Freset;
+	m.s = nil;
+	send(fromtap, &m);
 	incref(input);
 	c = chancreate(sizeof(Window*), 0);
 	wsendctlmesg(input, Repaint, ZR, c);
--- a/sys/src/cmd/rio/xfid.c
+++ b/sys/src/cmd/rio/xfid.c
@@ -376,6 +376,7 @@
 	Window *w;
 	Rune *r;
 	Conswritemesg cwm;
+	Tapmesg fmsg;
 	Stringpair pair;
 	enum { CWdata, CWgone, CWflush, NCW };
 	Alt alts[NCW+1];
@@ -568,6 +569,16 @@
 		}
 		break;
 
+	case Qtap:
+		if(cnt < 2){
+			filsysrespond(x->fs, x, &fc, "malformed key");
+			return;
+		}
+		fmsg.type = x->data[0];
+		fmsg.s = strdup(x->data+1);
+		send(fromtap, &fmsg);
+		break;
+
 	default:
 		fprint(2, "unknown qid %d in write\n", qid);
 		filsysrespond(x->fs, x, &fc, "unknown qid in write");
@@ -678,6 +689,14 @@
 		recv(c2, &pair);
 		fc.data = pair.s;
 		fc.count = min(cnt, pair.ns);
+		filsysrespond(x->fs, x, &fc, nil);
+		free(t);
+		break;
+
+	case Qtap:
+		recv(totap, &t);
+		fc.data = t;
+		fc.count = strlen(t)+1;
 		filsysrespond(x->fs, x, &fc, nil);
 		free(t);
 		break;