Add config for sup label on key
[fvkbd:fvkbd.git] / src / fvkbd-key.c
1 /*
2  * fvkbd-key.c key unit for fvkbd  
3  *
4  * Copyright (C) 2009, Intel Corporation.
5  *
6  * Author: Raymond Liu <raymond.liu@intel.com>
7  * 
8  * 
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * version 2.1 as published by the Free Software Foundation.
12  * 
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  * 
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23
24
25 #include "fvkbd.h"
26 #include <X11/Xlib.h>
27 #include <X11/keysym.h>
28
29 #include "misc-utility.h"
30 #include "fvkbd-keyboard.h"
31 #include "fvkbd-key.h"
32
33
34 #define FVKBD_KEY_GET_PRIVATE(object)\
35         (G_TYPE_INSTANCE_GET_PRIVATE((object), FVKBD_TYPE_KEY, FvkbdKeyPrivate))
36
37 struct _FvkbdKeyPrivate {
38         gint x;
39         gint y;
40         gint width;
41         gint height;
42         gboolean disable_pop;
43
44         GSList *actions;
45 };
46
47 G_DEFINE_TYPE (FvkbdKey, fvkbd_key, FVKBD_TYPE_UNIT);
48
49 static KeyFuncName key_func_names[] = {
50         {KBD_FUNC_NONE, "No Function Defined"},
51         {KBD_FUNC_ModShift, "shift"},
52         {KBD_FUNC_ModCaps, "caps"},
53         {KBD_FUNC_ModControl, "control"},
54         {KBD_FUNC_ModAlt, "alt"},
55
56         {KBD_FUNC_MODE_FIRST, "mode:first"},
57         {KBD_FUNC_MODE_LAST, "mode:last"},
58         {KBD_FUNC_MODE_NEXT, "mode:next"},
59         {KBD_FUNC_MODE_PREV, "mode:prev"},
60         {KBD_FUNC_MODE_SELECT, "mode:"},
61
62         {KBD_FUNC_EXIT, "exit"},
63         {KBD_FUNC_MENU, "menu"},
64         {KBD_FUNC_NONE, NULL}
65 };
66
67
68 /* vars for key press state */
69 gboolean fvkbd_has_key_held = FALSE;
70
71 static gboolean fvkbd_key_parse_xml (FvkbdUnit *unit, FvkbdParser *parser);
72 static gint fvkbd_key_get_size (FvkbdUnit *unit, gint *w, gint *h);
73 static gint fvkbd_key_set_size (FvkbdUnit *unit, gint w, gint h);
74 static gint fvkbd_key_get_position (FvkbdUnit *unit, gint *x, gint *y);
75 static gint fvkbd_key_set_position (FvkbdUnit *unit, gint x, gint y);
76
77
78 static void
79 action_free_func(KbdFuncInfo *func)
80 {
81         switch (func->type) {
82         case KBD_FUNC_MODE_SELECT:
83                 g_free(func->data);
84         default:
85                 break;
86         }
87 }
88
89
90 static void
91 action_free_font_info(FvkbdKeyAction *action)
92 {
93         int i;
94
95         for (i = 0; i < KBD_FONT_TYPE_NUMBER; i++) {
96                 if (action->font[i]) {
97                         g_free(action->font[i]->family);
98                         g_free(action->font[i]->weight);
99                 }
100
101                 g_free(action->font[i]);
102                 action->font[i] = NULL;
103         }
104 }
105
106
107 static void
108 fvkbd_key_action_free(FvkbdKeyAction *action)
109 {
110         switch (action->type) {
111         case KEY_ACTION_STRING:
112         case KEY_ACTION_SCRIPT:
113
114                 g_free(action->u.string);
115                 break;
116
117         case KEY_ACTION_STRING_GROUP:
118                 g_strfreev(action->u.string_group);
119                 break;
120
121         case KEY_ACTION_FUNC:
122                 action_free_func(&(action->u.func));
123                 break;
124
125         case KEY_ACTION_SYM:
126                 break;
127
128         default:
129                 break;
130         }
131
132         g_free(action->disp);
133         g_free(action->sup_label);
134         g_free(action->img);
135         g_free(action->img_dn);
136
137         if (G_UNLIKELY(action->unique_font == TRUE))
138                 action_free_font_info(action);
139
140         g_free(action);
141
142 }
143
144
145 static void
146 fvkbd_key_finalize (GObject *object)
147 {
148         FvkbdKey *key = FVKBD_KEY(object);
149         FvkbdKeyPrivate *priv = FVKBD_KEY_GET_PRIVATE(key);
150         GSList *tmp;
151
152         if (FVKBD_UNIT_HAS_KEY_SHAPE_INFO(object)) {
153                 FVKBD_UNIT_UNSET_FLAG(FVKBD_UNIT(object), FLAG_KEY_SHAPE_INFO);
154                 fvkbd_unit_set_qdata(FVKBD_UNIT(object), quark_key_shape_info, NULL, NULL);
155         }
156
157         if (FVKBD_UNIT_HAS_KEY_BG_FILE(object)) {
158                 FVKBD_UNIT_UNSET_FLAG(FVKBD_UNIT(object), FLAG_KEY_BG_FILE);
159                 fvkbd_unit_set_qdata(FVKBD_UNIT(object), quark_key_bg_file, NULL, NULL);
160         }
161
162         for (tmp = priv->actions; tmp; tmp = tmp->next)
163                 fvkbd_key_action_free(tmp->data);
164
165         g_slist_free(priv->actions);
166         priv->actions = NULL;
167
168         G_OBJECT_CLASS(fvkbd_key_parent_class)->finalize(object);
169 }
170
171
172 static void
173 fvkbd_key_class_init (FvkbdKeyClass *klass)
174 {
175         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
176         FvkbdUnitClass *unit_class = FVKBD_UNIT_CLASS(klass);
177
178         g_type_class_add_private(klass, sizeof(FvkbdKeyPrivate));
179
180         gobject_class->finalize = fvkbd_key_finalize;
181
182         unit_class->parse_xml = fvkbd_key_parse_xml;
183         unit_class->get_size = fvkbd_key_get_size;
184         unit_class->set_size = fvkbd_key_set_size;
185         unit_class->get_position = fvkbd_key_get_position;
186         unit_class->set_position = fvkbd_key_set_position;
187 }
188
189
190 static void
191 fvkbd_key_init (FvkbdKey *self)
192 {
193         FvkbdKeyPrivate *priv;
194         FvkbdUnit *unit = FVKBD_UNIT(self);
195         priv = FVKBD_KEY_GET_PRIVATE(self);
196
197         fvkbd_set_unit_type(unit, UNIT_TYPE_KEY);
198 }
199
200
201 FvkbdUnit *
202 fvkbd_key_new (void)
203 {
204         return g_object_new(FVKBD_TYPE_KEY, NULL);
205 }
206
207
208 FvkbdKeyAction *
209 key_action_find_by_id (GSList *lists, gint id)
210 {
211         gint i;
212         FvkbdKeyAction *current = NULL;
213
214         g_return_val_if_fail(lists != NULL, NULL);
215         
216         for (i = 0; i < g_slist_length(lists); i++) {
217                 current = (FvkbdKeyAction *)g_slist_nth_data(lists, i);
218                 if (current->mode_id == id)
219                         return current;
220         }
221
222         // if could not find the action with the id number, return the default action.
223         return g_slist_nth_data(lists, 0);
224 }
225
226
227 static gboolean
228 key_actions_insert_sort_unique (GSList **lists_p, FvkbdKeyAction *action)
229 {
230         gint i;
231         gboolean ret = TRUE;
232         FvkbdKeyAction *current = NULL;
233
234         g_return_val_if_fail(lists_p != NULL, FALSE);
235         
236         for (i = 0; i < g_slist_length(*lists_p); i++) {
237                 current = (FvkbdKeyAction *)g_slist_nth_data(*lists_p, i);
238                 if (current->mode_id    > action->mode_id)
239                         break;
240
241                 if (current->mode_id    == action->mode_id) {
242                         ret = FALSE;
243                         goto done;
244                 }
245         }
246
247         *lists_p = g_slist_insert(*lists_p, action, i);
248 done:
249         return ret;
250 }
251
252
253 static KbdFuncType
254 action_str_to_func (FvkbdKeyAction *action, gchar *name)
255 {
256         KeyFuncName *p;
257         int id;
258         KbdFuncType ret = KBD_FUNC_NONE;
259
260         for (p = key_func_names; p->name != NULL; p++) {
261                 if (!strncmp(name, p->name, strlen(p->name))) {
262                         ret = p->type;
263                         break;
264                 }
265         }
266
267         // continue to handle some special cases
268         switch (ret) {
269         case KBD_FUNC_MODE_SELECT:
270                 id = atoi(&name[5]);
271                 if (id < 0) {
272                         ret = KBD_FUNC_NONE;
273                         break;
274                 }
275
276                 action->u.func.data = g_new0(int, 1);
277                 *((int *)(action->u.func.data)) = id;
278                 break;
279         default:
280                 break;
281         }
282
283         action->u.func.type = ret;
284         return ret;
285 }
286
287
288 static gint
289 key_parse_action (FvkbdUnit *unit, FvkbdParser *parser, void *data)
290 {
291         FvkbdKey *key = FVKBD_KEY(unit);
292         FvkbdKeyPrivate *priv = FVKBD_KEY_GET_PRIVATE(key);
293         FvkbdKeyAction *action = NULL;
294         KbdFontInfo *font;
295         gchar *tmp_str = NULL;
296         gint id;
297         gint ret = FALSE;
298
299         action = g_new0(FvkbdKeyAction, 1);
300
301         /* parsing mode_id attr */
302         if ((tmp_str = fvkbd_parser_get_attribute(parser, "mode_id")) == NULL) {
303                 id = 0;
304         } else {
305                 id = atoi(tmp_str);
306                 if (id < 0) {
307                         fvkbd_parser_set_error(parser, "Invalid value for mode_id");
308                         goto done;
309                 }
310         }
311
312         action->mode_id = id;
313         g_free(tmp_str);
314
315         /* parsing type attr */
316         if ((tmp_str = fvkbd_parser_get_attribute(parser, "type")) == NULL) {
317                 action->type = KEY_ACTION_STRING;
318         } else if (!g_strcmp0(tmp_str, "sym")) {
319                 action->type = KEY_ACTION_SYM;
320         } else if (!g_strcmp0(tmp_str, "string")) {
321                 action->type = KEY_ACTION_STRING;
322         } else if (!g_strcmp0(tmp_str, "strings")) {
323                 action->type = KEY_ACTION_STRING_GROUP;
324         } else if (!g_strcmp0(tmp_str, "func")) {
325                 action->type = KEY_ACTION_FUNC;
326         } else if (!g_strcmp0(tmp_str, "script")) {
327                 action->type = KEY_ACTION_SCRIPT;
328         } else {
329                 fvkbd_parser_set_error(parser, "Invalid value for type");
330                 goto done;
331         }
332
333         g_free(tmp_str);
334
335         /* parsing disp attr */
336         tmp_str = fvkbd_parser_get_attribute(parser, "disp");
337         action->disp = g_strdup(tmp_str);
338         g_free(tmp_str);
339
340         /* parsing superscript label attr */
341         tmp_str = fvkbd_parser_get_attribute(parser, "sup_label");
342         action->sup_label = g_strdup(tmp_str);
343         g_free(tmp_str);
344
345         /* parsing img attr */
346         tmp_str = fvkbd_parser_get_attribute(parser, "img");
347         if (tmp_str != NULL) {
348                 action->img = locate_img_file(tmp_str);
349         } else {
350                 action->img = g_strdup(tmp_str);
351         }
352         g_free(tmp_str);
353
354         /* parsing img_dn attr */
355         tmp_str = fvkbd_parser_get_attribute(parser, "img_dn");
356         if (tmp_str != NULL) {
357                 action->img_dn = locate_img_file(tmp_str);
358         } else {
359                 action->img_dn = g_strdup(tmp_str);
360         }
361         g_free(tmp_str);
362
363         // parsing font attr
364         tmp_str = fvkbd_parser_get_attribute(parser, "font");
365         if (G_UNLIKELY(tmp_str)) {
366                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_NORMAL),
367                                 kbd_get_default_font_weight(KBD_FONT_TYPE_NORMAL),
368                                 kbd_get_default_font_size(KBD_FONT_TYPE_NORMAL));
369
370                 action->font[KBD_FONT_TYPE_NORMAL] = font;
371                 action->unique_font = TRUE;
372         }
373         g_free(tmp_str);
374
375         tmp_str = fvkbd_parser_get_attribute(parser, "efont");
376         if (G_UNLIKELY(tmp_str)) {
377                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_EXTRA),
378                                 kbd_get_default_font_weight(KBD_FONT_TYPE_EXTRA),
379                                 kbd_get_default_font_size(KBD_FONT_TYPE_EXTRA));
380
381                 action->font[KBD_FONT_TYPE_EXTRA] = font;
382                 action->unique_font = TRUE;
383         }
384         g_free(tmp_str);
385
386         tmp_str = fvkbd_parser_get_attribute(parser, "ofont");
387         if (G_UNLIKELY(tmp_str)) {
388                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_POP),
389                                 kbd_get_default_font_weight(KBD_FONT_TYPE_POP),
390                                 kbd_get_default_font_size(KBD_FONT_TYPE_POP));
391
392                 action->font[KBD_FONT_TYPE_POP] = font;
393                 action->unique_font = TRUE;
394         }
395         g_free(tmp_str);
396
397
398         /* read action's content */
399         if ((tmp_str = fvkbd_parser_element_get_content(parser)) == NULL) {
400                 fvkbd_parser_set_error(parser, "Missing content");
401                 goto done;
402         }
403
404         switch (action->type) {
405         case KEY_ACTION_STRING:
406         case KEY_ACTION_SCRIPT:
407                 if (!g_utf8_validate(tmp_str, -1, NULL)) {
408                         fvkbd_parser_set_error(parser, "Not a valid utf8 string");
409                         goto done;
410                 }
411
412                 action->u.string = g_strdup(tmp_str);
413                 break;
414
415         case KEY_ACTION_STRING_GROUP:
416                 if (!g_utf8_validate(tmp_str, -1, NULL)) {
417                         fvkbd_parser_set_error(parser, "Not a valid utf8 string");
418                         goto done;
419                 }
420
421                 action->u.string_group = g_strsplit(tmp_str, " ", 0);
422
423                 break;
424
425         case KEY_ACTION_SYM:
426                 {
427                         KeySym sym = XStringToKeysym(tmp_str);
428                         if (sym == NoSymbol) {
429                                 gchar *errmsg = g_strconcat("Unrecognized key sym : ", tmp_str, NULL);
430                                 fvkbd_parser_set_error(parser, errmsg);
431                                 g_free(errmsg);
432                                 goto done;
433                         }
434
435                         action->u.sym = sym;
436                         break;
437                 }
438
439         case KEY_ACTION_FUNC:
440                 if ((action_str_to_func(action, tmp_str)) == KBD_FUNC_NONE) {
441                         gchar *errmsg = g_strconcat("Unrecognized function : ", tmp_str, NULL);
442                         fvkbd_parser_set_error(parser, errmsg);
443                         g_free(errmsg);
444                         goto done;
445                 }
446
447                 break;
448
449         default:
450                 break;
451         }
452
453
454         if (key_actions_insert_sort_unique(&priv->actions, action) == FALSE) {
455                 fvkbd_parser_set_error(parser, "Invalid action");
456                 goto done;
457         }
458
459         ret = TRUE;
460 done:
461         g_free(tmp_str);
462         return ret;
463 }
464
465
466 static UnitParserFunc key_element_parsers[] = {
467         {"action", key_parse_action},
468         {NULL}
469 };
470
471
472 static gboolean
473 fvkbd_key_parse_xml (FvkbdUnit *unit, FvkbdParser *parser)
474 {
475         FvkbdKey *key;
476         FvkbdKeyPrivate *priv;
477         gchar *tmp_str = NULL;
478         KbdFontInfo *font;
479         gint value;
480         UnitParserFunc *pfp;
481         gint ret = FALSE;
482
483         g_return_val_if_fail(FVKBD_IS_KEY(unit), FALSE);
484         key = FVKBD_KEY(unit);
485         priv = FVKBD_KEY_GET_PRIVATE(key);
486
487         // parsing x/y attr
488         if ((tmp_str = fvkbd_parser_get_attribute(parser, "x")) == NULL) {
489                 priv->x = 0;
490         } else {
491                 value = atoi(tmp_str);
492                 if (value < 0)
493                         value = 0;
494                 priv->x = value;
495         }
496
497         g_free(tmp_str);
498         if ((tmp_str = fvkbd_parser_get_attribute(parser, "y")) == NULL) {
499                 priv->y = 0;
500         } else {
501                 value = atoi(tmp_str);
502                 if (value < 0)
503                         value = 0;
504                 priv->y = value;
505         }
506
507         // parsing width/height attr
508         g_free(tmp_str);
509         if ((tmp_str = fvkbd_parser_get_attribute(parser, "width")) == NULL) {
510                 priv->width = KEY_DEFAULT_WIDTH;
511         } else {
512                 value = atoi(tmp_str);
513                 if (value < 0){
514                         fvkbd_parser_set_error(parser, "Invalid value for width");
515                         goto done;
516                 }
517
518                 priv->width = value;
519         }
520
521         g_free(tmp_str);
522         if ((tmp_str = fvkbd_parser_get_attribute(parser, "height")) == NULL) {
523                 priv->height = KEY_DEFAULT_HEIGHT;
524         } else {
525                 value = atoi(tmp_str);
526                 if (value < 0) {
527                         fvkbd_parser_set_error(parser, "Invalid value for height");
528                         goto done;
529                 }
530
531                 priv->height = value;
532         }
533
534         /* parsing bg_img attr */
535         g_free(tmp_str);
536         tmp_str = fvkbd_parser_get_attribute(parser, "bg_img");
537         if (tmp_str != NULL) {
538                 gchar *bg_file;
539                 if ((bg_file = locate_img_file(tmp_str)) != NULL) {
540                         fvkbd_unit_set_qdata(unit, quark_key_bg_file, bg_file,
541                                         (GDestroyNotify)g_free);
542                         FVKBD_UNIT_SET_FLAG(unit, FLAG_KEY_BG_FILE);
543                 }
544         }
545
546         // parsing color attr
547         g_free(tmp_str);
548         if ((tmp_str = fvkbd_parser_get_attribute(parser, "bgcolor")) != NULL)
549                 fvkbd_unit_set_color(unit, KBD_COLOR_TYPE_KEY_BG, kbd_str_to_color(tmp_str));
550
551         g_free(tmp_str);
552         if ((tmp_str = fvkbd_parser_get_attribute(parser, "fgcolor")) != NULL)
553                 fvkbd_unit_set_color(unit, KBD_COLOR_TYPE_KEY_FG, kbd_str_to_color(tmp_str));
554
555         g_free(tmp_str);
556         if ((tmp_str = fvkbd_parser_get_attribute(parser, "extra_fgcolor")) != NULL)
557                 fvkbd_unit_set_color(unit, KBD_COLOR_TYPE_KEY_EXTRA_FG, kbd_str_to_color(tmp_str));
558
559         g_free(tmp_str);
560         if ((tmp_str = fvkbd_parser_get_attribute(parser, "pop_bgcolor")) != NULL)
561                 fvkbd_unit_set_color(unit, KBD_COLOR_TYPE_KEY_POP_BG, kbd_str_to_color(tmp_str));
562
563         g_free(tmp_str);
564         if ((tmp_str = fvkbd_parser_get_attribute(parser, "pop_fgcolor")) != NULL)
565                 fvkbd_unit_set_color(unit, KBD_COLOR_TYPE_KEY_POP_FG, kbd_str_to_color(tmp_str));
566
567         // parsing font attr
568         g_free(tmp_str);
569         tmp_str = fvkbd_parser_get_attribute(parser, "font");
570         if (tmp_str) {
571                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_NORMAL),
572                                 kbd_get_default_font_weight(KBD_FONT_TYPE_NORMAL),
573                                 kbd_get_default_font_size(KBD_FONT_TYPE_NORMAL));
574
575                 fvkbd_unit_set_font(unit, KBD_FONT_TYPE_NORMAL, font);
576         }
577
578         g_free(tmp_str);
579         tmp_str = fvkbd_parser_get_attribute(parser, "efont");
580         if (tmp_str) {
581                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_EXTRA),
582                                 kbd_get_default_font_weight(KBD_FONT_TYPE_EXTRA),
583                                 kbd_get_default_font_size(KBD_FONT_TYPE_EXTRA));
584
585                 fvkbd_unit_set_font(unit, KBD_FONT_TYPE_EXTRA, font);
586         }
587
588         g_free(tmp_str);
589         tmp_str = fvkbd_parser_get_attribute(parser, "ofont");
590         if (tmp_str) {
591                 font = parse_font_property(tmp_str, kbd_get_default_font_family(KBD_FONT_TYPE_POP),
592                                 kbd_get_default_font_weight(KBD_FONT_TYPE_POP),
593                                 kbd_get_default_font_size(KBD_FONT_TYPE_POP));
594
595                 fvkbd_unit_set_font(unit, KBD_FONT_TYPE_POP, font);
596         }
597
598         /* parsing show_pop attr  */
599         g_free(tmp_str);
600         tmp_str = fvkbd_parser_get_attribute(parser, "pop");
601         if (tmp_str != NULL) {
602                 if (!g_strcmp0(tmp_str, "none")) {
603                         priv->disable_pop = TRUE;
604                 }
605         }
606
607         /* parsing shape attr */
608         g_free(tmp_str);
609         tmp_str = fvkbd_parser_get_attribute(parser, "shape");
610         if (tmp_str != NULL) {
611                 KbdShapeInfo *shape_info;
612
613                 shape_info = parse_shape_info_property(tmp_str);
614                 if (!shape_info) {
615                         fvkbd_parser_set_error(parser, "Invalid shape type");
616                         goto done;
617                 }
618
619                 /* parsing detail shape data */
620                 g_free(tmp_str);
621                 tmp_str = fvkbd_parser_get_attribute(parser, "shape_data");
622                 parse_shape_data_property(shape_info, tmp_str);
623
624                 if (shape_info->shape_type != KBD_SHAPE_NULL) {
625                         fvkbd_unit_set_qdata(unit, quark_key_shape_info, shape_info,
626                                                 (GDestroyNotify)kbd_shape_info_destroy);
627                         FVKBD_UNIT_SET_FLAG(unit, FLAG_KEY_SHAPE_INFO);
628                 } else {
629                         g_slice_free(KbdShapeInfo, shape_info);
630                 }
631         }
632
633         // parsing children elements
634         if (!fvkbd_parser_go_child_element(parser)) {
635                 fvkbd_parser_set_error(parser, "Missing children");
636                 goto done;
637         }
638
639         do {
640                 for (pfp = key_element_parsers; pfp->node_name != NULL; pfp++) {
641                         if (!fvkbd_parser_element_match(parser, pfp->node_name))
642                                 continue;
643
644                         if (pfp->parser(unit, parser, NULL) != TRUE)
645                                 goto done;
646
647                         break;
648                 }
649
650                 if (pfp->node_name == NULL) {
651                         fvkbd_parser_set_error(parser, "Unknown Element");
652                         goto done;
653                 }
654
655         } while (fvkbd_parser_element_next(parser));
656
657         if(priv->actions == NULL) {
658                 fvkbd_parser_set_error(parser, "no action found");
659                 goto done;
660         }
661
662         if (((FvkbdKeyAction *)g_slist_nth_data(priv->actions, 0))->mode_id != 0) {
663                 fvkbd_parser_set_error(parser, "Need to have a default action for mode_id \"0\"\n");
664                 goto done;
665         }
666
667         ret = TRUE;
668 done:
669         g_free(tmp_str);
670         fvkbd_parser_go_parent_element(parser);
671         return ret;
672 }
673
674
675 static gint
676 fvkbd_key_get_size (FvkbdUnit *unit, gint *w, gint *h)
677 {
678         FvkbdKey *key;
679         FvkbdKeyPrivate *priv;
680
681         g_return_val_if_fail(FVKBD_IS_KEY(unit), -1);
682         key = FVKBD_KEY(unit);
683         priv = FVKBD_KEY_GET_PRIVATE(key);
684
685         *w = priv->width;
686         *h = priv->height;
687
688         return 0;
689 }
690
691
692 static gint
693 fvkbd_key_set_size (FvkbdUnit *unit, gint w, gint h)
694 {
695         FvkbdKey *key;
696         FvkbdKeyPrivate *priv;
697
698         g_return_val_if_fail(FVKBD_IS_KEY(unit), -1);
699         key = FVKBD_KEY(unit);
700         priv = FVKBD_KEY_GET_PRIVATE(key);
701
702         priv->width = w;
703         priv->height = h;
704
705         return 0;
706 }
707
708
709 static gint
710 fvkbd_key_get_position (FvkbdUnit *unit, gint *x, gint *y)
711 {
712         FvkbdKey *key;
713         FvkbdKeyPrivate *priv;
714
715         g_return_val_if_fail(FVKBD_IS_KEY(unit), -1);
716         key = FVKBD_KEY(unit);
717         priv = FVKBD_KEY_GET_PRIVATE(key);
718
719         *x = priv->x;
720         *y = priv->y;
721
722         return 0;
723 }
724
725
726 static gint
727 fvkbd_key_set_position (FvkbdUnit *unit, gint x, gint y)
728 {
729         FvkbdKey *key;
730         FvkbdKeyPrivate *priv;
731
732         g_return_val_if_fail(FVKBD_IS_KEY(unit), -1);
733         key = FVKBD_KEY(unit);
734         priv = FVKBD_KEY_GET_PRIVATE(key);
735
736         priv->x = x;
737         priv->y = y;
738
739         return 0;
740 }
741
742
743 gchar *
744 fvkbd_key_get_disp (FvkbdKey *self, gint id)
745 {
746         FvkbdKeyPrivate *priv;
747         FvkbdKeyAction *action;
748
749         g_return_val_if_fail(FVKBD_IS_KEY(self), NULL);
750
751         priv = FVKBD_KEY_GET_PRIVATE(self);
752
753         if ((action = key_action_find_by_id(priv->actions, id)) == NULL)
754                 return NULL;
755
756         return action->disp;
757 }
758
759
760 gchar *
761 fvkbd_key_get_image (FvkbdKey *self, gint id)
762 {
763         FvkbdKeyPrivate *priv;
764         FvkbdKeyAction *action;
765
766         g_return_val_if_fail(FVKBD_IS_KEY(self), NULL);
767
768         priv = FVKBD_KEY_GET_PRIVATE(self);
769
770         if ((action = key_action_find_by_id(priv->actions, id)) == NULL)
771                 return NULL;
772
773         return action->img;
774 }
775
776
777 void
778 fvkbd_key_send_utf8_string(gchar *string)
779 {
780         gint i,ret = 1;
781         gchar *p = string;
782
783         for (i = g_utf8_strlen(string, -1); i > 0; i--) {
784                 ret = fakekey_press(get_fakekey_instance(),
785                                 (unsigned char *)p, -1, 0);
786                 fakekey_release(get_fakekey_instance());
787
788                 if (ret == 0)
789                         break;
790
791                 p = g_utf8_find_next_char(p, NULL);
792         }
793         DBG("action: send string: %s, result:%d\n", string, ret);
794 }
795
796
797 void
798 fvkbd_key_send_xkeysym(KeySym sym)
799 {
800         gint ret;
801
802         ret = fakekey_press_keysym(get_fakekey_instance(), sym, 0);
803         fakekey_release(get_fakekey_instance());
804         DBG("action: send sym: %x, result:%d\n", (unsigned int)sym, ret);
805 }
806
807
808 FvkbdKeyAction *
809 fvkbd_key_get_action(FvkbdKey *self, gint id)
810 {
811         FvkbdKeyPrivate *priv;
812
813         g_return_val_if_fail(FVKBD_IS_KEY(self), NULL);
814
815         priv = FVKBD_KEY_GET_PRIVATE(self);
816
817         return key_action_find_by_id(priv->actions, id);
818 }
819
820 inline gboolean
821 fvkbd_key_pop_notify_disabled(FvkbdKey *self)
822 {
823         FvkbdKeyPrivate *priv;
824         priv = FVKBD_KEY_GET_PRIVATE(self);
825
826         return priv->disable_pop;
827 }