diff bed7f3f1a31946d417822613d01094ace514c73f uncommitted --- a//sys/src/cmd/ktrans/main.c +++ b//sys/src/cmd/ktrans/main.c @@ -497,7 +497,7 @@ threadsetname("keytrans"); while(recv(input, &m) != -1){ - if(m.code == 'r'){ + if(m.code == 'z'){ emitutf(dictch, " ", 1); resetstr(&line, nil); continue; @@ -609,7 +609,7 @@ p++; switch(msg.code){ case 'c': case 'k': case 'K': - case 'r': + case 'z': break; default: goto Drop; @@ -684,6 +684,8 @@ default: usage(); } + if(write(kbdout, "z", 2) < 2) + sysfatal("failed to enable focus watch: %r"); memset(backspace, '\b', sizeof backspace-1); backspace[sizeof backspace-1] = '\0'; --- a//sys/src/cmd/rio/dat.h +++ b//sys/src/cmd/rio/dat.h @@ -318,11 +318,14 @@ enum{ Tapon = 'b', Tapoff = 'e', + Tapwatch = 'z', }; -Channel *ctltap; /* on/off messages */ +Channel *ctltap; /* open/close */ +Channel *resptap; /* open/close err */ 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 */ + Window *input; QLock all; /* BUG */ Filsys *filsys; --- a//sys/src/cmd/rio/rio.c +++ b//sys/src/cmd/rio/rio.c @@ -199,7 +199,8 @@ totap = chancreate(sizeof(char*), 32); fromtap = chancreate(sizeof(char*), 32); wintap = chancreate(sizeof(Window*), 0); - ctltap = chancreate(sizeof(Window*), 0); + ctltap = chancreate(sizeof(char*), 0); + resptap = chancreate(sizeof(char*), 0); proccreate(keyboardtap, nil, STACK); wscreen = allocscreen(screen, background, 0); @@ -350,17 +351,53 @@ write(window[i]->notefd, "hangup", 6); } +static int tapseats[] = { [OREAD] Tapoff, [OWRITE] Tapoff }; + +char* +tapctlmsg(char *msg) +{ + int perm; + + perm = msg[1]; + switch(msg[0]){ + case Tapwatch: + if(tapseats[OREAD] == Tapoff) + return "no active reader"; + tapseats[OREAD] = Tapwatch; + break; + 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 *watched; Window *w, *cur; - int mode; - enum { Awin, Actl, Afrom, Adev, Ato, Ainp, NALT }; - enum { Mnorm, Mtap }; - threadsetname("keyboardtap"); - + threadsetname("keyboardtap"); + enum { Awin, Actl, Afrom, Adev, Ato, Ainp, Awatch, NALT }; static Alt alts[NALT+1]; /* ctl */ alts[Awin].c = wintap; @@ -383,10 +420,13 @@ alts[Ainp].c = nil; alts[Ainp].v = &s; alts[Ainp].op = CHANNOP; + alts[Awatch].c = totap; + alts[Awatch].v = &watched; + alts[Awatch].op = CHANNOP; alts[NALT].op = CHANEND; cur = nil; - mode = Mnorm; + watched = nil; for(;;) switch(alt(alts)){ case Awin: @@ -393,20 +433,18 @@ cur = w; if(cur != nil){ alts[Ainp].c = cur->ck; - break; + if(tapseats[OREAD] != Tapwatch) + break; + if(alts[Awatch].op == CHANSND) + free(watched); + watched = smprint("z%d", cur->id); + alts[Awatch].op = CHANSND; } if(alts[Ainp].op != CHANNOP || alts[Ato].op != CHANNOP) free(s); goto Reset; case Actl: - switch(*ctl){ - case Tapon: - mode = Mtap; - break; - case Tapoff: - mode = Mnorm; - break; - } + sendp(resptap, tapctlmsg(ctl)); free(ctl); break; case Afrom: @@ -420,16 +458,19 @@ alts[Ainp].op = CHANSND; break; case Adev: - if(mode == Mnorm && cur == nil){ + if(tapseats[OWRITE] == Tapoff && cur == nil){ free(s); break; } alts[Afrom].op = CHANNOP; alts[Adev].op = CHANNOP; - if(mode == Mnorm) + if(tapseats[OWRITE] == Tapoff) alts[Ainp].op = CHANSND; else alts[Ato].op = CHANSND; + break; + case Awatch: + alts[Awatch].op = CHANNOP; break; case Ainp: if(*s == 'k' || *s == 'K') --- a//sys/src/cmd/rio/xfid.c +++ b//sys/src/cmd/rio/xfid.c @@ -247,6 +247,7 @@ { Fcall t; Window *w; + char *s; w = x->f->w; if(w != nil && w->deleted){ @@ -312,8 +313,12 @@ } break; case Qtap: - chanprint(ctltap, "%c", Tapon); - break; + chanprint(ctltap, "%c%c", Tapon, x->mode); + s = recvp(resptap); + if(s == nil) + break; + filsysrespond(x->fs, x, &t, s); + return; } t.qid = x->f->qid; t.iounit = messagesize-IOHDRSZ; @@ -369,7 +374,8 @@ w->wctlopen = FALSE; break; case Qtap: - chanprint(ctltap, "%c", Tapoff); + chanprint(ctltap, "%c%c", Tapoff, x->f->mode); + recvp(resptap); break; } if(w) @@ -382,7 +388,7 @@ { Fcall fc; int cnt, qid, nb, nr; - char err[ERRMAX], *p, *e; + char err[ERRMAX], *p, *e, *s; Point pt; Window *w; Rune *r; @@ -581,12 +587,22 @@ } e = x->data + cnt; for(p = x->data; p < e; p += strlen(p)+1){ - if(*p == '\0'){ + switch(*p){ + case '\0': fc.count = p - x->data; filsysrespond(x->fs, x, &fc, "null message type"); return; + case Tapwatch: + chanprint(ctltap, "%s", p); + s = recvp(resptap); + if(s == nil) + break; + filsysrespond(x->fs, x, &fc, s); + return; + default: + chanprint(fromtap, "%s", p); + break; } - chanprint(fromtap, "%s", p); } break;