enlightenment/src/modules/gadman/e_mod_gadman.c

1686 lines
54 KiB
C

#include "e_mod_gadman.h"
/* local protos */
static void _attach_menu(void *data, E_Gadcon_Client *gcc, E_Menu *menu);
static void _save_widget_position(E_Gadcon_Client *gcc);
static void _apply_widget_position(E_Gadcon_Client *gcc);
static E_Gadcon_Client *_gadman_gadget_add(const E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer, E_Config_Gadcon_Client *src_cf);
static Eina_Bool _gadman_module_init_end_cb(void *d EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
static Evas_Object *_create_mover(E_Gadcon *gc);
static Evas_Object *_get_mover(E_Gadcon_Client *gcc);
static E_Gadcon *_gadman_gadcon_new(const char *name, Gadman_Layer_Type layer, E_Zone *zone, E_Gadcon_Location *loc);
static void _gadman_overlay_create(void);
static void on_top(void *data, Evas_Object *o, const char *em, const char *src);
static void on_right(void *data, Evas_Object *o, const char *em, const char *src);
static void on_down(void *data, Evas_Object *o, const char *em, const char *src);
static void on_left(void *data, Evas_Object *o, const char *em, const char *src);
static void on_move(void *data, Evas_Object *o, const char *em, const char *src);
static void on_frame_click(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void on_bg_click(void *data, Evas_Object *o, const char *em, const char *src);
static void on_hide_stop(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED,
const char *em EINA_UNUSED, const char *src EINA_UNUSED);
static void on_menu_style_plain(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_style_inset(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_style_float(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_style_horiz(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_style_vert(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_delete(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_add(void *data, E_Menu *m, E_Menu_Item *mi);
static Eina_Bool _gadman_module_cb(void *d EINA_UNUSED, int type EINA_UNUSED, E_Event_Module_Update *ev);
static int _e_gadman_client_add(void *data EINA_UNUSED, E_Gadcon_Client *, const E_Gadcon_Client_Class *cc);
static void _e_gadman_client_remove(void *data EINA_UNUSED, E_Gadcon_Client *gcc);
static void _e_gadman_handlers_add(void);
static void _e_gadman_handler_del(void);
static Eina_Bool _e_gadman_cb_zone_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static E_Gadcon_Client *gadman_gadget_place(E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf, Gadman_Layer_Type layer, E_Zone *zone);
static E_Gadcon *gadman_gadcon_get(const E_Zone *zone, Gadman_Layer_Type layer);
static Eina_Bool gadman_locked;
Manager *Man = NULL;
static Eina_List *_gadman_hdls = NULL;
static Eina_Hash *_gadman_gadgets = NULL;
static Ecore_Job *gadman_reset_job = NULL;
/* for locking geometry during our own move/resize */
static Eina_Bool mover_lock = EINA_FALSE;
/* Implementation */
void
gadman_reset(void *d EINA_UNUSED)
{
E_Gadcon *gc;
unsigned int layer;
const Eina_List *l;
E_Zone *zone;
E_FREE_FUNC(gadman_reset_job, ecore_job_del);
if (gadman_locked) return;
evas_event_freeze(e_comp->evas);
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
E_FREE_LIST(Man->gadcons[layer], e_object_del);
Man->gadgets[layer] = eina_list_free(Man->gadgets[layer]);
E_FREE_FUNC(Man->movers[layer], evas_object_del);
}
evas_object_hide(Man->overlay);
E_FREE_FUNC(Man->overlay, evas_object_del);
E_FREE_FUNC(Man->full_bg, evas_object_del);
if (_gadman_gadgets)
{
eina_hash_free_cb_set(_gadman_gadgets, EINA_FREE_CB(eina_list_free));
eina_hash_free(_gadman_gadgets);
}
/* iterating through zones - and making gadmans on each */
EINA_LIST_FOREACH(e_comp->zones, l, zone)
{
const char *layer_name[] = {"gadman", "gadman_top"};
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
gc = _gadman_gadcon_new(layer_name[layer], layer, zone, Man->location[layer]);
Man->gadcons[layer] = eina_list_append(Man->gadcons[layer], gc);
}
}
_gadman_overlay_create();
_gadman_gadgets = eina_hash_string_superfast_new(NULL);
gadman_update_bg();
Man->visible = !Man->visible;
{
int prev = Man->conf->anim_bg;
Man->conf->anim_bg = 0;
gadman_gadgets_toggle();
Man->conf->anim_bg = prev;
}
edje_object_message_signal_process(Man->full_bg);
evas_event_thaw(e_comp->evas);
}
void
gadman_init(E_Module *m)
{
E_Gadcon_Location *location;
/* Create Manager */
Man = calloc(1, sizeof(Manager));
if (!Man) return;
Man->module = m;
gadman_locked = e_module_loading_get();
Man->width = e_comp->w;
Man->height = e_comp->h;
/* create and register "desktop" location */
location = Man->location[GADMAN_LAYER_BG] = e_gadcon_location_new(_("Desktop"), E_GADCON_SITE_DESKTOP,
_e_gadman_client_add, (intptr_t*)(long)GADMAN_LAYER_BG,
_e_gadman_client_remove, NULL);
e_gadcon_location_set_icon_name(location, "preferences-desktop");
e_gadcon_location_register(location);
/* create and register "desktop hover" location */
location = Man->location[GADMAN_LAYER_TOP] = e_gadcon_location_new(_("Desktop Overlay"), E_GADCON_SITE_DESKTOP,
_e_gadman_client_add, (intptr_t*)(long)GADMAN_LAYER_TOP,
_e_gadman_client_remove, NULL);
e_gadcon_location_set_icon_name(location, "preferences-desktop");
e_gadcon_location_register(location);
_e_gadman_handlers_add();
if (!gadman_locked) gadman_reset_job = ecore_job_add(gadman_reset, NULL);
}
void
gadman_shutdown(void)
{
unsigned int layer;
E_FREE_FUNC(gadman_reset_job, ecore_job_del);
_e_gadman_handler_del();
gadman_gadget_edit_end(NULL, NULL, NULL, NULL);
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
e_gadcon_location_unregister(Man->location[layer]);
E_FREE_LIST(Man->gadcons[layer], e_object_del);
evas_object_del(Man->movers[layer]);
Man->gadgets[layer] = eina_list_free(Man->gadgets[layer]);
e_gadcon_location_free(Man->location[layer]);
}
eina_stringshare_del(Man->icon_name);
/* free manager */
evas_object_hide(Man->overlay);
E_FREE_FUNC(Man->overlay, evas_object_del);
if (_gadman_gadgets)
{
eina_hash_free_cb_set(_gadman_gadgets, EINA_FREE_CB(eina_list_free));
eina_hash_free(_gadman_gadgets);
}
_gadman_gadgets = NULL;
free(Man);
}
void
gadman_populate_class(void *data, E_Gadcon *gc, const E_Gadcon_Client_Class *cc)
{
Gadman_Layer_Type layer = (Gadman_Layer_Type)(long)data;
const Eina_List *l, *ll;
E_Config_Gadcon_Client *cf_gcc;
E_Gadcon_Client *gcc = NULL;
EINA_LIST_FOREACH(gc->cf->clients, l, cf_gcc)
{
if ((!strcmp(cf_gcc->name, cc->name)) && (gc->cf->zone == gc->zone->num))
{
gcc = e_gadcon_client_find(gc, cf_gcc);
ll = eina_hash_find(_gadman_gadgets, cc->name);
if ((!gcc) || (ll && (!eina_list_data_find(ll, cf_gcc))))
gadman_gadget_place(gcc, cc, cf_gcc, layer, gc->zone);
}
}
gc->populated_classes = eina_list_append(gc->populated_classes, cc);
}
static E_Gadcon *
gadman_gadcon_get(const E_Zone *zone, Gadman_Layer_Type layer)
{
const Eina_List *l;
E_Gadcon *gc;
EINA_LIST_FOREACH(Man->gadcons[layer], l, gc)
if (gc->zone == zone) return gc;
return NULL;
}
static void
gadman_gadcon_place_job(E_Gadcon_Client *gcc)
{
_apply_widget_position(gcc);
if (gcc == gcc->gadcon->drag_gcc)
gadman_gadget_edit_start(gcc);
if (Man->visible || (!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gcc->gadcon)))
e_gadcon_client_show(gcc);
else
e_gadcon_client_hide(gcc);
}
static void
_gadman_gadget_free(void *data EINA_UNUSED, void *obj)
{
E_Gadcon_Client *gcc = obj;
Eina_List *l;
int layer;
Eina_Bool edit;
layer = gcc->gadcon->id - ID_GADMAN_LAYER_BASE;
// edje_object_part_unswallow(gcc->o_frame, gcc->o_base);
if (gcc->cf)
{
Man->gadgets[layer] = eina_list_remove(Man->gadgets[layer], gcc->cf);
l = eina_hash_find(_gadman_gadgets, gcc->name);
if (l)
{
eina_hash_set(_gadman_gadgets, gcc->name, eina_list_remove(l, gcc->cf));
}
gcc->cf = NULL;
}
edit = (gcc == gcc->gadcon->drag_gcc) || (Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE] == gcc);
if (!edit) return;
gcc->gadcon->editing = 1; // may get unset from a dialog, force here to prevent crash
gadman_gadget_edit_end(NULL, NULL, NULL, NULL);
}
static void
_gadman_gadget_size_hints_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
E_Gadcon_Client *gcc = data;
int w, h;
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
/* size hints change for either min or aspect */
if (gcc->min.w || gcc->min.h)
{
w = MAX(w, gcc->min.w);
h = MAX(h, gcc->min.h);
}
if (gcc->aspect.w && gcc->aspect.h)
{
w = MAX(w, gcc->aspect.w);
h = MAX(h, gcc->aspect.h);
}
evas_object_resize(gcc->o_frame, w, h);
_save_widget_position(gcc);
}
static E_Gadcon_Client *
gadman_gadget_place(E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf, Gadman_Layer_Type layer, E_Zone *zone)
{
E_Gadcon *gc;
Eina_List *l;
if (!cf->name) return NULL;
gc = gadman_gadcon_get(zone, layer);
if (!cc)
{
EINA_LIST_FOREACH(gc->populated_classes, l, cc)
{
if (!strcmp(cc->name, cf->name))
break;
else
cc = NULL;
}
}
/* Find provider */
if (!cc)
{
e_gadcon_client_queue(gc, cf);
e_gadcon_custom_populate_request(gc);
return NULL;
}
/* init Gadcon_Client */
if (!gcc)
{
gcc = cc->func.init(gc, cf->name, cf->id, cc->default_style);
if (!gcc) return NULL;
e_object_delfn_add(E_OBJECT(gcc), _gadman_gadget_free, NULL);
gcc->cf = cf;
gcc->client_class = cc;
/* Call the client orientation function */
if (cc->func.orient)
cc->func.orient(gcc, gcc->cf->orient);
}
Man->gadgets[layer] = eina_list_append(Man->gadgets[layer], cf);
//printf("Place Gadget %s (style: %s id: %s) (gadcon: %s)\n", gcc->name, cf->style, cf->id, gc->name);
/* create frame */
gcc->o_frame = edje_object_add(gc->evas);
e_theme_edje_object_set(gcc->o_frame, "base/theme/gadman", "e/gadman/frame");
if ((cf->style) && (!strcmp(cf->style, E_GADCON_CLIENT_STYLE_INSET)))
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,inset", "e");
else
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,plain", "e");
/* swallow the client inside the frame */
edje_object_part_swallow(gcc->o_frame, "e.swallow.content", gcc->o_base);
evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_DOWN,
on_frame_click, gcc);
evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
_gadman_gadget_size_hints_cb, gcc);
gcc->hidden = 1;
if (gcc->gadcon->id == ID_GADMAN_LAYER_TOP)
{
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,hide", "e");
evas_object_layer_set(gcc->o_frame, E_LAYER_POPUP);
}
else
evas_object_layer_set(gcc->o_frame, E_LAYER_DESKTOP);
if (cc->name)
{
l = eina_hash_find(_gadman_gadgets, cc->name);
eina_hash_set(_gadman_gadgets, cc->name, eina_list_append(l, gcc->cf));
}
ecore_job_add((Ecore_Cb)gadman_gadcon_place_job, gcc);
return gcc;
}
E_Gadcon_Client *
gadman_gadget_add(const E_Gadcon_Client_Class *cc, E_Gadcon_Client *gcc, Gadman_Layer_Type layer)
{
return _gadman_gadget_add(cc, layer, gcc->cf);
}
static E_Gadcon_Client *
_gadman_gadget_add(const E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer, E_Config_Gadcon_Client *src_cf)
{
E_Config_Gadcon_Client *cf = NULL;
E_Gadcon_Client *gcc = NULL;
E_Gadcon *gc;
int w, h;
gc = gadman_gadcon_get(e_zone_current_get(),
layer);
/* Create Config_Gadcon_Client */
cf = e_gadcon_client_config_new(gc, cc->name);
if (cf)
{
if (!src_cf)
{
cf->style = eina_stringshare_add(cc->default_style);
cf->geom.pos_x = DEFAULT_POS_X;
cf->geom.pos_y = DEFAULT_POS_Y;
cf->geom.size_w = DEFAULT_SIZE_W;
cf->geom.size_h = DEFAULT_SIZE_H;
}
else
{
cf->style = eina_stringshare_add(src_cf->style);
cf->geom.pos_x = src_cf->geom.pos_x;
cf->geom.pos_y = src_cf->geom.pos_y;
cf->geom.size_w = src_cf->geom.size_w;
cf->geom.size_h = src_cf->geom.size_h;
}
}
/* Place the new gadget */
if (cf)
gcc = gadman_gadget_place(NULL, cc, cf, layer, gc->zone);
if (!gcc) return NULL;
/* Respect Aspect */
evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
if (gcc->aspect.w && gcc->aspect.h)
{
if (gcc->aspect.w > gcc->aspect.h)
w = ((float)h / (float)gcc->aspect.h) * (gcc->aspect.w);
else
h = ((float)w / (float)gcc->aspect.w) * (gcc->aspect.h);
if (h < gcc->min.h) h = gcc->min.h;
if (w < gcc->min.w) w = gcc->min.w;
evas_object_resize(gcc->o_frame, w, h);
}
return gcc;
}
static void
gadman_edit(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
_apply_widget_position(data);
}
static void
_gadman_gadget_edit_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
int w, h;
if (mover_lock) return;
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
evas_object_resize(_get_mover(data), w, h);
}
static void
_gadman_gadget_edit_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
int x, y;
if (mover_lock) return;
evas_object_geometry_get(obj, &x, &y, NULL, NULL);
evas_object_move(_get_mover(data), x, y);
}
void
gadman_gadget_edit_start(E_Gadcon_Client *gcc)
{
E_Gadcon *gc;
Evas_Object *mover;
Eina_List *l;
int x, y, w, h;
if (Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE] == gcc) return;
else if (Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE])
e_object_unref(E_OBJECT(Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE]));
EINA_LIST_FOREACH(Man->gadcons[gcc->gadcon->id - ID_GADMAN_LAYER_BASE], l, gc)
gc->editing = 1;
gc = gcc->gadcon;
e_object_ref(E_OBJECT(gcc));
//INF("START: %u", e_object_ref_get((void*)gcc));
/* Move/resize the correct mover */
mover = _get_mover(gcc);
if (!mover) return;
evas_object_geometry_get(gcc->o_frame, &x, &y, &w, &h);
evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_RESIZE, _gadman_gadget_edit_resize_cb, gcc);
evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOVE, _gadman_gadget_edit_move_cb, gcc);
Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE] = gcc;
evas_object_move(mover, x, y);
evas_object_resize(mover, w, h);
evas_object_raise(mover);
if (Man->visible || (!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gc)))
evas_object_show(mover);
evas_object_event_callback_del(mover, EVAS_CALLBACK_HIDE, gadman_edit);
evas_object_event_callback_add(mover, EVAS_CALLBACK_HIDE, gadman_edit, gcc);
}
void
gadman_gadget_edit_end(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
unsigned int layer;
E_Gadcon_Client *drag_gcc = NULL;
for (layer = GADMAN_LAYER_COUNT - 1; layer < GADMAN_LAYER_COUNT; layer--)
{
const Eina_List *l;
E_Gadcon *gc;
gc = eina_list_data_get(Man->gadcons[layer]);
if (!gc) continue;
if (!gc->editing) continue;
evas_object_event_callback_del(Man->movers[layer], EVAS_CALLBACK_HIDE, gadman_edit);
evas_object_hide(Man->movers[layer]);
EINA_LIST_FOREACH(Man->gadcons[layer], l, gc)
gc->editing = 0;
drag_gcc = Man->drag_gcc[layer];
if (drag_gcc)
{
evas_object_event_callback_del_full(drag_gcc->o_frame, EVAS_CALLBACK_RESIZE, _gadman_gadget_edit_resize_cb, drag_gcc);
evas_object_event_callback_del_full(drag_gcc->o_frame, EVAS_CALLBACK_MOVE, _gadman_gadget_edit_move_cb, drag_gcc);
}
Man->drag_gcc[layer] = NULL;
break;
}
if (!drag_gcc) return;
drag_gcc->gadcon->drag_gcc = NULL;
_save_widget_position(drag_gcc);
if (!e_object_is_del(E_OBJECT(drag_gcc)))
e_object_unref(E_OBJECT(drag_gcc));
//INF("END: %d:%u", e_object_is_del(E_OBJECT(drag_gcc)), e_object_ref_get((void*)drag_gcc));
}
void
gadman_gadgets_show(void)
{
Eina_List *l, *ll;
E_Gadcon *gc;
E_Gadcon_Client *gcc;
Eina_Bool editing = EINA_FALSE;
Man->visible = 1;
evas_object_show(Man->overlay);
if (Man->conf->bg_type == BG_STD)
{
if (Man->conf->anim_bg)
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,show", "e");
else
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,show,now", "e");
}
else
{
if (Man->conf->anim_bg)
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,show,custom", "e");
else
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,show,custom,now", "e");
}
/* Showing top gadgets */
EINA_LIST_FOREACH(Man->gadcons[GADMAN_LAYER_TOP], l, gc)
{
EINA_LIST_FOREACH(gc->clients, ll, gcc)
{
if (Man->conf->anim_gad)
edje_object_signal_emit(gcc->o_frame,
"e,state,visibility,show", "e");
else
edje_object_signal_emit(gcc->o_frame,
"e,state,visibility,show,now", "e");
e_gadcon_client_show(gcc);
}
gc->drop_handler->hidden = 0;
editing = gc->editing;
}
if (editing && gcc) evas_object_show(_get_mover(gcc));
}
void
gadman_gadgets_hide(void)
{
Eina_List *l, *ll;
E_Gadcon *gc;
E_Gadcon_Client *gcc;
Eina_Bool editing = EINA_FALSE;
Man->visible = 0;
if (Man->conf->bg_type == BG_STD)
{
if (Man->conf->anim_bg)
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,hide", "e");
else
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,hide,now", "e");
}
else
{
if (Man->conf->anim_bg)
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,hide,custom", "e");
else
edje_object_signal_emit(Man->full_bg,
"e,state,visibility,hide,custom,now", "e");
}
/* Hiding top gadgets */
EINA_LIST_FOREACH(Man->gadcons[GADMAN_LAYER_TOP], l, gc)
{
gc->drop_handler->hidden = 1;
editing = gc->editing;
EINA_LIST_FOREACH(gc->clients, ll, gcc)
{
if (Man->conf->anim_gad)
edje_object_signal_emit(gcc->o_frame,
"e,state,visibility,hide", "e");
else
edje_object_signal_emit(gcc->o_frame,
"e,state,visibility,hide,now", "e");
e_gadcon_client_hide(gcc);
}
}
if (editing)
gadman_gadget_edit_end(NULL, NULL, NULL, NULL);
}
void
gadman_gadgets_toggle(void)
{
if (Man->visible)
gadman_gadgets_hide();
else
gadman_gadgets_show();
}
void
gadman_update_bg(void)
{
Evas_Object *obj;
if (!Man->gadcons[GADMAN_LAYER_TOP]) return;
if (!Man->conf) return;
obj = edje_object_part_swallow_get(Man->full_bg, "e.swallow.bg");
if (obj)
{
edje_object_part_unswallow(Man->full_bg, obj);
evas_object_del(obj);
}
switch (Man->conf->bg_type)
{
case BG_STD:
case BG_TRANS:
break;
case BG_COLOR:
{
double r, g, b;
r = (double)Man->conf->color_r * (200. / 255.);
g = (double)Man->conf->color_g * (200. / 255.);
b = (double)Man->conf->color_b * (200. / 255.);
obj = evas_object_rectangle_add(e_comp->evas);
evas_object_color_set(obj, lround(r), lround(g), lround(b), 200);
edje_object_part_swallow(Man->full_bg, "e.swallow.bg", obj);
}
break;
case BG_CUSTOM:
if (eina_str_has_extension(Man->conf->custom_bg, ".edj"))
{
//THIS IS FOR E backgrounds
obj = edje_object_add(e_comp->evas);
edje_object_file_set(obj, Man->conf->custom_bg,
"e/desktop/background");
}
else
{
//THIS IS FOR A NORMAL IMAGE
obj = evas_object_image_add(e_comp->evas);
evas_object_image_file_set(obj, Man->conf->custom_bg, NULL);
evas_object_image_fill_set(obj, 0, 0, e_comp->w, e_comp->h);
}
edje_object_part_swallow(Man->full_bg, "e.swallow.bg", obj);
break;
default:
break;
}
}
static void
_gadman_gadcon_free(E_Gadcon *gc)
{
e_gadcon_unpopulate(gc);
e_gadcon_custom_del(gc);
/* free gadcons */
e_config->gadcons = eina_list_remove(e_config->gadcons, gc);
eina_stringshare_del(gc->name);
if (gc->config_dialog) e_object_del(E_OBJECT(gc->config_dialog));
eina_list_free(gc->populated_classes);
if (gc->drop_handler) e_drop_handler_del(gc->drop_handler);
free(gc);
}
static void
_gadman_gadcon_dnd_enter_cb(E_Gadcon *gc, E_Gadcon_Client *gcc)
{
/* only use this for dragging gadcons around the desktop */
if ((!eina_list_data_find(Man->gadcons[GADMAN_LAYER_BG], gc)) &&
(!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gc)))
return;
if (gc != gcc->gadcon) return;
//INF("ENTER: %u", e_object_ref_get((void*)gcc));
gadman_gadget_edit_start(gcc);
}
static void
_gadman_gadcon_dnd_leave_cb(E_Gadcon *gc, E_Gadcon_Client *gcc)
{
unsigned int layer;
E_Gadcon_Client *drag_gcc = NULL;
/* only use this for dragging gadcons around the desktop */
if ((!eina_list_data_find(Man->gadcons[GADMAN_LAYER_BG], gc)) &&
(!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gc)))
return;
if (gc != gcc->gadcon) return;
//INF("LEAVE: %u", e_object_ref_get((void*)gcc));
Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE] = NULL;
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
const Eina_List *l;
evas_object_event_callback_del(Man->movers[layer], EVAS_CALLBACK_HIDE, gadman_edit);
evas_object_hide(Man->movers[layer]);
EINA_LIST_FOREACH(Man->gadcons[layer], l, gc)
{
gc->editing = 0;
drag_gcc = gc->drag_gcc;
}
}
/* this is slightly different from edit_end because we don't save the position or unset the drag gcc */
if (!drag_gcc) return;
e_object_unref(E_OBJECT(drag_gcc));
}
static void
_gadman_gadcon_dnd_move_cb(E_Gadcon *gc, E_Gadcon_Client *gcc)
{
Evas_Object *mover;
E_Zone *zone;
int x, y, mx, my;
int ox, oy, ow, oh;
if (gc != gcc->gadcon) return;
/* only use this for dragging gadcons around the desktop */
if ((!eina_list_data_find(Man->gadcons[GADMAN_LAYER_BG], gc)) &&
(!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gc)))
return;
mover = _get_mover(gcc);
evas_object_geometry_get(gcc->o_frame, &x, &y, NULL, NULL);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
/* don't go out of the screen */
x = MAX(x, gcc->dx), y = MAX(y, gcc->dy);
/* adjust in case one screen is larger than another */
zone = e_gadcon_zone_get(gc);
mx = MIN(Man->width, zone->x + zone->w), my = MIN(Man->height, zone->y + zone->h);
x = MIN(x, mx - ow + gcc->dx), y = MIN(y, my - oh + gcc->dy);
evas_object_move(gcc->o_frame, x - gcc->dx, y - gcc->dy);
evas_object_move(mover, x - gcc->dx, y - gcc->dy);
evas_object_raise(gcc->o_frame);
evas_object_raise(mover);
_save_widget_position(gcc);
}
static void
_gadman_gadcon_dnd_drop_cb(E_Gadcon *gc, E_Gadcon_Client *gcc)
{
E_Config_Gadcon_Client *cf;
E_Zone *dst_zone = NULL;
E_Gadcon *dst_gadcon;
Evas_Object *mover;
int gx, gy;
if (gc != gcc->gadcon) return;
/* only use this for dragging gadcons around the desktop */
if ((!eina_list_data_find(Man->gadcons[GADMAN_LAYER_BG], gc)) &&
(!eina_list_data_find(Man->gadcons[GADMAN_LAYER_TOP], gc)))
return;
gcc->moving = 0;
gcc->dx = gcc->dy = 0;
/* checking if zone was changed for dragged gadget */
mover = _get_mover(gcc);
evas_object_geometry_get(mover, &gx, &gy, NULL, NULL);
dst_zone = e_comp_zone_xy_get(gx, gy);
if (dst_zone && (gcc->gadcon->zone != dst_zone))
{
unsigned int layer = gcc->gadcon->id - ID_GADMAN_LAYER_BASE;
cf = gcc->cf;
gcc->gadcon->cf->clients = eina_list_remove(gcc->gadcon->cf->clients, cf);
dst_gadcon = gadman_gadcon_get(dst_zone, layer);
if (dst_gadcon)
{
dst_gadcon->cf->clients = eina_list_append(dst_gadcon->cf->clients, cf);
}
}
_save_widget_position(gcc);
e_config_save_queue();
}
static void
_gadman_overlay_create(void)
{
Eina_List *l;
E_Gadcon *gc;
/* create full background object */
Man->full_bg = edje_object_add(e_comp->evas);
evas_object_geometry_set(Man->full_bg, 0, 0, e_comp->w, e_comp->h);
e_theme_edje_object_set(Man->full_bg, "base/theme/gadman",
"e/gadman/full_bg");
edje_object_signal_callback_add(Man->full_bg, "mouse,down,*",
"grabber", on_bg_click, NULL);
edje_object_signal_callback_add(Man->full_bg, "e,action,hide,stop",
"", on_hide_stop, NULL);
Man->overlay = e_comp_object_util_add(Man->full_bg, E_COMP_OBJECT_TYPE_NONE);
evas_object_layer_set(Man->overlay, E_LAYER_CLIENT_FULLSCREEN);
/* create placeholder rect to maintain our dnd stacking layer */
EINA_LIST_FOREACH(Man->gadcons[GADMAN_LAYER_TOP], l, gc)
{
gc->drop_handler->base = Man->overlay;
gc->drop_handler->hidden = 1;
}
}
static E_Gadcon *
_gadman_gadcon_new(const char *name, Gadman_Layer_Type layer, E_Zone *zone, E_Gadcon_Location *loc)
{
const Eina_List *l;
E_Gadcon *gc;
E_Config_Gadcon *cg;
/* Create Gadcon */
gc = E_OBJECT_ALLOC(E_Gadcon, E_GADCON_TYPE, _gadman_gadcon_free);
if (!gc) return NULL;
gc->name = eina_stringshare_add(name);
gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
gc->orient = E_GADCON_ORIENT_FLOAT;
gc->location = loc;
gc->evas = e_comp->evas;
e_gadcon_ecore_evas_set(gc, e_comp->ee);
e_gadcon_xdnd_window_set(gc, e_comp->ee_win);
e_gadcon_dnd_window_set(gc, e_comp->ee_win);
e_gadcon_drop_handler_add(gc, _gadman_gadcon_dnd_enter_cb, _gadman_gadcon_dnd_leave_cb,
_gadman_gadcon_dnd_move_cb, _gadman_gadcon_dnd_drop_cb,
zone->x, zone->y, zone->w, zone->h);
e_gadcon_zone_set(gc, zone);
e_gadcon_util_menu_attach_func_set(gc, _attach_menu, NULL);
e_gadcon_populate_callback_set(gc, gadman_populate_class, (void *)layer);
gc->id = ID_GADMAN_LAYER_BASE + layer;
gc->edje.o_parent = NULL;
gc->edje.swallow_name = NULL;
gc->shelf = NULL;
gc->toolbar = NULL;
gc->editing = 0;
gc->o_container = NULL;
gc->frame_request.func = NULL;
gc->resize_request.func = NULL;
gc->min_size_request.func = NULL;
/* Search for existing gadcon config */
gc->cf = NULL;
EINA_LIST_FOREACH(e_config->gadcons, l, cg)
{
if ((!strcmp(cg->name, name)) && (cg->zone == zone->num))
{
gc->cf = cg;
break;
}
}
/* ... or create a new one */
if (!gc->cf)
{
gc->cf = E_NEW(E_Config_Gadcon, 1);
gc->cf->name = eina_stringshare_add(name);
gc->cf->id = gc->id;
gc->cf->zone = zone->num;
gc->cf->clients = NULL;
e_config->gadcons = eina_list_append(e_config->gadcons, gc->cf);
e_config_save_queue();
}
e_gadcon_custom_new(gc);
e_gadcon_custom_populate_request(gc);
if (!Man->movers[layer])
Man->movers[layer] = _create_mover(gc);
return gc;
}
static void
_mover_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
unsigned int layer;
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
if (Man->movers[layer] != obj) continue;
Man->movers[layer] = NULL;
return;
}
}
static Evas_Object *
_create_mover(E_Gadcon *gc)
{
Evas_Object *mover;
/* create mover object */
mover = edje_object_add(gc->evas);
if (gc->id == ID_GADMAN_LAYER_BG)
{
evas_object_layer_set(mover, E_LAYER_DESKTOP);
evas_object_event_callback_add(mover, EVAS_CALLBACK_DEL, _mover_del, NULL);
}
else
evas_object_layer_set(mover, E_LAYER_MENU);
e_theme_edje_object_set(mover, "base/theme/gadman", "e/gadman/control");
edje_object_signal_callback_add(mover, "e,action,move,start", "",
on_move, (void *)DRAG_START);
edje_object_signal_callback_add(mover, "mouse,down,3", "*",
gadman_gadget_edit_end, NULL);
edje_object_signal_callback_add(mover, "e,action,resize,left,start", "",
on_left, (void *)DRAG_START);
edje_object_signal_callback_add(mover, "e,action,resize,left,stop", "",
on_left, (void *)DRAG_STOP);
edje_object_signal_callback_add(mover, "e,action,resize,left,go", "",
on_left, (void *)DRAG_MOVE);
edje_object_signal_callback_add(mover, "e,action,resize,down,start", "",
on_down, (void *)DRAG_START);
edje_object_signal_callback_add(mover, "e,action,resize,down,stop", "",
on_down, (void *)DRAG_STOP);
edje_object_signal_callback_add(mover, "e,action,resize,down,go", "",
on_down, (void *)DRAG_MOVE);
edje_object_signal_callback_add(mover, "e,action,resize,right,start", "",
on_right, (void *)DRAG_START);
edje_object_signal_callback_add(mover, "e,action,resize,right,stop", "",
on_right, (void *)DRAG_STOP);
edje_object_signal_callback_add(mover, "e,action,resize,right,go", "",
on_right, (void *)DRAG_MOVE);
edje_object_signal_callback_add(mover, "e,action,resize,up,start", "",
on_top, (void *)DRAG_START);
edje_object_signal_callback_add(mover, "e,action,resize,up,stop", "",
on_top, (void *)DRAG_STOP);
edje_object_signal_callback_add(mover, "e,action,resize,up,go", "",
on_top, (void *)DRAG_MOVE);
return mover;
}
static Evas_Object *
_get_mover(E_Gadcon_Client *gcc)
{
return Man->movers[gcc->gadcon->id - ID_GADMAN_LAYER_BASE];
}
static void
_save_widget_position(E_Gadcon_Client *gcc)
{
int x, y, w, h;
evas_object_geometry_get(gcc->o_frame, &x, &y, &w, &h);
x -= gcc->gadcon->zone->x, y -= gcc->gadcon->zone->y;
gcc->config.pos_x = (double)x / (double)gcc->gadcon->zone->w;
gcc->config.pos_y = (double)y / (double)gcc->gadcon->zone->h;
gcc->config.size_w = (double)w / (double)gcc->gadcon->zone->w;
gcc->config.size_h = (double)h / (double)gcc->gadcon->zone->h;
if (gcc->cf)
{
gcc->cf->geom.pos_x = gcc->config.pos_x;
gcc->cf->geom.pos_y = gcc->config.pos_y;
gcc->cf->geom.size_w = gcc->config.size_w;
gcc->cf->geom.size_h = gcc->config.size_h;
e_config_save_queue();
}
}
static void
_apply_widget_position(E_Gadcon_Client *gcc)
{
int x, y, w, h;
E_Zone *zone;
Evas_Object *mover;
/* Obtain zone from parent gadcon */
zone = gcc->gadcon->zone;
x = gcc->cf->geom.pos_x * zone->w + zone->x;
y = gcc->cf->geom.pos_y * zone->h + zone->y;
w = gcc->cf->geom.size_w * zone->w;
h = gcc->cf->geom.size_h * zone->h;
/* something broke the config's geom, make it visible so it can be
* resized/deleted
*/
if ((gcc->cf->geom.pos_x < 0) || (gcc->cf->geom.pos_y < 0) || (!gcc->cf->geom.size_w) || (!gcc->cf->geom.size_h))
{
gcc->cf->style = eina_stringshare_add(gcc->client_class->default_style ?: E_GADCON_CLIENT_STYLE_INSET);
gcc->style = eina_stringshare_ref(gcc->cf->style);
gcc->cf->geom.pos_x = DEFAULT_POS_X;
gcc->cf->geom.pos_y = DEFAULT_POS_Y;
gcc->cf->geom.size_w = DEFAULT_SIZE_W;
gcc->cf->geom.size_h = DEFAULT_SIZE_H;
if (!strcmp(gcc->style, E_GADCON_CLIENT_STYLE_INSET))
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,inset", "e");
else
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,plain", "e");
_apply_widget_position(gcc);
gadman_gadget_edit_start(gcc);
return;
}
/* Respect min sizes */
if (h < gcc->min.h) h = gcc->min.h;
if (w < gcc->min.w) w = gcc->min.w;
if (h < 1) h = 100;
if (w < 1) w = 100;
/* Respect zone marigin */
if (x < zone->x) x = zone->x;
if (y < zone->y) y = zone->y;
if (x > (zone->x + zone->w)) x = zone->x;
if (y > (zone->y + zone->h)) y = zone->y;
if ((y + h) > (zone->y + zone->h + MIN_VISIBLE_MARIGIN))
h = ((zone->y + zone->h + MIN_VISIBLE_MARIGIN) - y);
if ((x + w) > (zone->x + zone->w + MIN_VISIBLE_MARIGIN))
w = ((zone->x + zone->w + MIN_VISIBLE_MARIGIN) - x);
evas_object_move(gcc->o_frame, x, y);
evas_object_resize(gcc->o_frame, w, h);
if (Man->drag_gcc[gcc->gadcon->id - ID_GADMAN_LAYER_BASE] != gcc) return;
/* Move/resize the correct mover */
mover = _get_mover(gcc);
if (!mover) return;
evas_object_move(mover, x, y);
evas_object_resize(mover, w, h);
}
static void
_attach_menu(void *data EINA_UNUSED, E_Gadcon_Client *gcc, E_Menu *menu)
{
E_Menu *mn;
E_Menu_Item *mi;
//printf("Attach menu (gcc: %x id: %s) [%s]\n", gcc, gcc->cf->id, gcc->cf->style);
if (!gcc) return;
if (e_menu_item_nth(menu, 0))
{
mi = e_menu_item_new(menu);
e_menu_item_separator_set(mi, 1);
}
/* Move / resize*/
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Begin move/resize"));
e_util_menu_item_theme_icon_set(mi, "transform-scale");
e_menu_item_callback_set(mi, on_menu_edit, gcc);
/* plain / inset */
if (gcc->cf)
{
if (!gcc->cf->style)
gcc->cf->style = eina_stringshare_add(E_GADCON_CLIENT_STYLE_INSET);
mn = e_menu_new();
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Plain"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (!strcmp(gcc->cf->style, E_GADCON_CLIENT_STYLE_PLAIN))
e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, on_menu_style_plain, gcc);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Inset"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (!strcmp(gcc->cf->style, E_GADCON_CLIENT_STYLE_INSET))
e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, on_menu_style_inset, gcc);
mi = e_menu_item_new(mn);
e_menu_item_separator_set(mi, 1);
/* orient */
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Free"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 2);
if (gcc->cf->orient == E_GADCON_ORIENT_FLOAT)
e_menu_item_toggle_set(mi, 1);
if (!mi->toggle)
e_menu_item_callback_set(mi, on_menu_style_float, gcc);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Horizontal"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 2);
if (gcc->cf->orient == E_GADCON_ORIENT_HORIZ)
e_menu_item_toggle_set(mi, 1);
if (!mi->toggle)
e_menu_item_callback_set(mi, on_menu_style_horiz, gcc);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Vertical"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 2);
if (gcc->cf->orient == E_GADCON_ORIENT_VERT)
e_menu_item_toggle_set(mi, 1);
if (!mi->toggle)
e_menu_item_callback_set(mi, on_menu_style_vert, gcc);
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Appearance"));
e_util_menu_item_theme_icon_set(mi, "preferences-look");
e_menu_item_submenu_set(mi, mn);
e_object_unref(E_OBJECT(mn));
mi = e_menu_item_new(menu);
e_menu_item_separator_set(mi, 1);
e_gadcon_client_add_location_menu(gcc, menu);
}
/* Remove this gadgets */
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Remove"));
e_util_menu_item_theme_icon_set(mi, "list-remove");
e_menu_item_callback_set(mi, on_menu_delete, gcc);
/* Add other gadgets */
mi = e_menu_item_new(menu);
e_menu_item_separator_set(mi, 1);
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Add other gadgets"));
e_util_menu_item_theme_icon_set(mi, "list-add");
e_menu_item_callback_set(mi, on_menu_add, gcc);
}
static void
on_menu_style_plain(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
E_Gadcon_Client *gcc = data;
eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_PLAIN);
eina_stringshare_replace(&gcc->cf->style, E_GADCON_CLIENT_STYLE_PLAIN);
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,plain", "e");
e_config_save_queue();
}
static void
on_menu_style_inset(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
E_Gadcon_Client *gcc = data;
eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_INSET);
eina_stringshare_replace(&gcc->cf->style, E_GADCON_CLIENT_STYLE_INSET);
edje_object_signal_emit(gcc->o_frame, "e,state,visibility,inset", "e");
e_config_save_queue();
}
static void
_menu_style_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
{
int ow, oh, w, h;
Eina_Bool same;
same = (((orient == E_GADCON_ORIENT_LEFT) && (gcc->cf->orient == E_GADCON_ORIENT_FLOAT)) ||
((orient == E_GADCON_ORIENT_FLOAT) && (gcc->cf->orient == E_GADCON_ORIENT_LEFT)));
gcc->cf->orient = orient;
evas_object_geometry_get(gcc->o_frame, NULL, NULL, &ow, &oh);
if (gcc->client_class->func.orient)
gcc->client_class->func.orient(gcc, orient);
if (same)
{
w = ow, h = oh;
}
else
{
/* just flip aspect */
w = oh;
h = ow;
}
gcc->max.w = w;
gcc->max.h = h;
evas_object_resize(gcc->o_frame, w, h);
_save_widget_position(gcc);
}
static void
on_menu_style_float(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
_menu_style_orient(data, E_GADCON_ORIENT_FLOAT);
}
static void
on_menu_style_horiz(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
_menu_style_orient(data, E_GADCON_ORIENT_HORIZ);
}
static void
on_menu_style_vert(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
_menu_style_orient(data, E_GADCON_ORIENT_VERT);
}
static void
on_menu_edit(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
gadman_gadget_edit_start(data);
}
static void
on_menu_add(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
if (Man->visible)
gadman_gadgets_hide();
e_configure_registry_call("extensions/gadman", NULL, NULL);
}
static void
on_menu_delete(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
E_Gadcon_Client *gcc = data;
e_gadcon_client_config_del(gcc->gadcon->cf, gcc->cf);
e_object_del(data);
e_config_save_queue();
}
static void
on_frame_click(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Down *ev;
E_Gadcon_Client *gcc;
ev = event_info;
gcc = data;
if (ev->button == 5)
{
E_Menu *m;
int cx, cy, cw, ch;
m = e_menu_new();
m = e_gadcon_client_util_menu_items_append(gcc, m, 0);
gcc->menu = m;
e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, &cw, &ch);
e_menu_activate_mouse(m,
e_zone_current_get(),
cx + ev->output.x, cy + ev->output.y, 1, 1,
E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
evas_event_feed_mouse_up(gcc->gadcon->evas, ev->button,
EVAS_BUTTON_NONE, ev->timestamp, NULL);
}
}
static void
on_top(void *data, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
static int ox, oy, ow, oh; //Object coord
int mx, my; //Mouse coord
int action = (int)(long)data;
Evas_Object *mover;
E_Gadcon_Client *drag_gcc;
int layer = Man->visible;
drag_gcc = Man->drag_gcc[layer];
if (!drag_gcc) return;
mover = _get_mover(drag_gcc);
if (!mover) return;
mover_lock = EINA_TRUE;
if (action == DRAG_START)
{
drag_gcc->resizing = 1;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
drag_gcc->dy = my - oy;
}
else if (action == DRAG_STOP)
{
drag_gcc->resizing = 0;
drag_gcc->dy = 0;
_save_widget_position(drag_gcc);
}
else if ((action == DRAG_MOVE) && drag_gcc->resizing)
{
int h;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
h = oy + oh + drag_gcc->dy - my;
if (h < drag_gcc->min.h)
{
my -= drag_gcc->min.h - h;
h = drag_gcc->min.h;
}
/* don't go out of the screen */
if (my < drag_gcc->dy)
{
h += my - drag_gcc->dy;
my = drag_gcc->dy;
}
if (drag_gcc->aspect.w && drag_gcc->aspect.h)
{
ow = h * drag_gcc->aspect.w / drag_gcc->aspect.h;
}
evas_object_resize(mover, ow, h);
evas_object_move(mover, ox, my - drag_gcc->dy);
drag_gcc->max.w = ow, drag_gcc->max.h = h;
evas_object_resize(drag_gcc->o_frame, ow, h);
evas_object_move(drag_gcc->o_frame, ox, my - drag_gcc->dy);
_save_widget_position(drag_gcc);
}
mover_lock = EINA_FALSE;
}
static void
on_right(void *data, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
Evas_Object *mover;
static int ox, oy, ow, oh; //Object coord
int mx, my; //Mouse coord
int action;
E_Gadcon_Client *drag_gcc;
int layer = Man->visible;
drag_gcc = Man->drag_gcc[layer];
if (!drag_gcc) return;
mover = _get_mover(drag_gcc);
if (!mover) return;
mover_lock = EINA_TRUE;
action = (int)(long)data;
if (action == DRAG_START)
{
drag_gcc->resizing = 1;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
drag_gcc->dx = mx - ow;
}
else if (action == DRAG_STOP)
{
drag_gcc->resizing = 0;
drag_gcc->dx = 0;
_save_widget_position(drag_gcc);
}
else if ((action == DRAG_MOVE) && drag_gcc->resizing)
{
int w;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
w = mx - drag_gcc->dx;
if (w < drag_gcc->min.w) w = drag_gcc->min.w;
/* don't go out of the screen */
if (w > (Man->width - ox)) w = Man->width - ox;
if (drag_gcc->aspect.w && drag_gcc->aspect.h)
{
oh = w * drag_gcc->aspect.h / drag_gcc->aspect.w;
}
drag_gcc->max.w = w, drag_gcc->max.h = oh;
evas_object_resize(mover, w, oh);
evas_object_resize(drag_gcc->o_frame, w, oh);
_save_widget_position(drag_gcc);
}
mover_lock = EINA_FALSE;
}
static void
on_down(void *data, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
Evas_Object *mover;
static int ox, oy, ow, oh; //Object coord
int mx, my; //Mouse coord
int action = (int)(long)data;
E_Gadcon_Client *drag_gcc;
int layer = Man->visible;
drag_gcc = Man->drag_gcc[layer];
if (!drag_gcc) return;
mover = _get_mover(drag_gcc);
if (!mover) return;
mover_lock = EINA_TRUE;
if (action == DRAG_START)
{
drag_gcc->resizing = 1;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
drag_gcc->dy = my - oh;
}
else if (action == DRAG_STOP)
{
drag_gcc->resizing = 0;
drag_gcc->dy = 0;
_save_widget_position(drag_gcc);
}
else if ((action == DRAG_MOVE) && drag_gcc->resizing)
{
int h;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
h = my - drag_gcc->dy;
if (h < drag_gcc->min.h) h = drag_gcc->min.h;
/* don't go out of the screen */
if (h > (Man->height - oy)) h = Man->height - oy;
if (drag_gcc->aspect.w && drag_gcc->aspect.h)
{
ow = h * drag_gcc->aspect.w / drag_gcc->aspect.h;
}
evas_object_resize(mover, ow, h);
drag_gcc->max.w = ow, drag_gcc->max.h = h;
evas_object_resize(drag_gcc->o_frame, ow, h);
_save_widget_position(drag_gcc);
}
mover_lock = EINA_FALSE;
}
static void
on_left(void *data, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
Evas_Object *mover;
static int ox, oy, ow, oh; //Object coord
int mx, my; //Mouse coord
int action = (int)(long)data;
E_Gadcon_Client *drag_gcc;
int layer = Man->visible;
drag_gcc = Man->drag_gcc[layer];
if (!drag_gcc) return;
mover = _get_mover(drag_gcc);
if (!mover) return;
mover_lock = EINA_TRUE;
if (action == DRAG_START)
{
drag_gcc->resizing = 1;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
drag_gcc->dx = mx - ox;
}
else if (action == DRAG_STOP)
{
drag_gcc->resizing = 0;
drag_gcc->dx = 0;
_save_widget_position(drag_gcc);
}
else if ((action == DRAG_MOVE) && drag_gcc->resizing)
{
int w;
evas_pointer_output_xy_get(drag_gcc->gadcon->evas, &mx, &my);
w = ox + ow + drag_gcc->dx - mx;
if (w < drag_gcc->min.w)
{
mx -= drag_gcc->min.w - w;
w = drag_gcc->min.w;
}
/* don't go out of the screen */
if (mx < drag_gcc->dx)
{
w += mx - drag_gcc->dx;
mx = drag_gcc->dx;
}
if (drag_gcc->aspect.w && drag_gcc->aspect.h)
{
oh = w * drag_gcc->aspect.h / drag_gcc->aspect.w;
}
evas_object_resize(mover, w, oh);
evas_object_move(mover, mx - drag_gcc->dx, oy);
drag_gcc->max.w = w, drag_gcc->max.h = oh;
evas_object_resize(drag_gcc->o_frame, w, oh);
evas_object_move(drag_gcc->o_frame, mx - drag_gcc->dx, oy);
_save_widget_position(drag_gcc);
}
mover_lock = EINA_FALSE;
}
static void
on_move(void *data, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
Evas_Object *mover;
static int ox, oy; //Starting object position
static int ow, oh; //Starting object size
int mx, my; //Mouse coord
int action = (int)(long)data;
E_Gadcon *gc;
E_Gadcon_Client *drag_gcc;
E_Drag *drag;
const char *drag_types[] = { "enlightenment/gadcon_client" };
/* DRAG_START */
if (action != DRAG_START) return;
drag_gcc = Man->drag_gcc[Man->visible];
if (!drag_gcc) return;
gc = drag_gcc->gadcon;
mover = _get_mover(drag_gcc);
drag_gcc->moving = 1;
gc->cf->clients = eina_list_remove(gc->cf->clients, drag_gcc->cf);
e_gadcon_client_drag_set(drag_gcc);
e_object_ref(E_OBJECT(drag_gcc));
evas_pointer_output_xy_get(gc->evas, &mx, &my);
evas_object_geometry_get(mover, &ox, &oy, &ow, &oh);
drag_gcc->dx = mx - ox;
drag_gcc->dy = my - oy;
drag_gcc->drag.drag = drag = e_drag_new(mx, my,
drag_types, 1, drag_gcc, -1, NULL,
e_gadcon_drag_finished_cb);
if (!drag) return;
drag->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
o = drag_gcc->client_class->func.icon((E_Gadcon_Client_Class *)drag_gcc->client_class,
e_drag_evas_get(drag));
if (!o)
{
/* FIXME: fallback icon for drag */
o = evas_object_rectangle_add(e_drag_evas_get(drag));
evas_object_color_set(o, 255, 255, 255, 100);
}
e_drag_object_set(drag, o);
e_drag_resize(drag, ow, oh);
e_drag_start(drag, mx, my);
e_drag_hide(drag);
}
static void
on_bg_click(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
gadman_gadgets_hide();
}
static void
on_hide_stop(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *em EINA_UNUSED, const char *src EINA_UNUSED)
{
evas_object_hide(Man->overlay);
}
static int
_e_gadman_client_add(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc)
{
return !!gadman_gadget_add(cc, gcc, (intptr_t)data);
}
static void
_e_gadman_client_remove(void *data EINA_UNUSED, E_Gadcon_Client *gcc)
{
if (gcc->cf)
gcc->gadcon->cf->clients = eina_list_remove(gcc->gadcon->cf->clients, gcc->cf);
e_object_del(E_OBJECT(gcc));
}
static void
_e_gadman_handlers_add(void)
{
E_LIST_HANDLER_APPEND(_gadman_hdls, E_EVENT_ZONE_ADD, _e_gadman_cb_zone_change, NULL);
E_LIST_HANDLER_APPEND(_gadman_hdls, E_EVENT_ZONE_MOVE_RESIZE, _e_gadman_cb_zone_change, NULL);
E_LIST_HANDLER_APPEND(_gadman_hdls, E_EVENT_ZONE_DEL, _e_gadman_cb_zone_change, NULL);
E_LIST_HANDLER_APPEND(_gadman_hdls, E_EVENT_MODULE_UPDATE, _gadman_module_cb, NULL);
E_LIST_HANDLER_APPEND(_gadman_hdls, E_EVENT_MODULE_INIT_END, _gadman_module_init_end_cb, NULL);
}
static void
_e_gadman_handler_del(void)
{
E_FREE_LIST(_gadman_hdls, ecore_event_handler_del);
}
static Eina_Bool
_gadman_module_init_end_cb(void *d EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
gadman_locked = EINA_FALSE;
gadman_reset(NULL);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_gadman_module_cb(void *d EINA_UNUSED, int type EINA_UNUSED, E_Event_Module_Update *ev)
{
if (!ev->enabled)
{
Eina_List *l;
E_Config_Gadcon_Client *cf_gcc;
E_Gadcon_Client *gcc;
l = eina_hash_set(_gadman_gadgets, ev->name, NULL);
if (!l) return ECORE_CALLBACK_RENEW;
EINA_LIST_FREE(l, cf_gcc)
{
gcc = e_gadcon_client_find(NULL, cf_gcc);
if (!gcc) continue;
gcc->cf = NULL;
e_object_del(E_OBJECT(gcc));
}
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_gadman_cb_zone_change(void *data EINA_UNUSED, int type, void *event)
{
E_Gadcon *gc;
Eina_List *l, *ll;
E_Event_Zone_Move_Resize *ev = event;
const char *layer_name[] = {"gadman", "gadman_top"};
int layer;
E_Gadcon_Client *gcc;
if (!Man) return ECORE_CALLBACK_RENEW;
if (gadman_locked) return ECORE_CALLBACK_RENEW;
if (type == E_EVENT_ZONE_MOVE_RESIZE)
{
/* probably zone dirty being set */
EINA_LIST_FOREACH(Man->gadcons[GADMAN_LAYER_BG], l, gc)
{
if (e_gadcon_zone_get(gc) != ev->zone) continue;
EINA_LIST_FOREACH(gc->clients, ll, gcc)
_apply_widget_position(gcc);
return ECORE_CALLBACK_RENEW;
}
}
if (type == E_EVENT_ZONE_DEL)
{
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
EINA_LIST_FOREACH(Man->gadcons[layer], l, gc)
{
if (e_gadcon_zone_get(gc) != ev->zone) continue;
e_object_del(E_OBJECT(gc));
Man->gadcons[layer] = eina_list_remove_list(Man->gadcons[layer], l);
E_FREE_FUNC(Man->movers[layer], evas_object_del);
break;
}
}
evas_object_hide(Man->overlay);
E_FREE_FUNC(Man->overlay, evas_object_del);
_gadman_overlay_create();
return ECORE_CALLBACK_RENEW;
}
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
Eina_Bool found = EINA_FALSE;
EINA_LIST_FOREACH(Man->gadcons[GADMAN_LAYER_BG], l, gc)
if (e_gadcon_zone_get(gc) == ev->zone)
{
found = EINA_TRUE;
break;
}
if (found) continue;
gc = _gadman_gadcon_new(layer_name[layer], layer, ev->zone, Man->location[layer]);
Man->gadcons[layer] = eina_list_append(Man->gadcons[layer], gc);
gc->drop_handler->base = Man->overlay;
gc->drop_handler->hidden = 1;
}
return ECORE_CALLBACK_PASS_ON;
}