keyboard.c 11 KB

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