diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index 6224f6dd4..15116c2fb 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -239,7 +239,7 @@ SUBDIRS += connman endif if USE_MODULE_ILLUME -SUBDIRS += illume illume2 illume-home illume-bar +SUBDIRS += illume illume2 illume-home illume-bar illume-keyboard endif if USE_MODULE_SYSCON diff --git a/src/modules/conf_wallpaper/e_int_config_wallpaper_web.c b/src/modules/conf_wallpaper/e_int_config_wallpaper_web.c index 93f2668d6..762504aff 100644 --- a/src/modules/conf_wallpaper/e_int_config_wallpaper_web.c +++ b/src/modules/conf_wallpaper/e_int_config_wallpaper_web.c @@ -26,7 +26,9 @@ _web_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) evas_object_geometry_get(obj, NULL, NULL, NULL, &vh); if (y < 0) y = 0; - if (y > th - vh) y = th - vh; + printf("Web Pan Set: %d %d\n", th, vh); + if (y > vh - th) y = vh - th; + printf("Web Pan Offset: %d\n", y); exchange_smart_object_offset_set(obj, 0, y); } diff --git a/src/modules/illume-keyboard/Makefile.am b/src/modules/illume-keyboard/Makefile.am new file mode 100644 index 000000000..423215061 --- /dev/null +++ b/src/modules/illume-keyboard/Makefile.am @@ -0,0 +1,33 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume-kbd + +# data files for the module +filesdir = $(libdir)/enlightenment/modules/$(MODULE) +files_DATA = \ +e-module-$(MODULE).edj module.desktop + +EXTRA_DIST = $(files_DATA) + +# the module .so file +INCLUDES = -I. \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/modules/$(MODULE) \ + -I$(top_srcdir)/src/bin \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/modules \ + @e_cflags@ +pkgdir = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la +module_la_SOURCES = e_mod_main.c \ + e_mod_main.h \ + e_kbd.h \ + e_kbd.c \ + e_kbd_dbus.h \ + e_kbd_dbus.c + +module_la_LIBADD = @e_libs@ @dlopen_libs@ +module_la_LDFLAGS = -module -avoid-version +module_la_DEPENDENCIES = $(top_builddir)/config.h + +uninstall: + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE) diff --git a/src/modules/illume-keyboard/e-module-illume-kbd.edj b/src/modules/illume-keyboard/e-module-illume-kbd.edj new file mode 100644 index 000000000..8e3511a50 Binary files /dev/null and b/src/modules/illume-keyboard/e-module-illume-kbd.edj differ diff --git a/src/modules/illume-keyboard/e_kbd.c b/src/modules/illume-keyboard/e_kbd.c new file mode 100644 index 000000000..951a3dd71 --- /dev/null +++ b/src/modules/illume-keyboard/e_kbd.c @@ -0,0 +1,738 @@ +#include "e.h" +#include "e_kbd.h" +#include "e_kbd_dbus.h" + +/* local function prototypes */ +static int _e_kbd_cb_client_message(void *data, int type, void *event); +static int _e_kbd_cb_border_remove(void *data, int type, void *event); +static int _e_kbd_cb_border_focus_in(void *data, int type, void *event); +static int _e_kbd_cb_border_focus_out(void *data, int type, void *event); +static int _e_kbd_cb_border_property(void *data, int type, void *event); +static void _e_kbd_cb_border_hook_pre_post_fetch(void *data, void *data2); +static void _e_kbd_cb_border_hook_post_border_assign(void *data, void *data2); +static void _e_kbd_cb_border_hook_end(void *data, void *data2); +static int _e_kbd_cb_delayed_hide(void *data); +static void _e_kbd_layout_send(E_Kbd *kbd); +static void _e_kbd_cb_apply_all_job(void *data); +static void _e_kbd_apply_all_job_queue(void); +static void _e_kbd_apply_all_job_queue_end(void); +static void _e_kbd_apply_all_job(void *data); +static void _e_kbd_free(E_Kbd *kbd); +static E_Kbd *_e_kbd_by_border_get(E_Border *bd); +static void _e_kbd_border_adopt(E_Kbd *kbd, E_Border *bd); +static void _e_kbd_border_hide(E_Border *bd); +static int _e_kbd_border_is_keyboard(E_Border *bd); + +/* local variables */ +static Eina_List *handlers = NULL; +static Eina_List *hooks = NULL; +static Eina_List *kbds = NULL; +static Ecore_X_Atom atom_mb = 0; +static Ecore_X_Atom atom_mtp = 0; +static Ecore_Job *_apply_all_job = NULL; +static E_Border *focused_border = NULL; +static Ecore_X_Atom focused_vkbd_state = 0; + +EAPI int +e_kbd_init(E_Module *m) +{ + focused_border = NULL; + focused_vkbd_state = 0; + atom_mb = ecore_x_atom_get("_MB_IM_INVOKER_COMMAND"); + atom_mtp = ecore_x_atom_get("_MTP_IM_INVOKER_COMMAND"); + + handlers = + eina_list_append(handlers, + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _e_kbd_cb_client_message, NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_REMOVE, + _e_kbd_cb_border_remove, NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, + _e_kbd_cb_border_focus_in, NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, + _e_kbd_cb_border_focus_out, NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_PROPERTY, + _e_kbd_cb_border_property, NULL)); + + hooks = + eina_list_append(hooks, + e_border_hook_add(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, + _e_kbd_cb_border_hook_pre_post_fetch, + NULL)); + hooks = + eina_list_append(hooks, + e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, + _e_kbd_cb_border_hook_post_border_assign, + NULL)); + hooks = + eina_list_append(hooks, + e_border_hook_add(E_BORDER_HOOK_EVAL_END, + _e_kbd_cb_border_hook_end, NULL)); + + e_kbd_dbus_real_kbd_init(); + return 1; +} + +EAPI int +e_kbd_shutdown(void) +{ + E_Border_Hook *hook; + Ecore_Event_Handler *handle; + + _e_kbd_apply_all_job_queue_end(); + e_kbd_dbus_real_kbd_shutdown(); + EINA_LIST_FREE(handlers, handle) + ecore_event_handler_del(handle); + EINA_LIST_FREE(hooks, hook) + e_border_hook_del(hook); + + focused_border = NULL; + focused_vkbd_state = 0; + + return 1; +} + +EAPI E_Kbd * +e_kbd_new(E_Zone *zone, const char *themedir, const char *syskbds, const char *sysdicts) +{ + E_Kbd *kbd; + + kbd = E_OBJECT_ALLOC(E_Kbd, E_KBD_TYPE, _e_kbd_free); + if (!kbd) return NULL; + kbds = eina_list_append(kbds, kbd); + kbd->layout = ECORE_X_VIRTUAL_KEYBOARD_STATE_ON; + return kbd; +} + +EAPI void +e_kbd_enable(E_Kbd *kbd) +{ + if (!kbd) return; + if (!kbd->disabled) return; + kbd->disabled = 0; + if (kbd->visible) + { + kbd->visible = 0; + e_kbd_show(kbd); + } +} + +EAPI void +e_kbd_disable(E_Kbd *kbd) +{ + if (!kbd) return; + if (kbd->disabled) return; + if (kbd->visible) e_kbd_hide(kbd); + kbd->disabled = 1; +} + +EAPI void +e_kbd_show(E_Kbd *kbd) +{ + if (!kbd) return; + if (kbd->delay_hide) + { + ecore_timer_del(kbd->delay_hide); + kbd->delay_hide = NULL; + } + if (kbd->visible) return; + kbd->visible = 1; + if (kbd->disabled) return; + kbd->actually_visible = kbd->visible; + _e_kbd_layout_send(kbd); +#if 0 +#endif +} + +EAPI void +e_kbd_layout_set(E_Kbd *kbd, E_Kbd_Layout layout) +{ + if (!kbd) return; + kbd->layout = layout; + _e_kbd_layout_send(kbd); +} + +EAPI void +e_kbd_hide(E_Kbd *kbd) +{ + if ((!kbd) || (!kbd->visible)) return; + kbd->visible = 0; + if (!kbd->delay_hide) + kbd->delay_hide = ecore_timer_add(0.2, _e_kbd_cb_delayed_hide, kbd); +} + +EAPI void +e_kbd_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h) +{ + Eina_List *l; + E_Kbd *kbd; + + if (x) *x = zone->x; + if (y) *y = zone->y; + if (w) *w = zone->w; + if (h) *h = zone->h; + EINA_LIST_FOREACH(kbds, l, kbd) + { + if ((kbd->border) && (kbd->border->zone == zone)) + { + if ((kbd->visible) && (!kbd->animator) && (!kbd->disabled)) + { + if (h) + { + *h -= kbd->border->h; + if (*h < 0) *h = 0; + } + } + return; + } + } +} + +EAPI void +e_kbd_fullscreen_set(E_Zone *zone, int fullscreen) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + if ((!!fullscreen) != kbd->fullscreen) + { + kbd->fullscreen = fullscreen; + if (kbd->fullscreen) + e_border_layer_set(kbd->border, 250); + else + e_border_layer_set(kbd->border, 100); + } +} + +EAPI void +e_kbd_all_enable(void) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + e_kbd_enable(kbd); +} + +EAPI void +e_kbd_all_disable(void) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + e_kbd_disable(kbd); +} + +EAPI void +e_kbd_all_show(void) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + e_kbd_show(kbd); +} + +EAPI void +e_kbd_all_hide(void) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + e_kbd_hide(kbd); +} + +EAPI void +e_kbd_all_toggle(void) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + { + if (kbd->visible) + e_kbd_hide(kbd); + else + e_kbd_show(kbd); + } +} + +EAPI void +e_kbd_all_layout_set(E_Kbd_Layout layout) +{ + Eina_List *l; + E_Kbd *kbd; + + EINA_LIST_FOREACH(kbds, l, kbd) + e_kbd_layout_set(kbd, layout); +} + +/* local function prototypes */ +static int +_e_kbd_cb_client_message(void *data, int type, void *event) +{ + Ecore_X_Event_Client_Message *ev; + + ev = event; + if ((ev->win == ecore_x_window_root_first_get()) && + ((ev->message_type == atom_mb) || (ev->message_type == atom_mtp))) + { + if (ev->data.l[0] == 1) e_kbd_all_show(); + else if (ev->data.l[0] == 2) e_kbd_all_hide(); + else if (ev->data.l[0] == 3) e_kbd_all_toggle(); + } + return 1; +} + +static int +_e_kbd_cb_border_remove(void *data, int type, void *event) +{ + E_Event_Border_Remove *ev; + E_Kbd *kbd; + + ev = event; + if (ev->border == focused_border) + { + focused_border = NULL; + focused_vkbd_state = 0; + return 1; + } + kbd = _e_kbd_by_border_get(ev->border); + if (!kbd) return 1; + if (kbd->border == ev->border) + { + kbd->border = NULL; + if (kbd->waiting_borders) + { + E_Border *bd; + + bd = kbd->waiting_borders->data; + kbd->waiting_borders = + eina_list_remove_list(kbd->waiting_borders, + kbd->waiting_borders); + _e_kbd_border_adopt(kbd, bd); + } + if (kbd->visible) + { + kbd->visible = 0; + _e_kbd_border_hide(kbd->border); + kbd->actually_visible = kbd->visible; + e_kbd_show(kbd); + } + _e_kbd_apply_all_job_queue(); + } + else + kbd->waiting_borders = eina_list_remove(kbd->waiting_borders, ev->border); + return 1; +} + +static int +_e_kbd_cb_border_focus_in(void *data, int type, void *event) +{ + E_Event_Border_Focus_In *ev; + + ev = event; + if (_e_kbd_by_border_get(ev->border)) return 1; + if ((ev->border->need_fullscreen) || (ev->border->fullscreen)) + e_kbd_fullscreen_set(ev->border->zone, 1); + else + e_kbd_fullscreen_set(ev->border->zone, 0); + focused_border = ev->border; + focused_vkbd_state = ev->border->client.vkbd.state; + if (ev->border->client.vkbd.state == 0) return 1; + if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) + { + e_kbd_all_layout_set(E_KBD_LAYOUT_NONE); + e_kbd_all_hide(); + return 1; + } + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA) + e_kbd_all_layout_set(E_KBD_LAYOUT_ALPHA); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC) + e_kbd_all_layout_set(E_KBD_LAYOUT_NUMERIC); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN) + e_kbd_all_layout_set(E_KBD_LAYOUT_PIN); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER) + e_kbd_all_layout_set(E_KBD_LAYOUT_PHONE_NUMBER); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX) + e_kbd_all_layout_set(E_KBD_LAYOUT_HEX); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL) + e_kbd_all_layout_set(E_KBD_LAYOUT_TERMINAL); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD) + e_kbd_all_layout_set(E_KBD_LAYOUT_PASSWORD); + else + e_kbd_all_layout_set(E_KBD_LAYOUT_DEFAULT); + e_kbd_all_show(); + return 1; +} + +static int +_e_kbd_cb_border_focus_out(void *data, int type, void *event) +{ + E_Event_Border_Focus_Out *ev; + + ev = event; + if (_e_kbd_by_border_get(ev->border)) return 1; + if ((ev->border->need_fullscreen) || (ev->border->fullscreen)) + e_kbd_fullscreen_set(ev->border->zone, 1); + else + e_kbd_fullscreen_set(ev->border->zone, 0); + e_kbd_all_layout_set(E_KBD_LAYOUT_NONE); + e_kbd_all_hide(); + focused_border = NULL; + focused_vkbd_state = 0; + return 1; +} + +static int +_e_kbd_cb_border_property(void *data, int type, void *event) +{ + E_Event_Border_Property *ev; + + ev = event; + if (_e_kbd_by_border_get(ev->border)) return 1; + if (!ev->border->focused) return 1; + if ((ev->border == focused_border) && + (ev->border->client.vkbd.state == focused_vkbd_state)) return 1; + if ((ev->border->need_fullscreen) || (ev->border->fullscreen)) + e_kbd_fullscreen_set(ev->border->zone, 1); + else + e_kbd_fullscreen_set(ev->border->zone, 0); + if (ev->border->client.vkbd.state == 0) return 1; + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) + e_kbd_all_hide(); + else + { + if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA) + e_kbd_all_layout_set(E_KBD_LAYOUT_ALPHA); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC) + e_kbd_all_layout_set(E_KBD_LAYOUT_NUMERIC); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN) + e_kbd_all_layout_set(E_KBD_LAYOUT_PIN); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER) + e_kbd_all_layout_set(E_KBD_LAYOUT_PHONE_NUMBER); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX) + e_kbd_all_layout_set(E_KBD_LAYOUT_HEX); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL) + e_kbd_all_layout_set(E_KBD_LAYOUT_TERMINAL); + else if (ev->border->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD) + e_kbd_all_layout_set(E_KBD_LAYOUT_PASSWORD); + else + e_kbd_all_layout_set(E_KBD_LAYOUT_DEFAULT); + e_kbd_all_show(); + } + return 1; +} + +static void +_e_kbd_cb_border_hook_pre_post_fetch(void *data, void *data2) +{ + Eina_List *l; + E_Kbd *kbd; + E_Border *bd; + + if (!(bd = data2)) return; + if (!bd->new_client) return; + if (_e_kbd_by_border_get(bd)) return; + if (!_e_kbd_border_is_keyboard(bd)) return; + EINA_LIST_FOREACH(kbds, l, kbd) + { + if (!kbd->border) + { + _e_kbd_border_adopt(kbd, bd); + bd->stolen = 1; + if (bd->remember) + { + if (bd->bordername) + { + eina_stringshare_del(bd->bordername); + bd->bordername = NULL; + bd->client.border.changed = 1; + } + e_remember_unuse(bd->remember); + bd->remember = NULL; + } + eina_stringshare_replace(&bd->bordername, "borderless"); + bd->client.border.changed = 1; + return; + } + else + { + kbd->waiting_borders = eina_list_append(kbd->waiting_borders, bd); + bd->stolen = 1; + if (bd->remember) + { + if (bd->bordername) + { + eina_stringshare_del(bd->bordername); + bd->bordername = NULL; + bd->client.border.changed = 1; + } + e_remember_unuse(bd->remember); + bd->remember = NULL; + } + eina_stringshare_replace(&bd->bordername, "borderless"); + bd->client.border.changed = 1; + return; + } + } +} + +static void +_e_kbd_cb_border_hook_post_border_assign(void *data, void *data2) +{ + E_Kbd *kbd; + E_Border *bd; + int pbx, pby, pbw, pbh; + + if (!(bd = data2)) return; + kbd = _e_kbd_by_border_get(bd); + if (!kbd) return; + + pbx = bd->x; + pby = bd->y; + pbw = bd->w; + pbh = bd->h; + + bd->lock_border = 1; + + bd->lock_client_location = 1; + bd->lock_client_size = 1; + bd->lock_client_desk = 1; + bd->lock_client_sticky = 1; + bd->lock_client_shade = 1; + bd->lock_client_maximize = 1; + + bd->lock_user_location = 1; + bd->lock_user_size = 1; + bd->lock_user_desk = 1; + bd->lock_user_sticky = 1; + bd->lock_user_shade = 1; + bd->lock_user_maximize = 1; + + bd->client.icccm.accepts_focus = 0; + bd->client.icccm.take_focus = 0; + + bd->w = bd->zone->w; + bd->h = bd->h; + bd->x = bd->zone->x; + bd->y = bd->zone->y + bd->zone->h - bd->h; + + bd->client.w = bd->w - bd->client_inset.l - bd->client_inset.r; + bd->client.h = bd->h - bd->client_inset.t - bd->client_inset.b; + + bd->changes.size = 1; + bd->placed = 1; + + if ((pbx != bd->x) || (pby != bd->y) || + (pbw != bd->w) || (pbh != bd->h)) + { + if (bd->internal_ecore_evas) + { + ecore_evas_managed_move(bd->internal_ecore_evas, + bd->x + bd->fx.x + bd->client_inset.l, + bd->y + bd->fx.y + bd->client_inset.t); + } + ecore_x_icccm_move_resize_send(bd->client.win, + bd->x + bd->fx.x + bd->client_inset.l, + bd->y + bd->fx.y + bd->client_inset.t, + bd->client.w, + bd->client.h); + bd->changed = 1; + bd->changes.pos = 1; + bd->changes.size = 1; + } + if (bd == kbd->border) + { + if (kbd->h != bd->h) + { + if (kbd->animator) + { + if (kbd->adjust_end > kbd->adjust_start) + { + kbd->adjust_start -= (bd->h - kbd->h); + kbd->adjust_end -= (bd->h - kbd->h); + } + } + else if (!kbd->actually_visible) + e_border_fx_offset(kbd->border, 0, kbd->border->h); + kbd->h = bd->h; + } + } +} + +static void +_e_kbd_cb_border_hook_end(void *data, void *data2) +{ + E_Kbd *kbd; + E_Border *bd; + + if (!(bd = data2)) return; + kbd = _e_kbd_by_border_get(bd); + if (!kbd) return; + if (kbd->border == bd) + { + if (!kbd->actually_visible) + _e_kbd_border_hide(kbd->border); + } + else + _e_kbd_border_hide(bd); + +} + +static int +_e_kbd_cb_delayed_hide(void *data) +{ + E_Kbd *kbd; + + if (!(kbd = data)) return 0; + e_kbd_hide(kbd); + kbd->delay_hide = NULL; + return 0; +} + +static void +_e_kbd_layout_send(E_Kbd *kbd) +{ + Ecore_X_Virtual_Keyboard_State type; + + if ((kbd->actually_visible) && (!kbd->disabled)) + { + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ON; + if (kbd->layout == E_KBD_LAYOUT_DEFAULT) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ON; + else if (kbd->layout == E_KBD_LAYOUT_ALPHA) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA; + else if (kbd->layout == E_KBD_LAYOUT_NUMERIC) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC; + else if (kbd->layout == E_KBD_LAYOUT_PIN) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN; + else if (kbd->layout == E_KBD_LAYOUT_PHONE_NUMBER) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER; + else if (kbd->layout == E_KBD_LAYOUT_HEX) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX; + else if (kbd->layout == E_KBD_LAYOUT_TERMINAL) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL; + else if (kbd->layout == E_KBD_LAYOUT_PASSWORD) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD; + else if (kbd->layout == E_KBD_LAYOUT_NONE) + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF; + } + else + type = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF; + if (kbd->border) + ecore_x_e_virtual_keyboard_state_send(kbd->border->client.win, type); +} + +static void +_e_kbd_cb_apply_all_job(void *data) +{ + /* _E_MOD_LAYOUT_APPLY_ALL */ + _apply_all_job = NULL; +} + +static void +_e_kbd_apply_all_job_queue(void) +{ + if (_apply_all_job) ecore_job_del(_apply_all_job); + _apply_all_job = ecore_job_add(_e_kbd_cb_apply_all_job, NULL); +} + +static void +_e_kbd_apply_all_job_queue_end(void) +{ + if (_apply_all_job) ecore_job_del(_apply_all_job); + _apply_all_job = NULL; +} + +static void +_e_kbd_apply_all_job(void *data) +{ + _apply_all_job = NULL; +} + +static void +_e_kbd_free(E_Kbd *kbd) +{ + E_Border *bd; + + kbds = eina_list_remove(kbds, kbd); + if (kbd->animator) ecore_animator_del(kbd->animator); + if (kbd->delay_hide) ecore_timer_del(kbd->delay_hide); + EINA_LIST_FREE(kbd->waiting_borders, bd) + bd->stolen = 0; + E_FREE(kbd); +} + +static E_Kbd * +_e_kbd_by_border_get(E_Border *bd) +{ + Eina_List *l, *ll; + E_Border *over; + E_Kbd *kbd; + + if (!bd->stolen) return NULL; + EINA_LIST_FOREACH(kbds, l, kbd) + { + if (kbd->border == bd) return kbd; + EINA_LIST_FOREACH(kbd->waiting_borders, ll, over) + if (over == bd) return kbd; + } + return NULL; +} + +static void +_e_kbd_border_adopt(E_Kbd *kbd, E_Border *bd) +{ + kbd->border = bd; + bd->sticky = 1; + if (kbd->fullscreen) + e_border_layer_set(kbd->border, 250); + else + e_border_layer_set(kbd->border, 100); + if (!kbd->actually_visible) + { + e_border_fx_offset(kbd->border, 0, kbd->border->h); + _e_kbd_layout_send(kbd); + } + kbd->h = kbd->border->h; +} + +static void +_e_kbd_border_hide(E_Border *bd) +{ + if (!bd) return; +#ifdef ICONIFY_TO_HIDE + e_border_iconify(bd); +#else + e_border_hide(bd, 2); +#endif +} + +static int +_e_kbd_border_is_keyboard(E_Border *bd) +{ + if (!bd) return 0; + if ((bd->client.vkbd.vkbd) || /* explicit hint that its a virtual keyboard */ + /* legacy */ + ( /* trap the matchbox qwerty and multitap kbd's */ + (((bd->client.icccm.title) && (!strcmp(bd->client.icccm.title, "Keyboard"))) || + ((bd->client.icccm.name) && ((!strcmp(bd->client.icccm.name, "multitap-pad"))))) + && (bd->client.netwm.state.skip_taskbar) + && (bd->client.netwm.state.skip_pager)) + ) + return 1; + + return 0; +} diff --git a/src/modules/illume-keyboard/e_kbd.h b/src/modules/illume-keyboard/e_kbd.h new file mode 100644 index 000000000..ec09ea5de --- /dev/null +++ b/src/modules/illume-keyboard/e_kbd.h @@ -0,0 +1,55 @@ +#ifndef E_KBD_H +#define E_KBD_H + +typedef struct _E_Kbd E_Kbd; + +#define E_KBD_TYPE 0xE1b0988 + +typedef enum _E_Kbd_Layout +{ + E_KBD_LAYOUT_NONE, + E_KBD_LAYOUT_DEFAULT, + E_KBD_LAYOUT_ALPHA, + E_KBD_LAYOUT_NUMERIC, + E_KBD_LAYOUT_PIN, + E_KBD_LAYOUT_PHONE_NUMBER, + E_KBD_LAYOUT_HEX, + E_KBD_LAYOUT_TERMINAL, + E_KBD_LAYOUT_PASSWORD +} E_Kbd_Layout; + +struct _E_Kbd +{ + E_Object e_obj_inherit; + E_Win *win; + E_Border *border; + Ecore_Timer *delay_hide; + Ecore_Animator *animator; + Eina_List *waiting_borders; + E_Kbd_Layout layout; + double start, len; + int h, adjust_start, adjust, adjust_end; + unsigned char visible : 1; + unsigned char actually_visible : 1; + unsigned char disabled : 1; // if we have a real kbd plugged in + unsigned char fullscreen : 1; +}; + +EAPI int e_kbd_init(E_Module *m); +EAPI int e_kbd_shutdown(void); +EAPI E_Kbd *e_kbd_new(E_Zone *zone, const char *themedir, const char *syskbds, const char *sysdicts); +EAPI void e_kbd_enable(E_Kbd *kbd); +EAPI void e_kbd_disable(E_Kbd *kbd); +EAPI void e_kbd_show(E_Kbd *kbd); +EAPI void e_kbd_layout_set(E_Kbd *kbd, E_Kbd_Layout layout); +EAPI void e_kbd_hide(E_Kbd *kbd); +EAPI void e_kbd_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h); +EAPI void e_kbd_fullscreen_set(E_Zone *zone, int fullscreen); +EAPI void e_kbd_all_enable(void); +EAPI void e_kbd_all_disable(void); +EAPI void e_kbd_all_show(void); +EAPI void e_kbd_all_hide(void); +EAPI void e_kbd_all_toggle(void); +EAPI void e_kbd_all_layout_set(E_Kbd_Layout layout); + +#endif diff --git a/src/modules/illume-keyboard/e_kbd_dbus.c b/src/modules/illume-keyboard/e_kbd_dbus.c new file mode 100644 index 000000000..aad615d8d --- /dev/null +++ b/src/modules/illume-keyboard/e_kbd_dbus.c @@ -0,0 +1,251 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_kbd.h" + +/* local function prototypes */ +static void _e_kbd_dbus_ignore_keyboards_load(void); +static void _e_kbd_dbus_ignore_keyboards_file_load(const char *file); +static void _e_kbd_dbus_cb_dev_input_keyboard(void *data, void *reply, DBusError *error); +static void _e_kbd_dbus_keyboard_add(const char *udi); +static void _e_kbd_dbus_keyboard_eval(void); +static void _e_kbd_dbus_cb_dev_add(void *data, DBusMessage *msg); +static void _e_kbd_dbus_cb_dev_del(void *data, DBusMessage *msg); +static void _e_kbd_dbus_cb_cap_add(void *data, DBusMessage *msg); +static void _e_kbd_dbus_cb_input_keyboard_is(void *user_data, void *method_return, DBusError *error); +static void _e_kbd_dbus_keyboard_del(const char *udi); + +/* local variables */ +static int have_real_keyboard = 0; +static E_DBus_Connection *_e_kbd_dbus_conn = NULL; +static E_DBus_Signal_Handler *_e_kbd_dbus_handler_dev_add = NULL; +static E_DBus_Signal_Handler *_e_kbd_dbus_handler_dev_del = NULL; +static E_DBus_Signal_Handler *_e_kbd_dbus_handler_dev_chg = NULL; +static Eina_List *_e_kbd_dbus_keyboards = NULL; +static Eina_List *_e_kbd_dbus_real_ignore = NULL; + +/* public functions */ +EAPI void +e_kbd_dbus_real_kbd_init(void) +{ + have_real_keyboard = 0; + _e_kbd_dbus_ignore_keyboards_load(); + _e_kbd_dbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (_e_kbd_dbus_conn) + { + e_hal_manager_find_device_by_capability(_e_kbd_dbus_conn, + "input.keyboard", + _e_kbd_dbus_cb_dev_input_keyboard, + NULL); + _e_kbd_dbus_handler_dev_add = + e_dbus_signal_handler_add(_e_kbd_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "DeviceAdded", _e_kbd_dbus_cb_dev_add, NULL); + _e_kbd_dbus_handler_dev_del = + e_dbus_signal_handler_add(_e_kbd_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "DeviceRemoved", _e_kbd_dbus_cb_dev_del, NULL); + _e_kbd_dbus_handler_dev_chg = + e_dbus_signal_handler_add(_e_kbd_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "NewCapability", _e_kbd_dbus_cb_cap_add, NULL); + } +} + +EAPI void +e_kbd_dbus_real_kbd_shutdown(void) +{ + char *str; + + if (_e_kbd_dbus_conn) + { + e_dbus_signal_handler_del(_e_kbd_dbus_conn, _e_kbd_dbus_handler_dev_add); + e_dbus_signal_handler_del(_e_kbd_dbus_conn, _e_kbd_dbus_handler_dev_del); + e_dbus_signal_handler_del(_e_kbd_dbus_conn, _e_kbd_dbus_handler_dev_chg); + } + EINA_LIST_FREE(_e_kbd_dbus_real_ignore, str) + eina_stringshare_del(str); + EINA_LIST_FREE(_e_kbd_dbus_keyboards, str) + eina_stringshare_del(str); + have_real_keyboard = 0; +} + +/* local functions */ +static void +_e_kbd_dbus_ignore_keyboards_load(void) +{ + char buff[PATH_MAX]; + + e_user_dir_concat_static(buff, "keyboards/ignore_built_in_keyboards"); + _e_kbd_dbus_ignore_keyboards_file_load(buff); + snprintf(buff, sizeof(buff), + "%s/keyboards/ignore_built_in_keyboards", mod_dir); + _e_kbd_dbus_ignore_keyboards_file_load(buff); +} + +static void +_e_kbd_dbus_ignore_keyboards_file_load(const char *file) +{ + char buff[PATH_MAX]; + FILE *f; + + if (!(f = fopen(file, "r"))) return; + while (fgets(buff, sizeof(buff), f)) + { + char *p; + int len; + + if (buff[0] == '#') continue; + len = strlen(buff); + if (len > 0) + { + if (buff[len - 1] == '\n') buff[len - 1] = 0; + } + p = buff; + while (isspace(*p)) p++; + if (*p) + _e_kbd_dbus_real_ignore = + eina_list_append(_e_kbd_dbus_real_ignore, eina_stringshare_add(p)); + } + fclose(f); +} + +static void +_e_kbd_dbus_cb_dev_input_keyboard(void *data, void *reply, DBusError *error) +{ + E_Hal_Manager_Find_Device_By_Capability_Return *ret; + Eina_List *l; + char *device; + + if (!(ret = reply)) return; + if (!ret->strings) return; + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + return; + } + EINA_LIST_FOREACH(ret->strings, l, device) + { + _e_kbd_dbus_keyboard_add(device); + _e_kbd_dbus_keyboard_eval(); + } +} + +static void +_e_kbd_dbus_keyboard_add(const char *udi) +{ + const char *str; + Eina_List *l; + + EINA_LIST_FOREACH(_e_kbd_dbus_keyboards, l, str) + if (!strcmp(str, udi)) return; + _e_kbd_dbus_keyboards = + eina_list_append(_e_kbd_dbus_keyboards, eina_stringshare_add(udi)); +} + +static void +_e_kbd_dbus_keyboard_eval(void) +{ + Eina_List *l, *ll; + const char *g, *gg; + int have_real = 0; + + have_real = eina_list_count(_e_kbd_dbus_keyboards); + EINA_LIST_FOREACH(_e_kbd_dbus_keyboards, l, g) + EINA_LIST_FOREACH(_e_kbd_dbus_real_ignore, ll, gg) + if (e_util_glob_match(g, gg)) + { + have_real--; + break; + } + + if (have_real != have_real_keyboard) + { + have_real_keyboard = have_real; + if (have_real_keyboard) + e_kbd_all_disable(); + else + e_kbd_all_enable(); + } +} + +static void +_e_kbd_dbus_cb_dev_add(void *data, DBusMessage *msg) +{ + DBusError err; + char *udi; + int ret; + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); + udi = strdup(udi); + ret = + e_hal_device_query_capability(_e_kbd_dbus_conn, udi, "input.keyboard", + _e_kbd_dbus_cb_input_keyboard_is, + udi); +} + +static void +_e_kbd_dbus_cb_dev_del(void *data, DBusMessage *msg) +{ + DBusError err; + char *udi; + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); + _e_kbd_dbus_keyboard_del(udi); + _e_kbd_dbus_keyboard_eval(); +} + +static void +_e_kbd_dbus_cb_cap_add(void *data, DBusMessage *msg) +{ + DBusError err; + char *udi, *cap; + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, + DBUS_TYPE_STRING, &cap, DBUS_TYPE_INVALID); + if (!strcmp(cap, "input.keyboard")) + { + _e_kbd_dbus_keyboard_add(udi); + _e_kbd_dbus_keyboard_eval(); + } +} + +static void +_e_kbd_dbus_cb_input_keyboard_is(void *user_data, void *method_return, DBusError *error) +{ + char *udi = user_data; + E_Hal_Device_Query_Capability_Return *ret = method_return; + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + free(udi); + return; + } + if ((ret) && (ret->boolean)) + { + _e_kbd_dbus_keyboard_add(udi); + _e_kbd_dbus_keyboard_eval(); + } +} + +static void +_e_kbd_dbus_keyboard_del(const char *udi) +{ + Eina_List *l; + char *str; + + EINA_LIST_FOREACH(_e_kbd_dbus_keyboards, l, str) + if (!strcmp(str, udi)) + { + eina_stringshare_del(str); + _e_kbd_dbus_keyboards = + eina_list_remove_list(_e_kbd_dbus_keyboards, l); + return; + } +} diff --git a/src/modules/illume-keyboard/e_kbd_dbus.h b/src/modules/illume-keyboard/e_kbd_dbus.h new file mode 100644 index 000000000..1893e9286 --- /dev/null +++ b/src/modules/illume-keyboard/e_kbd_dbus.h @@ -0,0 +1,7 @@ +#ifndef E_KBD_DBUS_H +#define E_KBD_DBUS_H + +EAPI void e_kbd_dbus_real_kbd_init(void); +EAPI void e_kbd_dbus_real_kbd_shutdown(void); + +#endif diff --git a/src/modules/illume-keyboard/e_mod_main.c b/src/modules/illume-keyboard/e_mod_main.c new file mode 100644 index 000000000..385004ef1 --- /dev/null +++ b/src/modules/illume-keyboard/e_mod_main.c @@ -0,0 +1,28 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_kbd.h" + +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume Keyboard" }; +const char *mod_dir = NULL; + +EAPI void * +e_modapi_init(E_Module *m) +{ + if (!e_kbd_init(m)) return NULL; + mod_dir = eina_stringshare_add(m->dir); + return m; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + if (mod_dir) eina_stringshare_del(mod_dir); + e_kbd_shutdown(); + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + return 1; +} diff --git a/src/modules/illume-keyboard/e_mod_main.h b/src/modules/illume-keyboard/e_mod_main.h new file mode 100644 index 000000000..2ac97c3f8 --- /dev/null +++ b/src/modules/illume-keyboard/e_mod_main.h @@ -0,0 +1,12 @@ +#ifndef E_MOD_MAIN_H +#define E_MOD_MAIN_H + +EAPI extern E_Module_Api e_modapi; + +EAPI void *e_modapi_init(E_Module *m); +EAPI int e_modapi_shutdown(E_Module *m); +EAPI int e_modapi_save(E_Module *m); + +extern EAPI const char *mod_dir; + +#endif diff --git a/src/modules/illume-keyboard/module.desktop.in b/src/modules/illume-keyboard/module.desktop.in new file mode 100644 index 000000000..780c952b6 --- /dev/null +++ b/src/modules/illume-keyboard/module.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=Illume-Keyboard +Icon=e-module-illume-kbd +X-Enlightenment-ModuleType=system +Comment=Illume Keyboard for Embedded diff --git a/src/modules/illume2/Makefile.am b/src/modules/illume2/Makefile.am index f1dd59fc5..cfd3f0c10 100644 --- a/src/modules/illume2/Makefile.am +++ b/src/modules/illume2/Makefile.am @@ -23,9 +23,7 @@ module_la_SOURCES = e_mod_main.c \ e_mod_layout.h \ e_mod_layout.c \ e_mod_layout_illume.c \ - e_mod_layout_illume.h \ - e_kbd.h \ - e_kbd.c + e_mod_layout_illume.h module_la_LIBADD = @e_libs@ @dlopen_libs@ module_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/illume2/e_mod_main.c b/src/modules/illume2/e_mod_main.c index 7975f6b89..78264ad34 100644 --- a/src/modules/illume2/e_mod_main.c +++ b/src/modules/illume2/e_mod_main.c @@ -1,6 +1,4 @@ #include "e.h" - -#include "e_kbd.h" #include "e_mod_main.h" #include "e_mod_layout.h" @@ -18,7 +16,6 @@ EAPI void * e_modapi_init(E_Module *m) { /* set up the virtual keyboard */ -// e_kbd_init(m); e_mod_layout_init(m); return m; /* return NULL on failure, anything else on success. the pointer * returned will be set as m->data for convenience tracking */ @@ -29,7 +26,6 @@ EAPI int e_modapi_shutdown(E_Module *m) { e_mod_layout_shutdown(); -// e_kbd_shutdown(); return 1; /* 1 for success, 0 for failure */ }