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