enlightenment-module-engage/src/ng_launcher.c

605 lines
14 KiB
C

#include "e_mod_main.h"
/*
TODO
- update on icon changes
*/
static void _box_fill (Ngi_Box *box);
static void _app_change_cb (void *data, E_Order *eo);
static void _item_new (Ngi_Box *box, Efreet_Desktop *dekstop, int instant, Ngi_Item_Launcher *after);
static void _item_fill (Ngi_Item_Launcher *it);
static void _item_cb_free (Ngi_Item *it);
static void _item_cb_drag_start (Ngi_Item *it);
static void _item_cb_mouse_up (Ngi_Item *it, Ecore_Event_Mouse_Button *ev);
static void _item_cb_mouse_down (Ngi_Item *it, Ecore_Event_Mouse_Button *ev);
static void _cb_drop_enter (void *data, const char *type, void *event_info);
static void _cb_drop_leave (void *data, const char *type, void *event_info);
static void _cb_drop_move (void *data, const char *type, void *event_info);
static void _cb_drop_end (void *data, const char *type, void *event_info);
static Eina_Bool _cb_icons_update(void *data, int type, void *event);
void
ngi_launcher_new(Ng *ng, Config_Box *cfg)
{
char buf[4096];
Ecore_Event_Handler *h;
Ngi_Box *box = ngi_box_new(ng);
box->cfg = cfg;
cfg->box = box;
const char *drop[] =
{ "enlightenment/desktop",
"enlightenment/border",
"text/uri-list" };
box->drop_handler = e_drop_handler_add
(ng->win->drop_win, box,
_cb_drop_enter, _cb_drop_move,
_cb_drop_leave, _cb_drop_end,
drop, 3, 0, 0, 0, 0);
h = ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME, _cb_icons_update, box);
if (h) box->handlers = eina_list_append(box->handlers, h);
h = ecore_event_handler_add(EFREET_EVENT_ICON_CACHE_UPDATE, _cb_icons_update, box);
if (h) box->handlers = eina_list_append(box->handlers, h);
h = ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _cb_icons_update, box);
if (h) box->handlers = eina_list_append(box->handlers, h);
if (!cfg->launcher_app_dir || strlen(cfg->launcher_app_dir) == 0)
return;
if (cfg->launcher_app_dir[0] != '/')
{
snprintf(buf, sizeof(buf), "%s/.e/e/applications/bar/%s/.order",
e_user_homedir_get(), cfg->launcher_app_dir);
}
else
snprintf(buf, sizeof(buf), "%s", cfg->launcher_app_dir);
box->apps = e_order_new(buf);
e_order_update_callback_set(box->apps, _app_change_cb, box);
_box_fill(box);
}
void
ngi_launcher_remove(Ngi_Box *box)
{
Ecore_Event_Handler *h;
e_drop_handler_del(box->drop_handler);
if (box->apps)
{
e_order_update_callback_set(box->apps, NULL, NULL);
e_object_del(E_OBJECT(box->apps));
}
EINA_LIST_FREE(box->handlers, h)
ecore_event_handler_del(h);
ngi_box_free(box);
}
static void
_box_fill(Ngi_Box *box)
{
Efreet_Desktop *desktop;
Eina_List *l;
if (!box->apps)
return;
ngi_freeze(box->ng);
EINA_LIST_FOREACH(box->apps->desktops, l, desktop)
_item_new(box, desktop, 1, NULL);
ngi_thaw(box->ng);
}
static Eina_Bool
_cb_icons_update(void *data, int type, void *event)
{
Ngi_Box *box = (Ngi_Box *)data;
Eina_List *l;
Ngi_Item_Launcher *it;
EINA_LIST_FOREACH(box->items, l, it)
_item_fill(it);
return ECORE_CALLBACK_PASS_ON;
}
static void
_app_change_cb(void *data, E_Order *eo)
{
Ngi_Box *box = (Ngi_Box *)data;
if (box->item_drop)
return;
while(box->items)
ngi_item_free(box->items->data);
_box_fill(box);
}
/* ******************************* LAUNCHER DROP HANDLER ******************** */
static Ngi_Item *
_drop_item_new(Ngi_Box *box)
{
Ngi_Item *it;
it = (Ngi_Item*)E_NEW(Ngi_Item_Launcher, 1);
it->box = box;
ngi_item_show(it, 0);
it->delete_me = EINA_TRUE;
return it;
}
static void
_drop_handle_move(Ngi_Box *box, int x, int y)
{
Ngi_Item *item;
Ngi_Item_Launcher *it, *it2;
Eina_List *l;
if (box->ng->horizontal)
box->ng->pos = x + box->ng->size/2 - box->ng->zone->x;
else
box->ng->pos = y + box->ng->size/2 - box->ng->zone->y;
item = ngi_item_at_position_get(box->ng);
if (item && (item->box != box))
{
l = eina_list_last(box->items);
if (l && (it = l->data) && (!it->app)) return;
ngi_item_remove(box->item_drop);
box->item_drop = _drop_item_new(box);
box->items = eina_list_append(box->items, box->item_drop);
}
else if (item && item->box == box)
{
it = (Ngi_Item_Launcher*)item;
l = eina_list_data_find_list(box->items, it);
if (l) it2 = eina_list_data_get(l->prev);
if (it->app && (!it2 || it2->app))
{
ngi_item_remove(box->item_drop);
box->item_drop = _drop_item_new(box);
box->items = eina_list_prepend_relative(box->items, box->item_drop, it);
}
}
}
static void
_cb_drop_enter(void *data, const char *type, void *event_info)
{
E_Event_Dnd_Enter *ev = (E_Event_Dnd_Enter *)event_info;
Ngi_Box *box = (Ngi_Box *)data;
if (!strcmp(type, "text/uri-list"))
return;
_drop_handle_move(box, ev->x, ev->y);
box->ng->dnd = 1;
ngi_mouse_in(box->ng);
}
static void
_cb_drop_move(void *data, const char *type, void *event_info)
{
E_Event_Dnd_Move *ev = (E_Event_Dnd_Move *)event_info;
Ngi_Box *box = (Ngi_Box *)data;
if (!strcmp(type, "text/uri-list"))
return;
_drop_handle_move(box, ev->x, ev->y);
ngi_thaw(box->ng);
}
static void
_cb_drop_leave(void *data, const char *type, void *event_info)
{
Ngi_Box *box = (Ngi_Box *)data;
if (!strcmp(type, "text/uri-list"))
return;
if (box->item_drop)
ngi_item_remove(box->item_drop);
box->item_drop = NULL;
ngi_reposition(box->ng);
ngi_input_extents_calc(box->ng);
box->ng->dnd = 0;
ngi_mouse_out(box->ng);
}
static void
_cb_drop_end(void *data, const char *type, void *event_info)
{
E_Event_Dnd_Drop *ev = (E_Event_Dnd_Drop *)event_info;
Ngi_Box *box = data;
Efreet_Desktop *app = NULL;
Ngi_Item_Launcher *it = NULL;
Eina_List *l;
if (!strcmp(type, "enlightenment/desktop"))
{
app = (Efreet_Desktop *)ev->data;
}
else if (!strcmp(type, "enlightenment/border"))
{
E_Border *bd = (E_Border *)ev->data;
app = bd->desktop;
if (bd->internal)
{
const char *class = bd->client.icccm.class;
if ((class) && (!strncmp(class, "e_fwin::", 8)) &&
(ecore_file_exists(class+8)))
{
const char *file = class+8;
char buf[PATH_MAX];
if (!app)
{
app = e_desktop_border_create(bd);
if (app->name) free(app->name);
app->name = strdup(ecore_file_file_get(file));
if (app->icon) free(app->icon);
app->icon = strdup("folder");
if (app->comment)free(app->comment);
app->comment = strdup(D_("Open Directory"));
if (app->exec) free(app->exec);
snprintf(buf, PATH_MAX, "enlightenment_remote -efm-open-dir %s", file);
app->exec = strdup(buf);
efreet_desktop_save(app);
}
}
}
else if (!app)
{
app = e_desktop_border_create(bd);
efreet_desktop_save(app);
e_desktop_edit(e_container_current_get(e_manager_current_get()), app);
}
}
else if (!strcmp(type, "text/uri-list"))
return;
if (!app)
return;
l = eina_list_data_find_list(box->items, box->item_drop);
if (l) it = eina_list_data_get(l->next);
if (box->item_drop)
ngi_item_free(box->item_drop);
if (it && it->app)
e_order_prepend_relative(box->apps, app, it->app);
else
e_order_append(box->apps, app);
/* _save_order(box); */
_item_new(box, app, 1, it);
box->ng->dnd = 0;
ngi_reposition(box->ng);
ngi_input_extents_calc(box->ng);
}
/* ******************************* LAUNCHER ITEM ********************************** */
static void
_item_new(Ngi_Box *box, Efreet_Desktop *desktop, int instant, Ngi_Item_Launcher *after)
{
Ngi_Item_Launcher *it;
it = E_NEW(Ngi_Item_Launcher, 1);
it->base.box = box;
ngi_item_init_defaults((Ngi_Item*)it);
it->base.cb_free = _item_cb_free;
it->base.cb_mouse_down = _item_cb_mouse_down;
it->base.cb_mouse_up = _item_cb_mouse_up;
it->base.cb_drag_start = _item_cb_drag_start;
efreet_desktop_ref(desktop);
it->app = desktop;
_item_fill(it);
if (after)
box->items = eina_list_prepend_relative(box->items, it, after);
else
box->items = eina_list_append(box->items, it);
ngi_item_show((Ngi_Item*)it, instant);
}
static void
_item_cb_free(Ngi_Item *item)
{
Ngi_Item_Launcher *it = (Ngi_Item_Launcher *) item;
if (it->app)
efreet_desktop_unref(it->app);
if (it->o_icon)
evas_object_del(it->o_icon);
if (it->o_proxy)
evas_object_del(it->o_proxy);
E_FREE(it);
}
static void
_item_fill(Ngi_Item_Launcher *it)
{
Evas_Object *o;
Evas *e = it->base.box->ng->evas;
if (it->o_icon)
{
edje_object_part_unswallow(it->base.obj, it->o_icon);
evas_object_del(it->o_icon);
}
if (it->o_proxy)
{
edje_object_part_unswallow(it->base.obj, it->o_proxy);
evas_object_del(it->o_proxy);
}
o = e_util_desktop_icon_add(it->app, 128, e);
if (o)
{
edje_object_part_swallow(it->base.obj, "e.swallow.content", o);
evas_object_show(o);
it->o_icon = o;
o = evas_object_image_filled_add(e);
evas_object_image_fill_set(o, 0, 0, 1, 1);
evas_object_image_source_set(o, it->base.obj);
edje_object_part_swallow(it->base.over, "e.swallow.content", o);
evas_object_show(o);
it->o_proxy = o;
}
if (it->app->name && it->app->name[0])
ngi_item_label_set((Ngi_Item*)it, it->app->name);
else if (it->app->generic_name && it->app->generic_name[0])
ngi_item_label_set((Ngi_Item*)it, it->app->generic_name);
}
static void
_cb_drag_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
Ngi_Box *box = data;
ngi_bar_lock(box->ng, 0);
ngi_thaw(box->ng);
}
static void
_cb_drag_finished(E_Drag *d, int dropped)
{
efreet_desktop_unref((Efreet_Desktop*)d->data);
}
static void
_item_cb_drag_start(Ngi_Item *item)
{
Ngi_Item_Launcher *it = (Ngi_Item_Launcher*) item;
E_Drag *d;
Evas_Object *o;
Evas_Coord x, y, w, h, px, py;
Ngi_Box *box = item->box;
const char *drag_types[] = { "enlightenment/desktop" };
if (item->box->cfg->launcher_lock_dnd)
return;
evas_object_geometry_get(it->o_icon, &x, &y, &w, &h);
if (!ngi_config->use_composite)
{
x -= box->ng->win->rect.x;
y -= box->ng->win->rect.y;
}
d = e_drag_new(box->ng->zone->container, x, y, drag_types, 1,
it->app, -1, NULL,
_cb_drag_finished);
efreet_desktop_ref(it->app);
o = e_util_desktop_icon_add(it->app, MIN(w, h), e_drag_evas_get(d));
e_drag_object_set(d, o);
e_drag_resize(d, w, h);
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _cb_drag_del, box);
e_order_remove(item->box->apps, it->app);
evas_object_hide(it->base.obj);
ngi_item_remove(&(it->base));
ecore_x_pointer_xy_get(box->ng->win->input, &px, &py);
e_drag_start(d, px, py);
box->ng->item_drag = NULL;
ngi_bar_lock(box->ng, 1);
ngi_thaw(box->ng);
}
static void
_menu_cb_lock_dnd(void *data, E_Menu *m, E_Menu_Item *mi)
{
Ngi_Box *box = (Ngi_Box *)data;
if (box) box->cfg->launcher_lock_dnd = e_menu_item_toggle_get(mi);
}
static void
_menu_cb_edit_icon(void *data, E_Menu *m, E_Menu_Item *mi)
{
Ngi_Item_Launcher *it = data;
if (it) e_desktop_edit(e_container_current_get(e_manager_current_get()), it->app);
}
static void
_menu_cb_configure_bar(void *data, E_Menu *m, E_Menu_Item *mi)
{
Ng *ng = (Ng *)data;
if (ng) ngi_configure_module(ng->cfg);
}
static void
_menu_cb_configure_launcher(void *data, E_Menu *m, E_Menu_Item *mi)
{
Ngi_Box *box = (Ngi_Box *)data;
char path[4096];
if (!box)
return;
snprintf(path, sizeof(path), "%s/.e/e/applications/bar/%s/.order",
e_user_homedir_get(), box->cfg->launcher_app_dir);
e_configure_registry_call("internal/ibar_other",
e_container_current_get(e_manager_current_get()),
path);
}
static void
_menu_cb_menu_end(void *data, E_Menu *m)
{
Ng *ng = (Ng *)data;
e_object_del(E_OBJECT(m));
ngi_thaw(ng);
}
static void
_item_cb_mouse_down(Ngi_Item *item, Ecore_Event_Mouse_Button *ev)
{
Ngi_Item_Launcher *it = (Ngi_Item_Launcher *) item;
Evas_Coord x, y, w, h;
E_Menu *m;
E_Menu_Item *mi;
Ngi_Box *box = item->box;
if (!(ev->buttons == 3))
{
item->mouse_down = 1;
return;
}
if (!it->app)
return;
evas_object_geometry_get(item->obj, &x, &y, &w, &h);
x += box->ng->win->popup->x + box->ng->zone->x;
y += box->ng->win->popup->y + box->ng->zone->y;
int dir = E_MENU_POP_DIRECTION_AUTO;
switch(box->ng->cfg->orient)
{
case E_GADCON_ORIENT_TOP:
dir = E_MENU_POP_DIRECTION_DOWN;
y += h;
break;
case E_GADCON_ORIENT_BOTTOM:
dir = E_MENU_POP_DIRECTION_UP;
break;
case E_GADCON_ORIENT_LEFT:
dir = E_MENU_POP_DIRECTION_RIGHT;
x += w;
break;
case E_GADCON_ORIENT_RIGHT:
dir = E_MENU_POP_DIRECTION_LEFT;
break;
}
m = e_menu_new();
mi = e_menu_item_new(m);
e_menu_item_label_set(mi, D_("Configure Bar"));
e_menu_item_callback_set(mi, _menu_cb_configure_bar, box->ng);
mi = e_menu_item_new(m);
e_menu_item_label_set(mi, D_("Lock Dragging"));
e_menu_item_check_set(mi, 1);
e_menu_item_toggle_set(mi, box->cfg->launcher_lock_dnd);
e_menu_item_callback_set(mi, _menu_cb_lock_dnd, box);
mi = e_menu_item_new(m);
e_menu_item_separator_set(mi, 1);
mi = e_menu_item_new(m);
e_menu_item_label_set(mi, D_("Applications"));
e_menu_item_callback_set(mi, _menu_cb_configure_launcher, box);
mi = e_menu_item_new(m);
e_menu_item_label_set(mi, D_("Edit Icon"));
e_menu_item_callback_set(mi, _menu_cb_edit_icon, it);
e_menu_post_deactivate_callback_set(m, _menu_cb_menu_end, box->ng);
e_menu_activate_mouse(m, box->ng->zone, x, y, 1, 1,
dir, ev->timestamp);
}
static void
_item_cb_mouse_up(Ngi_Item *item, Ecore_Event_Mouse_Button *ev)
{
Ngi_Item_Launcher *it = (Ngi_Item_Launcher *) item;
if (!item->mouse_down)
return;
item->mouse_down = 0;
if (ev->buttons == 1)
{
e_exec(e_util_zone_current_get(e_manager_current_get()), it->app, NULL, NULL, NULL);
ngi_item_signal_emit((Ngi_Item*)it, "e,action,start");
}
}