1 #include "e_illume_private.h"
3 #include "e_mod_kbd_device.h"
5 /* local function prototypes */
6 static Eina_Bool _e_mod_kbd_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event);
7 static Eina_Bool _e_mod_kbd_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event);
8 static Eina_Bool _e_mod_kbd_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
9 static Eina_Bool _e_mod_kbd_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
10 static Eina_Bool _e_mod_kbd_cb_border_property(void *data __UNUSED__, int type __UNUSED__, void *event);
11 static void _e_mod_kbd_cb_border_pre_post_fetch(void *data __UNUSED__, void *data2);
12 static void _e_mod_kbd_cb_free(E_Illume_Keyboard *kbd);
13 static Eina_Bool _e_mod_kbd_cb_delay_hide(void *data __UNUSED__);
14 static void _e_mod_kbd_hide(void);
15 static void _e_mod_kbd_slide(int visible, double len);
16 static Eina_Bool _e_mod_kbd_cb_animate(void *data __UNUSED__);
17 static E_Illume_Keyboard *_e_mod_kbd_by_border_get(E_Border *bd);
18 static void _e_mod_kbd_border_adopt(E_Border *bd);
19 static void _e_mod_kbd_layout_send(void);
20 static void _e_mod_kbd_geometry_send(void);
21 static void _e_mod_kbd_changes_send(void);
24 static Eina_List *_kbd_hdls = NULL;
25 static E_Border_Hook *_kbd_hook = NULL;
26 static Ecore_X_Atom _focused_state = 0;
27 static E_Border *_focused_border = NULL, *_prev_focused_border = NULL;
32 /* add handlers for events we are interested in */
34 eina_list_append(_kbd_hdls,
35 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
36 _e_mod_kbd_cb_client_message,
39 eina_list_append(_kbd_hdls,
40 ecore_event_handler_add(E_EVENT_BORDER_REMOVE,
41 _e_mod_kbd_cb_border_remove,
44 eina_list_append(_kbd_hdls,
45 ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN,
46 _e_mod_kbd_cb_border_focus_in,
49 eina_list_append(_kbd_hdls,
50 ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT,
51 _e_mod_kbd_cb_border_focus_out,
54 eina_list_append(_kbd_hdls,
55 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
56 _e_mod_kbd_cb_border_property,
59 /* add hooks for events we are interested in */
60 _kbd_hook = e_border_hook_add(E_BORDER_HOOK_EVAL_PRE_POST_FETCH,
61 _e_mod_kbd_cb_border_pre_post_fetch, NULL);
63 /* initialize the device subsystem */
64 e_mod_kbd_device_init();
70 e_mod_kbd_shutdown(void)
72 Ecore_Event_Handler *hdl;
74 /* shutdown the device subsystem */
75 e_mod_kbd_device_shutdown();
77 /* destroy the hook */
78 e_border_hook_del(_kbd_hook);
80 /* destroy the handlers and free the list */
81 EINA_LIST_FREE(_kbd_hdls, hdl)
82 ecore_event_handler_del(hdl);
90 E_Illume_Keyboard *kbd;
92 /* try to allocate our new keyboard object */
93 kbd = E_OBJECT_ALLOC(E_Illume_Keyboard, E_ILLUME_KBD_TYPE,
95 if (!kbd) return NULL;
97 /* set default layout on new keyboard */
98 kbd->layout = E_ILLUME_KEYBOARD_LAYOUT_ALPHA;
105 e_mod_kbd_enable(void)
107 /* don't try to enable a keyboard that is already enabled */
108 if (!_e_illume_kbd->disabled) return;
110 /* set keyboard to enabled */
111 _e_illume_kbd->disabled = 0;
113 /* show it if we need to */
114 if (!_e_illume_kbd->visible) e_mod_kbd_show();
118 e_mod_kbd_disable(void)
120 /* don't try to disable a keyboard that is already disabled */
121 if (_e_illume_kbd->disabled) return;
123 /* hide it if we need to */
124 if (_e_illume_kbd->visible) e_mod_kbd_hide();
126 /* set keyboard to disabled */
127 _e_illume_kbd->disabled = 1;
133 /* destroy existing timer */
134 if (_e_illume_kbd->timer) ecore_timer_del(_e_illume_kbd->timer);
135 _e_illume_kbd->timer = NULL;
137 /* destroy the animator if it exists */
138 if (_e_illume_kbd->animator) ecore_animator_del(_e_illume_kbd->animator);
139 _e_illume_kbd->animator = NULL;
141 if ((_focused_border) && (_e_illume_kbd->border))
143 if (_e_illume_kbd->border->zone != _focused_border->zone)
144 e_border_zone_set(_e_illume_kbd->border, _focused_border->zone);
147 /* if it's disabled, get out */
148 if (_e_illume_kbd->disabled) return;
150 // _e_mod_kbd_layout_send();
152 /* if we are not animating, just show it */
153 if (_e_illume_cfg->animation.vkbd.duration <= 0)
155 /* show the border */
156 if (_e_illume_kbd->border)
158 e_border_fx_offset(_e_illume_kbd->border, 0, 0);
159 if (!_e_illume_kbd->border->visible)
160 e_border_show(_e_illume_kbd->border);
161 e_border_raise(_e_illume_kbd->border);
163 _e_illume_kbd->visible = 1;
165 _e_mod_kbd_geometry_send();
167 _e_mod_kbd_changes_send();
171 /* show the border */
172 if (_e_illume_kbd->border)
174 if (!_e_illume_kbd->border->visible)
175 e_border_show(_e_illume_kbd->border);
176 e_border_raise(_e_illume_kbd->border);
180 _e_mod_kbd_slide(1, (double)_e_illume_cfg->animation.vkbd.duration / 1000.0);
187 /* cannot hide keyboard that is not visible */
188 // if (!_e_illume_kbd->visible) return;
190 /* create new hide timer if it doesn't exist */
191 if (!_e_illume_kbd->timer)
192 _e_illume_kbd->timer = ecore_timer_add(0.2, _e_mod_kbd_cb_delay_hide, NULL);
196 e_mod_kbd_toggle(void)
198 if (_e_illume_kbd->visible) e_mod_kbd_hide();
199 else e_mod_kbd_show();
203 e_mod_kbd_fullscreen_set(E_Zone *zone, int fullscreen)
205 if (!_e_illume_kbd->border) return;
206 if (_e_illume_kbd->border->zone != zone) return;
207 if ((!!fullscreen) != _e_illume_kbd->fullscreen)
208 _e_illume_kbd->fullscreen = fullscreen;
212 e_mod_kbd_layout_set(E_Illume_Keyboard_Layout layout)
214 if (!_e_illume_kbd->border) return;
215 _e_illume_kbd->layout = layout;
216 _e_mod_kbd_layout_send();
219 /* local functions */
221 _e_mod_kbd_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event)
223 Ecore_X_Event_Client_Message *ev;
226 if (ev->win != ecore_x_window_root_first_get())
227 return ECORE_CALLBACK_PASS_ON;
229 /* legacy illume 1 code */
230 if ((ev->message_type == ecore_x_atom_get("_MB_IM_INVOKER_COMMAND")) ||
231 (ev->message_type == ecore_x_atom_get("_MTP_IM_INVOKER_COMMAND")))
233 if (ev->data.l[0] == 1) e_mod_kbd_show();
234 else if (ev->data.l[0] == 2) e_mod_kbd_hide();
235 else if (ev->data.l[0] == 3) e_mod_kbd_toggle();
237 return ECORE_CALLBACK_PASS_ON;
241 _e_mod_kbd_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event)
243 E_Event_Border_Remove *ev;
244 E_Illume_Keyboard *kbd;
248 /* if we removed the focused border, reset some variables */
249 if ((_prev_focused_border) && (_prev_focused_border == ev->border))
250 _prev_focused_border = NULL;
251 if ((_focused_border) && (_focused_border == ev->border))
254 _focused_border = NULL;
256 return ECORE_CALLBACK_PASS_ON;
259 /* try to find the keyboard for this border */
260 if (!(kbd = _e_mod_kbd_by_border_get(ev->border)))
261 return ECORE_CALLBACK_PASS_ON;
263 if ((kbd->border) && (kbd->border == ev->border))
266 if (kbd->waiting_borders)
270 bd = kbd->waiting_borders->data;
271 kbd->waiting_borders =
272 eina_list_remove_list(kbd->waiting_borders, kbd->waiting_borders);
274 _e_mod_kbd_border_adopt(bd);
278 e_border_hide(ev->border, 2);
282 else if (!kbd->border)
283 kbd->waiting_borders = eina_list_remove(kbd->waiting_borders, ev->border);
285 return ECORE_CALLBACK_PASS_ON;
289 _e_mod_kbd_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
291 E_Event_Border_Focus_In *ev;
294 if (_e_mod_kbd_by_border_get(ev->border)) return ECORE_CALLBACK_PASS_ON;
296 // printf("Kbd Focus in: %s\n", ev->border->client.icccm.name);
298 /* set focused border for kbd */
299 _focused_border = ev->border;
300 _focused_state = ev->border->client.vkbd.state;
302 if (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
307 return ECORE_CALLBACK_PASS_ON;
311 _e_mod_kbd_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
313 E_Event_Border_Focus_Out *ev;
316 if (_e_mod_kbd_by_border_get(ev->border)) return ECORE_CALLBACK_PASS_ON;
318 // printf("Kbd Focus Out: %s\n", ev->border->client.icccm.name);
320 _prev_focused_border = _focused_border;
322 /* hide the keyboard */
325 /* tell the focused border it changed so layout gets udpated */
326 if (_prev_focused_border)
328 if (!e_illume_border_is_conformant(_prev_focused_border))
330 _prev_focused_border->changes.size = 1;
331 _prev_focused_border->changed = 1;
335 /* reset some variables */
336 _focused_border = NULL;
339 return ECORE_CALLBACK_PASS_ON;
343 _e_mod_kbd_cb_border_property(void *data __UNUSED__, int type __UNUSED__, void *event)
345 Ecore_X_Event_Window_Property *ev;
351 /* only interested in vkbd state changes here */
352 if (ev->atom != ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
353 return ECORE_CALLBACK_PASS_ON;
355 /* make sure we have a border */
356 if (!(bd = e_border_find_by_client_window(ev->win)))
357 return ECORE_CALLBACK_PASS_ON;
359 // printf("Kbd Border Property Change: %s\n", bd->client.icccm.name);
361 /* if it's not focused, we don't care */
362 if ((!bd->focused) || (_e_mod_kbd_by_border_get(bd)))
363 return ECORE_CALLBACK_PASS_ON;
365 /* NB: Not sure why, but we seem to need to fetch kbd state here. This could
366 * be a result of filtering the container_hook_layout. Not real happy
367 * with this because it is an X round-trip, but it is here because this
368 * needs more time to investigate. */
369 e_hints_window_virtual_keyboard_state_get(bd);
371 if ((_focused_border) && (_focused_border == bd))
373 /* if focused state is the same, get out */
374 if (_focused_state == bd->client.vkbd.state)
375 return ECORE_CALLBACK_PASS_ON;
378 /* set our variables */
379 _focused_border = bd;
380 _focused_state = bd->client.vkbd.state;
382 /* handle a border needing fullscreen keyboard */
383 if ((bd->need_fullscreen) || (bd->fullscreen)) fullscreen = 1;
384 if (_e_illume_kbd->fullscreen != fullscreen)
385 e_mod_kbd_fullscreen_set(bd->zone, fullscreen);
387 if (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
392 return ECORE_CALLBACK_PASS_ON;
396 _e_mod_kbd_cb_border_pre_post_fetch(void *data __UNUSED__, void *data2)
400 if (!(bd = data2)) return;
401 if (!bd->new_client) return;
402 if (_e_mod_kbd_by_border_get(bd)) return;
403 if (e_illume_border_is_keyboard(bd))
405 if (!_e_illume_kbd->border)
406 _e_mod_kbd_border_adopt(bd);
409 _e_illume_kbd->waiting_borders =
410 eina_list_append(_e_illume_kbd->waiting_borders, bd);
417 _e_mod_kbd_cb_free(E_Illume_Keyboard *kbd)
421 /* destroy the animator if it exists */
422 if (kbd->animator) ecore_animator_del(kbd->animator);
423 kbd->animator = NULL;
425 /* destroy the timer if it exists */
426 if (kbd->timer) ecore_timer_del(kbd->timer);
429 /* free the list of waiting borders */
430 EINA_LIST_FREE(kbd->waiting_borders, bd)
433 /* free the keyboard structure */
438 _e_mod_kbd_cb_delay_hide(void *data __UNUSED__)
441 return ECORE_CALLBACK_CANCEL;
445 _e_mod_kbd_hide(void)
447 /* destroy existing timer */
448 if (_e_illume_kbd->timer) ecore_timer_del(_e_illume_kbd->timer);
449 _e_illume_kbd->timer = NULL;
451 /* destroy the animator if it exists */
452 if (_e_illume_kbd->animator) ecore_animator_del(_e_illume_kbd->animator);
453 _e_illume_kbd->animator = NULL;
455 /* can't hide keyboard if it's disabled */
456 if (_e_illume_kbd->disabled) return;
458 // _e_mod_kbd_layout_send();
460 /* if we are not animating, just hide it */
461 if (_e_illume_cfg->animation.vkbd.duration <= 0)
463 if (_e_illume_kbd->border)
465 e_border_fx_offset(_e_illume_kbd->border, 0,
466 _e_illume_kbd->border->h);
467 e_border_hide(_e_illume_kbd->border, 2);
469 _e_illume_kbd->visible = 0;
471 _e_mod_kbd_geometry_send();
473 _e_mod_kbd_changes_send();
476 _e_mod_kbd_slide(0, (double)_e_illume_cfg->animation.vkbd.duration / 1000.0);
480 _e_mod_kbd_slide(int visible, double len)
482 _e_illume_kbd->start = ecore_loop_time_get();
483 _e_illume_kbd->len = len;
484 _e_illume_kbd->adjust_start = _e_illume_kbd->adjust;
485 _e_illume_kbd->adjust_end = 0;
486 if ((visible) && (_e_illume_kbd->border))
487 _e_illume_kbd->adjust_end = _e_illume_kbd->border->h;
488 if (!_e_illume_kbd->animator)
489 _e_illume_kbd->animator = ecore_animator_add(_e_mod_kbd_cb_animate, NULL);
493 _e_mod_kbd_cb_animate(void *data __UNUSED__)
497 t = (ecore_loop_time_get() - _e_illume_kbd->start);
498 if (t > _e_illume_kbd->len) t = _e_illume_kbd->len;
499 if (_e_illume_kbd->len > 0.0)
501 v = (t / _e_illume_kbd->len);
508 t = _e_illume_kbd->len;
511 _e_illume_kbd->adjust = ((_e_illume_kbd->adjust_end * v) +
512 (_e_illume_kbd->adjust_start * (1.0 - v)));
514 if (_e_illume_kbd->border)
515 e_border_fx_offset(_e_illume_kbd->border, 0,
516 (_e_illume_kbd->border->h - _e_illume_kbd->adjust));
518 if (t == _e_illume_kbd->len)
520 _e_illume_kbd->animator = NULL;
521 if (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
523 if (_e_illume_kbd->border)
524 e_border_hide(_e_illume_kbd->border, 2);
525 _e_illume_kbd->visible = 0;
528 _e_illume_kbd->visible = 1;
530 _e_mod_kbd_geometry_send();
532 _e_mod_kbd_changes_send();
534 return ECORE_CALLBACK_CANCEL;
537 return ECORE_CALLBACK_RENEW;
540 static E_Illume_Keyboard *
541 _e_mod_kbd_by_border_get(E_Border *bd)
546 if ((!bd) || (!bd->stolen)) return NULL;
548 /* if this border is the one that vkbd is working with, return the kbd */
549 if (_e_illume_kbd->border == bd) return _e_illume_kbd;
551 /* loop the waiting borders */
552 EINA_LIST_FOREACH(_e_illume_kbd->waiting_borders, l, over)
553 if (over == bd) return _e_illume_kbd;
559 _e_mod_kbd_border_adopt(E_Border *bd)
561 if ((!_e_illume_kbd) || (!bd)) return;
563 _e_illume_kbd->border = bd;
565 if (!_e_illume_kbd->visible)
567 e_border_fx_offset(bd, 0, bd->h);
568 _e_mod_kbd_layout_send();
573 _e_mod_kbd_layout_send(void)
575 Ecore_X_Virtual_Keyboard_State type;
577 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
578 if ((!_e_illume_kbd->visible) && (!_e_illume_kbd->disabled))
580 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ON;
581 if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_DEFAULT)
582 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ON;
583 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_ALPHA)
584 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA;
585 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_NUMERIC)
586 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC;
587 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_PIN)
588 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN;
589 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_PHONE_NUMBER)
590 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER;
591 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_HEX)
592 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX;
593 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_TERMINAL)
594 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL;
595 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_PASSWORD)
596 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD;
597 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_IP)
598 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_IP;
599 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_HOST)
600 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST;
601 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_FILE)
602 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE;
603 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_URL)
604 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_URL;
605 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_KEYPAD)
606 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD;
607 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_J2ME)
608 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME;
609 else if (_e_illume_kbd->layout == E_ILLUME_KEYBOARD_LAYOUT_NONE)
610 type = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
612 if (_e_illume_kbd->border)
613 ecore_x_e_virtual_keyboard_state_send(_e_illume_kbd->border->client.win, type);
617 _e_mod_kbd_geometry_send(void)
622 /* make sure we have a keyboard border */
623 if (!_e_illume_kbd->border) return;
625 /* adjust Y for keyboard visibility */
626 if (_e_illume_kbd->border->fx.y <= 0)
627 y = _e_illume_kbd->border->y;
629 if (_focused_border) zone = _focused_border->zone;
630 else zone = _e_illume_kbd->border->zone;
632 ecore_x_e_illume_keyboard_geometry_set(zone->black_win,
633 _e_illume_kbd->border->x, y,
634 _e_illume_kbd->border->w,
635 _e_illume_kbd->border->h);
639 _e_mod_kbd_changes_send(void)
641 if (((_prev_focused_border) && (_focused_border)) &&
642 (_prev_focused_border != _focused_border))
644 /* tell previous focused border it changed so layout udpates */
645 if (_prev_focused_border->client.vkbd.state >
646 ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN)
648 if (!e_illume_border_is_conformant(_prev_focused_border))
650 _prev_focused_border->changes.size = 1;
651 _prev_focused_border->changed = 1;
656 /* tell the focused border it changed so layout gets udpated */
657 if ((_focused_border) &&
658 (_focused_border->client.vkbd.state >
659 ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN))
661 if (!e_illume_border_is_conformant(_focused_border))
663 _focused_border->changes.size = 1;
664 _focused_border->changed = 1;