diff --git a/src/modules/illume-home/Makefile.am b/src/modules/illume-home/Makefile.am new file mode 100644 index 000000000..35bbe3ea6 --- /dev/null +++ b/src/modules/illume-home/Makefile.am @@ -0,0 +1,33 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume-home + +# 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_mod_config.c \ + e_mod_config.h \ + e_busycover.c \ + e_busycover.h + +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-home/e-module-illume-home.edj b/src/modules/illume-home/e-module-illume-home.edj new file mode 100644 index 000000000..f6dc60946 Binary files /dev/null and b/src/modules/illume-home/e-module-illume-home.edj differ diff --git a/src/modules/illume-home/e_busycover.c b/src/modules/illume-home/e_busycover.c new file mode 100644 index 000000000..610b13302 --- /dev/null +++ b/src/modules/illume-home/e_busycover.c @@ -0,0 +1,92 @@ +#include "e.h" +#include "e_busycover.h" +#include "e_mod_config.h" + +/* local function prototypes */ +static void _e_busycover_cb_free(E_Busycover *cover); + +EAPI E_Busycover * +e_busycover_new(E_Win *win) +{ + E_Busycover *cover; + char buff[PATH_MAX]; + + cover = E_OBJECT_ALLOC(E_Busycover, E_BUSYCOVER_TYPE, _e_busycover_cb_free); + if (!cover) return NULL; + snprintf(buff, sizeof(buff), "%s/e-module-illume-home.edj", + il_home_cfg->mod_dir); + + cover->o_base = edje_object_add(e_win_evas_get(win)); + if (!e_theme_edje_object_set(cover->o_base, + "base/theme/modules/illume-home", + "modules/illume-home/busycover")) + edje_object_file_set(cover->o_base, buff, "modules/illume-home/busycover"); + edje_object_part_text_set(cover->o_base, "e.text.title", _("LOADING")); + evas_object_move(cover->o_base, win->x, win->y); + evas_object_resize(cover->o_base, win->w, win->h); + evas_object_layer_set(cover->o_base, 999); + return cover; +} + +EAPI E_Busycover_Handle * +e_busycover_push(E_Busycover *cover, const char *msg, const char *icon) +{ + E_Busycover_Handle *handle; + + E_OBJECT_CHECK(cover); + E_OBJECT_TYPE_CHECK_RETURN(cover, E_BUSYCOVER_TYPE, NULL); + + handle = E_NEW(E_Busycover_Handle, 1); + handle->cover = cover; + if (msg) handle->msg = eina_stringshare_add(msg); + if (icon) handle->icon = eina_stringshare_add(icon); + cover->handles = eina_list_append(cover->handles, handle); + edje_object_part_text_set(cover->o_base, "e.text.title", msg); + evas_object_show(cover->o_base); + return handle; +} + +EAPI void +e_busycover_pop(E_Busycover *cover, E_Busycover_Handle *handle) +{ + E_OBJECT_CHECK(cover); + E_OBJECT_TYPE_CHECK(cover, E_BUSYCOVER_TYPE); + if (!eina_list_data_find(cover->handles, handle)) return; + cover->handles = eina_list_remove(cover->handles, handle); + if (handle->msg) eina_stringshare_del(handle->msg); + if (handle->icon) eina_stringshare_del(handle->icon); + E_FREE(handle); + if (cover->handles) + { + handle = cover->handles->data; + edje_object_part_text_set(cover->o_base, "e.text.title", handle->msg); + } + else + evas_object_hide(cover->o_base); +} + +EAPI void +e_busycover_resize(E_Busycover *cover, int w, int h) +{ + E_OBJECT_CHECK(cover); + E_OBJECT_TYPE_CHECK(cover, E_BUSYCOVER_TYPE); + evas_object_resize(cover->o_base, w, h); +} + +/* local function prototypes */ +static void +_e_busycover_cb_free(E_Busycover *cover) +{ + Eina_List *l; + E_Busycover_Handle *handle; + + EINA_LIST_FREE(cover->handles, handle) + { + if (handle->msg) eina_stringshare_del(handle->msg); + if (handle->icon) eina_stringshare_del(handle->icon); + E_FREE(handle); + } + + if (cover->o_base) evas_object_del(cover->o_base); + E_FREE(cover); +} diff --git a/src/modules/illume-home/e_busycover.h b/src/modules/illume-home/e_busycover.h new file mode 100644 index 000000000..35e084984 --- /dev/null +++ b/src/modules/illume-home/e_busycover.h @@ -0,0 +1,26 @@ +#ifndef E_BUSYCOVER_H +# define E_BUSYCOVER_H + +# define E_BUSYCOVER_TYPE 0xE1b0782 + +typedef struct _E_Busycover E_Busycover; +typedef struct _E_Busycover_Handle E_Busycover_Handle; + +struct _E_Busycover +{ + E_Object e_obj_inherit; + Evas_Object *o_base; + Eina_List *handles; +}; +struct _E_Busycover_Handle +{ + E_Busycover *cover; + const char *msg, *icon; +}; + +EAPI E_Busycover *e_busycover_new(E_Win *win); +EAPI E_Busycover_Handle *e_busycover_push(E_Busycover *cover, const char *msg, const char *icon); +EAPI void e_busycover_pop(E_Busycover *cover, E_Busycover_Handle *handle); +EAPI void e_busycover_resize(E_Busycover *cover, int w, int h); + +#endif diff --git a/src/modules/illume-home/e_mod_config.c b/src/modules/illume-home/e_mod_config.c new file mode 100644 index 000000000..5e206c62f --- /dev/null +++ b/src/modules/illume-home/e_mod_config.c @@ -0,0 +1,200 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_config.h" + +/* local function prototypes */ +static void *_il_home_config_create(E_Config_Dialog *cfd); +static void _il_home_config_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_il_home_config_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static void _il_home_config_changed(void *data, Evas_Object *obj, void *event); +static void _il_home_config_click_changed(void *data, Evas_Object *obj, void *event); +static int _il_home_config_change_timeout(void *data); + +/* local variables */ +EAPI Il_Home_Config *il_home_cfg = NULL; +static E_Config_DD *conf_edd = NULL; +Ecore_Timer *_il_home_config_change_timer = NULL; +Evas_Object *delay_label, *delay_slider; + +/* public functions */ +int +il_home_config_init(E_Module *m) +{ + conf_edd = E_CONFIG_DD_NEW("Illume-Home_Cfg", Il_Home_Config); + #undef T + #undef D + #define T Il_Home_Config + #define D conf_edd + E_CONFIG_VAL(D, T, version, INT); + E_CONFIG_VAL(D, T, icon_size, INT); + E_CONFIG_VAL(D, T, single_click, INT); + E_CONFIG_VAL(D, T, single_click_delay, INT); + + il_home_cfg = e_config_domain_load("module.illume-home", conf_edd); + if ((il_home_cfg) && + ((il_home_cfg->version >> 16) < IL_CONFIG_MAJ)) + { + E_FREE(il_home_cfg); + il_home_cfg = NULL; + } + if (!il_home_cfg) + { + il_home_cfg = E_NEW(Il_Home_Config, 1); + il_home_cfg->version = 0; + il_home_cfg->icon_size = 120; + il_home_cfg->single_click = 1; + il_home_cfg->single_click_delay = 50; + } + if (il_home_cfg) + { + /* Add new config variables here */ + /* if ((il_home_cfg->version & 0xffff) < 1) */ + il_home_cfg->version = (IL_CONFIG_MAJ << 16) | IL_CONFIG_MIN; + } + + il_home_cfg->mod_dir = eina_stringshare_add(m->dir); + + e_configure_registry_category_add("illume", 0, _("Illume"), NULL, + "enlightenment/display"); + e_configure_registry_generic_item_add("illume/home", 0, _("Home"), + NULL, "enlightenment/launcher", + il_home_config_show); + return 1; +} + +int +il_home_config_shutdown(void) +{ + il_home_cfg->cfd = NULL; + + e_configure_registry_item_del("illume/home"); + e_configure_registry_category_del("illume"); + + if (il_home_cfg->mod_dir) eina_stringshare_del(il_home_cfg->mod_dir); + + E_FREE(il_home_cfg); + il_home_cfg = NULL; + + E_CONFIG_DD_FREE(conf_edd); + return 1; +} + +int +il_home_config_save(void) +{ + e_config_domain_save("module.illume-home", conf_edd, il_home_cfg); + return 1; +} + +void +il_home_config_show(E_Container *con, const char *params) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v = NULL; + + if (e_config_dialog_find("E", "_config_illume_home_settings")) return; + + v = E_NEW(E_Config_Dialog_View, 1); + v->create_cfdata = _il_home_config_create; + v->free_cfdata = _il_home_config_free; + v->basic.create_widgets = _il_home_config_ui; + v->basic_only = 1; + v->normal_win = 1; + v->scroll = 1; + + cfd = e_config_dialog_new(con, _("Home Settings"), "E", + "_config_illume_home_settings", + "enlightenment/launcher_settings", 0, v, NULL); + e_dialog_resizable_set(cfd->dia, 1); + il_home_cfg->cfd = cfd; +} + +/* local functions */ +static void * +_il_home_config_create(E_Config_Dialog *cfd) +{ + return NULL; +} + +static void +_il_home_config_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + il_home_cfg->cfd = NULL; + il_home_win_cfg_update(); +} + +static Evas_Object * +_il_home_config_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *list, *of, *o; + E_Radio_Group *rg; + + list = e_widget_list_add(evas, 0, 0); + + of = e_widget_framelist_add(evas, _("Icon Size"), 0); + rg = e_widget_radio_group_new(&(il_home_cfg->icon_size)); + o = e_widget_radio_add(evas, _("Small"), 60, rg); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", _il_home_config_changed, NULL); + o = e_widget_radio_add(evas, _("Medium"), 80, rg); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", _il_home_config_changed, NULL); + o = e_widget_radio_add(evas, _("Large"), 120, rg); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", _il_home_config_changed, NULL); + o = e_widget_radio_add(evas, _("Very Large"), 160, rg); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", _il_home_config_changed, NULL); + o = e_widget_radio_add(evas, _("Massive"), 240, rg); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", _il_home_config_changed, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + of = e_widget_framelist_add(evas, _("Launch Action"), 0); + o = e_widget_check_add(evas, _("Single press"), + &(il_home_cfg->single_click)); + e_widget_framelist_object_append(of, o); + evas_object_smart_callback_add(o, "changed", + _il_home_config_click_changed, NULL); + o = e_widget_label_add(evas, _("Press Delay")); + delay_label = o; + e_widget_disabled_set(o, !(il_home_cfg->single_click)); + e_widget_framelist_object_append(of, o); + o = e_widget_slider_add(evas, 1, 0, "%1.0f ms", 0, 350, 1, 0, NULL, + &(il_home_cfg->single_click_delay), 150); + delay_slider = o; + /* Slider does not emit a changed signal */ +// evas_object_smart_callback_add(o, "changed", +// _il_home_config_changed, NULL); + e_widget_disabled_set(o, !(il_home_cfg->single_click)); + e_widget_framelist_object_append(of, o); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + return list; +} + +static void +_il_home_config_changed(void *data, Evas_Object *obj, void *event) +{ + if (_il_home_config_change_timer) + ecore_timer_del(_il_home_config_change_timer); + _il_home_config_change_timer = + ecore_timer_add(0.5, _il_home_config_change_timeout, data); +} + +static void +_il_home_config_click_changed(void *data, Evas_Object *obj, void *event) +{ + e_widget_disabled_set(delay_label, !il_home_cfg->single_click); + e_widget_disabled_set(delay_slider, !il_home_cfg->single_click); + _il_home_config_changed(data, obj, event); +} + +static int +_il_home_config_change_timeout(void *data) +{ + il_home_win_cfg_update(); + e_config_save_queue(); + _il_home_config_change_timer = NULL; + return 0; +} diff --git a/src/modules/illume-home/e_mod_config.h b/src/modules/illume-home/e_mod_config.h new file mode 100644 index 000000000..b7b04a9ff --- /dev/null +++ b/src/modules/illume-home/e_mod_config.h @@ -0,0 +1,27 @@ +#ifndef E_MOD_CONFIG_H +#define E_MOD_CONFIG_H + +#define IL_CONFIG_MIN 0 +#define IL_CONFIG_MAJ 0 + +typedef struct _Il_Home_Config Il_Home_Config; + +struct _Il_Home_Config +{ + int version; + int mode, icon_size; + int single_click, single_click_delay; + + // Not User Configurable. Placeholders + const char *mod_dir; + E_Config_Dialog *cfd; +}; + +int il_home_config_init(E_Module *m); +int il_home_config_shutdown(void); +int il_home_config_save(void); +void il_home_config_show(E_Container *con, const char *params); + +extern EAPI Il_Home_Config *il_home_cfg; + +#endif diff --git a/src/modules/illume-home/e_mod_main.c b/src/modules/illume-home/e_mod_main.c new file mode 100644 index 000000000..20f2935e6 --- /dev/null +++ b/src/modules/illume-home/e_mod_main.c @@ -0,0 +1,903 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_config.h" +#include "e_busycover.h" + +#define IL_HOME_WIN_TYPE 0xE0b0102f + +/* local structures */ +typedef struct _Instance Instance; +typedef struct _Il_Home_Win Il_Home_Win; +typedef struct _Il_Home_Exec Il_Home_Exec; + +struct _Instance +{ + E_Gadcon_Client *gcc; + Evas_Object *o_btn; + Eina_List *wins, *handlers; +}; + +struct _Il_Home_Win +{ + E_Object e_obj_inherit; + + E_Win *win; + Evas_Object *o_bg, *o_sf, *o_fm, *o_cover; + E_Busycover *cover; + E_Zone *zone; +}; + +struct _Il_Home_Exec +{ + E_Busycover *cover; + Efreet_Desktop *desktop; + Ecore_Exe *exec; + E_Border *border; + E_Zone *zone; + Ecore_Timer *timeout; + int startup_id; + pid_t pid; + void *handle; +}; + +/* local function prototypes */ +static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style); +static void _gc_shutdown(E_Gadcon_Client *gcc); +static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient); +static char *_gc_label(E_Gadcon_Client_Class *cc); +static Evas_Object *_gc_icon(E_Gadcon_Client_Class *cc, Evas *evas); +static const char *_gc_id_new(E_Gadcon_Client_Class *cc); +static void _il_home_btn_cb_click(void *data, void *data2); +static void _il_home_win_new(Instance *inst); +static void _il_home_win_cb_free(Il_Home_Win *hwin); +static void _il_home_win_cb_resize(E_Win *win); +static void _il_home_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y); +static void _il_home_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y); +static void _il_home_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y); +static void _il_home_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h); +static void _il_home_cb_selected(void *data, Evas_Object *obj, void *event); +static void _il_home_desktop_run(Il_Home_Win *hwin, Efreet_Desktop *desktop); +static void _il_home_apps_populate(void); +static void _il_home_apps_unpopulate(void); +static void _il_home_fmc_set(Evas_Object *obj); +static void _il_home_desks_populate(void); +static int _il_home_desktop_list_change(void *data, int type, void *event); +static int _il_home_desktop_change(void *data, int type, void *event); +static int _il_home_update_deferred(void *data); +static int _il_home_win_cb_exe_del(void *data, int type, void *event); +static E_Border *_il_home_desktop_find_border(E_Zone *zone, Efreet_Desktop *desktop); +static int _il_home_win_cb_timeout(void *data); +static int _il_home_border_add(void *data, int type, void *event); +static int _il_home_border_remove(void *data, int type, void *event); +static int _il_home_cb_client_message(void *data, int type, void *event); +static int _il_home_cb_prop_change(void *data, int type, void *event); + +/* local variables */ +static Eina_List *instances = NULL; +static Eina_List *desks = NULL; +static Eina_List *handlers = NULL; +static Eina_List *exes = NULL; +static Ecore_Timer *defer = NULL; + +static const E_Gadcon_Client_Class _gc_class = +{ + GADCON_CLIENT_CLASS_VERSION, "illume-home", + { _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, + e_gadcon_site_is_not_toolbar + }, E_GADCON_CLIENT_STYLE_PLAIN +}; + +/* public functions */ +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume Home" }; + +EAPI void * +e_modapi_init(E_Module *m) +{ + if (!il_home_config_init(m)) return NULL; + + _il_home_apps_unpopulate(); + _il_home_apps_populate(); + + handlers = + eina_list_append(handlers, + ecore_event_handler_add(EFREET_EVENT_DESKTOP_LIST_CHANGE, + _il_home_desktop_list_change, + NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(EFREET_EVENT_DESKTOP_CHANGE, + _il_home_desktop_change, NULL)); + + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_ADD, + _il_home_border_add, NULL)); + handlers = + eina_list_append(handlers, + ecore_event_handler_add(E_EVENT_BORDER_REMOVE, + _il_home_border_remove, NULL)); + + handlers = + eina_list_append(handlers, + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _il_home_win_cb_exe_del, NULL)); + + e_gadcon_provider_register(&_gc_class); + return m; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + Ecore_Event_Handler *handle; + Il_Home_Exec *exe; + + EINA_LIST_FREE(exes, exe) + { + if (exe->exec) + { + ecore_exe_terminate(exe->exec); + ecore_exe_free(exe->exec); + exe->exec = NULL; + } + if (exe->handle) + { + e_busycover_pop(exe->cover, exe->handle); + exe->handle = NULL; + } + if (exe->timeout) ecore_timer_del(exe->timeout); + E_FREE(exe); + } + + _il_home_apps_unpopulate(); + + EINA_LIST_FREE(handlers, handle) + ecore_event_handler_del(handle); + + e_gadcon_provider_unregister(&_gc_class); + + il_home_config_shutdown(); + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + return il_home_config_save(); +} + +void +il_home_win_cfg_update(void) +{ + _il_home_apps_unpopulate(); + _il_home_apps_populate(); +} + +/* local functions */ +static E_Gadcon_Client * +_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) +{ + Instance *inst; + Evas_Object *icon; + Ecore_X_Window xwin; + Ecore_X_Illume_Mode mode; + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), "%s/e-module-illume-home.edj", + il_home_cfg->mod_dir); + + inst = E_NEW(Instance, 1); + inst->o_btn = e_widget_button_add(gc->evas, NULL, NULL, + _il_home_btn_cb_click, inst, NULL); + icon = e_icon_add(evas_object_evas_get(inst->o_btn)); + e_icon_file_edje_set(icon, buff, "icon"); + e_widget_button_icon_set(inst->o_btn, icon); + + inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->o_btn); + inst->gcc->data = inst; + + _il_home_win_new(inst); + + xwin = inst->gcc->gadcon->zone->black_win; + mode = ecore_x_e_illume_mode_get(xwin); + if (mode > ECORE_X_ILLUME_MODE_SINGLE) + _il_home_win_new(inst); + + inst->handlers = + eina_list_append(inst->handlers, + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _il_home_cb_client_message, inst)); + inst->handlers = + eina_list_append(inst->handlers, + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, + _il_home_cb_prop_change, inst)); + + instances = eina_list_append(instances, inst); + return inst->gcc; +} + +static void +_gc_shutdown(E_Gadcon_Client *gcc) +{ + Instance *inst; + Il_Home_Win *hwin; + Ecore_Event_Handler *hdl; + + if (!(inst = gcc->data)) return; + + instances = eina_list_remove(instances, inst); + + EINA_LIST_FREE(inst->handlers, hdl) + ecore_event_handler_del(hdl); + + if (inst->o_btn) evas_object_del(inst->o_btn); + + EINA_LIST_FREE(inst->wins, hwin) + e_object_del(E_OBJECT(hwin)); + + E_FREE(inst); +} + +static void +_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient) +{ + e_gadcon_client_aspect_set(gcc, 16, 16); + e_gadcon_client_min_size_set(gcc, 16, 16); +} + +static char * +_gc_label(E_Gadcon_Client_Class *cc) +{ + return _("Illume-Home"); +} + +static Evas_Object * +_gc_icon(E_Gadcon_Client_Class *cc, Evas *evas) +{ + Evas_Object *o; + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), "%s/e-module-illume-home.edj", + il_home_cfg->mod_dir); + o = edje_object_add(evas); + edje_object_file_set(o, buff, "icon"); + return o; +} + +static const char * +_gc_id_new(E_Gadcon_Client_Class *cc) +{ + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), "%s.%d", _gc_class.name, + eina_list_count(instances)); + return strdup(buff); +} + +static void +_il_home_btn_cb_click(void *data, void *data2) +{ + Instance *inst; + + if (!(inst = data)) return; + + /* if there are less than 2 home windows, create a new one */ + if (eina_list_count(inst->wins) < 2) + _il_home_win_new(inst); + else + { + E_Zone *zone; + + zone = inst->gcc->gadcon->zone; + + /* already 2 home windows, so tell illume to focus one */ + ecore_x_e_illume_focus_home_send(zone->black_win); + } +} + +static void +_il_home_win_new(Instance *inst) +{ + Il_Home_Win *hwin; + E_Zone *zone; + char buff[PATH_MAX]; + + if (!inst) return; + + hwin = E_OBJECT_ALLOC(Il_Home_Win, IL_HOME_WIN_TYPE, + _il_home_win_cb_free); + if (!hwin) return; + inst->wins = eina_list_append(inst->wins, hwin); + + zone = inst->gcc->gadcon->zone; + hwin->zone = zone; + + hwin->win = e_win_new(zone->container); + if (!hwin->win) + { + e_object_del(E_OBJECT(hwin)); + return; + } + hwin->win->data = inst; + e_win_title_set(hwin->win, _("Illume Home")); + e_win_name_class_set(hwin->win, "Illume-Home", "Illume-Home"); + e_win_resize_callback_set(hwin->win, _il_home_win_cb_resize); + e_win_no_remember_set(hwin->win, EINA_TRUE); + + /* don't accept focus */ + ecore_x_icccm_hints_set(hwin->win->evas_win, 0, 0, 0, 0, 0, 0, 0); + + snprintf(buff, sizeof(buff), "%s/e-module-illume-home.edj", + il_home_cfg->mod_dir); + + hwin->o_bg = edje_object_add(e_win_evas_get(hwin->win)); + if (!e_theme_edje_object_set(hwin->o_bg, + "base/theme/modules/illume-home", + "modules/illume-home/window")) + edje_object_file_set(hwin->o_bg, buff, "modules/illume-home/window"); + evas_object_move(hwin->o_bg, 0, 0); + evas_object_show(hwin->o_bg); + + hwin->o_sf = e_scrollframe_add(e_win_evas_get(hwin->win)); + e_scrollframe_single_dir_set(hwin->o_sf, 1); + evas_object_move(hwin->o_sf, 0, 0); + evas_object_show(hwin->o_sf); + + e_scrollframe_custom_edje_file_set(hwin->o_sf, buff, + "modules/illume-home/launcher/scrollview"); + + hwin->o_fm = e_fm2_add(e_win_evas_get(hwin->win)); + _il_home_fmc_set(hwin->o_fm); + evas_object_show(hwin->o_fm); + e_user_dir_concat_static(buff, "appshadow"); + e_fm2_path_set(hwin->o_fm, NULL, buff); + + e_fm2_window_object_set(hwin->o_fm, E_OBJECT(hwin->win)); + + e_scrollframe_extern_pan_set(hwin->o_sf, hwin->o_fm, + _il_home_pan_set, + _il_home_pan_get, + _il_home_pan_max_get, + _il_home_pan_child_size_get); + evas_object_propagate_events_set(hwin->o_fm, 0); + evas_object_smart_callback_add(hwin->o_fm, "selected", + _il_home_cb_selected, hwin); + + hwin->cover = e_busycover_new(hwin->win); + + e_win_move_resize(hwin->win, zone->x, zone->y, zone->w, (zone->h / 2)); + e_win_show(hwin->win); + + e_border_zone_set(hwin->win->border, zone); + + if (hwin->win->evas_win) + e_drop_xdnd_register_set(hwin->win->evas_win, 1); +} + +static void +_il_home_win_cb_free(Il_Home_Win *hwin) +{ + if (hwin->win->evas_win) + e_drop_xdnd_register_set(hwin->win->evas_win, 0); + + if (hwin->cover) e_object_del(E_OBJECT(hwin->cover)); + hwin->cover = NULL; + + if (hwin->o_bg) evas_object_del(hwin->o_bg); + hwin->o_bg = NULL; + if (hwin->o_sf) evas_object_del(hwin->o_sf); + hwin->o_sf = NULL; + if (hwin->o_fm) evas_object_del(hwin->o_fm); + hwin->o_fm = NULL; + + if (hwin->win) e_object_del(E_OBJECT(hwin->win)); + hwin->win = NULL; +} + +static void +_il_home_win_cb_resize(E_Win *win) +{ + Instance *inst; + Il_Home_Win *hwin; + Eina_List *l; + + if (!(inst = win->data)) return; + EINA_LIST_FOREACH(inst->wins, l, hwin) + { + if (hwin->win != win) + { + hwin = NULL; + continue; + } + else break; + } + if (!hwin) return; + + if (hwin->o_bg) evas_object_resize(hwin->o_bg, win->w, win->h); + if (hwin->o_sf) evas_object_resize(hwin->o_sf, win->w, win->h); + if (hwin->cover) e_busycover_resize(hwin->cover, win->w, win->h); +} + +static void +_il_home_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) +{ + e_fm2_pan_set(obj, x, y); +} + +static void +_il_home_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) +{ + e_fm2_pan_get(obj, x, y); +} + +static void +_il_home_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) +{ + e_fm2_pan_max_get(obj, x, y); +} + +static void +_il_home_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) +{ + e_fm2_pan_child_size_get(obj, w, h); +} + +static void +_il_home_cb_selected(void *data, Evas_Object *obj, void *event) +{ + Il_Home_Win *hwin; + Eina_List *selected; + E_Fm2_Icon_Info *ici; + + if (!(hwin = data)) return; + if (!(selected = e_fm2_selected_list_get(hwin->o_fm))) return; + EINA_LIST_FREE(selected, ici) + { + Efreet_Desktop *desktop; + + if (ici) + { + if (ici->real_link) + { + desktop = efreet_desktop_get(ici->real_link); + if (desktop) + _il_home_desktop_run(hwin, desktop); + } + } + } +} + +static void +_il_home_desktop_run(Il_Home_Win *hwin, Efreet_Desktop *desktop) +{ + E_Exec_Instance *eins; + Il_Home_Exec *exe; + Eina_List *l; + E_Border *b; + char buff[PATH_MAX]; + + if ((!desktop) || (!desktop->exec)) return; + + EINA_LIST_FOREACH(exes, l, exe) + { + if (exe->desktop == desktop) + { + if ((exe->border) && + (exe->border->zone == hwin->win->border->zone)) + { + e_border_uniconify(exe->border); + e_border_show(exe->border); + e_border_raise(exe->border); + e_border_focus_set(exe->border, 1, 1); + return; + } + } + } + + b = _il_home_desktop_find_border(hwin->win->border->zone, desktop); + if (b) + { + e_border_uniconify(b); + e_border_show(b); + e_border_raise(b); + e_border_focus_set(b, 1, 1); + return; + } + + exe = E_NEW(Il_Home_Exec, 1); + if (!exe) return; + exe->cover = hwin->cover; + + eins = e_exec(hwin->win->border->zone, desktop, NULL, NULL, "illume-home"); + exe->desktop = desktop; + exe->zone = hwin->win->border->zone; + if (eins) + { + exe->exec = eins->exe; + exe->startup_id = eins->startup_id; + if (eins->exe) + exe->pid = ecore_exe_pid_get(eins->exe); + } + + exe->timeout = ecore_timer_add(20.0, _il_home_win_cb_timeout, exe); + snprintf(buff, sizeof(buff), "Starting %s", desktop->name); + exe->handle = e_busycover_push(hwin->cover, buff, NULL); + exes = eina_list_append(exes, exe); +} + +static void +_il_home_apps_populate(void) +{ + Eina_List *l, *ll; + Instance *inst; + char buff[PATH_MAX]; + + e_user_dir_concat_static(buff, "appshadow"); + ecore_file_mkpath(buff); + + _il_home_desks_populate(); + + EINA_LIST_FOREACH(instances, l, inst) + { + Il_Home_Win *hwin; + + EINA_LIST_FOREACH(inst->wins, ll, hwin) + { + if (!hwin) continue; + _il_home_fmc_set(hwin->o_fm); + e_fm2_path_set(hwin->o_fm, NULL, buff); + } + } +} + +static void +_il_home_apps_unpopulate(void) +{ + Efreet_Desktop *desktop; + Eina_List *files; + char buff[PATH_MAX], *file; + size_t len; + + EINA_LIST_FREE(desks, desktop) + efreet_desktop_free(desktop); + + len = e_user_dir_concat_static(buff, "appshadow"); + if ((len + 2) >= sizeof(buff)) return; + + files = ecore_file_ls(buff); + buff[len] = '/'; + len++; + + EINA_LIST_FREE(files, file) + { + if (eina_strlcpy(buff + len, file, sizeof(buff) - len) >= sizeof(buff) - len) + continue; + ecore_file_unlink(buff); + free(file); + } +} + +static void +_il_home_fmc_set(Evas_Object *obj) +{ + E_Fm2_Config fmc; + + if (!obj) return; + memset(&fmc, 0, sizeof(E_Fm2_Config)); + fmc.view.mode = E_FM2_VIEW_MODE_GRID_ICONS; + fmc.view.open_dirs_in_place = 1; + fmc.view.selector = 0; + fmc.view.single_click = il_home_cfg->single_click; + fmc.view.single_click_delay = il_home_cfg->single_click_delay; + fmc.view.no_subdir_jump = 1; + fmc.icon.extension.show = 0; + fmc.icon.icon.w = il_home_cfg->icon_size * e_scale / 2.0; + fmc.icon.icon.h = il_home_cfg->icon_size * e_scale / 2.0; + fmc.icon.fixed.w = il_home_cfg->icon_size * e_scale / 2.0; + fmc.icon.fixed.h = il_home_cfg->icon_size * e_scale / 2.0; + fmc.list.sort.no_case = 0; + fmc.list.sort.dirs.first = 1; + fmc.list.sort.dirs.last = 0; + fmc.selection.single = 1; + fmc.selection.windows_modifiers = 0; + e_fm2_config_set(obj, &fmc); +} + +static void +_il_home_desks_populate(void) +{ + Efreet_Menu *menu; + + menu = efreet_menu_get(); + if (menu) + { + Eina_List *l, *ll; + Efreet_Menu *entry, *subentry; + Eina_List *settings, *sys, *kbd; + int num = 0; + + settings = efreet_util_desktop_category_list("Settings"); + sys = efreet_util_desktop_category_list("System"); + kbd = efreet_util_desktop_category_list("Keyboard"); + EINA_LIST_FOREACH(menu->entries, l, entry) + { + if (entry->type != EFREET_MENU_ENTRY_MENU) continue; + EINA_LIST_FOREACH(entry->entries, ll, subentry) + { + Efreet_Desktop *desktop; + + if (subentry->type != EFREET_MENU_ENTRY_DESKTOP) continue; + if (!(desktop = subentry->desktop)) continue; + if ((settings) && (sys) && + (eina_list_data_find(settings, desktop)) && + (eina_list_data_find(sys, desktop))) continue; + if ((kbd) && (eina_list_data_find(kbd, desktop))) + continue; + if (!desktop) continue; + desks = eina_list_append(desks, desktop); + efreet_desktop_ref(desktop); + if (desktop) + { + char buff[PATH_MAX]; + + e_user_dir_snprintf(buff, sizeof(buff), + "appshadow/%04x.desktop", num); + ecore_file_symlink(desktop->orig_path, buff); + } + num++; + } + } + } +} + +static int +_il_home_desktop_list_change(void *data, int type, void *event) +{ + if (defer) ecore_timer_del(defer); + defer = ecore_timer_add(1.0, _il_home_update_deferred, NULL); + return 1; +} + +static int +_il_home_desktop_change(void *data, int type, void *event) +{ + if (defer) ecore_timer_del(defer); + defer = ecore_timer_add(1.0, _il_home_update_deferred, NULL); + return 1; +} + +static int +_il_home_update_deferred(void *data) +{ + _il_home_apps_unpopulate(); + _il_home_apps_populate(); + defer = NULL; + return 0; +} + +static int +_il_home_win_cb_exe_del(void *data, int type, void *event) +{ + Il_Home_Exec *exe; + Ecore_Exe_Event_Del *ev; + Eina_List *l; + + ev = event; + EINA_LIST_FOREACH(exes, l, exe) + { + if (exe->pid == ev->pid) + { + if (exe->handle) + { + e_busycover_pop(exe->cover, exe->handle); + exe->handle = NULL; + } + exes = eina_list_remove_list(exes, l); + if (exe->timeout) ecore_timer_del(exe->timeout); + E_FREE(exe); + return 1; + } + } + return 1; +} + +static E_Border * +_il_home_desktop_find_border(E_Zone *zone, Efreet_Desktop *desktop) +{ + Eina_List *l; + E_Border *bd; + char *exe = NULL, *p; + + if (!desktop) return NULL; + if (!desktop->exec) return NULL; + p = strchr(desktop->exec, ' '); + if (!p) + exe = strdup(desktop->exec); + else + { + exe = malloc(p - desktop->exec + 1); + memset(exe, 0, sizeof(exe)); + if (exe) eina_strlcpy(exe, desktop->exec, p - desktop->exec + 1); + } + if (exe) + { + p = strrchr(exe, '/'); + if (p) strcpy(exe, p + 1); + } + + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + if (bd->zone != zone) continue; + if (e_exec_startup_id_pid_find(bd->client.netwm.pid, + bd->client.netwm.startup_id) == desktop) + { + if (exe) free(exe); + return bd; + } + if (exe) + { + if (bd->client.icccm.command.argv) + { + char *pp; + + pp = strrchr(bd->client.icccm.command.argv[0], '/'); + if (!pp) pp = bd->client.icccm.command.argv[0]; + if (!strcmp(exe, pp)) + { + free(exe); + return bd; + } + } + if ((bd->client.icccm.name) && + (!strcasecmp(bd->client.icccm.name, exe))) + { + free(exe); + return bd; + } + } + } + if (exe) free(exe); + return NULL; +} + +static int +_il_home_win_cb_timeout(void *data) +{ + Il_Home_Exec *exe; + + if (!(exe = data)) return 1; + + if (exe->handle) e_busycover_pop(exe->cover, exe->handle); + exe->handle = NULL; + + if (!exe->border) + { + exes = eina_list_remove(exes, exe); + E_FREE(exe); + return 0; + } + exe->timeout = NULL; + return 0; +} + +static int +_il_home_border_add(void *data, int type, void *event) +{ + E_Event_Border_Add *ev; + Il_Home_Exec *exe; + Eina_List *l; + + ev = event; + EINA_LIST_FOREACH(exes, l, exe) + { + if (!exe->border) + { + if ((exe->startup_id == ev->border->client.netwm.startup_id) || + (exe->pid == ev->border->client.netwm.pid)) + { + exe->border = ev->border; + } + } + if (!exe->border) continue; + if (exe->border->zone != exe->zone) + { + exe->border->zone = exe->zone; + exe->border->x = exe->zone->x; + exe->border->y = exe->zone->y; + exe->border->changes.pos = 1; + exe->border->changed = 1; + } + if (exe->handle) + { + e_busycover_pop(exe->cover, exe->handle); + exe->handle = NULL; + } + if (exe->timeout) ecore_timer_del(exe->timeout); + exe->timeout = NULL; + } + return 1; +} + +static int +_il_home_border_remove(void *data, int type, void *event) +{ + E_Event_Border_Remove *ev; + Il_Home_Exec *exe; + Eina_List *l; + + ev = event; + EINA_LIST_FOREACH(exes, l, exe) + { + if (exe->border == ev->border) + { + if (exe->exec) ecore_exe_free(exe->exec); + exe->exec = NULL; + if (exe->handle) e_busycover_pop(exe->cover, exe->handle); + exe->handle = NULL; + exe->border = NULL; + break; + } + } + return 1; +} + +static int +_il_home_cb_client_message(void *data, int type, void *event) +{ + Ecore_X_Event_Client_Message *ev; + Instance *inst; + + ev = event; + if (!(inst = data)) return 1; + if (ev->message_type == ECORE_X_ATOM_E_ILLUME_HOME_NEW) + { + E_Zone *zone; + + zone = inst->gcc->gadcon->zone; + if (zone->black_win != ev->win) return 1; + _il_home_win_new(inst); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_HOME_DEL) + { + E_Border *bd; + Eina_List *l; + Il_Home_Win *hwin; + + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + EINA_LIST_FOREACH(inst->wins, l, hwin) + { + if (hwin->win->border == bd) + { + inst->wins = eina_list_remove_list(inst->wins, inst->wins); + e_object_del(E_OBJECT(hwin)); + break; + } + } + } + + return 1; +} + +static int +_il_home_cb_prop_change(void *data, int type, void *event) +{ + Instance *inst; + Ecore_X_Event_Window_Property *ev; + Eina_List *l; + Il_Home_Win *hwin; + + ev = event; + if (!(inst = data)) return 1; +// if (ev->win != ecore_x_window_root_first_get()) return 1; + if (strcmp(ecore_x_atom_name_get(ev->atom), "ENLIGHTENMENT_SCALE")) + return 1; + + EINA_LIST_FOREACH(inst->wins, l, hwin) + if (hwin->o_fm) + { + _il_home_fmc_set(hwin->o_fm); + e_fm2_refresh(hwin->o_fm); + } + + return 1; +} diff --git a/src/modules/illume-home/e_mod_main.h b/src/modules/illume-home/e_mod_main.h new file mode 100644 index 000000000..04c4f9724 --- /dev/null +++ b/src/modules/illume-home/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); + +void il_home_win_cfg_update(void); + +#endif diff --git a/src/modules/illume-home/module.desktop.in b/src/modules/illume-home/module.desktop.in new file mode 100644 index 000000000..c5e5ce227 --- /dev/null +++ b/src/modules/illume-home/module.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Link +Name=Illume-Home +Icon=e-module-illume-home +X-Enlightenment-ModuleType=system +Comment=Illume Home for Embedded +Comment[fr]=Illume pour l'embarqué – Home +Comment[it]=Illume per sistemi embedded – modulo Home diff --git a/src/modules/illume-indicator/e_mod_main.c b/src/modules/illume-indicator/e_mod_main.c new file mode 100644 index 000000000..c825207ed --- /dev/null +++ b/src/modules/illume-indicator/e_mod_main.c @@ -0,0 +1,72 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_ind_win.h" + +/* local variables */ +static Eina_List *iwins = NULL; + +/* external variables */ +const char *_ind_mod_dir = NULL; + +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume-Indicator" }; + +EAPI void * +e_modapi_init(E_Module *m) +{ + E_Manager *man; + Eina_List *ml; + + /* set module priority so we load before others */ + e_module_priority_set(m, 90); + + /* set module directory variable */ + _ind_mod_dir = eina_stringshare_add(m->dir); + + /* loop through the managers (root windows) */ + EINA_LIST_FOREACH(e_manager_list(), ml, man) + { + E_Container *con; + Eina_List *cl; + + /* loop through containers */ + EINA_LIST_FOREACH(man->containers, cl, con) + { + E_Zone *zone; + Eina_List *zl; + + /* for each zone, create an indicator window */ + EINA_LIST_FOREACH(con->zones, zl, zone) + { + Ind_Win *iwin; + + /* try to create new indicator window */ + if (!(iwin = e_mod_ind_win_new(zone))) continue; + iwins = eina_list_append(iwins, iwin); + } + } + } + + return m; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + Ind_Win *iwin; + + /* destroy the indicator windows */ + EINA_LIST_FREE(iwins, iwin) + e_object_del(E_OBJECT(iwin)); + + /* clear module directory variable */ + if (_ind_mod_dir) eina_stringshare_del(_ind_mod_dir); + _ind_mod_dir = NULL; + + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + return 1; +} diff --git a/src/modules/illume-softkey/Makefile.am b/src/modules/illume-softkey/Makefile.am new file mode 100644 index 000000000..e9b26d9cf --- /dev/null +++ b/src/modules/illume-softkey/Makefile.am @@ -0,0 +1,51 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume-softkey +SUBDIRS = images + +EDJE_CC = @edje_cc@ +EDJE_FLAGS = -v \ + -id $(top_srcdir)/src/modules/$(MODULE)/images \ + @EDJE_DEF@ + +# data files for the module +filesdir = $(libdir)/enlightenment/modules/$(MODULE) +files_DATA = \ + e-module-$(MODULE).edj \ + module.desktop + +EXTRA_DIST = \ + e-module-$(MODULE).edc \ + module.desktop.in + +# 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_sft_win.c \ + e_mod_sft_win.h \ + e_mod_main.c \ + e_mod_main.h + +module_la_LIBADD = @e_libs@ @dlopen_libs@ +module_la_LDFLAGS = -module -avoid-version +module_la_DEPENDENCIES = $(top_builddir)/config.h + +e-module-$(MODULE).edj: Makefile $(EXTRA_DIST) + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/src/modules/$(MODULE)/e-module-$(MODULE).edc \ + $(top_builddir)/src/modules/$(MODULE)/e-module-$(MODULE).edj + +clean-local: + rm -f *.edj + +uninstall: + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE) diff --git a/src/modules/illume-softkey/e-module-illume-softkey.edc b/src/modules/illume-softkey/e-module-illume-softkey.edc new file mode 100644 index 000000000..73d4f3ccf --- /dev/null +++ b/src/modules/illume-softkey/e-module-illume-softkey.edc @@ -0,0 +1,133 @@ +collections +{ + group + { + images.image: "module_icon.png" COMP; + name: "icon"; + max: 128 128; + parts + { + part + { + name: "base"; + mouse_events: 0; + description + { + state: "default" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + image.normal: "module_icon.png"; + } + } + } + } + group + { + images + { + image: "shelf_alt_bg.png" COMP; + image: "shelf_alt_over.png" COMP; + image: "shelf_alt_shine.png" COMP; + } + name: "modules/illume-softkey/window"; + parts + { + part + { + name: "base"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + color_class: "shelf_base"; + image.normal: "shelf_alt_bg.png"; + fill.smooth: 0; + } + } + part + { + name: "shine"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + image.normal: "shelf_alt_shine.png"; + rel2.relative: 1.0 0.5; + fill.smooth: 0; + } + } + part + { + name: "over"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + image + { + normal: "shelf_alt_over.png"; + border: 5 5 5 5; + middle: 0; + } + fill.smooth: 0; + } + } + part + { + name: "e.box.extra_buttons"; + type: BOX; + description + { + state: "default" 0.0; + rel1 + { + offset: 3 3; + to: "base"; + } + rel2 + { + relative: 0.60 1.0; + offset: 0 -4; + to: "base"; + } + box + { + layout: "horizontal"; + padding: 2 0; + align: 0.0 0.5; + min: 1 1; + } + } + } + part + { + name: "e.box.buttons"; + type: BOX; + description + { + state: "default" 0.0; + rel1 + { + relative: 1.0 0.0; + to: "e.box.extra_buttons"; + } + rel2 + { + offset: -2 -4; + to: "base"; + } + box + { + layout: "horizontal"; + padding: 2 0; + align: 1.0 0.5; + min: 1 1; + } + } + } + } + } +} diff --git a/src/modules/illume-softkey/e_mod_main.c b/src/modules/illume-softkey/e_mod_main.c new file mode 100644 index 000000000..0be948f57 --- /dev/null +++ b/src/modules/illume-softkey/e_mod_main.c @@ -0,0 +1,76 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_sft_win.h" + +/* local variables */ +static Eina_List *swins = NULL; + +/* external variables */ +const char *_sft_mod_dir = NULL; + +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume-Softkey" }; + +EAPI void * +e_modapi_init(E_Module *m) +{ + E_Manager *man; + Eina_List *ml; + + /* set module priority so we load before others */ + e_module_priority_set(m, 85); + + /* set module directory variable */ + _sft_mod_dir = eina_stringshare_add(m->dir); + + /* loop through the managers (root windows) */ + EINA_LIST_FOREACH(e_manager_list(), ml, man) + { + E_Container *con; + Eina_List *cl; + + /* loop through containers */ + EINA_LIST_FOREACH(man->containers, cl, con) + { + E_Zone *zone; + Eina_List *zl; + + /* for each zone, create a softkey window */ + EINA_LIST_FOREACH(con->zones, zl, zone) + { + Sft_Win *swin; + + /* try to create new softkey window */ + if (!(swin = e_mod_sft_win_new(zone))) continue; + swins = eina_list_append(swins, swin); + } + } + } + + return m; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + Sft_Win *swin; + + /* destroy the softkey windows */ + EINA_LIST_FREE(swins, swin) + e_object_del(E_OBJECT(swin)); + + /* reset softkey geometry for conformant apps */ + ecore_x_e_illume_softkey_geometry_set(ecore_x_window_root_first_get(), + 0, 0, 0, 0); + + /* clear module directory variable */ + if (_sft_mod_dir) eina_stringshare_del(_sft_mod_dir); + _sft_mod_dir = NULL; + + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + return 1; +} diff --git a/src/modules/illume-softkey/e_mod_main.h b/src/modules/illume-softkey/e_mod_main.h new file mode 100644 index 000000000..78ba22502 --- /dev/null +++ b/src/modules/illume-softkey/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 const char *_sft_mod_dir; + +#endif diff --git a/src/modules/illume-softkey/e_mod_sft_win.c b/src/modules/illume-softkey/e_mod_sft_win.c new file mode 100644 index 000000000..72aec3569 --- /dev/null +++ b/src/modules/illume-softkey/e_mod_sft_win.c @@ -0,0 +1,333 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_sft_win.h" + +/* local function prototypes */ +static void _e_mod_sft_win_cb_free(Sft_Win *swin); +static void _e_mod_sft_win_cb_hook_eval_end(void *data, void *data2); +static int _e_mod_sft_win_cb_win_prop(void *data, int type __UNUSED__, void *event); +static int _e_mod_sft_win_cb_client_message(void *data, int type __UNUSED__, void *event); +static void _e_mod_sft_win_cb_resize(E_Win *win); +static void _e_mod_sft_win_create_default_buttons(Sft_Win *swin); +static void _e_mod_sft_win_cb_close(void *data, void *data2 __UNUSED__); +static void _e_mod_sft_win_cb_back(void *data, void *data2 __UNUSED__); + +Sft_Win * +e_mod_sft_win_new(E_Zone *zone) +{ + Sft_Win *swin; + Ecore_X_Window_State states[2]; + + /* create our new softkey window object */ + swin = E_OBJECT_ALLOC(Sft_Win, SFT_WIN_TYPE, _e_mod_sft_win_cb_free); + if (!swin) return NULL; + + swin->zone = zone; + + /* hook into eval so we can set the softkey on the correct zone + swin->hook = e_border_hook_add(E_BORDER_HOOK_EVAL_END, + _e_mod_sft_win_cb_hook_eval_end, swin); +*/ + + /* hook into property change so we can adjust w/ e_scale */ + swin->scale_hdl = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, + _e_mod_sft_win_cb_win_prop, swin); + + /* hook into client messages + swin->msg_hdl = + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _e_mod_sft_win_cb_client_message, swin); + */ + + /* create new window */ + swin->win = e_win_new(zone->container); + swin->win->data = swin; + + /* set some properties on the window */ + e_win_title_set(swin->win, _("Illume Softkey")); + e_win_name_class_set(swin->win, "Illume-Softkey", "Illume-Softkey"); + e_win_no_remember_set(swin->win, EINA_TRUE); + + /* hook into window resize so we can resize our objects */ + e_win_resize_callback_set(swin->win, _e_mod_sft_win_cb_resize); + + /* set this window to not show in taskbar or pager */ + states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER; + ecore_x_netwm_window_state_set(swin->win->evas_win, states, 2); + + /* set this window to not accept or take focus */ + ecore_x_icccm_hints_set(swin->win->evas_win, 0, 0, 0, 0, 0, 0, 0); + + /* create our base object */ + swin->o_base = edje_object_add(swin->win->evas); + if (!e_theme_edje_object_set(swin->o_base, + "base/theme/modules/illume-softkey", + "modules/illume-softkey/window")) + { + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), + "%s/e-module-illume-softkey.edj", _sft_mod_dir); + edje_object_file_set(swin->o_base, buff, + "modules/illume-softkey/window"); + } + evas_object_move(swin->o_base, 0, 0); + evas_object_show(swin->o_base); + + /* create default buttons */ + _e_mod_sft_win_create_default_buttons(swin); + + /* set minimum size of this window */ + e_win_size_min_set(swin->win, zone->w, (32 * e_scale)); + + /* position and resize this window */ + e_win_move_resize(swin->win, zone->x, (zone->y + zone->h - (32 * e_scale)), + zone->w, (32 * e_scale)); + + /* show the window */ + e_win_show(swin->win); + + e_border_zone_set(swin->win->border, zone); + + /* set this window to be a dock window. This needs to be done after show + * as E will sometimes reset the window type */ + ecore_x_netwm_window_type_set(swin->win->evas_win, ECORE_X_WINDOW_TYPE_DOCK); + + /* tell conformant apps our position and size */ + ecore_x_e_illume_softkey_geometry_set(zone->black_win, + zone->x, (zone->h - (32 * e_scale)), + zone->w, (32 * e_scale)); + + return swin; +} + +/* local functions */ +static void +_e_mod_sft_win_cb_free(Sft_Win *swin) +{ + const Evas_Object *box; + + /* delete the message handler */ + if (swin->msg_hdl) ecore_event_handler_del(swin->msg_hdl); + swin->msg_hdl = NULL; + + /* delete the scale handler */ + if (swin->scale_hdl) ecore_event_handler_del(swin->scale_hdl); + swin->scale_hdl = NULL; + + /* delete the border hook */ + if (swin->hook) e_border_hook_del(swin->hook); + swin->hook = NULL; + + if (box = edje_object_part_object_get(swin->o_base, "e.box.buttons")) + { + Evas_Object *btn; + + /* delete the buttons */ + EINA_LIST_FREE(swin->btns, btn) + { + edje_object_part_box_remove(swin->o_base, "e.box.buttons", btn); + evas_object_del(btn); + } + } + if (box = edje_object_part_object_get(swin->o_base, "e.box.extra_buttons")) + { + Evas_Object *btn; + + /* delete the buttons */ + EINA_LIST_FREE(swin->extra_btns, btn) + { + edje_object_part_box_remove(swin->o_base, "e.box.extra_buttons", btn); + evas_object_del(btn); + } + } + + /* delete the objects */ + if (swin->o_base) evas_object_del(swin->o_base); + swin->o_base = NULL; + + /* delete the window */ + if (swin->win) e_object_del(E_OBJECT(swin->win)); + swin->win = NULL; + + /* tell conformant apps our position and size */ + ecore_x_e_illume_softkey_geometry_set(swin->zone->black_win, 0, 0, 0, 0); + + /* free the allocated object */ + E_FREE(swin); +} + +static void +_e_mod_sft_win_cb_hook_eval_end(void *data, void *data2) +{ + Sft_Win *swin; + E_Border *bd; + + if (!(swin = data)) return; + if (!(bd = data2)) return; + if (bd != swin->win->border) return; + + /* check border position and size */ + if (bd->x != swin->zone->x) + { + bd->x = swin->zone->x; + bd->changes.pos = 1; + } + if (bd->y != ((swin->zone->y + swin->zone->h) - bd->h)) + { + bd->y = ((swin->zone->y + swin->zone->h) - bd->h); + bd->changes.pos = 1; + } + if (bd->w != swin->zone->w) + { + bd->w = swin->zone->w; + bd->changes.size = 1; + } + if ((bd->changes.pos) || (bd->changes.size)) bd->changed = 1; + + /* if zone is not correct, set it */ + if (bd->zone != swin->zone) e_border_zone_set(bd, swin->zone); +} + +static int +_e_mod_sft_win_cb_win_prop(void *data, int type __UNUSED__, void *event) +{ + Sft_Win *swin; + Ecore_X_Event_Window_Property *ev; + + ev = event; + + if (!(swin = data)) return 1; + if (ev->win != ecore_x_window_root_get(swin->win->evas_win)) return 1; + if (strcmp(ecore_x_atom_name_get(ev->atom), "ENLIGHTENMENT_SCALE")) return 1; + + /* set minimum size of this window */ + e_win_size_min_set(swin->win, swin->zone->w, (32 * e_scale)); + + /* resize this window */ + e_win_resize(swin->win, swin->zone->w, (32 * e_scale)); + + /* tell conformant apps our position and size */ + ecore_x_e_illume_softkey_geometry_set(swin->zone->black_win, + swin->win->x, swin->win->y, + swin->win->w, (32 * e_scale)); + return 1; +} + +static int +_e_mod_sft_win_cb_client_message(void *data, int type __UNUSED__, void *event) +{ + Sft_Win *swin; + Ecore_X_Event_Client_Message *ev; + + ev = event; + if (!(swin = data)) return 1; + if (ev->win != swin->zone->black_win) return 1; + return 1; +} + +static void +_e_mod_sft_win_cb_resize(E_Win *win) +{ + Sft_Win *swin; + Evas_Object *btn; + const Evas_Object *box; + Eina_List *l; + int mw, mh; + + if (!(swin = win->data)) return; + + /* adjust button(s) size for e_scale */ + EINA_LIST_FOREACH(swin->btns, l, btn) + { + e_widget_size_min_get(btn, &mw, &mh); + evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale)); + evas_object_resize(btn, (mw * e_scale), (mh * e_scale)); + } + + /* adjust box size for content */ + if (box = edje_object_part_object_get(swin->o_base, "e.box.buttons")) + { + evas_object_size_hint_min_get((Evas_Object *)box, &mw, &mh); + evas_object_resize((Evas_Object *)box, mw, mh); + } + + mw = mh = 0; + /* adjust button(s) size for e_scale */ + EINA_LIST_FOREACH(swin->extra_btns, l, btn) + { + e_widget_size_min_get(btn, &mw, &mh); + evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale)); + evas_object_resize(btn, (mw * e_scale), (mh * e_scale)); + } + + /* adjust box size for content */ + if (box = edje_object_part_object_get(swin->o_base, "e.box.extra_buttons")) + { + evas_object_size_hint_min_get((Evas_Object *)box, &mw, &mh); + evas_object_resize((Evas_Object *)box, mw, mh); + } + + /* resize the base object */ + if (swin->o_base) evas_object_resize(swin->o_base, win->w, win->h); +} + +static void +_e_mod_sft_win_create_default_buttons(Sft_Win *swin) +{ + Evas_Object *btn; + int mw, mh; + + /* create back button */ + btn = e_widget_button_add(swin->win->evas, _("Back"), "go-previous", + _e_mod_sft_win_cb_back, swin, NULL); + e_widget_size_min_get(btn, &mw, &mh); + evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale)); + + /* NB: this show is required when packing e_widgets into an edje box else + * the widgets do not receive any events */ + evas_object_show(btn); + + /* add button to box */ + edje_object_part_box_append(swin->o_base, "e.box.buttons", btn); + + /* add button to our list */ + swin->btns = eina_list_append(swin->btns, btn); + + + /* create close button */ + btn = e_widget_button_add(swin->win->evas, _("Close"), "window-close", + _e_mod_sft_win_cb_close, swin, NULL); + e_widget_size_min_get(btn, &mw, &mh); + evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale)); + + /* NB: this show is required when packing e_widgets into an edje box else + * the widgets do not receive any events */ + evas_object_show(btn); + + /* add button to box */ + edje_object_part_box_append(swin->o_base, "e.box.buttons", btn); + + /* add button to our list */ + swin->btns = eina_list_append(swin->btns, btn); +} + +static void +_e_mod_sft_win_cb_close(void *data, void *data2 __UNUSED__) +{ + Sft_Win *swin; + + if (!(swin = data)) return; + ecore_x_e_illume_close_send(swin->zone->black_win); +} + +static void +_e_mod_sft_win_cb_back(void *data, void *data2 __UNUSED__) +{ + Sft_Win *swin; + + if (!(swin = data)) return; + ecore_x_e_illume_focus_back_send(swin->zone->black_win); +} diff --git a/src/modules/illume-softkey/e_mod_sft_win.h b/src/modules/illume-softkey/e_mod_sft_win.h new file mode 100644 index 000000000..d481ed1f2 --- /dev/null +++ b/src/modules/illume-softkey/e_mod_sft_win.h @@ -0,0 +1,24 @@ +#ifndef E_MOD_SFT_WIN_H +# define E_MOD_SFT_WIN_H + +/* define softkey window object type */ +# define SFT_WIN_TYPE 0xE1b0784 + +/* define structure for softkey window */ +typedef struct _Sft_Win Sft_Win; +struct _Sft_Win +{ + E_Object e_obj_inherit; + + E_Zone *zone; + E_Border_Hook *hook; + Ecore_Event_Handler *scale_hdl, *msg_hdl; + + E_Win *win; + Evas_Object *o_base; + Eina_List *btns, *extra_btns; +}; + +Sft_Win *e_mod_sft_win_new(E_Zone *zone); + +#endif diff --git a/src/modules/illume-softkey/images/Makefile.am b/src/modules/illume-softkey/images/Makefile.am new file mode 100644 index 000000000..e6de6fd76 --- /dev/null +++ b/src/modules/illume-softkey/images/Makefile.am @@ -0,0 +1,6 @@ +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = shelf_alt_bg.png \ + shelf_alt_shine.png \ + module_icon.png \ + shelf_alt_over.png diff --git a/src/modules/illume-softkey/images/module_icon.png b/src/modules/illume-softkey/images/module_icon.png new file mode 100644 index 000000000..82c1b76f3 Binary files /dev/null and b/src/modules/illume-softkey/images/module_icon.png differ diff --git a/src/modules/illume-softkey/images/shelf_alt_bg.png b/src/modules/illume-softkey/images/shelf_alt_bg.png new file mode 100644 index 000000000..64e2b2c2c Binary files /dev/null and b/src/modules/illume-softkey/images/shelf_alt_bg.png differ diff --git a/src/modules/illume-softkey/images/shelf_alt_over.png b/src/modules/illume-softkey/images/shelf_alt_over.png new file mode 100644 index 000000000..cef17132f Binary files /dev/null and b/src/modules/illume-softkey/images/shelf_alt_over.png differ diff --git a/src/modules/illume-softkey/images/shelf_alt_shine.png b/src/modules/illume-softkey/images/shelf_alt_shine.png new file mode 100644 index 000000000..5c0588d8b Binary files /dev/null and b/src/modules/illume-softkey/images/shelf_alt_shine.png differ diff --git a/src/modules/illume-softkey/module.desktop.in b/src/modules/illume-softkey/module.desktop.in new file mode 100644 index 000000000..1ae0e2f08 --- /dev/null +++ b/src/modules/illume-softkey/module.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=Illume-Softkey +Icon=e-module-illume-softkey +X-Enlightenment-ModuleType=system +Comment=Illume Softkey for Embedded diff --git a/src/modules/illume2/e_illume.h b/src/modules/illume2/e_illume.h new file mode 100644 index 000000000..4cb8f805b --- /dev/null +++ b/src/modules/illume2/e_illume.h @@ -0,0 +1,329 @@ +#ifndef E_ILLUME_H +# define E_ILLUME_H + +/* include standard E header */ +# include "e.h" + +/** + * @mainpage Illume + * + * @image html e.png + * + * @author Christopher Michael + * @date 2010 + * + * @section illume_toc_sec Table of contents + * + * + * + * @section illume_intro_sec Introduction to Illume + * + * Illume is a module for Enlightenment that modifies the user interface of + * enlightenment to work cleanly and nicely on a mobile device - such as an + * Openmoko phone. It is resolution independent meaning that it can + * accommodate a very wide range of devices, from cell phones and PDAs to + * tablets and desktops. Illume has been designed from the ground up to + * support more than one screen in more than one way (multihead and xinerama). + * + * This is a work in progress and as such is subject to change. + */ + +/** + * @file e_illume.h + * + * This header provides the various defines, structures and functions that + * make writing illume policies easier. + * + * For details on the available functions, see @ref E_Illume_Main_Group. + * + * For details on the configuration structure, see @ref E_Illume_Config_Group. + * + * For details on the virtual keyboard, see @ref E_Illume_Keyboard_Group. + * + * For details on the Policy API, see @ref E_Illume_Policy_Group. + * + * For details on quickpanels, see @ref E_Illume_Quickpanel_Group. + */ + +/** + * @defgroup E_Illume_Keyboard_Group Illume Keyboard Information + * + * The following group defines information needed to interact with the + * Virtual Keyboard. + * + */ + +/* define enumeration for keyboard layout */ +typedef enum _E_Illume_Keyboard_Layout E_Illume_Keyboard_Layout; +enum _E_Illume_Keyboard_Layout +{ + E_ILLUME_KEYBOARD_LAYOUT_NONE, + E_ILLUME_KEYBOARD_LAYOUT_DEFAULT, + E_ILLUME_KEYBOARD_LAYOUT_ALPHA, + E_ILLUME_KEYBOARD_LAYOUT_NUMERIC, + E_ILLUME_KEYBOARD_LAYOUT_PIN, + E_ILLUME_KEYBOARD_LAYOUT_PHONE_NUMBER, + E_ILLUME_KEYBOARD_LAYOUT_HEX, + E_ILLUME_KEYBOARD_LAYOUT_TERMINAL, + E_ILLUME_KEYBOARD_LAYOUT_PASSWORD, + E_ILLUME_KEYBOARD_LAYOUT_IP, + E_ILLUME_KEYBOARD_LAYOUT_HOST, + E_ILLUME_KEYBOARD_LAYOUT_FILE, + E_ILLUME_KEYBOARD_LAYOUT_URL, + E_ILLUME_KEYBOARD_LAYOUT_KEYPAD, + E_ILLUME_KEYBOARD_LAYOUT_J2ME +}; + +/** + * @typedef E_Illume_Keyboard + * @brief structure for keyboard. + * + * @ingroup E_Illume_Keyboard_Group + */ +typedef struct _E_Illume_Keyboard E_Illume_Keyboard; + +/** + * @struct E_Illume_Keyboard + * @brief structure for keyboard. + * + * @ingroup E_Illume_Keyboard_Group + */ +struct _E_Illume_Keyboard +{ + E_Object e_obj_inherit; + + E_Border *border; /**< Test struct member */ + Ecore_Timer *timer; + Ecore_Animator *animator; + + E_Illume_Keyboard_Layout layout; + Eina_List *waiting_borders; + + double start, len; + int adjust, adjust_start, adjust_end; + + unsigned char visible : 1; + unsigned char disabled : 1; + unsigned char fullscreen : 1; +}; + +/** + * @defgroup E_Illume_Policy_Group Illume Policy Information + * + * The following group defines information needed to implement an Illume + * Policy. + * + * @warning There are some requirements that every policy must implement. + */ + +/** + * @def E_ILLUME_POLICY_API_VERSION + * @brief Current version of the Policy API that is supported by the Illume module. + * + * @warning Policies not written to match this version will fail to load. + * + * @ingroup E_Illume_Policy_Group + */ +# define E_ILLUME_POLICY_API_VERSION 2 + +/** + * @struct E_Illume_Policy_Api + * @brief structure for policy api + * + * When Illume tries to load a policy, it will check for the existince of + * this structure. If it is not found, the policy will fail to load. + * + * @warning This structure is required for Illume to load a policy. + * + * @ingroup E_Illume_Policy_Group + */ +typedef struct _E_Illume_Policy_Api E_Illume_Policy_Api; +struct _E_Illume_Policy_Api +{ + int version; /**< The version of this policy. */ + + /**< The name of this policy. */ + const char *name; + /**< The label of this policy. */ + const char *label; +}; + +/** + * @typedef E_Illume_Policy + * @brief structure for policy + * + * This structure actually holds the policy functions to call. + * + * @ingroup E_Illume_Policy_Group + */ +typedef struct _E_Illume_Policy E_Illume_Policy; +struct _E_Illume_Policy +{ + E_Object e_obj_inherit; + + /** pointer to the @ref E_Illume_Policy_Api policy api structure. */ + E_Illume_Policy_Api *api; + + void *handle; + + struct + { + /** @warning Required Functions. */ + void *(*init) (E_Illume_Policy *p); /**< pointer to the function that will be called by Illume to initialize this policy. */ + int (*shutdown) (E_Illume_Policy *p); /**< pointer to the function that Illume will call to shutdown this policy.*/ + + /** @note Optional Functions. */ + void (*border_add) (E_Border *bd); + void (*border_del) (E_Border *bd); + void (*border_focus_in) (E_Border *bd); + void (*border_focus_out) (E_Border *bd); + void (*border_activate) (E_Border *bd); + void (*border_post_fetch) (E_Border *bd); + void (*border_post_assign) (E_Border *bd); + void (*zone_layout) (E_Zone *zone); + void (*zone_move_resize) (E_Zone *zone); + void (*zone_mode_change) (E_Zone *zone, Ecore_X_Atom mode); + void (*zone_close) (E_Zone *zone); + void (*drag_start) (E_Border *bd); + void (*drag_end) (E_Border *bd); + void (*focus_back) (E_Zone *zone); + void (*focus_forward) (E_Zone *zone); + void (*focus_home) (E_Zone *zone); + void (*property_change) (Ecore_X_Event_Window_Property *event); + } funcs; +}; + +/** + * @defgroup E_Illume_Config_Group Illume Configuration Information + * + * The following group defines information pertaining to Illume Configuration. + */ + +/** + * @typedef E_Illume_Config + * @brief structure for Illume configuration. + * + * @ingroup E_Illume_Config_Group + */ +typedef struct _E_Illume_Config E_Illume_Config; +struct _E_Illume_Config +{ + int version; + + struct + { + struct + { + int duration; + } vkbd, quickpanel; + } animation; + + struct + { + const char *name; + struct + { + const char *class, *name, *title; + int type; + struct + { + int class, name, title, type; + } match; + } vkbd, indicator, softkey, home; + Eina_List *zones; + } policy; +}; + + +/** + * @typedef E_Illume_Config_Zone + * @brief structure for Illume zone configuration. + * + * @ingroup E_Illume_Config_Group + */ +typedef struct _E_Illume_Config_Zone E_Illume_Config_Zone; +struct _E_Illume_Config_Zone +{ + int id; /**< Id of the Zone that this config belongs to. */ + struct + { + int dual; + int side; + } mode; + + /* NB: These are not configurable by user...just placeholders */ + struct + { + int size; + } vkbd, indicator, softkey; +}; + +/** + * @defgroup E_Illume_Quickpanel_Group Illume Quickpanel Information + * + * The following group defines information pertaining to Illume Quickpanels. + */ + +/** + * @typedef E_Illume_Quickpanel + * @brief structure for Illume Quickpanels. + * + * @ingroup E_Illume_Quickpanel_Group + */ +typedef struct _E_Illume_Quickpanel E_Illume_Quickpanel; +struct _E_Illume_Quickpanel +{ + E_Object e_obj_inherit; + + E_Zone *zone; + Eina_List *borders; + Ecore_Timer *timer; + Ecore_Animator *animator; + double start, len; + int h, ih, adjust, adjust_start, adjust_end; + unsigned char visible : 1; +}; + +/* define function prototypes that policies can use */ +E_Illume_Config_Zone *e_illume_zone_config_get(int id); + +/* general functions */ +Eina_Bool e_illume_border_is_indicator(E_Border *bd); +Eina_Bool e_illume_border_is_softkey(E_Border *bd); +Eina_Bool e_illume_border_is_keyboard(E_Border *bd); +Eina_Bool e_illume_border_is_home(E_Border *bd); +Eina_Bool e_illume_border_is_splash(E_Border *bd); +Eina_Bool e_illume_border_is_dialog(E_Border *bd); +Eina_Bool e_illume_border_is_qt_frame(E_Border *bd); +Eina_Bool e_illume_border_is_fullscreen(E_Border *bd); +Eina_Bool e_illume_border_is_conformant(E_Border *bd); +Eina_Bool e_illume_border_is_quickpanel(E_Border *bd); + +void e_illume_border_min_get(E_Border *bd, int *w, int *h); +E_Border *e_illume_border_at_xy_get(E_Zone *zone, int x, int y); +E_Border *e_illume_border_parent_get(E_Border *bd); +void e_illume_border_show(E_Border *bd); +void e_illume_border_hide(E_Border *bd); + +/* indicator functions */ +E_Border *e_illume_border_indicator_get(E_Zone *zone); +void e_illume_border_indicator_pos_get(E_Zone *zone, int *x, int *y); + +/* softkey functions */ +E_Border *e_illume_border_softkey_get(E_Zone *zone); +void e_illume_border_softkey_pos_get(E_Zone *zone, int *x, int *y); + +/* keyboard functions */ +E_Illume_Keyboard *e_illume_keyboard_get(void); +void e_illume_keyboard_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h); + +/* home functions */ +E_Border *e_illume_border_home_get(E_Zone *zone); +Eina_List *e_illume_border_home_borders_get(E_Zone *zone); + +/* quickpanel functions */ +E_Illume_Quickpanel *e_illume_quickpanel_by_zone_get(E_Zone *zone); + +#endif diff --git a/src/modules/illume2/e_mod_config_animation.c b/src/modules/illume2/e_mod_config_animation.c new file mode 100644 index 000000000..b7d2eb1ac --- /dev/null +++ b/src/modules/illume2/e_mod_config_animation.c @@ -0,0 +1,127 @@ +#include "e_illume_private.h" +#include "e_mod_config_animation.h" + +/* local function prototypes */ +static void *_e_mod_config_animation_create(E_Config_Dialog *cfd); +static void _e_mod_config_animation_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_e_mod_config_animation_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static void _e_mod_config_animation_change(void *data, Evas_Object *obj, void *event); +static int _e_mod_config_animation_timeout(void *data); + +/* local variables */ +Ecore_Timer *_anim_change_timer = NULL; + +void +e_mod_config_animation_show(E_Container *con, const char *params __UNUSED__) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + + if (e_config_dialog_find("E", "_config_illume_animation_settings")) return; + + v = E_NEW(E_Config_Dialog_View, 1); + if (!v) return; + + v->create_cfdata = _e_mod_config_animation_create; + v->free_cfdata = _e_mod_config_animation_free; + v->basic.create_widgets = _e_mod_config_animation_ui; + v->basic_only = 1; + v->normal_win = 1; + v->scroll = 1; + + cfd = e_config_dialog_new(con, _("Animation Settings"), "E", + "_config_illume_animation_settings", + "enlightenment/animation_settings", 0, v, NULL); + if (!cfd) return; + + e_dialog_resizable_set(cfd->dia, 1); +} + +/* local function prototypes */ +static void * +_e_mod_config_animation_create(E_Config_Dialog *cfd) +{ + return NULL; +} + +static void +_e_mod_config_animation_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + if (_anim_change_timer) ecore_timer_del(_anim_change_timer); + _anim_change_timer = NULL; +} + +static Evas_Object * +_e_mod_config_animation_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *list, *of, *ow; + E_Radio_Group *rg; + + list = e_widget_list_add(evas, 0, 0); + + of = e_widget_framelist_add(evas, _("Keyboard"), 0); + rg = e_widget_radio_group_new(&(_e_illume_cfg->animation.vkbd.duration)); + ow = e_widget_radio_add(evas, _("Slow"), 2000, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Medium"), 1000, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Fast"), 500, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Very Fast"), 250, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Off"), 0, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + of = e_widget_framelist_add(evas, _("Quickpanel"), 0); + rg = e_widget_radio_group_new(&(_e_illume_cfg->animation.quickpanel.duration)); + ow = e_widget_radio_add(evas, _("Slow"), 2000, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Medium"), 1000, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Fast"), 500, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Very Fast"), 250, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + ow = e_widget_radio_add(evas, _("Off"), 0, rg); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_animation_change, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + return list; +} + +static void +_e_mod_config_animation_change(void *data, Evas_Object *obj, void *event) +{ + if (_anim_change_timer) ecore_timer_del(_anim_change_timer); + _anim_change_timer = + ecore_timer_add(0.5, _e_mod_config_animation_timeout, data); +} + +static int +_e_mod_config_animation_timeout(void *data) +{ + e_config_save_queue(); + _anim_change_timer = NULL; + return 0; +} diff --git a/src/modules/illume2/e_mod_main.c b/src/modules/illume2/e_mod_main.c new file mode 100644 index 000000000..44581d02b --- /dev/null +++ b/src/modules/illume2/e_mod_main.c @@ -0,0 +1,127 @@ +#include "e_illume_private.h" +#include "e_mod_main.h" +#include "e_mod_config.h" +#include "e_mod_policy.h" +#include "e_mod_kbd.h" +#include "e_mod_quickpanel.h" + +/* NB: Initially I had done this rewrite with eina_logging enabled, but it + * degraded performance so much that it was just not worth it. So now this + * module just uses printfs on the console to report things */ + +/* external variables */ +const char *_e_illume_mod_dir = NULL; +E_Illume_Keyboard *_e_illume_kbd = NULL; +Eina_List *_e_illume_qps = NULL; + +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Illume2" }; + +EAPI void * +e_modapi_init(E_Module *m) +{ + Eina_List *ml; + E_Manager *man; + + /* set module priority so we load first */ + e_module_priority_set(m, 100); + + /* set module directory variable */ + _e_illume_mod_dir = eina_stringshare_add(m->dir); + + /* try to initialize the config subsystem */ + if (!e_mod_config_init()) + { + /* clear module directory variable */ + if (_e_illume_mod_dir) eina_stringshare_del(_e_illume_mod_dir); + _e_illume_mod_dir = NULL; + + return NULL; + } + + /* try to initialize the policy subsystem */ + if (!e_mod_policy_init()) + { + /* shutdown the config subsystem */ + e_mod_config_shutdown(); + + /* clear module directory variable */ + if (_e_illume_mod_dir) eina_stringshare_del(_e_illume_mod_dir); + _e_illume_mod_dir = NULL; + + return NULL; + } + + /* initialize the keyboard subsystem */ + e_mod_kbd_init(); + + /* initialize the quickpanel subsystem */ + e_mod_quickpanel_init(); + + /* create a new vkbd & hide it initially */ + _e_illume_kbd = e_mod_kbd_new(); + e_mod_kbd_hide(); + + /* loop the zones and create quickpanels for each one */ + EINA_LIST_FOREACH(e_manager_list(), ml, man) + { + Eina_List *cl; + E_Container *con; + + EINA_LIST_FOREACH(man->containers, cl, con) + { + Eina_List *zl; + E_Zone *zone; + + EINA_LIST_FOREACH(con->zones, zl, zone) + { + E_Illume_Quickpanel *qp; + + /* try to create a new quickpanel for this zone */ + if (!(qp = e_mod_quickpanel_new(zone))) continue; + + /* append new qp to list */ + _e_illume_qps = eina_list_append(_e_illume_qps, qp); + } + } + } + + return m; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + E_Illume_Quickpanel *qp; + + /* delete the quickpanels */ + EINA_LIST_FREE(_e_illume_qps, qp) + e_object_del(E_OBJECT(qp)); + + /* shutdown the quickpanel subsystem */ + e_mod_quickpanel_shutdown(); + + /* delete the keyboard object */ + if (_e_illume_kbd) e_object_del(E_OBJECT(_e_illume_kbd)); + _e_illume_kbd = NULL; + + /* shutdown the keyboard subsystem */ + e_mod_kbd_shutdown(); + + /* shutdown the policy subsystem */ + e_mod_policy_shutdown(); + + /* shutdown the config subsystem */ + e_mod_config_shutdown(); + + /* clear module directory variable */ + if (_e_illume_mod_dir) eina_stringshare_del(_e_illume_mod_dir); + _e_illume_mod_dir = NULL; + + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + return e_mod_config_save(); +} diff --git a/src/modules/illume2/e_mod_quickpanel.c b/src/modules/illume2/e_mod_quickpanel.c new file mode 100644 index 000000000..14dcc3054 --- /dev/null +++ b/src/modules/illume2/e_mod_quickpanel.c @@ -0,0 +1,415 @@ +#include "e_illume_private.h" +#include "e_mod_quickpanel.h" + +/* local function prototypes */ +static int _e_mod_quickpanel_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_quickpanel_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_quickpanel_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event); +static void _e_mod_quickpanel_cb_post_fetch(void *data __UNUSED__, void *data2); +static void _e_mod_quickpanel_cb_free(E_Illume_Quickpanel *qp); +static int _e_mod_quickpanel_cb_delay_hide(void *data); +static void _e_mod_quickpanel_slide(E_Illume_Quickpanel *qp, int visible, double len); +static void _e_mod_quickpanel_hide(E_Illume_Quickpanel *qp); +static int _e_mod_quickpanel_cb_animate(void *data); +static void _e_mod_quickpanel_position_update(E_Illume_Quickpanel *qp); + +/* local variables */ +static Eina_List *_qp_hdls = NULL; +static E_Border_Hook *_qp_hook = NULL; +static Ecore_X_Window _qp_input_win = 0; + +int +e_mod_quickpanel_init(void) +{ + /* add handlers for messages we are interested in */ + _qp_hdls = + eina_list_append(_qp_hdls, + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _e_mod_quickpanel_cb_client_message, + NULL)); + _qp_hdls = + eina_list_append(_qp_hdls, + ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, + _e_mod_quickpanel_cb_mouse_down, + NULL)); + _qp_hdls = + eina_list_append(_qp_hdls, + ecore_event_handler_add(E_EVENT_BORDER_ADD, + _e_mod_quickpanel_cb_border_add, + NULL)); + + /* add hook for new borders so we can test for qp borders */ + _qp_hook = e_border_hook_add(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, + _e_mod_quickpanel_cb_post_fetch, NULL); + + return 1; +} + +int +e_mod_quickpanel_shutdown(void) +{ + Ecore_Event_Handler *hdl; + + /* delete the event handlers */ + EINA_LIST_FREE(_qp_hdls, hdl) + ecore_event_handler_del(hdl); + + /* delete the border hook */ + if (_qp_hook) e_border_hook_del(_qp_hook); + _qp_hook = NULL; + + return 1; +} + +E_Illume_Quickpanel * +e_mod_quickpanel_new(E_Zone *zone) +{ + E_Illume_Quickpanel *qp; + + /* try to allocate a new quickpanel object */ + qp = E_OBJECT_ALLOC(E_Illume_Quickpanel, E_ILLUME_QP_TYPE, + _e_mod_quickpanel_cb_free); + if (!qp) return NULL; + + /* set quickpanel zone */ + qp->zone = zone; + + return qp; +} + +void +e_mod_quickpanel_show(E_Illume_Quickpanel *qp) +{ + E_Illume_Config_Zone *cz; + int duration; + + /* delete the animator if it exists */ + if (qp->animator) ecore_animator_del(qp->animator); + qp->animator = NULL; + + /* delete any existing timer */ + if (qp->timer) ecore_timer_del(qp->timer); + qp->timer = NULL; + + /* if it's already visible, or has no borders to show, then get out */ + if ((qp->visible) || (!qp->borders)) return; + + duration = _e_illume_cfg->animation.quickpanel.duration; + cz = e_illume_zone_config_get(qp->zone->id); + qp->ih = cz->indicator.size; + + if (!_qp_input_win) + { + /* create a new input window to catch clicks */ + _qp_input_win = + ecore_x_window_input_new(qp->zone->container->win, + qp->zone->x, qp->zone->y, + qp->zone->w, qp->zone->h); + ecore_x_window_show(_qp_input_win); + + /* grab mouse */ + if (!e_grabinput_get(_qp_input_win, 1, _qp_input_win)) + { + ecore_x_window_free(_qp_input_win); + _qp_input_win = 0; + return; + } + } + + /* check animation duration */ + if (duration <= 0) + { + Eina_List *l; + E_Border *bd; + int ny = 0; + + ny = qp->ih; + + /* if we are not animating, just show the borders */ + EINA_LIST_FOREACH(qp->borders, l, bd) + { + if (!bd->visible) e_illume_border_show(bd); + e_border_fx_offset(bd, 0, ny); + ny += bd->h; + } + qp->visible = 1; + } + else + _e_mod_quickpanel_slide(qp, 1, (double)duration / 1000.0); +} + +void +e_mod_quickpanel_hide(E_Illume_Quickpanel *qp) +{ + if (!qp->visible) return; + if (!qp->timer) + qp->timer = ecore_timer_add(0.2, _e_mod_quickpanel_cb_delay_hide, qp); +} + +/* local functions */ +static int +_e_mod_quickpanel_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_X_Event_Client_Message *ev; + + ev = event; + if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE) + { + E_Zone *zone; + + if (zone = e_util_zone_window_find(ev->win)) + { + E_Illume_Quickpanel *qp; + + if (qp = e_illume_quickpanel_by_zone_get(zone)) + { + if (ev->data.l[0] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF) + e_mod_quickpanel_hide(qp); + else + e_mod_quickpanel_show(qp); + } + } + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE) + { + E_Border *bd; + E_Illume_Quickpanel *qp; + + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + if (!(qp = e_illume_quickpanel_by_zone_get(bd->zone))) return 1; + _e_mod_quickpanel_position_update(qp); + } + + return 1; +} + +static int +_e_mod_quickpanel_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Event_Mouse_Button *ev; + Eina_List *l; + E_Illume_Quickpanel *qp; + + ev = event; + if (ev->event_window != _qp_input_win) return 1; + EINA_LIST_FOREACH(_e_illume_qps, l, qp) + if (qp->visible) + ecore_x_e_illume_quickpanel_state_send(qp->zone->black_win, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + + return 1; +} + +static int +_e_mod_quickpanel_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Add *ev; + E_Illume_Quickpanel *qp; + E_Zone *zone; + int iy; + + ev = event; + if (!ev->border->client.illume.quickpanel.quickpanel) return 1; + + zone = ev->border->zone; + + /* if this border should be on a different zone, get requested zone */ + if (zone->num != ev->border->client.illume.quickpanel.zone) + { + E_Container *con; + int zn = 0; + + /* find this zone */ + con = e_container_current_get(e_manager_current_get()); + zn = ev->border->client.illume.quickpanel.zone; + zone = e_util_container_zone_number_get(con->num, zn); + if (!zone) return 1; + } + + if (!(qp = e_illume_quickpanel_by_zone_get(zone))) return 1; + + /* set position and zone */ + e_illume_border_indicator_pos_get(zone, NULL, &iy); + if ((ev->border->x != zone->x) || (ev->border->y != iy)) + e_border_move(ev->border, zone->x, iy); + if (ev->border->zone != zone) + e_border_zone_set(ev->border, zone); + + /* hide this border */ + e_illume_border_hide(ev->border); + + qp->h += ev->border->h; + + /* add this border to QP border collection */ + qp->borders = eina_list_append(qp->borders, ev->border); + + return 1; +} + +static void +_e_mod_quickpanel_cb_post_fetch(void *data __UNUSED__, void *data2) +{ + E_Border *bd; + + if (!(bd = data2)) return; + if (!bd->client.illume.quickpanel.quickpanel) return; + bd->stolen = 1; +} + +static void +_e_mod_quickpanel_cb_free(E_Illume_Quickpanel *qp) +{ + E_Border *bd; + + /* delete the animator if it exists */ + if (qp->animator) ecore_animator_del(qp->animator); + qp->animator = NULL; + + /* delete the timer if it exists */ + if (qp->timer) ecore_timer_del(qp->timer); + qp->timer = NULL; + + /* set the borders of this quickpanel to not stolen */ + EINA_LIST_FREE(qp->borders, bd) + bd->stolen = 0; + + /* free the structure */ + E_FREE(qp); +} + +static int +_e_mod_quickpanel_cb_delay_hide(void *data) +{ + E_Illume_Quickpanel *qp; + + if (!(qp = data)) return 0; + _e_mod_quickpanel_hide(qp); + return 0; +} + +static void +_e_mod_quickpanel_slide(E_Illume_Quickpanel *qp, int visible, double len) +{ + qp->start = ecore_loop_time_get(); + qp->len = len; + qp->adjust_start = qp->adjust; + qp->adjust_end = 0; + if (visible) qp->adjust_end = qp->h; + if (!qp->animator) + qp->animator = ecore_animator_add(_e_mod_quickpanel_cb_animate, qp); +} + +static void +_e_mod_quickpanel_hide(E_Illume_Quickpanel *qp) +{ + int duration; + + /* delete the animator if it exists */ + if (qp->animator) ecore_animator_del(qp->animator); + qp->animator = NULL; + + /* delete the timer if it exists */ + if (qp->timer) ecore_timer_del(qp->timer); + qp->timer = NULL; + + /* if it's not visible, we can't hide it */ + if (!qp->visible) return; + + duration = _e_illume_cfg->animation.quickpanel.duration; + + /* destroy the input window */ + if (_qp_input_win) + { + ecore_x_window_free(_qp_input_win); + e_grabinput_release(_qp_input_win, _qp_input_win); + _qp_input_win = 0; + } + + if (duration <= 0) + { + Eina_List *l; + E_Border *bd; + + /* if we are not animating, hide the qp borders */ + EINA_LIST_REVERSE_FOREACH(qp->borders, l, bd) + { + e_border_fx_offset(bd, 0, 0); + if (bd->visible) e_illume_border_hide(bd); + } + qp->visible = 0; + } + else + _e_mod_quickpanel_slide(qp, 0, (double)duration / 1000.0); +} + +static int +_e_mod_quickpanel_cb_animate(void *data) +{ + E_Illume_Quickpanel *qp; + Eina_List *l; + E_Border *bd; + int pbh = 0; + double t, v = 1.0; + + if (!(qp = data)) return 0; + t = (ecore_loop_time_get() - qp->start); + if (t > qp->len) t = qp->len; + if (qp->len > 0.0) + { + v = (t / qp->len); + v = (1.0 - v); + v = (v * v * v * v); + v = (1.0 - v); + } + else + t = qp->len; + + qp->adjust = (qp->adjust_end * v) + (qp->adjust_start * (1.0 - v)); + + pbh = (qp->ih - qp->h); + EINA_LIST_FOREACH(qp->borders, l, bd) + { + /* don't adjust borders that are being deleted */ + if (e_object_is_del(E_OBJECT(bd))) continue; + if (bd->fx.y != (qp->adjust + pbh)) + e_border_fx_offset(bd, 0, (qp->adjust + pbh)); + pbh += bd->h; + if (!qp->visible) + { + if (bd->fx.y > 0) + { + if (!bd->visible) e_illume_border_show(bd); + } + } + else + { + if (bd->fx.y <= 10) + { + if (bd->visible) e_illume_border_hide(bd); + } + } + } + + if (t == qp->len) + { + qp->animator = NULL; + if (qp->visible) qp->visible = 0; + else qp->visible = 1; + return 0; + } + + return 1; +} + +static void +_e_mod_quickpanel_position_update(E_Illume_Quickpanel *qp) +{ + Eina_List *l; + E_Border *bd; + int iy = 0; + + e_mod_quickpanel_hide(qp); + e_illume_border_indicator_pos_get(qp->zone, NULL, &iy); + EINA_LIST_FOREACH(qp->borders, l, bd) + e_border_move(bd, qp->zone->x, iy); +}