summaryrefslogtreecommitdiff
path: root/sys/src/cmd/bitsy/keyboard.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/bitsy/keyboard.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/bitsy/keyboard.c')
-rwxr-xr-xsys/src/cmd/bitsy/keyboard.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/sys/src/cmd/bitsy/keyboard.c b/sys/src/cmd/bitsy/keyboard.c
new file mode 100755
index 000000000..0972bcd75
--- /dev/null
+++ b/sys/src/cmd/bitsy/keyboard.c
@@ -0,0 +1,437 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <control.h>
+#include <scribble.h>
+
+int debug = 0;
+typedef struct Win Win;
+struct Win {
+ int n;
+ int dirty;
+ char *label;
+ Control *button;
+};
+
+Win *win;
+int nwin;
+int mwin;
+int onwin;
+int rows, cols;
+int kbdonly;
+int scribbleleft;
+int winshow;
+
+Channel *kc;
+Channel *ec;
+Channel *tc;
+Rectangle r, rk, rs, rw;
+Font *keyfont, *keyctlfont;
+
+enum{
+ Back,
+ Shade,
+ Light,
+ Mask,
+ Ncol
+};
+
+enum {
+ kbdheight = 2 + 5*13,
+};
+
+enum {
+ Keyback = 0xeeee9eff,
+ Keyshade = 0xaaaa55ff,
+ Keylight = DWhite,
+ Keymask = 0x0C0C0C0C,
+};
+
+Image *colors[Ncol];
+
+Control *kbd;
+Control *scrib;
+Control *boxbox;
+Controlset *cs;
+
+int ctldeletequits = 1;
+int wctl;
+
+int
+hidden(void)
+{
+ char buf[128];
+ int n;
+
+ close(wctl);
+ if ((wctl = open("/dev/wctl", ORDWR)) < 0)
+ return 0;
+ n = read(wctl, buf, sizeof buf-1);
+ if (n <= 0)
+ sysfatal("wctl read: %r");
+ buf[n] = 0;
+ return strstr(buf, "visible") == nil;
+}
+
+void
+mousemux(void *v)
+{
+ Mouse m;
+ Channel *c;
+ int ob;
+
+ c = v;
+
+ for(ob = 0;;ob = m.buttons){
+ if(recv(c, &m) < 0)
+ break;
+ if ((m.buttons & 0x20) == 0) {
+ if (ob & 0x20) {
+ /* hide button just came up */
+ if (hidden()) {
+ if (debug) fprint(2, "unhide");
+ if (fprint(wctl, "unhide") <= 0)
+ fprint(2, "unhide failed: %r\n");
+ } else {
+ if (debug) fprint(2, "hide");
+ if (fprint(wctl, "hide") <= 0)
+ fprint(2, "hide failed: %r\n");
+ }
+ } else
+ send(cs->mousec, &m);
+ }
+ }
+}
+
+void
+refreshwin(void)
+{
+ char label[128];
+ int i, fd, lfd, n, nr, nw, m;
+ Dir *pd;
+
+ if((fd = open("/dev/wsys", OREAD)) < 0)
+ return;
+
+ nw = 0;
+/* i'd rather read one at a time but rio won't let me */
+ while((nr=dirread(fd, &pd)) > 0){
+ for(i=0; i<nr; i++){
+ n = atoi(pd[i].name);
+ sprint(label, "/dev/wsys/%d/label", n);
+ if((lfd = open(label, OREAD)) < 0)
+ continue;
+ m = read(lfd, label, sizeof(label)-1);
+ close(lfd);
+ if(m < 0)
+ continue;
+ label[m] = '\0';
+ if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){
+ nw++;
+ continue;
+ }
+
+ if(nw < nwin){
+ free(win[nw].label);
+ win[nw].label = nil;
+ }
+ if(nw >= mwin){
+ mwin += 8;
+ win = ctlrealloc(win, mwin*sizeof(win[0]));
+ memset(&win[mwin-8], 0, 8*sizeof(win[0]));
+ }
+ win[nw].n = n;
+ win[nw].label = ctlstrdup(label);
+ win[nw].dirty = 1;
+ sprint(label, "%d", nw);
+ if (win[nw].button == nil){
+ win[nw].button = createtextbutton(cs, label);
+ chanprint(cs->ctl, "%q font keyfont", label);
+ chanprint(cs->ctl, "%q image keyback", label);
+ chanprint(cs->ctl, "%q pressedtextcolor red", label);
+ chanprint(cs->ctl, "%q mask transparent", label);
+ chanprint(cs->ctl, "%q border 1", label);
+ chanprint(cs->ctl, "%q bordercolor black", label);
+ chanprint(cs->ctl, "%q align centerleft", label);
+ chanprint(cs->ctl, "%q size 16 %d 512 %d", label, keyfont->height+2, keyfont->height+2);
+ controlwire(win[nw].button, "event", ec);
+ }
+ if (nw >= nwin){
+ activate(win[nw].button);
+ chanprint(cs->ctl, "cols add %q", label);
+ }
+ chanprint(cs->ctl, "%q text %q", win[nw].button->name, win[nw].label);
+ nw++;
+ }
+ }
+ for(i = nw; i < nwin; i++){
+ free(win[i].label);
+ win[i].label = nil;
+ deactivate(win[i].button);
+ chanprint(cs->ctl, "cols remove %q", win[i].button->name);
+ }
+ nwin = nw;
+ close(fd);
+ if (rw.max.x)
+ chanprint(cs->ctl, "cols rect %R\ncols show", rw);
+}
+
+void
+resizecontrolset(Controlset*)
+{
+ int fd;
+ char buf[61];
+
+
+ if(getwindow(display, Refnone) < 0)
+ ctlerror("resize failed: %r");
+
+ if (hidden()) {
+ if (debug) fprint(2, "resizecontrolset: hidden\n");
+ return;
+ }
+
+ fd = open("/dev/screen", OREAD);
+ if (fd < 0) {
+ r = display->image->r;
+ if (debug) fprint(2, "display->imgae->r: %R\n", r);
+ } else {
+ if (read(fd, buf, 60) != 60)
+ sysfatal("resizecontrolset: read: /dev/screen: %r");
+ close(fd);
+ buf[60] = '\0';
+ r.min.x = atoi(buf+1+1*12);
+ r.min.y = atoi(buf+1+2*12);
+ r.max.x = atoi(buf+1+3*12);
+ r.max.y = atoi(buf+1+4*12);
+ if (debug) fprint(2, "/dev/screen: %R\n", r);
+ }
+ r = insetrect(r, 4);
+ r.min.y = r.max.y - kbdheight - 2*Borderwidth;
+ if (debug) fprint(2, "before eqrect: %R\n", r);
+ if (eqrect(r, screen->r) == 0) {
+ if (debug) fprint(2, "resizecontrolset: resize %R\n", r);
+ if (fprint(wctl, "resize -r %R", insetrect(r, -4)) <= 0) {
+ fprint(2, "resizecontrolset: resize failed\n");
+ }
+ return;
+ }
+
+ if (debug) fprint(2, "after eqrect: %R\n", r);
+ rk = r;
+ if (winshow){
+ rw = rk;
+ rw.min.x = (3*rk.max.x + rk.min.x)/4;
+ rk.max.x = rw.min.x;
+ if (debug) fprint(2, "rw: rect %R\n", rw);
+ chanprint(cs->ctl, "cols rect %R\ncols show", rw);
+ }
+ if (kbdonly) {
+ chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);
+ } else {
+ rs = rk;
+ if (scribbleleft){
+ rk.min.x = (rk.max.x + 3*rk.min.x)/4;
+ rs.max.x = rk.min.x;
+ }else{
+ rk.max.x = (3*rk.max.x + rk.min.x)/4;
+ rs.min.x = rk.max.x;
+ }
+ chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);
+ if (debug) fprint(2, "rk: rect %R\nkeyboard show\n", rk);
+ chanprint(cs->ctl, "scribble rect %R\nscribble show", rs);
+ if (debug) fprint(2, "rs: rect %R\nscribble show\n", rs);
+ }
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: keyboard\n");
+ threadexitsall("usage");
+}
+
+void
+timerproc(void*v)
+{
+ Channel *c;
+
+ c = v;
+ for(;;){
+ sleep(5000);
+ sendul(c, 1);
+ }
+}
+
+void
+watchproc(void*)
+{
+
+ for(;;){}
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ int i, n, kbdfd;
+ char str[UTFmax+1];
+ Rune r;
+ Mousectl *mousectl;
+ Channel *mtok;
+ char *e, buf[128], *args[8];
+ int fd;
+
+ ARGBEGIN{
+ case 'w':
+ winshow++;
+ break;
+ case 'l':
+ scribbleleft++;
+ break;
+ case 'n':
+ kbdonly++;
+ break;
+ case 'd':
+ ScribbleDebug++;
+ debug++;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 0)
+ usage();
+
+ kbdfd = open("/dev/kbdin", OWRITE);
+ if (kbdfd < 0 && (kbdfd = open("#r/kbdin", OWRITE)) < 0) {
+ if (debug) fprint(2, "open %s: %r\n", "#r/kbdin");
+ kbdfd = 1;
+ }
+
+ initdraw(0, 0, "keyboard");
+ mousectl = initmouse(nil, screen);
+
+ wctl = open("/dev/wctl", ORDWR);
+ if (wctl < 0) {
+ fprint(2, "open %s: %r\n", "/dev/wctl");
+ wctl = 2; /* for debugging */
+ }
+
+ mtok = chancreate(sizeof(Mouse), 0);
+
+ initcontrols();
+
+ cs = newcontrolset(screen, nil, mtok, mousectl->resizec);
+
+ threadcreate(mousemux, mousectl->c, 4096);
+
+ kc = chancreate(sizeof(char*), 0);
+ tc = chancreate(sizeof(int), 1);
+ ec = chancreate(sizeof(char*), 1);
+
+ colors[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback);
+ namectlimage(colors[Back], "keyback");
+ colors[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight);
+ namectlimage(colors[Light], "keylight");
+ colors[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade);
+ namectlimage(colors[Shade], "keyshade");
+ colors[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask);
+ namectlimage(colors[Shade], "keymask");
+ keyfont = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font");
+ namectlfont(keyfont, "keyfont");
+ keyctlfont = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font");
+ namectlfont(keyctlfont, "keyctlfont");
+
+ kbd = createkeyboard(cs, "keyboard");
+ chanprint(cs->ctl, "keyboard font keyfont keyctlfont");
+ chanprint(cs->ctl, "keyboard image keyback");
+ chanprint(cs->ctl, "keyboard light keylight");
+ chanprint(cs->ctl, "keyboard mask keymask");
+ chanprint(cs->ctl, "keyboard border 1");
+ chanprint(cs->ctl, "keyboard size %d %d %d %d", 246, 2 + 5 * (keyfont->height + 1), 512, 256);
+ controlwire(kbd, "event", kc);
+
+ if (kbdonly == 0){
+ scrib = createscribble(cs, "scribble");
+ if (scrib == nil)
+ sysfatal("createscribble");
+ chanprint(cs->ctl, "scribble font keyfont");
+ chanprint(cs->ctl, "scribble image keyback");
+ chanprint(cs->ctl, "scribble border 1");
+ controlwire(scrib, "event", kc);
+ }
+
+ if (winshow){
+ boxbox = createboxbox(cs, "cols");
+
+ chanprint(cs->ctl, "cols border 2");
+ chanprint(cs->ctl, "cols bordercolor keyback");
+ }
+
+ resizecontrolset(nil);
+
+ activate(kbd);
+ if (kbdonly == 0)
+ activate(scrib);
+ if (winshow){
+ refreshwin();
+ proccreate(timerproc, tc, 2048);
+ }
+
+ for(;;){
+ Alt a[] = {
+ { kc, &e, CHANRCV },
+ { ec, &e, CHANRCV },
+ { tc, &n, CHANRCV },
+ { nil, nil, CHANEND }
+ };
+ switch(alt(a)){
+ case 0: /* Keyboard */
+ n = tokenize(e, args, nelem(args));
+ if(n == 3)
+ if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0)
+ if(strcmp(args[1], "value") == 0){
+ n = atoi(args[2]);
+ if(n <= 0xFFFF){
+ r = n;
+ i = runetochar(str, &r);
+ write(kbdfd, str, i);
+ }
+ }
+ break;
+ case 1: /* Button event */
+ n = tokenize(e, args, nelem(args));
+ if (n != 3 || strcmp(args[1], "value"))
+ sysfatal("event string");
+ i = atoi(args[0]);
+ if (i < 0 || i >= nwin)
+ sysfatal("win out of range: %d of %d", i, nwin);
+ n = atoi(args[2]);
+ if (n){
+ sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
+ if((fd = open(buf, OWRITE)) >= 0){
+ while (write(fd, "top\n", 4) < 0) {
+ /* wait until mouse comes up */
+ rerrstr(buf, sizeof buf);
+ if (strncmp(buf, "action disallowed when mouse active", sizeof buf)){
+ fprint(2, "write top: %s\n", buf);
+ break;
+ }
+ sleep(100);
+ }
+ if (write(fd, "current\n", 8) < 0)
+ fprint(2, "write current: %r\n");
+ close(fd);
+ }
+ chanprint(cs->ctl, "%q value 0", win[i].button->name);
+ }
+ break;
+ case 2:
+ refreshwin();
+ break;
+ }
+ }
+}