ref: ed2124f31c1951c787469a9b140733c8cd024984
parent: 224c03c17e5c664b1b5b8417d1940301d9fccfd5
author: aap <[email protected]>
date: Wed Feb 21 05:30:08 EST 2024
implemented new kbdtap
--- a/fs.c
+++ b/fs.c
@@ -340,6 +340,7 @@
fsopen(Req *r)
{
Window *w;
+ int rd, wr;
w = XF(r->fid)->w;
@@ -354,6 +355,8 @@
if(QFILE(r->fid->qid.path) != Qtext)
r->ifcall.mode &= (OREAD|OWRITE|ORDWR);
+ rd = r->ifcall.mode==ORDWR || r->ifcall.mode==OREAD;
+ wr = r->ifcall.mode==ORDWR || r->ifcall.mode==OWRITE;
switch(QFILE(r->fid->qid.path)){
case Qtext:
if(r->ifcall.mode & OTRUNC)
@@ -361,7 +364,7 @@
break;
case Qsnarf:
- if(r->ifcall.mode==ORDWR || r->ifcall.mode==OWRITE)
+ if(wr)
ntsnarf = 0;
break;
@@ -391,7 +394,7 @@
break;
case Qwctl:
- if(w && (r->ifcall.mode==ORDWR || r->ifcall.mode==OREAD)){
+ if(wr && rd){
/* can only have one reader of wctl */
if(w->wctlopen){
respond(r, Einuse);
@@ -404,9 +407,19 @@
break;
case Qtap:
- chanprint(ctltap, "%c%c", Tapon, r->ifcall.mode);
- respond(r, recvp(resptap));
- return;
+ if(rd && totap || wr && fromtap){
+ respond(r, Einuse);
+ return;
+ }
+ if(rd){
+ totap = chancreate(sizeof(Channel**), 0);
+ sendp(opentap, totap);
+ }
+ if(wr){
+ fromtap = chancreate(sizeof(char*), 32);
+ sendp(opentap, fromtap);
+ }
+ break;
}
respond(r, nil);
@@ -418,6 +431,7 @@
Xfid *xf;
Window *w;
Text *x;
+ int rd, wr;
xf = XF(fid);
if(xf == nil)
@@ -425,10 +439,12 @@
w = xf->w;
x = &w->text;
+ rd = fid->omode==ORDWR || fid->omode==OREAD;
+ wr = fid->omode==ORDWR || fid->omode==OWRITE;
switch(QFILE(fid->qid.path)){
/* replace snarf buffer when /dev/snarf is closed */
case Qsnarf:
- if(fid->omode==ORDWR || fid->omode==OWRITE){
+ if(wr){
setsnarf(tsnarf, ntsnarf);
ntsnarf = 0;
}
@@ -462,13 +478,15 @@
break;
case Qwctl:
- if(w && (fid->omode==ORDWR || fid->omode==OREAD))
+ if(w && rd)
w->wctlopen = FALSE;
break;
case Qtap:
- chanprint(ctltap, "%c%c", Tapoff, fid->omode);
- recvp(resptap);
+ if(wr && fromtap)
+ sendp(closetap, fromtap);
+ if(rd && totap)
+ sendp(closetap, totap);
break;
}
@@ -820,8 +838,8 @@
r->ofcall.count = p - data;
respond(r, "null message type");
return;
- case Tapfocus:
- /* cleanup our own pollution */
+ case 'z':
+ /* ignore context change */
break;
default:
chanprint(fromtap, "%s", p);
--- a/inc.h
+++ b/inc.h
@@ -165,8 +165,8 @@
bool full; /* filled the queue; no more recording until client comes back */
};
-typedef struct Kbdqueue Kbdqueue;
-struct Kbdqueue
+typedef struct Queue Queue;
+struct Queue
{
char *q[32];
int ri;
@@ -173,6 +173,9 @@
int wi;
bool full;
};
+int qadd(Queue *q, char *data);
+char *qget(Queue *q);
+int qempty(Queue *q);
enum
{
@@ -223,7 +226,7 @@
Cursor cursor;
Channel *kbd;
- Kbdqueue kq;
+ Queue kq;
bool consctlopen;
bool kbdopen;
@@ -288,16 +291,11 @@
Wctlcmd parsewctl(char *s, Rectangle r);
char *writewctl(Window *w, char *data);
-enum{
- Tapon = 'b',
- Tapoff = 'e',
- Tapfocus = 'z',
-};
-extern Channel *ctltap; /* open/close */
-extern Channel *resptap; /* open/close err */
-extern Channel *fromtap; /* input from kbd tap program to window */
+
+extern Channel *opentap; /* open fromtap or totap */
+extern Channel *closetap; /* close fromtap or totap */
+extern Channel *fromtap; /* input from kbd tap program to window */
extern Channel *totap; /* our keyboard input to tap program */
-extern Channel *wintap; /* tell the tapthread which Window to send to */
extern Srv fsys;
--- a/main.c
+++ b/main.c
@@ -655,150 +655,112 @@
* from tap --------+----> window
*/
-Channel *ctltap; /* open/close */
-Channel *resptap; /* open/close err */
-Channel *fromtap; /* input from kbd tap program to window */
+Channel *opentap; /* open fromtap or totap */
+Channel *closetap; /* close fromtap or totap */
+Channel *fromtap; /* input from kbd tap program to window */
Channel *totap; /* our keyboard input to tap program */
-Channel *wintap; /* tell the tapthread which Window to send to */
-static int tapseats[] = { [OREAD] Tapoff, [OWRITE] Tapoff };
-
-char*
-tapctlmsg(char *msg)
-{
- int perm;
-
- perm = msg[1];
- switch(msg[0]){
- case Tapoff:
- if(perm == ORDWR)
- tapseats[OREAD] = Tapoff, tapseats[OWRITE] = Tapoff;
- else
- tapseats[perm] = Tapoff;
- break;
- case Tapon:
- switch(perm){
- case ORDWR:
- if(tapseats[OREAD] != Tapoff || tapseats[OWRITE] != Tapoff)
- return "seat taken";
- tapseats[OREAD] = Tapon, tapseats[OWRITE] = Tapon;
- break;
- case OREAD: case OWRITE:
- if(tapseats[perm] != Tapoff)
- return "seat taken";
- tapseats[perm] = Tapon;
- break;
- }
- break;
- }
- return nil;
-}
-
void
keyboardtap(void*)
{
- char *s, *ctl;
- char *e;
- char *watched;
- Channel *fschan;
+ char *s, *z;
+ Channel *fschan, *chan;
int n;
Stringpair pair;
- Window *w, *cur;
+ Window *cur, *prev;
+ Queue tapq;
threadsetname("keyboardtap");
+
fschan = chancreate(sizeof(Stringpair), 0);
- enum { Awin, Actl, Afrom, Adev, Ato, Ainp, Awatch, NALT };
+ enum { Akbd, Afromtap, Atotap, Aopen, Aclose, NALT };
Alt alts[NALT+1] = {
- [Awin] {.c = wintap, .v = &w, .op = CHANRCV},
- [Actl] {.c = ctltap, .v = &ctl, .op = CHANRCV},
- [Afrom] {.c = fromtap, .v = &s, .op = CHANRCV},
- [Adev] {.c = kbctl->c, .v = &s, .op = CHANRCV},
- [Ato] {.c = totap, .v = &fschan, .op = CHANNOP},
- [Ainp] {.c = nil, .v = &s, .op = CHANNOP},
- [Awatch]{.c = totap, .v = &fschan, .op = CHANNOP},
- [NALT] {.op = CHANEND},
+ [Akbd] {.c = kbctl->c, .v = &s, .op = CHANRCV},
+ [Afromtap] {.c = nil, .v = &s, .op = CHANNOP},
+ [Atotap] {.c = nil, .v = &fschan, .op = CHANNOP},
+ [Aopen] {.c = opentap, .v = &chan, .op = CHANRCV},
+ [Aclose] {.c = closetap, .v = &chan, .op = CHANRCV},
+ [NALT] {.op = CHANEND},
};
+ memset(&tapq, 0, sizeof(tapq));
cur = nil;
- watched = nil;
- for(;;)
+ for(;;){
+ if(alts[Atotap].c && !qempty(&tapq))
+ alts[Atotap].op = CHANSND;
+ else
+ alts[Atotap].op = CHANNOP;
switch(alt(alts)){
- case Awin:
- cur = w;
- if(cur != nil){
- alts[Ainp].c = cur->kbd;
- if(tapseats[OREAD] == Tapoff)
- goto Reset;
- if(alts[Awatch].op == CHANSND)
- free(watched);
- watched = smprint("%c%d", Tapfocus, cur->id);
- alts[Awatch].op = CHANSND;
+ case Akbd:
+ /* from keyboard to tap or to window */
+ if(*s == 'k' || *s == 'K')
+ shiftdown = utfrune(s+1, Kshift) != nil;
+ prev = cur;
+ cur = focused;
+ if(totap){
+ if(cur != prev && cur){
+ /* notify tap of focus change */
+ z = smprint("z%d", cur->id);
+ if(!qadd(&tapq, z))
+ free(z);
+ }
+ /* send to tap */
+ if(qadd(&tapq, s))
+ break;
+ /* tap is wedged, send directly instead */
}
- if(alts[Ainp].op != CHANNOP || alts[Ato].op != CHANNOP)
+ if(cur)
+ sendp(cur->kbd, s);
+ else
free(s);
- goto Reset;
- case Actl:
- e = tapctlmsg(ctl);
- sendp(resptap, e);
- if(e != nil || *ctl != Tapoff){
- free(ctl);
- break;
- }
- free(ctl);
- goto Reset;
- case Afrom:
- if(cur == nil){
- free(s);
- break;
- }
- alts[Afrom].op = CHANNOP;
- alts[Adev].op = CHANNOP;
- alts[Ato].op = CHANNOP;
- alts[Ainp].op = CHANSND;
break;
- case Adev:
- if(tapseats[OWRITE] == Tapoff && cur == nil){
- free(s);
- break;
- }
- alts[Afrom].op = CHANNOP;
- alts[Adev].op = CHANNOP;
- if(tapseats[OWRITE] == Tapoff)
- alts[Ainp].op = CHANSND;
+
+ case Afromtap:
+ /* from tap to window */
+ if(cur && cur == focused)
+ sendp(cur->kbd, s);
else
- alts[Ato].op = CHANSND;
+ free(s);
break;
- /* These two do the xreq channel dance
- * ugly... */
- case Ato:
+ case Atotap:
+ /* send queued up messages */
recv(fschan, &pair);
+ s = qget(&tapq);
n = strlen(s)+1;
pair.ns = min(n, pair.ns);
memmove(pair.s, s, pair.ns);
free(s);
send(fschan, &pair);
- goto Reset;
- case Awatch:
- recv(fschan, &pair);
- n = strlen(watched)+1;
- pair.ns = min(n, pair.ns);
- memmove(pair.s, watched, pair.ns);
- free(watched);
- send(fschan, &pair);
- alts[Awatch].op = CHANNOP;
break;
- case Ainp:
- if(*s == 'k' || *s == 'K')
- shiftdown = utfrune(s+1, Kshift) != nil;
- Reset:
- alts[Ainp].op = CHANNOP;
- alts[Ato].op = CHANNOP;
- alts[Afrom].op = CHANRCV;
- alts[Adev].op = CHANRCV;
+ case Aopen:
+ if(chan == fromtap){
+ alts[Afromtap].c = fromtap;
+ alts[Afromtap].op = CHANRCV;
+ }
+ if(chan == totap)
+ alts[Atotap].c = totap;
break;
+
+ case Aclose:
+ if(chan == fromtap){
+ fromtap = nil;
+ alts[Afromtap].c = nil;
+ alts[Afromtap].op = CHANNOP;
+ // TODO: empty chan
+ }
+ if(chan == totap){
+ totap = nil;
+ alts[Atotap].c = nil;
+ alts[Atotap].op = CHANNOP;
+ while(!qempty(&tapq))
+ free(qget(&tapq));
+ }
+ chanfree(chan);
+ break;
}
+ }
}
void
@@ -820,11 +782,8 @@
mctl = initmouse(nil, screen);
if(mctl == nil)
sysfatal("initmouse: %r");
- totap = chancreate(sizeof(Channel**), 0);
- fromtap = chancreate(sizeof(char*), 32);
- wintap = chancreate(sizeof(Window*), 0);
- ctltap = chancreate(sizeof(char*), 0);
- resptap = chancreate(sizeof(char*), 0);
+ opentap = chancreate(sizeof(Channel*), 0);
+ closetap = chancreate(sizeof(Channel*), 0);
servekbd = kbctl->kbdfd >= 0;
snarffd = open("/dev/snarf", OREAD|OCEXEC);
@@ -840,8 +799,7 @@
threadcreate(mthread, nil, mainstacksize);
threadcreate(resthread, nil, mainstacksize);
- /* proc so mouse keeps working if tap program crashes */
- proccreate(keyboardtap, nil, mainstacksize);
+ threadcreate(keyboardtap, nil, mainstacksize);
flushimage(display, 1);
--- a/util.c
+++ b/util.c
@@ -126,3 +126,30 @@
return pair;
}
+int
+qadd(Queue *q, char *data)
+{
+ if(q->full)
+ return 0;
+ q->q[q->wi++] = data;
+ q->wi %= nelem(q->q);
+ q->full = q->wi == q->ri;
+ return 1;
+}
+
+char*
+qget(Queue *q)
+{
+ char *data;
+
+ data = q->q[q->ri++];
+ q->ri %= nelem(q->q);
+ q->full = FALSE;
+ return data;
+}
+
+int
+qempty(Queue *q)
+{
+ return q->ri == q->wi && !q->full;
+}
--- a/wind.c
+++ b/wind.c
@@ -369,7 +369,6 @@
return;
prev = focused;
focused = w;
- sendp(wintap, w);
/* TODO a bit ugly the repetition,
* but this might not stay anyways */
if(prev){
@@ -827,7 +826,7 @@
alts[AConsWrite].op = CHANSND;
else
alts[AConsWrite].op = CHANNOP;
- if(w->kbdopen && (w->kq.ri != w->kq.wi || w->kq.full))
+ if(w->kbdopen && !qempty(&w->kq))
alts[AKbdRead].op = CHANSND;
else
alts[AKbdRead].op = CHANNOP;
@@ -840,17 +839,11 @@
switch(alt(alts)){
case AKbd:
- if(!w->kq.full){
- w->kq.q[w->kq.wi++] = s;
- w->kq.wi %= nelem(w->kq.q);
- w->kq.full = w->kq.wi == w->kq.ri;
- }else
+ if(!qadd(&w->kq, s))
free(s);
if(!w->kbdopen)
- while(w->kq.ri != w->kq.wi || w->kq.full){
- s = w->kq.q[w->kq.ri++];
- w->kq.ri %= nelem(w->kq.q);
- w->kq.full = FALSE;
+ while(!qempty(&w->kq)){
+ s = qget(&w->kq);
if(*s == 'c'){
chartorune(&r, s+1);
if(r)
@@ -863,13 +856,12 @@
case AKbdRead:
recv(fsc, &pair);
nb = 0;
- while(w->kq.ri != w->kq.wi || w->kq.full){
+ while(!qempty(&w->kq)){
s = w->kq.q[w->kq.ri];
i = strlen(s)+1;
if(nb+i > pair.ns)
break;
- w->kq.ri = (w->kq.ri+1) % nelem(w->kq.q);
- w->kq.full = FALSE;
+ qget(&w->kq);
memmove((char*)pair.s + nb, s, i);
free(s);
nb += i;