2 xkbd - xlib based onscreen keyboard.
4 Copyright (C) 2001 Matthew Allum
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
21 #include <X11/Xutil.h>
22 #include <X11/extensions/XTest.h>
23 #include <X11/keysym.h>
26 #include <X11/Xft/Xft.h>
33 #include "libvirtkeys.h"
38 #define DBG(txt, args... ) fprintf(stderr, "DEBUG" txt "\n", ##args )
40 #define DBG(txt, args... ) /* nothing */
48 load_a_single_font(keyboard *kb, char *fontname )
51 if ((kb->xftfont = XftFontOpenName(kb->display,
52 DefaultScreen(kb->display),
58 if ((kb->font_info = XLoadQueryFont(kb->display, fontname)) != NULL)
60 XSetFont(kb->display, kb->gc, kb->font_info->fid);
67 void _kb_load_font(keyboard *kb, char *defstr )
69 const char delim[] = "|";
72 if ((strchr(defstr, delim[0]) != NULL))
75 while( (token = strsep (&str, delim)) != NULL )
76 if (load_a_single_font(kb, token))
81 if (load_a_single_font(kb, defstr )) return;
84 fprintf(stderr, "xkbd: unable to find suitable font in '%s'\n", defstr);
88 keyboard* kb_new(Window win, Display *display, int kb_x, int kb_y,
89 int kb_width, int kb_height, char *conf_file,
90 char *font_name, int font_is_xft)
96 int max_width = 0; /* required for sizing code */
97 //int cy = 0; /* ditto */
100 char rcbuf[255]; /* buffer for conf file */
101 char *tp; /* tmp pointer */
107 button *tmp_but = NULL;
109 enum { none, kbddef, rowdef, keydef } context;
113 int max_single_char_width = 0;
114 int max_single_char_height = 0;
118 XRenderColor colortmp;
121 kb = malloc(sizeof(keyboard));
123 kb->display = display;
125 cmp = DefaultColormap(display, DefaultScreen(display));
127 /* create lots and lots of gc's */
128 kb->gc = _createGC(display, win);
129 XSetForeground(display, kb->gc,
130 BlackPixel(display, DefaultScreen(display) ));
131 XSetBackground(display, kb->gc,
132 WhitePixel(display, DefaultScreen(display) ));
134 kb->rev_gc = _createGC(display, win);
135 XSetForeground(display, kb->rev_gc,
136 WhitePixel(display, DefaultScreen(display) ));
137 XSetBackground(display, kb->rev_gc,
138 BlackPixel(display, DefaultScreen(display) ));
140 kb->txt_gc = _createGC(display, win);
141 XSetForeground(display, kb->txt_gc,
142 BlackPixel(display, DefaultScreen(display) ));
143 XSetBackground(display, kb->txt_gc,
144 WhitePixel(display, DefaultScreen(display) ));
146 kb->txt_rev_gc = _createGC(display, win);
147 XSetForeground(display, kb->txt_rev_gc,
148 WhitePixel(display, DefaultScreen(display) ));
149 XSetBackground(display, kb->rev_gc,
150 BlackPixel(display, DefaultScreen(display) ));
152 kb->bdr_gc = _createGC(display, win);
153 XSetForeground(display, kb->bdr_gc,
154 BlackPixel(display, DefaultScreen(display) ));
155 XSetBackground(display, kb->bdr_gc,
156 WhitePixel(display, DefaultScreen(display) ));
159 kb->render_type = xft;
161 kb->render_type = oldskool;
163 if (font_name != NULL)
167 kb->render_type = xft;
169 _kb_load_font(kb, font_name );
175 /* -- xft bits -------------------------------------------- */
177 colortmp.red = 0xFFFF;
178 colortmp.green = 0xFFFF;
179 colortmp.blue = 0xFFFF;
180 colortmp.alpha = 0xFFFF;
181 XftColorAllocValue(display,
182 DefaultVisual(display, DefaultScreen(display)),
183 DefaultColormap(display,DefaultScreen(display)),
187 colortmp.red = 0x0000;
188 colortmp.green = 0x0000;
189 colortmp.blue = 0x0000;
190 colortmp.alpha = 0xFFFF;
191 XftColorAllocValue(display,
192 DefaultVisual(display, DefaultScreen(display)),
193 DefaultColormap(display,DefaultScreen(display)),
197 /* --- end xft bits -------------------------- */
203 kb->state = KB_STATE_NORMAL;
204 kb->state_locked = KB_STATE_NORMAL;
206 kb->slide_margin = 0;
207 kb->key_delay_repeat = 10;
210 kb->total_layouts = 0;
215 if ((rcfp = fopen(conf_file, "r")) == NULL)
217 fprintf(stderr, "xkbd: Cant open conf file: %s\n", conf_file);
223 while(fgets(rcbuf, sizeof(rcbuf), rcfp) != NULL)
227 /* strip init spaces */
228 while(*tp == ' ' || *tp == '\t') tp++;
230 /* ignore comments and blank lines */
231 if (*tp == '\n' || *tp == '#') { DBG("Config: got hash\n"); continue; }
233 if (*tp == '<') /* a 'tag' - set the context */
235 if (*(tp+1) == '/') /* closing tag */
240 _kb_load_font(kb, "fixed" );
246 button_calc_c_width(tmp_but);
247 button_calc_c_height(tmp_but);
255 if (sscanf(tp, "<%s", tmpstr_A) == 1) /* get tag name */
257 if (strncmp(tmpstr_A, "global", 5) == 0)
262 if (strncmp(tmpstr_A, "layout", 6) == 0)
265 kb->kbd_layouts[kb->total_layouts-1] = box_new();
266 kb->vbox = kb->kbd_layouts[kb->total_layouts-1];
267 kb->vbox->act_width = kb_width;
268 kb->vbox->act_height = kb_height;
269 kb->vbox->min_height = 0;
270 kb->vbox->min_width = 0;
275 if (strncmp(tmpstr_A, "row", 3) == 0)
277 if (kb->total_layouts == 0)
281 So older configs work we can work with
285 kb->kbd_layouts[kb->total_layouts-1] = box_new();
286 kb->vbox = kb->kbd_layouts[kb->total_layouts-1];
287 kb->vbox->act_width = kb_width;
288 kb->vbox->act_height = kb_height;
289 kb->vbox->min_height = 0;
290 kb->vbox->min_width = 0;
295 tmp_box = box_add_box(kb->vbox, box_new());
299 if (strncmp(tmpstr_A, "key", 3) == 0)
301 /* check here for NULL tmp_button */
302 tmp_but = box_add_button(tmp_box, button_new(kb) );
308 fprintf(stderr,"Config file parse failed (tag) at line: %i\n",
313 else /* a key=value setting */
315 if (sscanf(tp, "%s %s", tmpstr_A,tmpstr_C) == 2) {
321 if (strcmp(tmpstr_A, "render") == 0)
323 if ((strncmp(tmpstr_C, "xft", 3) == 0)
326 kb->render_type = xft;
331 if ((strcmp(tmpstr_A, "font") == 0)
334 _kb_load_font(kb,tmpstr_C );
337 else if (strcmp(tmpstr_A, "button_style") == 0)
339 if (strcmp(tmpstr_C, "square") == 0)
341 else if (strcmp(tmpstr_C, "plain") == 0)
344 else if (strcmp(tmpstr_A, "col") == 0)
347 if (_XColorFromStr(kb->display, &col, tmpstr_C) == 0)
349 perror("color allocation failed\n"); exit(1);
351 XSetForeground(kb->display, kb->rev_gc, col.pixel );
353 else if (strcmp(tmpstr_A, "border_col") == 0)
356 if (_XColorFromStr(kb->display, &col, tmpstr_C) == 0)
358 perror("color allocation failed\n"); exit(1);
360 XSetForeground(kb->display, kb->bdr_gc, col.pixel );
362 else if (strcmp(tmpstr_A, "down_col") == 0)
365 if (_XColorFromStr(kb->display, &col, tmpstr_C) == 0)
367 perror("color allocation failed\n"); exit(1);
369 XSetForeground(kb->display, kb->gc, col.pixel );
371 else if (strcmp(tmpstr_A, "width") == 0)
373 /* TODO fix! seg's as kb->vbox does not yet exist
374 if (!kb->vbox->act_width)
375 kb->vbox->act_width = atoi(tmpstr_C);
378 else if (strcmp(tmpstr_A, "height") == 0)
380 /* TODO fix! seg's as kb->vbox does not yet exist
381 if (!kb->vbox->act_height)
382 kb->vbox->act_height = atoi(tmpstr_C);
385 else if (strcmp(tmpstr_A, "slide_margin") == 0)
387 kb->slide_margin = atoi(tmpstr_C);
389 else if (strcmp(tmpstr_A, "repeat_delay") == 0)
391 kb->key_delay_repeat = atoi(tmpstr_C);
393 else if (strcmp(tmpstr_A, "repeat_time") == 0)
395 kb->key_repeat = atoi(tmpstr_C);
398 else if (strcmp(tmpstr_A, "txt_col") == 0)
401 if (_XColorFromStr(kb->display, &col, tmpstr_C) == 0)
403 perror("color allocation failed\n"); exit(1);
406 if (kb->render_type == oldskool)
409 XSetForeground(kb->display, kb->txt_gc, col.pixel );
415 colortmp.red = col.red;
416 colortmp.green = col.green;
417 colortmp.blue = col.blue;
418 colortmp.alpha = 0xFFFF;
419 XftColorAllocValue(display,
420 DefaultVisual(display,
421 DefaultScreen(display)),
422 DefaultColormap(display,
423 DefaultScreen(display)),
431 case rowdef: /* no rowdefs as yet */
434 if (strcmp(tmpstr_A, "default") == 0)
435 button_set_txt(tmp_but, tmpstr_C);
436 else if (strcmp(tmpstr_A, "shift") == 0)
437 button_set_shift_txt(tmp_but, tmpstr_C);
438 else if (strcmp(tmpstr_A, "switch") == 0)
439 button_set_layout(tmp_but, tmpstr_C);
440 else if (strcmp(tmpstr_A, "mod") == 0)
441 button_set_mod_txt(tmp_but, tmpstr_C);
442 else if (strcmp(tmpstr_A, "default_ks") == 0)
443 button_set_txt_ks(tmp_but, tmpstr_C);
444 else if (strcmp(tmpstr_A, "shift_ks") == 0)
445 button_set_shift_ks(tmp_but, tmpstr_C);
446 else if (strcmp(tmpstr_A, "mod_ks") == 0)
447 button_set_mod_ks(tmp_but, tmpstr_C);
449 else if (strcmp(tmpstr_A, "img") == 0)
450 { button_set_pixmap(tmp_but, tmpstr_C); }
452 else if (strcmp(tmpstr_A, "bg") == 0)
453 { button_set_bg_col(tmp_but, tmpstr_C); }
454 else if (strcmp(tmpstr_A, "fg") == 0)
455 { button_set_fg_col(tmp_but, tmpstr_C); }
456 else if (strcmp(tmpstr_A, "slide_up_ks") == 0)
457 button_set_slide_ks(tmp_but, tmpstr_C, UP);
458 else if (strcmp(tmpstr_A, "slide_down_ks") == 0)
459 button_set_slide_ks(tmp_but, tmpstr_C, DOWN);
460 else if (strcmp(tmpstr_A, "slide_left_ks") == 0)
461 button_set_slide_ks(tmp_but, tmpstr_C, LEFT);
462 else if (strcmp(tmpstr_A, "slide_right_ks") == 0)
463 button_set_slide_ks(tmp_but, tmpstr_C, RIGHT);
464 else if (strcmp(tmpstr_A, "scancode") == 0)
465 button_set_scancode(tmp_but, tmpstr_C);
466 else if (strcmp(tmpstr_A, "width") == 0)
468 tmp_but->is_width_spec = True;
469 tmp_but->c_width = atoi(tmpstr_C);
471 else if (strcmp(tmpstr_A, "key_span_width") == 0)
473 tmp_but->is_width_spec = True;
474 tmp_but->key_span_width = atoi(tmpstr_C);
477 else if (strcmp(tmpstr_A, "height") == 0)
478 tmp_but->c_height = atoi(tmpstr_C);
479 else if (strcmp(tmpstr_A, "obey_capslock") == 0)
481 if (strcmp(tmpstr_C, "yes") == 0)
482 tmp_but->options |= OPT_OBEYCAPS;
483 else if (strcmp(tmpstr_C, "no") == 0)
484 tmp_but->options &= ~OPT_OBEYCAPS;
487 perror("invalid value for obey_capslock\n"); exit(1);
494 fprintf(stderr,"Config file parse failed at line: %i\n",
504 kb->vbox = kb->kbd_layouts[0];
506 /* pass 1 - calculate min dimentions */
508 listp = kb->vbox->root_kid;
511 /* find the max single char width */
513 while (listp != NULL)
516 tmp_box = (box *)listp->data;
517 ip = tmp_box->root_kid;
522 b = (button *)ip->data;
523 if (b->is_width_spec == False)
525 if ( ( b->default_txt == NULL || (strlen(b->default_txt) == 1))
526 && (b->shift_txt == NULL || (strlen(b->shift_txt) == 1))
527 && (b->mod_txt == NULL || (strlen(b->mod_txt) == 1))
531 if (b->c_width > max_single_char_width)
532 max_single_char_width = b->c_width;
535 if (b->c_height > max_single_char_height)
536 max_single_char_height = b->c_height;
545 /* Set all single char widths to the max one, figure out minimum sizes */
547 max_single_char_height += 2;
549 for(j=0;j<kb->total_layouts;j++)
551 kb->vbox = kb->kbd_layouts[j];
552 listp = kb->vbox->root_kid;
554 while (listp != NULL)
561 tmp_box = (box *)listp->data;
562 ip = tmp_box->root_kid;
567 b = (button *)ip->data;
568 if (!b->is_width_spec)
570 if ((b->default_txt == NULL || (strlen(b->default_txt) == 1))
571 && (b->shift_txt == NULL || (strlen(b->shift_txt) == 1))
572 && (b->mod_txt == NULL || (strlen(b->mod_txt) == 1))
573 && b->pixmap == NULL )
575 b->c_width = max_single_char_width;
578 b->c_height = max_single_char_height;
579 //printf("width is %i\n", b->c_width);
580 if (b->key_span_width)
581 b->c_width = b->key_span_width * max_single_char_width;
583 tmp_width += ( ((button *)ip->data)->c_width +
584 (((button *)ip->data)->b_size*2) );
585 tmp_height = ( ((button *)ip->data)->c_height +
586 (((button *)ip->data)->b_size*2));
587 if (tmp_height >= max_height) max_height = tmp_height;
590 if (tmp_width > max_width) max_width = tmp_width;
591 if (tmp_height >= max_height) max_height = tmp_height;
592 tmp_box->min_width = tmp_width;
593 tmp_box->min_height = max_height;
594 kb->vbox->min_height += max_height; // +1;
600 if ((j > 0) && kb->vbox->min_height > kb->kbd_layouts[0]->min_height)
601 kb->kbd_layouts[0]->min_height = kb->vbox->min_height;
603 kb->vbox->min_width = max_width;
606 /* TODO: copy all temp vboxs */
609 kb->vbox = kb->kbd_layouts[0];
610 //setupKeyboardVariables(kb->display);
616 void kb_size(keyboard *kb)
619 /* let the fun begin :) */
624 if ( kb->vbox->act_width == 0)
625 kb->vbox->act_width = kb->vbox->min_width ; /* by default add a
626 little to this on init */
627 if ( kb->vbox->act_height == 0)
628 kb->vbox->act_height = kb->vbox->min_height ;
630 if (kb->backing != None)
631 XFreePixmap(kb->display, kb->backing);
633 kb->backing = XCreatePixmap(kb->display, kb->win,
634 kb->vbox->act_width, kb->vbox->act_height,
635 DefaultDepth(kb->display,
636 DefaultScreen(kb->display)) );
638 XFillRectangle(kb->display, kb->backing,
640 kb->vbox->act_width, kb->vbox->act_height);
643 if (kb->xftdraw != NULL) XftDrawDestroy(kb->xftdraw);
646 kb->xftdraw = XftDrawCreate(kb->display, (Drawable) kb->backing,
647 DefaultVisual(kb->display,
648 DefaultScreen(kb->display)),
649 DefaultColormap(kb->display,
650 DefaultScreen(kb->display)));
654 listp = kb->vbox->root_kid;
655 while (listp != NULL)
661 button *tmp_but = NULL;
662 tmp_box = (box *)listp->data;
665 ip = tmp_box->root_kid;
667 ( (float)(tmp_box->min_height)/kb->vbox->min_height )
668 * kb->vbox->act_height );
675 tmp_but = (button *)ip->data;
677 tmp_but->x = cx; /*remember relative to holding box ! */
679 but_total_width = tmp_but->c_width+(2*tmp_but->b_size);
681 tmp_but->x_pad = (int)(((float)but_total_width/tmp_box->min_width)
682 * kb->vbox->act_width);
684 tmp_but->x_pad -= but_total_width;
686 tmp_but->act_width = tmp_but->c_width + tmp_but->x_pad
687 + (2*tmp_but->b_size);
689 cx += (tmp_but->act_width );
692 tmp_but->y_pad = y_pad - tmp_but->c_height - (2*tmp_but->b_size);
693 tmp_but->act_height = y_pad;
696 /* hack for using all screen space */
697 if (listp->next == NULL) tmp_but->act_height--;
701 /* another hack for using up all space */
702 tmp_but->x_pad += (kb->vbox->act_width-cx) -1 ;
703 tmp_but->act_width += (kb->vbox->act_width-cx) -1;
706 tmp_box->act_height = y_pad;
707 tmp_box->act_width = kb->vbox->act_width;
716 kb_switch_layout(keyboard *kb, int kbd_layout_num)
718 int w = kb->vbox->act_width;
719 int h = kb->vbox->act_height;
720 int mw = kb->vbox->min_width;
721 int mh = kb->vbox->min_height;
723 kb->vbox = kb->kbd_layouts[kbd_layout_num];
725 kb->vbox->act_width = w;
726 kb->vbox->act_height = h;
727 kb->vbox->min_width = mw;
728 kb->vbox->min_height = mh;
735 void kb_render(keyboard *kb)
740 listp = kb->vbox->root_kid;
741 while (listp != NULL)
745 button *tmp_but = NULL;
746 tmp_box = (box *)listp->data;
748 ip = tmp_box->root_kid;
752 tmp_but = (button *)ip->data;
753 if (tmp_but->modifier & kb->state_locked)
756 button_render(tmp_but, BUTTON_LOCKED);
758 else if (tmp_but->modifier & kb->state)
761 button_render(tmp_but, BUTTON_PRESSED);
764 button_render(tmp_but, BUTTON_RELEASED);
772 void kb_paint(keyboard *kb)
774 XCopyArea(kb->display, kb->backing, kb->win, kb->gc,
775 0, 0, kb->vbox->act_width, kb->vbox->act_height,
776 kb->vbox->x, kb->vbox->y);
779 button *kb_handle_events(keyboard *kb, XEvent an_event)
781 static button *active_but;
783 switch (an_event.type)
786 active_but = kb_find_button(kb,
788 an_event.xmotion.y );
789 if (active_but != NULL)
791 button_render(active_but, BUTTON_PRESSED);
792 button_paint(active_but);
793 /* process state here
794 send keypress via kbd state
797 bthid_process_keypress(active_but, 1);
801 if (active_but != NULL)
805 kb_set_slide(active_but, an_event.xmotion.x,
806 an_event.xmotion.y );
808 new_state = bthid_process_keypress(active_but, 0);
809 //new_state = kb_process_keypress(active_but);
811 if (new_state != active_but->kb->state ||
812 new_state & active_but->modifier)
814 /* if the states changed repaint the entire kbd
815 as its chars have probably changed */
817 active_but->kb->state = new_state;
818 kb_render(active_but->kb);
819 kb_paint(active_but->kb);
821 button_render(active_but, BUTTON_RELEASED);
822 button_paint(active_but);
824 /* check for slide */
826 active_but->slide = none;
828 if (active_but->layout_switch > -1)
830 DBG("switching layout\n");
831 kb_switch_layout(active_but->kb, active_but->layout_switch);
842 void kb_set_slide(button *active_but, int x, int y)
844 if (x < (button_get_abs_x(active_but)-active_but->kb->slide_margin))
845 { active_but->slide = left; return; }
847 if (x > ( button_get_abs_x(active_but)
848 + active_but->act_width + -active_but->kb->slide_margin ))
849 { active_but->slide = right; return; }
851 if (y < (button_get_abs_y(active_but)-active_but->kb->slide_margin))
852 { active_but->slide = up; return; }
854 if (y > ( button_get_abs_y(active_but) + active_but->act_height )
855 + -active_but->kb->slide_margin )
856 { active_but->slide = down; return; }
861 void kb_do_repeat(keyboard *kb, button *active_but)
865 if (active_but == NULL)
869 return; /* reset everything */
872 if ((delay && timer == kb->key_repeat)
873 || (!delay && timer == kb->key_delay_repeat))
875 //kb_process_keypress(active_but);
876 bthid_process_keypress(active_but, 2);
882 int kb_process_keypress(button *active_but)
884 /* holder for new keyboard state */
885 int new_state = active_but->kb->state;
887 DBG("got release state %i %i %i %i \n",
888 new_state, KB_STATE_SHIFT, KB_STATE_MOD, KB_STATE_CTRL );
891 if (active_but->modifier/* is a shift / ctrl / mod pressed */
892 && !(active_but->modifier & BUT_CAPS) )
894 if (active_but->kb->state_locked & active_but->modifier)
896 /* was locked then unset & unlock */
897 active_but->kb->state_locked ^= active_but->modifier;
898 new_state ^= active_but->modifier;
900 else if (new_state & active_but->modifier)
902 /* was set then lock */
903 active_but->kb->state_locked ^= active_but->modifier;
907 /* was unset then set */
908 new_state ^= active_but->modifier;
910 DBG("got a modifier key - %i \n", new_state);
912 else if (active_but->modifier & BUT_CAPS)
913 /* deal with caps key - maybe this can go above now ?*/
915 new_state ^= KB_STATE_CAPS; /* turn caps on/off */
916 DBG("got caps key - %i \n", new_state);
918 else if ( (active_but->kb->state & KB_STATE_SHIFT)
919 || (active_but->kb->state & KB_STATE_MOD)
920 || (active_but->kb->state & KB_STATE_CTRL)
921 || (active_but->kb->state & KB_STATE_META)
922 || (active_but->kb->state & KB_STATE_ALT) )
923 /* check if the kbd is already in a state and reset it
924 leaving caps key state alone */
926 new_state &= KB_STATE_CAPS;
927 new_state |= active_but->kb->state_locked;
928 DBG("kbd is shifted, unshifting - %i \n", new_state);
931 kb_send_keypress(active_but);
932 DBG("%s clicked \n", active_but->default_txt);
937 int kb_find_keycode(keyboard *kb, KeySym keysym,
938 KeyCode *code_ret, int *col_ret)
939 { /* Thanks carl ! */
945 XDisplayKeycodes(kb->display, &min_kc, &max_kc);
947 for (keycode = min_kc; keycode <= max_kc; keycode++) {
948 for (col = 0; (k = XKeycodeToKeysym (kb->display, keycode, col))
952 if (col_ret) *col_ret = col;
960 void kb_send_keypress(button *b)
965 struct keycodeEntry vk_keycodes[10];
967 if (b->kb->state & KB_STATE_SHIFT || b->kb->state & KB_STATE_CAPS)
969 if (b->kb->state & KB_STATE_SHIFT && b->kb->state & KB_STATE_CAPS)
971 if (b->options & OPT_OBEYCAPS)
976 else if (b->kb->state & KB_STATE_CAPS)
978 if (b->options & OPT_OBEYCAPS)
980 } else ks = b->shift_ks;
982 else if (b->kb->state & KB_STATE_MOD)
985 if (b->slide != none)
991 if (ks == 0) ks = b->shift_ks;
993 case down : /* hold ctrl */
994 ks = b->slide_down_ks;
995 if (ks == 0) slide_flag = KB_STATE_CTRL;
997 case left : /* hold alt */
998 ks = b->slide_left_ks;
1002 slide_flag = KB_STATE_MOD;
1005 case right : /* hold alt */
1006 ks = b->slide_right_ks;
1013 if (ks == 0) ks = b->default_ks;
1015 if (ks == 0) return; /* no keysym defined, abort */
1017 if (lookupKeyCodeSequence(ks, vk_keycodes, NULL))
1018 sendKeySequence(vk_keycodes,
1019 ( (b->kb->state & KB_STATE_CTRL) || (slide_flag == KB_STATE_CTRL) ),
1020 ( (b->kb->state & KB_STATE_META) || (slide_flag == KB_STATE_META) ),
1021 ( (b->kb->state & KB_STATE_ALT) || (slide_flag == KB_STATE_ALT) ),
1022 0 */ /* ( (b->kb->state & KB_STATE_SHIFT) || (slide_flag == KB_STATE_SHIFT) ) */
1029 button * kb_find_button(keyboard *kb, int x, int y)
1032 box *tmp_box = NULL;
1033 int offset_x, offset_y;
1035 offset_x = kb->vbox->x;
1036 offset_y = kb->vbox->y;
1038 if (x >= offset_x &&
1040 x <= (offset_x+kb->vbox->act_width) &&
1041 y <= (offset_y+kb->vbox->act_height) )
1043 listp = kb->vbox->root_kid;
1044 while (listp != NULL)
1048 button *tmp_but = NULL;
1049 tmp_box = (box *)listp->data;
1050 if (y > (offset_y + tmp_box->y) &&
1051 y < (offset_y + tmp_box->y + tmp_box->act_height))
1053 ip = tmp_box->root_kid;
1054 while (ip != NULL) /* now the row is found, find the key */
1056 tmp_but = (button *)ip->data;
1057 if (x > (tmp_but->x+offset_x+tmp_box->x) &&
1058 x < (tmp_but->x+offset_x+tmp_box->x+tmp_but->act_width) &&
1059 y > (tmp_but->y+offset_y+tmp_box->y) &&
1060 y < (tmp_but->y+offset_y+tmp_box->y+tmp_but->act_height)
1069 listp = listp->next;
1076 void kb_destroy(keyboard *kb)
1078 XFreeGC(kb->display, kb->gc);
1079 /* -- to do -- somwthing like this
1080 while (listp != NULL)
1084 button *tmp_but = NULL;
1085 tmp_box = (box *)listp->data;
1086 box_destroy(tmp_box) -- this will destroy the buttons