diff --git a/configure.ac b/configure.ac index f2b448e58..71a1ea4f7 100644 --- a/configure.ac +++ b/configure.ac @@ -1121,6 +1121,7 @@ src/modules/packagekit/module.desktop src/modules/wl_desktop_shell/module.desktop src/modules/wireless/module.desktop src/modules/time/module.desktop +src/modules/luncher/module.desktop data/xsession/enlightenment.desktop data/etc/sysactions.conf data/units/enlightenment.service diff --git a/src/bin/e_module.c b/src/bin/e_module.c index 25ec3a7b1..9bfc3170b 100644 --- a/src/bin/e_module.c +++ b/src/bin/e_module.c @@ -1009,6 +1009,7 @@ _e_module_whitelist_check(void) "ibox", "layout", "lokker", + "luncher", "mixer", "msgbus", "notification", diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk index 0962f9ee9..ed74f598c 100644 --- a/src/modules/Makefile.mk +++ b/src/modules/Makefile.mk @@ -94,6 +94,8 @@ include src/modules/Makefile_teamwork.mk include src/modules/Makefile_lokker.mk +include src/modules/Makefile_luncher.mk + include src/modules/Makefile_shot.mk include src/modules/Makefile_backlight.mk diff --git a/src/modules/Makefile_luncher.mk b/src/modules/Makefile_luncher.mk new file mode 100644 index 000000000..d867ff8de --- /dev/null +++ b/src/modules/Makefile_luncher.mk @@ -0,0 +1,23 @@ +EXTRA_DIST += src/modules/luncher/module.desktop.in \ +src/modules/luncher/e-module-luncher.edj +if USE_MODULE_IBAR +luncherdir = $(MDIR)/luncher +luncher_DATA = src/modules/luncher/e-module-luncher.edj \ + src/modules/luncher/module.desktop + + +luncherpkgdir = $(MDIR)/luncher/$(MODULE_ARCH) +luncherpkg_LTLIBRARIES = src/modules/luncher/module.la + +src_modules_luncher_module_la_LIBADD = $(MOD_LIBS) +src_modules_luncher_module_la_CPPFLAGS = $(MOD_CPPFLAGS) -Wall +src_modules_luncher_module_la_LDFLAGS = $(MOD_LDFLAGS) +src_modules_luncher_module_la_SOURCES = src/modules/luncher/mod.c \ + src/modules/luncher/luncher.h \ + src/modules/luncher/bar.c \ + src/modules/luncher/config.c + +PHONIES += luncher install-luncher +luncher: $(luncherpkg_LTLIBRARIES) $(luncher_DATA) +install-luncher: install-luncherDATA install-luncherpkgLTLIBRARIES +endif diff --git a/src/modules/conf_applications/e_int_config_apps.c b/src/modules/conf_applications/e_int_config_apps.c index 91ac0baf3..7e2267511 100644 --- a/src/modules/conf_applications/e_int_config_apps.c +++ b/src/modules/conf_applications/e_int_config_apps.c @@ -84,7 +84,7 @@ e_int_config_apps_ibar(Evas_Object *parent EINA_UNUSED, const char *params EINA_ e_user_dir_concat_static(buff, "applications/bar/default/.order"); data = E_NEW(E_Config_Data, 1); - data->title = eina_stringshare_add(_("IBar Applications")); + data->title = eina_stringshare_add(_("Launcher Applications")); data->dialog = eina_stringshare_add("applications/ibar_applications"); data->icon = eina_stringshare_add("preferences-applications-ibar"); data->filename = eina_stringshare_add(buff); @@ -98,7 +98,7 @@ e_int_config_apps_ibar_other(Evas_Object *parent EINA_UNUSED, const char *path) if (!path) return NULL; data = E_NEW(E_Config_Data, 1); - data->title = eina_stringshare_add(_("IBar Applications")); + data->title = eina_stringshare_add(_("Launcher Applications")); data->dialog = eina_stringshare_add("internal/ibar_other"); data->icon = eina_stringshare_add("preferences-applications-ibar"); data->filename = eina_stringshare_add(path); diff --git a/src/modules/conf_applications/e_mod_main.c b/src/modules/conf_applications/e_mod_main.c index 41ddea27d..cee7f37ba 100644 --- a/src/modules/conf_applications/e_mod_main.c +++ b/src/modules/conf_applications/e_mod_main.c @@ -30,7 +30,7 @@ e_modapi_init(E_Module *m) "user-bookmarks", e_int_config_apps_favs); e_configure_registry_item_add("applications/ibar_applications", 40, - _("IBar Applications"), NULL, + _("Launcher Applications"), NULL, "preferences-applications-ibar", e_int_config_apps_ibar); e_configure_registry_item_add("applications/screen_lock_applications", 45, @@ -59,7 +59,7 @@ e_modapi_init(E_Module *m) e_int_config_deskenv); e_configure_registry_category_add("internal", -1, _("Internal"), NULL, "enlightenment/internal"); - e_configure_registry_item_add("internal/ibar_other", -1, _("IBar Other"), + e_configure_registry_item_add("internal/ibar_other", -1, _("Launcher Other"), NULL, "preferences-system-windows", e_int_config_apps_ibar_other); diff --git a/src/modules/luncher/bar.c b/src/modules/luncher/bar.c new file mode 100644 index 000000000..187f38a14 --- /dev/null +++ b/src/modules/luncher/bar.c @@ -0,0 +1,1773 @@ +#include "luncher.h" +static Eina_List *handlers; +static Evas_Object *current_preview; +static Eina_Bool current_preview_menu; +static Eina_Bool _bar_icon_preview_show(void *data); + +static Evas_Object * +_bar_gadget_configure(Evas_Object *g) +{ + if (!luncher_config) return NULL; + if (luncher_config->config_dialog) return NULL; + Instance *inst = evas_object_data_get(g, "instance"); + return config_luncher(e_comp_object_util_zone_get(g), inst, EINA_TRUE); +} + +static const char * +_bar_location_get(Instance *inst) +{ + const char *s = "float"; + + E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main)); + E_Gadget_Site_Anchor anchor = e_gadget_site_anchor_get(e_gadget_site_get(inst->o_main)); + + if (anchor & E_GADGET_SITE_ANCHOR_LEFT) + { + if (anchor & E_GADGET_SITE_ANCHOR_TOP) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "top"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "left"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "left"; + break; + } + } + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "bottom"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "left"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "left"; + break; + } + } + else + s = "left"; + } + else if (anchor & E_GADGET_SITE_ANCHOR_RIGHT) + { + if (anchor & E_GADGET_SITE_ANCHOR_TOP) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "top"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "right"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "right"; + break; + } + } + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "bottom"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "right"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "right"; + break; + } + } + else + s = "right"; + } + else if (anchor & E_GADGET_SITE_ANCHOR_TOP) + s = "top"; + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + s = "bottom"; + else + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "bottom"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "left"; + break; + default: break; + } + } + return s; +} + +static Icon * +_bar_icon_match(Instance *inst, E_Client *ec) +{ + Icon *ic = NULL; + Eina_Bool has_desktop = EINA_FALSE; + + if (ec->exe_inst) + { + if (ec->exe_inst->desktop) + has_desktop = EINA_TRUE; + } + + if (has_desktop) + ic = eina_hash_find(inst->icons_desktop_hash, ec->exe_inst->desktop->orig_path); + if (has_desktop && !ic) + ic = eina_hash_find(inst->icons_clients_hash, ec); + if (!ic) + ic = eina_hash_find(inst->icons_clients_hash, ec); + + return ic; +} + +static void +_bar_instance_watch(void *data, E_Exec_Instance *ex, E_Exec_Watch_Type type) +{ + Icon *ic = data; + char buf[4096]; + + switch (type) + { + case E_EXEC_WATCH_STARTED: + if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e"); + ic->starting = EINA_FALSE; + if (!ic->execs) + { + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(ic->inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + } + if (!eina_list_data_find(ic->execs, ex)) + ic->execs = eina_list_append(ic->execs, ex); + break; + default: + break; + } +} + +static void +_bar_icon_del(Instance *inst, Icon *ic) +{ + inst->icons = eina_list_remove(inst->icons, ic); + evas_object_del(ic->o_layout); + evas_object_del(ic->o_icon); + eina_hash_del_by_data(inst->icons_desktop_hash, ic); + eina_hash_del_by_data(inst->icons_clients_hash, ic); + if (ic->desktop) + efreet_desktop_unref(ic->desktop); + eina_list_free(ic->execs); + eina_list_free(ic->clients); + eina_stringshare_del(ic->icon); + eina_stringshare_del(ic->key); + if (ic->exec) + e_exec_instance_watcher_del(ic->exec, _bar_instance_watch, ic); + ic->exec = NULL; + E_FREE(ic); +} + +static void +_bar_icon_menu_settings_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + elm_ctxpopup_dismiss(popup); + e_gadget_configure(ic->inst->o_main); +} + +static void +_bar_icon_menu_add_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + elm_ctxpopup_dismiss(popup); + e_order_append(ic->inst->order, ic->desktop); +} + +static void +_bar_icon_menu_remove_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + elm_ctxpopup_dismiss(popup); + e_order_remove(ic->inst->order, ic->desktop); +} + +static void +_bar_icon_menu_properties_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + elm_ctxpopup_dismiss(popup); + e_desktop_edit(ic->desktop); +} + +static void +_bar_icon_menu_action_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Efreet_Desktop_Action *action = (Efreet_Desktop_Action*)data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + elm_ctxpopup_dismiss(popup); + e_exec(e_zone_current_get(), NULL, action->exec, NULL, "luncher"); +} + +static void +_bar_icon_menu_icon_mouse_out(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + elm_layout_signal_emit(obj, "e,state,unfocused", "e"); +} + +static void +_bar_icon_menu_icon_mouse_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + elm_layout_signal_emit(obj, "e,state,focused", "e"); +} + +static Evas_Object * +_bar_icon_menu_item_new(Icon *ic, Evas_Object *popup, Evas_Object *parent, const char *name, const char *icon) +{ + const char *path = NULL, *k = NULL; + int len = 0; + Evas_Object *layout, *label, *img; + + layout = elm_layout_add(parent); + e_theme_edje_object_set(layout, "e/gadget/luncher/preview", + "e/gadget/luncher/preview"); + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_IN, _bar_icon_menu_icon_mouse_in, NULL); + evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_OUT, _bar_icon_menu_icon_mouse_out, NULL); + elm_layout_signal_emit(layout, "e,state,icon,menu", "e"); + elm_box_pack_end(parent, layout); + evas_object_data_set(layout, "popup", popup); + evas_object_show(layout); + + label = elm_label_add(layout); + elm_object_style_set(label, "luncher_preview"); + elm_label_ellipsis_set(label, EINA_TRUE); + elm_object_text_set(label, name); + evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_FILL); + elm_layout_content_set(layout, "e.swallow.title", label); + evas_object_show(label); + + img = elm_icon_add(layout); + evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, 1, 1); + if (!icon) + path = NULL; + else if (strncmp(icon, "/", 1) && !ecore_file_exists(icon)) + { + path = efreet_icon_path_find(e_config->icon_theme, icon, ic->inst->size); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", icon, ic->inst->size); + } + } + else if (ecore_file_exists(icon)) + { + path = icon; + } + if (!path) + { + char buf[4096]; + snprintf(buf, sizeof(buf), "e/icons/%s", icon); + if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf))) + { + path = e_theme_edje_file_get("base/theme/icons", buf); + k = buf; + } + else + { + path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"); + k = "e/icons/unknown"; + } + } + if (path && icon) + { + len = strlen(icon); + if ((len > 4) && (!strcasecmp(icon + len - 4, ".edj"))) + k = "icon"; + } + elm_image_file_set(img, path, k); + elm_layout_content_set(layout, "e.swallow.icon", img); + evas_object_show(img); + + elm_layout_sizing_eval(layout); + + return layout; +} + +static void +_bar_icon_drag_done(E_Drag *drag, int dropped) +{ + Instance *inst = e_object_data_get(E_OBJECT(drag)); + + efreet_desktop_unref(drag->data); + if (!inst) return; + if (!dropped) + bar_recalculate(inst); +} + +static void +_bar_icon_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data) +{ + Icon *ic = data; + Evas_Event_Mouse_Move *ev = event_data; + int dx, dy; + + if (!ic->drag.start) return; + + dx = ev->cur.output.x - ic->drag.x; + dy = ev->cur.output.y - ic->drag.y; + if (((dx * dx) + (dy * dy)) > + (e_config->drag_resist * e_config->drag_resist)) + { + E_Drag *d; + Evas_Object *o; + Evas_Coord x, y, w, h; + unsigned int size; + const char *drag_types[] = { "enlightenment/desktop" }; + + if (ic->preview) + { + evas_object_del(ic->preview_box); + ic->preview_box = NULL; + elm_ctxpopup_dismiss(ic->preview); + ic->preview = NULL; + current_preview = NULL; + current_preview_menu = EINA_FALSE; + ic->active = EINA_FALSE; + } + ic->drag.dnd = 1; + ic->drag.start = 0; + + evas_object_geometry_get(ic->o_icon, &x, &y, &w, &h); + d = e_drag_new(x, y, drag_types, 1, + ic->desktop, -1, NULL, _bar_icon_drag_done); + d->button_mask = evas_pointer_button_down_mask_get(e_comp->evas); + efreet_desktop_ref(ic->desktop); + size = MAX(w, h); + o = e_util_desktop_icon_add(ic->desktop, size, e_drag_evas_get(d)); + e_drag_object_set(d, o); + + e_drag_resize(d, w, h); + e_drag_start(d, ic->drag.x, ic->drag.y); + e_object_data_set(E_OBJECT(d), ic->inst); + if (ic->in_order) + e_order_remove(ic->inst->order, ic->desktop); + } +} + +static Eina_Bool +_bar_drag_timer(void *data) +{ + Icon *ic = data; + + ic->drag_timer = NULL; + ic->drag.start = 1; + return EINA_FALSE; +} + +static void +_bar_icon_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data) +{ + Icon *ic = data; + Evas_Event_Mouse_Up *ev = event_data; + + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + + if (ev->button == 1) + { + ic->drag.x = ev->output.x; + ic->drag.y = ev->output.y; + if (ic->drag_timer) + ecore_timer_del(ic->drag_timer); + ic->drag_timer = ecore_timer_add(.35, _bar_drag_timer, ic); + } + if (ev->button == 3) + { + Evas_Object *popup, *box, *item, *sep; + Eina_List *l = NULL; + Efreet_Desktop_Action *action; + E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(ic->inst->o_main)); + + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + + popup = elm_ctxpopup_add(e_comp->elm); + elm_object_style_set(popup, "noblock"); + evas_object_size_hint_min_set(popup, ic->inst->size, ic->inst->size); + + box = elm_box_add(popup); + evas_object_size_hint_align_set(box, 0, 0); + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + elm_box_horizontal_set(box, EINA_TRUE); + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + elm_box_horizontal_set(box, EINA_FALSE); + break; + default: + elm_box_horizontal_set(box, EINA_FALSE); + } + + if (ic->desktop) + { + if (ic->desktop->actions) + { + EINA_LIST_FOREACH(ic->desktop->actions, l, action) + { + item = _bar_icon_menu_item_new(ic, popup, box, action->name, action->icon); + evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_UP, _bar_icon_menu_action_clicked, action); + } + sep = elm_separator_add(box); + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + elm_separator_horizontal_set(item, EINA_TRUE); + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + elm_separator_horizontal_set(item, EINA_FALSE); + break; + default: + elm_separator_horizontal_set(item, EINA_FALSE); + } + elm_box_pack_end(box, sep); + evas_object_show(sep); + } + } + item = _bar_icon_menu_item_new(ic, popup, box, _("Icon Properties"), "preferences-applications"); + evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_UP, _bar_icon_menu_properties_clicked, ic); + if (ic->in_order) + { + item = _bar_icon_menu_item_new(ic, popup, box, _("Remove From Bar"), "list-remove"); + evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_UP, _bar_icon_menu_remove_clicked, ic); + } + else + { + item = _bar_icon_menu_item_new(ic, popup, box, _("Add To Bar"), "list-add"); + evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_UP, _bar_icon_menu_add_clicked, ic); + } + item = _bar_icon_menu_item_new(ic, popup, box, _("Luncher Settings"), "configure"); + evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_UP, _bar_icon_menu_settings_clicked, ic); + + elm_object_content_set(popup, box); + evas_object_show(box); + + e_gadget_util_ctxpopup_place(ic->inst->o_main, popup, ic->o_layout); + e_comp_object_util_autoclose(popup, NULL, NULL, NULL); + evas_object_layer_set(popup, E_LAYER_POPUP); + evas_object_show(popup); + } +} + +static void +_bar_icon_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data) +{ + Icon *ic = data; + Evas_Event_Mouse_Up *ev = event_data; + + if (ev->button == 1) + { + if (ic->drag_timer) + ecore_timer_del(ic->drag_timer); + if (ic->drag.dnd) + { + ic->drag.start = 0; + ic->drag.dnd = 0; + return; + } + } + if (ev->button == 1 && ic->desktop) + { + if (ic->desktop->type == EFREET_DESKTOP_TYPE_APPLICATION) + { + E_Exec_Instance *ex; + + ex = e_exec(e_zone_current_get(), ic->desktop, NULL, NULL, "luncher"); + ic->exec = ex; + e_exec_instance_watcher_add(ex, _bar_instance_watch, ic); + if (!ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,starting", "e"); + ic->starting = EINA_TRUE; + } + else if (ic->desktop->type == EFREET_DESKTOP_TYPE_LINK) + { + if (!strncasecmp(ic->desktop->url, "file:", 5)) + { + E_Action *act; + + act = e_action_find("fileman"); + if (act) + act->func.go(NULL, ic->desktop->url + 5); + } + } + } + else if (ev->button == 1 && !ic->in_order) + { + if (ic->preview) + { + evas_object_del(ic->preview_box); + ic->preview_box = NULL; + elm_ctxpopup_dismiss(ic->preview); + ic->preview = NULL; + } + current_preview = NULL; + current_preview_menu = EINA_FALSE; + _bar_icon_preview_show(ic); + } +} + +static Eina_Bool +_bar_icon_preview_hide(void *data) +{ + Icon *ic = data; + + ic->mouse_out_timer = NULL; + + if (!ic->preview) + return EINA_FALSE; + + evas_object_del(ic->preview_box); + ic->preview_box = NULL; + elm_ctxpopup_dismiss(ic->preview); + ic->preview = NULL; + current_preview = NULL; + current_preview_menu = EINA_FALSE; + ic->active = EINA_FALSE; + + return EINA_FALSE; +} + +static void +_bar_icon_preview_item_mouse_out(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + elm_layout_signal_emit(obj, "e,state,unfocused", "e"); +} + +static void +_bar_icon_preview_item_mouse_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + elm_layout_signal_emit(obj, "e,state,focused", "e"); +} + +static void +_bar_icon_preview_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + + if (current_preview_menu) + return; + if (ic->mouse_out_timer) + ecore_timer_del(ic->mouse_out_timer); + ic->mouse_out_timer = ecore_timer_add(0.75, _bar_icon_preview_hide, ic); +} + +static void +_bar_icon_preview_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + + if (ic->mouse_out_timer) + ecore_timer_del(ic->mouse_out_timer); + ic->mouse_out_timer = NULL; +} + +static void +_bar_icon_preview_menu_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + + evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _bar_icon_preview_menu_hide, ic); + if (ic) + { + if (ic->preview) + { + current_preview_menu = EINA_FALSE; + _bar_icon_preview_mouse_out(ic, NULL, NULL, NULL); + } + } +} + +static void +_bar_icon_preview_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data) +{ + E_Client *ec = data; + Evas_Event_Mouse_Up *ev = event_data; + Icon *ic = evas_object_data_get(current_preview, "icon"); + + if (ev->button == 3) + { + e_int_client_menu_show(ec, ev->canvas.x, ev->canvas.y, 0, ev->timestamp); + evas_object_event_callback_add(ec->border_menu->comp_object, EVAS_CALLBACK_HIDE, + _bar_icon_preview_menu_hide, ic); + current_preview_menu = EINA_TRUE; + return; + } + e_client_activate(ec, 1); + if (current_preview) + { + elm_ctxpopup_dismiss(current_preview); + } + current_preview = NULL; + current_preview_menu = EINA_FALSE; +} + +static void +_bar_icon_preview_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Evas_Object *img = data; + + evas_object_del(img); +} + +static void +_bar_icon_preview_client_add(Icon *ic, E_Client *ec) +{ + Evas_Object *layout, *label, *img; + + layout = elm_layout_add(ic->preview_box); + e_theme_edje_object_set(layout, "e/gadget/luncher/preview", + "e/gadget/luncher/preview"); + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_IN, + _bar_icon_preview_item_mouse_in, ic); + evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_OUT, + _bar_icon_preview_item_mouse_out, ic); + elm_box_pack_end(ic->preview_box, layout); + evas_object_show(layout); + + label = elm_label_add(layout); + elm_object_style_set(label, "luncher_preview"); + elm_label_ellipsis_set(label, EINA_TRUE); + elm_object_text_set(label, e_client_util_name_get(ec)); + evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_FILL); + elm_layout_content_set(layout, "e.swallow.title", label); + evas_object_show(label); + + img = e_comp_object_util_mirror_add(ec->frame); + edje_extern_object_aspect_set(img, EDJE_ASPECT_CONTROL_BOTH, ec->client.w, ec->client.h); + elm_layout_content_set(layout, "e.swallow.icon", img); + evas_object_show(img); + + if (!(ec->desk->visible) || (ec->iconic)) + elm_layout_signal_emit(layout, "e,state,invisible", "e"); + + evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_UP, + _bar_icon_preview_mouse_up, ec); + evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, + _bar_icon_preview_del, img); + elm_layout_sizing_eval(layout); +} + +static Eina_Bool +_bar_icon_preview_show(void *data) +{ + Icon *ic = data; + Eina_List *l, *ll; + E_Client *ec; + E_Exec_Instance *ex; + Eina_List *clients = NULL; + E_Gadget_Site_Orient orient; + int count = 0; + + if (!ic) + return EINA_FALSE; + ic->mouse_in_timer = NULL; + if (ic->drag.dnd) + return EINA_FALSE; + if (!ic->inst && !ic->inst->o_icon_con) + return EINA_FALSE; + + orient = e_gadget_site_orient_get(e_gadget_site_get(ic->inst->o_main)); + + if (current_preview) + { + elm_ctxpopup_dismiss(current_preview); + } + current_preview = NULL; + current_preview_menu = EINA_FALSE; + + if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients)) + return EINA_FALSE; + + ic->preview = elm_ctxpopup_add(e_comp->elm); + elm_object_style_set(ic->preview, "noblock"); + evas_object_size_hint_min_set(ic->preview, ic->inst->size, ic->inst->size); + evas_object_event_callback_add(ic->preview, EVAS_CALLBACK_MOUSE_IN, + _bar_icon_preview_mouse_in, ic); + evas_object_event_callback_add(ic->preview, EVAS_CALLBACK_MOUSE_OUT, + _bar_icon_preview_mouse_out, ic); + + ic->preview_box = elm_box_add(ic->preview); + evas_object_size_hint_align_set(ic->preview_box, 0, 0); + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + elm_box_horizontal_set(ic->preview_box, EINA_TRUE); + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + elm_box_horizontal_set(ic->preview_box, EINA_FALSE); + break; + default: + elm_box_horizontal_set(ic->preview_box, EINA_FALSE); + } + EINA_LIST_FOREACH(ic->execs, l, ex) + { + EINA_LIST_FOREACH(ex->clients, ll, ec) + clients = eina_list_append(clients, ec); + } + EINA_LIST_FOREACH(ic->clients, l, ec) + clients = eina_list_append(clients, ec); + + EINA_LIST_FREE(clients, ec) + { + if (!ec->netwm.state.skip_taskbar && !e_client_util_ignored_get(ec)) + { + if (!e_client_util_is_popup(ec)) + { + _bar_icon_preview_client_add(ic, ec); + + count++; + } + } + } + + if (!count) + { + evas_object_del(ic->preview_box); + ic->preview_box = NULL; + elm_ctxpopup_dismiss(ic->preview); + ic->preview = NULL; + return EINA_FALSE; + } + elm_object_content_set(ic->preview, ic->preview_box); + evas_object_show(ic->preview_box); + + e_gadget_util_ctxpopup_place(ic->inst->o_main, ic->preview, ic->o_layout); + evas_object_layer_set(ic->preview, E_LAYER_POPUP); + evas_object_show(ic->preview); + + evas_object_data_del(ic->preview, "icon"); + evas_object_data_set(ic->preview, "icon", ic); + current_preview = ic->preview; + + return EINA_FALSE; +} + +static void +_bar_icon_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + Eina_Bool clients = EINA_FALSE; + + elm_object_tooltip_show(obj); + elm_layout_signal_emit(ic->o_layout, "e,state,focused", "e"); + ic->active = EINA_TRUE; + + if (ic->mouse_out_timer) + ecore_timer_del(ic->mouse_out_timer); + ic->mouse_out_timer = NULL; + if (ic->mouse_in_timer) + ecore_timer_del(ic->mouse_in_timer); + if (eina_list_count(ic->execs) || eina_list_count(ic->clients)) + clients = EINA_TRUE; + if (current_preview && clients && !current_preview_menu) + { + Icon *icon = evas_object_data_get(current_preview, "icon"); + if (icon->preview) + { + evas_object_del(icon->preview_box); + icon->preview_box = NULL; + elm_ctxpopup_dismiss(icon->preview); + icon->preview = NULL; + } + current_preview = NULL; + current_preview_menu = EINA_FALSE; + _bar_icon_preview_show(ic); + } + else + ic->mouse_in_timer = ecore_timer_add(1.0, _bar_icon_preview_show, ic); +} + +static void +_bar_icon_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + + elm_object_tooltip_hide(obj); + elm_layout_signal_emit(ic->o_layout, "e,state,unfocused", "e"); + if (!ic->preview) + ic->active = EINA_FALSE; + if (ic->mouse_in_timer) + ecore_timer_del(ic->mouse_in_timer); + ic->mouse_in_timer = NULL; + if (ic->mouse_out_timer) + ecore_timer_del(ic->mouse_out_timer); + ic->mouse_out_timer = ecore_timer_add(0.45, _bar_icon_preview_hide, ic); +} + +static void +_bar_exec_new_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Icon *ic = data; + E_Client *ec = e_comp_object_client_get(obj); + + if (ic->preview) + _bar_icon_preview_client_add(ic, ec); + evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW, _bar_exec_new_show, ic); +} + +static Icon * +_bar_icon_add(Instance *inst, Efreet_Desktop *desktop, E_Client *non_desktop_client) +{ + const char *path = NULL, *k = NULL; + int len = 0; + Icon *ic; + const Eina_List *l; + + ic = E_NEW(Icon, 1); + if (desktop) + efreet_desktop_ref(desktop); + ic->desktop = desktop; + ic->inst = inst; + ic->preview = NULL; + ic->preview_box = NULL; + ic->mouse_in_timer = NULL; + ic->mouse_out_timer = NULL; + ic->active = EINA_FALSE; + ic->starting = EINA_FALSE; + ic->exec = NULL; + + ic->o_layout = elm_layout_add(inst->o_icon_con); + e_theme_edje_object_set(ic->o_layout, "e/gadget/luncher/icon", + "e/gadget/luncher/icon"); + evas_object_size_hint_min_set(ic->o_layout, inst->size, inst->size); + elm_box_pack_end(inst->o_icon_con, ic->o_layout); + evas_object_show(ic->o_layout); + + ic->o_icon = elm_icon_add(ic->o_layout); + E_EXPAND(ic->o_icon); + + ic->o_overlay = elm_icon_add(ic->o_layout); + E_EXPAND(ic->o_overlay); + + if (desktop) + { + if (!desktop->icon) + path = NULL; + else if (strncmp(desktop->icon, "/", 1) && !ecore_file_exists(desktop->icon)) + { + path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, inst->size); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", desktop->icon, inst->size); + } + } + else if (ecore_file_exists(desktop->icon)) + { + path = desktop->icon; + } + if (!path) + { + char buf[4096]; + snprintf(buf, sizeof(buf), "e/icons/%s", desktop->icon); + if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf))) + { + path = e_theme_edje_file_get("base/theme/icons", buf); + k = buf; + } + else + { + path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"); + k = "e/icons/unknown"; + } + } + if (path && desktop->icon && !k) + { + len = strlen(desktop->icon); + if ((len > 4) && (!strcasecmp(desktop->icon + len - 4, ".edj"))) + k = "icon"; + } + } + else if (non_desktop_client) + { + E_Client *ec = non_desktop_client; + if (!ec->internal_icon) + { + eina_stringshare_replace(&ic->icon, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown")); + eina_stringshare_replace(&ic->key, "e/icons/unknown"); + } + else + { + eina_stringshare_replace(&ic->icon, ec->internal_icon); + eina_stringshare_replace(&ic->key, ec->internal_icon_key); + } + if (strncmp(ic->icon, "/", 1)) + { + path = efreet_icon_path_find(e_config->icon_theme, ic->icon, inst->size); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", ic->icon, inst->size); + } + } + else if (ecore_file_exists(ic->icon)) + path = ic->icon; + if (path && !ic->key) + { + len = strlen(path); + if ((len > 4) && (!strcasecmp(path + len - 4, ".edj"))) + k = "icon"; + if (k) + eina_stringshare_replace(&ic->key, k); + } + else if (!path) + { + path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"); + k = "e/icons/unknown"; + } + else + k = ic->key; + } + elm_image_file_set(ic->o_icon, path, k); + + if (desktop) + elm_object_tooltip_text_set(ic->o_icon, desktop->name); + else if (non_desktop_client && non_desktop_client->icccm.class) + elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.class); + else if (non_desktop_client && non_desktop_client->icccm.name) + elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.name); + else if (non_desktop_client && non_desktop_client->icccm.title) + elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->icccm.title); + else if (non_desktop_client && non_desktop_client->netwm.name) + elm_object_tooltip_text_set(ic->o_icon, non_desktop_client->netwm.name); + else + elm_object_tooltip_text_set(ic->o_icon, _("Unknown")); + + elm_object_tooltip_orient_set(ic->o_icon, ELM_TOOLTIP_ORIENT_CENTER); + elm_object_tooltip_style_set(ic->o_icon, "luncher"); + evas_object_size_hint_aspect_set(ic->o_icon, EVAS_ASPECT_CONTROL_BOTH, 1, 1); + elm_layout_content_set(ic->o_layout, "e.swallow.icon", ic->o_icon); + evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_UP, + _bar_icon_mouse_up, ic); + evas_object_event_callback_priority_add(ic->o_icon, EVAS_CALLBACK_MOUSE_DOWN, 0, + _bar_icon_mouse_down, ic); + evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_MOVE, + _bar_icon_mouse_move, ic); + evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_IN, + _bar_icon_mouse_in, ic); + evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_OUT, + _bar_icon_mouse_out, ic); + evas_object_show(ic->o_icon); + + elm_image_file_set(ic->o_overlay, path, k); + evas_object_size_hint_aspect_set(ic->o_overlay, EVAS_ASPECT_CONTROL_BOTH, 1, 1); + elm_layout_content_set(ic->o_layout, "e.swallow.overlay", ic->o_overlay); + evas_object_show(ic->o_overlay); + + if (desktop) + eina_hash_add(inst->icons_desktop_hash, eina_stringshare_add(desktop->orig_path), ic); + else + eina_hash_add(inst->icons_clients_hash, non_desktop_client, ic); + + if (desktop) + { + l = e_exec_desktop_instances_find(desktop); + if (l) + { + char buf[4096]; + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + ic->execs = eina_list_clone(l); + } + } + else + ic->clients = eina_list_append(ic->clients, non_desktop_client); + elm_layout_sizing_eval(ic->o_layout); + return ic; +} + +static Eina_Bool +_bar_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client_Property *ev) +{ + Instance *inst = NULL; + Eina_List *l = NULL; + + EINA_LIST_FOREACH(luncher_instances, l, inst) + { + Icon *ic = NULL; + + if (ev->ec) + ic = _bar_icon_match(inst, ev->ec); + + if (ic) + { + if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e"); + ic->starting = EINA_FALSE; + if (ev->ec->exe_inst) + ic->execs = eina_list_remove(ic->execs, ev->ec->exe_inst); + if (ev->ec) + ic->clients = eina_list_remove(ic->clients, ev->ec); + if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients)) + { + elm_layout_signal_emit(ic->o_layout, "e,state,off", "e"); + if (!ic->in_order) + _bar_icon_del(inst, ic); + } + } + } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_bar_cb_exec_del(void *data EINA_UNUSED, int type EINA_UNUSED, E_Exec_Instance *ex) +{ + Instance *inst = NULL; + Eina_List *l = NULL; + E_Client *ec = NULL; + + EINA_LIST_FOREACH(ex->clients, l, ec) + { + if (!ec->netwm.state.skip_taskbar) + { + break; + } + } + EINA_LIST_FOREACH(luncher_instances, l, inst) + { + Icon *ic = NULL; + if (!inst || !inst->icons_desktop_hash) + return ECORE_CALLBACK_RENEW; + ic = eina_hash_find(inst->icons_desktop_hash, ex->desktop->orig_path); + if (ic) + { + if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e"); + ic->starting = EINA_FALSE; + ic->execs = eina_list_remove(ic->execs, ex); + ic->clients = eina_list_remove(ic->clients, ec); + if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients)) + { + elm_layout_signal_emit(ic->o_layout, "e,state,off", "e"); + if (!ic->in_order) + _bar_icon_del(inst, ic); + } + } + } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_bar_cb_exec_client_prop(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client_Property *ev) +{ + Instance *inst = NULL; + E_Client *ec = NULL; + Eina_List *l = NULL; + Eina_Bool skip; + Eina_Bool has_desktop = EINA_TRUE; + + if (e_client_util_ignored_get(ev->ec)) + return ECORE_CALLBACK_RENEW; + if ((!(ev->property & E_CLIENT_PROPERTY_NETWM_STATE)) && (!(ev->property & E_CLIENT_PROPERTY_ICON)) + && (!(ev->property & E_CLIENT_PROPERTY_URGENCY))) + return ECORE_CALLBACK_RENEW; + + if (!ev->ec->exe_inst) + has_desktop = EINA_FALSE; + if (ev->ec->exe_inst) + { + if (!ev->ec->exe_inst->desktop) + has_desktop = EINA_FALSE; + } + if (has_desktop) + { + skip = EINA_TRUE; + EINA_LIST_FOREACH(ev->ec->exe_inst->clients, l, ec) + { + if (!ec->netwm.state.skip_taskbar) + { + skip = EINA_FALSE; + break; + } + } + } + else + skip = ev->ec->netwm.state.skip_taskbar; + + EINA_LIST_FOREACH(luncher_instances, l, inst) + { + Icon *ic = NULL; + char buf[4096]; + + if (ev->ec) + ic = _bar_icon_match(inst, ev->ec); + + if (skip && !ic) continue; + if (!skip) + { + if (ic) + { + if ((ev->property & E_CLIENT_PROPERTY_URGENCY)) + { + if (ev->ec->urgent) + elm_layout_signal_emit(ic->o_layout, "e,state,urgent", "e"); + else + elm_layout_signal_emit(ic->o_layout, "e,state,normal", "e"); + return ECORE_CALLBACK_RENEW; + } + if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e"); + ic->starting = EINA_FALSE; + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + if (has_desktop) + { + if (!eina_list_data_find(ic->execs, ev->ec->exe_inst)) + ic->execs = eina_list_append(ic->execs, ev->ec->exe_inst); + } + else + { + if (!eina_list_data_find(ic->clients, ev->ec)) + ic->clients = eina_list_append(ic->clients, ev->ec); + } + } + else + { + if (has_desktop) + ic = _bar_icon_add(inst, ev->ec->exe_inst->desktop, NULL); + else + ic = _bar_icon_add(inst, NULL, ev->ec); + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + ic->in_order = EINA_FALSE; + inst->icons = eina_list_append(inst->icons, ic); + } + } + else + { + if (has_desktop) + ic->execs = eina_list_remove(ic->execs, ev->ec->exe_inst); + if (ev->ec) + ic->clients = eina_list_remove(ic->clients, ev->ec); + if (!eina_list_count(ic->execs) && !eina_list_count(ic->clients)) + { + if (!ic->in_order) + _bar_icon_del(inst, ic); + else + elm_layout_signal_emit(ic->o_layout, "e,state,off", "e"); + } + } + } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_bar_cb_exec_new(void *data EINA_UNUSED, int type, E_Exec_Instance *ex) +{ + Instance *inst = NULL; + E_Client *ec = NULL; + Eina_List *l = NULL; + Eina_Bool skip; + + if (type == E_EVENT_EXEC_NEW_CLIENT) + { + ec = eina_list_data_get(ex->clients); + skip = ec->netwm.state.skip_taskbar; + } + else + { + skip = EINA_TRUE; + EINA_LIST_FOREACH(ex->clients, l, ec) + { + if (!ec->netwm.state.skip_taskbar) + { + skip = EINA_FALSE; + break; + } + } + } + EINA_LIST_FOREACH(luncher_instances, l, inst) + { + Icon *ic = NULL; + char buf[4096]; + + if (ec) + ic = _bar_icon_match(inst, ec); + + if (ic) + { + if (skip) continue; + if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e"); + ic->starting = EINA_FALSE; + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + if (ex->desktop) + { + if (!eina_list_data_find(ic->execs, ex)) + ic->execs = eina_list_append(ic->execs, ex); + evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, + _bar_exec_new_show, ic); + } + else + { + if (!eina_list_data_find(ic->clients, ec)) + ic->clients = eina_list_append(ic->clients, ec); + evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, + _bar_exec_new_show, ic); + } + } + else + { + if (skip) continue; + if (ex->desktop) + ic = _bar_icon_add(inst, ex->desktop, NULL); + else + ic = _bar_icon_add(inst, NULL, ec); + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + ic->in_order = EINA_FALSE; + inst->icons = eina_list_append(inst->icons, ic); + } + } + return ECORE_CALLBACK_RENEW; +} + +static void +_bar_empty(Instance *inst) +{ + if (inst->icons) + { + Icon *ic; + + elm_box_clear(inst->o_icon_con); + EINA_LIST_FREE(inst->icons, ic) + _bar_icon_del(inst, ic); + eina_list_free(inst->icons); + inst->icons = NULL; + } +} + +static void +_bar_fill(Instance *inst) +{ + const Eina_Hash *execs = e_exec_instances_get(); + Eina_Iterator *it; + Eina_List *l, *ll, *lll; + E_Exec_Instance *ex; + Icon *ic; + char buf[4096]; + + if (inst->order) + { + Efreet_Desktop *desktop; + Eina_List *l; + + EINA_LIST_FOREACH(inst->order->desktops, l, desktop) + { + ic = _bar_icon_add(inst, desktop, NULL); + ic->in_order = EINA_TRUE; + inst->icons = eina_list_append(inst->icons, ic); + } + } + it = eina_hash_iterator_data_new(execs); + EINA_ITERATOR_FOREACH(it, l) + { + EINA_LIST_FOREACH(l, ll, ex) + { + E_Client *ec; + Eina_Bool skip = EINA_TRUE; + + EINA_LIST_FOREACH(ex->clients, lll, ec) + { + if (!ec->netwm.state.skip_taskbar) + { + skip = EINA_FALSE; + break; + } + if (skip) continue; + ic = _bar_icon_match(inst, ec); + if (ic) + { + if (!eina_list_data_find(ic->execs, ex)) + ic->execs = eina_list_append(ic->execs, ex); + continue; + } + ic = _bar_icon_add(inst, ex->desktop, NULL); + snprintf(buf, sizeof(buf), "e,state,on,%s", _bar_location_get(inst)); + elm_layout_signal_emit(ic->o_layout, buf, "e"); + ic->in_order = EINA_FALSE; + inst->icons = eina_list_append(inst->icons, ic); + } + } + } +} + +static void +_bar_resize_job(void *data) +{ + Instance *inst = data; + Eina_List *l; + Icon *ic; + E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main)); + Evas_Coord x, y, w, h, size; + + if (inst) + { + evas_object_geometry_get(inst->o_main, &x, &y, &w, &h); + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + size = h; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + size = w; + break; + default: + size = h; + } + inst->size = size; + EINA_LIST_FOREACH(inst->icons, l, ic) + { + const char *path = NULL, *key = NULL; + int len = 0; + + if (ic->desktop) + { + if (!ic->desktop->icon) + path = NULL; + else if (strncmp(ic->desktop->icon, "/", 1) && !ecore_file_exists(ic->desktop->icon)) + { + path = efreet_icon_path_find(e_config->icon_theme, ic->desktop->icon, inst->size); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", ic->desktop->icon, inst->size); + } + } + else if (ecore_file_exists(ic->desktop->icon)) + { + path = ic->desktop->icon; + } + if (!path) + { + elm_image_file_set(ic->o_icon, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + elm_image_file_set(ic->o_overlay, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + } + if (path && ic->desktop->icon) + { + len = strlen(ic->desktop->icon); + if ((len > 4) && (!strcasecmp(ic->desktop->icon + len - 4, ".edj"))) + key = "icon"; + + elm_image_file_set(ic->o_icon, path, key); + elm_image_file_set(ic->o_overlay, path, key); + } + } + else if (ic->icon) + { + if (strncmp(ic->icon, "/", 1) && !ecore_file_exists(ic->icon)) + { + path = efreet_icon_path_find(e_config->icon_theme, ic->icon, inst->size); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", ic->icon, inst->size); + } + } + else if (ecore_file_exists(ic->icon)) + { + path = ic->icon; + } + if (!path) + { + elm_image_file_set(ic->o_icon, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + elm_image_file_set(ic->o_overlay, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + } + else + { + elm_image_file_set(ic->o_icon, path, ic->key); + elm_image_file_set(ic->o_overlay, path, ic->key); + } + } + else + { + elm_image_file_set(ic->o_icon, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + elm_image_file_set(ic->o_overlay, e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"), + "e/icons/unknown"); + } + evas_object_size_hint_min_set(ic->o_layout, inst->size, inst->size); + } + inst->resize_job = NULL; + } +} + +static Eina_Bool +_bar_cb_update_icons(EINA_UNUSED void *data, EINA_UNUSED int ev_type, EINA_UNUSED void *ev) +{ + Instance *inst = NULL; + Eina_List *l = NULL; + + EINA_LIST_FOREACH(luncher_instances, l, inst) + { + if (inst->resize_job) return ECORE_CALLBACK_RENEW; + inst->resize_job = ecore_job_add(_bar_resize_job, inst); + } + return ECORE_CALLBACK_PASS_ON; +} + +static void +_bar_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + + if (inst->resize_job) return; + inst->resize_job = ecore_job_add(_bar_resize_job, inst); +} + +static void +_bar_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + + if (inst->drop_handler) + evas_object_del(inst->drop_handler); + luncher_instances = eina_list_remove(luncher_instances, inst); + free(inst); +} + +static void +_bar_drop_drop(void *data, const char *type, void *event_data) +{ + Instance *inst = data; + E_Event_Dnd_Drop *ev = event_data; + Efreet_Desktop *desktop = NULL; + Eina_List *l = NULL; + Icon *ic = NULL; + + evas_object_del(inst->place_holder); + inst->place_holder = NULL; + if (!strcmp(type, "enlightenment/desktop")) + desktop = ev->data; + else if (!strcmp(type, "enlightenment/border")) + { + E_Client *ec; + + ec = ev->data; + desktop = ec->desktop; + if (!desktop) + { + desktop = e_desktop_client_create(ec); + efreet_desktop_save(desktop); + e_desktop_edit(desktop); + } + } + else if (!strcmp(type, "text/uri-list")) + l = ev->data; + + ic = inst->drop_before; + if (ic) + { + if (desktop) + e_order_prepend_relative(inst->order, desktop, ic->desktop); + else + e_order_files_prepend_relative(inst->order, l, ic->desktop); + } + else + { + if (desktop) + e_order_append(inst->order, desktop); + else + e_order_files_append(inst->order, l); + } +} + +static void +_bar_drop_leave(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + + evas_object_del(inst->place_holder); + inst->place_holder = NULL; +} + +static void +_bar_drop_move(void *data, const char *type EINA_UNUSED, void *event_data) +{ + Instance *inst = data; + E_Event_Dnd_Move *ev = event_data; + Evas_Coord x = ev->x, y = ev->y; + Eina_List *l; + Icon *ic; + + EINA_LIST_FOREACH(inst->icons, l, ic) + { + Evas_Coord dx, dy, dw, dh; + + if (!ic->in_order) continue; + evas_object_geometry_get(ic->o_layout, &dx, &dy, &dw, &dh); + if (E_INSIDE(x, y, dx, dy, dw, dh)) + inst->drop_before = ic; + } + elm_box_unpack(inst->o_icon_con, inst->place_holder); + elm_box_pack_before(inst->o_icon_con, inst->place_holder, inst->drop_before->o_layout); +} + +static void +_bar_drop_enter(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + + inst->place_holder = evas_object_rectangle_add(evas_object_evas_get(inst->o_icon_con)); + evas_object_color_set(inst->place_holder, 0, 0, 0, 0); + evas_object_size_hint_min_set(inst->place_holder, inst->size, inst->size); + evas_object_size_hint_max_set(inst->place_holder, inst->size, inst->size); + evas_object_show(inst->place_holder); +} + +static void +_bar_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data) +{ + Instance *inst = data; + char buf[PATH_MAX]; + + if (inst->o_main != event_data) return; + if (e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", inst->cfg->dir) >= sizeof(buf)) + return; + + luncher_config->items = eina_list_remove(luncher_config->items, inst->cfg); + eina_stringshare_del(inst->cfg->dir); + eina_hash_free(inst->icons_desktop_hash); + eina_hash_free(inst->icons_clients_hash); + E_FREE(inst->cfg); +} + +static void +_bar_iconify_end(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED) +{ + E_Client *ec = data; + + evas_object_layer_set(ec->frame, ec->layer); + ec->layer_block = 0; + if (ec->iconic) + evas_object_hide(ec->frame); +} + +static Eina_Bool +_bar_iconify_start(void *data, Evas_Object *obj, const char *signal EINA_UNUSED) +{ + Instance *inst = data; + Icon *ic = NULL; + E_Client *ec; + int ox, oy, ow, oh; + + ec = e_comp_object_client_get(obj); + + if (ec) + ic = _bar_icon_match(inst, ec); + + if (!ic) return EINA_FALSE; + ec->layer_block = 1; + evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO); + evas_object_geometry_get(ic->o_layout, &ox, &oy, &ow, &oh); + e_comp_object_effect_set(ec->frame, "iconify/luncher"); + e_comp_object_effect_params_set(ec->frame, 1, (int[]){ec->x, ec->y, ec->w, ec->h, ox, oy, ow, oh}, 8); + e_comp_object_effect_params_set(ec->frame, 0, (int[]){!!strcmp(signal, "e,action,iconify")}, 1); + e_comp_object_effect_start(ec->frame, _bar_iconify_end, ec); + return EINA_TRUE; +} + +static void +_bar_anchor_changed_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + + if (inst && inst->o_icon_con) + { + _bar_empty(inst); + _bar_fill(inst); + } +} + +static void +_bar_order_update(void *data, E_Order *eo EINA_UNUSED) +{ + Instance *inst = data; + + bar_recalculate(inst); +} + +static void +_bar_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + char buf[PATH_MAX]; + const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" }; + E_Gadget_Site_Orient orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main)); + + inst->o_icon_con = elm_box_add(inst->o_main); + elm_box_homogeneous_set(inst->o_icon_con, EINA_TRUE); + E_EXPAND(inst->o_icon_con); + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + elm_box_horizontal_set(inst->o_icon_con, EINA_TRUE); + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + elm_box_horizontal_set(inst->o_icon_con, EINA_FALSE); + break; + default: + elm_box_horizontal_set(inst->o_icon_con, EINA_TRUE); + } + elm_layout_content_set(inst->o_main, "e.swallow.bar", inst->o_icon_con); + evas_object_show(inst->o_icon_con); + + evas_object_data_set(inst->o_main, "instance", inst); + evas_object_data_set(inst->o_icon_con, "instance", inst); + + e_gadget_configure_cb_set(inst->o_main, _bar_gadget_configure); + evas_object_smart_callback_del_full(obj, "gadget_created", _bar_created_cb, data); + + if (!inst->cfg->dir) + inst->cfg->dir = eina_stringshare_add("default"); + if (inst->cfg->dir[0] != '/') + e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order", + inst->cfg->dir); + else + eina_strlcpy(buf, inst->cfg->dir, sizeof(buf)); + + inst->order = e_order_new(buf); + e_order_update_callback_set(inst->order, _bar_order_update, inst); + + inst->iconify_provider = e_comp_object_effect_mover_add(80, "e,action,*iconify", + _bar_iconify_start, inst); + + _bar_fill(inst); + + inst->drop_handler = + e_gadget_drop_handler_add(inst->o_main, inst, + _bar_drop_enter, _bar_drop_move, + _bar_drop_leave, _bar_drop_drop, + drop, 3); + elm_layout_content_set(inst->o_main, "e.swallow.drop", inst->drop_handler); + evas_object_show(inst->drop_handler); + + evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_RESIZE, _bar_resize, inst); +} + +static Config_Item * +_conf_item_get(int *id) +{ + Config_Item *ci; + Eina_List *l; + + if (*id > 0) + { + EINA_LIST_FOREACH(luncher_config->items, l, ci) + if (*id == ci->id) return ci; + } + + ci = E_NEW(Config_Item, 1); + + ci->id = eina_list_count(luncher_config->items)+1; + ci->dir = eina_stringshare_add("default"); + luncher_config->items = eina_list_append(luncher_config->items, ci); + + return ci; +} + +EINTERN void +bar_recalculate(Instance *inst) +{ + if (inst && inst->o_icon_con) + { + _bar_empty(inst); + _bar_fill(inst); + } +} + +EINTERN void +bar_reorder(Instance *inst) +{ + char buf[PATH_MAX]; + + if (inst) + { + _bar_empty(inst); + if (!inst->cfg->dir) + inst->cfg->dir = eina_stringshare_add("default"); + if (inst->cfg->dir[0] != '/') + e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order", + inst->cfg->dir); + else + eina_strlcpy(buf, inst->cfg->dir, sizeof(buf)); + e_object_del(E_OBJECT(inst->order)); + inst->order = e_order_new(buf); + e_order_update_callback_set(inst->order, _bar_order_update, inst); + _bar_fill(inst); + } +} + +EINTERN Evas_Object * +bar_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient) +{ + Instance *inst; + + inst = E_NEW(Instance, 1); + inst->size = 0; + inst->resize_job = NULL; + inst->cfg = _conf_item_get(id); + *id = inst->cfg->id; + inst->icons_desktop_hash = eina_hash_string_superfast_new(NULL); + inst->icons_clients_hash = eina_hash_pointer_new(NULL); + inst->o_main = elm_layout_add(parent); + e_theme_edje_object_set(inst->o_main, "e/gadget/luncher/bar", + "e/gadget/luncher/bar"); + evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, _bar_del, inst); + evas_object_smart_callback_add(parent, "gadget_created", _bar_created_cb, inst); + evas_object_smart_callback_add(parent, "gadget_site_anchor", _bar_anchor_changed_cb, inst); + evas_object_smart_callback_add(parent, "gadget_removed", _bar_removed_cb, inst); + evas_object_show(inst->o_main); + + E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_ICON_THEME, + _bar_cb_update_icons, NULL); + E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_ICON_CACHE_UPDATE, + _bar_cb_update_icons, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_NEW, + _bar_cb_exec_new, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_NEW_CLIENT, + _bar_cb_exec_new, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY, + _bar_cb_exec_client_prop, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_EXEC_DEL, + _bar_cb_exec_del, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, + _bar_cb_client_remove, NULL); + + if (inst->cfg->id < 0) return inst->o_main; + luncher_instances = eina_list_append(luncher_instances, inst); + + current_preview = NULL; + current_preview_menu = EINA_FALSE; + + return inst->o_main; +} + diff --git a/src/modules/luncher/config.c b/src/modules/luncher/config.c new file mode 100644 index 000000000..73404ba66 --- /dev/null +++ b/src/modules/luncher/config.c @@ -0,0 +1,377 @@ +#include "luncher.h" + +static void +_config_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + luncher_config->list = NULL; + evas_object_del(luncher_config->config_dialog); + luncher_config->config_dialog = NULL; + e_config_save_queue(); +} + +static void +_config_source_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + const char *dir = elm_object_item_text_get(elm_list_selected_item_get(luncher_config->list)); + + if (!strcmp(inst->cfg->dir, dir)) + return; + if (inst->cfg->dir) eina_stringshare_del(inst->cfg->dir); + inst->cfg->dir = NULL; + if (dir) inst->cfg->dir = eina_stringshare_ref(dir); + bar_reorder(inst); +} + +static void +_config_populate_order_list(Evas_Object *list, Instance *inst) +{ + Eina_List *dirs; + char buf[4096], *file; + size_t len; + Elm_Object_Item *it; + + elm_list_clear(list); + + len = e_user_dir_concat_static(buf, "applications/bar"); + if (len + 2 >= sizeof(buf)) return; + dirs = ecore_file_ls(buf); + + buf[len] = '/'; + len++; + + EINA_LIST_FREE(dirs, file) + { + if (file[0] == '.') continue; + if (eina_strlcpy(buf + len, file, sizeof(buf) - len) >= sizeof(buf) - len) + continue; + if (ecore_file_is_dir(buf)) + { + it = elm_list_item_append(list, file, NULL, NULL, _config_source_changed, inst); + if ((inst->cfg->dir) && (!strcmp(inst->cfg->dir, file))) + elm_list_item_selected_set(it, EINA_TRUE); + } + free(file); + } + elm_list_go(list); +} + +static void +_config_source_cancel(void *data) +{ + Instance *inst = data; + + config_luncher(e_zone_current_get(), inst, luncher_config->bar); +} + +static void +_config_source_added(void *data, char *text) +{ + Instance *inst = data; + char buf[4096]; + char tmp[4096] = {0}; + FILE *f; + size_t len; + + len = e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", text); + if (len + sizeof("/.order") >= sizeof(buf)) return; + while (!ecore_file_exists(buf)) + { + ecore_file_mkdir(buf); + memcpy(buf + len, "/.order", sizeof("/.order")); + e_user_dir_concat_static(tmp, "applications/bar/default/.order"); + if (ecore_file_cp(tmp, buf)) break; + f = fopen(buf, "w"); + if (!f) break; + /* Populate this .order file with some defaults */ + snprintf(tmp, sizeof(tmp), + "terminology.desktop\n" + "sylpheed.desktop\n" + "firefox.desktop\n" + "openoffice.desktop\n" + "xchat.desktop\n" + "gimp.desktop\n"); + fwrite(tmp, sizeof(char), strlen(tmp), f); + fclose(f); + break; + } + config_luncher(e_zone_current_get(), inst, luncher_config->bar); +} + +static void +_config_source_deleted(void *data) +{ + char buf[4096]; + Instance *inst = data; + + if (e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", inst->cfg->dir) >= sizeof(buf)) + return; + if (ecore_file_is_dir(buf)) + ecore_file_recursive_rm(buf); + e_object_del(E_OBJECT(inst->order)); + config_luncher(e_zone_current_get(), inst, luncher_config->bar); +} + +static void +_config_source_add(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + + evas_object_del(luncher_config->config_dialog); + e_entry_dialog_show(_("Create new Luncher source"), "enlightenment", + _("Enter a name for this new source:"), "", NULL, NULL, + _config_source_added, _config_source_cancel, inst); +} + +static void +_config_source_del(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + char buf[4096]; + + evas_object_del(luncher_config->config_dialog); + snprintf(buf, sizeof(buf), _("You requested to delete \"%s\".

" + "Are you sure you want to delete this bar source?"), + inst->cfg->dir); + e_confirm_dialog_show(_("Are you sure you want to delete this bar source?"), + "application-exit", buf, _("Delete"), _("Keep"), + _config_source_deleted, _config_source_cancel, inst, inst, + NULL, NULL); +} + +static void +_config_contents(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + if (e_configure_registry_exists("applications/ibar_applications")) + { + char path[PATH_MAX]; + e_user_dir_snprintf(path, sizeof(path), "applications/bar/%s/.order", + inst->cfg->dir); + e_configure_registry_call("internal/ibar_other", NULL, path); + evas_object_del(popup); + } + +} + +static void +_config_create_icon(void *data, Evas_Object *obj, void *event_data EINA_UNUSED) +{ + Instance *inst = data; + Evas_Object *popup = evas_object_data_get(obj, "popup"); + + if (e_configure_registry_exists("applications/new_application")) + { + char path[PATH_MAX]; + e_user_dir_snprintf(path, sizeof(path), "applications/bar/%s/.order", + inst->cfg->dir); + e_configure_registry_call("applications/new_application", NULL, path); + evas_object_del(popup); + } +} + +static void +_icon_theme_file_set(Evas_Object *img, const char *icon) +{ + const char *path = NULL, *k = NULL; + int len = 0; + + if (!icon) + path = NULL; + else if (strncmp(icon, "/", 1) && !ecore_file_exists(icon)) + { + path = efreet_icon_path_find(e_config->icon_theme, icon, 48); + if (!path) + { + if (e_util_strcmp(e_config->icon_theme, "hicolor")) + path = efreet_icon_path_find("hicolor", icon, 48); + } + } + else if (ecore_file_exists(icon)) + { + path = icon; + } + if (!path) + { + char buf[4096]; + snprintf(buf, sizeof(buf), "e/icons/%s", icon); + if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf))) + { + path = e_theme_edje_file_get("base/theme/icons", buf); + k = buf; + } + else + { + path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown"); + k = "e/icons/unknown"; + } + } + if (path && icon) + { + len = strlen(icon); + if ((len > 4) && (!strcasecmp(icon + len - 4, ".edj"))) + k = "icon"; + } + elm_image_file_set(img, path, k); +} + +EINTERN Evas_Object * +config_luncher(E_Zone *zone, Instance *inst, Eina_Bool bar) +{ + Evas_Object *popup, *tb, *lbl, *fr, *box, *list; + Evas_Object *butbox, *sep, *hbox, *img, *but; + + luncher_config->bar = bar; + + popup = elm_popup_add(e_comp->elm); + E_EXPAND(popup); + elm_popup_allow_events_set(popup, 1); + elm_popup_scrollable_set(popup, 1); + + tb = elm_table_add(popup); + E_EXPAND(tb); + evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(tb); + elm_object_content_set(popup, tb); + + lbl = elm_label_add(tb); + evas_object_size_hint_weight_set(lbl, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(lbl, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_style_set(lbl, "marker"); + evas_object_show(lbl); + elm_object_text_set(lbl, _("Luncher Configuration")); + elm_table_pack(tb, lbl, 0, 0, 1, 1); + + box = elm_box_add(tb); + elm_box_horizontal_set(box, EINA_FALSE); + E_EXPAND(box); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(tb, box, 0, 1, 1, 1); + evas_object_show(box); + + fr = elm_frame_add(box); + elm_object_text_set(fr, _("Icon Order")); + E_EXPAND(fr); + evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, fr); + evas_object_show(fr); + + box = elm_box_add(fr); + elm_box_horizontal_set(box, EINA_FALSE); + E_EXPAND(box); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(box); + + hbox = elm_box_add(box); + elm_box_horizontal_set(hbox, EINA_TRUE); + elm_box_homogeneous_set(hbox, EINA_FALSE); + evas_object_size_hint_expand_set(hbox, 0.0, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, hbox); + evas_object_show(hbox); + + list = elm_list_add(hbox); + E_ALIGN(list, EVAS_HINT_FILL, EVAS_HINT_FILL); + E_WEIGHT(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_pack_end(hbox, list); + elm_list_select_mode_set(list, ELM_OBJECT_SELECT_MODE_ALWAYS); + elm_scroller_content_min_limit(list, 1, 1); + evas_object_show(list); + luncher_config->list = list; + _config_populate_order_list(list, inst); + + butbox = elm_box_add(hbox); + elm_box_horizontal_set(butbox, EINA_FALSE); + E_EXPAND(butbox); + evas_object_size_hint_align_set(butbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(hbox, butbox); + evas_object_show(butbox); + + sep = elm_separator_add(box); + elm_separator_horizontal_set(sep, EINA_TRUE); + elm_box_pack_end(box, sep); + evas_object_show(sep); + + img = elm_icon_add(butbox); + evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + _icon_theme_file_set(img, "list-add"); + evas_object_show(img); + + but = elm_button_add(butbox); + elm_object_part_content_set(but, "icon", img); + elm_object_text_set(but, _("Add")); + E_EXPAND(but); + evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_data_set(but, "popup", popup); + evas_object_smart_callback_add(but, "clicked", _config_source_add, inst); + elm_box_pack_end(butbox, but); + evas_object_show(but); + + img = elm_icon_add(butbox); + evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + _icon_theme_file_set(img, "list-remove"); + evas_object_show(img); + + but = elm_button_add(butbox); + elm_object_part_content_set(but, "icon", img); + elm_object_text_set(but, _("Delete")); + E_EXPAND(but); + evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_data_set(but, "popup", popup); + evas_object_smart_callback_add(but, "clicked", _config_source_del, inst); + elm_box_pack_end(butbox, but); + evas_object_show(but); + + hbox = elm_box_add(box); + elm_box_horizontal_set(hbox, EINA_TRUE); + elm_box_homogeneous_set(hbox, EINA_TRUE); + E_EXPAND(box); + evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, hbox); + evas_object_show(hbox); + + img = elm_icon_add(hbox); + evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + _icon_theme_file_set(img, "document-new"); + evas_object_show(img); + + but = elm_button_add(hbox); + elm_object_part_content_set(but, "icon", img); + elm_object_text_set(but, _("Create New Icon")); + E_EXPAND(but); + evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_data_set(but, "popup", popup); + evas_object_smart_callback_add(but, "clicked", _config_create_icon, inst); + elm_box_pack_end(hbox, but); + evas_object_show(but); + + img = elm_icon_add(hbox); + evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + _icon_theme_file_set(img, "list-add"); + evas_object_show(img); + + but = elm_button_add(hbox); + elm_object_part_content_set(but, "icon", img); + elm_object_text_set(but, _("Contents")); + E_EXPAND(but); + evas_object_size_hint_align_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_data_set(but, "popup", popup); + evas_object_smart_callback_add(but, "clicked", _config_contents, inst); + elm_box_pack_end(hbox, but); + evas_object_show(but); + + elm_object_content_set(fr, box); + + popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE); + evas_object_layer_set(popup, E_LAYER_POPUP); + evas_object_resize(popup, zone->w / 4, zone->h / 3); + e_comp_object_util_center(popup); + evas_object_show(popup); + e_comp_object_util_autoclose(popup, NULL, e_comp_object_util_autoclose_on_escape, NULL); + evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _config_close, NULL); + + return luncher_config->config_dialog = popup; +} + diff --git a/src/modules/luncher/e-module-luncher.edj b/src/modules/luncher/e-module-luncher.edj new file mode 100644 index 000000000..f2dd5d4bb Binary files /dev/null and b/src/modules/luncher/e-module-luncher.edj differ diff --git a/src/modules/luncher/luncher.h b/src/modules/luncher/luncher.h new file mode 100644 index 000000000..7ab9c1dc3 --- /dev/null +++ b/src/modules/luncher/luncher.h @@ -0,0 +1,87 @@ +#ifndef LUNCHER_H +#define LUNCHER_H + +#include "e.h" + +E_API extern E_Module_Api e_modapi; + +E_API void *e_modapi_init (E_Module *m); +E_API int e_modapi_shutdown (E_Module *m); +E_API int e_modapi_save (E_Module *m); + +typedef struct _Config Config; +typedef struct _Config_Item Config_Item; +typedef struct _Instance Instance; +typedef struct _Icon Icon; + +struct _Config +{ + Eina_List *items; + + E_Module *module; + Evas_Object *config_dialog; + Evas_Object *list; + Eina_Bool bar; +}; + +struct _Config_Item +{ + int id; + Eina_Stringshare *dir; +}; + +struct _Instance +{ + Evas_Object *o_main; + Evas_Object *o_icon_con; + E_Order *order; + Config_Item *cfg; + Eina_List *icons; + Eina_Hash *icons_desktop_hash; + Eina_Hash *icons_clients_hash; + Evas_Coord size; + Ecore_Job *resize_job; + E_Comp_Object_Mover *iconify_provider; + Evas_Object *drop_handler; + Evas_Object *place_holder; + Icon *drop_before; +}; + +struct _Icon +{ + Instance *inst; + Evas_Object *o_layout; + Evas_Object *o_icon; + Evas_Object *o_overlay; + Evas_Object *preview; + Evas_Object *preview_box; + E_Exec_Instance *exec; + Efreet_Desktop *desktop; + Eina_List *execs; + Eina_List *clients; + Ecore_Timer *mouse_in_timer; + Ecore_Timer *mouse_out_timer; + Ecore_Timer *drag_timer; + Eina_Stringshare *icon; + Eina_Stringshare *key; + Eina_Bool in_order; + Eina_Bool active; + Eina_Bool starting; + struct + { + unsigned char start : 1; + unsigned char dnd : 1; + int x, y; + } drag; +}; + +EINTERN Evas_Object *config_luncher(E_Zone *zone, Instance *inst, Eina_Bool bar); +EINTERN Evas_Object *bar_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient); +EINTERN void bar_reorder(Instance *inst); +EINTERN void bar_recalculate(Instance *inst); + +extern Config *luncher_config; +extern Eina_List *luncher_instances; +extern E_Module *module; + +#endif diff --git a/src/modules/luncher/mod.c b/src/modules/luncher/mod.c new file mode 100644 index 000000000..91109f92e --- /dev/null +++ b/src/modules/luncher/mod.c @@ -0,0 +1,87 @@ +#include "luncher.h" +static E_Config_DD *conf_edd = NULL; +static E_Config_DD *conf_item_edd = NULL; +Eina_List *luncher_instances = NULL; +E_Module *module = NULL; +Config *luncher_config = NULL; + +EINTERN void +luncher_init(void) +{ + conf_item_edd = E_CONFIG_DD_NEW("Luncher_Config_Item", Config_Item); +#undef T +#undef D +#define T Config_Item +#define D conf_item_edd + E_CONFIG_VAL(D, T, id, INT); + E_CONFIG_VAL(D, T, dir, STR); + + conf_edd = E_CONFIG_DD_NEW("Luncher_Config", Config); +#undef T +#undef D +#define T Config +#define D conf_edd + E_CONFIG_LIST(D, T, items, conf_item_edd); + + luncher_config = e_config_domain_load("module.luncher", conf_edd); + + if (!luncher_config) + { + Config_Item *ci; + + luncher_config = E_NEW(Config, 1); + ci = E_NEW(Config_Item, 1); + ci->id = 0; + ci->dir = eina_stringshare_add("default"); + luncher_config->items = eina_list_append(luncher_config->items, ci); + } + e_gadget_type_add("Luncher Bar", bar_create, NULL); +} + +EINTERN void +luncher_shutdown(void) +{ + if (luncher_config) + { + Config_Item *ci; + EINA_LIST_FREE(luncher_config->items, ci) + { + eina_stringshare_del(ci->dir); + free(ci); + } + E_FREE(luncher_config); + } + E_CONFIG_DD_FREE(conf_edd); + E_CONFIG_DD_FREE(conf_item_edd); + + e_gadget_type_del("Luncher Bar"); +} + +E_API E_Module_Api e_modapi = +{ + E_MODULE_API_VERSION, + "Luncher" +}; + +E_API void * +e_modapi_init(E_Module *m) +{ + luncher_init(); + + module = m; + return m; +} + +E_API int +e_modapi_shutdown(E_Module *m EINA_UNUSED) +{ + luncher_shutdown(); + return 1; +} + +E_API int +e_modapi_save(E_Module *m EINA_UNUSED) +{ + e_config_domain_save("module.luncher", conf_edd, luncher_config); + return 1; +} diff --git a/src/modules/luncher/module.desktop.in b/src/modules/luncher/module.desktop.in new file mode 100644 index 000000000..75c268c50 --- /dev/null +++ b/src/modules/luncher/module.desktop.in @@ -0,0 +1,37 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Link +Name=Luncher +Name[ca]=Luncher +Name[cs]=Lišta spouštěčů +Name[de]=Luncher +Name[eo]=Breto Luncher +Name[fi]=Luncher +Name[fr]=Luncher +Name[gl]=Luncher +Name[ja]=Luncher +Name[ms]=Luncher +Name[pl]=Luncher +Name[ru]=Luncher +Name[sr]=И-трака +Name[tr]=Luncher +Comment=Iconic application launcher. +Comment[ca]=Barra d'icones per a executar aplicacions. +Comment[cs]=Lišta se spouštěči. +Comment[de]=Symbolbasierter Anwendungsstarter. +Comment[el]=Εικονικός εκκινητής εφαρμογών. +Comment[eo]=Lanĉilo de piktograma aplikaĵo. +Comment[es]=Lanzador de aplicaciones con íconos. +Comment[fi]=Ikoninen sovelluskäynnistin. +Comment[fr]=Barre d'icones permettant de lancer des applications. +Comment[gl]=Unha barra de iconas para iniciar aplicativos. +Comment[hu]=Ikonokkal bővíthető alkalmazásindító modul. +Comment[it]=Una barra di icone per il lancio di applicazioni. +Comment[ja]=Iconic アプリケーションランチャー +Comment[ms]=Pelancar aplikasi ikonik +Comment[pt]=Barra para iniciar aplicações +Comment[ru]=Панель для запуска приложений, представленных в виде значков. +Comment[sr]=Трака иконица покретача програма. +Comment[tr]=Uygulama başlatıcı. +Icon=e-module-ibar +X-Enlightenment-ModuleType=utils