keyboard.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <thread.h>
  13. #include <mouse.h>
  14. #include <keyboard.h>
  15. #include <control.h>
  16. typedef struct Keyboard Keyboard;
  17. enum{
  18. SRegular = 0,
  19. SShift = 1,
  20. SCaps = 2,
  21. SMask = 3,
  22. Nstate = 4,
  23. SControl = 4,
  24. };
  25. struct Keyboard
  26. {
  27. Control Control;
  28. CImage *image;
  29. CImage *mask;
  30. CImage *light;
  31. CImage *textcolor;
  32. CImage *bordercolor;
  33. CFont *font;
  34. CFont *ctlfont;
  35. Image *im[Nstate];
  36. int border;
  37. int lastbut;
  38. int state;
  39. char *_key; // Declared in struct Control
  40. };
  41. enum{
  42. EBorder,
  43. EBordercolor,
  44. EFocus,
  45. EFont,
  46. EFormat,
  47. EHide,
  48. EImage,
  49. ELight,
  50. EMask,
  51. ERect,
  52. EReveal,
  53. EShow,
  54. ESize,
  55. };
  56. static char *cmds[] = {
  57. [EBorder] = "border",
  58. [EBordercolor] = "bordercolor",
  59. [EFocus] = "focus",
  60. [EFont] = "font",
  61. [EFormat] = "format",
  62. [EHide] = "hide",
  63. [EImage] = "image",
  64. [ELight] = "light",
  65. [EMask] = "mask",
  66. [ERect] = "rect",
  67. [EReveal] = "reveal",
  68. [EShow] = "show",
  69. [ESize] = "size",
  70. nil
  71. };
  72. enum
  73. {
  74. Nrow = 5
  75. };
  76. static uint8_t wid [Nrow][16] = {
  77. {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, },
  78. {24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, },
  79. {32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
  80. {40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
  81. {30, 30, 80, 40, 42, 24, },
  82. };
  83. static char *keyregular[Nrow] = {
  84. "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",
  85. "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0[\0]\0Del\0\0",
  86. "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0;\0'\0Enter\0\0",
  87. "Shift\0z\0x\0c\0v\0b\0n\0m\0,\0.\0/\0Shift\0\0",
  88. "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
  89. };
  90. static char *keyshift[Nrow] = {
  91. "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
  92. "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0{\0}\0Del\0\0",
  93. "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0:\0\"\0Enter\0\0",
  94. "Shift\0Z\0X\0C\0V\0B\0N\0M\0<\0>\0?\0Shift\0\0",
  95. "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
  96. };
  97. static char *keycaps[Nrow] = {
  98. "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",
  99. "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0[\0]\0Del\0\0",
  100. "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0;\0'\0Enter\0\0",
  101. "Shift\0Z\0X\0C\0V\0B\0N\0M\0,\0.\0/\0Shift\0\0",
  102. "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
  103. };
  104. static char *keycapsshift[Nrow] = {
  105. "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
  106. "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0{\0}\0Del\0\0",
  107. "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0:\0\"\0Enter\0\0",
  108. "Shift\0z\0x\0c\0v\0b\0n\0m\0<\0>\0?\0Shift\0\0",
  109. "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
  110. };
  111. struct{
  112. char *name;
  113. int val;
  114. }keytab[] = {
  115. {"Shift", 0},
  116. {"Ctrl", 0},
  117. {"Alt", 0},
  118. {"Caps", 0},
  119. {"Del", '\177'},
  120. {"Enter", '\n'},
  121. {"Esc", '\033'},
  122. {"<-", '\b'},
  123. {"->", '\t'},
  124. {"Scrib", 0x10000},
  125. {"Menu", 0x10001},
  126. {nil, 0},
  127. };
  128. static char **keyset[Nstate] = {
  129. keyregular,
  130. keyshift,
  131. keycaps,
  132. keycapsshift,
  133. };
  134. static void keyboardshow(Keyboard*);
  135. static void keyup(Keyboard*, Point);
  136. static void keydown(Keyboard*, Point);
  137. static void keyresize(Keyboard*);
  138. static void
  139. keyboardmouse(Control *c, Mouse *m)
  140. {
  141. Keyboard *k;
  142. k = (Keyboard *)c;
  143. if(m->buttons==1)
  144. keydown(k, m->xy);
  145. else if(k->lastbut==1 && m->buttons==0)
  146. keyup(k, m->xy);
  147. k->lastbut = m->buttons;
  148. }
  149. static void
  150. keyboardfree(Control *c)
  151. {
  152. int i;
  153. Keyboard *k;
  154. k = (Keyboard *)c;
  155. _putctlimage(k->image);
  156. _putctlimage(k->mask);
  157. _putctlimage(k->light);
  158. _putctlimage(k->textcolor);
  159. _putctlimage(k->bordercolor);
  160. _putctlfont(k->font);
  161. _putctlfont(k->ctlfont);
  162. for(i=0; i<nelem(k->im); i++)
  163. freeimage(k->im[i]);
  164. free(k->Control.format);
  165. }
  166. static int
  167. keyboardy(Keyboard *k, int row)
  168. {
  169. int dy;
  170. if(row >= Nrow)
  171. return k->Control.rect.max.y-k->border;
  172. dy = Dy(k->Control.rect)-2*k->border;
  173. return k->Control.rect.min.y+k->border+(row*dy+Nrow-1)/Nrow;
  174. }
  175. static char*
  176. whichkey(Keyboard *k, Point p, int *rowp, int *colp, Rectangle *rp)
  177. {
  178. uint8_t *wp;
  179. char *kp;
  180. int row, col, dx, dy, x, n, maxx;
  181. Rectangle r;
  182. r = insetrect(k->Control.rect, k->border);
  183. if(!ptinrect(p, r))
  184. return nil;
  185. maxx = r.max.x;
  186. dx = Dx(r);
  187. dy = Dy(r);
  188. row = (p.y - r.min.y)*Nrow/dy;
  189. if(row >= Nrow)
  190. row = Nrow-1;
  191. r.min.y = keyboardy(k, row);
  192. r.max.y = keyboardy(k, row+1);
  193. x = r.min.x;
  194. kp = keyset[k->state&SMask][row];
  195. wp = wid[row];
  196. for(col=0; *kp; col++,kp+=n+1){
  197. n = strlen(kp);
  198. r.min.x = x;
  199. r.max.x = x + (wp[col]*dx+255)/256;
  200. if(kp[n+1] == '\0')
  201. r.max.x = maxx;
  202. if(r.max.x > p.x)
  203. break;
  204. x = r.max.x;
  205. }
  206. *rp = insetrect(r, 1);
  207. *rowp = row;
  208. *colp = col;
  209. return kp;
  210. }
  211. static Rectangle
  212. keyrect(Keyboard *k, int row, int col)
  213. {
  214. uint8_t *wp;
  215. char *kp;
  216. int i, x, n, dx;
  217. Rectangle r;
  218. Point p;
  219. r = insetrect(k->Control.rect, k->border);
  220. p = r.min;
  221. dx = Dx(r);
  222. r.min.y = keyboardy(k, row);
  223. r.max.y = keyboardy(k, row+1);
  224. x = r.min.x;
  225. kp = keyset[0][row];
  226. wp = wid[row];
  227. for(i=0; *kp; i++,kp+=n+1){
  228. n = strlen(kp);
  229. r.min.x = x;
  230. r.max.x = x + (wp[i]*dx+255)/256;
  231. if(kp[n+1] == '\0')
  232. r.max.x = p.x+dx;
  233. if(i >= col)
  234. break;
  235. x = r.max.x;
  236. }
  237. return insetrect(r, 1);
  238. }
  239. static void
  240. keydraw(Keyboard *k, int state)
  241. {
  242. Point p, q;
  243. int row, col, x, dx, dy, nexty, n;
  244. uint8_t *wp;
  245. char *kp;
  246. Rectangle r;
  247. Font *f, *f1, *f2;
  248. Image *im;
  249. freeimage(k->im[state]);
  250. k->im[state] = nil;
  251. if(Dx(k->Control.rect)-2*k->border <= 0)
  252. return;
  253. im = allocimage(display, k->Control.rect, screen->chan, 0, ~0);
  254. if(im == nil)
  255. return;
  256. k->im[state] = im;
  257. r = insetrect(k->Control.rect, k->border);
  258. border(im, k->Control.rect, k->border, k->bordercolor->image, ZP);
  259. draw(im, r, k->image->image, nil, ZP);
  260. dx = Dx(r);
  261. dy = Dy(r);
  262. p = r.min;
  263. f1 = k->font->font;
  264. f2 = k->ctlfont->font;
  265. nexty = p.y;
  266. for(row=0; row<Nrow; row++){
  267. x = p.x;
  268. kp = keyset[state][row];
  269. wp = wid[row];
  270. r.min.y = nexty;
  271. nexty = keyboardy(k, row+1);
  272. r.max.y = nexty;
  273. for(col=0; *kp; col++,kp+=n+1){
  274. r.min.x = x;
  275. r.max.x = x + (wp[col]*dx+255)/256;
  276. n = strlen(kp);
  277. if(kp[n+1] == '\0')
  278. r.max.x = p.x+dx;
  279. if(row == Nrow-1)
  280. r.max.y = p.y+dy;
  281. if(n > 1)
  282. f = f2;
  283. else
  284. f = f1;
  285. q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter);
  286. _string(im, q, k->textcolor->image,
  287. ZP, f, kp, nil, n, r,
  288. nil, ZP, SoverD);
  289. x = r.max.x;
  290. if(kp[n+1])
  291. draw(im, Rect(x, r.min.y, x+1, r.max.y),
  292. k->textcolor->image, nil, ZP);
  293. }
  294. if(row != Nrow-1)
  295. draw(im, Rect(p.x, r.max.y, p.x+dx, r.max.y+1),
  296. k->textcolor->image, nil, ZP);
  297. }
  298. }
  299. static void
  300. keyresize(Keyboard *k)
  301. {
  302. int i;
  303. for(i=0; i<Nstate; i++)
  304. keydraw(k, i);
  305. }
  306. static void
  307. keyboardshow(Keyboard *k)
  308. {
  309. Rectangle r;
  310. if (k->Control.hidden)
  311. return;
  312. if(k->im[0]==nil || !eqrect(k->im[0]->r, k->Control.rect))
  313. keyresize(k);
  314. if(k->im[k->state&SMask] == nil)
  315. return;
  316. draw(k->Control.screen, k->Control.rect, k->im[k->state&SMask], nil, k->Control.rect.min);
  317. if(k->state & SShift){
  318. r = keyrect(k, 3, 0);
  319. draw(k->Control.screen, r, k->light->image, k->mask->image, ZP);
  320. r = keyrect(k, 3, 11);
  321. draw(k->Control.screen, r, k->light->image, k->mask->image, ZP);
  322. }
  323. if(k->state & SCaps){
  324. r = keyrect(k, 2, 0);
  325. draw(k->Control.screen, r, k->light->image, k->mask->image, ZP);
  326. }
  327. if(k->state & SControl){
  328. r = keyrect(k, 4, 0);
  329. draw(k->Control.screen, r, k->light->image, k->mask->image, ZP);
  330. }
  331. flushimage(display, 1);
  332. }
  333. static void
  334. keydown(Keyboard *k, Point p)
  335. {
  336. int row, col;
  337. Rectangle r;
  338. char *s;
  339. s = whichkey(k, p, &row, &col, &r);
  340. if(s == k->_key)
  341. return;
  342. keyboardshow(k);
  343. if(s != nil)
  344. draw(k->Control.screen, r, k->light->image, k->mask->image, ZP);
  345. flushimage(display, 1);
  346. k->_key = s;
  347. }
  348. static int
  349. keylookup(char *s)
  350. {
  351. int i;
  352. for(i=0; keytab[i].name; i++)
  353. if(strcmp(s, keytab[i].name) == 0)
  354. return keytab[i].val;
  355. return s[0];
  356. }
  357. static void
  358. keyup(Keyboard *k, Point p)
  359. {
  360. int row, col;
  361. Rectangle r;
  362. char *s;
  363. int val;
  364. s = whichkey(k, p, &row, &col, &r);
  365. if(s == nil)
  366. return;
  367. val = keylookup(s);
  368. if(k->state & SControl)
  369. if(' '<val && val<0177)
  370. val &= ~0x60;
  371. if(strcmp(s, "Alt") == 0)
  372. {;}
  373. if(strcmp(s, "Ctrl") == 0){
  374. k->state ^= SControl;
  375. }else
  376. k->state &= ~SControl;
  377. if(strcmp(s, "Shift")==0 || strcmp(s, "Caps")==0){
  378. if(strcmp(s, "Shift") == 0)
  379. k->state ^= SShift;
  380. if(strcmp(s, "Caps") == 0)
  381. k->state ^= SCaps;
  382. }else
  383. k->state &= ~SShift;
  384. keyboardshow(k);
  385. if(val)
  386. chanprint(k->Control.event, k->Control.format, k->Control.name, val);
  387. k->Control.key = nil;
  388. }
  389. static void
  390. keyboardctl(Control *c, CParse *cp)
  391. {
  392. int cmd;
  393. Rectangle r;
  394. Keyboard *k;
  395. k = (Keyboard*)c;
  396. cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
  397. switch(cmd){
  398. default:
  399. ctlerror("%q: unrecognized message '%s'", k->Control.name, cp->str);
  400. break;
  401. case EBorder:
  402. _ctlargcount(&k->Control, cp, 2);
  403. if(cp->iargs[1] < 0)
  404. ctlerror("%q: bad border: %c", k->Control.name, cp->str);
  405. k->border = cp->iargs[1];
  406. break;
  407. case EBordercolor:
  408. _ctlargcount(&k->Control, cp, 2);
  409. _setctlimage(&k->Control, &k->bordercolor, cp->args[1]);
  410. break;
  411. case EFocus:
  412. /* ignore focus change */
  413. break;
  414. case EFont:
  415. if(cp->nargs!=2 && cp->nargs!=3)
  416. ctlerror("%q: bad font message '%s'", k->Control.name, cp->str);
  417. _setctlfont(&k->Control, &k->font, cp->args[1]);
  418. if(cp->nargs == 3)
  419. _setctlfont(&k->Control, &k->ctlfont, cp->args[2]);
  420. else
  421. _setctlfont(&k->Control, &k->ctlfont, cp->args[1]);
  422. break;
  423. case EFormat:
  424. _ctlargcount(&k->Control, cp, 2);
  425. k->Control.format = ctlstrdup(cp->args[1]);
  426. break;
  427. case EHide:
  428. _ctlargcount(&k->Control, cp, 1);
  429. k->Control.hidden = 1;
  430. break;
  431. case EImage:
  432. _ctlargcount(&k->Control, cp, 2);
  433. _setctlimage(&k->Control, &k->image, cp->args[1]);
  434. break;
  435. case ELight:
  436. _ctlargcount(&k->Control, cp, 2);
  437. _setctlimage(&k->Control, &k->light, cp->args[1]);
  438. break;
  439. case EMask:
  440. _ctlargcount(&k->Control, cp, 2);
  441. _setctlimage(&k->Control, &k->mask, cp->args[1]);
  442. break;
  443. case ERect:
  444. _ctlargcount(&k->Control, cp, 5);
  445. r.min.x = cp->iargs[1];
  446. r.min.y = cp->iargs[2];
  447. r.max.x = cp->iargs[3];
  448. r.max.y = cp->iargs[4];
  449. if(Dx(r)<0 || Dy(r)<0)
  450. ctlerror("%q: bad rectangle: %s", k->Control.name, cp->str);
  451. k->Control.rect = r;
  452. keyboardshow(k);
  453. break;
  454. case EReveal:
  455. _ctlargcount(&k->Control, cp, 1);
  456. k->Control.hidden = 0;
  457. keyboardshow(k);
  458. break;
  459. case EShow:
  460. _ctlargcount(&k->Control, cp, 1);
  461. keyboardshow(k);
  462. break;
  463. case ESize:
  464. if (cp->nargs == 3)
  465. r.max = Pt(0x7fffffff, 0x7fffffff);
  466. else{
  467. _ctlargcount(&k->Control, cp, 5);
  468. r.max.x = cp->iargs[3];
  469. r.max.y = cp->iargs[4];
  470. }
  471. r.min.x = cp->iargs[1];
  472. r.min.y = cp->iargs[2];
  473. if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
  474. ctlerror("%q: bad sizes: %s", k->Control.name, cp->str);
  475. k->Control.size.min = r.min;
  476. k->Control.size.max = r.max;
  477. break;
  478. }
  479. }
  480. Control*
  481. createkeyboard(Controlset *cs, char *name)
  482. {
  483. Keyboard *k;
  484. k = (Keyboard *)_createctl(cs, "keyboard", sizeof(Keyboard), name);
  485. k->image = _getctlimage("white");
  486. k->mask = _getctlimage("opaque");
  487. k->light = _getctlimage("yellow");
  488. k->bordercolor = _getctlimage("black");
  489. k->textcolor = _getctlimage("black");
  490. k->font = _getctlfont("font");
  491. k->ctlfont = _getctlfont("font");
  492. k->Control.format = ctlstrdup("%q: value 0x%x");
  493. k->border = 0;
  494. k->lastbut = 0;
  495. k->Control.key = nil;
  496. k->state = SRegular;
  497. k->Control.ctl = keyboardctl;
  498. k->Control.mouse = keyboardmouse;
  499. k->Control.exit = keyboardfree;
  500. k->Control.size = Rect(246, 2 + 5 * (k->font->font->height + 1), 512, 256);
  501. return &k->Control;
  502. }