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/Makefile.am b/src/modules/illume-indicator/Makefile.am new file mode 100644 index 000000000..688486ac9 --- /dev/null +++ b/src/modules/illume-indicator/Makefile.am @@ -0,0 +1,51 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume-indicator +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_ind_win.c \ + e_mod_ind_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-indicator/e-module-illume-indicator.edc b/src/modules/illume-indicator/e-module-illume-indicator.edc new file mode 100644 index 000000000..df8d9197d --- /dev/null +++ b/src/modules/illume-indicator/e-module-illume-indicator.edc @@ -0,0 +1,57 @@ +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: "base_bg.png" COMP; + name: "modules/illume-indicator/window"; + parts + { + part + { + name: "base"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + color_class: "shelf_base"; + image.normal: "base_bg.png"; + image.border: 2 2 2 2; + fill.smooth: 0; + } + } + part + { + name: "e.swallow.content"; + type: SWALLOW; + description + { + state: "default" 0.0; + rel1.offset: 3 3; + rel2.offset: -4 -4; + } + } + } + } +} diff --git a/src/modules/illume-indicator/e_mod_ind_win.c b/src/modules/illume-indicator/e_mod_ind_win.c new file mode 100644 index 000000000..8de4b5d8d --- /dev/null +++ b/src/modules/illume-indicator/e_mod_ind_win.c @@ -0,0 +1,475 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_ind_win.h" + +/* local function prototypes */ +static void _e_mod_ind_win_cb_free(Ind_Win *iwin); +static int _e_mod_ind_win_cb_win_prop(void *data, int type __UNUSED__, void *event); +static void _e_mod_ind_win_cb_resize(E_Win *win); +static void _e_mod_ind_win_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); +static void _e_mod_ind_win_cb_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); +static void _e_mod_ind_win_cb_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); +static void _e_mod_ind_win_cb_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h); +static void _e_mod_ind_win_cb_size_request(void *data __UNUSED__, E_Gadcon *gc __UNUSED__, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__); +static Evas_Object *_e_mod_ind_win_cb_frame_request(void *data __UNUSED__, E_Gadcon_Client *gcc __UNUSED__, const char *style __UNUSED__); +static void _e_mod_ind_win_cb_menu_items_append(void *data, E_Gadcon_Client *gcc __UNUSED__, E_Menu *mn); +static void _e_mod_ind_win_cb_menu_append(Ind_Win *iwin, E_Menu *mn); +static void _e_mod_ind_win_cb_menu_pre(void *data, E_Menu *mn); +static void _e_mod_ind_win_cb_menu_post(void *data, E_Menu *mn __UNUSED__); +static void _e_mod_ind_win_cb_menu_contents(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__); +static void _e_mod_ind_win_cb_menu_edit(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__); + +Ind_Win * +e_mod_ind_win_new(E_Zone *zone) +{ + Ind_Win *iwin; + Ecore_X_Window_State states[2]; + + /* create our new indicator window object */ + iwin = E_OBJECT_ALLOC(Ind_Win, IND_WIN_TYPE, _e_mod_ind_win_cb_free); + if (!iwin) return NULL; + + iwin->zone = zone; + + /* hook into property change so we can adjust w/ e_scale */ + iwin->scale_hdl = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, + _e_mod_ind_win_cb_win_prop, iwin); + + /* create new window */ + iwin->win = e_win_new(zone->container); + iwin->win->data = iwin; + + /* set some properties on the window */ + e_win_title_set(iwin->win, _("Illume Indicator")); + e_win_name_class_set(iwin->win, "Illume-Indicator", "Illume-Indicator"); + e_win_no_remember_set(iwin->win, EINA_TRUE); + + /* hook into window resize so we can resize our objects */ + e_win_resize_callback_set(iwin->win, _e_mod_ind_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(iwin->win->evas_win, states, 2); + + /* set this window to not accept or take focus */ + ecore_x_icccm_hints_set(iwin->win->evas_win, 0, 0, 0, 0, 0, 0, 0); + + /* create our event rectangle */ + iwin->o_event = evas_object_rectangle_add(iwin->win->evas); + evas_object_color_set(iwin->o_event, 0, 0, 0, 0); + evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_DOWN, + _e_mod_ind_win_cb_mouse_down, iwin); + evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_UP, + _e_mod_ind_win_cb_mouse_up, iwin); + evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_MOVE, + _e_mod_ind_win_cb_mouse_move, iwin); + evas_object_move(iwin->o_event, 0, 0); + evas_object_show(iwin->o_event); + + /* create our base object */ + iwin->o_base = edje_object_add(iwin->win->evas); + if (!e_theme_edje_object_set(iwin->o_base, + "base/theme/modules/illume-indicator", + "modules/illume-indicator/window")) + { + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), + "%s/e-module-illume-indicator.edj", _ind_mod_dir); + edje_object_file_set(iwin->o_base, buff, + "modules/illume-indicator/window"); + } + evas_object_move(iwin->o_base, 0, 0); + evas_object_show(iwin->o_base); + + /* create our gadget container */ + iwin->gadcon = e_gadcon_swallowed_new("illume-indicator", zone->id, + iwin->o_base, "e.swallow.content"); +// iwin->gadcon->instant_edit = 1; + edje_extern_object_min_size_set(iwin->gadcon->o_container, zone->w, + (32 * e_scale)); + edje_object_part_swallow(iwin->o_base, "e.swallow.container", + iwin->gadcon->o_container); + e_gadcon_min_size_request_callback_set(iwin->gadcon, + _e_mod_ind_win_cb_min_size_request, + iwin); + e_gadcon_size_request_callback_set(iwin->gadcon, + _e_mod_ind_win_cb_size_request, iwin); + e_gadcon_frame_request_callback_set(iwin->gadcon, + _e_mod_ind_win_cb_frame_request, iwin); + e_gadcon_orient(iwin->gadcon, E_GADCON_ORIENT_FLOAT); + e_gadcon_zone_set(iwin->gadcon, zone); + e_gadcon_ecore_evas_set(iwin->gadcon, iwin->win->ecore_evas); + e_gadcon_util_menu_attach_func_set(iwin->gadcon, + _e_mod_ind_win_cb_menu_items_append, iwin); + e_gadcon_populate(iwin->gadcon); + + /* set minimum size of this window */ + e_win_size_min_set(iwin->win, zone->w, (32 * e_scale)); + + /* position and resize this window */ + e_win_move_resize(iwin->win, zone->x, zone->y, zone->w, (32 * e_scale)); + + /* show the window */ + e_win_show(iwin->win); + + /* set this window on proper zone */ + e_border_zone_set(iwin->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(iwin->win->evas_win, ECORE_X_WINDOW_TYPE_DOCK); + + /* tell conformant apps our position and size */ + ecore_x_e_illume_indicator_geometry_set(zone->black_win, zone->x, zone->y, + zone->w, (32 * e_scale)); + + return iwin; +} + +/* local function prototypes */ +static void +_e_mod_ind_win_cb_free(Ind_Win *iwin) +{ + /* delete the scale handler */ + if (iwin->scale_hdl) ecore_event_handler_del(iwin->scale_hdl); + iwin->scale_hdl = NULL; + + /* delete the border hook */ + if (iwin->hook) e_border_hook_del(iwin->hook); + iwin->hook = NULL; + + /* delete the menu */ + if (iwin->menu) + { + e_menu_post_deactivate_callback_set(iwin->menu, NULL, NULL); + e_object_del(E_OBJECT(iwin->menu)); + } + iwin->menu = NULL; + + /* delete the gadget container */ + if (iwin->gadcon) e_object_del(E_OBJECT(iwin->gadcon)); + iwin->gadcon = NULL; + + /* delete the objects */ + if (iwin->o_base) evas_object_del(iwin->o_base); + iwin->o_base = NULL; + if (iwin->o_event) evas_object_del(iwin->o_event); + iwin->o_event = NULL; + + /* tell conformant apps our position and size */ + ecore_x_e_illume_indicator_geometry_set(iwin->zone->black_win, 0, 0, 0, 0); + ecore_x_e_illume_zone_set(iwin->win->border->client.win, iwin->zone->black_win); + + /* delete the window */ + if (iwin->win) e_object_del(E_OBJECT(iwin->win)); + iwin->win = NULL; + + /* free the allocated object */ + E_FREE(iwin); +} + +static int +_e_mod_ind_win_cb_win_prop(void *data, int type __UNUSED__, void *event) +{ + Ind_Win *iwin; + Ecore_X_Event_Window_Property *ev; + + ev = event; + + if (!(iwin = data)) return 1; + if (ev->win != ecore_x_window_root_get(iwin->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(iwin->win, iwin->zone->w, (32 * e_scale)); + + /* resize this window */ + e_win_resize(iwin->win, iwin->zone->w, (32 * e_scale)); + + /* tell conformant apps our position and size */ + ecore_x_e_illume_indicator_geometry_set(iwin->zone->black_win, + iwin->win->x, iwin->win->y, + iwin->win->w, (32 * e_scale)); + + return 1; +} + +static void +_e_mod_ind_win_cb_resize(E_Win *win) +{ + Ind_Win *iwin; + + if (!(iwin = win->data)) return; + if (iwin->o_event) evas_object_resize(iwin->o_event, win->w, win->h); + if (iwin->o_base) evas_object_resize(iwin->o_base, win->w, win->h); + if (iwin->gadcon->o_container) + edje_extern_object_min_size_set(iwin->gadcon->o_container, win->w, win->h); +} + +static void +_e_mod_ind_win_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) +{ + Ind_Win *iwin; + Evas_Event_Mouse_Down *ev; + + ev = event; + if (!(iwin = data)) return; + if (ev->button == 1) + { + iwin->mouse_down = 1; + + /* make sure we can drag */ + if (iwin->win->border->client.illume.drag.locked) return; + + iwin->drag.start = 1; + iwin->drag.dnd = 0; + iwin->drag.y = ev->output.y; + iwin->drag.by = iwin->win->border->y; + + /* change mouse pointer to indicate we are dragging */ + if (iwin->win->border->pointer) + e_pointer_type_push(iwin->win->border->pointer, + iwin->win->border, "move"); + } + else if (ev->button == 3) + { + int x, y; + + /* create our popup menu */ + iwin->menu = e_menu_new(); + e_menu_post_deactivate_callback_set(iwin->menu, + _e_mod_ind_win_cb_menu_post, iwin); + + /* append items to our menu */ + _e_mod_ind_win_cb_menu_append(iwin, iwin->menu); + + /* show menu */ + e_gadcon_canvas_zone_geometry_get(iwin->gadcon, &x, &y, NULL, NULL); + e_menu_activate_mouse(iwin->menu, iwin->zone, x + ev->output.x, + y + ev->output.y, 1, 1, + E_MENU_POP_DIRECTION_AUTO, ev->timestamp); + } +} + +static void +_e_mod_ind_win_cb_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) +{ + Ind_Win *iwin; + Evas_Event_Mouse_Up *ev; + + ev = event; + if (ev->button != 1) return; + if (!(iwin = data)) return; + + /* if we are not dragging, send message to show quickpanel */ + if ((!iwin->drag.dnd) && (iwin->mouse_down == 1)) + { + Ecore_X_Window xwin; + + xwin = iwin->win->border->zone->black_win; + ecore_x_e_illume_quickpanel_state_send + (xwin, ECORE_X_ILLUME_QUICKPANEL_STATE_ON); + } + else if (iwin->drag.dnd) + { + E_Border *bd; + + bd = iwin->win->border; + + /* reset mouse pointer */ + if (bd->pointer) e_pointer_type_pop(bd->pointer, bd, "move"); + + /* tell edj we are done moving */ + edje_object_signal_emit(iwin->o_base, "e,action,move,stop", "e"); + + /* send message that we are done dragging */ + ecore_x_e_illume_drag_end_send(bd->client.win); + + /* update quickpanel position if needed */ + if (bd->y != iwin->drag.by) + ecore_x_e_illume_quickpanel_position_update_send(bd->client.win); + } + iwin->drag.start = 0; + iwin->drag.dnd = 0; + iwin->drag.y = 0; + iwin->drag.by = 0; + iwin->mouse_down = 0; +} + +static void +_e_mod_ind_win_cb_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) +{ + Ind_Win *iwin; + Evas_Event_Mouse_Move *ev; + E_Border *bd; + + ev = event; + if (!(iwin = data)) return; + bd = iwin->win->border; + if (iwin->drag.start) + { + iwin->drag.dnd = 1; + iwin->drag.start = 0; + + /* tell edj we are going to start moving */ + edje_object_signal_emit(iwin->o_base, "e,action,move,start", "e"); + + /* send message that we are going to start dragging */ + ecore_x_e_illume_drag_start_send(bd->client.win); + } + + /* make sure we are dragging */ + if (iwin->drag.dnd) + { + int dy, py, ny; + + /* get current mouse position */ + py = ev->cur.output.y; + + /* do moves in 'chunks' of screen size */ + dy = ((bd->zone->h - bd->h) / 8); + + /* are we moving up or down ? */ + if (ev->cur.output.y > ev->prev.output.y) + { + /* moving down */ + if ((py - iwin->drag.y) < dy) return; + } + else if (ev->cur.output.y < ev->prev.output.y) + { + /* moving up */ + if ((iwin->drag.y - py) < dy) return; + } + else return; + + if (py > iwin->drag.y) + ny = bd->y + dy; + else if (py < iwin->drag.y) + ny = bd->y - dy; + else return; + + /* make sure we don't drag off the screen */ + if (ny < iwin->zone->y) + ny = iwin->zone->y; + else if ((ny + bd->h) > (iwin->zone->y + iwin->zone->h)) + return; + + /* move the border if we need to */ + if (bd->y != ny) + { + bd->y = ny; + bd->changes.pos = 1; + bd->changed = 1; + } + } +} + +static void +_e_mod_ind_win_cb_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h) +{ + Ind_Win *iwin; + + if (!(iwin = data)) return; + if (gc != iwin->gadcon) return; + if (h < iwin->win->h) h = iwin->win->h; + edje_extern_object_min_size_set(iwin->gadcon->o_container, w, h); +} + +static void +_e_mod_ind_win_cb_size_request(void *data __UNUSED__, E_Gadcon *gc __UNUSED__, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__) +{ + return; +} + +static Evas_Object * +_e_mod_ind_win_cb_frame_request(void *data __UNUSED__, E_Gadcon_Client *gcc __UNUSED__, const char *style __UNUSED__) +{ + return NULL; +} + +static void +_e_mod_ind_win_cb_menu_items_append(void *data, E_Gadcon_Client *gcc __UNUSED__, E_Menu *mn) +{ + Ind_Win *iwin; + + if (!(iwin = data)) return; + _e_mod_ind_win_cb_menu_append(iwin, mn); +} + +static void +_e_mod_ind_win_cb_menu_append(Ind_Win *iwin, E_Menu *mn) +{ + E_Menu *subm; + E_Menu_Item *mi; + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), + "%s/e-module-illume-indicator.edj", _ind_mod_dir); + + subm = e_menu_new(); + mi = e_menu_item_new(mn); + e_menu_item_label_set(mi, _("Illume Indicator")); + e_menu_item_icon_edje_set(mi, buff, "icon"); + e_menu_pre_activate_callback_set(subm, _e_mod_ind_win_cb_menu_pre, iwin); + e_menu_item_submenu_set(mi, subm); +} + +static void +_e_mod_ind_win_cb_menu_pre(void *data, E_Menu *mn) +{ + Ind_Win *iwin; + E_Menu_Item *mi; + + if (!(iwin = data)) return; + e_menu_pre_activate_callback_set(mn, NULL, NULL); + + mi = e_menu_item_new(mn); + e_menu_item_label_set(mi, _("Set Contents")); + e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); + e_menu_item_callback_set(mi, _e_mod_ind_win_cb_menu_contents, iwin); + + mi = e_menu_item_new(mn); + if (iwin->gadcon->editing) + e_menu_item_label_set(mi, _("End Move/Resize Items")); + else + e_menu_item_label_set(mi, _("Begin Move/Resize Items")); + + e_util_menu_item_theme_icon_set(mi, "transform-scale"); + e_menu_item_callback_set(mi, _e_mod_ind_win_cb_menu_edit, iwin); +} + +static void +_e_mod_ind_win_cb_menu_post(void *data, E_Menu *mn __UNUSED__) +{ + Ind_Win *iwin; + + if (!(iwin = data)) return; + if (!iwin->menu) return; + e_object_del(E_OBJECT(iwin->menu)); + iwin->menu = NULL; +} + +static void +_e_mod_ind_win_cb_menu_contents(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__) +{ + Ind_Win *iwin; + + if (!(iwin = data)) return; + if (!iwin->gadcon->config_dialog) + e_int_gadcon_config_shelf(iwin->gadcon); +} + +static void +_e_mod_ind_win_cb_menu_edit(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__) +{ + Ind_Win *iwin; + + if (!(iwin = data)) return; + if (iwin->gadcon->editing) + e_gadcon_edit_end(iwin->gadcon); + else + e_gadcon_edit_begin(iwin->gadcon); +} diff --git a/src/modules/illume-indicator/e_mod_ind_win.h b/src/modules/illume-indicator/e_mod_ind_win.h new file mode 100644 index 000000000..1f2036585 --- /dev/null +++ b/src/modules/illume-indicator/e_mod_ind_win.h @@ -0,0 +1,32 @@ +#ifndef E_MOD_IND_WIN_H +# define E_MOD_IND_WIN_H + +/* define indicator window object type */ +# define IND_WIN_TYPE 0xE1b0886 + +/* define structure for indicator window */ +typedef struct _Ind_Win Ind_Win; +struct _Ind_Win +{ + E_Object e_obj_inherit; + + E_Zone *zone; + E_Border_Hook *hook; + Ecore_Event_Handler *scale_hdl; + + E_Win *win; + Evas_Object *o_base, *o_event; + E_Gadcon *gadcon; + E_Menu *menu; + + struct + { + int y, start, dnd, by; + } drag; + + int mouse_down; +}; + +Ind_Win *e_mod_ind_win_new(E_Zone *zone); + +#endif 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-indicator/e_mod_main.h b/src/modules/illume-indicator/e_mod_main.h new file mode 100644 index 000000000..9591f0c1f --- /dev/null +++ b/src/modules/illume-indicator/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 *_ind_mod_dir; + +#endif diff --git a/src/modules/illume-indicator/images/Makefile.am b/src/modules/illume-indicator/images/Makefile.am new file mode 100644 index 000000000..692077fed --- /dev/null +++ b/src/modules/illume-indicator/images/Makefile.am @@ -0,0 +1,4 @@ +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = base_bg.png \ + module_icon.png diff --git a/src/modules/illume-indicator/images/base_bg.png b/src/modules/illume-indicator/images/base_bg.png new file mode 100644 index 000000000..a47ea1659 Binary files /dev/null and b/src/modules/illume-indicator/images/base_bg.png differ diff --git a/src/modules/illume-indicator/images/module_icon.png b/src/modules/illume-indicator/images/module_icon.png new file mode 100644 index 000000000..82c1b76f3 Binary files /dev/null and b/src/modules/illume-indicator/images/module_icon.png differ diff --git a/src/modules/illume-indicator/module.desktop.in b/src/modules/illume-indicator/module.desktop.in new file mode 100644 index 000000000..249dbf46a --- /dev/null +++ b/src/modules/illume-indicator/module.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=Illume-Indicator +Icon=e-module-illume-indicator +X-Enlightenment-ModuleType=system +Comment=Illume Indicator for Embedded 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/Makefile.am b/src/modules/illume2/Makefile.am new file mode 100644 index 000000000..aefdf0639 --- /dev/null +++ b/src/modules/illume2/Makefile.am @@ -0,0 +1,80 @@ +MAINTAINERCLEANFILES = Makefile.in module.desktop +MODULE = illume2 +SUBDIRS = images keyboards policies doc + +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_illume.h \ + e_illume.c \ + e_illume_private.h \ + e_mod_config_policy.h \ + e_mod_config_policy.c \ + e_mod_select_window.h \ + e_mod_select_window.c \ + e_mod_config_windows.h \ + e_mod_config_windows.c \ + e_mod_config_animation.h \ + e_mod_config_animation.c \ + e_mod_quickpanel.h \ + e_mod_quickpanel.c \ + e_mod_kbd_dbus.h \ + e_mod_kbd_dbus.c \ + e_mod_kbd.h \ + e_mod_kbd.c \ + e_mod_policy.h \ + e_mod_policy.c \ + e_mod_config.h \ + e_mod_config.c \ + e_mod_main.h \ + e_mod_main.c + +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 + +.PHONY: doc + +# Documentation + +doc: + @echo "entering doc/" + make -C doc doc + +clean-local: + rm -f *.edj + +uninstall: + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE) + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)/policies + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)/keyboards diff --git a/src/modules/illume2/doc/Doxyfile b/src/modules/illume2/doc/Doxyfile new file mode 100644 index 000000000..bdd35f508 --- /dev/null +++ b/src/modules/illume2/doc/Doxyfile @@ -0,0 +1,1349 @@ +# Doxyfile 1.5.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Illume + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 2.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = YES + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST = YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c *.h *.x + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = ./img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 2 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = head.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = foot.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = e.css + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 1 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = NO + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = __UNUSED__= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/src/modules/illume2/doc/Makefile.am b/src/modules/illume2/doc/Makefile.am new file mode 100644 index 000000000..83826b4c2 --- /dev/null +++ b/src/modules/illume2/doc/Makefile.am @@ -0,0 +1,22 @@ +MAINTAINERCLEANFILES = Makefile.in + +.PHONY: doc + +if EFL_BUILD_DOC + +doc: all + rm -rf html/ latex/ man/ + $(efl_doxygen) + cp img/* html/ + +else + +doc: + @echo "Documentation not built. Run ./configure --help" + +endif + +clean-local: + @rm -rf html/ latex/ man/ + +EXTRA_DIST = Doxyfile $(wildcard img/*.*) e.css head.html foot.html diff --git a/src/modules/illume2/doc/e.css b/src/modules/illume2/doc/e.css new file mode 100644 index 000000000..2dd6b4479 --- /dev/null +++ b/src/modules/illume2/doc/e.css @@ -0,0 +1,273 @@ +/* + Author: + Andres Blanc + DaveMDS Andreoli + + Supported Browsers: + ie7, opera9, konqueror4 and firefox3 + + Please use a different file for ie6, ie5, etc. hacks. +*/ + + +/* Necessary to place the footer at the bottom of the page */ +html, body { + height: 100%; + margin: 0px; + padding: 0px; +} + +#container { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -53px; +} + +#footer, #push { + height: 53px; +} + + +* html #container { + height: 100%; +} + +/* Prevent floating elements overflowing containers */ +.clear { + clear: both; + width: 0px; + height: 0px; +} + +/* Flexible & centered layout from 750 to 960 pixels */ +.layout { + max-width: 960px; + min-width: 760px; + margin-left: auto; + margin-right: auto; +} + +body { + /*font-family: Lucida Grande, Helvetica, sans-serif;*/ + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif +} + +/* Prevent design overflowing the viewport in small resolutions */ +#container { + padding-right: 17px; + padding-left: 17px; + background-image: url(head_bg.png); + background-repeat: repeat-x; +} + +/****************************/ +/* Top main menu */ +/****************************/ +#header_logo { + background-image : url(logo.png); + width : 61px; +} + +#header_logo a { + position : absolute; + border : 0px; + background-color : transparent; + top : 0px; + width : 60px; + height : 60px; +} + +#header_menu { + background-image : url(header_menu_background.png); + font : normal 10pt verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + text-align : right; +} + +#header_last { + background-image : url(header_menu_background_last.png); + width : 15px; +} + +td.nav_passive { + background : url(header_menu_unselected_background.png) 0 0 no-repeat; + height : 63px; + font-family : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + font-size : 11px; + padding : 20px 10px 20px 10px; + vertical-align : middle; +} + +td.nav_active { + background : url(header_menu_current_background.png) 0 0 no-repeat; + height : 63px; + color : #646464; + font-family : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + font-size : 11px; + font-weight : bold; + padding : 20px 10px 20px 10px; + vertical-align : middle; +} + +#header_menu a { + display : block; + text-decoration : none; + cursor : pointer; + color : #cdcdcd; +} + + + +#header { + width: 100%; + height: 102px; +} + +#header h1 { + width: 63px; + height: 63px; + position: absolute; + margin: 0px; +} + +#header h1 span { + display: none; +} + +#header h2 { + display: none; +} + +/* .menu-container is used to set properties common to .menu and .submenu */ +#header .menu-container { +} + +#header .menu-container ul { + list-style-type: none; + list-style-position: inside; + margin: 0; +} + +#header .menu-container li { + display: block; + float: right; +} + +#header .menu { + height: 63px; + display: block; + background-image: url(menu_bg.png); + background-repeat: repeat-x; +} + +#header .menu ul { + height: 100%; + display: block; + background-image: url(menu_bg_last.png); + background-repeat: no-repeat; + background-position: top right; + padding-right: 17px; +} + +#header .menu li { + height: 100%; + text-align: center; + background-image: url(menu_bg_unsel.png); + background-repeat: no-repeat; +} + +#header .menu a { + height: 100%; + display: block; + color: #cdcdcd; + text-decoration: none; + font-size: 10pt; + line-height: 59px; + text-align: center; + padding: 0px 15px 0px 15px; +} + +#header .menu li:hover { + background-image: url(menu_bg_hover.png); + background-repeat: no-repeat; +} + +#header .menu li:hover a { + color: #FFFFFF; +} + +#header .menu li.current { + background-image: url(menu_bg_current.png); + background-repeat: no-repeat; +} + +#header .menu li.current a { + color: #646464; +} + + +/* Hide all the submenus but the current */ +#header .submenu ul { + display: none; +} + +#header .submenu .current { + display: block; +} + +#header .submenu { + font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + margin-top: 10px; +} + +#header .submenu a { + color: #888888; + text-decoration: none; + font-size: 0.9em; + line-height: 15px; + padding:0px 5px 0px 5px; +} + +#header .submenu a:hover { + color: #444444; +} + +#header .submenu li { + border-left: 1px solid #DDDDDD; +} + +#header .submenu li:last-child { + border-left: 0; +} + +#header .doxytitle { + position: absolute; + font-size: 1.8em; + font-weight: bold; + color: #444444; + line-height: 35px; +} + +#header small { + font-size: 0.4em; +} + +#footer { + background-image: url(foot_bg.png); + width: 100%; +} + +#footer table { + width: 100%; + text-align: center; + white-space: nowrap; + padding: 5px 30px 5px 30px; + font-size: 0.8em; + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + color: #888888; +} + +#footer td.copyright { + width: 100%; +} + diff --git a/src/modules/illume2/doc/foot.html b/src/modules/illume2/doc/foot.html new file mode 100644 index 000000000..d43cf8fcc --- /dev/null +++ b/src/modules/illume2/doc/foot.html @@ -0,0 +1,18 @@ + +
+ + + + + + + + + + + diff --git a/src/modules/illume2/doc/head.html b/src/modules/illume2/doc/head.html new file mode 100644 index 000000000..2c617959f --- /dev/null +++ b/src/modules/illume2/doc/head.html @@ -0,0 +1,69 @@ + + + $title + + + + + + + + + + + + + + +
+ + + +
+
diff --git a/src/modules/illume2/doc/img/e.png b/src/modules/illume2/doc/img/e.png new file mode 100644 index 000000000..d42aeb420 Binary files /dev/null and b/src/modules/illume2/doc/img/e.png differ diff --git a/src/modules/illume2/doc/img/edoxy.css b/src/modules/illume2/doc/img/edoxy.css new file mode 100644 index 000000000..311ca23d4 --- /dev/null +++ b/src/modules/illume2/doc/img/edoxy.css @@ -0,0 +1,486 @@ +/* + * This file contain a custom doxygen style to match e.org graphics + */ + + + +/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +}*/ +BODY, TD { + font-size: 12px; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover, A:visited:hover { + text-decoration: none; + /* background-color: #f2f2ff; */ + color: #000055; +} +A.anchor { + color: #000; +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +/*BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +}*/ +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +SPAN.vhdldigit { color: #ff00ff } +SPAN.vhdlchar { color: #000000 } +SPAN.vhdlkeyword { color: #700070 } +SPAN.vhdllogic { color: #ff0000 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { + color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { + font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #eeeeee; + border: 1px solid #dddddd; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eeeeee; + border-width: 1px; + border-style: solid; + border-color: #dddddd; + -moz-border-radius: 4px 4px 4px 4px; +} +.memname { + white-space: nowrap; + font-weight: bold; + color: #ffffff; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #111111; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #000000; + font-weight: bold; + -moz-border-radius: 4px 4px 4px 4px; +} +.paramkey { + text-align: right; + color: #ffffff; +} +.paramtype { + white-space: nowrap; + color: #aaaaaa; +} +.paramname { + color: #ff0000; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +/* these are for tree view when used as main index */ +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* The following two styles can be used to replace the root node title */ +/* with an image of your choice. Simply uncomment the next two styles, */ +/* specify the name of your image and be sure to set 'height' to the */ +/* proper pixel height of your image. */ + +/* .directory h3.swap { */ +/* height: 61px; */ +/* background-repeat: no-repeat; */ +/* background-image: url("yourimage.gif"); */ +/* } */ +/* .directory h3.swap span { */ +/* display: none; */ +/* } */ + +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} +/* these are for tree view when not used as main index */ +.directory-alt { + font-size: 100%; + font-weight: bold; +} +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory-alt > h3 { + margin-top: 0; +} +.directory-alt p { + margin: 0px; + white-space: nowrap; +} +.directory-alt div { + display: none; + margin: 0px; +} +.directory-alt img { + vertical-align: -30%; +} + diff --git a/src/modules/illume2/doc/img/foot_bg.png b/src/modules/illume2/doc/img/foot_bg.png new file mode 100644 index 000000000..b24f3a48b Binary files /dev/null and b/src/modules/illume2/doc/img/foot_bg.png differ diff --git a/src/modules/illume2/doc/img/head_bg.png b/src/modules/illume2/doc/img/head_bg.png new file mode 100644 index 000000000..081dc131e Binary files /dev/null and b/src/modules/illume2/doc/img/head_bg.png differ diff --git a/src/modules/illume2/doc/img/header_menu_background.png b/src/modules/illume2/doc/img/header_menu_background.png new file mode 100644 index 000000000..e97874365 Binary files /dev/null and b/src/modules/illume2/doc/img/header_menu_background.png differ diff --git a/src/modules/illume2/doc/img/header_menu_background_last.png b/src/modules/illume2/doc/img/header_menu_background_last.png new file mode 100644 index 000000000..88c116c8c Binary files /dev/null and b/src/modules/illume2/doc/img/header_menu_background_last.png differ diff --git a/src/modules/illume2/doc/img/header_menu_current_background.png b/src/modules/illume2/doc/img/header_menu_current_background.png new file mode 100644 index 000000000..de97c9268 Binary files /dev/null and b/src/modules/illume2/doc/img/header_menu_current_background.png differ diff --git a/src/modules/illume2/doc/img/header_menu_unselected_background.png b/src/modules/illume2/doc/img/header_menu_unselected_background.png new file mode 100644 index 000000000..50e5fd8d3 Binary files /dev/null and b/src/modules/illume2/doc/img/header_menu_unselected_background.png differ diff --git a/src/modules/illume2/doc/img/logo.png b/src/modules/illume2/doc/img/logo.png new file mode 100644 index 000000000..b3884a5cb Binary files /dev/null and b/src/modules/illume2/doc/img/logo.png differ diff --git a/src/modules/illume2/e-module-illume2.edc b/src/modules/illume2/e-module-illume2.edc new file mode 100644 index 000000000..8b408f9f4 --- /dev/null +++ b/src/modules/illume2/e-module-illume2.edc @@ -0,0 +1,25 @@ +collections +{ + group + { + images.image: "module_icon.png" COMP; + name: "icon"; + max: 128 128; + parts + { + part + { + name: "icon"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + image.normal: "module_icon.png"; + } + } + } + } +} diff --git a/src/modules/illume2/e_illume.c b/src/modules/illume2/e_illume.c new file mode 100644 index 000000000..5310e8eb3 --- /dev/null +++ b/src/modules/illume2/e_illume.c @@ -0,0 +1,931 @@ +#include "e_illume_private.h" +#include "e_mod_config.h" + +/** + * @defgroup E_Illume_Main_Group Illume API Information + * + * The following group defines variables, structures, and functions available + * to a policy. + */ + +/** + * Returns the @ref E_Illume_Config_Zone structure for a specific zone. + * + * @param id The id of the E_Zone. + * @return The @ref E_Illume_Config_Zone structure for this zone. + * + * @note This function will return a new @ref E_Illume_Config_Zone structure + * if none exists. This new @ref E_Illume_Config_Zone will be added to the + * existing list of @ref E_Illume_Config_Zone structures automatically. + * + * @ingroup E_Illume_Config_Group + */ +E_Illume_Config_Zone * +e_illume_zone_config_get(int id) +{ + Eina_List *l; + E_Illume_Config_Zone *cz = NULL; + + /* loop existing zone configs and look for this id */ + EINA_LIST_FOREACH(_e_illume_cfg->policy.zones, l, cz) + { + if (cz->id != id) continue; + return cz; + } + + /* we did not find an existing one for this zone, so create a new one */ + cz = E_NEW(E_Illume_Config_Zone, 1); + cz->id = id; + cz->mode.dual = 0; + cz->mode.side = 0; + + /* add it to the list */ + _e_illume_cfg->policy.zones = + eina_list_append(_e_illume_cfg->policy.zones, cz); + + /* save it in config */ + e_mod_config_save(); + + /* return a fallback */ + return cz; +} + +/** + * Determine if a given border is an Indicator window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is an Indicator window, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @note It is assumed that Indicator windows are of type + * ECORE_X_WINDOW_TYPE_DOCK. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_indicator(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* indicator windows should be set to dock type, so check for that */ + if (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) return EINA_FALSE; + + /* we have a dock window, check against any matches in config */ + + /* check if we are matching on name */ + if (_e_illume_cfg->policy.indicator.match.name) + { + if ((bd->client.icccm.name) && + (!strcmp(bd->client.icccm.name, + _e_illume_cfg->policy.indicator.name))) + return EINA_TRUE; + } + + /* check if we are matching on class */ + if (_e_illume_cfg->policy.indicator.match.class) + { + if ((bd->client.icccm.class) && + (!strcmp(bd->client.icccm.class, + _e_illume_cfg->policy.indicator.class))) + return EINA_TRUE; + } + + /* check if we are matching on title */ + if (_e_illume_cfg->policy.indicator.match.title) + { + const char *title; + + title = e_border_name_get(bd); + if (!strcmp(title, _e_illume_cfg->policy.indicator.title)) + return EINA_TRUE; + } + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a Softkey window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a Softkey window, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @note It is assumed that Softkey windows are of type + * ECORE_X_WINDOW_TYPE_DOCK. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_softkey(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* legacy code from illume 1 */ + if (bd->client.qtopia.soft_menu) return EINA_TRUE; + + /* softkey windows should be set to dock type, so check for that */ + if (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) return EINA_FALSE; + + /* we have a softkey window, check against any matches in config */ + + /* check if we are matching on name */ + if (_e_illume_cfg->policy.softkey.match.name) + { + if ((bd->client.icccm.name) && + (!strcmp(bd->client.icccm.name, + _e_illume_cfg->policy.softkey.name))) + return EINA_TRUE; + } + + /* check if we are matching on class */ + if (_e_illume_cfg->policy.softkey.match.class) + { + if ((bd->client.icccm.class) && + (!strcmp(bd->client.icccm.class, + _e_illume_cfg->policy.softkey.class))) + return EINA_TRUE; + } + + /* check if we are matching on title */ + if (_e_illume_cfg->policy.softkey.match.title) + { + const char *title; + + title = e_border_name_get(bd); + if (!strcmp(title, _e_illume_cfg->policy.softkey.title)) + return EINA_TRUE; + } + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a Keyboard window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a Keyboard window, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_keyboard(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* check for specific flag first */ + if (bd->client.vkbd.vkbd) return EINA_TRUE; + + /* legacy code from illume 1 */ + if ((bd->client.icccm.name) && + ((!strcmp(bd->client.icccm.name, "multitap-pad"))) && + (bd->client.netwm.state.skip_taskbar) && + (bd->client.netwm.state.skip_pager)) + return EINA_TRUE; + + /* check if we are matching on name */ + if (_e_illume_cfg->policy.vkbd.match.name) + { + if ((bd->client.icccm.name) && + (!strcmp(bd->client.icccm.name, + _e_illume_cfg->policy.vkbd.name))) + return EINA_TRUE; + } + + /* check if we are matching on class */ + if (_e_illume_cfg->policy.vkbd.match.class) + { + if ((bd->client.icccm.class) && + (!strcmp(bd->client.icccm.class, + _e_illume_cfg->policy.vkbd.class))) + return EINA_TRUE; + } + + /* check if we are matching on title */ + if (_e_illume_cfg->policy.vkbd.match.title) + { + const char *title; + + title = e_border_name_get(bd); + if (!strcmp(title, _e_illume_cfg->policy.vkbd.title)) + return EINA_TRUE; + } + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a Home window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a Home window, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_home(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* check if we are matching on name */ + if (_e_illume_cfg->policy.home.match.name) + { + if ((bd->client.icccm.name) && + (!strcmp(bd->client.icccm.name, + _e_illume_cfg->policy.home.name))) + return EINA_TRUE; + } + + /* check if we are matching on class */ + if (_e_illume_cfg->policy.home.match.class) + { + if ((bd->client.icccm.class) && + (!strcmp(bd->client.icccm.class, + _e_illume_cfg->policy.home.class))) + return EINA_TRUE; + } + + /* check if we are matching on title */ + if (_e_illume_cfg->policy.home.match.title) + { + const char *title; + + title = e_border_name_get(bd); + if (!strcmp(title, _e_illume_cfg->policy.home.title)) + return EINA_TRUE; + } + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a splash screen. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a splash screen, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_splash(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* check actual type */ + if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_SPLASH) return EINA_TRUE; + + /* check for transient flag */ +// if (bd->client.icccm.transient_for != 0) return EINA_TRUE; + + /* NB: may or may not need to handle these. Needs Testing */ + if (bd->client.netwm.extra_types) + printf("\t\tBorder has extra types: %s\n", bd->client.icccm.class); + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a dialog. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a dialog, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_dialog(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* check actual type */ + if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) return EINA_TRUE; + + /* check for transient flag */ + if (bd->client.icccm.transient_for != 0) return EINA_TRUE; + + /* check for client leader */ + /* NB: disabled currently as some GTK windows set this even tho they are + * not a dialog. */ +// if (bd->client.icccm.client_leader) return EINA_TRUE; + + /* NB: may or may not need to handle these. Needs Testing */ + if (bd->client.netwm.extra_types) + printf("\t\tBorder has extra types: %s\n", bd->client.icccm.class); + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a QT VCLSalFrame. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a VCLSalFrame, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_qt_frame(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* make sure we have the icccm name and compare it */ + if ((bd->client.icccm.name) && + (!strncmp(bd->client.icccm.name, "VCLSalFrame", 11))) + return EINA_TRUE; + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is a fullscreen window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is fullscreen, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_fullscreen(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* check for fullscreen */ + if ((bd->fullscreen) || (bd->need_fullscreen)) return EINA_TRUE; + + /* return a fallback */ + return EINA_FALSE; +} + +/** + * Determine if a given border is an illume conformant window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is conformant, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_conformant(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* return if it is conformant or not */ + return bd->client.illume.conformant.conformant; +} + +/** + * Determine if a given border is a quickpanel window. + * + * @param bd The border to test. + * @return EINA_TRUE if it is a quickpanel, EINA_FALSE otherwise. + * + * @note If @p bd is NULL then this function will return EINA_FALSE. + * + * @ingroup E_Illume_Main_Group + */ +Eina_Bool +e_illume_border_is_quickpanel(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return EINA_FALSE; + + /* return if it is a quickpanel or not */ + return bd->client.illume.quickpanel.quickpanel; +} + +/** + * Retrieves the minimum space required to display this border. + * + * @param bd The border to get the minium space for. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * + * @note if @p bd is NULL then @p w and @p h will return @c 0. + * + * @ingroup E_Illume_Main_Group + */ +void +e_illume_border_min_get(E_Border *bd, int *w, int *h) +{ + if (w) *w = 0; + if (h) *h = 0; + if (!bd) return; + + if (w) + { + if (bd->client.icccm.base_w > bd->client.icccm.min_w) + *w = bd->client.icccm.base_w; + else + *w = bd->client.icccm.min_w; + } + if (h) + { + if (bd->client.icccm.base_h > bd->client.icccm.min_h) + *h = bd->client.icccm.base_h; + else + *h = bd->client.icccm.min_h; + } +} + +/** + * Retrieves a border, given an x and y coordinate, from a zone. + * + * @param zone The zone. + * @param x The X coordinate to check for border at. + * @param y The Y coordinate to check for border at. + * + * @note if @p zone is NULL then this function will return NULL. + * + * @warning Both X and Y coordinates are required to reliably detect a border. + * + * @ingroup E_Illume_Main_Group + */ +E_Border * +e_illume_border_at_xy_get(E_Zone *zone, int x, int y) +{ + Eina_List *l; + E_Border *bd; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the border client list */ + /* NB: We use e_border_client_list here, rather than + * e_container_border_list, because e_border_client_list is faster. + * This is done in reverse order so we get the most recent border first */ + EINA_LIST_REVERSE_FOREACH(e_border_client_list(), l, bd) + { + /* check zone and skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip invisibles */ + if (!bd->visible) continue; + + /* filter out borders we don't want */ + if (e_illume_border_is_indicator(bd)) continue; + if (e_illume_border_is_softkey(bd)) continue; + if (e_illume_border_is_keyboard(bd)) continue; + if (e_illume_border_is_quickpanel(bd)) continue; + if (e_illume_border_is_home(bd)) continue; + + /* check position against given coordinates */ + if ((bd->x != x) || (bd->y != y)) continue; + + /* found one, return it */ + return bd; + } + + /* return a fallback */ + return NULL; +} + +/** + * Retrieve the parent of a given dialog. + * + * @param bd The border to get the parent of. + * @return The border's parent, or NULL if no parent exists. + * + * @note If @p bd is NULL then this function will return NULL. + * + * @ingroup E_Illume_Main_Group + */ +E_Border * +e_illume_border_parent_get(E_Border *bd) +{ + /* make sure we have a border */ + if (!bd) return NULL; + + /* check for border's parent */ + if (bd->parent) return bd->parent; + + /* NB: TEST CODE - may need to check bd->leader here */ + if (bd->leader) + { + printf("\tDialog Has Leader: %s\n", bd->client.icccm.name); + } + + /* check for transient */ + if (bd->client.icccm.transient_for) + { + /* try to find this borders parent */ + return e_border_find_by_client_window(bd->client.icccm.transient_for); + } + else if (bd->client.icccm.client_leader) + { + /* NB: using client_leader as parent. THIS NEEDS THOROUGH TESTING !! */ + return e_border_find_by_client_window(bd->client.icccm.client_leader); + } + + /* return a fallback */ + return NULL; +} + +/** + * Show a given border. + * + * @param bd The border to show. + * + * @note If @p bd is NULL then this function will return. + * + * @ingroup E_Illume_Main_Group + */ +void +e_illume_border_show(E_Border *bd) +{ + unsigned int visible = 1; + + /* make sure we have a border */ + if (!bd) return; + + /* NB: We handle shows this way so we don't get extra layout events from + * the e_border calls */ + e_container_border_lower(bd); + e_container_shape_show(bd->shape); + if (!bd->need_reparent) ecore_x_window_show(bd->client.win); + e_hints_window_visible_set(bd); + bd->visible = 1; + bd->changes.visible = 1; + ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1); + ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1); +} + +/** + * Hide a given border. + * + * @param bd The border to hide. + * + * @note If @p bd is NULL then this function will return. + * + * @ingroup E_Illume_Main_Group + */ +void +e_illume_border_hide(E_Border *bd) +{ + unsigned int visible = 0; + + /* make sure we have a border */ + if (!bd) return; + + /* NB: We handle hides this way so we don't get extra layout events from + * the e_border calls */ + e_container_shape_hide(bd->shape); + if (!bd->iconic) e_hints_window_hidden_set(bd); + bd->visible = 0; + bd->changes.visible = 1; + ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1); +} + +/** + * Retrieve the Indicator window on a given zone. + * + * @param zone The zone. + * @return The Indicator border, or NULL if no Indicator exists. + * + * @note If @p zone is NULL then this function will return NULL. + * + * @ingroup E_Illume_Main_Group + */ +E_Border * +e_illume_border_indicator_get(E_Zone *zone) +{ + Eina_List *l; + E_Border *bd; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the border client list */ + /* NB: We use e_border_client_list here, rather than + * e_container_border_list, because e_border_client_list is faster */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* check zone and skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip borders that are not indicators */ + if (!e_illume_border_is_indicator(bd)) continue; + + /* found one, return it */ + return bd; + } + + /* return a fallback */ + return NULL; +} + +/** + * Retrieves the current position of the Indicator window. + * + * @param zone The zone on which to retrieve the Indicator position. + * @param x Pointer to an integer into which the left is to be stored. + * @param y Pointer to an integer into which the top is to be stored. + * + * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0. + * + * @ingroup E_Illume_Main_Group + */ +void +e_illume_border_indicator_pos_get(E_Zone *zone, int *x, int *y) +{ + E_Border *ind; + + /* make sure we have a zone */ + if (!zone) + { + if (x) *x = 0; + if (y) *y = 0; + return; + } + + /* set default values */ + if (x) *x = zone->x; + if (y) *y = zone->y; + + /* try and get the Indicator on this zone */ + if (!(ind = e_illume_border_indicator_get(zone))) return; + + /* return Indicator position(s) */ + if (x) *x = ind->x; + if (y) *y = ind->y; +} + +/** + * Retrieve the Softkey window on a given zone. + * + * @param zone The zone. + * @return The Softkey border, or NULL if no Softkey exists. + * + * @note If @p zone is NULL then this function will return NULL. + * + * @ingroup E_Illume_Main_Group + */ +E_Border * +e_illume_border_softkey_get(E_Zone *zone) +{ + Eina_List *l; + E_Border *bd; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the border client list */ + /* NB: We use e_border_client_list here, rather than + * e_container_border_list, because e_border_client_list is faster */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* check zone and skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip borders that are not indicators */ + if (!e_illume_border_is_softkey(bd)) continue; + + /* found one, return it */ + return bd; + } + + /* return a fallback */ + return NULL; +} + +/** + * Retrieves the current position of the Softkey window. + * + * @param zone The zone on which to retrieve the Softkey position. + * @param x Pointer to an integer into which the left is to be stored. + * @param y Pointer to an integer into which the top is to be stored. + * + * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0. + * + * @ingroup E_Illume_Main_Group + */ +void +e_illume_border_softkey_pos_get(E_Zone *zone, int *x, int *y) +{ + E_Border *sft; + + /* make sure we have a zone */ + if (!zone) + { + if (x) *x = 0; + if (y) *y = 0; + return; + } + + /* set default values */ + if (x) *x = zone->x; + if (y) *y = zone->y; + + /* try and get the Softkey on this zone */ + if (!(sft = e_illume_border_softkey_get(zone))) return; + + /* return Indicator position(s) */ + if (x) *x = sft->x; + if (y) *y = sft->y; +} + +/** + * Retrieve the Keyboard on a given zone. + * + * @return The @ref E_Illume_Keyboard, or NULL if no keyboard exists. + * + * @ingroup E_Illume_Keyboard_Group + */ +E_Illume_Keyboard * +e_illume_keyboard_get(void) +{ + /* make sure we have a keyboard and a zone */ + if (!_e_illume_kbd) return NULL; + + /* return the keyboard */ + return _e_illume_kbd; +} + +/** + * Retrieves the available screen space not occupied by the virtual keyboard. + * + * @param zone The zone on which to retrieve the available space. + * @param x Pointer to an integer into which the left is to be stored. + * @param y Pointer to an integer into which the top is to be stored. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * + * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0. + * + * @warning This function does not account for space or position of Indicator + * or Softkey windows. + * + * @ingroup E_Illume_Keyboard_Group + */ +void +e_illume_keyboard_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h) +{ + /* make sure we have a zone */ + if (!zone) + { + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 0; + if (h) *h = 0; + return; + } + + /* set default values */ + if (x) *x = zone->x; + if (y) *y = zone->y; + if (w) *w = zone->w; + if (h) *h = zone->h; + + /* if the keyboard is disabled, get out */ + if ((!_e_illume_kbd->visible) || (_e_illume_kbd->disabled)) return; + + /* if we don't have a border, get out */ + /* NB: This basically means that we have the vkbd structure, but no + * app or module present to act as the vkbd */ + if (!_e_illume_kbd->border) return; + + /* if the keyboard border is not on this zone, get out */ + if (_e_illume_kbd->border->zone != zone) return; + + if (!_e_illume_kbd->animator) + { + if (h) + { + *h -= _e_illume_kbd->border->h; + if (*h < 0) *h = 0; + } + } +} + +/** + * Retrieve the Home window on a given zone. + * + * @param zone The zone. + * @return The Home window, or NULL if no Home window exists. + * + * @note If @p zone is NULL then this function will return NULL. + * + * @ingroup E_Illume_Main_Group + */ +E_Border * +e_illume_border_home_get(E_Zone *zone) +{ + E_Border *bd; + Eina_List *l; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the border client list */ + /* NB: We use e_border_client_list here, rather than + * e_container_border_list, because e_border_client_list is faster */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* check zone and skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip borders that are not home windows */ + if (!e_illume_border_is_home(bd)) continue; + + /* found one, return it */ + return bd; + } + + /* return a fallback */ + return NULL; +} + +/** + * Retrieve the list of Home windows on a given zone. + * + * @param zone The zone. + * @return A list of existing Home windows, or NULL if none exist. + * + * @note If @p zone is NULL then this function will return NULL. + * + * @ingroup E_Illume_Main_Group + */ +Eina_List * +e_illume_border_home_borders_get(E_Zone *zone) +{ + Eina_List *ret = NULL, *l; + E_Border *bd; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the border client list */ + /* NB: We use e_border_client_list here, rather than + * e_container_border_list, because e_border_client_list is faster */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* check zone and skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip borders that are not home windows */ + if (!e_illume_border_is_home(bd)) continue; + + /* found one, append it to the list */ + ret = eina_list_append(ret, bd); + } + + /* return the list */ + return ret; +} + +/** + * Retrieve the Illume Quickpanel on a given zone. + * + * @param zone The zone on which to retrieve the Quickpanel. + * @return The Quickpanel on this zone, or NULL if none exists. + * + * @note If @p zone is NULL then this function will return NULL. + * + * @ingroup E_Illume_Quickpanel_Group + */ +E_Illume_Quickpanel * +e_illume_quickpanel_by_zone_get(E_Zone *zone) +{ + E_Illume_Quickpanel *qp; + Eina_List *l; + + /* make sure we have a zone */ + if (!zone) return NULL; + + /* loop the list of quickpanels, looking for one on this zone */ + EINA_LIST_FOREACH(_e_illume_qps, l, qp) + if (qp->zone == zone) return qp; + + /* return a fallback */ + return NULL; +} 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 + * + *
    + *
  • @ref illume_intro_sec + *
+ * + * @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_illume_private.h b/src/modules/illume2/e_illume_private.h new file mode 100644 index 000000000..41a605544 --- /dev/null +++ b/src/modules/illume2/e_illume_private.h @@ -0,0 +1,24 @@ +#ifndef E_ILLUME_PRIVATE_H +# define E_ILLUME_PRIVATE_H + +# include "e_illume.h" + +/* define policy object type */ +# define E_ILLUME_POLICY_TYPE 0xE0b200b + +/* external variable to store list of quickpanels */ +extern Eina_List *_e_illume_qps; + +/* external variable to store keyboard */ +extern E_Illume_Keyboard *_e_illume_kbd; + +/* external variable to store active config */ +extern E_Illume_Config *_e_illume_cfg; + +/* external variable to store module directory */ +extern const char *_e_illume_mod_dir; + +/* external event for policy changes */ +extern int E_ILLUME_POLICY_EVENT_CHANGE; + +#endif diff --git a/src/modules/illume2/e_mod_config.c b/src/modules/illume2/e_mod_config.c new file mode 100644 index 000000000..bb056edfa --- /dev/null +++ b/src/modules/illume2/e_mod_config.c @@ -0,0 +1,262 @@ +#include "e_illume_private.h" +#include "e_mod_config.h" +#include "e_mod_config_animation.h" +#include "e_mod_config_windows.h" +#include "e_mod_config_policy.h" + +/* local function prototypes */ +static void _e_mod_config_free(void); +static void _e_mod_config_new(void); + +/* local variables */ +static E_Config_DD *_conf_edd = NULL; +static E_Config_DD *_conf_zone_edd = NULL; + +/* external variables */ +E_Illume_Config *_e_illume_cfg = NULL; + +int +e_mod_config_init(void) +{ + char buff[PATH_MAX]; + + /* create config structure for zones */ + _conf_zone_edd = E_CONFIG_DD_NEW("Illume_Config_Zone", E_Illume_Config_Zone); +#undef T +#undef D +#define T E_Illume_Config_Zone +#define D _conf_zone_edd + E_CONFIG_VAL(D, T, id, INT); + E_CONFIG_VAL(D, T, mode.dual, INT); + E_CONFIG_VAL(D, T, mode.side, INT); + + /* create config structure for module */ + _conf_edd = E_CONFIG_DD_NEW("Illume_Config", E_Illume_Config); +#undef T +#undef D +#define T E_Illume_Config +#define D _conf_edd + E_CONFIG_VAL(D, T, version, INT); + E_CONFIG_VAL(D, T, animation.vkbd.duration, INT); + E_CONFIG_VAL(D, T, animation.quickpanel.duration, INT); + E_CONFIG_VAL(D, T, policy.name, STR); + E_CONFIG_VAL(D, T, policy.vkbd.class, STR); + E_CONFIG_VAL(D, T, policy.vkbd.name, STR); + E_CONFIG_VAL(D, T, policy.vkbd.title, STR); + E_CONFIG_VAL(D, T, policy.vkbd.type, INT); + E_CONFIG_VAL(D, T, policy.vkbd.match.class, INT); + E_CONFIG_VAL(D, T, policy.vkbd.match.name, INT); + E_CONFIG_VAL(D, T, policy.vkbd.match.title, INT); + E_CONFIG_VAL(D, T, policy.vkbd.match.type, INT); + E_CONFIG_VAL(D, T, policy.indicator.class, STR); + E_CONFIG_VAL(D, T, policy.indicator.name, STR); + E_CONFIG_VAL(D, T, policy.indicator.title, STR); + E_CONFIG_VAL(D, T, policy.indicator.type, INT); + E_CONFIG_VAL(D, T, policy.indicator.match.class, INT); + E_CONFIG_VAL(D, T, policy.indicator.match.name, INT); + E_CONFIG_VAL(D, T, policy.indicator.match.title, INT); + E_CONFIG_VAL(D, T, policy.indicator.match.type, INT); + E_CONFIG_VAL(D, T, policy.softkey.class, STR); + E_CONFIG_VAL(D, T, policy.softkey.name, STR); + E_CONFIG_VAL(D, T, policy.softkey.title, STR); + E_CONFIG_VAL(D, T, policy.softkey.type, INT); + E_CONFIG_VAL(D, T, policy.softkey.match.class, INT); + E_CONFIG_VAL(D, T, policy.softkey.match.name, INT); + E_CONFIG_VAL(D, T, policy.softkey.match.title, INT); + E_CONFIG_VAL(D, T, policy.softkey.match.type, INT); + E_CONFIG_VAL(D, T, policy.home.class, STR); + E_CONFIG_VAL(D, T, policy.home.name, STR); + E_CONFIG_VAL(D, T, policy.home.title, STR); + E_CONFIG_VAL(D, T, policy.home.type, INT); + E_CONFIG_VAL(D, T, policy.home.match.class, INT); + E_CONFIG_VAL(D, T, policy.home.match.name, INT); + E_CONFIG_VAL(D, T, policy.home.match.title, INT); + E_CONFIG_VAL(D, T, policy.home.match.type, INT); + E_CONFIG_LIST(D, T, policy.zones, _conf_zone_edd); + + /* attempt to load existing configuration */ + _e_illume_cfg = e_config_domain_load("module.illume2", _conf_edd); + + /* check version */ + if ((_e_illume_cfg) && ((_e_illume_cfg->version >> 16) < IL_CONFIG_MAJOR)) + _e_mod_config_free(); + + /* create new config if we need to */ + if (!_e_illume_cfg) _e_mod_config_new(); + + /* setup category for config panel */ + snprintf(buff, sizeof(buff), "%s/e-module-illume2.edj", _e_illume_mod_dir); + e_configure_registry_category_add("illume", 0, _("Illume"), buff, "icon"); + + /* add config items to category */ + e_configure_registry_generic_item_add("illume/policy", 0, _("Policy"), + NULL, "enlightenment/policy", + e_mod_config_policy_show); + e_configure_registry_generic_item_add("illume/animation", 0, _("Animation"), + NULL, "enlightenment/animation", + e_mod_config_animation_show); + e_configure_registry_generic_item_add("illume/windows", 0, _("Windows"), + NULL, "enlightenment/windows", + e_mod_config_windows_show); + + return 1; +} + +int +e_mod_config_shutdown(void) +{ + /* destroy config item entries */ + e_configure_registry_item_del("illume/windows"); + e_configure_registry_item_del("illume/animation"); + e_configure_registry_item_del("illume/policy"); + + /* destroy config category */ + e_configure_registry_category_del("illume"); + + /* free config structure */ + _e_mod_config_free(); + + /* free data descriptors */ + E_CONFIG_DD_FREE(_conf_zone_edd); + E_CONFIG_DD_FREE(_conf_edd); + + return 1; +} + +int +e_mod_config_save(void) +{ + return e_config_domain_save("module.illume2", _conf_edd, _e_illume_cfg); +} + +/* local functions */ +static void +_e_mod_config_free(void) +{ + E_Illume_Config_Zone *cz; + + /* check for config */ + if (!_e_illume_cfg) return; + + /* cleanup any stringshares */ + if (_e_illume_cfg->policy.name) + eina_stringshare_del(_e_illume_cfg->policy.name); + _e_illume_cfg->policy.name = NULL; + + if (_e_illume_cfg->policy.vkbd.class) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.class); + _e_illume_cfg->policy.vkbd.class = NULL; + if (_e_illume_cfg->policy.vkbd.name) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.name); + _e_illume_cfg->policy.vkbd.name = NULL; + if (_e_illume_cfg->policy.vkbd.title) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.title); + _e_illume_cfg->policy.vkbd.title = NULL; + + if (_e_illume_cfg->policy.indicator.class) + eina_stringshare_del(_e_illume_cfg->policy.indicator.class); + _e_illume_cfg->policy.indicator.class = NULL; + if (_e_illume_cfg->policy.indicator.name) + eina_stringshare_del(_e_illume_cfg->policy.indicator.name); + _e_illume_cfg->policy.indicator.name = NULL; + if (_e_illume_cfg->policy.indicator.title) + eina_stringshare_del(_e_illume_cfg->policy.indicator.title); + _e_illume_cfg->policy.indicator.title = NULL; + + if (_e_illume_cfg->policy.softkey.class) + eina_stringshare_del(_e_illume_cfg->policy.softkey.class); + _e_illume_cfg->policy.softkey.class = NULL; + if (_e_illume_cfg->policy.softkey.name) + eina_stringshare_del(_e_illume_cfg->policy.softkey.name); + _e_illume_cfg->policy.softkey.name = NULL; + if (_e_illume_cfg->policy.softkey.title) + eina_stringshare_del(_e_illume_cfg->policy.softkey.title); + _e_illume_cfg->policy.softkey.title = NULL; + + if (_e_illume_cfg->policy.home.class) + eina_stringshare_del(_e_illume_cfg->policy.home.class); + _e_illume_cfg->policy.home.class = NULL; + if (_e_illume_cfg->policy.home.name) + eina_stringshare_del(_e_illume_cfg->policy.home.name); + _e_illume_cfg->policy.home.name = NULL; + if (_e_illume_cfg->policy.home.title) + eina_stringshare_del(_e_illume_cfg->policy.home.title); + _e_illume_cfg->policy.home.title = NULL; + + /* free configured zones */ + EINA_LIST_FREE(_e_illume_cfg->policy.zones, cz) + E_FREE(cz); + + /* free config structure */ + E_FREE(_e_illume_cfg); +} + +static void +_e_mod_config_new(void) +{ + E_Illume_Config_Zone *cz; + + /* create initial config */ + _e_illume_cfg = E_NEW(E_Illume_Config, 1); + _e_illume_cfg->version = 0; + _e_illume_cfg->animation.vkbd.duration = 1000; + _e_illume_cfg->animation.quickpanel.duration = 1000; + _e_illume_cfg->policy.name = eina_stringshare_add("illume"); + + _e_illume_cfg->policy.vkbd.class = eina_stringshare_add("Virtual-Keyboard"); + _e_illume_cfg->policy.vkbd.name = eina_stringshare_add("Virtual-Keyboard"); + _e_illume_cfg->policy.vkbd.title = eina_stringshare_add("Virtual Keyboard"); + _e_illume_cfg->policy.vkbd.type = ECORE_X_WINDOW_TYPE_NORMAL; + _e_illume_cfg->policy.vkbd.match.class = 0; + _e_illume_cfg->policy.vkbd.match.name = 1; + _e_illume_cfg->policy.vkbd.match.title = 1; + _e_illume_cfg->policy.vkbd.match.type = 0; + + _e_illume_cfg->policy.indicator.class = + eina_stringshare_add("Illume-Indicator"); + _e_illume_cfg->policy.indicator.name = + eina_stringshare_add("Illume-Indicator"); + _e_illume_cfg->policy.indicator.title = + eina_stringshare_add("Illume Indicator"); + _e_illume_cfg->policy.indicator.type = ECORE_X_WINDOW_TYPE_DOCK; + _e_illume_cfg->policy.indicator.match.class = 0; + _e_illume_cfg->policy.indicator.match.name = 1; + _e_illume_cfg->policy.indicator.match.title = 1; + _e_illume_cfg->policy.indicator.match.type = 0; + + _e_illume_cfg->policy.softkey.class = + eina_stringshare_add("Illume-Softkey"); + _e_illume_cfg->policy.softkey.name = + eina_stringshare_add("Illume-Softkey"); + _e_illume_cfg->policy.softkey.title = + eina_stringshare_add("Illume Softkey"); + _e_illume_cfg->policy.softkey.type = ECORE_X_WINDOW_TYPE_DOCK; + _e_illume_cfg->policy.softkey.match.class = 0; + _e_illume_cfg->policy.softkey.match.name = 1; + _e_illume_cfg->policy.softkey.match.title = 1; + _e_illume_cfg->policy.softkey.match.type = 0; + + _e_illume_cfg->policy.home.class = eina_stringshare_add("Illume-Home"); + _e_illume_cfg->policy.home.name = eina_stringshare_add("Illume-Home"); + _e_illume_cfg->policy.home.title = eina_stringshare_add("Illume Home"); + _e_illume_cfg->policy.home.type = ECORE_X_WINDOW_TYPE_NORMAL; + _e_illume_cfg->policy.home.match.class = 0; + _e_illume_cfg->policy.home.match.name = 1; + _e_illume_cfg->policy.home.match.title = 1; + _e_illume_cfg->policy.home.match.type = 0; + + /* create config for initial zone */ + cz = E_NEW(E_Illume_Config_Zone, 1); + cz->id = 0; + cz->mode.dual = 0; + cz->mode.side = 0; + + /* add zone config to main config structure */ + _e_illume_cfg->policy.zones = + eina_list_append(_e_illume_cfg->policy.zones, cz); + + /* add any new config variables here */ + /* if ((_e_illume_cfg->version & 0xffff) < 1) */ + + _e_illume_cfg->version = ((IL_CONFIG_MAJOR << 16) | IL_CONFIG_MINOR); +} diff --git a/src/modules/illume2/e_mod_config.h b/src/modules/illume2/e_mod_config.h new file mode 100644 index 000000000..9d740a38f --- /dev/null +++ b/src/modules/illume2/e_mod_config.h @@ -0,0 +1,11 @@ +#ifndef E_MOD_CONFIG_H +# define E_MOD_CONFIG_H + +# define IL_CONFIG_MAJOR 0 +# define IL_CONFIG_MINOR 1 + +int e_mod_config_init(void); +int e_mod_config_shutdown(void); +int e_mod_config_save(void); + +#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_config_animation.h b/src/modules/illume2/e_mod_config_animation.h new file mode 100644 index 000000000..84e73bbc7 --- /dev/null +++ b/src/modules/illume2/e_mod_config_animation.h @@ -0,0 +1,6 @@ +#ifndef E_MOD_CONFIG_ANIMATION_H +# define E_MOD_CONFIG_ANIMATION_H + +void e_mod_config_animation_show(E_Container *con, const char *params __UNUSED__); + +#endif diff --git a/src/modules/illume2/e_mod_config_policy.c b/src/modules/illume2/e_mod_config_policy.c new file mode 100644 index 000000000..bdeb61258 --- /dev/null +++ b/src/modules/illume2/e_mod_config_policy.c @@ -0,0 +1,175 @@ +#include "e_illume_private.h" +#include "e_mod_config_policy.h" + +/* local function prototypes */ +static void *_e_mod_config_policy_create(E_Config_Dialog *cfd); +static void _e_mod_config_policy_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_e_mod_config_policy_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static void _e_mod_config_policy_list_changed(void *data); +static int _e_mod_config_policy_change_timeout(void *data); +static Evas_Object *_e_mod_config_policy_settings_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static Eina_List *_e_mod_config_policy_policies_get(void); +static void _e_mod_config_policy_policy_free(E_Illume_Policy *p); + +/* local variables */ +Ecore_Timer *_policy_change_timer = NULL; +const char *_policy_name = NULL; + +void +e_mod_config_policy_show(E_Container *con, const char *params) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + + if (e_config_dialog_find("E", "_config_illume_policy")) return; + + v = E_NEW(E_Config_Dialog_View, 1); + if (!v) return; + + v->create_cfdata = _e_mod_config_policy_create; + v->free_cfdata = _e_mod_config_policy_free; + v->basic.create_widgets = _e_mod_config_policy_ui; + v->basic_only = 1; + v->normal_win = 1; + v->scroll = 1; + cfd = e_config_dialog_new(con, _("Policy"), "E", "_config_illume_policy", + "enlightenment/policy", 0, v, NULL); + if (!cfd) return; + e_dialog_resizable_set(cfd->dia, 1); +} + +/* local functions */ +static void * +_e_mod_config_policy_create(E_Config_Dialog *cfd) +{ + return NULL; +} + +static void +_e_mod_config_policy_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + if (_policy_change_timer) ecore_timer_del(_policy_change_timer); + _policy_change_timer = NULL; +} + +static Evas_Object * +_e_mod_config_policy_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *list, *ow; + Eina_List *policies; + E_Illume_Policy *p; + int i = 0, sel = 0; + + list = e_widget_list_add(evas, 0, 0); + ow = e_widget_ilist_add(evas, 24, 24, &(_policy_name)); + e_widget_ilist_selector_set(ow, 1); + evas_event_freeze(evas); + edje_freeze(); + e_widget_ilist_freeze(ow); + e_widget_ilist_clear(ow); + e_widget_ilist_go(ow); + + policies = _e_mod_config_policy_policies_get(); + if (policies) + { + EINA_LIST_FREE(policies, p) + { + e_widget_ilist_append(ow, NULL, strdup(p->api->label), + _e_mod_config_policy_list_changed, NULL, + strdup(p->api->name)); + + if ((p) && (_e_illume_cfg->policy.name) && + (!strcmp(_e_illume_cfg->policy.name, p->api->name))) + sel = i; + + if (p) e_object_del(E_OBJECT(p)); + i++; + } + } + + e_widget_size_min_set(ow, 100, 200); + e_widget_ilist_go(ow); + e_widget_ilist_selected_set(ow, sel); + e_widget_ilist_thaw(ow); + edje_thaw(); + evas_event_thaw(evas); + e_widget_list_object_append(list, ow, 1, 0, 0.0); + return list; +} + +static void +_e_mod_config_policy_list_changed(void *data) +{ + if (_e_illume_cfg->policy.name) + eina_stringshare_del(_e_illume_cfg->policy.name); + if (_policy_name) + _e_illume_cfg->policy.name = eina_stringshare_add(_policy_name); + if (_policy_change_timer) ecore_timer_del(_policy_change_timer); + _policy_change_timer = + ecore_timer_add(0.5, _e_mod_config_policy_change_timeout, data); +} + +static int +_e_mod_config_policy_change_timeout(void *data) +{ + e_config_save_queue(); + _policy_change_timer = NULL; + ecore_event_add(E_ILLUME_POLICY_EVENT_CHANGE, NULL, NULL, NULL); + return 0; +} + +static Eina_List * +_e_mod_config_policy_policies_get(void) +{ + Eina_List *l = NULL, *files; + char dir[PATH_MAX], *file; + + snprintf(dir, sizeof(dir), "%s/policies", _e_illume_mod_dir); + + if (!(files = ecore_file_ls(dir))) return NULL; + + EINA_LIST_FREE(files, file) + { + E_Illume_Policy *p; + + if (!strstr(file, ".so")) continue; + snprintf(dir, sizeof(dir),"%s/policies/%s", _e_illume_mod_dir, file); + + p = E_OBJECT_ALLOC(E_Illume_Policy, E_ILLUME_POLICY_TYPE, + _e_mod_config_policy_policy_free); + if (!p) continue; + + p->handle = dlopen(dir, RTLD_NOW | RTLD_GLOBAL); + if (!p->handle) + { + e_object_del(E_OBJECT(p)); + continue; + } + p->api = dlsym(p->handle, "e_illume_policy_api"); + if (!p->api) + { + e_object_del(E_OBJECT(p)); + continue; + } + if (p->api->version < E_ILLUME_POLICY_API_VERSION) + { + e_object_del(E_OBJECT(p)); + continue; + } + if (file) free(file); + l = eina_list_append(l, p); + } + + return l; +} + +static void +_e_mod_config_policy_policy_free(E_Illume_Policy *p) +{ + p->api = NULL; + + if (p->handle) dlclose(p->handle); + p->handle = NULL; + + E_FREE(p); +} diff --git a/src/modules/illume2/e_mod_config_policy.h b/src/modules/illume2/e_mod_config_policy.h new file mode 100644 index 000000000..161768618 --- /dev/null +++ b/src/modules/illume2/e_mod_config_policy.h @@ -0,0 +1,6 @@ +#ifndef E_MOD_CONFIG_POLICY_H +# define E_MOD_CONFIG_POLICY_H + +void e_mod_config_policy_show(E_Container *con, const char *params __UNUSED__); + +#endif diff --git a/src/modules/illume2/e_mod_config_windows.c b/src/modules/illume2/e_mod_config_windows.c new file mode 100644 index 000000000..856e05375 --- /dev/null +++ b/src/modules/illume2/e_mod_config_windows.c @@ -0,0 +1,221 @@ +#include "e_illume_private.h" +#include "e_mod_config_windows.h" +#include "e_mod_select_window.h" + +/* local function prototypes */ +static void *_e_mod_config_windows_create(E_Config_Dialog *cfd); +static void _e_mod_config_windows_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_e_mod_config_windows_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static void _e_mod_config_windows_check_changed(void *data, Evas_Object *obj, void *event); +static void _e_mod_config_windows_change(void *data, Evas_Object *obj, void *event); +static int _e_mod_config_windows_change_timeout(void *data); +static void _e_mod_config_windows_select_home(void *data, void *data2); +static void _e_mod_config_windows_select_vkbd(void *data, void *data2); +static void _e_mod_config_windows_select_softkey(void *data, void *data2); +static void _e_mod_config_windows_select_indicator(void *data, void *data2); + +/* local variables */ +Ecore_Timer *_windows_change_timer = NULL; + +/* public functions */ +void +e_mod_config_windows_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_windows_settings")) return; + + v = E_NEW(E_Config_Dialog_View, 1); + if (!v) return; + + v->create_cfdata = _e_mod_config_windows_create; + v->free_cfdata = _e_mod_config_windows_free; + v->basic.create_widgets = _e_mod_config_windows_ui; + v->basic_only = 1; + v->normal_win = 1; + v->scroll = 1; + cfd = e_config_dialog_new(con, _("Window Settings"), "E", + "_config_illume_windows_settings", + "preferences-system-windows", 0, v, NULL); + if (!cfd) return; + e_dialog_resizable_set(cfd->dia, 1); +} + +/* local function prototypes */ +static void * +_e_mod_config_windows_create(E_Config_Dialog *cfd) +{ + return NULL; +} + +static void +_e_mod_config_windows_free(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + if (_windows_change_timer) ecore_timer_del(_windows_change_timer); + _windows_change_timer = NULL; +} + +static Evas_Object * +_e_mod_config_windows_ui(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *list, *of, *ow; + + list = e_widget_list_add(evas, 0, 0); + + of = e_widget_framelist_add(evas, _("Home"), 0); + ow = e_widget_button_add(evas, _("Select Window"), NULL, + _e_mod_config_windows_select_home, NULL, NULL); + e_widget_framelist_object_append(of, ow); + ow = e_widget_check_add(evas, _("Match Window Class"), + &_e_illume_cfg->policy.home.match.class); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Name"), + &_e_illume_cfg->policy.home.match.name); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Title"), + &_e_illume_cfg->policy.home.match.title); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Type"), + &_e_illume_cfg->policy.home.match.type); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + of = e_widget_framelist_add(evas, _("Indicator"), 0); + ow = e_widget_button_add(evas, _("Select Window"), NULL, + _e_mod_config_windows_select_indicator, NULL, NULL); + e_widget_framelist_object_append(of, ow); + ow = e_widget_check_add(evas, _("Match Window Class"), + &_e_illume_cfg->policy.indicator.match.class); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Name"), + &_e_illume_cfg->policy.indicator.match.name); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Title"), + &_e_illume_cfg->policy.indicator.match.title); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Type"), + &_e_illume_cfg->policy.indicator.match.type); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + of = e_widget_framelist_add(evas, _("Keyboard"), 0); + ow = e_widget_button_add(evas, _("Select Window"), NULL, + _e_mod_config_windows_select_vkbd, NULL, NULL); + e_widget_framelist_object_append(of, ow); + ow = e_widget_check_add(evas, _("Match Window Class"), + &_e_illume_cfg->policy.vkbd.match.class); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Name"), + &_e_illume_cfg->policy.vkbd.match.name); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Title"), + &_e_illume_cfg->policy.vkbd.match.title); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Type"), + &_e_illume_cfg->policy.vkbd.match.type); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + of = e_widget_framelist_add(evas, _("Softkey"), 0); + ow = e_widget_button_add(evas, _("Select Window"), NULL, + _e_mod_config_windows_select_softkey, NULL, NULL); + e_widget_framelist_object_append(of, ow); + ow = e_widget_check_add(evas, _("Match Window Class"), + &_e_illume_cfg->policy.softkey.match.class); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Name"), + &_e_illume_cfg->policy.softkey.match.name); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Title"), + &_e_illume_cfg->policy.softkey.match.title); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + ow = e_widget_check_add(evas, _("Match Window Type"), + &_e_illume_cfg->policy.softkey.match.type); + e_widget_framelist_object_append(of, ow); + evas_object_smart_callback_add(ow, "changed", + _e_mod_config_windows_check_changed, NULL); + e_widget_list_object_append(list, of, 1, 0, 0.0); + + return list; +} + +static void +_e_mod_config_windows_check_changed(void *data, Evas_Object *obj, void *event) +{ + _e_mod_config_windows_change(data, obj, event); +} + +static void +_e_mod_config_windows_change(void *data, Evas_Object *obj, void *event) +{ + if (_windows_change_timer) ecore_timer_del(_windows_change_timer); + _windows_change_timer = + ecore_timer_add(0.5, _e_mod_config_windows_change_timeout, data); +} + +static int +_e_mod_config_windows_change_timeout(void *data) +{ + e_config_save_queue(); + _windows_change_timer = NULL; + return 0; +} + +static void +_e_mod_config_windows_select_home(void *data, void *data2) +{ + if (e_config_dialog_find("E", "_config_illume_select_window")) return; + e_mod_config_select_window(E_ILLUME_SELECT_WINDOW_TYPE_HOME); +} + +static void +_e_mod_config_windows_select_vkbd(void *data, void *data2) +{ + if (e_config_dialog_find("E", "_config_illume_select_window")) return; + e_mod_config_select_window(E_ILLUME_SELECT_WINDOW_TYPE_VKBD); +} + +static void +_e_mod_config_windows_select_softkey(void *data, void *data2) +{ + if (e_config_dialog_find("E", "_config_illume_select_window")) return; + e_mod_config_select_window(E_ILLUME_SELECT_WINDOW_TYPE_SOFTKEY); +} + +static void +_e_mod_config_windows_select_indicator(void *data, void *data2) +{ + if (e_config_dialog_find("E", "_config_illume_select_window")) return; + e_mod_config_select_window(E_ILLUME_SELECT_WINDOW_TYPE_INDICATOR); +} diff --git a/src/modules/illume2/e_mod_config_windows.h b/src/modules/illume2/e_mod_config_windows.h new file mode 100644 index 000000000..abfd01f88 --- /dev/null +++ b/src/modules/illume2/e_mod_config_windows.h @@ -0,0 +1,6 @@ +#ifndef E_MOD_CONFIG_WINDOWS_H +# define E_MOD_CONFIG_WINDOWS_H + +void e_mod_config_windows_show(E_Container *con, const char *params __UNUSED__); + +#endif diff --git a/src/modules/illume2/e_mod_kbd.c b/src/modules/illume2/e_mod_kbd.c new file mode 100644 index 000000000..1865897f3 --- /dev/null +++ b/src/modules/illume2/e_mod_kbd.c @@ -0,0 +1,564 @@ +#include "e_illume_private.h" +#include "e_mod_kbd.h" +#include "e_mod_kbd_dbus.h" + +/* local function prototypes */ +static int _e_mod_kbd_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_kbd_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_kbd_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_kbd_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_kbd_cb_border_property(void *data __UNUSED__, int type __UNUSED__, void *event); +static void _e_mod_kbd_cb_border_pre_post_fetch(void *data __UNUSED__, void *data2); +static void _e_mod_kbd_cb_free(E_Illume_Keyboard *kbd); +static int _e_mod_kbd_cb_delay_hide(void *data __UNUSED__); +static void _e_mod_kbd_hide(void); +static void _e_mod_kbd_slide(int visible, double len); +static int _e_mod_kbd_cb_animate(void *data __UNUSED__); +static E_Illume_Keyboard *_e_mod_kbd_by_border_get(E_Border *bd); +static void _e_mod_kbd_border_adopt(E_Border *bd); + +/* local variables */ +static Eina_List *_kbd_hdls = NULL; +static E_Border_Hook *_kbd_hook = NULL; +static Ecore_X_Atom _focused_state = 0; +static E_Border *_focused_border = NULL; + +int +e_mod_kbd_init(void) +{ + /* add handlers for events we are interested in */ + _kbd_hdls = + eina_list_append(_kbd_hdls, + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _e_mod_kbd_cb_client_message, + NULL)); + _kbd_hdls = + eina_list_append(_kbd_hdls, + ecore_event_handler_add(E_EVENT_BORDER_REMOVE, + _e_mod_kbd_cb_border_remove, + NULL)); + _kbd_hdls = + eina_list_append(_kbd_hdls, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, + _e_mod_kbd_cb_border_focus_in, + NULL)); + _kbd_hdls = + eina_list_append(_kbd_hdls, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, + _e_mod_kbd_cb_border_focus_out, + NULL)); + _kbd_hdls = + eina_list_append(_kbd_hdls, + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, + _e_mod_kbd_cb_border_property, + NULL)); + + /* add hooks for events we are interested in */ + _kbd_hook = e_border_hook_add(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, + _e_mod_kbd_cb_border_pre_post_fetch, NULL); + + /* initialize the dbus subsystem */ + e_mod_kbd_dbus_init(); + + return 1; +} + +int +e_mod_kbd_shutdown(void) +{ + Ecore_Event_Handler *hdl; + + /* shutdown the dbus subsystem */ + e_mod_kbd_dbus_shutdown(); + + /* destroy the hook */ + e_border_hook_del(_kbd_hook); + + /* destroy the handlers and free the list */ + EINA_LIST_FREE(_kbd_hdls, hdl) + ecore_event_handler_del(hdl); + + return 1; +} + +E_Illume_Keyboard * +e_mod_kbd_new(void) +{ + E_Illume_Keyboard *kbd; + + /* try to allocate our new keyboard object */ + kbd = E_OBJECT_ALLOC(E_Illume_Keyboard, E_ILLUME_KBD_TYPE, _e_mod_kbd_cb_free); + if (!kbd) return NULL; + + /* set default layout on new keyboard */ + kbd->layout = E_ILLUME_KEYBOARD_LAYOUT_ALPHA; + kbd->visible = 1; + + return kbd; +} + +void +e_mod_kbd_enable(void) +{ + /* don't try to enable a keyboard that is already enabled */ + if (!_e_illume_kbd->disabled) return; + + /* set keyboard to enabled */ + _e_illume_kbd->disabled = 0; + + /* show it if we need to */ + if (!_e_illume_kbd->visible) e_mod_kbd_show(); +} + +void +e_mod_kbd_disable(void) +{ + /* don't try to disable a keyboard that is already disabled */ + if (_e_illume_kbd->disabled) return; + + /* hide it if we need to */ + if (_e_illume_kbd->visible) e_mod_kbd_hide(); + + /* set keyboard to disabled */ + _e_illume_kbd->disabled = 1; +} + +void +e_mod_kbd_show(void) +{ + /* destroy existing timer */ + if (_e_illume_kbd->timer) ecore_timer_del(_e_illume_kbd->timer); + _e_illume_kbd->timer = NULL; + + /* destroy the animator if it exists */ + if (_e_illume_kbd->animator) ecore_animator_del(_e_illume_kbd->animator); + _e_illume_kbd->animator = NULL; + + if (_focused_border) + { +// printf("Focused Border: %s\n", _focused_border->client.icccm.name); + if (_e_illume_kbd->border->zone != _focused_border->zone) + { + e_border_zone_set(_e_illume_kbd->border, _focused_border->zone); + } + } + + /* if it's disabled, get out */ + if (_e_illume_kbd->disabled) return; + + /* TODO: Layout send */ + + /* if we are not animating, just show it */ + if (_e_illume_cfg->animation.vkbd.duration <= 0) + { + /* show the border */ + if (_e_illume_kbd->border) + { + e_border_fx_offset(_e_illume_kbd->border, 0, 0); + if (!_e_illume_kbd->border->visible) + e_border_show(_e_illume_kbd->border); + e_border_raise(_e_illume_kbd->border); + } + _e_illume_kbd->visible = 1; + } + else + { + /* show the border */ + if (_e_illume_kbd->border) + { + if (!_e_illume_kbd->border->visible) + e_border_show(_e_illume_kbd->border); + e_border_raise(_e_illume_kbd->border); + } + + /* animate it */ + _e_mod_kbd_slide(1, (double)_e_illume_cfg->animation.vkbd.duration / 1000.0); + } +} + +void +e_mod_kbd_hide(void) +{ + /* cannot hide keyboard that is not visible */ + if (!_e_illume_kbd->visible) return; + + /* create new hide timer if it doesn't exist */ + if (!_e_illume_kbd->timer) + { + _e_illume_kbd->timer = + ecore_timer_add(0.2, _e_mod_kbd_cb_delay_hide, NULL); + } +} + +void +e_mod_kbd_toggle(void) +{ + if (_e_illume_kbd->visible) e_mod_kbd_hide(); + else e_mod_kbd_show(); +} + +void +e_mod_kbd_fullscreen_set(E_Zone *zone, int fullscreen) +{ + if (!_e_illume_kbd->border) return; + if (_e_illume_kbd->border->zone != zone) return; + printf("Kbd Fullscreen Set: %d\n", fullscreen); + printf("\tCurrent: %d\n", _e_illume_kbd->fullscreen); + if ((!!fullscreen) != _e_illume_kbd->fullscreen) + _e_illume_kbd->fullscreen = fullscreen; +} + +void +e_mod_kbd_layout_set(E_Illume_Keyboard *kbd, E_Illume_Keyboard_Layout layout) +{ + +} + +/* local functions */ +static int +_e_mod_kbd_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_X_Event_Client_Message *ev; + + ev = event; + if (ev->win != ecore_x_window_root_first_get()) return 1; + + /* legacy illume 1 code */ + if ((ev->message_type == ecore_x_atom_get("_MB_IM_INVOKER_COMMAND")) || + (ev->message_type == ecore_x_atom_get("_MTP_IM_INVOKER_COMMAND"))) + { + if (ev->data.l[0] == 1) e_mod_kbd_show(); + else if (ev->data.l[0] == 2) e_mod_kbd_hide(); + else if (ev->data.l[0] == 3) e_mod_kbd_toggle(); + } + return 1; +} + +static int +_e_mod_kbd_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Remove *ev; + E_Illume_Keyboard *kbd; + + ev = event; + + /* if we removed the focused border, reset some variables */ + if ((_focused_border) && (_focused_border == ev->border)) + { + e_mod_kbd_hide(); + _focused_border = NULL; + _focused_state = 0; + return 1; + } + + /* try to find the keyboard for this border */ + if (!(kbd = _e_mod_kbd_by_border_get(ev->border))) return 1; + + if ((kbd->border) && (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_mod_kbd_border_adopt(bd); + } + if (kbd->visible) + { + e_border_hide(ev->border, 2); + e_mod_kbd_hide(); + } + } + else if (!kbd->border) + { + kbd->waiting_borders = + eina_list_remove(kbd->waiting_borders, ev->border); + } + + return 1; +} + +static int +_e_mod_kbd_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Focus_In *ev; + + ev = event; + if (_e_mod_kbd_by_border_get(ev->border)) return 1; + +// printf("Kbd Focus in: %s\n", ev->border->client.icccm.name); + + /* set focused border for kbd */ + _focused_border = ev->border; + _focused_state = ev->border->client.vkbd.state; + + if (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) + e_mod_kbd_hide(); + else + e_mod_kbd_show(); + + return 1; +} + +static int +_e_mod_kbd_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Focus_Out *ev; + + ev = event; + if (_e_mod_kbd_by_border_get(ev->border)) return 1; + +// printf("Kbd Focus Out: %s\n", ev->border->client.icccm.name); + + /* tell this border it changed so layout gets updated for hidden + * keyboard */ + if (!e_illume_border_is_conformant(ev->border)) + { + ev->border->changes.size = 1; + ev->border->changed = 1; + } + + /* hide the keyboard */ + e_mod_kbd_hide(); + + /* reset some variables */ + _focused_border = NULL; + _focused_state = 0; + + return 1; +} + +static int +_e_mod_kbd_cb_border_property(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_X_Event_Window_Property *ev; + E_Border *bd; + int fullscreen = 0; + + ev = event; + + /* only interested in vkbd state changes here */ + if (ev->atom != ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) return 1; + + /* make sure we have a border */ + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + +// printf("Kbd Border Property Change: %s\n", bd->client.icccm.name); + + /* if it's not focused, we don't care */ + if ((!bd->focused) || (_e_mod_kbd_by_border_get(bd))) return 1; + + /* NB: Not sure why, but we seem to need to fetch kbd state here. This could + * be a result of filtering the container_hook_layout. Not real happy + * with this because it is an X round-trip, but it is here because this + * needs more time to investigate. */ + e_hints_window_virtual_keyboard_state_get(bd); + + if ((_focused_border) && (_focused_border == bd)) + { + /* if focused state is the same, get out */ + if (_focused_state == bd->client.vkbd.state) return 1; + } + + /* set our variables */ + _focused_border = bd; + _focused_state = bd->client.vkbd.state; + + /* handle a border needing fullscreen keyboard */ + if ((bd->need_fullscreen) || (bd->fullscreen)) fullscreen = 1; + if (_e_illume_kbd->fullscreen != fullscreen) + e_mod_kbd_fullscreen_set(bd->zone, fullscreen); + + if (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) + e_mod_kbd_hide(); + else + { + // Layout set + e_mod_kbd_show(); + } + + return 1; +} + +static void +_e_mod_kbd_cb_border_pre_post_fetch(void *data __UNUSED__, void *data2) +{ + E_Border *bd; + + if (!(bd = data2)) return; + if (!bd->new_client) return; + if (_e_mod_kbd_by_border_get(bd)) return; + if (e_illume_border_is_keyboard(bd)) + { + if (!_e_illume_kbd->border) + _e_mod_kbd_border_adopt(bd); + else + { + _e_illume_kbd->waiting_borders = + eina_list_append(_e_illume_kbd->waiting_borders, bd); + } + bd->stolen = 1; + } +} + +static void +_e_mod_kbd_cb_free(E_Illume_Keyboard *kbd) +{ + E_Border *bd; + + /* destroy the animator if it exists */ + if (kbd->animator) ecore_animator_del(kbd->animator); + kbd->animator = NULL; + + /* destroy the timer if it exists */ + if (kbd->timer) ecore_timer_del(kbd->timer); + kbd->timer = NULL; + + /* free the list of waiting borders */ + EINA_LIST_FREE(kbd->waiting_borders, bd) + bd->stolen = 0; + + /* free the keyboard structure */ + E_FREE(kbd); +} + +static int +_e_mod_kbd_cb_delay_hide(void *data __UNUSED__) +{ + _e_mod_kbd_hide(); + _e_illume_kbd->timer = NULL; + return 0; +} + +static void +_e_mod_kbd_hide(void) +{ + /* destroy existing timer */ + if (_e_illume_kbd->timer) ecore_timer_del(_e_illume_kbd->timer); + _e_illume_kbd->timer = NULL; + + /* can't hide keyboard if it's not visible, or disabled */ + if ((!_e_illume_kbd->visible) || (_e_illume_kbd->disabled)) return; + + /* if we are not animating, just hide it */ + if (_e_illume_cfg->animation.vkbd.duration <= 0) + { + if (_e_illume_kbd->border) + { + e_border_fx_offset(_e_illume_kbd->border, 0, + _e_illume_kbd->border->h); + e_border_hide(_e_illume_kbd->border, 2); + } + _e_illume_kbd->visible = 0; + } + else + _e_mod_kbd_slide(0, (double)_e_illume_cfg->animation.vkbd.duration / 1000.0); +} + +static void +_e_mod_kbd_slide(int visible, double len) +{ + _e_illume_kbd->start = ecore_loop_time_get(); + _e_illume_kbd->len = len; + _e_illume_kbd->adjust_start = _e_illume_kbd->adjust; + _e_illume_kbd->adjust_end = 0; + if ((visible) && (_e_illume_kbd->border)) + _e_illume_kbd->adjust_end = _e_illume_kbd->border->h; + if (!_e_illume_kbd->animator) + _e_illume_kbd->animator = ecore_animator_add(_e_mod_kbd_cb_animate, NULL); +} + +static int +_e_mod_kbd_cb_animate(void *data __UNUSED__) +{ + double t, v; + + t = (ecore_loop_time_get() - _e_illume_kbd->start); + if (t > _e_illume_kbd->len) t = _e_illume_kbd->len; + if (_e_illume_kbd->len > 0.0) + { + v = (t / _e_illume_kbd->len); + v = (1.0 - v); + v = (v * v * v * v); + v = (1.0 - v); + } + else + { + t = _e_illume_kbd->len; + v = 1.0; + } + _e_illume_kbd->adjust = ((_e_illume_kbd->adjust_end * v) + + (_e_illume_kbd->adjust_start * (1.0 - v))); + + if (_e_illume_kbd->border) + { + e_border_fx_offset(_e_illume_kbd->border, 0, + (_e_illume_kbd->border->h - _e_illume_kbd->adjust)); + } + + if (t == _e_illume_kbd->len) + { + _e_illume_kbd->animator = NULL; + if ((_e_illume_kbd->visible) && + (_focused_state <= ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)) + { + if (_e_illume_kbd->border) + e_border_hide(_e_illume_kbd->border, 2); + _e_illume_kbd->visible = 0; + } + else + _e_illume_kbd->visible = 1; + + /* layout send */ + + /* tell the focused border it changed so layout gets udpated */ + if (_focused_border) + { + if (!e_illume_border_is_conformant(_focused_border)) + { + _focused_border->changes.size = 1; + _focused_border->changed = 1; + } + } + + return 0; + } + + return 1; +} + +static E_Illume_Keyboard * +_e_mod_kbd_by_border_get(E_Border *bd) +{ + Eina_List *l; + E_Border *over; + + if ((!bd) || (!bd->stolen)) return NULL; + + /* if this border is the one that vkbd is working with, return the kbd */ + if (_e_illume_kbd->border == bd) return _e_illume_kbd; + + /* loop the waiting borders */ + EINA_LIST_FOREACH(_e_illume_kbd->waiting_borders, l, over) + if (over == bd) return _e_illume_kbd; + + return NULL; +} + +static void +_e_mod_kbd_border_adopt(E_Border *bd) +{ + if ((!_e_illume_kbd) || (!bd)) return; + + _e_illume_kbd->border = bd; + + if (!_e_illume_kbd->visible) + { + e_border_fx_offset(bd, 0, bd->h); + /* layout send */ + } +} diff --git a/src/modules/illume2/e_mod_kbd.h b/src/modules/illume2/e_mod_kbd.h new file mode 100644 index 000000000..ebcd9df1c --- /dev/null +++ b/src/modules/illume2/e_mod_kbd.h @@ -0,0 +1,19 @@ +#ifndef E_MOD_KBD_H +# define E_MOD_KBD_H + +/* define keyboard object type */ +# define E_ILLUME_KBD_TYPE 0xE1b0988 + +int e_mod_kbd_init(void); +int e_mod_kbd_shutdown(void); + +E_Illume_Keyboard *e_mod_kbd_new(void); +void e_mod_kbd_enable(void); +void e_mod_kbd_disable(void); +void e_mod_kbd_show(void); +void e_mod_kbd_hide(void); +void e_mod_kbd_toggle(void); +void e_mod_kbd_fullscreen_set(E_Zone *zone, int fullscreen); +void e_mod_kbd_layout_set(E_Illume_Keyboard *kbd, E_Illume_Keyboard_Layout layout); + +#endif diff --git a/src/modules/illume2/e_mod_kbd_dbus.c b/src/modules/illume2/e_mod_kbd_dbus.c new file mode 100644 index 000000000..cdcb86488 --- /dev/null +++ b/src/modules/illume2/e_mod_kbd_dbus.c @@ -0,0 +1,279 @@ +#include "e_illume_private.h" +#include "e_mod_kbd_dbus.h" + +/* local function prototypes */ +static void _e_mod_kbd_dbus_ignore_load(void); +static void _e_mod_kbd_dbus_ignore_load_file(const char *file); +static void _e_mod_kbd_dbus_cb_input_kbd(void *data, void *reply, DBusError *err); +static void _e_mod_kbd_dbus_cb_input_kbd_is(void *data, void *reply, DBusError *err); +static void _e_mod_kbd_dbus_kbd_add(const char *udi); +static void _e_mod_kbd_dbus_kbd_del(const char *udi); +static void _e_mod_kbd_dbus_kbd_eval(void); +static void _e_mod_kbd_dbus_dev_add(void *data, DBusMessage *msg); +static void _e_mod_kbd_dbus_dev_del(void *data, DBusMessage *msg); +static void _e_mod_kbd_dbus_dev_chg(void *data, DBusMessage *msg); + +/* local variables */ +static int have_real_kbd = 0; +static E_DBus_Connection *_dbus_conn = NULL; +static E_DBus_Signal_Handler *_dev_add = NULL; +static E_DBus_Signal_Handler *_dev_del = NULL; +static E_DBus_Signal_Handler *_dev_chg = NULL; +static Eina_List *_dbus_kbds = NULL, *_ignore_kbds = NULL; + +void +e_mod_kbd_dbus_init(void) +{ + /* load the 'ignored' keyboard file */ + _e_mod_kbd_dbus_ignore_load(); + + /* try to attach to the system dbus */ + if (!(_dbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM))) return; + + /* ask HAL for any input keyboards */ + e_hal_manager_find_device_by_capability(_dbus_conn, "input.keyboard", + _e_mod_kbd_dbus_cb_input_kbd, NULL); + + /* setup dbus signal handlers for when a device gets added/removed/changed */ + _dev_add = + e_dbus_signal_handler_add(_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "DeviceAdded", _e_mod_kbd_dbus_dev_add, NULL); + _dev_del = + e_dbus_signal_handler_add(_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "DeviceRemoved", _e_mod_kbd_dbus_dev_del, NULL); + _dev_chg = + e_dbus_signal_handler_add(_dbus_conn, "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager", + "org.freedesktop.Hal.Manager", + "NewCapability", _e_mod_kbd_dbus_dev_chg, NULL); +} + +void +e_mod_kbd_dbus_shutdown(void) +{ + char *str; + + /* remove the dbus signal handlers if we can */ + if (_dev_add) e_dbus_signal_handler_del(_dbus_conn, _dev_add); + if (_dev_del) e_dbus_signal_handler_del(_dbus_conn, _dev_del); + if (_dev_chg) e_dbus_signal_handler_del(_dbus_conn, _dev_chg); + + /* free the list of ignored keyboards */ + EINA_LIST_FREE(_ignore_kbds, str) + eina_stringshare_del(str); + + /* free the list of keyboards */ + EINA_LIST_FREE(_dbus_kbds, str) + eina_stringshare_del(str); +} + +/* local functions */ +static void +_e_mod_kbd_dbus_ignore_load(void) +{ + char buff[PATH_MAX]; + + /* load the 'ignore' file from the user's home dir */ + e_user_dir_concat_static(buff, "keyboards/ignore_built_in_keyboards"); + _e_mod_kbd_dbus_ignore_load_file(buff); + + /* load the 'ignore' file from the system/module dir */ + snprintf(buff, sizeof(buff), + "%s/ignore_built_in_keyboards", _e_illume_mod_dir); + _e_mod_kbd_dbus_ignore_load_file(buff); +} + +static void +_e_mod_kbd_dbus_ignore_load_file(const char *file) +{ + char buff[PATH_MAX]; + FILE *f; + + /* can this file be opened */ + if (!(f = fopen(file, "r"))) return; + + /* parse out the info in the ignore file */ + 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++; + + /* append this kbd to the ignore list */ + if (*p) + { + _ignore_kbds = + eina_list_append(_ignore_kbds, eina_stringshare_add(p)); + } + } + fclose(f); +} + +static void +_e_mod_kbd_dbus_cb_input_kbd(void *data, void *reply, DBusError *err) +{ + E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply; + Eina_List *l; + char *dev; + + if ((!ret) || (!ret->strings)) return; + + /* if dbus errored then cleanup and get out */ + if (dbus_error_is_set(err)) + { + dbus_error_free(err); + return; + } + + /* for each returned keyboard, add it and evaluate it */ + EINA_LIST_FOREACH(ret->strings, l, dev) + { + _e_mod_kbd_dbus_kbd_add(dev); + _e_mod_kbd_dbus_kbd_eval(); + } +} + +static void +_e_mod_kbd_dbus_cb_input_kbd_is(void *data, void *reply, DBusError *err) +{ + E_Hal_Device_Query_Capability_Return *ret = reply; + char *udi = data; + + /* if dbus errored then cleanup and get out */ + if (dbus_error_is_set(err)) + { + dbus_error_free(err); + if (udi) free(udi); + return; + } + + /* if it's an input keyboard, than add it and eval */ + if ((ret) && (ret->boolean)) + { + if (udi) + { + _e_mod_kbd_dbus_kbd_add(udi); + _e_mod_kbd_dbus_kbd_eval(); + free(udi); + } + } +} + +static void +_e_mod_kbd_dbus_kbd_add(const char *udi) +{ + const char *str; + Eina_List *l; + + if (!udi) return; + EINA_LIST_FOREACH(_dbus_kbds, l, str) + if (!strcmp(str, udi)) return; + _dbus_kbds = eina_list_append(_dbus_kbds, eina_stringshare_add(udi)); +} + +static void +_e_mod_kbd_dbus_kbd_del(const char *udi) +{ + const char *str; + Eina_List *l; + + if (!udi) return; + EINA_LIST_FOREACH(_dbus_kbds, l, str) + if (!strcmp(str, udi)) + { + eina_stringshare_del(str); + _dbus_kbds = eina_list_remove_list(_dbus_kbds, l); + return; + } +} + +static void +_e_mod_kbd_dbus_kbd_eval(void) +{ + Eina_List *l, *ll; + const char *g, *gg; + int have_real = 0; + + have_real = eina_list_count(_dbus_kbds); + EINA_LIST_FOREACH(_dbus_kbds, l, g) + EINA_LIST_FOREACH(_ignore_kbds, ll, gg) + if (e_util_glob_match(g, gg)) + { + have_real--; + break; + } + + if (have_real != have_real_kbd) + { + have_real_kbd = have_real; +#if 0 +// if (have_real_kbd) e_kbd_all_disable(); + else +#endif +// e_kbd_all_enable(); + } +} + +static void +_e_mod_kbd_dbus_dev_add(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_hal_device_query_capability(_dbus_conn, udi, "input.keyboard", + _e_mod_kbd_dbus_cb_input_kbd_is, udi); +} + +static void +_e_mod_kbd_dbus_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); + if (udi) + { + _e_mod_kbd_dbus_kbd_del(udi); + _e_mod_kbd_dbus_kbd_eval(); + free(udi); + } +} + +static void +_e_mod_kbd_dbus_dev_chg(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 (cap) + { + if (!strcmp(cap, "input.keyboard")) + { + if (udi) + { + _e_mod_kbd_dbus_kbd_add(udi); + _e_mod_kbd_dbus_kbd_eval(); + free(udi); + } + } + free(cap); + } +} diff --git a/src/modules/illume2/e_mod_kbd_dbus.h b/src/modules/illume2/e_mod_kbd_dbus.h new file mode 100644 index 000000000..071d244e2 --- /dev/null +++ b/src/modules/illume2/e_mod_kbd_dbus.h @@ -0,0 +1,7 @@ +#ifndef E_MOD_KBD_DBUS_H +# define E_MOD_KBD_DBUS_H + +void e_mod_kbd_dbus_init(void); +void e_mod_kbd_dbus_shutdown(void); + +#endif 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_main.h b/src/modules/illume2/e_mod_main.h new file mode 100644 index 000000000..f415823c6 --- /dev/null +++ b/src/modules/illume2/e_mod_main.h @@ -0,0 +1,10 @@ +#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); + +#endif diff --git a/src/modules/illume2/e_mod_policy.c b/src/modules/illume2/e_mod_policy.c new file mode 100644 index 000000000..568a43a48 --- /dev/null +++ b/src/modules/illume2/e_mod_policy.c @@ -0,0 +1,520 @@ +#include "e_illume_private.h" +#include "e_mod_policy.h" + +/* local function prototypes */ +static char *_e_mod_policy_find(void); +static int _e_mod_policy_load(char *file); +static void _e_mod_policy_handlers_add(void); +static void _e_mod_policy_hooks_add(void); +static void _e_mod_policy_cb_free(E_Illume_Policy *p); +static int _e_mod_policy_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_zone_move_resize(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_window_property(void *data __UNUSED__, int type __UNUSED__, void *event); +static int _e_mod_policy_cb_policy_change(void *data __UNUSED__, int type, void *event __UNUSED__); +static void _e_mod_policy_cb_hook_post_fetch(void *data __UNUSED__, void *data2); +static void _e_mod_policy_cb_hook_post_assign(void *data __UNUSED__, void *data2); +static void _e_mod_policy_cb_hook_layout(void *data __UNUSED__, void *data2 __UNUSED__); + +/* local variables */ +static E_Illume_Policy *_policy = NULL; +static Eina_List *_policy_hdls = NULL, *_policy_hooks = NULL; + +/* external variables */ +int E_ILLUME_POLICY_EVENT_CHANGE = 0; + +int +e_mod_policy_init(void) +{ + Eina_List *ml; + E_Manager *man; + char *file; + + /* try to find the policy specified in config */ + if (!(file = _e_mod_policy_find())) + { + printf("Cannot find policy\n"); + return 0; + } + + /* attempt to load policy */ + if (!_e_mod_policy_load(file)) + { + /* loading policy failed, bail out */ + printf("Cannot load policy: %s\n", file); + if (file) free(file); + return 0; + } + + /* create new event for policy changes */ + E_ILLUME_POLICY_EVENT_CHANGE = ecore_event_type_new(); + + /* add our event handlers */ + _e_mod_policy_handlers_add(); + + /* add our border hooks */ + _e_mod_policy_hooks_add(); + + /* loop the root windows */ + EINA_LIST_FOREACH(e_manager_list(), ml, man) + { + Eina_List *cl; + E_Container *con; + + /* loop the containers */ + EINA_LIST_FOREACH(man->containers, cl, con) + { + Eina_List *zl; + E_Zone *zone; + + /* loop the zones */ + EINA_LIST_FOREACH(con->zones, zl, zone) + { + E_Illume_Config_Zone *cz; + Ecore_X_Illume_Mode mode; + + /* check for zone config */ + if (!(cz = e_illume_zone_config_get(zone->id))) + continue; + + /* set mode on this zone */ + if (cz->mode.dual == 0) + mode = ECORE_X_ILLUME_MODE_SINGLE; + else + { + if ((cz->mode.dual == 1) && (cz->mode.side == 0)) + mode = ECORE_X_ILLUME_MODE_DUAL_TOP; + else if ((cz->mode.dual == 1) && (cz->mode.side == 1)) + mode = ECORE_X_ILLUME_MODE_DUAL_LEFT; + } + ecore_x_e_illume_mode_set(zone->black_win, mode); + } + } + } + + return 1; +} + +int +e_mod_policy_shutdown(void) +{ + Ecore_Event_Handler *hdl; + E_Border_Hook *hook; + + /* remove the ecore event handlers */ + EINA_LIST_FREE(_policy_hdls, hdl) + ecore_event_handler_del(hdl); + + /* remove the border hooks */ + EINA_LIST_FREE(_policy_hooks, hook) + e_border_hook_del(hook); + + /* destroy the policy if it exists */ + if (_policy) e_object_del(E_OBJECT(_policy)); + + /* reset event type */ + E_ILLUME_POLICY_EVENT_CHANGE = 0; + + return 1; +} + +/* local functions */ +static char * +_e_mod_policy_find(void) +{ + Eina_List *files; + char buff[PATH_MAX], dir[PATH_MAX], *file; + + snprintf(buff, sizeof(buff), "%s.so", _e_illume_cfg->policy.name); + snprintf(dir, sizeof(dir), "%s/policies", _e_illume_mod_dir); + + /* try to list all files in this directory */ + if (!(files = ecore_file_ls(dir))) return NULL; + + /* loop the returned files */ + EINA_LIST_FREE(files, file) + { + /* compare file with needed .so */ + if (!strcmp(file, buff)) + { + snprintf(dir, sizeof(dir), "%s/policies/%s", + _e_illume_mod_dir, file); + break; + } + free(file); + } + if (file) free(file); + else + { + /* if we did not find the requested policy, use a fallback */ + snprintf(dir, sizeof(dir), "%s/policies/illume.so", _e_illume_mod_dir); + } + + return strdup(dir); +} + +static int +_e_mod_policy_load(char *file) +{ + /* safety check */ + if (!file) return 0; + + /* delete existing policy first */ + if (_policy) e_object_del(E_OBJECT(_policy)); + + /* try to create our new policy object */ + _policy = + E_OBJECT_ALLOC(E_Illume_Policy, E_ILLUME_POLICY_TYPE, + _e_mod_policy_cb_free); + if (!_policy) + { + printf("Failed to allocate new policy object\n"); + return 0; + } + + /* attempt to open the .so */ + if (!(_policy->handle = dlopen(file, (RTLD_NOW | RTLD_GLOBAL)))) + { + /* cannot open the .so file, bail out */ + printf("Cannot open policy: %s\n", ecore_file_file_get(file)); + printf("\tError: %s\n", dlerror()); + e_object_del(E_OBJECT(_policy)); + return 0; + } + + /* clear any existing errors in dynamic loader */ + dlerror(); + + /* try to link to the needed policy api functions */ + _policy->api = dlsym(_policy->handle, "e_illume_policy_api"); + _policy->funcs.init = dlsym(_policy->handle, "e_illume_policy_init"); + _policy->funcs.shutdown = dlsym(_policy->handle, "e_illume_policy_shutdown"); + + /* check that policy supports needed functions */ + if ((!_policy->api) || (!_policy->funcs.init) || (!_policy->funcs.shutdown)) + { + /* policy doesn't support needed functions, bail out */ + printf("Policy does not support needed functions: %s\n", + ecore_file_file_get(file)); + printf("\tError: %s\n", dlerror()); + e_object_del(E_OBJECT(_policy)); + return 0; + } + + /* check policy api version */ + if (_policy->api->version < E_ILLUME_POLICY_API_VERSION) + { + /* policy is too old, bail out */ + printf("Policy is too old: %s\n", ecore_file_file_get(file)); + e_object_del(E_OBJECT(_policy)); + return 0; + } + + /* try to initialize the policy */ + if (!_policy->funcs.init(_policy)) + { + /* init failed, bail out */ + printf("Policy failed to initialize: %s\n", ecore_file_file_get(file)); + e_object_del(E_OBJECT(_policy)); + return 0; + } + + return 1; +} + +static void +_e_mod_policy_handlers_add(void) +{ + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_EVENT_BORDER_ADD, + _e_mod_policy_cb_border_add, NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_EVENT_BORDER_REMOVE, + _e_mod_policy_cb_border_del, NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, + _e_mod_policy_cb_border_focus_in, + NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, + _e_mod_policy_cb_border_focus_out, + NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE, + _e_mod_policy_cb_zone_move_resize, + NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + _e_mod_policy_cb_client_message, + NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, + _e_mod_policy_cb_window_property, + NULL)); + _policy_hdls = + eina_list_append(_policy_hdls, + ecore_event_handler_add(E_ILLUME_POLICY_EVENT_CHANGE, + _e_mod_policy_cb_policy_change, + NULL)); +} + +static void +_e_mod_policy_hooks_add(void) +{ + _policy_hooks = + eina_list_append(_policy_hooks, + e_border_hook_add(E_BORDER_HOOK_EVAL_POST_FETCH, + _e_mod_policy_cb_hook_post_fetch, NULL)); + _policy_hooks = + eina_list_append(_policy_hooks, + e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, + _e_mod_policy_cb_hook_post_assign, NULL)); + _policy_hooks = + eina_list_append(_policy_hooks, + e_border_hook_add(E_BORDER_HOOK_CONTAINER_LAYOUT, + _e_mod_policy_cb_hook_layout, NULL)); +} + +static void +_e_mod_policy_cb_free(E_Illume_Policy *p) +{ + /* tell the policy to shutdown */ + if (p->funcs.shutdown) p->funcs.shutdown(p); + p->funcs.shutdown = NULL; + + p->funcs.init = NULL; + p->api = NULL; + + /* close the linked .so */ + if (p->handle) dlclose(p->handle); + p->handle = NULL; + + E_FREE(p); +} + +static int +_e_mod_policy_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Add *ev; + + ev = event; + if ((_policy) && (_policy->funcs.border_add)) + _policy->funcs.border_add(ev->border); + + return 1; +} + +static int +_e_mod_policy_cb_border_del(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Remove *ev; + + ev = event; + if ((_policy) && (_policy->funcs.border_del)) + _policy->funcs.border_del(ev->border); + + return 1; +} + +static int +_e_mod_policy_cb_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Focus_In *ev; + + ev = event; + if ((_policy) && (_policy->funcs.border_focus_in)) + _policy->funcs.border_focus_in(ev->border); + + return 1; +} + +static int +_e_mod_policy_cb_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Border_Focus_Out *ev; + + ev = event; + if ((_policy) && (_policy->funcs.border_focus_out)) + _policy->funcs.border_focus_out(ev->border); + + return 1; +} + +static int +_e_mod_policy_cb_zone_move_resize(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + E_Event_Zone_Move_Resize *ev; + + ev = event; + if ((_policy) && (_policy->funcs.zone_move_resize)) + _policy->funcs.zone_move_resize(ev->zone); + + return 1; +} + +static int +_e_mod_policy_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_NET_ACTIVE_WINDOW) + { + E_Border *bd; + + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + if ((_policy) && (_policy->funcs.border_activate)) + _policy->funcs.border_activate(bd); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_MODE) + { + E_Zone *zone; + + if (!(zone = e_util_zone_window_find(ev->win))) return 1; + if ((_policy) && (_policy->funcs.zone_mode_change)) + _policy->funcs.zone_mode_change(zone, ev->data.l[0]); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_CLOSE) + { + E_Zone *zone; + + if (!(zone = e_util_zone_window_find(ev->win))) return 1; + if ((_policy) && (_policy->funcs.zone_close)) + _policy->funcs.zone_close(zone); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_BACK) + { + E_Zone *zone; + + if (!(zone = e_util_zone_window_find(ev->win))) return 1; + if ((_policy) && (_policy->funcs.focus_back)) + _policy->funcs.focus_back(zone); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD) + { + E_Zone *zone; + + if (!(zone = e_util_zone_window_find(ev->win))) return 1; + if ((_policy) && (_policy->funcs.focus_forward)) + _policy->funcs.focus_forward(zone); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_FOCUS_HOME) + { + E_Zone *zone; + + if (!(zone = e_util_zone_window_find(ev->win))) return 1; + if ((_policy) && (_policy->funcs.focus_home)) + _policy->funcs.focus_home(zone); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_DRAG_START) + { + E_Border *bd; + + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + if ((_policy) && (_policy->funcs.drag_start)) + _policy->funcs.drag_start(bd); + } + else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_DRAG_END) + { + E_Border *bd; + + if (!(bd = e_border_find_by_client_window(ev->win))) return 1; + if ((_policy) && (_policy->funcs.drag_end)) + _policy->funcs.drag_end(bd); + } +// else +// printf("Client Message: %s\n", ecore_x_atom_name_get(ev->message_type)); + + return 1; +} + +static int +_e_mod_policy_cb_window_property(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_X_Event_Window_Property *ev; + + ev = event; + if ((_policy) && (_policy->funcs.property_change)) + _policy->funcs.property_change(ev); + + return 1; +} + +static int +_e_mod_policy_cb_policy_change(void *data __UNUSED__, int type, void *event __UNUSED__) +{ + char *file; + + if (type != E_ILLUME_POLICY_EVENT_CHANGE) return 1; + + /* find policy specified in config */ + if (!(file = _e_mod_policy_find())) return 1; + + /* try to load the policy */ + _e_mod_policy_load(file); + + if (file) free(file); + + return 1; +} + +static void +_e_mod_policy_cb_hook_post_fetch(void *data __UNUSED__, void *data2) +{ + E_Border *bd; + + if (!(bd = data2)) return; + if ((_policy) && (_policy->funcs.border_post_fetch)) + _policy->funcs.border_post_fetch(bd); +} + +static void +_e_mod_policy_cb_hook_post_assign(void *data __UNUSED__, void *data2) +{ + E_Border *bd; + + if (!(bd = data2)) return; + if ((_policy) && (_policy->funcs.border_post_assign)) + _policy->funcs.border_post_assign(bd); +} + +static void +_e_mod_policy_cb_hook_layout(void *data __UNUSED__, void *data2 __UNUSED__) +{ + E_Zone *zone; + E_Border *bd; + Eina_List *zl = NULL, *l; + + /* loop through border list and find what changed */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + if ((bd->new_client) || (bd->pending_move_resize) || + (bd->changes.pos) || (bd->changes.size) || (bd->changes.visible)) + { + /* NB: this border changed. add it's zone to list of what needs + * updating. This is done so we do not waste cpu cycles + * updating zones where nothing changed */ + if (!eina_list_data_find(zl, bd->zone)) + zl = eina_list_append(zl, bd->zone); + } + } + l = eina_list_free(l); + + /* loop the zones that need updating and call the policy update function */ + EINA_LIST_FREE(zl, zone) + { + if ((_policy) && (_policy->funcs.zone_layout)) + _policy->funcs.zone_layout(zone); + } + zl = eina_list_free(zl); +} diff --git a/src/modules/illume2/e_mod_policy.h b/src/modules/illume2/e_mod_policy.h new file mode 100644 index 000000000..29b61e5b3 --- /dev/null +++ b/src/modules/illume2/e_mod_policy.h @@ -0,0 +1,7 @@ +#ifndef E_MOD_POLICY_H +# define E_MOD_POLICY_H + +int e_mod_policy_init(void); +int e_mod_policy_shutdown(void); + +#endif 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); +} diff --git a/src/modules/illume2/e_mod_quickpanel.h b/src/modules/illume2/e_mod_quickpanel.h new file mode 100644 index 000000000..b3eb3f15c --- /dev/null +++ b/src/modules/illume2/e_mod_quickpanel.h @@ -0,0 +1,13 @@ +#ifndef E_MOD_QUICKPANEL_H +# define E_MOD_QUICKPANEL_H + +# define E_ILLUME_QP_TYPE 0xE1b0990 + +int e_mod_quickpanel_init(void); +int e_mod_quickpanel_shutdown(void); + +E_Illume_Quickpanel *e_mod_quickpanel_new(E_Zone *zone); +void e_mod_quickpanel_show(E_Illume_Quickpanel *qp); +void e_mod_quickpanel_hide(E_Illume_Quickpanel *qp); + +#endif diff --git a/src/modules/illume2/e_mod_select_window.c b/src/modules/illume2/e_mod_select_window.c new file mode 100644 index 000000000..962f5f781 --- /dev/null +++ b/src/modules/illume2/e_mod_select_window.c @@ -0,0 +1,277 @@ +#include "e_illume_private.h" +#include "e_mod_select_window.h" + +/* local function prototypes */ +static void *_e_mod_config_select_window_create_data(E_Config_Dialog *cfd); +static void _e_mod_config_select_window_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_e_mod_config_select_window_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static void _e_mod_config_select_window_list_changed(void *data); +static int _e_mod_config_select_window_change_timeout(void *data); +static int _e_mod_config_select_window_match(E_Border *bd); + +/* local variables */ +E_Illume_Select_Window_Type stype; +Ecore_Timer *_sw_change_timer = NULL; + +/* public functions */ +void +e_mod_config_select_window(E_Illume_Select_Window_Type type) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + + if (e_config_dialog_find("E", "_config_illume_select_window")) return; + + v = E_NEW(E_Config_Dialog_View, 1); + if (!v) return; + + v->create_cfdata = _e_mod_config_select_window_create_data; + v->free_cfdata = _e_mod_config_select_window_free_data; + v->basic.create_widgets = _e_mod_config_select_window_create; + v->basic_only = 1; + v->normal_win = 1; + v->scroll = 1; + cfd = e_config_dialog_new(e_container_current_get(e_manager_current_get()), + _("Select Home Window"), "E", + "_config_illume_select_window", + "enlightenment/windows", 0, v, NULL); + if (!cfd) return; + e_dialog_resizable_set(cfd->dia, 1); + stype = type; +} + +static void * +_e_mod_config_select_window_create_data(E_Config_Dialog *cfd) +{ + return NULL; +} + +static void +_e_mod_config_select_window_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + +} + +static Evas_Object * +_e_mod_config_select_window_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *list, *ow; + Eina_List *bds, *l; + int i = 0, sel = -1; + + list = e_widget_list_add(evas, 0, 0); + ow = e_widget_ilist_add(evas, 24, 24, NULL); + e_widget_ilist_selector_set(ow, 1); + evas_event_freeze(evas); + edje_freeze(); + e_widget_ilist_freeze(ow); + e_widget_ilist_clear(ow); + e_widget_ilist_go(ow); + + bds = e_border_client_list(); + if (bds) + { + for (i = 0, l = bds; l; l = l->next, i++) + { + E_Border *bd; + const char *name; + + if (!(bd = l->data)) continue; + if (e_object_is_del(E_OBJECT(bd))) continue; + if (_e_mod_config_select_window_match(bd)) sel = i; + if (!(name = e_border_name_get(bd))) continue; + e_widget_ilist_append(ow, NULL, name, + _e_mod_config_select_window_list_changed, + bd, name); + } + } + + e_widget_size_min_set(ow, 100, 200); + e_widget_ilist_go(ow); + if (sel >= 0) e_widget_ilist_selected_set(ow, sel); + e_widget_ilist_thaw(ow); + edje_thaw(); + evas_event_thaw(evas); + e_widget_list_object_append(list, ow, 1, 0, 0.0); + return list; +} + +static void +_e_mod_config_select_window_list_changed(void *data) +{ + E_Border *bd; + Ecore_X_Window_Type wtype; + char *title, *name, *class; + + if (!(bd = data)) return; + title = ecore_x_icccm_title_get(bd->client.win); + ecore_x_icccm_name_class_get(bd->client.win, &name, &class); + ecore_x_netwm_window_type_get(bd->client.win, &wtype); + + switch (stype) + { + case E_ILLUME_SELECT_WINDOW_TYPE_HOME: + if (_e_illume_cfg->policy.home.title) + eina_stringshare_del(_e_illume_cfg->policy.home.title); + if (title) _e_illume_cfg->policy.home.title = eina_stringshare_add(title); + if (_e_illume_cfg->policy.home.class) + eina_stringshare_del(_e_illume_cfg->policy.home.class); + if (class) _e_illume_cfg->policy.home.class = eina_stringshare_add(class); + if (_e_illume_cfg->policy.home.name) + eina_stringshare_del(_e_illume_cfg->policy.home.name); + if (name) _e_illume_cfg->policy.home.name = eina_stringshare_add(name); + break; + case E_ILLUME_SELECT_WINDOW_TYPE_VKBD: + if (_e_illume_cfg->policy.vkbd.title) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.title); + if (title) _e_illume_cfg->policy.vkbd.title = eina_stringshare_add(title); + if (_e_illume_cfg->policy.vkbd.class) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.class); + if (class) _e_illume_cfg->policy.vkbd.class = eina_stringshare_add(class); + if (_e_illume_cfg->policy.vkbd.name) + eina_stringshare_del(_e_illume_cfg->policy.vkbd.name); + if (name) _e_illume_cfg->policy.vkbd.name = eina_stringshare_add(name); + break; + case E_ILLUME_SELECT_WINDOW_TYPE_SOFTKEY: + if (_e_illume_cfg->policy.softkey.title) + eina_stringshare_del(_e_illume_cfg->policy.softkey.title); + if (title) _e_illume_cfg->policy.softkey.title = eina_stringshare_add(title); + if (_e_illume_cfg->policy.softkey.class) + eina_stringshare_del(_e_illume_cfg->policy.softkey.class); + if (class) _e_illume_cfg->policy.softkey.class = eina_stringshare_add(class); + if (_e_illume_cfg->policy.softkey.name) + eina_stringshare_del(_e_illume_cfg->policy.softkey.name); + if (name) _e_illume_cfg->policy.softkey.name = eina_stringshare_add(name); + break; + case E_ILLUME_SELECT_WINDOW_TYPE_INDICATOR: + if (_e_illume_cfg->policy.indicator.title) + eina_stringshare_del(_e_illume_cfg->policy.indicator.title); + if (title) _e_illume_cfg->policy.indicator.title = eina_stringshare_add(title); + if (_e_illume_cfg->policy.indicator.class) + eina_stringshare_del(_e_illume_cfg->policy.indicator.class); + if (class) _e_illume_cfg->policy.indicator.class = eina_stringshare_add(class); + if (_e_illume_cfg->policy.indicator.name) + eina_stringshare_del(_e_illume_cfg->policy.indicator.name); + if (name) _e_illume_cfg->policy.indicator.name = eina_stringshare_add(name); + break; + } + + if (title) free(title); + if (name) free(name); + if (class) free(class); + + if (_sw_change_timer) ecore_timer_del(_sw_change_timer); + _sw_change_timer = + ecore_timer_add(0.5, _e_mod_config_select_window_change_timeout, data); +} + +static int +_e_mod_config_select_window_change_timeout(void *data) +{ + e_config_save_queue(); + _sw_change_timer = NULL; + return 0; +} + +static int +_e_mod_config_select_window_match(E_Border *bd) +{ + Ecore_X_Window_Type wtype; + char *title, *name, *class; + int match = 0; + + if (!bd) return 0; + title = ecore_x_icccm_title_get(bd->client.win); + ecore_x_icccm_name_class_get(bd->client.win, &name, &class); + ecore_x_netwm_window_type_get(bd->client.win, &wtype); + + switch (stype) + { + case E_ILLUME_SELECT_WINDOW_TYPE_HOME: + if (_e_illume_cfg->policy.home.match.title) + { + if ((title) && (!strcmp(title, _e_illume_cfg->policy.home.title))) + match = 1; + break; + } + if (_e_illume_cfg->policy.home.match.name) + { + if ((name) && (!strcmp(name, _e_illume_cfg->policy.home.name))) + match = 1; + break; + } + if (_e_illume_cfg->policy.home.match.class) + { + if ((class) && (!strcmp(class, _e_illume_cfg->policy.home.class))) + match = 1; + break; + } + break; + case E_ILLUME_SELECT_WINDOW_TYPE_VKBD: + if (_e_illume_cfg->policy.vkbd.match.title) + { + if ((title) && (!strcmp(title, _e_illume_cfg->policy.vkbd.title))) + match = 1; + break; + } + if (_e_illume_cfg->policy.vkbd.match.name) + { + if ((name) && (!strcmp(name, _e_illume_cfg->policy.vkbd.name))) + match = 1; + break; + } + if (_e_illume_cfg->policy.vkbd.match.class) + { + if ((class) && (!strcmp(class, _e_illume_cfg->policy.vkbd.class))) + match = 1; + break; + } + break; + case E_ILLUME_SELECT_WINDOW_TYPE_SOFTKEY: + if (_e_illume_cfg->policy.softkey.match.title) + { + if ((title) && (!strcmp(title, _e_illume_cfg->policy.softkey.title))) + match = 1; + break; + } + if (_e_illume_cfg->policy.softkey.match.name) + { + if ((name) && (!strcmp(name, _e_illume_cfg->policy.softkey.name))) + match = 1; + break; + } + if (_e_illume_cfg->policy.softkey.match.class) + { + if ((class) && (!strcmp(class, _e_illume_cfg->policy.softkey.class))) + match = 1; + break; + } + break; + case E_ILLUME_SELECT_WINDOW_TYPE_INDICATOR: + if (_e_illume_cfg->policy.indicator.match.title) + { + if ((title) && (!strcmp(title, _e_illume_cfg->policy.indicator.title))) + match = 1; + break; + } + if (_e_illume_cfg->policy.indicator.match.name) + { + if ((name) && (!strcmp(name, _e_illume_cfg->policy.indicator.name))) + match = 1; + break; + } + if (_e_illume_cfg->policy.indicator.match.class) + { + if ((class) && (!strcmp(class, _e_illume_cfg->policy.indicator.class))) + match = 1; + break; + } + break; + } + + if (title) free(title); + if (name) free(name); + if (class) free(class); + + return match; +} diff --git a/src/modules/illume2/e_mod_select_window.h b/src/modules/illume2/e_mod_select_window.h new file mode 100644 index 000000000..a4c2ca764 --- /dev/null +++ b/src/modules/illume2/e_mod_select_window.h @@ -0,0 +1,15 @@ +#ifndef E_MOD_SELECT_WINDOW_H +#define E_MOD_SELECT_WINDOW_H + +typedef enum _E_Illume_Select_Window_Type E_Illume_Select_Window_Type; +enum _E_Illume_Select_Window_Type +{ + E_ILLUME_SELECT_WINDOW_TYPE_HOME, + E_ILLUME_SELECT_WINDOW_TYPE_VKBD, + E_ILLUME_SELECT_WINDOW_TYPE_SOFTKEY, + E_ILLUME_SELECT_WINDOW_TYPE_INDICATOR +}; + +void e_mod_config_select_window(E_Illume_Select_Window_Type type); + +#endif diff --git a/src/modules/illume2/images/Makefile.am b/src/modules/illume2/images/Makefile.am new file mode 100644 index 000000000..6093afd3b --- /dev/null +++ b/src/modules/illume2/images/Makefile.am @@ -0,0 +1,3 @@ +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = module_icon.png diff --git a/src/modules/illume2/images/module_icon.png b/src/modules/illume2/images/module_icon.png new file mode 100644 index 000000000..babb89634 Binary files /dev/null and b/src/modules/illume2/images/module_icon.png differ diff --git a/src/modules/illume2/keyboards/Makefile.am b/src/modules/illume2/keyboards/Makefile.am new file mode 100644 index 000000000..57f0a2643 --- /dev/null +++ b/src/modules/illume2/keyboards/Makefile.am @@ -0,0 +1,11 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume3 + +filesdir = $(libdir)/enlightenment/modules/$(MODULE)/keyboards +files_DATA = ignore_built_in_keyboards + +EXTRA_DIST = $(files_DATA) + +uninstall: + rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)/keyboards + diff --git a/src/modules/illume2/keyboards/ignore_built_in_keyboards b/src/modules/illume2/keyboards/ignore_built_in_keyboards new file mode 100644 index 000000000..bdb9d6bbb --- /dev/null +++ b/src/modules/illume2/keyboards/ignore_built_in_keyboards @@ -0,0 +1 @@ +/org/freedesktop/Hal/devices/platform_* diff --git a/src/modules/illume2/module.desktop.in b/src/modules/illume2/module.desktop.in new file mode 100644 index 000000000..bbacd7507 --- /dev/null +++ b/src/modules/illume2/module.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=Illume2 +Icon=e-module-illume2 +X-Enlightenment-ModuleType=system +Comment=Illume2 for Embedded diff --git a/src/modules/illume2/policies/Makefile.am b/src/modules/illume2/policies/Makefile.am new file mode 100644 index 000000000..e433fcee7 --- /dev/null +++ b/src/modules/illume2/policies/Makefile.am @@ -0,0 +1,2 @@ +MAINTAINERCLEANFILES = Makefile.in +SUBDIRS = illume diff --git a/src/modules/illume2/policies/illume/Makefile.am b/src/modules/illume2/policies/illume/Makefile.am new file mode 100644 index 000000000..75fecc51e --- /dev/null +++ b/src/modules/illume2/policies/illume/Makefile.am @@ -0,0 +1,27 @@ +MAINTAINERCLEANFILES = Makefile.in +MODULE = illume2 +POLICY = illume + +# the module .so file +INCLUDES = -I.. \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/modules/$(MODULE) \ + -I$(top_srcdir)/src/modules/$(MODULE)/policies/$(POLICY) \ + -I$(top_srcdir)/src/bin \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/modules \ + @e_cflags@ + +plugindir = $(libdir)/enlightenment/modules/$(MODULE)/policies + +illumedir = $(plugindir) +illume_LTLIBRARIES = illume.la +illume_la_SOURCES = \ + policy.h \ + policy.c \ + illume.h \ + illume.c + +illume_la_LIBADD = @e_libs@ +illume_la_LDFLAGS = -no-undefined -module -avoid-version +illume_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/src/modules/illume2/policies/illume/illume.c b/src/modules/illume2/policies/illume/illume.c new file mode 100644 index 000000000..62ac5c884 --- /dev/null +++ b/src/modules/illume2/policies/illume/illume.c @@ -0,0 +1,58 @@ +#include "e_illume.h" +#include "illume.h" +#include "policy.h" + +EAPI E_Illume_Policy_Api e_illume_policy_api = +{ + /* version, name, label */ + E_ILLUME_POLICY_API_VERSION, "illume", "Illume" +}; + +EAPI int +e_illume_policy_init(E_Illume_Policy *p) +{ + /* tell the policy what functions we support */ + p->funcs.border_add = _policy_border_add; + p->funcs.border_del = _policy_border_del; + p->funcs.border_focus_in = _policy_border_focus_in; + p->funcs.border_focus_out = _policy_border_focus_out; + p->funcs.border_activate = _policy_border_activate; + p->funcs.border_post_fetch = _policy_border_post_fetch; + p->funcs.border_post_assign = _policy_border_post_assign; + p->funcs.zone_layout = _policy_zone_layout; + p->funcs.zone_move_resize = _policy_zone_move_resize; + p->funcs.zone_mode_change = _policy_zone_mode_change; + p->funcs.zone_close = _policy_zone_close; + p->funcs.drag_start = _policy_drag_start; + p->funcs.drag_end = _policy_drag_end; + p->funcs.focus_back = _policy_focus_back; + p->funcs.focus_forward = _policy_focus_forward; + p->funcs.focus_home = _policy_focus_home; + p->funcs.property_change = _policy_property_change; + + return 1; +} + +EAPI int +e_illume_policy_shutdown(E_Illume_Policy *p) +{ + p->funcs.border_add = NULL; + p->funcs.border_del = NULL; + p->funcs.border_focus_in = NULL; + p->funcs.border_focus_out = NULL; + p->funcs.border_activate = NULL; + p->funcs.border_post_fetch = NULL; + p->funcs.border_post_assign = NULL; + p->funcs.zone_layout = NULL; + p->funcs.zone_move_resize = NULL; + p->funcs.zone_mode_change = NULL; + p->funcs.zone_close = NULL; + p->funcs.drag_start = NULL; + p->funcs.drag_end = NULL; + p->funcs.focus_back = NULL; + p->funcs.focus_forward = NULL; + p->funcs.focus_home = NULL; + p->funcs.property_change = NULL; + + return 1; +} diff --git a/src/modules/illume2/policies/illume/illume.h b/src/modules/illume2/policies/illume/illume.h new file mode 100644 index 000000000..d7d975b61 --- /dev/null +++ b/src/modules/illume2/policies/illume/illume.h @@ -0,0 +1,9 @@ +#ifndef _ILLUME_H +# define _ILLUME_H + +EAPI extern E_Illume_Policy_Api e_illume_policy_api; + +EAPI int e_illume_policy_init(E_Illume_Policy *p); +EAPI int e_illume_policy_shutdown(E_Illume_Policy *p); + +#endif diff --git a/src/modules/illume2/policies/illume/policy.c b/src/modules/illume2/policies/illume/policy.c new file mode 100644 index 000000000..8bc1c3db1 --- /dev/null +++ b/src/modules/illume2/policies/illume/policy.c @@ -0,0 +1,1607 @@ +#include "e_illume.h" +#include "policy.h" + +/* NB: DIALOG_USES_PIXEL_BORDER is an experiment in setting dialog windows + * to use the 'pixel' type border. This is done because some dialogs, + * when shown, blend into other windows too much. Pixel border adds a + * little distinction between the dialog window and an app window. + * Disable if this is not wanted */ +#define DIALOG_USES_PIXEL_BORDER 1 + +/* local function prototypes */ +static void _policy_border_set_focus(E_Border *bd); +static void _policy_border_move(E_Border *bd, int x, int y); +static void _policy_border_resize(E_Border *bd, int w, int h); +static void _policy_border_hide_below(E_Border *bd); +static void _policy_border_show_below(E_Border *bd); +static void _policy_zone_layout_update(E_Zone *zone); +static void _policy_zone_layout_indicator(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_quickpanel(E_Border *bd); +static void _policy_zone_layout_softkey(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_keyboard(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_home_single(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_home_dual_top(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_home_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_home_dual_left(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_fullscreen(E_Border *bd); +static void _policy_zone_layout_app_single(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_app_dual_top(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_app_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_app_dual_left(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_dialog(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_splash(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_conformant_single(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_conformant_dual_top(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_conformant_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz); +static void _policy_zone_layout_conformant_dual_left(E_Border *bd, E_Illume_Config_Zone *cz); + +/* local functions */ +static void +_policy_border_set_focus(E_Border *bd) +{ + /* if focus is locked out then get out */ + if (bd->lock_focus_out) return; + + /* make sure the border can accept or take focus */ + if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus)) + { + /* check E's focus settings */ + if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || + ((bd->parent) && + ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) || + ((bd->parent->focused) && + (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED))))) + { + /* if the border is iconified then uniconify */ + if (bd->iconic) + { + /* if the user is allowed to uniconify, then do it */ + if (!bd->lock_user_iconify) e_border_uniconify(bd); + } + + /* if we can raise the border do it */ + if (!bd->lock_user_stacking) e_border_raise(bd); + + /* focus the border */ + e_border_focus_set(bd, 1, 1); + + /* NB: since we skip needless border evals when container layout + * is called (to save cpu cycles), we need to + * signal this border that it's focused so that the edj gets + * updated. + * + * This is potentially useless as THIS policy + * makes all windows borderless anyway, but it's in here for + * completeness */ + e_border_focus_latest_set(bd); + if (bd->bg_object) + edje_object_signal_emit(bd->bg_object, "e,state,focused", "e"); + if (bd->icon_object) + edje_object_signal_emit(bd->icon_object, "e,state,focused", "e"); + e_focus_event_focus_in(bd); + } + } +} + +static void +_policy_border_move(E_Border *bd, int x, int y) +{ + /* NB: Qt uses a weird window type called 'VCLSalFrame' that needs to + * have bd->placed set else it doesn't position correctly... + * this could be a result of E honoring the icccm request position, + * not sure */ + + /* NB: Seems something similiar happens with elementary windows also + * so for now just set bd->placed on all windows until this + * gets investigated */ + bd->placed = 1; + bd->x = x; + bd->y = y; + bd->changes.pos = 1; + bd->changed = 1; +} + +static void +_policy_border_resize(E_Border *bd, int w, int h) +{ + bd->w = w; + bd->h = 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->changed = 1; +} + +static void +_policy_border_hide_below(E_Border *bd) +{ + int pos = 0, i; + +// printf("Hide Borders Below: %s %d %d\n", +// bd->client.icccm.class, bd->x, bd->y); + + /* determine layering position */ + if (bd->layer <= 0) pos = 0; + else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1; + else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2; + else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3; + else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4; + else pos = 5; + + /* Find the windows below this one */ + for (i = pos; i >= 0; i--) + { + Eina_List *l; + E_Border *b; + + EINA_LIST_FOREACH(bd->zone->container->layers[i].clients, l, b) + { + /* skip if it's not on this zone */ + if (b->zone != bd->zone) continue; + + /* skip if it's the same border */ + if (b == bd) continue; + + /* skip special borders */ + if (e_illume_border_is_indicator(b)) continue; + if (e_illume_border_is_softkey(b)) continue; + if (e_illume_border_is_keyboard(b)) continue; + if (e_illume_border_is_quickpanel(b)) continue; + + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + if (b->visible) e_border_hide(b, 2); + } + else + { + /* we need to check x/y position */ + if ((b->x == bd->x) && (b->y == bd->y)) + { + if (b->visible) e_border_hide(b, 2); + } + } + } + } +} + +static void +_policy_border_show_below(E_Border *bd) +{ + int pos = 0, i; + +// printf("Show Borders Below: %s %d %d\n", +// bd->client.icccm.name, bd->x, bd->y); + + /* determine layering position */ + if (bd->layer <= 0) pos = 0; + else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1; + else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2; + else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3; + else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4; + else pos = 5; + + /* Find the windows below this one */ + for (i = pos; i >= 0; i--) + { + Eina_List *l; + E_Border *b; + + EINA_LIST_REVERSE_FOREACH(bd->zone->container->layers[i].clients, l, b) + { + /* skip if it's not on this zone */ + if (b->zone != bd->zone) continue; + + /* skip if it's the same border */ + if (b == bd) continue; + + /* skip special borders */ + if (e_illume_border_is_indicator(b)) continue; + if (e_illume_border_is_softkey(b)) continue; + if (e_illume_border_is_keyboard(b)) continue; + if (e_illume_border_is_quickpanel(b)) continue; + + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + if (!b->visible) e_border_show(b); + } + else + { + /* need to check x/y position */ + if ((b->x == bd->x) && (b->y == bd->y)) + { + if (!b->visible) e_border_show(b); + } + } + } + } +} + +static void +_policy_zone_layout_update(E_Zone *zone) +{ + Eina_List *l; + E_Border *bd; + + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip special windows */ + /* NB: We trigger a layout update on indicator windows so that + * quickpanel position gets updated so don't include indicators here */ +// if (e_illume_border_is_indicator(bd)) continue; + if (e_illume_border_is_softkey(bd)) continue; + if (e_illume_border_is_keyboard(bd)) continue; + if (e_illume_border_is_quickpanel(bd)) continue; + + /* signal a changed pos here so layout gets updated */ + bd->changes.pos = 1; + bd->changed = 1; + } +} + +static void +_policy_zone_layout_indicator(E_Border *bd, E_Illume_Config_Zone *cz) +{ + /* grab minimum indicator size */ + e_illume_border_min_get(bd, NULL, &cz->indicator.size); + + /* no point in doing anything here if indicator is hidden */ + if (!bd->visible) return; + + /* if we are dragging, then skip it for now */ + if (bd->client.illume.drag.drag) + { + /* when dragging indicator, we need to trigger a layout update */ + _policy_zone_layout_update(bd->zone); + return; + } + +// printf("\tLayout Indicator: %d\n", bd->zone->id); + + /* lock indicator window from dragging if we need to */ + if ((cz->mode.dual == 1) && (cz->mode.side == 0)) + ecore_x_e_illume_drag_locked_set(bd->client.win, 0); + else + ecore_x_e_illume_drag_locked_set(bd->client.win, 1); + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != cz->indicator.size)) + _policy_border_resize(bd, bd->zone->w, cz->indicator.size); + + /* are we in single mode ? */ + if (!cz->mode.dual) + { + /* move to 0, 0 (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != bd->zone->y)) + { + _policy_border_move(bd, bd->zone->x, bd->zone->y); + ecore_x_e_illume_quickpanel_position_update_send(bd->client.win); + } + } + else + { + /* dual app mode top */ + if (cz->mode.side == 0) + { + /* top mode...indicator is draggable so just set X */ + if (bd->x != bd->zone->x) + _policy_border_move(bd, bd->zone->x, bd->y); + } + else + { + /* move to 0, 0 (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != bd->zone->y)) + { + _policy_border_move(bd, bd->zone->x, bd->zone->y); + ecore_x_e_illume_quickpanel_position_update_send(bd->client.win); + } + } + } + + /* set layer if needed */ + if (bd->layer != POL_INDICATOR_LAYER) + e_border_layer_set(bd, POL_INDICATOR_LAYER); +} + +static void +_policy_zone_layout_quickpanel(E_Border *bd) +{ + int mh; + + /* grab minimum size */ + e_illume_border_min_get(bd, NULL, &mh); + + /* resize if needed */ + if ((bd->w != bd->zone->w) || (bd->h != mh)) + _policy_border_resize(bd, bd->zone->w, mh); + + /* set layer if needed */ + if (bd->layer != POL_QUICKPANEL_LAYER) + e_border_layer_set(bd, POL_QUICKPANEL_LAYER); +} + +static void +_policy_zone_layout_softkey(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int ny; + +// printf("\tLayout Softkey\n"); + + /* grab minimum softkey size */ + e_illume_border_min_get(bd, NULL, &cz->softkey.size); + + /* no point in doing anything here if softkey is hidden */ + if (!bd->visible) return; + + /* if we are dragging, then skip it for now */ + /* NB: Disabled currently until we confirm that softkey should be draggable */ +// if (bd->client.illume.drag.drag) return; + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != cz->softkey.size)) + _policy_border_resize(bd, bd->zone->w, cz->softkey.size); + + /* make sure it's in the correct position */ + ny = ((bd->zone->y + bd->zone->h) - cz->softkey.size); + + /* NB: not sure why yet, but on startup the border->y is reporting + * that it is already in this position...but it's actually not. + * So for now, just disable the ny check until this gets sorted out */ +// if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_SOFTKEY_LAYER) + e_border_layer_set(bd, POL_SOFTKEY_LAYER); +} + +static void +_policy_zone_layout_keyboard(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int ny, layer; + +// printf("\tLayout Keyboard\n"); + + /* grab minimum keyboard size */ + e_illume_border_min_get(bd, NULL, &cz->vkbd.size); + + /* no point in adjusting size or position if it's not visible */ + if (!bd->visible) return; + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != cz->vkbd.size)) + _policy_border_resize(bd, bd->zone->w, cz->vkbd.size); + + /* make sure it's in the correct position */ + ny = ((bd->zone->y + bd->zone->h) - cz->vkbd.size); + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* check layer according to fullscreen state */ + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + printf("Keyboard needs fullscreen\n"); + layer = POL_FULLSCREEN_LAYER; + } + else + layer = POL_KEYBOARD_LAYER; + + /* set layer if needed */ + if (bd->layer != layer) + e_border_layer_set(bd, layer); +} + +static void +_policy_zone_layout_home_single(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int ny, nh; + +// printf("\tLayout Home Single: %s\n", bd->client.icccm.class); + + /* no point in adjusting size or position if it's not visible */ + if ((!bd->new_client) && (!bd->visible)) return; + + /* make sure it's the required width & height */ + nh = (bd->zone->h - cz->indicator.size - cz->softkey.size); + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + ny = (bd->zone->y + cz->indicator.size); + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_HOME_LAYER) + e_border_layer_set(bd, POL_HOME_LAYER); +} + +static void +_policy_zone_layout_home_dual_top(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *home; + int ny, nh; + + /* no point in adjusting size or position if it's not visible */ + if ((!bd->new_client) && (!bd->visible)) return; + + /* set some defaults */ + ny = (bd->zone->y + cz->indicator.size); + nh = ((bd->zone->h - cz->indicator.size - cz->softkey.size) / 2); + + /* see if there are any other home windows */ + home = e_illume_border_home_get(bd->zone); + if (home) + { + if (bd != home) ny = (home->y + nh); + } + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_HOME_LAYER) + e_border_layer_set(bd, POL_HOME_LAYER); +} + +static void +_policy_zone_layout_home_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *home; + int iy, ny, nh; + +// printf("\tLayout Home Dual Custom: %s\n", bd->client.icccm.class); + + /* no point in adjusting size or position if it's not visible */ + if ((!bd->new_client) && (!bd->visible)) return; + + /* grab indicator position */ + e_illume_border_indicator_pos_get(bd->zone, NULL, &iy); + + /* set some defaults */ + ny = bd->zone->y; + nh = iy; + + /* see if there are any other home windows */ + home = e_illume_border_home_get(bd->zone); + if (home) + { + if (bd != home) + { + ny = (iy + cz->indicator.size); + nh = ((bd->zone->y + bd->zone->h) - ny - cz->softkey.size); + } + } + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_HOME_LAYER) + e_border_layer_set(bd, POL_HOME_LAYER); +} + +static void +_policy_zone_layout_home_dual_left(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *home; + int nx, nw, nh; + +// printf("\tLayout Home Dual Left: %s\n", bd->client.icccm.class); + + /* no point in adjusting size or position if it's not visible */ + if ((!bd->new_client) && (!bd->visible)) return; + + nh = (bd->zone->h - cz->indicator.size - cz->softkey.size); + + /* set some defaults */ + nx = bd->zone->x; + nw = (bd->zone->w / 2); + + /* see if there are any other home windows */ + home = e_illume_border_home_get(bd->zone); + if (home) + { + if (bd != home) nx = (home->x + nw); + } + + /* make sure it's the required width & height */ + if ((bd->w != nw) || (bd->h != nh)) + _policy_border_resize(bd, nw, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != nx) || (bd->y != (bd->zone->y + cz->indicator.size))) + _policy_border_move(bd, nx, (bd->zone->y + cz->indicator.size)); + + /* set layer if needed */ + if (bd->layer != POL_HOME_LAYER) + e_border_layer_set(bd, POL_HOME_LAYER); +} + +static void +_policy_zone_layout_fullscreen(E_Border *bd) +{ + int kh, ny, nh; + +// printf("\tLayout Fullscreen: %s\n", bd->client.icccm.name); + + /* grab keyboard safe region */ + e_illume_keyboard_safe_app_region_get(bd->zone, NULL, NULL, NULL, &kh); + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != kh)) + _policy_border_resize(bd, bd->zone->w, kh); + + /* set layer if needed */ + if (bd->layer != POL_FULLSCREEN_LAYER) + e_border_layer_set(bd, POL_FULLSCREEN_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_app_single(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *home; + int ky, kh, ny, nh; + +// printf("\tLayout App Single: %s\n", bd->client.icccm.name); + + if ((!bd->new_client) && (!bd->visible)) return; + + /* grab keyboard safe region */ + e_illume_keyboard_safe_app_region_get(bd->zone, NULL, &ky, NULL, &kh); + + /* make sure it's the required width & height */ + if (kh >= bd->zone->h) + nh = (kh - cz->indicator.size - cz->softkey.size); + else + nh = (kh - cz->indicator.size); + + /* resize if needed */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + ny = (bd->zone->y + cz->indicator.size); + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_APP_LAYER) + e_border_layer_set(bd, POL_APP_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_app_dual_top(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *b; + int kh, ny, nh; + +// printf("\tLayout App Dual Top: %s\n", bd->client.icccm.name); + + if ((!bd->new_client) && (!bd->visible)) return; + + /* set a default Y position */ + ny = (bd->zone->y + cz->indicator.size); + + if ((bd->focused) && + (bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)) + { + /* grab keyboard safe region */ + e_illume_keyboard_safe_app_region_get(bd->zone, NULL, NULL, NULL, &kh); + + nh = (kh - cz->indicator.size); + } + else + { + /* make sure it's the required width & height */ + nh = ((bd->zone->h - cz->indicator.size - cz->softkey.size) / 2); + } + + /* see if there is a border already there. if so, check placement based on + * virtual keyboard usage */ + b = e_illume_border_at_xy_get(bd->zone, bd->zone->x, ny); + if (b) + { + if (b != bd) + { + /* does this border need keyboard ? */ + if ((bd->focused) && + (bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)) + { + int h; + + /* move existing border to bottom if needed */ + h = ((bd->zone->h - cz->indicator.size - cz->softkey.size) / 2); + if ((b->x != b->zone->x) || (b->y != (ny + h))) + _policy_border_move(b, b->zone->x, (ny + h)); + + /* resize existing border if needed */ + if ((b->w != b->zone->w) || (b->h != h)) + _policy_border_resize(b, b->zone->w, h); + } + else + ny = b->y + nh; + } + } + + /* resize if needed */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_APP_LAYER) + e_border_layer_set(bd, POL_APP_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_app_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *app; + int iy, ny, nh; + +// printf("\tLayout App Dual Custom: %s\n", bd->client.icccm.class); + + if ((!bd->new_client) && (!bd->visible)) return; + + /* grab indicator position */ + e_illume_border_indicator_pos_get(bd->zone, NULL, &iy); + + /* set a default position */ + ny = bd->zone->y; + nh = iy; + + app = e_illume_border_at_xy_get(bd->zone, bd->zone->x, bd->zone->y); + if (app) + { + if (bd != app) + { + ny = (iy + cz->indicator.size); + nh = ((bd->zone->y + bd->zone->h) - ny - cz->softkey.size); + } + } + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_APP_LAYER) + e_border_layer_set(bd, POL_APP_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_app_dual_left(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *b; + int ky, kh, nx, nw; + +// printf("\tLayout App Dual Left: %s\n", bd->client.icccm.name); + + if ((!bd->new_client) && (!bd->visible)) return; + + /* grab keyboard safe region */ + e_illume_keyboard_safe_app_region_get(bd->zone, NULL, &ky, NULL, &kh); + + if (kh >= bd->zone->h) + kh = (kh - cz->indicator.size - cz->softkey.size); + else + kh = (kh - cz->indicator.size); + + /* set some defaults */ + nx = bd->zone->x; + nw = (bd->zone->w / 2); + + /* see if there is a border already there. if so, place at right */ + b = e_illume_border_at_xy_get(bd->zone, nx, (ky + cz->indicator.size)); + if (b) + { + if (bd != b) nx = b->x + nw; + } + + /* resize if needed */ + if ((bd->w != nw) || (bd->h != kh)) + _policy_border_resize(bd, nw, kh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != nx) || (bd->y != (ky + cz->indicator.size))) + _policy_border_move(bd, nx, (ky + cz->indicator.size)); + + /* set layer if needed */ + if (bd->layer != POL_APP_LAYER) + e_border_layer_set(bd, POL_APP_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_dialog(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *parent; + int mw, mh, nx, ny; + +// printf("\tLayout Dialog: %s\n", bd->client.icccm.name); + + /* NB: This policy ignores any ICCCM requested positions and centers the + * dialog on it's parent (if it exists) or on the zone */ + + /* grab minimum size */ + e_illume_border_min_get(bd, &mw, &mh); + + /* make sure it fits in this zone */ + if (mw > bd->zone->w) mw = bd->zone->w; + if (mh > bd->zone->h) mh = bd->zone->h; + + /* try to get this dialog's parent if it exists */ + parent = e_illume_border_parent_get(bd); + + /* if we have no parent, or we are in dual mode, then center on zone */ + /* NB: we check dual mode because if we are in dual mode, dialogs tend to + * be too small to be useful when positioned on the parent, so center + * on zone. We could check their size first here tho */ + if ((!parent) || (cz->mode.dual == 1)) + { + /* no parent or dual mode, center on screen */ + nx = (bd->zone->x + ((bd->zone->w - mw) / 2)); + ny = (bd->zone->y + ((bd->zone->h - mh) / 2)); + } + else + { + /* NB: there is an assumption here that the parent has already been + * layed out on screen. This could be bad. Needs Testing */ + + /* make sure we are not larger than the parent window */ + if (mw > parent->w) mw = parent->w; + if (mh > parent->h) mh = parent->h; + + /* center on parent */ + nx = (parent->x + ((parent->w - mw) / 2)); + ny = (parent->y + ((parent->h - mh) / 2)); + } + + /* make sure it's the required width & height */ + if ((bd->w != mw) || (bd->h != mh)) + _policy_border_resize(bd, mw, mh); + + /* make sure it's in the correct position */ + if ((bd->x != nx) || (bd->y != ny)) + _policy_border_move(bd, nx, ny); + + /* set layer if needed */ + if (bd->layer != POL_DIALOG_LAYER) + e_border_layer_set(bd, POL_DIALOG_LAYER); +} + +static void +_policy_zone_layout_splash(E_Border *bd, E_Illume_Config_Zone *cz) +{ + E_Border *parent; + int mw, mh, nx, ny; + + /* NB: This code is almost exactly the same as the dialog layout code + * (_policy_zone_layout_dialog) except for setting a different layer */ + +// printf("\tLayout Splash: %s\n", bd->client.icccm.name); + + /* NB: This policy ignores any ICCCM requested positions and centers the + * splash screen on it's parent (if it exists) or on the zone */ + + /* grab minimum size */ + e_illume_border_min_get(bd, &mw, &mh); + + /* make sure it fits in this zone */ + if (mw > bd->zone->w) mw = bd->zone->w; + if (mh > bd->zone->h) mh = bd->zone->h; + + /* if we have no parent, or we are in dual mode, then center on zone */ + /* NB: we check dual mode because if we are in dual mode, dialogs tend to + * be too small to be useful when positioned on the parent, + * so center on zone instead */ + if ((!parent) || (cz->mode.dual == 1)) + { + /* no parent or in dual mode, center on screen */ + nx = (bd->zone->x + ((bd->zone->w - mw) / 2)); + ny = (bd->zone->y + ((bd->zone->h - mh) / 2)); + } + else + { + /* NB: there is an assumption here that the parent has already been + * layed out on screen. This could be bad. Needs Testing */ + + /* make sure we are not larger than the parent window */ + if (mw > parent->w) mw = parent->w; + if (mh > parent->h) mh = parent->h; + + /* center on parent */ + nx = (parent->x + ((parent->w - mw) / 2)); + ny = (parent->y + ((parent->h - mh) / 2)); + } + + /* make sure it's the required width & height */ + if ((bd->w != mw) || (bd->h != mh)) + _policy_border_resize(bd, mw, mh); + + /* make sure it's in the correct position */ + if ((bd->x != nx) || (bd->y != ny)) + _policy_border_move(bd, nx, ny); + + /* set layer if needed */ + if (bd->layer != POL_SPLASH_LAYER) + e_border_layer_set(bd, POL_SPLASH_LAYER); +} + +static void +_policy_zone_layout_conformant_single(E_Border *bd, E_Illume_Config_Zone *cz) +{ + if ((!bd->new_client) && (!bd->visible)) return; + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != bd->zone->h)) + _policy_border_resize(bd, bd->zone->w, bd->zone->h); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != bd->zone->y)) + _policy_border_move(bd, bd->zone->x, bd->zone->y); + + /* set layer if needed */ + if (bd->layer != POL_CONFORMANT_LAYER) + e_border_layer_set(bd, POL_CONFORMANT_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_conformant_dual_top(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int nh, ny; + + /* according to the docs I have, conformant windows are always on the + * bottom in dual-top mode */ + + if ((!bd->new_client) && (!bd->visible)) return; + + /* set some defaults */ + nh = ((bd->zone->h - cz->indicator.size - cz->softkey.size) / 2); + ny = (bd->zone->y + cz->indicator.size) + nh; + nh += cz->softkey.size; + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != ny)) + _policy_border_move(bd, bd->zone->x, ny); + + /* set layer if needed */ + if (bd->layer != POL_CONFORMANT_LAYER) + e_border_layer_set(bd, POL_CONFORMANT_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_conformant_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int iy, nh; + +// printf("\tLayout Conformant Dual Custom: %s\n", bd->client.icccm.class); + + if ((!bd->new_client) && (!bd->visible)) return; + + /* grab indicator position */ + e_illume_border_indicator_pos_get(bd->zone, NULL, &iy); + + /* set some defaults */ + nh = ((bd->zone->y + bd->zone->h) - iy); + + /* make sure it's the required width & height */ + if ((bd->w != bd->zone->w) || (bd->h != nh)) + _policy_border_resize(bd, bd->zone->w, nh); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != bd->zone->x) || (bd->y != iy)) + _policy_border_move(bd, bd->zone->x, iy); + + /* set layer if needed */ + if (bd->layer != POL_CONFORMANT_LAYER) + e_border_layer_set(bd, POL_CONFORMANT_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + +static void +_policy_zone_layout_conformant_dual_left(E_Border *bd, E_Illume_Config_Zone *cz) +{ + int nw, nx; + + /* according to the docs I have, conformant windows are always on the + * left in dual-left mode */ + + if ((!bd->new_client) && (!bd->visible)) return; + + /* set some defaults */ + nw = (bd->zone->w / 2); + nx = (bd->zone->x); + + /* make sure it's the required width & height */ + if ((bd->w != nw) || (bd->h != bd->zone->h)) + _policy_border_resize(bd, nw, bd->zone->h); + + /* move to correct position (relative to zone) if needed */ + if ((bd->x != nx) || (bd->y != bd->zone->y)) + _policy_border_move(bd, nx, bd->zone->y); + + /* set layer if needed */ + if (bd->layer != POL_CONFORMANT_LAYER) + e_border_layer_set(bd, POL_CONFORMANT_LAYER); + + /* hide any apps/windows below this one */ + _policy_border_hide_below(bd); +} + + +/* policy functions */ +void +_policy_border_add(E_Border *bd) +{ +// printf("Border added: %s\n", bd->client.icccm.class); + + /* NB: this call sets an atom on the window that specifices the zone. + * the logic here is that any new windows created can access the zone + * window by a 'get' call. This is useful for elementary apps as they + * normally would not have access to the zone window. Typical use case + * is for indicator & softkey windows so that they can send messages + * that apply to their respective zone only. Example: softkey sends close + * messages (or back messages to cycle focus) that should pertain just + * to it's current zone */ + ecore_x_e_illume_zone_set(bd->client.win, bd->zone->black_win); + + /* ignore stolen borders. These are typically quickpanel or keyboards */ + if (bd->stolen) return; + + /* if this is a fullscreen window, than we need to hide indicator window */ + /* NB: we could use the e_illume_border_is_fullscreen function here + * but we save ourselves a function call this way */ + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + E_Border *ind; + + /* try to get the Indicator on this zone */ + if (ind = e_illume_border_indicator_get(bd->zone)) + { + /* we have the indicator, hide it if needed */ + if (ind->visible) e_border_hide(ind, 2); + } + } + + /* set focus on new border if we can */ + _policy_border_set_focus(bd); +} + +void +_policy_border_del(E_Border *bd) +{ +// printf("Border deleted: %s\n", bd->client.icccm.class); + + /* if this is a fullscreen window, than we need to show indicator window */ + /* NB: we could use the e_illume_border_is_fullscreen function here + * but we save ourselves a function call this way */ + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + E_Border *ind; + + /* try to get the Indicator on this zone */ + if (ind = e_illume_border_indicator_get(bd->zone)) + { + /* we have the indicator, show it if needed */ + if (!ind->visible) e_border_show(ind); + } + } + + /* show borders below this one */ + _policy_border_show_below(bd); +} + +void +_policy_border_focus_in(E_Border *bd) +{ +// printf("Border focus in: %s\n", bd->client.icccm.name); +} + +void +_policy_border_focus_out(E_Border *bd) +{ +// printf("Border focus out: %s\n", bd->client.icccm.name); + + /* NB: if we got this focus_out event on a deleted border, we check if + * it is a transient (child) of another window. If it is, then we + * transfer focus back to the parent window */ + if (e_object_is_del(E_OBJECT(bd))) + { + if (e_illume_border_is_dialog(bd)) + { + E_Border *parent; + + parent = e_illume_border_parent_get(bd); + if (parent) _policy_border_set_focus(parent); + } + } +} + +void +_policy_border_activate(E_Border *bd) +{ + E_Border *sft; + +// printf("Border Activate: %s\n", bd->client.icccm.name); + + /* NB: stolen borders may or may not need focus call...have to test */ +// if (bd->stolen) return; + + /* conformant windows hide the softkey */ + sft = e_illume_border_softkey_get(bd->zone); + if (sft) + { + if (e_illume_border_is_conformant(bd)) + { + if (sft->visible) e_border_hide(sft, 2); + } + else + { + if (!sft->visible) e_border_show(sft); + } + } + + /* set focus on new border is we can */ + _policy_border_set_focus(bd); +} + +void +_policy_border_post_fetch(E_Border *bd) +{ +// printf("Border post fetch\n"); + + /* NB: for this policy we disable all remembers set on a border */ + if (bd->remember) e_remember_del(bd->remember); + bd->remember = NULL; + + /* set this border to borderless */ +#ifdef DIALOG_USES_PIXEL_BORDER + if ((e_illume_border_is_dialog(bd)) && + (e_illume_border_parent_get(bd))) + eina_stringshare_replace(&bd->bordername, "pixel"); + else + bd->borderless = 1; +#else + bd->borderless = 1; +#endif + + /* tell E the border has changed */ + bd->client.border.changed = 1; +} + +void +_policy_border_post_assign(E_Border *bd) +{ +// printf("Border post assign\n"); + + bd->internal_no_remember = 1; + + /* do not allow client to change these properties */ + bd->lock_client_size = 1; + bd->lock_client_shade = 1; + bd->lock_client_maximize = 1; + bd->lock_client_location = 1; + bd->lock_client_stacking = 1; + + /* do not allow the user to change these properties */ + bd->lock_user_location = 1; + bd->lock_user_size = 1; + bd->lock_user_shade = 1; + + /* clear any centered states */ + /* NB: this is mainly needed for E's main config dialog */ + bd->client.e.state.centered = 0; + + /* lock the border type so user/client cannot change */ + bd->lock_border = 1; +} + +void +_policy_zone_layout(E_Zone *zone) +{ + E_Illume_Config_Zone *cz; + Eina_List *l; + E_Border *bd; + +// printf("Zone Layout: %d\n", zone->id); + + /* get the config for this zone */ + cz = e_illume_zone_config_get(zone->id); + + /* loop through border list and update layout */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + /* skip borders not on this zone */ + if (bd->zone != zone) continue; + + /* skip borders that are being deleted */ + if (e_object_is_del(E_OBJECT(bd))) continue; + + /* only update layout for this border if it really needs it */ + if ((!bd->new_client) && (!bd->changes.pos) && (!bd->changes.size) && + (!bd->changes.visible) && (!bd->pending_move_resize)) continue; + + /* are we laying out an indicator ? */ + if (e_illume_border_is_indicator(bd)) + _policy_zone_layout_indicator(bd, cz); + + /* are we layout out a quickpanel ? */ + else if (e_illume_border_is_quickpanel(bd)) + _policy_zone_layout_quickpanel(bd); + + /* are we laying out a softkey ? */ + else if (e_illume_border_is_softkey(bd)) + _policy_zone_layout_softkey(bd, cz); + + /* are we laying out a keyboard ? */ + else if (e_illume_border_is_keyboard(bd)) + _policy_zone_layout_keyboard(bd, cz); + + /* are we layout out a home window ? */ + else if (e_illume_border_is_home(bd)) + { + if (!cz->mode.dual) + _policy_zone_layout_home_single(bd, cz); + else + { + /* we are in dual-mode, check orientation */ + if (cz->mode.side == 0) + { + int ty; + + e_illume_border_indicator_pos_get(bd->zone, NULL, &ty); + if (ty <= bd->zone->y) + _policy_zone_layout_home_dual_top(bd, cz); + else + _policy_zone_layout_home_dual_custom(bd, cz); + } + else + _policy_zone_layout_home_dual_left(bd, cz); + } + } + + /* are we laying out a fullscreen window ? */ + /* NB: we could use the e_illume_border_is_fullscreen function here + * but we save ourselves a function call this way. */ + else if ((bd->fullscreen) || (bd->need_fullscreen)) + _policy_zone_layout_fullscreen(bd); + + /* are we laying out a splash screen ? */ + /* NB: we check splash before dialog so if a splash screen does not + * register as a splash, than the dialog trap should catch it */ + else if (e_illume_border_is_splash(bd)) + _policy_zone_layout_splash(bd, cz); + + /* are we laying out a dialog ? */ + else if (e_illume_border_is_dialog(bd)) + _policy_zone_layout_dialog(bd, cz); + + /* are we layout out a conformant window ? */ + else if (e_illume_border_is_conformant(bd)) + { + if (!cz->mode.dual) + _policy_zone_layout_conformant_single(bd, cz); + else + { + /* we are in dual-mode, check orientation */ + if (cz->mode.side == 0) + { + int ty; + + e_illume_border_indicator_pos_get(bd->zone, NULL, &ty); + if (ty <= bd->zone->y) + _policy_zone_layout_conformant_dual_top(bd, cz); + else + _policy_zone_layout_conformant_dual_custom(bd, cz); + } + else + _policy_zone_layout_conformant_dual_left(bd, cz); + } + } + + /* must be an app */ + else + { + /* are we in single mode ? */ + if (!cz->mode.dual) + _policy_zone_layout_app_single(bd, cz); + else + { + /* we are in dual-mode, check orientation */ + if (cz->mode.side == 0) + { + int ty; + + /* grab the indicator position so we can tell if it + * is in a custom position or not (user dragged it) */ + e_illume_border_indicator_pos_get(bd->zone, NULL, &ty); + if (ty <= bd->zone->y) + _policy_zone_layout_app_dual_top(bd, cz); + else + _policy_zone_layout_app_dual_custom(bd, cz); + } + else + _policy_zone_layout_app_dual_left(bd, cz); + } + } + + } +} + +void +_policy_zone_move_resize(E_Zone *zone) +{ + printf("Zone move resize\n"); + + /* zone size or position changed, tell layout to update */ + _policy_zone_layout(zone); +} + +void +_policy_zone_mode_change(E_Zone *zone, Ecore_X_Atom mode) +{ + E_Illume_Config_Zone *cz; + E_Border *bd; + int count; + +// printf("Zone mode change\n"); + + /* get the config for this zone */ + cz = e_illume_zone_config_get(zone->id); + + /* update config with new mode */ + if (mode == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE) + cz->mode.dual = 0; + else + { + cz->mode.dual = 1; + if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP) + cz->mode.side = 0; + else if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT) + cz->mode.side = 1; + } + e_config_save_queue(); + + /* lock indicator window from dragging if we need to */ + bd = e_illume_border_indicator_get(zone); + if (bd) + { + /* only dual-top mode can drag */ + if ((cz->mode.dual == 1) && (cz->mode.side == 0)) + { + /* only set locked if we need to */ + if (bd->client.illume.drag.locked != 0) + ecore_x_e_illume_drag_locked_set(bd->client.win, 0); + } + else + { + /* only set locked if we need to */ + if (bd->client.illume.drag.locked != 1) + ecore_x_e_illume_drag_locked_set(bd->client.win, 1); + } + } + + count = eina_list_count(e_illume_border_home_borders_get(zone)); + + /* create a new home window (if needed) for dual mode */ + if (cz->mode.dual == 1) + { + if (count < 2) + ecore_x_e_illume_home_new_send(zone->black_win); + } + else if (cz->mode.dual == 0) + { + /* if we went to single mode, delete any extra home windows */ + if (count >= 2) + { + E_Border *home; + + /* try to get a home window on this zone and remove it */ + if (home = e_illume_border_home_get(zone)) + ecore_x_e_illume_home_del_send(home->client.win); + } + } + + /* Need to trigger a layout update here */ + _policy_zone_layout_update(zone); +} + +void +_policy_zone_close(E_Zone *zone) +{ + E_Border *bd; + +// printf("Zone close\n"); + + /* make sure we have a focused border */ + if (!(bd = e_border_focused_get())) return; + + /* make sure focused border is on this zone */ + if (bd->zone != zone) return; + + /* close this border */ + e_border_act_close_begin(bd); + + /* revert focus to previous border (if possible) */ + _policy_focus_back(zone); +} + +void +_policy_drag_start(E_Border *bd) +{ +// printf("Drag start\n"); + + /* ignore stolen borders */ + if (bd->stolen) return; + + /* set property on this border to say we are dragging */ + ecore_x_e_illume_drag_set(bd->client.win, 1); + + /* set property on zone window that a drag is happening */ + ecore_x_e_illume_drag_set(bd->zone->black_win, 1); +} + +void +_policy_drag_end(E_Border *bd) +{ +// printf("Drag end\n"); + + /* ignore stolen borders */ + if (bd->stolen) return; + + /* set property on this border to say we are done dragging */ + ecore_x_e_illume_drag_set(bd->client.win, 0); + + /* set property on zone window that a drag is finished */ + ecore_x_e_illume_drag_set(bd->zone->black_win, 0); +} + +void +_policy_focus_back(E_Zone *zone) +{ + Eina_List *l, *fl = NULL; + E_Border *bd; + +// printf("Focus back\n"); + + /* loop the focus stack and check for borders on this zone */ + EINA_LIST_FOREACH(e_border_focus_stack_get(), l, bd) + { + /* not on this zone, skip */ + if (bd->zone != zone) continue; + + /* on this zone but being deleted, skip it */ + if (e_object_is_del(E_OBJECT(bd))) continue; + + /* doesn't accept or take focus, skip it */ + if ((!bd->client.icccm.accepts_focus) && + (!bd->client.icccm.take_focus)) continue; + + /* doesn't show in taskbar, skip it */ + if (bd->client.netwm.state.skip_taskbar) continue; + + /* add it to our list */ + fl = eina_list_append(fl, bd); + } + + /* if there are none on this zone then get out */ + if (!fl) return; + + /* if there is only one border then focus it and get out */ + if (eina_list_count(fl) < 2) + { + E_Border *fbd; + + if (fbd = fl->data) _policy_border_set_focus(fbd); + + /* cleanup our list variable */ + fl = eina_list_free(fl); + + return; + } + + /* loop focused borders on this zone */ + /* NB: This is done in reverse order so we get the most recently focused + * border first....saves time and iterations */ + EINA_LIST_REVERSE_FOREACH(fl, l, bd) + { + /* is this the currently focused border ? */ + if (bd == e_border_focused_get()) + { + E_Border *fbd; + + /* see if we have another border previous to this one */ + if (!(fbd = fl->next->data)) continue; + + /* focus the previous border */ + _policy_border_set_focus(fbd); + + /* we're done, get out */ + break; + } + } + + /* cleanup our list variable */ + fl = eina_list_free(fl); +} + +void +_policy_focus_forward(E_Zone *zone) +{ + printf("Focus forward\n"); +} + +void +_policy_focus_home(E_Zone *zone) +{ + E_Border *bd; + +// printf("Focus home\n"); + if (!(bd = e_illume_border_home_get(zone))) return; + + if (!bd->visible) e_border_show(bd); + + /* no point in calling set_focus here as home windows do not accept it + * anyway, so just raise */ + e_border_raise(bd); +} + +void +_policy_property_change(Ecore_X_Event_Window_Property *event) +{ +// printf("Property Change\n"); + + /* we are interested in state changes here */ + if (event->atom == ECORE_X_ATOM_NET_WM_STATE) + { + E_Border *bd, *ind; + + if (!(bd = e_border_find_by_client_window(event->win))) return; + + /* not interested in stolen or invisible borders */ + if ((bd->stolen) || (!bd->visible)) return; + + /* make sure the border has a name or class */ + /* NB: this check is here because some E borders get State Changes + * but do not have a name/class associated with them. Not entirely sure + * which ones they are, but I would guess Managers, Containers, or Zones. + * At any rate, we're not interested in those types of borders */ + if ((!bd->client.icccm.name) || (!bd->client.icccm.class)) return; + + /* NB: If we have reached this point, then it should be a fullscreen + * border that has toggled fullscreen on/off */ + + /* try to get the Indicator on this zone */ + if (!(ind = e_illume_border_indicator_get(bd->zone))) return; + + /* if we are fullscreen, hide the indicator...else we show it */ + /* NB: we could use the e_illume_border_is_fullscreen function here + * but we save ourselves a function call this way */ + if ((bd->fullscreen) || (bd->need_fullscreen)) + { + if (ind->visible) e_border_hide(ind, 2); + } + else + { + if (!ind->visible) e_border_show(ind); + } + } + else if (event->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY) + { + Eina_List *l; + E_Zone *zone; + E_Border *bd; + int x, y, w, h; + + /* make sure this property changed on a zone */ + if (!(zone = e_util_zone_window_find(event->win))) return; + + /* get the geometry. This is X round-trip :( */ + ecore_x_e_illume_indicator_geometry_get(zone->black_win, &x, &y, &w, &h); + + /* look for conformant borders */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + if (bd->zone != zone) continue; + if (!e_illume_border_is_conformant(bd)) continue; + /* set indicator geometry on conformant window */ + /* NB: This is needed so that conformant apps get told about + * the indicator size/position...else they have no way of + * knowing that the geometry has been updated */ + ecore_x_e_illume_indicator_geometry_set(bd->client.win, x, y, w, h); + } + } + else if (event->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY) + { + Eina_List *l; + E_Zone *zone; + E_Border *bd; + int x, y, w, h; + + /* make sure this property changed on a zone */ + if (!(zone = e_util_zone_window_find(event->win))) return; + + /* get the geometry. This is X round-trip :( */ + ecore_x_e_illume_softkey_geometry_get(zone->black_win, &x, &y, &w, &h); + + /* look for conformant borders */ + EINA_LIST_FOREACH(e_border_client_list(), l, bd) + { + if (bd->zone != zone) continue; + if (!e_illume_border_is_conformant(bd)) continue; + /* set softkey geometry on conformant window */ + /* NB: This is needed so that conformant apps get told about + * the softkey size/position...else they have no way of + * knowing that the geometry has been updated */ + ecore_x_e_illume_softkey_geometry_set(bd->client.win, x, y, w, h); + } + } + else if (!(strcmp(ecore_x_atom_name_get(event->atom), "ENLIGHTENMENT_SCALE"))) + { + Eina_List *ml; + E_Manager *man; + + EINA_LIST_FOREACH(e_manager_list(), ml, man) + { + Eina_List *cl; + E_Container *con; + + if (event->win != man->root) continue; + EINA_LIST_FOREACH(man->containers, cl, con) + { + Eina_List *zl; + E_Zone *zone; + + EINA_LIST_FOREACH(con->zones, zl, zone) + _policy_zone_layout_update(zone); + } + } + } +} diff --git a/src/modules/illume2/policies/illume/policy.h b/src/modules/illume2/policies/illume/policy.h new file mode 100644 index 000000000..8675bd660 --- /dev/null +++ b/src/modules/illume2/policies/illume/policy.h @@ -0,0 +1,34 @@ +#ifndef _POLICY_H +# define _POLICY_H + +/* define layer values here so we don't have to grep through code to change */ +# define POL_INDICATOR_LAYER 200 +# define POL_QUICKPANEL_LAYER 160 +# define POL_KEYBOARD_LAYER 150 +# define POL_FULLSCREEN_LAYER 140 +# define POL_DIALOG_LAYER 120 +# define POL_SPLASH_LAYER 120 +# define POL_SOFTKEY_LAYER 110 +# define POL_CONFORMANT_LAYER 100 +# define POL_APP_LAYER 100 +# define POL_HOME_LAYER 90 + +void _policy_border_add(E_Border *bd); +void _policy_border_del(E_Border *bd); +void _policy_border_focus_in(E_Border *bd); +void _policy_border_focus_out(E_Border *bd); +void _policy_border_activate(E_Border *bd); +void _policy_border_post_fetch(E_Border *bd); +void _policy_border_post_assign(E_Border *bd); +void _policy_zone_layout(E_Zone *zone); +void _policy_zone_move_resize(E_Zone *zone); +void _policy_zone_mode_change(E_Zone *zone, Ecore_X_Atom mode); +void _policy_zone_close(E_Zone *zone); +void _policy_drag_start(E_Border *bd); +void _policy_drag_end(E_Border *bd); +void _policy_focus_back(E_Zone *zone); +void _policy_focus_forward(E_Zone *zone); +void _policy_focus_home(E_Zone *zone); +void _policy_property_change(Ecore_X_Event_Window_Property *event); + +#endif