keyboard.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include <draw.h>
  5. #include <mouse.h>
  6. #include <keyboard.h>
  7. #include <control.h>
  8. #include <scribble.h>
  9. int debug = 0;
  10. typedef struct Win Win;
  11. struct Win {
  12. int n;
  13. int dirty;
  14. char *label;
  15. Control *button;
  16. };
  17. Win *win;
  18. int nwin;
  19. int mwin;
  20. int onwin;
  21. int rows, cols;
  22. int kbdonly;
  23. int scribbleleft;
  24. int winshow;
  25. Channel *kc;
  26. Channel *ec;
  27. Channel *tc;
  28. Rectangle r, rk, rs, rw;
  29. Font *keyfont, *keyctlfont;
  30. enum{
  31. Back,
  32. Shade,
  33. Light,
  34. Mask,
  35. Ncol
  36. };
  37. enum {
  38. kbdheight = 2 + 5*13,
  39. };
  40. enum {
  41. Keyback = 0xeeee9eff,
  42. Keyshade = 0xaaaa55ff,
  43. Keylight = DWhite,
  44. Keymask = 0x0C0C0C0C,
  45. };
  46. Image *colors[Ncol];
  47. Control *kbd;
  48. Control *scrib;
  49. Control *boxbox;
  50. Controlset *cs;
  51. int ctldeletequits = 1;
  52. int wctl;
  53. int
  54. hidden(void)
  55. {
  56. char buf[128];
  57. int n;
  58. close(wctl);
  59. if ((wctl = open("/dev/wctl", ORDWR)) < 0)
  60. return 0;
  61. n = read(wctl, buf, sizeof buf-1);
  62. if (n <= 0)
  63. sysfatal("wctl read: %r");
  64. buf[n] = 0;
  65. return strstr(buf, "visible") == nil;
  66. }
  67. void
  68. mousemux(void *v)
  69. {
  70. Mouse m;
  71. Channel *c;
  72. int ob;
  73. c = v;
  74. for(ob = 0;;ob = m.buttons){
  75. if(recv(c, &m) < 0)
  76. break;
  77. if ((m.buttons & 0x20) == 0) {
  78. if (ob & 0x20) {
  79. /* hide button just came up */
  80. if (hidden()) {
  81. if (debug) fprint(2, "unhide");
  82. if (fprint(wctl, "unhide") <= 0)
  83. fprint(2, "unhide failed: %r\n");
  84. } else {
  85. if (debug) fprint(2, "hide");
  86. if (fprint(wctl, "hide") <= 0)
  87. fprint(2, "hide failed: %r\n");
  88. }
  89. } else
  90. send(cs->mousec, &m);
  91. }
  92. }
  93. }
  94. void
  95. refreshwin(void)
  96. {
  97. char label[128];
  98. int i, fd, lfd, n, nr, nw, m;
  99. Dir *pd;
  100. if((fd = open("/dev/wsys", OREAD)) < 0)
  101. return;
  102. nw = 0;
  103. /* i'd rather read one at a time but rio won't let me */
  104. while((nr=dirread(fd, &pd)) > 0){
  105. for(i=0; i<nr; i++){
  106. n = atoi(pd[i].name);
  107. sprint(label, "/dev/wsys/%d/label", n);
  108. if((lfd = open(label, OREAD)) < 0)
  109. continue;
  110. m = read(lfd, label, sizeof(label)-1);
  111. close(lfd);
  112. if(m < 0)
  113. continue;
  114. label[m] = '\0';
  115. if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){
  116. nw++;
  117. continue;
  118. }
  119. if(nw < nwin){
  120. free(win[nw].label);
  121. win[nw].label = nil;
  122. }
  123. if(nw >= mwin){
  124. mwin += 8;
  125. win = ctlrealloc(win, mwin*sizeof(win[0]));
  126. memset(&win[mwin-8], 0, 8*sizeof(win[0]));
  127. }
  128. win[nw].n = n;
  129. win[nw].label = ctlstrdup(label);
  130. win[nw].dirty = 1;
  131. sprint(label, "%d", nw);
  132. if (win[nw].button == nil){
  133. win[nw].button = createtextbutton(cs, label);
  134. chanprint(cs->ctl, "%q font keyfont", label);
  135. chanprint(cs->ctl, "%q image keyback", label);
  136. chanprint(cs->ctl, "%q pressedtextcolor red", label);
  137. chanprint(cs->ctl, "%q mask transparent", label);
  138. chanprint(cs->ctl, "%q border 1", label);
  139. chanprint(cs->ctl, "%q bordercolor black", label);
  140. chanprint(cs->ctl, "%q align centerleft", label);
  141. chanprint(cs->ctl, "%q size 16 %d 512 %d", label, keyfont->height+2, keyfont->height+2);
  142. controlwire(win[nw].button, "event", ec);
  143. }
  144. if (nw >= nwin){
  145. activate(win[nw].button);
  146. chanprint(cs->ctl, "cols add %q", label);
  147. }
  148. chanprint(cs->ctl, "%q text %q", win[nw].button->name, win[nw].label);
  149. nw++;
  150. }
  151. }
  152. for(i = nw; i < nwin; i++){
  153. free(win[i].label);
  154. win[i].label = nil;
  155. deactivate(win[i].button);
  156. chanprint(cs->ctl, "cols remove %q", win[i].button->name);
  157. }
  158. nwin = nw;
  159. close(fd);
  160. if (rw.max.x)
  161. chanprint(cs->ctl, "cols rect %R\ncols show", rw);
  162. }
  163. void
  164. resizecontrolset(Controlset*)
  165. {
  166. int fd;
  167. char buf[61];
  168. if(getwindow(display, Refnone) < 0)
  169. ctlerror("resize failed: %r");
  170. if (hidden()) {
  171. if (debug) fprint(2, "resizecontrolset: hidden\n");
  172. return;
  173. }
  174. fd = open("/dev/screen", OREAD);
  175. if (fd < 0) {
  176. r = display->image->r;
  177. if (debug) fprint(2, "display->imgae->r: %R\n", r);
  178. } else {
  179. if (read(fd, buf, 60) != 60)
  180. sysfatal("resizecontrolset: read: /dev/screen: %r");
  181. close(fd);
  182. buf[60] = '\0';
  183. r.min.x = atoi(buf+1+1*12);
  184. r.min.y = atoi(buf+1+2*12);
  185. r.max.x = atoi(buf+1+3*12);
  186. r.max.y = atoi(buf+1+4*12);
  187. if (debug) fprint(2, "/dev/screen: %R\n", r);
  188. }
  189. r = insetrect(r, 4);
  190. r.min.y = r.max.y - kbdheight - 2*Borderwidth;
  191. if (debug) fprint(2, "before eqrect: %R\n", r);
  192. if (eqrect(r, screen->r) == 0) {
  193. if (debug) fprint(2, "resizecontrolset: resize %R\n", r);
  194. if (fprint(wctl, "resize -r %R", insetrect(r, -4)) <= 0) {
  195. fprint(2, "resizecontrolset: resize failed\n");
  196. }
  197. return;
  198. }
  199. if (debug) fprint(2, "after eqrect: %R\n", r);
  200. rk = r;
  201. if (winshow){
  202. rw = rk;
  203. rw.min.x = (3*rk.max.x + rk.min.x)/4;
  204. rk.max.x = rw.min.x;
  205. if (debug) fprint(2, "rw: rect %R\n", rw);
  206. chanprint(cs->ctl, "cols rect %R\ncols show", rw);
  207. }
  208. if (kbdonly) {
  209. chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);
  210. } else {
  211. rs = rk;
  212. if (scribbleleft){
  213. rk.min.x = (rk.max.x + 3*rk.min.x)/4;
  214. rs.max.x = rk.min.x;
  215. }else{
  216. rk.max.x = (3*rk.max.x + rk.min.x)/4;
  217. rs.min.x = rk.max.x;
  218. }
  219. chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk);
  220. if (debug) fprint(2, "rk: rect %R\nkeyboard show\n", rk);
  221. chanprint(cs->ctl, "scribble rect %R\nscribble show", rs);
  222. if (debug) fprint(2, "rs: rect %R\nscribble show\n", rs);
  223. }
  224. }
  225. void
  226. usage(void)
  227. {
  228. fprint(2, "usage: keyboard\n");
  229. threadexitsall("usage");
  230. }
  231. void
  232. timerproc(void*v)
  233. {
  234. Channel *c;
  235. c = v;
  236. for(;;){
  237. sleep(5000);
  238. sendul(c, 1);
  239. }
  240. }
  241. void
  242. watchproc(void*)
  243. {
  244. for(;;){}
  245. }
  246. void
  247. threadmain(int argc, char *argv[])
  248. {
  249. int i, n, kbdfd;
  250. char str[UTFmax+1];
  251. Rune r;
  252. Mousectl *mousectl;
  253. Channel *mtok;
  254. char *e, buf[128], *args[8];
  255. int fd;
  256. ARGBEGIN{
  257. case 'w':
  258. winshow++;
  259. break;
  260. case 'l':
  261. scribbleleft++;
  262. break;
  263. case 'n':
  264. kbdonly++;
  265. break;
  266. case 'd':
  267. ScribbleDebug++;
  268. debug++;
  269. break;
  270. default:
  271. usage();
  272. }ARGEND
  273. if(argc != 0)
  274. usage();
  275. kbdfd = open("/dev/kbdin", OWRITE);
  276. if (kbdfd < 0 && (kbdfd = open("#r/kbdin", OWRITE)) < 0) {
  277. if (debug) fprint(2, "open %s: %r\n", "#r/kbdin");
  278. kbdfd = 1;
  279. }
  280. initdraw(0, 0, "keyboard");
  281. mousectl = initmouse(nil, screen);
  282. wctl = open("/dev/wctl", ORDWR);
  283. if (wctl < 0) {
  284. fprint(2, "open %s: %r\n", "/dev/wctl");
  285. wctl = 2; /* for debugging */
  286. }
  287. mtok = chancreate(sizeof(Mouse), 0);
  288. initcontrols();
  289. cs = newcontrolset(screen, nil, mtok, mousectl->resizec);
  290. threadcreate(mousemux, mousectl->c, 4096);
  291. kc = chancreate(sizeof(char*), 0);
  292. tc = chancreate(sizeof(int), 1);
  293. ec = chancreate(sizeof(char*), 1);
  294. colors[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback);
  295. namectlimage(colors[Back], "keyback");
  296. colors[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight);
  297. namectlimage(colors[Light], "keylight");
  298. colors[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade);
  299. namectlimage(colors[Shade], "keyshade");
  300. colors[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask);
  301. namectlimage(colors[Shade], "keymask");
  302. keyfont = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font");
  303. namectlfont(keyfont, "keyfont");
  304. keyctlfont = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font");
  305. namectlfont(keyctlfont, "keyctlfont");
  306. kbd = createkeyboard(cs, "keyboard");
  307. chanprint(cs->ctl, "keyboard font keyfont keyctlfont");
  308. chanprint(cs->ctl, "keyboard image keyback");
  309. chanprint(cs->ctl, "keyboard light keylight");
  310. chanprint(cs->ctl, "keyboard mask keymask");
  311. chanprint(cs->ctl, "keyboard border 1");
  312. chanprint(cs->ctl, "keyboard size %d %d %d %d", 246, 2 + 5 * (keyfont->height + 1), 512, 256);
  313. controlwire(kbd, "event", kc);
  314. if (kbdonly == 0){
  315. scrib = createscribble(cs, "scribble");
  316. if (scrib == nil)
  317. sysfatal("createscribble");
  318. chanprint(cs->ctl, "scribble font keyfont");
  319. chanprint(cs->ctl, "scribble image keyback");
  320. chanprint(cs->ctl, "scribble border 1");
  321. controlwire(scrib, "event", kc);
  322. }
  323. if (winshow){
  324. boxbox = createboxbox(cs, "cols");
  325. chanprint(cs->ctl, "cols border 2");
  326. chanprint(cs->ctl, "cols bordercolor keyback");
  327. }
  328. resizecontrolset(nil);
  329. activate(kbd);
  330. if (kbdonly == 0)
  331. activate(scrib);
  332. if (winshow){
  333. refreshwin();
  334. proccreate(timerproc, tc, 2048);
  335. }
  336. for(;;){
  337. Alt a[] = {
  338. { kc, &e, CHANRCV },
  339. { ec, &e, CHANRCV },
  340. { tc, &n, CHANRCV },
  341. { nil, nil, CHANEND }
  342. };
  343. switch(alt(a)){
  344. case 0: /* Keyboard */
  345. n = tokenize(e, args, nelem(args));
  346. if(n == 3)
  347. if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0)
  348. if(strcmp(args[1], "value") == 0){
  349. n = atoi(args[2]);
  350. if(n <= 0xFFFF){
  351. r = n;
  352. i = runetochar(str, &r);
  353. write(kbdfd, str, i);
  354. }
  355. }
  356. break;
  357. case 1: /* Button event */
  358. n = tokenize(e, args, nelem(args));
  359. if (n != 3 || strcmp(args[1], "value"))
  360. sysfatal("event string");
  361. i = atoi(args[0]);
  362. if (i < 0 || i >= nwin)
  363. sysfatal("win out of range: %d of %d", i, nwin);
  364. n = atoi(args[2]);
  365. if (n){
  366. sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
  367. if((fd = open(buf, OWRITE)) >= 0){
  368. while (write(fd, "top\n", 4) < 0) {
  369. /* wait until mouse comes up */
  370. rerrstr(buf, sizeof buf);
  371. if (strncmp(buf, "action disallowed when mouse active", sizeof buf)){
  372. fprint(2, "write top: %s\n", buf);
  373. break;
  374. }
  375. sleep(100);
  376. }
  377. if (write(fd, "current\n", 8) < 0)
  378. fprint(2, "write current: %r\n");
  379. close(fd);
  380. }
  381. chanprint(cs->ctl, "%q value 0", win[i].button->name);
  382. }
  383. break;
  384. case 2:
  385. refreshwin();
  386. break;
  387. }
  388. }
  389. }