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;