Merge from TIZEN 2.3
[platform/core/uifw/e17.git] / src / modules / illume-keyboard / e_kbd_int.c
1 #include "e.h"
2 #include "e_kbd_buf.h"
3 #include "e_kbd_int.h"
4 #include "e_kbd_send.h"
5 #include "e_mod_config.h"
6
7 enum 
8 {
9    NORMAL = 0,
10    SHIFT = (1 << 0),
11    CAPSLOCK = (1 << 1),
12    CTRL = (1 << 2),
13    ALT = (1 << 3),
14    ALTGR = (1 << 4)
15 };
16
17 static Evas_Object *_theme_obj_new(Evas *e, const char *custom_dir, const char *group);
18
19 static void _e_kbd_int_layout_next(E_Kbd_Int *ki);
20 static void _e_kbd_int_zoomkey_down(E_Kbd_Int *ki);
21 static void _e_kbd_int_matches_update(void *data);
22 static void _e_kbd_int_dictlist_down(E_Kbd_Int *ki);
23 static void _e_kbd_int_matchlist_down(E_Kbd_Int *ki);
24 static Eina_Bool _e_kbd_int_cb_border_move(void *data, int type, void *event);
25
26
27 static const char *
28 _e_kbd_int_str_unquote(const char *str)
29 {
30    static char buf[256];
31    char *p;
32    
33    snprintf(buf, sizeof(buf), "%s", str + 1);
34    p = strrchr(buf, '"');
35    if (p) *p = 0;
36    return buf;
37 }
38
39 static E_Kbd_Int_Key *
40 _e_kbd_int_at_coord_get(E_Kbd_Int *ki, Evas_Coord x, Evas_Coord y)
41 {
42    Eina_List *l;
43    Evas_Coord dist;
44    E_Kbd_Int_Key *ky;  
45    E_Kbd_Int_Key *closest_ky = NULL;
46
47    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
48      if ((x >= ky->x) && (y >= ky->y) &&
49          (x < (ky->x + ky->w)) && (y < (ky->y + ky->h)))
50        return ky;
51    dist = 0x7fffffff;
52    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
53      {
54         Evas_Coord dx, dy;
55
56         dx = x - (ky->x + (ky->w / 2));
57         dy = y - (ky->y + (ky->h / 2));
58         dx = (dx * dx) + (dy * dy);
59         if (dx < dist)
60           {
61              dist = dx;
62              closest_ky = ky;
63           }
64      }
65    return closest_ky;
66 }
67
68 static E_Kbd_Int_Key_State *
69 _e_kbd_int_key_state_get(E_Kbd_Int *ki, E_Kbd_Int_Key *ky)
70 {
71    E_Kbd_Int_Key_State *found = NULL;
72    E_Kbd_Int_Key_State *st;
73    Eina_List *l;
74
75    EINA_LIST_FOREACH(ky->states, l, st)
76      {
77         if (st->state & ki->layout.state) return st;
78         if (!found && st->state == NORMAL) found = st;
79      }
80    return found;
81 }
82
83 static void
84 _e_kbd_int_layout_buf_update(E_Kbd_Int *ki)
85 {
86    E_Kbd_Int_Key *ky;
87    Eina_List *l, *l2;
88
89    e_kbd_buf_layout_clear(ki->kbuf);
90    e_kbd_buf_layout_size_set(ki->kbuf, ki->layout.w, ki->layout.h);
91    e_kbd_buf_layout_fuzz_set(ki->kbuf, ki->layout.fuzz);
92    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
93      {
94         E_Kbd_Int_Key_State *st;
95         const char *out, *out_shift, *out_capslock, *out_altgr;
96
97         out = NULL;
98         out_shift = NULL;
99         out_capslock = NULL;
100         out_altgr = NULL;
101
102         EINA_LIST_FOREACH(ky->states, l2, st)
103           {
104              if (st->state == NORMAL)
105                out = st->out;
106              else if (st->state == SHIFT)
107                out_shift = st->out;
108              else if (st->state == CAPSLOCK)
109                out_capslock = st->out;
110              else if (st->state == ALTGR)
111                out_altgr = st->out;
112           }
113         if (out)
114           {
115              char *s1 = NULL, *s2 = NULL, *s3 = NULL;
116
117              if ((out) && (out[0] == '"')) 
118                s1 = strdup(_e_kbd_int_str_unquote(out));
119              if ((out_shift) && (out_shift[0] == '"')) 
120                s2 = strdup(_e_kbd_int_str_unquote(out_shift));
121              if ((out_altgr) && (out_altgr[0] == '"')) 
122                s2 = strdup(_e_kbd_int_str_unquote(out_altgr));
123              if ((out_capslock) && (out_capslock[0] == '"')) 
124                s3 = strdup(_e_kbd_int_str_unquote(out_capslock));
125              e_kbd_buf_layout_key_add(ki->kbuf, s1, s2, s3, 
126                                       ky->x, ky->y, ky->w, ky->h);
127              if (s1) free(s1);
128              if (s2) free(s2);
129              if (s3) free(s3);
130           }
131      }
132 }
133
134 static void
135 _e_kbd_int_layout_state_update(E_Kbd_Int *ki)
136 {
137    E_Kbd_Int_Key *ky;
138    Eina_List *l;
139
140    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
141      {
142         E_Kbd_Int_Key_State *st;
143         int selected;
144
145         st = _e_kbd_int_key_state_get(ki, ky);
146         if (st)
147           {
148              if (st->label)
149                edje_object_part_text_set(ky->obj, "e.text.label", st->label);
150              else
151                edje_object_part_text_set(ky->obj, "e.text.label", "");
152              if (st->icon)
153                {
154                   char buf[PATH_MAX];
155                   char *p;
156
157                   snprintf(buf, sizeof(buf), "%s/%s", ki->layout.directory, st->icon);
158                   p = strrchr(st->icon, '.');
159                   if (!strcmp(p, ".edj"))
160                     e_icon_file_edje_set(ky->icon_obj, buf, "icon");
161                   else
162                     e_icon_file_set(ky->icon_obj, buf);
163                }
164              else
165                e_icon_file_set(ky->icon_obj, NULL);
166           }
167         selected = 0;
168         if ((ki->layout.state & SHIFT) && (ky->is_shift)) selected = 1;
169         if ((ki->layout.state & CTRL) && (ky->is_ctrl)) selected = 1;
170         if ((ki->layout.state & ALT) && (ky->is_alt)) selected = 1;
171         if ((ki->layout.state & ALTGR) && (ky->is_altgr)) selected = 1;
172         if ((ki->layout.state & CAPSLOCK) && (ky->is_capslock)) selected = 1;
173         if ((ki->layout.state & (SHIFT | CAPSLOCK)) && (ky->is_multi_shift)) 
174           selected = 1;
175         if (selected)
176           {
177              if (!ky->selected)
178                {
179                   edje_object_signal_emit(ky->obj, "e,state,selected", "e");
180                   ky->selected = 1;
181                }
182           }
183         if (!selected)
184           {
185              if (ky->selected)
186                {
187                   edje_object_signal_emit(ky->obj, "e,state,unselected", "e");
188                   ky->selected = 0;
189                }
190           }
191      }
192 }
193
194 static void
195 _e_kbd_int_string_send(E_Kbd_Int *ki, const char *str)
196 {
197    int pos, newpos, glyph;
198
199    pos = 0;
200    e_kbd_buf_word_use(ki->kbuf, str);
201    for (;;)
202      {
203         char buf[16];
204
205         newpos = evas_string_char_next_get(str, pos, &glyph);
206         if (glyph <= 0) return;
207         strncpy(buf, str + pos, newpos - pos);
208         buf[newpos - pos] = 0;
209         e_kbd_send_string_press(buf, 0);
210         pos = newpos;
211      }
212 }
213
214 static void
215 _e_kbd_int_buf_send(E_Kbd_Int *ki)
216 {
217    const char *str = NULL;
218    const Eina_List *matches;
219
220    matches = e_kbd_buf_string_matches_get(ki->kbuf);
221    if (matches) str = matches->data;
222    else str = e_kbd_buf_actual_string_get(ki->kbuf);
223    if (str) _e_kbd_int_string_send(ki, str);
224 }
225
226 static void
227 _e_kbd_int_cb_match_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
228 {
229    E_Kbd_Int_Match *km;
230
231    km = data;
232    _e_kbd_int_string_send(km->ki, km->str);
233    e_kbd_buf_clear(km->ki->kbuf);
234    e_kbd_send_keysym_press("space", 0);
235    if (km->ki->layout.state & (SHIFT | CTRL | ALT | ALTGR))
236      {
237         km->ki->layout.state &= (~(SHIFT | CTRL | ALT | ALTGR));
238         _e_kbd_int_layout_state_update(km->ki);
239      }
240    _e_kbd_int_matches_update(km->ki);
241 }
242
243 static void
244 _e_kbd_int_matches_add(E_Kbd_Int *ki, const char *str, int num)
245 {
246    E_Kbd_Int_Match *km;
247    Evas_Object *o;
248    Evas_Coord mw, mh;
249
250    km = E_NEW(E_Kbd_Int_Match, 1);
251    if (!km) return;
252    o = _theme_obj_new(ki->win->evas, ki->themedir,
253                       "e/modules/kbd/match/word");
254    km->ki = ki;
255    km->str = eina_stringshare_add(str);
256    km->obj = o;
257    ki->matches = eina_list_append(ki->matches, km);
258    edje_object_part_text_set(o, "e.text.label", str);
259    edje_object_size_min_calc(o, &mw, &mh);
260    if (mw < 32) mw = 32;
261    if (num & 0x1) e_box_pack_start(ki->box_obj, o);
262    else e_box_pack_end(ki->box_obj, o);
263    e_box_pack_options_set(o, 1, 1, 1, 1, 0.5, 0.5, mw, mh, 9999, 9999);
264    if (num == 0)
265      edje_object_signal_emit(o, "e,state,selected", "e");
266    edje_object_signal_callback_add(o, "e,action,do,select", "",
267                                    _e_kbd_int_cb_match_select, km);
268    evas_object_show(o);
269 }
270
271 static void
272 _e_kbd_int_matches_free(E_Kbd_Int *ki)
273 {
274    E_Kbd_Int_Match *km;
275
276    EINA_LIST_FREE(ki->matches, km)
277      {
278         if (km->str) eina_stringshare_del(km->str);
279         evas_object_del(km->obj);
280         free(km);
281      }
282 }
283
284 static void
285 _e_kbd_int_matches_update(void *data)
286 {
287    E_Kbd_Int *ki;
288    const Eina_List *l, *matches;
289    const char *actual;
290    Evas_Coord mw, mh, vw, vh;
291
292    if (!(ki = data)) return;
293    evas_event_freeze(ki->win->evas);
294    e_box_freeze(ki->box_obj);
295    _e_kbd_int_matches_free(ki);
296    matches = e_kbd_buf_string_matches_get(ki->kbuf);
297    if (!matches)
298      {
299         actual = e_kbd_buf_actual_string_get(ki->kbuf);
300         if (actual) _e_kbd_int_matches_add(ki, actual, 0);
301      }
302    else
303      {
304         int i = 0;
305
306         for (i = 0, l = matches; l; l = l->next, i++)
307           {
308              _e_kbd_int_matches_add(ki, l->data, i);
309              e_box_size_min_get(ki->box_obj, &mw, &mh);
310              edje_object_part_geometry_get(ki->base_obj, "e.swallow.label", 
311                                            NULL, NULL, &vw, &vh);
312              if (mw > vw) break;
313           }
314
315         if (!l)
316           {
317              actual = e_kbd_buf_actual_string_get(ki->kbuf);
318              if (actual)
319                {
320                   const char *str;
321
322                   EINA_LIST_FOREACH(matches, l, str)
323                     if (!strcmp(str, actual)) break;
324                   if (!l) _e_kbd_int_matches_add(ki, actual, i);
325                }
326           }
327      }
328    e_box_thaw(ki->box_obj);
329    e_box_size_min_get(ki->box_obj, &mw, &mh);
330    edje_extern_object_min_size_set(ki->box_obj, 0, mh);
331    edje_object_part_swallow(ki->base_obj, "e.swallow.label", ki->box_obj);
332    evas_event_thaw(ki->win->evas);
333
334    _e_kbd_int_matchlist_down(ki);
335 }
336
337 static void
338 _e_kbd_int_key_press_handle(E_Kbd_Int *ki, E_Kbd_Int_Key *ky)
339 {
340    E_Kbd_Int_Key_State *st;
341    const char *out = NULL;
342
343    if (!ky) return;
344
345    if (ky->is_shift)
346      {
347         if (ki->layout.state & SHIFT) ki->layout.state &= (~(SHIFT));
348         else ki->layout.state |= SHIFT;
349         _e_kbd_int_layout_state_update(ki);
350         return;
351      }
352    if (ky->is_multi_shift)
353      {
354         if (ki->layout.state & SHIFT)
355           {
356              ki->layout.state &= (~(SHIFT));
357              ki->layout.state |= CAPSLOCK;
358           }
359         else if (ki->layout.state & CAPSLOCK)
360           ki->layout.state &= (~(CAPSLOCK));
361         else
362           ki->layout.state |= SHIFT;
363         _e_kbd_int_layout_state_update(ki);
364         return;
365      }
366    if (ky->is_ctrl)
367      {
368         if (ki->layout.state & CTRL) ki->layout.state &= (~(CTRL));
369         else ki->layout.state |= CTRL;
370         if (e_kbd_buf_actual_string_get(ki->kbuf)) _e_kbd_int_buf_send(ki);
371         e_kbd_buf_clear(ki->kbuf);
372         _e_kbd_int_layout_state_update(ki);
373         _e_kbd_int_matches_update(ki);
374         return;
375      }
376    if (ky->is_alt)
377      {
378         if (ki->layout.state & ALT) ki->layout.state &= (~(ALT));
379         else ki->layout.state |= ALT;
380         if (e_kbd_buf_actual_string_get(ki->kbuf)) _e_kbd_int_buf_send(ki);
381         e_kbd_buf_clear(ki->kbuf);
382         _e_kbd_int_layout_state_update(ki);
383         _e_kbd_int_matches_update(ki);
384         return;
385      }
386    if (ky->is_altgr)
387      {
388         if (ki->layout.state & ALTGR) ki->layout.state &= (~(ALTGR));
389         else ki->layout.state |= ALTGR;
390         _e_kbd_int_layout_state_update(ki);
391         return;
392      }
393    if (ky->is_capslock)
394      {
395         if (ki->layout.state & CAPSLOCK) ki->layout.state &= (~CAPSLOCK);
396         else ki->layout.state |= CAPSLOCK;
397         _e_kbd_int_layout_state_update(ki);
398         return;
399      }
400    st = _e_kbd_int_key_state_get(ki, ky);
401    if (st) out = st->out;
402    if (ki->layout.state & (CTRL | ALT))
403      {
404         if (out)
405           {
406              Kbd_Mod mods = 0;
407
408              if (ki->layout.state & CTRL) mods |= KBD_MOD_CTRL;
409              if (ki->layout.state & ALT) mods |= KBD_MOD_ALT;
410              if (out[0] == '"')
411                e_kbd_send_string_press(_e_kbd_int_str_unquote(out), mods);
412              else
413                e_kbd_send_keysym_press(out, mods);
414           }
415         ki->layout.state &= (~(SHIFT | CTRL | ALT | ALTGR));
416         _e_kbd_int_layout_state_update(ki);
417         e_kbd_buf_lookup(ki->kbuf, _e_kbd_int_matches_update, ki);
418         return;
419      }
420    if (out)
421      {
422         if (out[0] == '"')
423           {
424              if (ki->down.zoom)
425                e_kbd_buf_pressed_key_add(ki->kbuf,
426                                          _e_kbd_int_str_unquote(out), 
427                                          ki->layout.state & SHIFT, 
428                                          ki->layout.state & CAPSLOCK);
429              else
430                e_kbd_buf_pressed_point_add(ki->kbuf,
431                                            ky->x + (ky->w / 2),
432                                            ky->y + (ky->h / 2),
433                                            ki->layout.state & SHIFT, 
434                                            ki->layout.state & CAPSLOCK);
435              e_kbd_buf_lookup(ki->kbuf, _e_kbd_int_matches_update, ki);
436           }
437         else
438           {
439              if (e_kbd_buf_actual_string_get(ki->kbuf)) 
440                _e_kbd_int_buf_send(ki);
441              e_kbd_buf_clear(ki->kbuf);
442              e_kbd_send_keysym_press(out, 0);
443              _e_kbd_int_matches_update(ki);
444           }
445      }
446    if (ki->layout.state & (SHIFT | CTRL | ALT | ALTGR))
447      {
448         printf("CLEARING STATE\n");
449         if (!ky->is_multi_shift) 
450           ki->layout.state &= (~(SHIFT | CTRL | ALT | ALTGR));
451         _e_kbd_int_layout_state_update(ki);
452      }
453 }
454     
455 static void
456 _e_kbd_int_stroke_handle(E_Kbd_Int *ki, int dir)
457 {
458    /* If the keyboard direction is RTL switch dir 3 and 1
459     * i.e, make forward backwards and the other way around */
460    if (ki->layout.direction == E_KBD_INT_DIRECTION_RTL)
461      {
462         if (dir == 3)
463           dir = 1;
464         else if (dir == 1)
465           dir = 3;
466      }
467
468    if (dir == 4) // up
469      _e_kbd_int_layout_next(ki);
470    else if (dir == 3) // left
471      {
472         if (e_kbd_buf_actual_string_get(ki->kbuf))
473           {
474              e_kbd_buf_backspace(ki->kbuf);
475              e_kbd_buf_lookup(ki->kbuf, _e_kbd_int_matches_update, ki);
476           }
477         else
478           e_kbd_send_keysym_press("BackSpace", 0);
479      }
480    else if (dir == 2) // down
481      {
482         if (e_kbd_buf_actual_string_get(ki->kbuf)) _e_kbd_int_buf_send(ki);
483         e_kbd_buf_clear(ki->kbuf);
484         e_kbd_send_keysym_press("Return", 0);
485         _e_kbd_int_matches_update(ki);
486      }
487    else if (dir == 1) // right
488      {
489         if (e_kbd_buf_actual_string_get(ki->kbuf)) _e_kbd_int_buf_send(ki);
490         e_kbd_buf_clear(ki->kbuf);
491         e_kbd_send_keysym_press("space", 0);
492         _e_kbd_int_matches_update(ki);
493      }
494    if (ki->layout.state)
495      {
496         ki->layout.state = 0;
497         _e_kbd_int_layout_state_update(ki);
498      }
499 }
500     
501 static void
502 _e_kbd_int_zoomkey_down(E_Kbd_Int *ki)
503 {
504    const Eina_List *l;
505
506    if (!ki->zoomkey.popup) return;
507    e_object_del(E_OBJECT(ki->zoomkey.popup));
508    ki->zoomkey.popup = NULL;
509    ki->zoomkey.layout_obj = NULL;
510    ki->zoomkey.sublayout_obj = NULL;
511    for (l = ki->layout.keys; l; l = l->next)
512      {
513         E_Kbd_Int_Key *ky;
514
515         ky = l->data;
516         ky->zoom_obj = NULL;
517         ky->zoom_icon_obj = NULL;
518      }
519 }
520
521 static void
522 _e_kbd_int_zoomkey_up(E_Kbd_Int *ki)
523 {
524    const Eina_List *l;
525    Evas_Object *o, *o2;
526    Evas_Coord mw, mh, vw, vh;
527    int sx, sy, sw, sh;
528
529    if (ki->zoomkey.popup) return;
530    ki->zoomkey.popup = e_popup_new(ki->win->border->zone, -1, -1, 1, 1);
531    e_popup_layer_set(ki->zoomkey.popup, 190);
532
533    o = _theme_obj_new(ki->zoomkey.popup->evas, ki->themedir,
534                       "e/modules/kbd/zoom/default");
535    ki->zoomkey.base_obj = o;
536
537    o = e_layout_add(ki->zoomkey.popup->evas);
538    e_layout_virtual_size_set(o, 100, 100);
539    edje_object_part_swallow(ki->zoomkey.base_obj, "e.swallow.content", o);
540    evas_object_show(o);
541    ki->zoomkey.layout_obj = o;
542
543    e_layout_virtual_size_get(ki->layout_obj, &vw, &vh);
544
545    o = e_layout_add(ki->zoomkey.popup->evas);
546    e_layout_virtual_size_set(o, vw, vh);
547    e_layout_pack(ki->zoomkey.layout_obj, o);
548    e_layout_child_move(o, 0, 0);
549    e_layout_child_resize(o,
550                          vw * il_kbd_cfg->zoom_level,
551                          vh * il_kbd_cfg->zoom_level);
552    evas_object_show(o);
553    ki->zoomkey.sublayout_obj = o;
554
555    for (l = ki->layout.keys; l; l = l->next)
556      {
557         E_Kbd_Int_Key *ky;
558         E_Kbd_Int_Key_State *st;
559         const char *label, *icon;
560         int selected;
561
562         ky = l->data;
563         o = _theme_obj_new(ki->zoomkey.popup->evas, ki->themedir,
564                            "e/modules/kbd/zoomkey/default");
565         label = "";
566         icon = NULL;
567         st = _e_kbd_int_key_state_get(ki, ky);
568         if (st)
569           {
570              label = st->label;
571              icon = st->icon;
572           }
573
574         edje_object_part_text_set(o, "e.text.label", label);
575
576         o2 = e_icon_add(ki->zoomkey.popup->evas);
577         e_icon_fill_inside_set(o2, 1);
578 //        e_icon_scale_up_set(o2, 0);
579         edje_object_part_swallow(o, "e.swallow.content", o2);
580         evas_object_show(o2);
581
582         if (icon)
583           {
584              char buf[PATH_MAX];
585              char *p;
586
587              snprintf(buf, sizeof(buf), "%s/%s", ki->layout.directory, icon);
588              p = strrchr(icon, '.');
589              if (!strcmp(p, ".edj"))
590                e_icon_file_edje_set(o2, buf, "icon");
591              else
592                e_icon_file_set(o2, buf);
593           }
594         selected = 0;
595         if ((ki->layout.state & SHIFT) && (ky->is_shift)) selected = 1;
596         if ((ki->layout.state & CTRL) && (ky->is_ctrl)) selected = 1;
597         if ((ki->layout.state & ALT) && (ky->is_alt)) selected = 1;
598         if ((ki->layout.state & ALTGR) && (ky->is_altgr)) selected = 1;
599         if ((ki->layout.state & CAPSLOCK) && (ky->is_capslock)) selected = 1;
600         if ((ki->layout.state & (SHIFT|CAPSLOCK)) && (ky->is_multi_shift)) 
601           selected = 1;
602         if (selected)
603           edje_object_signal_emit(o, "e,state,selected", "e");
604         if (!selected)
605           edje_object_signal_emit(o, "e,state,unselected", "e");
606         e_layout_pack(ki->zoomkey.sublayout_obj, o);
607         e_layout_child_move(o, ky->x, ky->y);
608         e_layout_child_resize(o, ky->w, ky->h);
609         evas_object_show(o);
610         ky->zoom_obj = o;
611         ky->zoom_icon_obj = o2;
612      }
613
614    edje_object_size_min_calc(ki->zoomkey.base_obj, &vw, &vh);
615    e_zone_useful_geometry_get(ki->win->border->zone, &sx, &sy, &sw, &sh);
616    sh -= ki->win->h;
617    mw = sw;
618    if ((vw > 0) && (mw > vw)) mw = vw;
619    mh = sh;
620    if ((vh > 0) && (mh > vh)) mh = vh;
621
622    e_popup_move_resize(ki->zoomkey.popup, 
623                        sx + ((sw - mw) / 2), sy + ((sh - mh) / 2), mw, mh);
624    evas_object_resize(ki->zoomkey.base_obj,
625                       ki->zoomkey.popup->w, ki->zoomkey.popup->h);
626    evas_object_show(ki->zoomkey.base_obj);
627    e_popup_edje_bg_object_set(ki->zoomkey.popup, ki->zoomkey.base_obj);
628    e_popup_show(ki->zoomkey.popup);
629    e_popup_layer_set(ki->zoomkey.popup, 190);
630 }
631
632 static void
633 _e_kbd_int_zoomkey_update(E_Kbd_Int *ki)
634 {
635    Evas_Coord w, h, ww, hh;
636    E_Kbd_Int_Key *ky;
637
638    evas_object_geometry_get(ki->zoomkey.layout_obj, NULL, NULL, &w, &h);
639    evas_object_geometry_get(ki->layout_obj, NULL, NULL, &ww, &hh);
640    e_layout_virtual_size_set(ki->zoomkey.layout_obj, w, h);
641    e_layout_child_resize(ki->zoomkey.sublayout_obj,
642                          ww * il_kbd_cfg->zoom_level,
643                          hh * il_kbd_cfg->zoom_level);
644    e_layout_child_move(ki->zoomkey.sublayout_obj, 
645                        (w / 2) - (ki->down.cx * il_kbd_cfg->zoom_level),
646                        (h / 2) - (ki->down.cy * il_kbd_cfg->zoom_level));
647    ky = _e_kbd_int_at_coord_get(ki, ki->down.clx, ki->down.cly);
648    if (ky != ki->zoomkey.pressed)
649      {
650         if (ki->zoomkey.pressed)
651           {
652              ki->zoomkey.pressed->pressed = 0;
653              edje_object_signal_emit(ki->zoomkey.pressed->zoom_obj,
654                                      "e,state,released", "e");
655              edje_object_signal_emit(ki->zoomkey.pressed->obj,
656                                      "e,state,released", "e");
657           }
658         ki->zoomkey.pressed = ky;
659         if (ki->zoomkey.pressed)
660           {
661              ki->zoomkey.pressed->pressed = 1;
662              e_layout_child_raise(ki->zoomkey.pressed->zoom_obj);
663              edje_object_signal_emit(ki->zoomkey.pressed->zoom_obj,
664                                      "e,state,pressed", "e");
665              e_layout_child_raise(ki->zoomkey.pressed->obj);
666              e_layout_child_raise(ki->event_obj);
667              edje_object_signal_emit(ki->zoomkey.pressed->obj,
668                                      "e,state,pressed", "e");
669           }
670      }
671 }
672
673 static Eina_Bool
674 _e_kbd_int_cb_hold_timeout(void *data)
675 {
676    E_Kbd_Int *ki;
677
678    ki = data;
679    ki->down.hold_timer = NULL;
680    ki->down.zoom = 1;
681    if (ki->layout.pressed)
682      {
683         ki->layout.pressed->pressed = 0;
684         edje_object_signal_emit(ki->layout.pressed->obj,
685                                 "e,state,released", "e");
686         ki->layout.pressed = NULL;
687      }
688    _e_kbd_int_zoomkey_up(ki);
689    _e_kbd_int_zoomkey_update(ki);
690    return ECORE_CALLBACK_CANCEL;
691 }
692
693 static void
694 _e_kbd_int_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
695 {
696    Evas_Event_Mouse_Down *ev;
697    E_Kbd_Int *ki;
698    Evas_Coord x, y, w, h;
699    E_Kbd_Int_Key *ky;
700
701    ev = event_info;
702    if (ev->button != 1) return;
703    ki = data;
704    ki->down.x = ev->canvas.x;
705    ki->down.y = ev->canvas.y;
706    ki->down.down = 1;
707    ki->down.stroke = 0;
708
709    evas_object_geometry_get(ki->event_obj, &x, &y, &w, &h);
710    x = ev->canvas.x - x;
711    y = ev->canvas.y - y;
712    ki->down.cx = x;
713    ki->down.cy = y;
714    x = (x * ki->layout.w) / w;
715    y = (y * ki->layout.h) / h;
716
717    ki->down.lx = x;
718    ki->down.ly = y;
719    ki->down.clx = x;
720    ki->down.cly = y;
721
722    if (ki->down.hold_timer) ecore_timer_del(ki->down.hold_timer);
723    ki->down.hold_timer = ecore_timer_add(il_kbd_cfg->hold_timer,
724                                          _e_kbd_int_cb_hold_timeout, ki);
725
726    ky = _e_kbd_int_at_coord_get(ki, x, y);
727    ki->layout.pressed = ky;
728    if (ky)
729      {
730         ky->pressed = 1;
731         e_layout_child_raise(ky->obj);
732         e_layout_child_raise(ki->event_obj);
733         edje_object_signal_emit(ky->obj, "e,state,pressed", "e");
734      }
735 }
736
737 static void
738 _e_kbd_int_cb_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
739 {
740    Evas_Event_Mouse_Move *ev;
741    E_Kbd_Int *ki;
742    Evas_Coord dx, dy, x, w, y, h;
743
744    ev = event_info;
745    ki = data;
746
747    if (ki->down.zoom)
748      {
749         evas_object_geometry_get(ki->event_obj, &x, &y, &w, &h);
750         x = ev->cur.canvas.x - x;
751         y = ev->cur.canvas.y - y;
752         ki->down.cx = x;
753         ki->down.cy = y;
754         x = (x * ki->layout.w) / w;
755         y = (y * ki->layout.h) / h;
756         ki->down.clx = x;
757         ki->down.cly = y;
758         _e_kbd_int_zoomkey_update(ki);
759         return;
760      }
761    if (ki->down.stroke) return;
762
763    dx = ev->cur.canvas.x - ki->down.x;
764    dy = ev->cur.canvas.y - ki->down.y;
765    evas_object_geometry_get(ki->event_obj, &x, &y, &w, &h);
766    dx = (dx * ki->layout.w) / w;
767    dy = (dy * ki->layout.h) / h;
768    if ((dx > 0) && (dx > (ki->layout.w / il_kbd_cfg->slide_dim)))
769      ki->down.stroke = 1;
770    else if ((dx < 0) && (-dx > (ki->layout.w / il_kbd_cfg->slide_dim)))
771      ki->down.stroke = 1;
772    if ((dy > 0) && (dy > (ki->layout.h / il_kbd_cfg->slide_dim)))
773      ki->down.stroke = 1;
774    else if ((dy < 0) && (-dy > (ki->layout.w / il_kbd_cfg->slide_dim)))
775      ki->down.stroke = 1;
776    if ((ki->down.stroke) && (ki->down.hold_timer))
777      {
778         ecore_timer_del(ki->down.hold_timer);
779         ki->down.hold_timer = NULL;
780      }
781 }
782
783 static void
784 _e_kbd_int_cb_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
785 {
786    Evas_Event_Mouse_Up *ev;
787    E_Kbd_Int *ki;
788    E_Kbd_Int_Key *ky;
789    int dir = 0;
790
791    ev = event_info;
792    if (ev->button != 1) return;
793    ki = data;
794
795    if (ki->down.zoom)
796      {
797         ky = _e_kbd_int_at_coord_get(ki, ki->down.clx, ki->down.cly);
798         _e_kbd_int_key_press_handle(ki, ky);
799         _e_kbd_int_zoomkey_down(ki);
800         ki->down.zoom = 0;
801      }
802    else if (!ki->down.down)
803      {
804         /* case of mouse up event without mouse down when popup appear */
805         Evas_Coord x, y, w, h;
806         evas_object_geometry_get(ki->event_obj, &x, &y, &w, &h);
807         x = ev->canvas.x - x;
808         y = ev->canvas.y - y;
809         x = (x * ki->layout.w) / w;
810         y = (y * ki->layout.h) / h;
811         ky = _e_kbd_int_at_coord_get(ki, x, y);
812         ki->layout.pressed = ky;
813         _e_kbd_int_key_press_handle(ki, ki->layout.pressed);
814         edje_object_signal_emit(ky->obj,
815                                 "e,state,pressed", "e");
816         edje_object_message_signal_process(ky->obj);
817      }
818    else if (!ki->down.stroke)
819      {
820
821         ky = _e_kbd_int_at_coord_get(ki, ki->down.lx, ki->down.ly);
822         _e_kbd_int_key_press_handle(ki, ky);
823      }
824    else
825      {
826         Evas_Coord dx, dy;
827
828         dx = ev->canvas.x - ki->down.x;
829         dy = ev->canvas.y - ki->down.y;
830         if (dx > 0)
831           {
832              if (dy > 0)
833                {
834                   if (dx > dy) dir = 1; // right
835                   else dir = 2; // down
836                }
837              else
838                {
839                   if (dx > -dy) dir = 1; // right
840                   else dir = 4; // up
841                }
842           }
843         else
844           {
845              if (dy > 0)
846                {
847                   if (-dx > dy) dir = 3; // left
848                   else dir = 2; // down
849                }
850              else
851                {
852                   if (-dx > -dy) dir = 3; // left
853                   else dir = 4; // up
854                }
855           }
856      }
857
858    ky = ki->layout.pressed;
859    if (ky)
860      {
861         ky->pressed = 0;
862         edje_object_signal_emit(ky->obj, "e,state,released", "e");
863         ki->layout.pressed = NULL;
864      }
865    ky = ki->zoomkey.pressed;
866    if (ky)
867      {
868         ky->pressed = 0;
869         edje_object_signal_emit(ky->obj, "e,state,released", "e");
870         ki->zoomkey.pressed = NULL;
871      }
872
873    ki->down.down = 0;
874    ki->down.stroke = 0;
875    if (ki->down.hold_timer)
876      {
877         ecore_timer_del(ki->down.hold_timer);
878         ki->down.hold_timer = NULL;
879      }
880
881    if (dir > 0) _e_kbd_int_stroke_handle(ki, dir);
882 }
883
884 static E_Kbd_Int_Layout *
885 _e_kbd_int_layouts_list_default_get(E_Kbd_Int *ki)
886 {
887    E_Kbd_Int_Layout *kil;
888    Eina_List *l;
889
890    EINA_LIST_FOREACH(ki->layouts, l, kil)
891      if (kil->type == il_kbd_cfg->layout)
892        return kil;
893
894    EINA_LIST_FOREACH(ki->layouts, l, kil)
895      if ((!strcmp(ecore_file_file_get(kil->path), "Default.kbd")))
896        return kil;
897    return NULL;
898 }
899
900 static E_Kbd_Int_Layout *
901 _e_kbd_int_layouts_type_get(E_Kbd_Int *ki, int type)
902 {
903    E_Kbd_Int_Layout *kil;
904    Eina_List *l;
905
906    EINA_LIST_FOREACH(ki->layouts, l, kil)
907      if (kil->type == type) return kil;
908    return NULL;
909 }
910
911 static void
912 _e_kbd_int_layout_free(E_Kbd_Int *ki)
913 {
914    E_Kbd_Int_Key *ky;
915
916    if (ki->layout.directory) free(ki->layout.directory);
917    if (ki->layout.file) eina_stringshare_del(ki->layout.file);
918    ki->layout.directory = NULL;
919    ki->layout.file = NULL;
920    EINA_LIST_FREE(ki->layout.keys, ky)
921      {
922         E_Kbd_Int_Key_State *st;
923
924         EINA_LIST_FREE(ky->states, st)
925           {
926              if (st->label) eina_stringshare_del(st->label);
927              if (st->icon) eina_stringshare_del(st->icon);
928              if (st->out) eina_stringshare_del(st->out);
929              free(st);
930           }
931         if (ky->obj) evas_object_del(ky->obj);
932         if (ky->icon_obj) evas_object_del(ky->icon_obj);
933         free(ky);
934      }
935    if (ki->event_obj) evas_object_del(ki->event_obj);
936    ki->event_obj = NULL;
937 }
938
939 static void
940 _e_kbd_int_layout_parse(E_Kbd_Int *ki, const char *layout)
941 {
942    FILE *f;
943    char buf[4096];
944    int isok = 0;
945    E_Kbd_Int_Key *ky = NULL;
946    E_Kbd_Int_Key_State *st = NULL;
947
948    if (!(f = fopen(layout, "r"))) return;
949
950    ki->layout.directory = ecore_file_dir_get(layout);
951    ki->layout.file = eina_stringshare_add(layout);
952
953    /* Make the default direction LTR */
954    ki->layout.direction = E_KBD_INT_DIRECTION_LTR;
955
956    while (fgets(buf, sizeof(buf), f))
957      {
958         int len;
959         char str[4096];
960
961         if (!isok)
962           {
963              if (!strcmp(buf, "##KBDCONF-1.0\n")) isok = 1;
964           }
965         if (!isok) break;
966         if (buf[0] == '#') continue;
967         len = strlen(buf);
968         if (len > 0)
969           {
970              if (buf[len - 1] == '\n') buf[len - 1] = 0;
971           }
972         if (sscanf(buf, "%4000s", str) != 1) continue;
973         if (!strcmp(str, "kbd"))
974           {
975              if (sscanf(buf, "%*s %i %i\n", &(ki->layout.w), &(ki->layout.orig_h)) != 2)
976                continue;
977           }
978         if (!strcmp(str, "fuzz"))
979           {
980              sscanf(buf, "%*s %i\n", &(ki->layout.fuzz));
981              continue;
982           }
983         if (!strcmp(str, "direction"))
984           {
985              char direction[4];
986
987              sscanf(buf, "%*s %3s\n", direction);
988
989              /* If rtl mark as rtl, otherwise make it ltr */
990              if (!strcmp(direction, "rtl"))
991                ki->layout.direction = E_KBD_INT_DIRECTION_RTL;
992              else
993                ki->layout.direction = E_KBD_INT_DIRECTION_LTR;
994              continue;
995           }
996         if (!strcmp(str, "key"))
997           {
998              ky = calloc(1, sizeof(E_Kbd_Int_Key));
999              if (!ky) continue;
1000              if (sscanf(buf, "%*s %i %i %i %i\n", &(ky->x), &(ky->orig_y), &(ky->w), &(ky->orig_h)) != 4)
1001                {
1002                   free(ky);
1003                   ky = NULL;
1004                   continue;
1005                }
1006              ki->layout.keys = eina_list_append(ki->layout.keys, ky);
1007           }
1008         if (!ky) continue;
1009         if ((!strcmp(str, "normal")) || (!strcmp(str, "shift")) ||
1010             (!strcmp(str, "capslock")) || (!strcmp(str, "altgr")))
1011           {
1012              char *p;
1013              char label[4096];
1014
1015              if (sscanf(buf, "%*s %4000s", label) != 1) continue;
1016              st = calloc(1, sizeof(E_Kbd_Int_Key_State));
1017              if (!st) continue;
1018              ky->states = eina_list_append(ky->states, st);
1019              if (!strcmp(str, "normal")) st->state = NORMAL;
1020              if (!strcmp(str, "shift")) st->state = SHIFT;
1021              if (!strcmp(str, "capslock")) st->state = CAPSLOCK;
1022              if (!strcmp(str, "altgr")) st->state = ALTGR;
1023              p = strrchr(label, '.');
1024              if ((p) && (!strcmp(p, ".png")))
1025                st->icon = eina_stringshare_add(label);
1026              else if ((p) && (!strcmp(p, ".edj")))
1027                st->icon = eina_stringshare_add(label);
1028              else
1029                st->label = eina_stringshare_add(label);
1030              if (sscanf(buf, "%*s %*s %4000s", str) != 1) continue;
1031              st->out = eina_stringshare_add(str);
1032           }
1033         if (!strcmp(str, "is_shift")) ky->is_shift = 1;
1034         if (!strcmp(str, "is_multi_shift")) ky->is_multi_shift = 1;
1035         if (!strcmp(str, "is_ctrl")) ky->is_ctrl = 1;
1036         if (!strcmp(str, "is_alt")) ky->is_alt = 1;
1037         if (!strcmp(str, "is_altgr")) ky->is_altgr = 1;
1038         if (!strcmp(str, "is_capslock")) ky->is_capslock = 1;
1039      }
1040    fclose(f);
1041 }
1042
1043 static void
1044 _e_kbd_int_layout_build(E_Kbd_Int *ki)
1045 {
1046    E_Kbd_Int_Key *ky;
1047    Evas_Object *o, *o2;
1048    Evas_Coord lw, lh;
1049    Eina_List *l;
1050
1051    ki->layout.h = ki->layout.orig_h * il_kbd_cfg->scale_height;
1052
1053    evas_event_freeze(ki->win->evas);
1054    e_layout_virtual_size_set(ki->layout_obj, ki->layout.w, ki->layout.h);
1055    edje_extern_object_aspect_set(ki->layout_obj, EDJE_ASPECT_CONTROL_BOTH, 
1056                                  ki->layout.w, ki->layout.h);
1057    edje_object_part_swallow(ki->base_obj, "e.swallow.content", ki->layout_obj);
1058    evas_object_resize(ki->base_obj, ki->win->w, ki->win->h);
1059    edje_object_part_geometry_get(ki->base_obj, "e.swallow.content", 
1060                                  NULL, NULL, &lw, &lh);
1061    lh = (ki->layout.h * lw) / ki->layout.w;
1062    if (lw > ki->win->w) lw = ki->win->w;
1063    if (lh > ki->win->h) lh = ki->win->h;
1064    edje_extern_object_min_size_set(ki->layout_obj, lw, lh);
1065    edje_extern_object_max_size_set(ki->layout_obj, ki->win->w, ki->win->h);
1066
1067    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
1068      {
1069         E_Kbd_Int_Key_State *st;
1070         const char *label, *icon;
1071
1072         ky->y = ky->orig_y * il_kbd_cfg->scale_height;
1073         ky->h = ky->orig_h * il_kbd_cfg->scale_height;
1074
1075         o = _theme_obj_new(ki->win->evas, ki->themedir,
1076                            "e/modules/kbd/key/default");
1077         ky->obj = o;
1078         label = "";
1079         icon = NULL;
1080         st = _e_kbd_int_key_state_get(ki, ky);
1081         if (st)
1082           {
1083              label = st->label;
1084              icon = st->icon;
1085           }
1086
1087         edje_object_part_text_set(o, "e.text.label", label);
1088
1089         o2 = e_icon_add(ki->win->evas);
1090         e_icon_fill_inside_set(o2, 1);
1091         e_icon_scale_up_set(o2, 0);
1092         ky->icon_obj = o2;
1093         edje_object_part_swallow(o, "e.swallow.content", o2);
1094         evas_object_show(o2);
1095
1096         if (icon)
1097           {
1098              char buf[PATH_MAX];
1099              char *p;
1100
1101              snprintf(buf, sizeof(buf), "%s/%s", ki->layout.directory, icon);
1102              p = strrchr(icon, '.');
1103              if (!strcmp(p, ".edj"))
1104                e_icon_file_edje_set(o2, buf, "icon");
1105              else
1106                e_icon_file_set(o2, buf);
1107           }
1108         e_layout_pack(ki->layout_obj, o);
1109         e_layout_child_move(o, ky->x, ky->y);
1110         e_layout_child_resize(o, ky->w, ky->h);
1111         evas_object_show(o);
1112      }
1113
1114    o = evas_object_rectangle_add(ki->win->evas);
1115    e_layout_pack(ki->layout_obj, o);
1116    e_layout_child_move(o, 0, 0);
1117    e_layout_child_resize(o, ki->layout.w, ki->layout.h);
1118    evas_object_color_set(o, 0, 0, 0, 0);
1119    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, 
1120                                   _e_kbd_int_cb_mouse_down, ki);
1121    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, 
1122                                   _e_kbd_int_cb_mouse_up, ki);
1123    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, 
1124                                   _e_kbd_int_cb_mouse_move, ki);
1125    evas_object_show(o);
1126    ki->event_obj = o;
1127    evas_event_thaw(ki->win->evas);
1128    _e_kbd_int_matchlist_down(ki);
1129 }
1130
1131 static void
1132 _e_kbd_int_layouts_free(E_Kbd_Int *ki)
1133 {
1134    E_Kbd_Int_Layout *kil;
1135
1136    EINA_LIST_FREE(ki->layouts, kil)
1137      {
1138         eina_stringshare_del(kil->path);
1139         eina_stringshare_del(kil->dir);
1140         eina_stringshare_del(kil->icon);
1141         eina_stringshare_del(kil->name);
1142         free(kil);
1143      }
1144 }
1145
1146 static void
1147 _e_kbd_int_layouts_list_update(E_Kbd_Int *ki)
1148 {
1149    Eina_List *files;
1150    Eina_List *l;
1151    char buf[PATH_MAX], *p, *file, *path;
1152    const char *fl;
1153    Eina_List *kbs = NULL, *layouts = NULL;
1154    int ok;
1155    size_t len;
1156
1157    len = e_user_dir_concat_static(buf, "keyboards");
1158    if (len + 2 >= sizeof(buf)) return;
1159
1160    files = ecore_file_ls(buf);
1161
1162    buf[len] = '/';
1163    len++;
1164
1165    EINA_LIST_FREE(files, file)
1166      {
1167         p = strrchr(file, '.');
1168         if ((p) && (!strcmp(p, ".kbd")))
1169           {
1170              if (eina_strlcpy(buf + len, file, sizeof(buf) - len) >= sizeof(buf) - len)
1171                continue;
1172              kbs = eina_list_append(kbs, eina_stringshare_add(buf));
1173           }
1174         free(file);
1175      }
1176
1177    len = snprintf(buf, sizeof(buf), "%s/keyboards", ki->syskbds);
1178    if (len + 2 >= sizeof(buf)) return;
1179
1180    files = ecore_file_ls(buf);
1181
1182    buf[len] = '/';
1183    len++;
1184
1185    EINA_LIST_FREE(files, file)
1186      {
1187         p = strrchr(file, '.');
1188         if ((p) && (!strcmp(p, ".kbd")))
1189           {
1190              ok = 1;
1191              EINA_LIST_FOREACH(kbs, l, fl)
1192                {
1193                   if (!strcmp(file, fl))
1194                     {
1195                        ok = 0;
1196                        break;
1197                     }
1198                }
1199              if (ok)
1200                {
1201                   if (eina_strlcpy(buf + len, file, sizeof(buf) - len) >= sizeof(buf) - len)
1202                     continue;
1203                   kbs = eina_list_append(kbs, eina_stringshare_add(buf));
1204                }
1205           }
1206         free(file);
1207      }
1208    /* Previous loop could break before destroying all items. */
1209    EINA_LIST_FREE(files, file)
1210      free(file);
1211
1212    EINA_LIST_FREE(kbs, path)
1213      {
1214         E_Kbd_Int_Layout *kil;
1215
1216         kil = E_NEW(E_Kbd_Int_Layout, 1);
1217         if (kil)
1218           {
1219              char *s;
1220              FILE *f;
1221
1222              kil->path = path;
1223              s = strdup(ecore_file_file_get(kil->path));
1224              if (s)
1225                {
1226                   p = strrchr(s, '.');
1227                   if (p) *p = 0;
1228                   kil->name = eina_stringshare_add(s);
1229                   free(s);
1230                }
1231              s = ecore_file_dir_get(kil->path);
1232              if (s)
1233                {
1234                   kil->dir = eina_stringshare_add(s);
1235                   free(s);
1236                }
1237              f = fopen(kil->path, "r");
1238              if (f)
1239                {
1240                   int isok = 0;
1241
1242                   while (fgets(buf, sizeof(buf), f))
1243                     {
1244                        char str[4096];
1245
1246                        if (!isok)
1247                          {
1248                             if (!strcmp(buf, "##KBDCONF-1.0\n")) isok = 1;
1249                          }
1250                        if (!isok) break;
1251                        if (buf[0] == '#') continue;
1252                        len = strlen(buf);
1253                        if (len > 0)
1254                          {
1255                             if (buf[len - 1] == '\n') buf[len - 1] = 0;
1256                          }
1257                        if (sscanf(buf, "%4000s", str) != 1) continue;
1258                        if (!strcmp(str, "type"))
1259                          {
1260                             sscanf(buf, "%*s %4000s\n", str);
1261                             if (!strcmp(str, "ALPHA"))
1262                               kil->type = E_KBD_INT_TYPE_ALPHA;
1263                             else if (!strcmp(str, "NUMERIC"))
1264                               kil->type = E_KBD_INT_TYPE_NUMERIC;
1265                             else if (!strcmp(str, "PIN"))
1266                               kil->type = E_KBD_INT_TYPE_PIN;
1267                             else if (!strcmp(str, "PHONE_NUMBER"))
1268                               kil->type = E_KBD_INT_TYPE_PHONE_NUMBER;
1269                             else if (!strcmp(str, "HEX"))
1270                               kil->type = E_KBD_INT_TYPE_HEX;
1271                             else if (!strcmp(str, "TERMINAL"))
1272                               kil->type = E_KBD_INT_TYPE_TERMINAL;
1273                             else if (!strcmp(str, "PASSWORD"))
1274                               kil->type = E_KBD_INT_TYPE_PASSWORD;
1275                             else if (!strcmp(str, "IP"))
1276                               kil->type = E_KBD_INT_TYPE_IP;
1277                             else if (!strcmp(str, "HOST"))
1278                               kil->type = E_KBD_INT_TYPE_HOST;
1279                             else if (!strcmp(str, "FILE"))
1280                               kil->type = E_KBD_INT_TYPE_FILE;
1281                             else if (!strcmp(str, "URL"))
1282                               kil->type = E_KBD_INT_TYPE_URL;
1283                             else if (!strcmp(str, "KEYPAD"))
1284                               kil->type = E_KBD_INT_TYPE_KEYPAD;
1285                             else if (!strcmp(str, "J2ME"))
1286                               kil->type = E_KBD_INT_TYPE_J2ME;
1287                             continue;
1288                          }
1289                        if (!strcmp(str, "icon"))
1290                          {
1291                             sscanf(buf, "%*s %4000s\n", str);
1292                             snprintf(buf, sizeof(buf), "%s/%s", kil->dir, str);
1293                             kil->icon = eina_stringshare_add(buf);
1294                             continue;
1295                          }
1296                     }
1297                   fclose(f);
1298                }
1299              layouts = eina_list_append(layouts, kil);
1300           }
1301      }
1302    _e_kbd_int_layouts_free(ki);
1303    ki->layouts = layouts;
1304 }
1305
1306 static void
1307 _e_kbd_int_layout_select(E_Kbd_Int *ki, E_Kbd_Int_Layout *kil)
1308 {
1309    _e_kbd_int_layout_free(ki);
1310    _e_kbd_int_layout_parse(ki, kil->path);
1311    _e_kbd_int_layout_build(ki);
1312    _e_kbd_int_layout_buf_update(ki);
1313    _e_kbd_int_layout_state_update(ki);
1314
1315    if (!kil->icon)
1316      e_icon_file_set(ki->icon_obj, kil->icon);
1317    else
1318      {
1319         const char *p;
1320
1321         p = strrchr(kil->icon, '.');
1322         if (!p)
1323           e_icon_file_set(ki->icon_obj, kil->icon);
1324         else
1325           {
1326              if (!strcmp(p, ".edj"))
1327                e_icon_file_edje_set(ki->icon_obj, kil->icon, "icon");
1328              else
1329                e_icon_file_set(ki->icon_obj, kil->icon);
1330           }
1331      }
1332 }
1333
1334 static void
1335 _e_kbd_int_layout_next(E_Kbd_Int *ki)
1336 {
1337    Eina_List *l, *ln = NULL;
1338    E_Kbd_Int_Layout *kil;
1339
1340    EINA_LIST_FOREACH(ki->layouts, l, kil)
1341      if (!strcmp(kil->path, ki->layout.file))
1342        {
1343           ln = l->next;
1344           break;
1345        }
1346    if (!ln) ln = ki->layouts;
1347    if (!ln) return;
1348    kil = ln->data;
1349    _e_kbd_int_layout_select(ki, kil);
1350 }
1351
1352 static Eina_Bool
1353 _e_kbd_int_cb_client_message(void *data, __UNUSED__ int type, void *event)
1354 {
1355    Ecore_X_Event_Client_Message *ev;
1356    E_Kbd_Int *ki;
1357
1358    ev = event;
1359    ki = data;
1360    if ((ev->win == ki->win->evas_win) && 
1361        (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)) 
1362      {
1363         E_Kbd_Int_Layout *kil = NULL;
1364
1365         if ((unsigned int)ev->data.l[0] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF)
1366           {
1367              _e_kbd_int_zoomkey_down(ki);
1368              _e_kbd_int_dictlist_down(ki);
1369              _e_kbd_int_matchlist_down(ki);
1370           }
1371         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
1372           {
1373              // do nothing - leave kbd as-is
1374           }
1375         else if ((unsigned int)ev->data.l[0] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA)
1376           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_ALPHA);
1377         else if ((unsigned int)ev->data.l[0] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC)
1378           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_NUMERIC);
1379         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN)
1380           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_PIN);
1381         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER)
1382           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_PHONE_NUMBER);
1383         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX)
1384           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_HEX);
1385         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL)
1386           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_TERMINAL);
1387         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD)
1388           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_PASSWORD);
1389         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_IP)
1390           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_IP);
1391         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST)
1392           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_HOST);
1393         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE)
1394           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_FILE);
1395         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_URL)
1396           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_URL);
1397         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD)
1398           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_KEYPAD);
1399         else if (ev->data.l[0] == ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME)
1400           kil = _e_kbd_int_layouts_type_get(ki, E_KBD_INT_TYPE_J2ME);
1401
1402         if (kil) _e_kbd_int_layout_select(ki, kil);
1403      }
1404    return ECORE_CALLBACK_PASS_ON;
1405 }
1406
1407 static void
1408 _e_kbd_int_dictlist_down(E_Kbd_Int *ki)
1409 {
1410    char *str;
1411
1412    if (!ki->dictlist.popup) return;
1413    e_object_del(E_OBJECT(ki->dictlist.popup));
1414    ki->dictlist.popup = NULL;
1415    EINA_LIST_FREE(ki->dictlist.matches, str)
1416      eina_stringshare_del(str);
1417 }
1418
1419 static void
1420 _e_kbd_int_cb_dictlist_item_sel(void *data)
1421 {
1422    E_Kbd_Int *ki;
1423    const char *str;
1424    int i;
1425
1426    ki = data;
1427    i = e_widget_ilist_selected_get(ki->dictlist.ilist_obj);
1428    str = eina_list_nth(ki->dictlist.matches, i);
1429    e_kbd_buf_clear(ki->kbuf);
1430    if (ki->layout.state & (SHIFT | CTRL | ALT | ALTGR))
1431      {
1432         ki->layout.state &= (~(SHIFT | CTRL | ALT | ALTGR));
1433         _e_kbd_int_layout_state_update(ki);
1434      }
1435
1436    eina_stringshare_replace(&il_kbd_cfg->dict, str);
1437    e_kbd_buf_dict_set(ki->kbuf, il_kbd_cfg->dict);
1438    e_config_save_queue();
1439
1440    _e_kbd_int_dictlist_down(ki);
1441 }
1442
1443 static void
1444 _e_kbd_int_dictlist_up(E_Kbd_Int *ki)
1445 {
1446    Evas_Object *o;
1447    Evas_Coord mw, mh, sh;
1448    Eina_List *files, *l;
1449    char buf[PATH_MAX], *p, *file, *pp;
1450    const char *str;
1451    int used;
1452
1453    if (ki->dictlist.popup) return;
1454
1455    ki->dictlist.popup = e_popup_new(ki->win->border->zone, -1, -1, 1, 1);
1456    e_popup_layer_set(ki->dictlist.popup, 190);
1457
1458    o = _theme_obj_new(ki->dictlist.popup->evas, ki->themedir,
1459                       "e/modules/kbd/match/default");
1460    ki->dictlist.base_obj = o;
1461
1462    o = e_widget_ilist_add(ki->dictlist.popup->evas, 
1463                           (32 * e_scale), (32 * e_scale), NULL);
1464    e_widget_ilist_selector_set(o, 1);
1465    e_widget_ilist_freeze(o);
1466    ki->dictlist.ilist_obj = o;
1467
1468    e_user_dir_concat_static(buf, "dicts");
1469    files = ecore_file_ls(buf);
1470
1471    EINA_LIST_FREE(files, file)
1472      {
1473         p = strrchr(file, '.');
1474         if ((p) && (!strcmp(p, ".dic")))
1475           {
1476              const char *match;
1477
1478              used = 0;
1479              EINA_LIST_FOREACH(ki->dictlist.matches, l, match)
1480                if (!strcmp(match, file)) used = 1;
1481
1482              if (used) goto next1;
1483
1484              p = strdup(file);
1485              if (!p) goto next1;
1486
1487              for (pp = p; *pp; pp++)
1488                {
1489                   if (*pp == '_') *pp = ' ';
1490                }
1491              pp = strrchr(p, '.');
1492              *pp = 0;
1493              str = eina_stringshare_add(file);
1494              ki->dictlist.matches = eina_list_append(ki->dictlist.matches, str);
1495              e_widget_ilist_append(o, NULL, p, _e_kbd_int_cb_dictlist_item_sel,
1496                                    ki, NULL);
1497              free(p);
1498           }
1499
1500         next1:
1501         free(file);
1502      }
1503
1504    snprintf(buf, sizeof(buf), "%s/dicts", ki->sysdicts);
1505    files = ecore_file_ls(buf);
1506    EINA_LIST_FREE(files, file)
1507      {
1508         p = strrchr(file, '.');
1509         if ((p) && (!strcmp(p, ".dic")))
1510           {
1511              const char *match;
1512
1513              used = 0;
1514              EINA_LIST_FOREACH(ki->dictlist.matches, l, match)
1515                if (!strcmp(match, file)) used = 1;
1516
1517              if (used) goto next2;
1518
1519              p = strdup(file);
1520              if (!p) goto next2;
1521
1522              for (pp = p; *pp; pp++)
1523                {
1524                   if (*pp == '_') *pp = ' ';
1525                }
1526              pp = strrchr(p, '.');
1527              *pp = 0;
1528              str = eina_stringshare_add(file);
1529              ki->dictlist.matches = eina_list_append(ki->dictlist.matches, str);
1530              e_widget_ilist_append(o, NULL, p, _e_kbd_int_cb_dictlist_item_sel,
1531                                    ki, NULL);
1532              free(p);
1533           }
1534         next2:
1535         free(file);
1536      }
1537    e_widget_ilist_thaw(o);
1538    e_widget_ilist_go(o);
1539
1540    e_widget_ilist_preferred_size_get(o, &mw, &mh);
1541    if (mh < (120 *e_scale)) mh = (120 * e_scale);
1542
1543    edje_extern_object_min_size_set(ki->dictlist.ilist_obj, mw, mh);
1544    edje_object_part_swallow(ki->dictlist.base_obj, "e.swallow.content",
1545                             ki->dictlist.ilist_obj);
1546    edje_object_size_min_calc(ki->dictlist.base_obj, &mw, &mh);
1547
1548    e_zone_useful_geometry_get(ki->win->border->zone, NULL, NULL, NULL, &sh);
1549    mw = ki->win->w;
1550    if (mh > (sh - ki->win->h)) mh = (sh - ki->win->h);
1551    e_popup_move_resize(ki->dictlist.popup, 0, ki->win->y - mh, mw, mh);
1552
1553    evas_object_resize(ki->dictlist.base_obj, 
1554                       ki->dictlist.popup->w, ki->dictlist.popup->h);
1555    evas_object_show(ki->dictlist.base_obj);
1556    e_popup_edje_bg_object_set(ki->dictlist.popup, ki->dictlist.base_obj);
1557    e_popup_show(ki->dictlist.popup);
1558    _e_kbd_int_matchlist_down(ki);
1559 }
1560
1561 static void
1562 _e_kbd_int_matchlist_down(E_Kbd_Int *ki)
1563 {
1564    char *str;
1565
1566    if (!ki->matchlist.popup) return;
1567    e_object_del(E_OBJECT(ki->matchlist.popup));
1568    ki->matchlist.popup = NULL;
1569    EINA_LIST_FREE(ki->matchlist.matches, str)
1570      eina_stringshare_del(str);
1571 }
1572
1573 static void
1574 _e_kbd_int_cb_matchlist_item_sel(void *data)
1575 {
1576    E_Kbd_Int *ki;
1577    const char *str;
1578
1579    ki = data;
1580    str = e_widget_ilist_selected_label_get(ki->matchlist.ilist_obj);
1581    _e_kbd_int_string_send(ki, str);
1582    e_kbd_buf_clear(ki->kbuf);
1583    e_kbd_send_keysym_press("space", 0);
1584    if (ki->layout.state & (SHIFT | CTRL | ALT | ALTGR))
1585      {
1586         ki->layout.state &= (~(SHIFT | CTRL | ALT | ALTGR));
1587         _e_kbd_int_layout_state_update(ki);
1588      }
1589    _e_kbd_int_matches_update(ki);
1590    _e_kbd_int_matchlist_down(ki);
1591 }
1592
1593 static void
1594 _e_kbd_int_matchlist_up(E_Kbd_Int *ki)
1595 {
1596    const Eina_List *l;
1597    Evas_Object *o;
1598    Evas_Coord mw, mh, sh;
1599
1600    if (!e_kbd_buf_string_matches_get(ki->kbuf)) return;
1601    if (ki->matchlist.popup) return;
1602    ki->matchlist.popup = e_popup_new(ki->win->border->zone, -1, -1, 1, 1);
1603    e_popup_layer_set(ki->matchlist.popup, 190);
1604
1605    o = _theme_obj_new(ki->matchlist.popup->evas, ki->themedir,
1606                       "e/modules/kbd/match/default");
1607    ki->matchlist.base_obj = o;
1608
1609    o = e_widget_ilist_add(ki->matchlist.popup->evas, 
1610                           (32 * e_scale), (32 * e_scale), NULL);
1611    e_widget_ilist_selector_set(o, 1);
1612    ki->matchlist.ilist_obj = o;
1613    edje_object_part_swallow(ki->matchlist.base_obj, "e.swallow.content", o);
1614    evas_object_show(o);
1615
1616    for (l = e_kbd_buf_string_matches_get(ki->kbuf); l; l = l->next)
1617      {
1618         const char *str;
1619
1620         if (!l->prev)
1621           {
1622              str = e_kbd_buf_actual_string_get(ki->kbuf);
1623              if (str)
1624                {
1625                   str = eina_stringshare_add(str);
1626                   ki->matchlist.matches = eina_list_append(ki->matchlist.matches, str);
1627                   e_widget_ilist_append(o, NULL, str, 
1628                                         _e_kbd_int_cb_matchlist_item_sel,
1629                                         ki, NULL);
1630                }
1631           }
1632         str = l->data;
1633         str = eina_stringshare_add(str);
1634         ki->matchlist.matches = eina_list_append(ki->matchlist.matches, str);
1635         e_widget_ilist_append(o, NULL, str, _e_kbd_int_cb_matchlist_item_sel,
1636                               ki, NULL);
1637      }
1638    e_widget_ilist_thaw(o);
1639    e_widget_ilist_go(o);
1640
1641    e_widget_ilist_preferred_size_get(o, &mw, &mh);
1642    if (mh < (120 *e_scale)) mh = (120 * e_scale);
1643
1644    edje_extern_object_min_size_set(ki->matchlist.ilist_obj, mw, mh);
1645    edje_object_part_swallow(ki->matchlist.base_obj, "e.swallow.content",
1646                                ki->matchlist.ilist_obj);
1647    edje_object_size_min_calc(ki->matchlist.base_obj, &mw, &mh);
1648
1649    edje_extern_object_min_size_set(ki->matchlist.ilist_obj, 0, 0);
1650    edje_object_part_swallow(ki->matchlist.base_obj, "e.swallow.content",
1651                                ki->matchlist.ilist_obj);
1652    e_zone_useful_geometry_get(ki->win->border->zone, NULL, NULL, NULL, &sh);
1653    mw = ki->win->w;
1654    if (mh > (sh - ki->win->h)) mh = (sh - ki->win->h);
1655    e_popup_move_resize(ki->matchlist.popup,
1656                        ki->win->x, ki->win->y - mh, mw, mh);
1657    evas_object_resize(ki->matchlist.base_obj, 
1658                       ki->matchlist.popup->w, ki->matchlist.popup->h);
1659    evas_object_show(ki->matchlist.base_obj);
1660    e_popup_edje_bg_object_set(ki->matchlist.popup, ki->matchlist.base_obj);
1661    e_popup_show(ki->matchlist.popup);
1662
1663    _e_kbd_int_dictlist_down(ki);
1664 }
1665
1666 static void
1667 _e_kbd_int_cb_matches(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1668 {
1669    E_Kbd_Int *ki;
1670
1671    ki = data;
1672    if (ki->dictlist.popup) _e_kbd_int_dictlist_down(ki);
1673    else if (ki->matchlist.popup) _e_kbd_int_matchlist_down(ki);
1674    else
1675      {
1676         if (!e_kbd_buf_actual_string_get(ki->kbuf))
1677           _e_kbd_int_dictlist_up(ki);
1678         else
1679           _e_kbd_int_matchlist_up(ki);
1680      }
1681 }
1682
1683 static void
1684 _e_kbd_int_cb_dicts(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1685 {
1686    E_Kbd_Int *ki;
1687
1688    ki = data;
1689    if (ki->dictlist.popup) _e_kbd_int_dictlist_down(ki);
1690    else _e_kbd_int_dictlist_up(ki);
1691 }
1692
1693 static void
1694 _e_kbd_int_cb_layouts(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1695 {
1696    E_Kbd_Int *ki;
1697
1698    ki = data;
1699    _e_kbd_int_layout_next(ki);
1700 }
1701
1702 static void
1703 _e_kbd_int_cb_resize(E_Win *win)
1704 {
1705    E_Kbd_Int *ki;
1706    E_Kbd_Int_Key *ky;
1707    Eina_List *l;
1708    
1709    ki = win->data;
1710    EINA_LIST_FOREACH(ki->layout.keys, l, ky)
1711      {
1712            if (ky->obj) evas_object_del(ky->obj);
1713            if (ky->icon_obj) evas_object_del(ky->icon_obj);
1714      }
1715    if (ki->event_obj) evas_object_del(ki->event_obj);
1716    ki->event_obj = NULL;
1717    
1718    _e_kbd_int_layout_build(ki);
1719    _e_kbd_int_layout_buf_update(ki);
1720    _e_kbd_int_layout_state_update(ki);
1721 }
1722
1723 EAPI E_Kbd_Int *
1724 e_kbd_int_new(const char *themedir, const char *syskbds, const char *sysdicts)
1725 {
1726    E_Kbd_Int *ki;
1727    Evas_Object *o;
1728    Evas_Coord mw, mh;
1729    E_Zone *zone;
1730    E_Kbd_Int_Layout *kil;
1731    Ecore_X_Window_State states[2];
1732
1733    ki = E_NEW(E_Kbd_Int, 1);
1734    if (!ki) return NULL;
1735    if (themedir) ki->themedir = eina_stringshare_add(themedir);
1736    if (syskbds) ki->syskbds = eina_stringshare_add(syskbds);
1737    if (sysdicts) ki->sysdicts = eina_stringshare_add(sysdicts);
1738    zone = e_util_zone_current_get(e_manager_current_get());
1739    ki->win = e_win_new(zone->container);
1740    states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
1741    states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
1742    ecore_x_netwm_window_state_set(ki->win->evas_win, states, 2);
1743    ecore_x_icccm_hints_set(ki->win->evas_win, 0, 0, 0, 0, 0, 0, 0);
1744    e_win_no_remember_set(ki->win, 1);
1745
1746    mw = zone->w;
1747    mh = zone->h;
1748
1749    if (mw > mh)
1750      e_win_resize(ki->win, mw, (mh / 2));
1751    else
1752      e_win_resize(ki->win, mw, mh);
1753
1754    e_win_resize_callback_set(ki->win, _e_kbd_int_cb_resize);
1755    e_win_borderless_set(ki->win, 1);
1756    ki->win->data = ki;
1757    e_win_name_class_set(ki->win, "Virtual-Keyboard", "Virtual-Keyboard");
1758    e_win_title_set(ki->win, "Virtual Keyboard");
1759
1760    ki->base_obj = _theme_obj_new(ki->win->evas, ki->themedir,
1761                                  "e/modules/kbd/base/default");
1762    edje_object_signal_callback_add(ki->base_obj, "e,action,do,matches", "",
1763                                    _e_kbd_int_cb_matches, ki);
1764    edje_object_signal_callback_add(ki->base_obj, "e,action,do,layouts", "",
1765                                    _e_kbd_int_cb_layouts, ki);
1766    edje_object_signal_callback_add(ki->base_obj, "e,action,do,dicts", "",
1767                                    _e_kbd_int_cb_dicts, ki);
1768
1769    o = e_layout_add(ki->win->evas);
1770    edje_object_part_swallow(ki->base_obj, "e.swallow.content", o);
1771    evas_object_show(o);
1772    ki->layout_obj = o;
1773
1774    o = e_icon_add(ki->win->evas);
1775    evas_object_pass_events_set(o, 1);
1776    e_icon_fill_inside_set(o, 1);
1777    e_icon_scale_up_set(o, 0);
1778    edje_object_part_swallow(ki->base_obj, "e.swallow.layout", o);
1779    evas_object_show(o);
1780    ki->icon_obj = o;
1781
1782    o = e_box_add(ki->win->evas);   
1783    e_box_orientation_set(o, 1);
1784    e_box_homogenous_set(o, 1);
1785    edje_object_part_swallow(ki->base_obj, "e.swallow.label", o);
1786    evas_object_show(o);
1787    ki->box_obj = o;
1788
1789    if (il_kbd_cfg->dict)
1790      ki->kbuf = e_kbd_buf_new(ki->sysdicts, il_kbd_cfg->dict);
1791    else
1792      ki->kbuf = e_kbd_buf_new(ki->sysdicts, "English_US.dic");
1793
1794    _e_kbd_int_layouts_list_update(ki);
1795
1796    kil = _e_kbd_int_layouts_list_default_get(ki);
1797    if ((!kil) && (ki->layouts))
1798      kil = ki->layouts->data;
1799
1800    if (kil) _e_kbd_int_layout_select(ki, kil);
1801
1802    edje_object_size_min_calc(ki->base_obj, &mw, &mh);
1803    if (mw < 48) mw = 48;
1804    if (mh < 48) mh = 48;
1805    evas_object_move(ki->base_obj, 0, 0);
1806    evas_object_resize(ki->base_obj, zone->w, mh);
1807    evas_object_show(ki->base_obj);
1808    
1809    e_win_size_min_set(ki->win, mw, mh);
1810    ecore_x_e_virtual_keyboard_set(ki->win->evas_win, 1);
1811
1812    ki->client_message_handler = 
1813      ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, 
1814                              _e_kbd_int_cb_client_message, ki);
1815    ki->kbd_move_hdl = 
1816      ecore_event_handler_add(E_EVENT_BORDER_MOVE, 
1817                              _e_kbd_int_cb_border_move, ki);
1818
1819    e_win_show(ki->win);
1820    ki->win->border->user_skip_winlist = 1;
1821    ki->win->border->lock_focus_in = 1;
1822    ki->win->border->lock_focus_out = 1;
1823
1824    return ki;
1825 }
1826
1827 EAPI void
1828 e_kbd_int_free(E_Kbd_Int *ki)
1829 {
1830    if (ki->themedir) eina_stringshare_del(ki->themedir);
1831    if (ki->syskbds) eina_stringshare_del(ki->syskbds);
1832    if (ki->sysdicts) eina_stringshare_del(ki->sysdicts);
1833    _e_kbd_int_layouts_free(ki);
1834    _e_kbd_int_matches_free(ki);
1835    _e_kbd_int_layout_free(ki);
1836    ecore_event_handler_del(ki->client_message_handler);
1837    ecore_event_handler_del(ki->kbd_move_hdl);
1838    if (ki->down.hold_timer) ecore_timer_del(ki->down.hold_timer);
1839    _e_kbd_int_matchlist_down(ki);
1840    _e_kbd_int_zoomkey_down(ki);
1841    e_kbd_buf_free(ki->kbuf);
1842    e_object_del(E_OBJECT(ki->win));
1843    E_FREE(ki);
1844 }
1845
1846 static Evas_Object *
1847 _theme_obj_new(Evas *e, const char *custom_dir, const char *group)
1848 {
1849    Evas_Object *o;
1850
1851    o = edje_object_add(e);
1852    if (!e_theme_edje_object_set(o, "base/theme/modules/illume", group))
1853      {
1854         if (custom_dir)
1855           {
1856              char buf[PATH_MAX];
1857
1858              snprintf(buf, sizeof(buf), "%s/e-module-illume-keyboard.edj", 
1859                       custom_dir);
1860              edje_object_file_set(o, buf, group);
1861           }
1862      }
1863    return o;
1864 }
1865
1866 static Eina_Bool
1867 _e_kbd_int_cb_border_move(void *data, int type __UNUSED__, void *event) 
1868 {
1869    E_Event_Border_Move *ev;
1870    E_Kbd_Int *ki;
1871
1872    ev = event;
1873    if (!(ki = data)) return ECORE_CALLBACK_PASS_ON;
1874    if (ki->win->border != ev->border) return ECORE_CALLBACK_PASS_ON;
1875    _e_kbd_int_zoomkey_down(ki);
1876    _e_kbd_int_matchlist_down(ki);
1877    _e_kbd_int_dictlist_down(ki);
1878    return ECORE_CALLBACK_PASS_ON;
1879 }