diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-02-06 19:04:15 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-02-06 19:04:15 +0000 |
commit | e982ca2f8d6779b6b103a0d812d61f88f2338294 (patch) | |
tree | 6b4068449f2c5ea93ce8e1a02c4bfd7bc87d07a8 /sys/src/cmd/rio | |
parent | 32acb3ebd8ecb684a4db054febc082b99d5957be (diff) |
rio: refactor the keyboardtap code a bit
run the keyboardtap as a thread instead of a proc
so that we can read input window variable.
This gets rid of the wintap channel.
do focus handling by tracking the last window and
only send context switch when we start typing into
a different window.
have fromtap, totap channels created by open and
use the variable also as the in-use flag.
handle use nbsendp() when sending to the tap
program, as it might be blocked or misbehaving.
if the totap channel is full, we bypass the tap
and send to input again.
handle keyup on focus loss in the window thread instead
(just like the artificial mouseup) it is unrelated to
keyboardtap.
Diffstat (limited to 'sys/src/cmd/rio')
-rw-r--r-- | sys/src/cmd/rio/dat.h | 13 | ||||
-rw-r--r-- | sys/src/cmd/rio/rio.c | 160 | ||||
-rw-r--r-- | sys/src/cmd/rio/wind.c | 15 | ||||
-rw-r--r-- | sys/src/cmd/rio/xfid.c | 34 |
4 files changed, 85 insertions, 137 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h index d9cb1432e..498bccdc9 100644 --- a/sys/src/cmd/rio/dat.h +++ b/sys/src/cmd/rio/dat.h @@ -172,6 +172,7 @@ struct Window uchar deleted; uchar mouseopen; uchar kbdopen; + uchar keyup; uchar winnameread; char *label; char *dir; @@ -315,16 +316,10 @@ int snarffd; int gotscreen; int servekbd; -enum{ - Tapon = 'b', - Tapoff = 'e', - Tapfocus = 'z', -}; -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; /* keyboard output from the tap program */ Channel *totap; /* our keyboard input to tap program */ -Channel *wintap; /* tell the tapthread which Window to send to */ Window *input; QLock all; /* BUG */ diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index 9ed6a0a3d..cb3da90e3 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -196,12 +196,9 @@ threadmain(int argc, char *argv[]) kbdchan = initkbd(); if(kbdchan == nil) error("can't find keyboard"); - totap = chancreate(sizeof(char*), 32); - fromtap = chancreate(sizeof(char*), 32); - wintap = chancreate(sizeof(Window*), 0); - ctltap = chancreate(sizeof(char*), 0); - resptap = chancreate(sizeof(char*), 0); - proccreate(keyboardtap, nil, STACK); + opentap = chancreate(sizeof(Channel*), 0); + closetap = chancreate(sizeof(Channel*), 0); + threadcreate(keyboardtap, nil, STACK); wscreen = allocscreen(screen, background, 0); if(wscreen == nil) @@ -352,132 +349,73 @@ killprocs(void) 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 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; - Window *w, *cur; - static char keys[64]; + Window *cur = nil; + Channel *c; + char *s; - threadsetname("keyboardtap"); - enum { Awin, Actl, Afrom, Adev, Ato, Ainp, Awatch, NALT }; + enum { Akbd, Aopen, Aclose, Awrite, 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 = kbdchan, .v = &s, .op = CHANRCV}, - [Ato] {.c = totap, .v = &s, .op = CHANNOP}, - [Ainp] {.c = nil, .v = &s, .op = CHANNOP}, - [Awatch]{.c = totap, .v = &watched, .op = CHANNOP}, + [Akbd] {.c = kbdchan, .v = &s, .op = CHANRCV}, + [Aopen] {.c = opentap, .v = &c, .op = CHANRCV}, + [Aclose]{.c = closetap, .v = &c, .op = CHANRCV}, + [Awrite]{.c = nil, .v = &s, .op = CHANNOP}, [NALT] {.op = CHANEND}, }; - cur = nil; - watched = nil; - keys[0] = 0; - for(;;) + threadsetname("keyboardtap"); + + for(;;){ switch(alt(alts)){ - case Awin: - cur = w; - if(cur != nil){ - alts[Ainp].c = cur->ck; - if(tapseats[OREAD] != Tapoff){ - if(alts[Awatch].op == CHANSND) - free(watched); - watched = smprint("%c%d", Tapfocus, cur->id); - alts[Awatch].op = CHANSND; + case Akbd: + if(*s == 'k' || *s == 'K') + shiftdown = utfrune(s+1, Kshift) != nil; + if(totap == nil) + goto Bypass; + if(input != nil && input != cur){ /* context change */ + char *z = smprint("z%d", input->id); + if(nbsendp(totap, z) != 1){ + free(z); + goto Bypass; } } - if(alts[Ainp].op != CHANNOP || alts[Ato].op != CHANNOP) - free(s); - if(cur == nil) - goto Reset; - s = smprint("K%s", keys); - alts[Ainp].op = CHANSND; - alts[Ato].op = CHANNOP; + cur = input; + if(nbsendp(totap, s) != 1) + goto Bypass; break; - case Actl: - e = tapctlmsg(ctl); - sendp(resptap, e); - if(e != nil || *ctl != Tapoff){ - free(ctl); - break; + case Aopen: + if(c == fromtap){ + alts[Awrite].c = c; + alts[Awrite].op = CHANRCV; } - free(ctl); - goto Reset; - case Afrom: - if(cur == nil){ + break; + case Aclose: + if(c == fromtap){ + fromtap = nil; + alts[Awrite].c = nil; + alts[Awrite].op = CHANNOP; + } + if(c == totap) + totap = nil; + chanfree(c); + break; + case Awrite: + if(input != cur){ free(s); break; } - alts[Afrom].op = CHANNOP; - alts[Adev].op = CHANNOP; - alts[Ato].op = CHANNOP; - alts[Ainp].op = CHANSND; - break; - case Adev: - if(*s == 'k' || *s == 'K') - strcpy(keys, s+1); - if(tapseats[OWRITE] == Tapoff && cur == nil){ + Bypass: + cur = input; + if(cur == nil){ free(s); break; } - alts[Afrom].op = CHANNOP; - alts[Adev].op = CHANNOP; - 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') - shiftdown = utfrune(s+1, Kshift) != nil; - case Ato: - Reset: - alts[Ainp].op = CHANNOP; - alts[Ato].op = CHANNOP; - alts[Afrom].op = CHANRCV; - alts[Adev].op = CHANRCV; + sendp(cur->ck, s); break; } + } } int diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c index 0bb63c83a..80e00eae7 100644 --- a/sys/src/cmd/rio/wind.c +++ b/sys/src/cmd/rio/wind.c @@ -83,14 +83,12 @@ wcurrent(Window *w) Channel *c; if(input == nil){ - sendp(wintap, w); input = w; return; } if(w == input) return; incref(input); - sendp(wintap, w); c = chancreate(sizeof(Window*), 0); wsendctlmesg(input, Repaint, ZR, c); sendp(c, w); /* send the new input */ @@ -1305,7 +1303,6 @@ wclunk(Window *w) return; w->deleted = TRUE; if(w == input){ - sendp(wintap, nil); input = nil; riosetcursor(nil); } @@ -1384,11 +1381,12 @@ wctlmesg(Window *w, int m, Rectangle r, void *p) Channel *c = p; input = recvp(c); - /* when we lost input, release mouse buttons */ + /* when we lost input, release mouse and keyboard buttons */ if(w->mc.buttons){ w->mc.buttons = 0; w->mouse.counter++; } + w->keyup = w->kbdopen; w->wctlready = 1; sendp(c, w); @@ -1559,9 +1557,9 @@ winctl(void *arg) alts[WWread].op = CHANNOP; alts[WCread].op = CHANNOP; } else { - alts[WKbdread].op = (w->kbdopen && kbdqw != kbdqr) ? + alts[WKbdread].op = w->kbdopen && (kbdqw != kbdqr || w->keyup) ? CHANSND : CHANNOP; - alts[WMouseread].op = (w->mouseopen && w->mouse.counter != w->mouse.lastcounter) ? + alts[WMouseread].op = w->mouseopen && w->mouse.counter != w->mouse.lastcounter ? CHANSND : CHANNOP; alts[WCwrite].op = w->scrolling || w->mouseopen || (w->qh <= w->org+w->nchars) ? CHANSND : CHANNOP; @@ -1615,6 +1613,11 @@ winctl(void *arg) nb += i; kbdqr++; } + if(w->keyup && nb+2 <= pair.ns){ + w->keyup = 0; + memmove((char*)pair.s + nb, "K", 2); + nb += 2; + } pair.ns = nb; send(crm.c2, &pair); continue; diff --git a/sys/src/cmd/rio/xfid.c b/sys/src/cmd/rio/xfid.c index 7afe02353..adee6e2bf 100644 --- a/sys/src/cmd/rio/xfid.c +++ b/sys/src/cmd/rio/xfid.c @@ -247,7 +247,6 @@ xfidopen(Xfid *x) { Fcall t; Window *w; - char *s; w = x->f->w; if(w != nil && w->deleted){ @@ -313,12 +312,23 @@ xfidopen(Xfid *x) } break; case Qtap: - chanprint(ctltap, "%c%c", Tapon, x->mode); - s = recvp(resptap); - if(s == nil) - break; - filsysrespond(x->fs, x, &t, s); - return; + if((x->mode == OWRITE || x->mode == ORDWR) && fromtap != nil){ + filsysrespond(x->fs, x, &t, Einuse); + return; + } + if(x->mode == OREAD || x->mode == ORDWR){ + if(totap != nil){ + filsysrespond(x->fs, x, &t, Einuse); + return; + } + totap = chancreate(sizeof(char*), 32); + sendp(opentap, totap); + } + if(x->mode == OWRITE || x->mode == ORDWR){ + fromtap = chancreate(sizeof(char*), 32); + sendp(opentap, fromtap); + } + break; } t.qid = x->f->qid; t.iounit = messagesize-IOHDRSZ; @@ -374,8 +384,10 @@ xfidclose(Xfid *x) w->wctlopen = FALSE; break; case Qtap: - chanprint(ctltap, "%c%c", Tapoff, x->f->mode); - recvp(resptap); + if(fromtap != nil && (x->f->mode == OWRITE || x->f->mode == ORDWR)) + sendp(closetap, fromtap); + if(totap != nil && (x->f->mode == OREAD || x->f->mode == ORDWR)) + sendp(closetap, totap); break; } if(w) @@ -592,8 +604,7 @@ xfidwrite(Xfid *x) fc.count = p - x->data; filsysrespond(x->fs, x, &fc, "null message type"); return; - case Tapfocus: - /* cleanup our own pollution */ + case 'z': /* ignore context change */ break; default: chanprint(fromtap, "%s", p); @@ -727,6 +738,7 @@ xfidread(Xfid *x) break; case Qtap: + assert(totap != nil); alts[Adata].c = totap; alts[Adata].v = &t; alts[Adata].op = CHANRCV; |