Fine tune pop window
[fvkbd:fvkbd.git] / ui / gtk / fvkbd-key-ui-gtk.c
1 /*
2  * fvkbd-key-ui-gtk.c key unit gtk ui 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 <gtk/gtk.h>
26 #include "fvkbd.h"
27 #include "fvkbd-keyboard.h"
28 #include "misc-utility.h"
29 #include "gtk-misc-utility.h"
30 #include "gtk-vkb-button.h"
31
32 #include "fvkbd-pop-win.h"
33 #include "fvkbd-key.h"
34
35
36 typedef struct _KeyUI KeyUI;
37 struct _KeyUI {
38         GtkWidget *main_label;
39         GtkWidget *sub_label;
40         GtkWidget *img;
41
42         PangoFontDescription *font_desc;
43         PangoFontDescription *efont_desc;
44         PangoFontDescription *ofont_desc;
45 };
46
47
48 static gboolean key_mode_do_switch_lock = FALSE;
49
50 static guint longpress_timeout_id = 0;
51 static guint longpress_timeout_val = 800;
52 static guint pop_window_hide_timeout_id = 0;
53 static guint pop_window_hide_timeout_val = 5000;
54
55 static void settle_pop_window(FvkbdKey *key, gint number, gboolean reverse);
56 static void show_pop_window(FvkbdKey *key, gboolean longpress);
57 static void hide_pop_window(void);
58 static gboolean hide_pop_window_cb(FvkbdKey *key);
59 static gboolean longpress_detected_cb(FvkbdKey *key);
60 static PangoFontDescription * get_key_pango_font_description (FvkbdUnit *unit, KbdFontType type);
61
62
63 static void
64 settle_pop_window(FvkbdKey *key, gint number, gboolean reverse)
65 {
66         GtkWidget *w = get_pop_window();
67         GdkWindow *keywindow;
68
69         int pop_w = 0, pop_h = 0;
70         int x, y;
71         int ux, uy, uw, uh;
72         int ww, wh;
73         gfloat x_ratio, y_ratio;
74         GtkWidget *key_widget;
75
76         key_widget = fvkbd_unit_get_widget(FVKBD_UNIT(key));
77         keywindow = gtk_widget_get_window(key_widget);
78
79         gdk_window_get_origin(keywindow, &x, &y);
80         gtk_window_get_size(GTK_WINDOW(w), &pop_w, &pop_h);
81
82         /* If key_widget don't have it's own gdk window, then gdk_window_get_origin will get the position
83             of it's parent window, say panel window, then we need to do some offset to gain the right position */
84         if (GTK_WIDGET_NO_WINDOW(key_widget)) {
85                 fvkbd_unit_get_position(FVKBD_UNIT(key), &ux, &uy);
86         } else {
87                 ux = 0;
88                 uy = 0;
89         }
90
91         if ((fvkbd_unit_get_size(FVKBD_UNIT(key), &uw, &uh) == 0) &&
92                 (fvkbd_unit_get_ratio(FVKBD_UNIT(key), &x_ratio, &y_ratio) == 0)) {
93
94                 gtk_window_get_size(GTK_WINDOW(w), &ww, &wh);
95
96                 if (!reverse) {
97                         x += (ux * x_ratio);
98                 } else {
99                         x += ((ux + uw) * x_ratio - ww);
100                 }
101
102                 y += ((uy * y_ratio) - (wh - (uh * y_ratio)) / 2);
103         }
104
105         gtk_window_move(GTK_WINDOW(w), x, y);
106 }
107
108
109 static void
110 show_pop_window(FvkbdKey *key, gboolean longpress)
111 {
112         FvkbdKeyAction *action;
113         GtkWidget *w = get_pop_window();
114         GdkColor bgcolor, fgcolor;
115         int item_number = 1;
116         int i;
117         int ux, uy, uw, uh, pw, ph;
118         gfloat x_ratio, y_ratio;
119         gboolean reverse = FALSE;
120
121         fvkbd_unit_get_size(fvkbd_unit_get_parent(FVKBD_UNIT(key)), &pw, &ph);
122         if ((fvkbd_unit_get_position(FVKBD_UNIT(key), &ux, &uy) == 0)) {
123                 if (ux <= (pw / 2))
124                         reverse = FALSE;
125                 else
126                         reverse = TRUE;
127         }
128
129         fvkbd_unit_get_ratio(FVKBD_UNIT(key), &x_ratio, &y_ratio);
130         fvkbd_unit_get_size(FVKBD_UNIT(key), &uw, &uh);
131
132         action = fvkbd_key_get_current_action(key);
133         KeyUI *ui_data = fvkbd_unit_get_ui_data(FVKBD_UNIT(key));
134         PangoFontDescription *desc;
135
136         if (!ui_data->ofont_desc) {
137                 desc = get_key_pango_font_description(FVKBD_UNIT(key), KBD_FONT_TYPE_POP);
138         } else
139                 desc = ui_data->ofont_desc;
140
141         switch (action->type) {
142
143         case KEY_ACTION_STRING:
144                 update_pop_win_item_string(action->disp, action->u.string, desc, reverse);
145                 item_number = 2;
146                 break;
147
148         case KEY_ACTION_STRING_GROUP:
149                 if (!longpress) {
150                         update_pop_win_item_string(action->disp, action->u.string, desc, reverse);
151                         item_number = 2;
152                 } else {
153                         update_pop_win_item_string_group(action->u.string_group, desc, reverse);
154                         for (i = 0; (i < MAX_POP_WIN_ITEMS) && *(action->u.string_group + i); i++)
155                                 item_number++;
156                 }
157                 break;
158
159         case KEY_ACTION_SYM:
160                 update_pop_win_item_sym(action->disp, action->u.sym, desc, reverse);
161                 item_number = 2;
162                 break;
163
164         default:
165                 update_pop_win_item_none();
166                 hide_pop_window();
167                 return;
168         }
169
170         set_pop_win_items_size(uw * x_ratio, uh * y_ratio);
171
172         get_gdkcolor(FVKBD_UNIT(key), KBD_COLOR_TYPE_KEY_POP_BG, &bgcolor);
173         get_gdkcolor(FVKBD_UNIT(key), KBD_COLOR_TYPE_KEY_POP_FG, &fgcolor);
174
175         settle_pop_window_color(item_number, &bgcolor, &fgcolor);
176         // well, hiding pop window here, just wish the window size will be retrived
177         // correctly by gtk_window_get_size later in settle_pop_window.
178         hide_pop_window();
179         settle_pop_window(key, item_number, reverse);
180         if (!GTK_WIDGET_VISIBLE(w))
181                 gtk_widget_show(w);
182 }
183
184
185 static void
186 hide_pop_window(void)
187 {
188         GtkWidget *w = get_pop_window();
189         if (GTK_WIDGET_VISIBLE(w))
190                 gtk_widget_hide(w);
191 }
192
193
194 static gboolean
195 hide_pop_window_cb(FvkbdKey *key)
196 {
197         hide_pop_window();
198         pop_window_hide_timeout_id = 0;
199         
200         return FALSE;
201 }
202
203
204 static gboolean
205 longpress_detected_cb(FvkbdKey *key)
206 {
207         FvkbdKeyAction *action;
208
209         action = fvkbd_key_get_current_action(key);
210
211         switch (action->type) {
212
213         case KEY_ACTION_STRING:
214         case KEY_ACTION_SYM:
215                 show_pop_window(key, TRUE);
216                 break;
217
218         case KEY_ACTION_STRING_GROUP:
219                 show_pop_window(key, TRUE);
220                 pop_window_hide_timeout_id = g_timeout_add(pop_window_hide_timeout_val,
221                                                 (GSourceFunc)hide_pop_window_cb, key);
222
223                 break;
224
225         case KEY_ACTION_FUNC:
226                 switch (action->u.func.type) {
227                 case FVKBD_KEY_FUNC_MODE_SELECT:
228                         key_mode_do_switch_lock = TRUE;
229                         break;
230
231                 default:
232                         break;
233                 }
234
235                 break;
236         default:
237                 break;
238         }
239
240         longpress_timeout_id = 0;
241         
242         return FALSE;
243 }
244
245
246 static void
247 fvkbd_key_gtk_pressed_cb(GtkButton *button, FvkbdKey *key)
248 {
249         if (longpress_timeout_id != 0) {
250                 g_source_remove(longpress_timeout_id);
251                 longpress_timeout_id = 0;
252         }
253
254         if (pop_window_hide_timeout_id != 0) {
255                 g_source_remove(pop_window_hide_timeout_id);
256                 pop_window_hide_timeout_id = 0;
257                 hide_pop_window();
258         }
259
260         longpress_timeout_id = g_timeout_add(longpress_timeout_val,
261                                         (GSourceFunc)longpress_detected_cb, key);
262
263         show_pop_window(key, FALSE);
264 }
265
266
267 static void
268 fvkbd_key_gtk_released_cb(GtkButton *button, FvkbdKey *key)
269 {
270         FvkbdKeyAction *action;
271         gboolean need_reset_default_mode = TRUE;
272
273         /* if the candiate window is shown, then we do nothing and return */
274         if (pop_window_hide_timeout_id != 0) {
275                 return;
276         }
277
278         if (longpress_timeout_id != 0) {
279                 g_source_remove(longpress_timeout_id);
280                 longpress_timeout_id = 0;
281         }
282
283         hide_pop_window();
284
285         if ((action = fvkbd_key_get_current_action(key)) == NULL)
286                 return;
287
288         switch (action->type) {
289         case KEY_ACTION_STRING:
290                 fvkbd_key_send_utf8_string(action->u.string);
291                 break;
292
293         case KEY_ACTION_STRING_GROUP:
294                 fvkbd_key_send_utf8_string(action->u.string_group[0]);
295                 break;
296
297         case KEY_ACTION_SYM:
298                 fvkbd_key_send_xkeysym(action->u.sym);
299                 break;
300
301         case KEY_ACTION_FUNC:
302                 switch (action->u.func.type) {
303                 case FVKBD_KEY_FUNC_MODE_SELECT:
304                         fvkbd_key_func_handlers(key, action, &key_mode_do_switch_lock);
305                         need_reset_default_mode = FALSE;
306                         key_mode_do_switch_lock = FALSE;
307                         break;
308
309                 default:
310                         fvkbd_key_func_handlers(key, action, NULL);
311                 }
312
313                 break;
314
315         case KEY_ACTION_SCRIPT:
316                 fvkbd_do_script(action->u.string);
317                 break;
318
319         default:
320                 break;
321         }
322
323         if (fvkbd_in_temp_mode() && need_reset_default_mode)
324                 fvkbd_keyboard_resume_default_mode();
325
326 }
327
328
329 static void
330 fvkbd_key_settle_color (FvkbdUnit *unit, GtkWidget *key_widget, gboolean lock)
331 {
332         KeyUI *ui_data = fvkbd_unit_get_ui_data(unit);
333         GdkColor color;
334         GtkWidget *label;
335
336         // set key background color
337         if (!lock) {
338                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_BG, &color)) {
339                         vkb_button_set_bg(key_widget, GTK_STATE_NORMAL, &color);
340                         vkb_button_set_bg(key_widget, GTK_STATE_PRELIGHT, &color);
341                 }
342
343                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_FG, &color)) {
344                         vkb_button_set_bg(key_widget, GTK_STATE_ACTIVE, &color);
345                 }
346         } else {
347                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_FG, &color)) {
348                         vkb_button_set_bg(key_widget, GTK_STATE_NORMAL, &color);
349                         vkb_button_set_bg(key_widget, GTK_STATE_PRELIGHT, &color);
350                 }
351
352                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_BG, &color)) {
353                         vkb_button_set_bg(key_widget, GTK_STATE_ACTIVE, &color);
354                 }
355         }
356
357         // set main label color
358         label = ui_data->main_label;
359         if (label) {
360                 if (!lock) {
361                         if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_FG, &color)) {
362                                 gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
363                                 gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &color);
364                         }
365
366                         if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_BG, &color)) {
367                                 gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &color);
368                         }
369                 } else {
370                         if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_BG, &color)) {
371                                 gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
372                                 gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &color);
373                         }
374
375                         if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_FG, &color)) {
376                                 gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &color);
377                         }
378                 }
379         }
380
381         // set sub label color
382         label = ui_data->sub_label;
383         if (label) {
384                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_EXTRA_FG, &color)) {
385                         gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
386                         gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &color);
387                 }
388
389                 if (get_gdkcolor(unit, KBD_COLOR_TYPE_KEY_BG, &color)) {
390                         gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &color);
391                 }
392         }
393 }
394
395
396 static PangoFontDescription *
397 get_key_pango_font_description (FvkbdUnit *unit, KbdFontType type)
398 {
399         gfloat x_ratio, y_ratio, ratio;
400         int dpi_xres, dpi_yres;
401         KeyUI *ui_data = fvkbd_unit_get_ui_data(unit);
402         gchar *font_family = fvkbd_key_get_font_family(unit, type);
403         gchar *font_weight = fvkbd_key_get_font_weight(unit, type);
404         gint font_size = fvkbd_key_get_font_size(unit, type);
405
406         PangoFontDescription *desc = NULL;
407
408         fvkbd_unit_get_ratio(unit, &x_ratio, &y_ratio);
409         get_resolution(&dpi_xres, &dpi_yres);
410
411         x_ratio = x_ratio * DEFAULT_DPI / dpi_xres;
412         y_ratio = y_ratio * DEFAULT_DPI / dpi_yres;
413
414         ratio = (x_ratio < y_ratio) ? x_ratio : y_ratio;
415         font_size = font_size * ratio;
416
417         switch (type) {
418                 case KBD_FONT_TYPE_NORMAL:
419                         if (!ui_data->font_desc)
420                                 ui_data->font_desc = get_pango_font_description_from_info(font_family, font_weight, font_size);
421                         desc = ui_data->font_desc;
422                         break;
423
424                 case KBD_FONT_TYPE_EXTRA:
425                         if (!ui_data->efont_desc)
426                                 ui_data->efont_desc = get_pango_font_description_from_info(font_family, font_weight, font_size);
427                         desc = ui_data->efont_desc;
428                         break;
429
430                 case KBD_FONT_TYPE_POP:
431                         if (!ui_data->ofont_desc)
432                                 ui_data->ofont_desc = get_pango_font_description_from_info(font_family, font_weight, font_size);
433                         desc = ui_data->ofont_desc;
434                         break;
435
436                 default:
437                         break;
438         }
439
440         return desc;
441 }
442
443
444 static void
445 fvkbd_key_settle_font (FvkbdUnit *unit, GtkWidget *key_widget)
446 {
447         KeyUI *ui_data = fvkbd_unit_get_ui_data(unit);
448         PangoFontDescription *desc;
449         GtkWidget *label;
450
451         // set main label font
452         label = ui_data->main_label;
453         if (label) {
454                 if (!ui_data->font_desc) {
455                         desc = get_key_pango_font_description(unit, KBD_FONT_TYPE_NORMAL);
456                 } else
457                         desc = ui_data->font_desc;
458
459                 gtk_widget_modify_font(label, desc);
460         }
461
462         // set sub label font
463         label = ui_data->sub_label;
464         if (label) {
465                 if (!ui_data->efont_desc) {
466                         desc = get_key_pango_font_description(unit, KBD_FONT_TYPE_EXTRA);
467                 } else
468                         desc = ui_data->efont_desc;
469
470                         gtk_widget_modify_font(label, desc);
471         }
472 }
473
474
475 static GtkWidget *
476 _create_key_label (FvkbdUnit *unit, gint id)
477 {
478         FvkbdKey *key;
479         FvkbdKeyAction *action;
480         KeyUI *ui_data = fvkbd_unit_get_ui_data(unit);
481         gint w,h;
482         GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
483         GtkWidget *label = NULL, *sub_label = NULL, *img = NULL;
484
485         g_return_val_if_fail(FVKBD_IS_KEY(unit), FALSE);
486         key = FVKBD_KEY(unit);
487
488         fvkbd_unit_get_size(unit, &w, &h);
489
490         if ((action = fvkbd_key_get_current_action(key)) == NULL)
491                 goto done;
492
493         if (action->img != NULL) {
494                 img = gtk_image_new_from_file(action->img);
495                 goto done;
496         }
497
498         if (action->type == KEY_ACTION_STRING_GROUP) {
499                 gchar *label_str = NULL;
500
501                 #if 0
502                 // show all the optional characters
503                 label_str = g_strjoinv(" ", &(action->u.string_group[1]));
504                 #else
505                 // only show the first optional character
506                 label_str = g_strdup(action->u.string_group[1]);
507                 #endif
508
509                 sub_label = gtk_label_new(label_str);
510                 g_free(label_str);
511                 label = gtk_label_new(fvkbd_key_get_disp(key, id));
512         } else if (action->type == KEY_ACTION_STRING ||
513                 action->type == KEY_ACTION_SYM ||
514                 action->type == KEY_ACTION_FUNC ||
515                 action->type == KEY_ACTION_SCRIPT) {
516
517                 sub_label = gtk_label_new(NULL);
518                 label = gtk_label_new(fvkbd_key_get_disp(key, id));
519         }
520
521 done:
522
523         ui_data->sub_label = sub_label;
524         if (sub_label)
525                 gtk_box_pack_start(GTK_BOX(vbox), sub_label, FALSE, FALSE, 0);
526
527         ui_data->main_label = label;
528         if (label)
529                 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
530
531         ui_data->img = img;
532         if (img)
533                 gtk_box_pack_start(GTK_BOX(vbox), img, TRUE, TRUE, 0);
534
535         gtk_widget_show_all(vbox);
536         return vbox;
537 }
538
539
540 static void
541 _update_key_label (FvkbdUnit *unit, gint id)
542 {
543         GtkWidget *key_widget;
544         GtkWidget *key_label;
545
546         key_widget = fvkbd_unit_get_widget(unit);
547         
548         key_label = gtk_bin_get_child(GTK_BIN(key_widget));
549
550         if (key_label) {
551                 gtk_widget_destroy(key_label);
552                 key_label = NULL;
553         }
554
555         key_label = _create_key_label(unit, id);
556         gtk_container_add(GTK_CONTAINER(key_widget), key_label);
557 }
558
559
560 static void
561 _set_key_label_tmp_mode (FvkbdUnit *unit)
562 {
563         KeyUI *ui_data = fvkbd_unit_get_ui_data(unit);
564         GtkWidget *label;
565         gchar *disp;
566
567         label = ui_data->main_label;
568         disp = g_strconcat("<u>", gtk_label_get_text(GTK_LABEL(label)), "</u>", NULL);
569         gtk_label_set_text(GTK_LABEL(label), disp);
570         gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
571         g_free(disp);
572 }
573
574
575 gboolean
576 fvkbd_key_build_ui (FvkbdUnit *unit, gpointer *widget)
577 {
578         FvkbdKey *key;
579         KeyUI *ui_data;
580         gint w,h;
581         gboolean ret = TRUE;
582
583         GtkWidget *key_widget;
584         GtkWidget *key_label;
585
586         g_return_val_if_fail(FVKBD_IS_KEY(unit), FALSE);
587         key = FVKBD_KEY(unit);
588
589         key_widget = gtk_vkb_button_new();
590
591         ui_data = g_new0(KeyUI, 1);
592         fvkbd_unit_set_ui_data(unit, ui_data);
593         ui_data->main_label = NULL;
594         ui_data->sub_label = NULL;
595         ui_data->font_desc = NULL;
596         ui_data->efont_desc = NULL;
597         ui_data->ofont_desc = NULL;
598
599         fvkbd_unit_get_size(unit, &w, &h);
600         gtk_widget_set_size_request(key_widget, w, h);
601
602         key_label = _create_key_label(unit, 0);
603         gtk_container_add(GTK_CONTAINER(key_widget), key_label);
604
605         // set color
606         fvkbd_key_settle_color(unit, key_widget, FALSE);
607
608         // set font
609         fvkbd_key_settle_font(unit, key_widget);
610
611         g_signal_connect(G_OBJECT(key_widget), "pressed",
612                         G_CALLBACK(fvkbd_key_gtk_pressed_cb), key);
613         g_signal_connect(G_OBJECT(key_widget), "released",
614                         G_CALLBACK(fvkbd_key_gtk_released_cb), key);
615
616         if (widget != NULL)
617                 *widget = key_widget;
618         fvkbd_unit_set_widget(unit, key_widget);
619         return ret;
620 }
621
622
623 gboolean
624 fvkbd_key_resize_ui (FvkbdUnit *unit, gfloat x_ratio, gfloat y_ratio)
625 {
626         FvkbdKey *key;
627         KeyUI *ui_data;
628         GtkWidget *key_widget;
629         //GtkWidget *key_label;
630         int tmp_w, tmp_h;
631         int new_w, new_h;
632
633         g_return_val_if_fail(FVKBD_IS_KEY(unit), FALSE);
634         key = FVKBD_KEY(unit);
635
636         ui_data = fvkbd_unit_get_ui_data(unit);
637         key_widget = fvkbd_unit_get_widget(unit);
638
639         if (fvkbd_unit_get_size(unit, &tmp_w, &tmp_h) == 0) {
640                 new_w = tmp_w * x_ratio;
641                 new_h = tmp_h * y_ratio;
642                 gtk_widget_set_size_request(key_widget, new_w, new_h);
643
644         } else
645                 return FALSE;
646
647         if (ui_data->font_desc) {
648                 pango_font_description_free(ui_data->font_desc);
649                 ui_data->font_desc = NULL;
650         }
651         if (ui_data->efont_desc) {
652                 pango_font_description_free(ui_data->efont_desc);
653                 ui_data->efont_desc = NULL;
654         }
655         if (ui_data->ofont_desc) {
656                 pango_font_description_free(ui_data->ofont_desc);
657                 ui_data->ofont_desc = NULL;
658         }
659
660         fvkbd_unit_set_ratio(unit, x_ratio, y_ratio);
661         fvkbd_key_settle_font(unit, key_widget);
662
663         return TRUE;
664 }
665
666
667 gboolean
668 fvkbd_key_destroy_ui (FvkbdUnit *unit)
669 {
670         FvkbdKey *key;
671         KeyUI *ui_data;
672         gboolean ret = TRUE;
673
674         GtkWidget *key_widget;
675
676         g_return_val_if_fail(FVKBD_IS_KEY(unit), FALSE);
677         key = FVKBD_KEY(unit);
678
679         key_widget = fvkbd_unit_get_widget(unit);
680
681         gtk_widget_hide_all(key_widget);
682         gtk_widget_destroy(key_widget);
683
684         fvkbd_unit_set_widget(unit, NULL);
685
686         ui_data = fvkbd_unit_get_ui_data(unit);
687         if (ui_data->font_desc)
688                 pango_font_description_free(ui_data->font_desc);
689         if (ui_data->efont_desc)
690                 pango_font_description_free(ui_data->efont_desc);
691         if (ui_data->ofont_desc)
692                 pango_font_description_free(ui_data->ofont_desc);
693         g_free(ui_data);
694         fvkbd_unit_set_ui_data(unit, NULL);
695
696         return ret;
697 }
698
699
700 gint
701 fvkbd_key_set_mode (FvkbdUnit *unit, gint id)
702 {
703         FvkbdKey *key;
704         FvkbdKeyAction *action;
705         GtkWidget *key_widget;
706         gboolean show_lock_mode = FALSE;
707
708         g_return_val_if_fail(FVKBD_IS_KEY(unit), -1);
709         key = FVKBD_KEY(unit);
710
711         key_widget = fvkbd_unit_get_widget(unit);
712
713         // Yes, we get the default action here to handle disp diffirently for tmply mode change
714         action = fvkbd_key_get_action(key, 0);
715
716         if ((action->type == KEY_ACTION_FUNC) &&
717                 (action->u.func.type == FVKBD_KEY_FUNC_MODE_SELECT)) {
718                 if ((fvkbd_in_temp_mode()) && ((*((int *)action->u.func.data)) == id)) {
719                         _update_key_label(unit, 0);
720                         _set_key_label_tmp_mode(unit);
721                 } else {
722                         _update_key_label(unit, id);
723                         if ((*((int *)action->u.func.data)) == id)
724                                 show_lock_mode = TRUE;
725                 }
726         } else {
727                 _update_key_label(unit, id);
728         }
729
730         // set color
731         fvkbd_key_settle_color(unit, key_widget, show_lock_mode);
732
733         // set font
734         fvkbd_key_settle_font(unit, key_widget);
735
736         return 0;
737 }
738