9 typedef struct Keyboard Keyboard;
53 static char *cmds[] = {
55 [EBordercolor] = "bordercolor",
75 static uchar wid [Nrow][16] = {
76 {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, },
77 {24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, },
78 {32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
79 {40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
80 {30, 30, 80, 40, 42, 24, },
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"
91 static char *keyshift[Nrow] = {
92 "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
93 "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0{\0}\0Del\0\0",
94 "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0:\0\"\0Enter\0\0",
95 "Shift\0Z\0X\0C\0V\0B\0N\0M\0<\0>\0?\0Shift\0\0",
96 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
99 static char *keycaps[Nrow] = {
100 "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",
101 "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0[\0]\0Del\0\0",
102 "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0;\0'\0Enter\0\0",
103 "Shift\0Z\0X\0C\0V\0B\0N\0M\0,\0.\0/\0Shift\0\0",
104 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
107 static char *keycapsshift[Nrow] = {
108 "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
109 "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0{\0}\0Del\0\0",
110 "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0:\0\"\0Enter\0\0",
111 "Shift\0z\0x\0c\0v\0b\0n\0m\0<\0>\0?\0Shift\0\0",
112 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
133 static char **keyset[Nstate] = {
140 static void keyboardshow(Keyboard*);
141 static void keyup(Keyboard*, Point);
142 static void keydown(Keyboard*, Point);
143 static void keyresize(Keyboard*);
146 keyboardmouse(Control *c, Mouse *m)
153 else if(k->lastbut==1 && m->buttons==0)
155 k->lastbut = m->buttons;
159 keyboardfree(Control *c)
165 _putctlimage(k->image);
166 _putctlimage(k->mask);
167 _putctlimage(k->light);
168 _putctlimage(k->textcolor);
169 _putctlimage(k->bordercolor);
170 _putctlfont(k->font);
171 _putctlfont(k->ctlfont);
172 for(i=0; i<nelem(k->im); i++)
178 keyboardy(Keyboard *k, int row)
183 return k->rect.max.y-k->border;
184 dy = Dy(k->rect)-2*k->border;
185 return k->rect.min.y+k->border+(row*dy+Nrow-1)/Nrow;
189 whichkey(Keyboard *k, Point p, int *rowp, int *colp, Rectangle *rp)
193 int row, col, dx, dy, x, n, maxx;
196 r = insetrect(k->rect, k->border);
202 row = (p.y - r.min.y)*Nrow/dy;
205 r.min.y = keyboardy(k, row);
206 r.max.y = keyboardy(k, row+1);
208 kp = keyset[k->state&SMask][row];
210 for(col=0; *kp; col++,kp+=n+1){
213 r.max.x = x + (wp[col]*dx+255)/256;
220 *rp = insetrect(r, 1);
227 keyrect(Keyboard *k, int row, int col)
235 r = insetrect(k->rect, k->border);
238 r.min.y = keyboardy(k, row);
239 r.max.y = keyboardy(k, row+1);
243 for(i=0; *kp; i++,kp+=n+1){
246 r.max.x = x + (wp[i]*dx+255)/256;
253 return insetrect(r, 1);
257 keydraw(Keyboard *k, int state)
260 int row, col, x, dx, dy, nexty, n;
267 freeimage(k->im[state]);
269 if(Dx(k->rect)-2*k->border <= 0)
272 im = allocimage(display, k->rect, screen->chan, 0, ~0);
277 r = insetrect(k->rect, k->border);
278 border(im, k->rect, k->border, k->bordercolor->image, ZP);
279 draw(im, r, k->image->image, nil, ZP);
284 f2 = k->ctlfont->font;
286 for(row=0; row<Nrow; row++){
288 kp = keyset[state][row];
291 nexty = keyboardy(k, row+1);
293 for(col=0; *kp; col++,kp+=n+1){
295 r.max.x = x + (wp[col]*dx+255)/256;
305 q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter);
306 _string(im, q, k->textcolor->image,
307 ZP, f, kp, nil, n, r,
311 draw(im, Rect(x, r.min.y, x+1, r.max.y),
312 k->textcolor->image, nil, ZP);
315 draw(im, Rect(p.x, r.max.y, p.x+dx, r.max.y+1),
316 k->textcolor->image, nil, ZP);
321 keyresize(Keyboard *k)
325 for(i=0; i<Nstate; i++)
330 keyboardshow(Keyboard *k)
336 if(k->im[0]==nil || !eqrect(k->im[0]->r, k->rect))
338 if(k->im[k->state&SMask] == nil)
340 draw(k->screen, k->rect, k->im[k->state&SMask], nil, k->rect.min);
341 if(k->state & SShift){
342 r = keyrect(k, 3, 0);
343 draw(k->screen, r, k->light->image, k->mask->image, ZP);
344 r = keyrect(k, 3, 11);
345 draw(k->screen, r, k->light->image, k->mask->image, ZP);
347 if(k->state & SCaps){
348 r = keyrect(k, 2, 0);
349 draw(k->screen, r, k->light->image, k->mask->image, ZP);
351 if(k->state & SControl){
352 r = keyrect(k, 4, 0);
353 draw(k->screen, r, k->light->image, k->mask->image, ZP);
355 flushimage(display, 1);
359 keydown(Keyboard *k, Point p)
365 s = whichkey(k, p, &row, &col, &r);
370 draw(k->screen, r, k->light->image, k->mask->image, ZP);
371 flushimage(display, 1);
380 for(i=0; keytab[i].name; i++)
381 if(strcmp(s, keytab[i].name) == 0)
382 return keytab[i].val;
387 keyup(Keyboard *k, Point p)
394 s = whichkey(k, p, &row, &col, &r);
398 if(k->state & SControl)
399 if(' '<val && val<0177)
401 if(strcmp(s, "Alt") == 0)
403 if(strcmp(s, "Ctrl") == 0){
404 k->state ^= SControl;
406 k->state &= ~SControl;
407 if(strcmp(s, "Shift")==0 || strcmp(s, "Caps")==0){
408 if(strcmp(s, "Shift") == 0)
410 if(strcmp(s, "Caps") == 0)
416 chanprint(k->event, k->format, k->name, val);
421 keyboardctl(Control *c, CParse *cp)
428 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
431 ctlerror("%q: unrecognized message '%s'", k->name, cp->str);
434 _ctlargcount(k, cp, 2);
436 ctlerror("%q: bad border: %c", k->name, cp->str);
437 k->border = cp->iargs[1];
440 _ctlargcount(k, cp, 2);
441 _setctlimage(k, &k->bordercolor, cp->args[1]);
444 /* ignore focus change */
447 if(cp->nargs!=2 && cp->nargs!=3)
448 ctlerror("%q: bad font message '%s'", k->name, cp->str);
449 _setctlfont(k, &k->font, cp->args[1]);
451 _setctlfont(k, &k->ctlfont, cp->args[2]);
453 _setctlfont(k, &k->ctlfont, cp->args[1]);
456 _ctlargcount(k, cp, 2);
457 k->format = ctlstrdup(cp->args[1]);
460 _ctlargcount(k, cp, 1);
464 _ctlargcount(k, cp, 2);
465 _setctlimage(k, &k->image, cp->args[1]);
468 _ctlargcount(k, cp, 2);
469 _setctlimage(k, &k->light, cp->args[1]);
472 _ctlargcount(k, cp, 2);
473 _setctlimage(k, &k->mask, cp->args[1]);
476 _ctlargcount(k, cp, 5);
477 r.min.x = cp->iargs[1];
478 r.min.y = cp->iargs[2];
479 r.max.x = cp->iargs[3];
480 r.max.y = cp->iargs[4];
481 if(Dx(r)<0 || Dy(r)<0)
482 ctlerror("%q: bad rectangle: %s", k->name, cp->str);
487 _ctlargcount(k, cp, 1);
492 _ctlargcount(k, cp, 1);
497 r.max = Pt(0x7fffffff, 0x7fffffff);
499 _ctlargcount(k, cp, 5);
500 r.max.x = cp->iargs[3];
501 r.max.y = cp->iargs[4];
503 r.min.x = cp->iargs[1];
504 r.min.y = cp->iargs[2];
505 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)
506 ctlerror("%q: bad sizes: %s", k->name, cp->str);
514 createkeyboard(Controlset *cs, char *name)
518 k = (Keyboard *)_createctl(cs, "keyboard", sizeof(Keyboard), name);
519 k->image = _getctlimage("white");
520 k->mask = _getctlimage("opaque");
521 k->light = _getctlimage("yellow");
522 k->bordercolor = _getctlimage("black");
523 k->textcolor = _getctlimage("black");
524 k->font = _getctlfont("font");
525 k->ctlfont = _getctlfont("font");
526 k->format = ctlstrdup("%q: value 0x%x");
531 k->ctl = keyboardctl;
532 k->mouse = keyboardmouse;
533 k->exit = keyboardfree;
534 k->size = Rect(246, 2 + 5 * (k->font->font->height + 1), 512, 256);