#include "e.h" static void _e_shelf_new_dialog_ok(void *data, char *text); static void _e_shelf_del_cb(void *d); static void _e_shelf_free(E_Shelf *es); static void _e_shelf_gadcon_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h); static void _e_shelf_gadcon_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h); static Evas_Object *_e_shelf_gadcon_frame_request(void *data, E_Gadcon_Client *gcc, const char *style); static void _e_shelf_toggle_client_fix(E_Shelf *es); static void _e_shelf_cb_menu_config(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_shelf_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_shelf_cb_menu_contents(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_shelf_cb_confirm_dialog_yes(void *data); static void _e_shelf_cb_menu_delete(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_shelf_menu_append(E_Shelf *es, E_Menu *mn); static void _e_shelf_cb_menu_items_append(void *data, E_Gadcon_Client *gcc, E_Menu *mn); static void _e_shelf_cb_locked_set(void *data, int lock); static void _e_shelf_cb_urgent_show(void *data); static void _e_shelf_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info); static Eina_Bool _e_shelf_cb_mouse_in(void *data, int type, void *event); //static Eina_Bool _e_shelf_cb_mouse_out(void *data, int type, void *event); //static void _e_shelf_cb_mouse_out2(E_Shelf *es, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Out *ev); static int _e_shelf_cb_id_sort(const void *data1, const void *data2); static void _e_shelf_cb_menu_rename(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED); static Eina_Bool _e_shelf_cb_hide_animator(void *data); static Eina_Bool _e_shelf_cb_hide_animator_timer(void *data); static Eina_Bool _e_shelf_cb_hide_urgent_timer(void *data); static Eina_Bool _e_shelf_cb_instant_hide_timer(void *data); static void _e_shelf_menu_pre_cb(void *data, E_Menu *m); static void _e_shelf_gadcon_client_remove(void *data, E_Gadcon_Client *gcc); static int _e_shelf_gadcon_client_add(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc); static const char *_e_shelf_orient_icon_name_get(E_Shelf *s); static void _e_shelf_bindings_add(E_Shelf *es); static void _e_shelf_bindings_del(E_Shelf *es); static Eina_Bool _e_shelf_on_current_desk(E_Shelf *es, E_Event_Zone_Edge *ev); static void _e_shelf_cb_dummy_del(E_Shelf *, Evas *e, Evas_Object *obj, void *event_info); static void _e_shelf_cb_dummy_moveresize(E_Shelf *, Evas *e, Evas_Object *obj, void *event_info); static Eina_Bool _e_shelf_gadcon_populate_handler_cb(void *, int, void *); static void _e_shelf_event_rename_end_cb(void *data, E_Event_Shelf *ev); static Eina_List *shelves = NULL; static Eina_List *dummies = NULL; static int orientations[] = { [E_GADCON_ORIENT_FLOAT] = 2, [E_GADCON_ORIENT_HORIZ] = 2, [E_GADCON_ORIENT_VERT] = 2, [E_GADCON_ORIENT_LEFT] = 37, [E_GADCON_ORIENT_RIGHT] = 31, [E_GADCON_ORIENT_TOP] = 29, [E_GADCON_ORIENT_BOTTOM] = 23, [E_GADCON_ORIENT_CORNER_TL] = 19, [E_GADCON_ORIENT_CORNER_TR] = 17, [E_GADCON_ORIENT_CORNER_BL] = 13, [E_GADCON_ORIENT_CORNER_BR] = 11, [E_GADCON_ORIENT_CORNER_LT] = 7, [E_GADCON_ORIENT_CORNER_RT] = 5, [E_GADCON_ORIENT_CORNER_LB] = 3, [E_GADCON_ORIENT_CORNER_RB] = 2 }; static const char *orient_names[] = { [E_GADCON_ORIENT_FLOAT] = N_("Float"), [E_GADCON_ORIENT_HORIZ] = N_("Horizontal"), [E_GADCON_ORIENT_VERT] = N_("Vertical"), [E_GADCON_ORIENT_LEFT] = N_("Left"), [E_GADCON_ORIENT_RIGHT] = N_("Right"), [E_GADCON_ORIENT_TOP] = N_("Top"), [E_GADCON_ORIENT_BOTTOM] = N_("Bottom"), [E_GADCON_ORIENT_CORNER_TL] = N_("Top-left Corner"), [E_GADCON_ORIENT_CORNER_TR] = N_("Top-right Corner"), [E_GADCON_ORIENT_CORNER_BL] = N_("Bottom-left Corner"), [E_GADCON_ORIENT_CORNER_BR] = N_("Bottom-right Corner"), [E_GADCON_ORIENT_CORNER_LT] = N_("Left-top Corner"), [E_GADCON_ORIENT_CORNER_RT] = N_("Right-top Corner"), [E_GADCON_ORIENT_CORNER_LB] = N_("Left-bottom Corner"), [E_GADCON_ORIENT_CORNER_RB] = N_("Right-bottom Corner") }; E_API int E_EVENT_SHELF_RENAME = -1; E_API int E_EVENT_SHELF_ADD = -1; E_API int E_EVENT_SHELF_DEL = -1; static Eina_List *handlers; static inline Eina_Bool _e_shelf_is_horizontal(const E_Shelf *es) { Eina_Bool horiz = EINA_FALSE; switch (es->gadcon->orient) { case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: horiz = 1; break; case E_GADCON_ORIENT_VERT: case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_CORNER_RT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_RB: horiz = 0; break; default: break; } return horiz; } static void _e_shelf_remaximize(E_Shelf *es) { E_Client *ec; if ((!e_config->border_fix_on_shelf_toggle) || es->cfg->overlap) return; E_CLIENT_FOREACH(ec) { E_Maximize max = ec->maximized; if (!ec->maximized) continue; if ((!ec->sticky) && (!e_shelf_desk_visible(es, ec->desk ?: e_desk_current_get(es->zone)))) continue; e_client_unmaximize(ec, ec->maximized); e_client_maximize(ec, max); } } static void _e_shelf_obstacles_update(E_Shelf *es) { Eina_List *l; E_Zone_Obstacle *obs; EINA_LIST_FOREACH(es->zone_obstacles, l, obs) e_zone_obstacle_modify(obs, &(Eina_Rectangle){es->x + es->zone->x, es->y + es->zone->y, es->w, es->h}, !_e_shelf_is_horizontal(es)); } static Eina_Bool _e_shelf_desk_count_handler(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Desk_Count_Set *ev) { Eina_List *l; E_Shelf *es; EINA_LIST_FOREACH(shelves, l, es) if (es->cfg->desk_show_mode && (ev->zone == es->zone)) e_shelf_obstacles_update(es); return ECORE_CALLBACK_RENEW; } static Eina_Bool _e_shelf_autohide_timer_extend(E_Shelf *es) { if (es->autohide_timer && es->hide_timer) { ecore_timer_loop_reset(es->autohide_timer); ecore_timer_loop_reset(es->hide_timer); return EINA_TRUE; } ecore_timer_del(es->autohide_timer); es->autohide_timer = NULL; return EINA_FALSE; } /* externally accessible functions */ EINTERN int e_shelf_init(void) { E_EVENT_SHELF_RENAME = ecore_event_type_new(); E_EVENT_SHELF_ADD = ecore_event_type_new(); E_EVENT_SHELF_DEL = ecore_event_type_new(); E_LIST_HANDLER_APPEND(handlers, E_EVENT_GADCON_POPULATE, _e_shelf_gadcon_populate_handler_cb, NULL); E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET, _e_shelf_desk_count_handler, NULL); return 1; } EINTERN int e_shelf_shutdown(void) { if (x_fatal) return 1; while (shelves) { E_Shelf *es; es = eina_list_data_get(shelves); e_object_del(E_OBJECT(es)); } E_FREE_LIST(handlers, ecore_event_handler_del); return 1; } E_API void e_shelf_config_update(void) { Eina_List *l; E_Config_Shelf *cf_es; int id = 0; while (shelves) { E_Shelf *es; es = eina_list_data_get(shelves); e_object_del(E_OBJECT(es)); } EINA_LIST_FOREACH(e_config->shelves, l, cf_es) { E_Zone *zone; if (cf_es->id <= 0) cf_es->id = id + 1; zone = e_comp_zone_number_get(cf_es->zone); if (zone) e_shelf_config_new(zone, cf_es); id = cf_es->id; } } E_API Eina_List * e_shelf_list_all(void) { Eina_List *d = NULL, *s = NULL, *ret = NULL; if (shelves) s = eina_list_clone(shelves); if (dummies) d = eina_list_clone(dummies); if (s && d) ret = eina_list_merge(s, d); else ret = d ? : s; return ret; } E_API Eina_List * e_shelf_list(void) { shelves = eina_list_sort(shelves, -1, _e_shelf_cb_id_sort); return shelves; } E_API E_Shelf * e_shelf_zone_dummy_new(E_Zone *zone, Evas_Object *obj, int id) { E_Shelf *es; es = E_OBJECT_ALLOC(E_Shelf, E_SHELF_DUMMY_TYPE, _e_shelf_free); if (!es) return NULL; es->id = id; evas_object_geometry_get(obj, &es->x, &es->y, &es->w, &es->h); evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_del, es); evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es); evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es); es->zone = zone; es->dummy = 1; es->o_base = obj; es->cfg = E_NEW(E_Config_Shelf, 1); e_object_del_attach_func_set(E_OBJECT(es), _e_shelf_del_cb); dummies = eina_list_append(dummies, es); return es; } static void _e_shelf_hidden(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { E_Shelf *es = data; es->hiding = 0; } static Eina_Bool _shelf_content_fix(void *data) { // I really don't know how it gets here but objects and their geometry are // wrong - something to do woith zoomap as well as geometry changing // at the same time so things going weird with child size and thus // position etc. E_Shelf *es = data; int w, h; es->fix_timer = NULL; w = es->w; h = es->h; e_shelf_resize(es, w + 1, h + 1); e_shelf_resize(es, w, h); return EINA_FALSE; } E_API E_Shelf * e_shelf_zone_new(E_Zone *zone, const char *name, const char *style, E_Layer layer, int id) { E_Shelf *es; char buf[1024]; E_Comp_Object_Type type = E_COMP_OBJECT_TYPE_POPUP; es = E_OBJECT_ALLOC(E_Shelf, E_SHELF_TYPE, _e_shelf_free); if (!es) return NULL; es->id = id; es->x = 0; es->y = 0; es->w = 32; es->h = 32; es->zone = zone; e_object_del_attach_func_set(E_OBJECT(es), _e_shelf_del_cb); es->ee = e_comp->ee; es->evas = e_comp->evas; es->fit_along = 1; es->layer = layer; E_LIST_HANDLER_APPEND(es->handlers, E_EVENT_ZONE_EDGE_MOVE, _e_shelf_cb_mouse_in, es); es->o_base = edje_object_add(es->evas); evas_object_name_set(es->o_base, "shelf"); evas_object_event_callback_add(es->o_base, EVAS_CALLBACK_MOUSE_DOWN, _e_shelf_cb_mouse_down, es); es->name = eina_stringshare_add(name); evas_object_resize(es->o_base, es->w, es->h); e_shelf_style_set(es, style); evas_object_move(es->o_base, es->zone->x + es->x, es->zone->y + es->y); if ((layer == E_LAYER_DESKTOP) || edje_object_data_get(es->o_base, "noshadow")) type = E_COMP_OBJECT_TYPE_NONE; es->comp_object = e_comp_object_util_add(es->o_base, type); evas_object_event_callback_add(es->comp_object, EVAS_CALLBACK_HIDE, _e_shelf_hidden, es); evas_object_data_set(es->comp_object, "E_Shelf", es); evas_object_data_set(es->comp_object, "comp_skip", (void*)1); evas_object_name_set(es->comp_object, es->name); evas_object_layer_set(es->comp_object, layer); evas_object_lower(es->comp_object); es->gadcon = e_gadcon_swallowed_new(es->name, es->id, es->o_base, "e.swallow.content"); if (es->name) snprintf(buf, sizeof(buf), "%s", es->name); else snprintf(buf, sizeof(buf), _("Shelf #%d"), es->id); es->gadcon->location = e_gadcon_location_new(buf, E_GADCON_SITE_SHELF, _e_shelf_gadcon_client_add, es, _e_shelf_gadcon_client_remove, es); e_gadcon_location_register(es->gadcon->location); // hmm dnd in ibar and ibox kill this. ok. need to look into this more // es->gadcon->instant_edit = 1; e_gadcon_min_size_request_callback_set(es->gadcon, _e_shelf_gadcon_min_size_request, es); e_gadcon_size_request_callback_set(es->gadcon, _e_shelf_gadcon_size_request, es); e_gadcon_frame_request_callback_set(es->gadcon, _e_shelf_gadcon_frame_request, es); e_gadcon_orient(es->gadcon, E_GADCON_ORIENT_TOP); snprintf(buf, sizeof(buf), "e,state,orientation,%s", e_shelf_orient_string_get(es)); edje_object_signal_emit(es->o_base, buf, "e"); edje_object_message_signal_process(es->o_base); e_gadcon_zone_set(es->gadcon, zone); e_gadcon_ecore_evas_set(es->gadcon, es->ee); e_gadcon_shelf_set(es->gadcon, es); e_gadcon_xdnd_window_set(es->gadcon, e_comp->ee_win); e_gadcon_dnd_window_set(es->gadcon, e_comp->ee_win); evas_object_clip_set(es->comp_object, es->zone->bg_clip_object); e_gadcon_util_menu_attach_func_set(es->gadcon, _e_shelf_cb_menu_items_append, es); e_gadcon_util_lock_func_set(es->gadcon, _e_shelf_cb_locked_set, es); e_gadcon_util_urgent_show_func_set(es->gadcon, _e_shelf_cb_urgent_show, es); shelves = eina_list_append(shelves, es); es->hidden = 0; es->locked = 0; es->hide_origin = -1; { E_Event_Shelf *ev; ev = E_NEW(E_Event_Shelf, 1); ev->shelf = es; ecore_event_add(E_EVENT_SHELF_ADD, ev, NULL, NULL); } es->fix_timer = ecore_timer_add(0.1, _shelf_content_fix, es); return es; } E_API void e_shelf_rename_dialog(E_Shelf *es) { if (!es) return; if (es->rename_dialog) return; _e_shelf_cb_menu_rename(es, NULL, NULL); } E_API void e_shelf_zone_move_resize_handle(E_Zone *zone) { Eina_List *l; E_Shelf *es; Evas_Coord w, h; EINA_LIST_FOREACH(shelves, l, es) { if (es->zone == zone) { E_Gadcon *gc; gc = es->gadcon; if (gc->min_size_request.func) { /* let gadcon container decrease to any size */ evas_object_size_hint_min_set(gc->o_container, 0, 0); } evas_object_smart_callback_call(gc->o_container, "min_size_request", NULL); e_shelf_position_calc(es); if (gc->min_size_request.func) { evas_object_geometry_get(gc->o_container, NULL, NULL, &w, &h); /* fix gadcon container min size to current geometry */ evas_object_size_hint_min_set(gc->o_container, w, h); } } } } E_API void e_shelf_populate(E_Shelf *es) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); e_gadcon_populate(es->gadcon); } E_API void e_shelf_show(E_Shelf *es) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if (es->hiding) evas_object_hide(es->comp_object); evas_object_show(es->comp_object); } E_API void e_shelf_hide(E_Shelf *es) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); evas_object_hide(es->comp_object); es->hiding = evas_object_visible_get(es->comp_object); } E_API void e_shelf_locked_set(E_Shelf *es, int lock) { if (lock) { e_shelf_toggle(es, 1); es->locked++; } else { if (es->locked > 0) es->locked--; if (!es->locked) e_shelf_toggle(es, es->toggle); } } E_API void e_shelf_name_set(E_Shelf *es, const char *name) { E_Event_Shelf *ev; if (!es) return; if (!name) return; if (es->name == name) return; eina_stringshare_replace(&es->name, name); eina_stringshare_replace(&es->cfg->name, name); ev = E_NEW(E_Event_Shelf, 1); ev->shelf = es; e_object_ref(E_OBJECT(es)); ecore_event_add(E_EVENT_SHELF_RENAME, ev, (Ecore_End_Cb)_e_shelf_event_rename_end_cb, NULL); if (es->dummy) return; e_gadcon_name_set(es->gadcon, name); } E_API void e_shelf_toggle(E_Shelf *es, int show) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); es->toggle = show; if (!es->hidden && _e_shelf_autohide_timer_extend(es)) return; if (es->locked) return; es->interrupted = -1; es->urgent_show = 0; if ((show) && (es->hidden)) { es->hidden = 0; edje_object_signal_emit(es->o_base, "e,state,visible", "e"); if (es->instant_delay >= 0.0) { _e_shelf_cb_instant_hide_timer(es); es->hide_timer = ecore_timer_loop_add(es->cfg->hide_timeout, _e_shelf_cb_hide_urgent_timer, es); } else { if (es->hide_timer) { ecore_timer_del(es->hide_timer); es->hide_timer = NULL; return; //we should not add a animator here, the shelf cannot have moved yet. } if (!es->hide_animator) { es->hide_begin = ecore_loop_time_get(); es->hide_animator = ecore_animator_add(_e_shelf_cb_hide_animator, es); } else { double time_elapsed = ecore_loop_time_get() - es->hide_begin; es->hide_begin = ecore_loop_time_get() - (es->cfg->hide_duration - time_elapsed); } } } else if ((!show) && (!es->hidden) && ((!es->gadcon) || (!es->gadcon->editing)) && (es->cfg->autohide)) { if (es->instant_delay >= 0.0) { if (es->hide_timer) { ecore_timer_del(es->hide_timer); es->hide_timer = NULL; } es->hidden = 1; if (!es->instant_timer) es->instant_timer = ecore_timer_loop_add(es->instant_delay, _e_shelf_cb_instant_hide_timer, es); } else { if (es->hide_animator) { es->interrupted = show; return; } es->hidden = 1; if (es->hide_timer) ecore_timer_del(es->hide_timer); es->hide_timer = ecore_timer_loop_add(es->cfg->hide_timeout, _e_shelf_cb_hide_animator_timer, es); } } } E_API void e_shelf_urgent_show(E_Shelf *es) { e_shelf_toggle(es, 1); es->urgent_show = 1; } E_API void e_shelf_move(E_Shelf *es, int x, int y) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if ((es->x == x) && (es->y == y)) return; es->x = x; es->y = y; evas_object_move(es->comp_object, es->zone->x + es->x, es->zone->y + es->y); _e_shelf_obstacles_update(es); if (!es->hide_animator) _e_shelf_remaximize(es); } E_API void e_shelf_resize(E_Shelf *es, int w, int h) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if ((es->w == w) && (es->h == h)) return; es->w = w; es->h = h; evas_object_resize(es->comp_object, es->w, es->h); _e_shelf_obstacles_update(es); if (!es->hide_animator) _e_shelf_remaximize(es); } E_API void e_shelf_move_resize(E_Shelf *es, int x, int y, int w, int h) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if ((es->x == x) && (es->y == y) && (es->w == w) && (es->h == h)) return; es->x = x; es->y = y; es->w = w; es->h = h; evas_object_geometry_set(es->comp_object, es->zone->x + es->x, es->zone->y + es->y, es->w, es->h); _e_shelf_obstacles_update(es); if (!es->hide_animator) _e_shelf_remaximize(es); } E_API void e_shelf_save(E_Shelf *es) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if (es->cfg) { es->cfg->orient = es->gadcon->orient; if (es->cfg->style) eina_stringshare_del(es->cfg->style); es->cfg->style = eina_stringshare_add(es->style); } else { E_Config_Shelf *cf_es; cf_es = E_NEW(E_Config_Shelf, 1); cf_es->name = eina_stringshare_add(es->name); cf_es->zone = es->zone->num; cf_es->layer = es->layer; e_config->shelves = eina_list_append(e_config->shelves, cf_es); cf_es->orient = es->gadcon->orient; cf_es->style = eina_stringshare_add(es->style); cf_es->fit_along = es->fit_along; cf_es->fit_size = es->fit_size; cf_es->overlap = 0; cf_es->autohide = 0; cf_es->hide_timeout = 1.0; cf_es->hide_duration = 1.0; es->cfg = cf_es; } e_config_save_queue(); } E_API void e_shelf_unsave(E_Shelf *es) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); es->cfg_delete = 1; } E_API void e_shelf_orient(E_Shelf *es, E_Gadcon_Orient orient) { char buf[4096]; E_OBJECT_CHECK(es); E_OBJECT_IF_NOT_TYPE(es, E_SHELF_DUMMY_TYPE) { E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); } if (!es->dummy) { e_gadcon_orient(es->gadcon, orient); snprintf(buf, sizeof(buf), "e,state,orientation,%s", e_shelf_orient_string_get(es)); edje_object_signal_emit(es->o_base, buf, "e"); edje_object_message_signal_process(es->o_base); e_gadcon_location_set_icon_name(es->gadcon->location, _e_shelf_orient_icon_name_get(es)); } e_zone_useful_geometry_dirty(es->zone); } E_API const char * e_shelf_orient_string_get(E_Shelf *es) { const char *sig = ""; switch (es->gadcon->orient) { case E_GADCON_ORIENT_FLOAT: sig = "float"; break; case E_GADCON_ORIENT_HORIZ: sig = "horizontal"; break; case E_GADCON_ORIENT_VERT: sig = "vertical"; break; case E_GADCON_ORIENT_LEFT: sig = "left"; break; case E_GADCON_ORIENT_RIGHT: sig = "right"; break; case E_GADCON_ORIENT_TOP: sig = "top"; break; case E_GADCON_ORIENT_BOTTOM: sig = "bottom"; break; case E_GADCON_ORIENT_CORNER_TL: sig = "top_left"; break; case E_GADCON_ORIENT_CORNER_TR: sig = "top_right"; break; case E_GADCON_ORIENT_CORNER_BL: sig = "bottom_left"; break; case E_GADCON_ORIENT_CORNER_BR: sig = "bottom_right"; break; case E_GADCON_ORIENT_CORNER_LT: sig = "left_top"; break; case E_GADCON_ORIENT_CORNER_RT: sig = "right_top"; break; case E_GADCON_ORIENT_CORNER_LB: sig = "left_bottom"; break; case E_GADCON_ORIENT_CORNER_RB: sig = "right_bottom"; break; default: break; } return sig; } E_API void e_shelf_position_calc(E_Shelf *es) { E_Gadcon_Orient orient = E_GADCON_ORIENT_FLOAT; int size = (40 * e_scale); int x, y, w, h; x = es->x, y = es->y, w = es->w, h = es->h; if (es->cfg) { orient = es->cfg->orient; size = es->cfg->size * e_scale; } else orient = es->gadcon->orient; switch (orient) { case E_GADCON_ORIENT_FLOAT: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; break; case E_GADCON_ORIENT_HORIZ: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = (es->zone->w - w) / 2; break; case E_GADCON_ORIENT_VERT: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; y = (es->zone->h - h) / 2; break; case E_GADCON_ORIENT_LEFT: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = 0; y = (es->zone->h - h) / 2; break; case E_GADCON_ORIENT_RIGHT: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = es->zone->w - w; y = (es->zone->h - h) / 2; break; case E_GADCON_ORIENT_TOP: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = (es->zone->w - w) / 2; y = 0; break; case E_GADCON_ORIENT_BOTTOM: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = (es->zone->w - w) / 2; y = es->zone->h - h; break; case E_GADCON_ORIENT_CORNER_TL: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = 0; y = 0; break; case E_GADCON_ORIENT_CORNER_TR: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = es->zone->w - w; y = 0; break; case E_GADCON_ORIENT_CORNER_BL: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = 0; y = es->zone->h - h; break; case E_GADCON_ORIENT_CORNER_BR: if (!es->fit_along) w = es->zone->w; if (!es->fit_size) h = size; x = es->zone->w - w; y = es->zone->h - h; break; case E_GADCON_ORIENT_CORNER_LT: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = 0; y = 0; break; case E_GADCON_ORIENT_CORNER_RT: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = es->zone->w - w; y = 0; break; case E_GADCON_ORIENT_CORNER_LB: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = 0; y = es->zone->h - h; break; case E_GADCON_ORIENT_CORNER_RB: if (!es->fit_along) h = es->zone->h; if (!es->fit_size) w = size; x = es->zone->w - w; y = es->zone->h - h; break; default: break; } es->hide_origin = -1; if ((es->x == x) && (es->y == y) && (es->w == w) && (es->h == h)) return; e_shelf_move_resize(es, x, y, w, h); if (es->hidden) { es->hidden = 0; e_shelf_toggle(es, 0); } e_zone_useful_geometry_dirty(es->zone); _e_shelf_bindings_add(es); do { Eina_Bool err = EINA_FALSE; if (!es->cfg) break; if (!es->zone) break; if (!es->cfg->autohide) break; switch (es->cfg->orient) { case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_CORNER_LB: if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_LEFT)) break; err = EINA_TRUE; break; case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RT: case E_GADCON_ORIENT_CORNER_RB: if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_RIGHT)) break; err = EINA_TRUE; break; case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_TOP)) break; err = EINA_TRUE; break; case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_BOTTOM)) break; err = EINA_TRUE; break; } if (err) e_util_dialog_show(_("Shelf Autohide Error"), _("Shelf autohiding will not work properly" "with the current configuration; set your shelf to" "\"Below Everything\" or disable autohiding.")); break; } while (0); } E_API Eina_Bool e_shelf_desk_visible(const E_Shelf *es, const E_Desk *desk) { Eina_List *ll; E_Config_Shelf *cf_es; E_Zone *zone; E_Config_Shelf_Desk *sd; EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE); if (!desk) { EINA_LIST_FOREACH(e_comp->zones, ll, zone) { desk = e_desk_current_get(zone); if (e_shelf_desk_visible(es, desk)) return EINA_TRUE; } return EINA_FALSE; } cf_es = es->cfg; if (!cf_es) return EINA_FALSE; zone = desk->zone; if (cf_es->zone != (int)zone->num) return EINA_FALSE; if (!es->cfg->desk_show_mode) return EINA_TRUE; EINA_LIST_FOREACH(es->cfg->desk_list, ll, sd) { if (!sd) continue; if ((desk->x == sd->x) && (desk->y == sd->y)) return EINA_TRUE; } return EINA_FALSE; } E_API void e_shelf_style_set(E_Shelf *es, const char *style) { const char *option; char buf[1024]; E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if (!es->o_base) return; if (style != es->style) eina_stringshare_replace(&es->style, style); if (style) snprintf(buf, sizeof(buf), "e/shelf/%s/base", style); else snprintf(buf, sizeof(buf), "e/shelf/%s/base", "default"); if (!e_theme_edje_object_set(es->o_base, "base/theme/shelf", buf)) e_theme_edje_object_set(es->o_base, "base/theme/shelf", "e/shelf/default/base"); option = edje_object_data_get(es->o_base, "hidden_state_size"); if (option) es->hidden_state_size = atoi(option); else es->hidden_state_size = 4; option = edje_object_data_get(es->o_base, "instant_delay"); if (option) es->instant_delay = atof(option); else es->instant_delay = -1.0; } E_API void e_shelf_autohide_set(E_Shelf *es, int autohide_type) { E_OBJECT_CHECK(es); E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE); if ((es->cfg->autohide == !!autohide_type) && ((!!es->autohide) == !!autohide_type)) { if ((!es->autohide) || (es->cfg->autohide_show_action == autohide_type - 1)) return; } es->cfg->autohide = !!autohide_type; if (!es->cfg->autohide) { if (!es->autohide) return; ecore_event_handler_del(es->autohide); es->autohide = NULL; return; } es->cfg->autohide_show_action = autohide_type - 1; if (es->autohide) ecore_event_handler_del(es->autohide); es->autohide = NULL; /* * see FIXME in _e_shelf_cb_mouse_in() for why these are commented out es->handlers = eina_list_append(es->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _e_shelf_cb_mouse_in, es)); */ if (!es->cfg->autohide_show_action) es->autohide = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _e_shelf_cb_mouse_in, es); /* es->handlers = eina_list_append(es->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _e_shelf_cb_mouse_out, es)); if (!popup) evas_object_event_callback_add(es->o_event, EVAS_CALLBACK_MOUSE_OUT, (Evas_Object_Event_Cb)_e_shelf_cb_mouse_out2, es); */ } E_API void e_shelf_obstacles_update(E_Shelf *es) { E_FREE_LIST(es->zone_obstacles, e_object_del); if ((es->cfg->overlap && e_config->border_fix_on_shelf_toggle) || es->cfg->autohide) return; if (es->cfg->desk_show_mode) { Eina_List *l; E_Config_Shelf_Desk *sd; EINA_LIST_FOREACH(es->cfg->desk_list, l, sd) { E_Desk *desk; desk = e_desk_at_xy_get(es->zone, sd->x, sd->y); if (!desk) continue; es->zone_obstacles = eina_list_append(es->zone_obstacles, e_zone_obstacle_add(es->zone, desk, &(Eina_Rectangle){es->x + es->zone->x, es->y + es->zone->y, es->w, es->h}, !_e_shelf_is_horizontal(es))); } } else es->zone_obstacles = eina_list_append(es->zone_obstacles, e_zone_obstacle_add(es->zone, NULL, &(Eina_Rectangle){es->x + es->zone->x, es->y + es->zone->y, es->w, es->h}, !_e_shelf_is_horizontal(es))); } E_API E_Shelf * e_shelf_config_new(E_Zone *zone, E_Config_Shelf *cf_es) { E_Shelf *es; es = e_shelf_zone_new(zone, cf_es->name, cf_es->style, cf_es->layer, cf_es->id); if (!es) return NULL; if (!EINA_DBL_NONZERO(cf_es->hide_timeout)) cf_es->hide_timeout = 1.0; if (!EINA_DBL_NONZERO(cf_es->hide_duration)) cf_es->hide_duration = 1.0; es->cfg = cf_es; es->fit_along = cf_es->fit_along; es->fit_size = cf_es->fit_size; e_shelf_autohide_set(es, cf_es->autohide + (cf_es->autohide * cf_es->autohide_show_action)); e_shelf_orient(es, cf_es->orient); e_shelf_populate(es); e_shelf_position_calc(es); if (cf_es->desk_show_mode) { if (e_shelf_desk_visible(es, NULL)) e_shelf_show(es); else e_shelf_hide(es); } else e_shelf_show(es); e_shelf_toggle(es, 0); e_shelf_obstacles_update(es); return es; } E_API E_Entry_Dialog * e_shelf_new_dialog(Evas_Object *parent, E_Zone *zone) { char buf[256]; snprintf(buf, sizeof(buf), _("Shelf #%d"), eina_list_count(e_config->shelves)); return e_entry_dialog_show(parent, _("Add New Shelf"), "preferences-desktop-shelf", _("Name:"), buf, NULL, NULL, _e_shelf_new_dialog_ok, NULL, zone); } /* local subsystem functions */ static void _e_shelf_new_dialog_ok(void *data, char *text) { E_Config_Shelf *cfg, *es_cf; E_Zone *zone = data; Eina_List *l; unsigned int x; unsigned long orient = 1; E_Shelf *es; if ((!text) || (!text[0])) return; EINA_LIST_FOREACH(e_config->shelves, l, es_cf) { if (strcmp(es_cf->name, text)) continue; e_util_dialog_internal(_("Shelf Error"), _("A shelf with that name already exists!")); return; } cfg = E_NEW(E_Config_Shelf, 1); cfg->name = eina_stringshare_add(text); cfg->zone = zone->num; cfg->layer = E_LAYER_CLIENT_ABOVE; EINA_LIST_FOREACH(e_config->shelves, l, es_cf) orient *= orientations[es_cf->orient]; for (x = 3; x < (sizeof(orientations) / sizeof(orientations[0])); x++) if (orient % orientations[x]) { cfg->orient = x; break; } cfg->fit_along = 1; cfg->fit_size = 0; cfg->style = eina_stringshare_add("default"); cfg->size = 40; cfg->overlap = 0; cfg->autohide = 0; e_config->shelves = eina_list_append(e_config->shelves, cfg); e_config_save_queue(); es_cf = eina_list_last_data_get(e_config->shelves); cfg->id = es_cf->id + 1; es = e_shelf_config_new(zone, cfg); if (es && es->gadcon) e_int_gadcon_config_shelf(es->gadcon); } static void _e_shelf_del_cb(void *d) { E_Shelf *es; es = d; if (es->dummy) { dummies = eina_list_remove(dummies, es); E_FREE(es->cfg); } else shelves = eina_list_remove(shelves, es); } static void _e_shelf_event_rename_end_cb(void *data EINA_UNUSED, E_Event_Shelf *ev) { e_object_unref(E_OBJECT(ev->shelf)); free(ev); } static void _e_shelf_free_cb(void *data EINA_UNUSED, void *event) { E_Event_Shelf *ev = event; E_Shelf *es = ev->shelf; eina_stringshare_del(es->name); eina_stringshare_del(es->style); if (es->cfg_delete) { if (es->cfg) { e_config->shelves = eina_list_remove(e_config->shelves, es->cfg); eina_stringshare_del(es->cfg->name); eina_stringshare_del(es->cfg->style); free(es->cfg); } e_config_save_queue(); } free(es); free(ev); } static void _e_shelf_free(E_Shelf *es) { E_Event_Shelf *ev; if (!es->dummy) _e_shelf_bindings_del(es); evas_object_event_callback_del(es->comp_object, EVAS_CALLBACK_HIDE, _e_shelf_hidden); E_FREE_LIST(es->handlers, ecore_event_handler_del); E_FREE_LIST(es->zone_obstacles, e_object_del); E_FREE_FUNC(es->autohide, ecore_event_handler_del); E_FREE_FUNC(es->hide_animator, ecore_animator_del); E_FREE_FUNC(es->autohide_timer, ecore_timer_del); E_FREE_FUNC(es->hide_timer, ecore_timer_del); E_FREE_FUNC(es->instant_timer, ecore_timer_del); E_FREE_FUNC(es->module_init_end_timer, ecore_timer_del); E_FREE_FUNC(es->fix_timer, ecore_timer_del); if (es->menu) { e_menu_post_deactivate_callback_set(es->menu, NULL, NULL); e_object_del(E_OBJECT(es->menu)); es->menu = NULL; } if (es->dummy) { evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_DEL, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_del, es); evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es); evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es); } else { e_gadcon_location_unregister(es->gadcon->location); e_gadcon_location_free(es->gadcon->location); if (es->cfg_delete) e_gadcon_config_del(es->gadcon); e_object_del(E_OBJECT(es->gadcon)); es->gadcon = NULL; } if (es->config_dialog) e_object_del(E_OBJECT(es->config_dialog)); es->config_dialog = NULL; if (stopping) evas_object_unref(es->comp_object); else evas_object_hide(es->comp_object); E_FREE_FUNC(es->comp_object, evas_object_del); E_FREE_FUNC(es->o_base, evas_object_del); ev = E_NEW(E_Event_Shelf, 1); ev->shelf = es; ecore_event_add(E_EVENT_SHELF_DEL, ev, _e_shelf_free_cb, NULL); } static void _e_shelf_gadcon_min_size_request(void *data EINA_UNUSED, E_Gadcon *gc EINA_UNUSED, Evas_Coord w EINA_UNUSED, Evas_Coord h EINA_UNUSED) { return; } static void _e_shelf_gadcon_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h) { E_Shelf *es; Evas_Coord nx, ny, nw, nh, ww, hh, wantw, wanth; es = data; nx = es->x; ny = es->y; nw = es->w; nh = es->h; ww = hh = 0; w = MAX(w, 16); h = MAX(h, 16); evas_object_geometry_get(gc->o_container, NULL, NULL, &ww, &hh); switch (gc->orient) { case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: if (!es->fit_along) w = ww; if (!es->fit_size) h = hh; break; case E_GADCON_ORIENT_VERT: case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_CORNER_RT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_RB: if (!es->fit_along) h = hh; if (!es->fit_size) w = ww; break; default: break; } e_gadcon_swallowed_min_size_set(gc, w, h); edje_object_size_min_calc(es->o_base, &nw, &nh); wantw = nw; wanth = nh; switch (gc->orient) { case E_GADCON_ORIENT_FLOAT: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = es->x + ((es->w - nw) / 2); /*if (nh != es->h)*/ ny = es->y + ((es->h - nh) / 2); break; case E_GADCON_ORIENT_HORIZ: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = es->x + ((es->w - nw) / 2); break; case E_GADCON_ORIENT_VERT: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = es->y + ((es->h - nh) / 2); break; case E_GADCON_ORIENT_LEFT: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = (es->zone->h - nh) / 2; //nx = 0; break; case E_GADCON_ORIENT_RIGHT: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = (es->zone->h - nh) / 2; //nx = es->zone->w - nw; break; case E_GADCON_ORIENT_TOP: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = (es->zone->w - nw) / 2; //ny = 0; break; case E_GADCON_ORIENT_BOTTOM: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = (es->zone->w - nw) / 2; //ny = es->zone->h - nh; break; case E_GADCON_ORIENT_CORNER_TL: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = 0; //ny = 0; break; case E_GADCON_ORIENT_CORNER_TR: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = es->zone->w - nw; //ny = 0; break; case E_GADCON_ORIENT_CORNER_BL: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = 0; //ny = es->zone->h - nh; break; case E_GADCON_ORIENT_CORNER_BR: if (!es->fit_along) nw = es->w; if (!es->fit_size) nh = es->h; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nw != es->w)*/ nx = es->zone->w - nw; //ny = es->zone->h - nh; break; case E_GADCON_ORIENT_CORNER_LT: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = 0; //nx = 0; break; case E_GADCON_ORIENT_CORNER_RT: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = 0; //nx = es->zone->w - nw; break; case E_GADCON_ORIENT_CORNER_LB: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = es->zone->h - nh; //nx = 0; break; case E_GADCON_ORIENT_CORNER_RB: if (!es->fit_along) nh = es->h; if (!es->fit_size) nw = es->w; if (nw > es->zone->w) nw = es->zone->w; if (nh > es->zone->h) nh = es->zone->h; /*if (nh != es->h)*/ ny = es->zone->h - nh; //nx = es->zone->w - nw; break; default: break; } w -= (wantw - nw); h -= (wanth - nh); e_gadcon_swallowed_min_size_set(gc, w, h); e_shelf_move_resize(es, nx, ny, nw, nh); e_zone_useful_geometry_dirty(es->zone); } static Evas_Object * _e_shelf_gadcon_frame_request(void *data, E_Gadcon_Client *gcc, const char *style) { E_Shelf *es; Evas_Object *o; char buf[4096]; es = data; o = edje_object_add(gcc->gadcon->evas); snprintf(buf, sizeof(buf), "e/shelf/%s/%s", es->style, style); if (!e_theme_edje_object_set(o, "base/theme/shelf", buf)) { /* if an inset style (e.g. plain) isn't implemented for a given * shelf style, fall back to the default one. no need for every * theme to implement the plain style */ snprintf(buf, sizeof(buf), "e/shelf/default/%s", style); if (!e_theme_edje_object_set(o, "base/theme/shelf", buf)) { evas_object_del(o); return NULL; } } snprintf(buf, sizeof(buf), "e,state,orientation,%s", e_shelf_orient_string_get(es)); edje_object_signal_emit(o, buf, "e"); edje_object_message_signal_process(o); return o; } static void _e_shelf_toggle_client_fix(E_Shelf *es) { E_Client *ec; if (!e_config->border_fix_on_shelf_toggle) return; if (es->cfg->overlap) return; E_CLIENT_FOREACH(ec) { if ((!ec->sticky) && (!e_shelf_desk_visible(es, ec->desk ?: e_desk_current_get(es->zone)))) continue; if ((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE) { if (ec->lock_client_location) continue; if (es->hidden) { if (!ec->shelf_fix.modified) continue; if (!--ec->shelf_fix.modified) { evas_object_move(ec->frame, ec->shelf_fix.x, ec->shelf_fix.y); continue; } } if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, es->x, es->y, es->w, es->h)) continue; if (!es->hidden) { if (!ec->shelf_fix.modified++) ec->shelf_fix.x = ec->x; ec->shelf_fix.y = ec->y; } switch (es->gadcon->orient) { case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: if (!es->hidden) evas_object_move(ec->frame, ec->x, ec->y + es->h); break; case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: if (!es->hidden) evas_object_move(ec->frame, ec->x, ec->y - es->h); break; case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_LT: if (!es->hidden) evas_object_move(ec->frame, ec->x + es->w, ec->y); break; case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RB: case E_GADCON_ORIENT_CORNER_RT: if (!es->hidden) evas_object_move(ec->frame, ec->x - es->w, ec->y); break; default: break; } } else { E_Maximize max; max = ec->maximized; e_client_unmaximize(ec, E_MAXIMIZE_BOTH); e_client_maximize(ec, max); } } } static void _e_shelf_menu_item_free(void *data) { E_Shelf *es; es = e_object_data_get(data); e_shelf_locked_set(es, 0); e_object_unref(E_OBJECT(es)); } static void _e_shelf_menu_append(E_Shelf *es, E_Menu *mn) { E_Menu_Item *mi; E_Menu *subm; char buf[256]; if (es->name) snprintf(buf, sizeof(buf), "%s", es->name); else snprintf(buf, sizeof(buf), _("Shelf %s"), e_shelf_orient_string_get(es)); e_shelf_locked_set(es, 1); subm = e_menu_new(); mi = e_menu_item_new(mn); e_menu_item_label_set(mi, buf); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); e_menu_pre_activate_callback_set(subm, _e_shelf_menu_pre_cb, es); e_object_ref(E_OBJECT(es)); e_object_free_attach_func_set(E_OBJECT(mi), _e_shelf_menu_item_free); e_object_data_set(E_OBJECT(mi), es); e_menu_item_submenu_set(mi, subm); e_object_unref(E_OBJECT(subm)); mi = e_menu_item_new(mn); e_menu_item_separator_set(mi, 1); mi = e_menu_item_new(mn); if (es->gadcon->editing) e_menu_item_label_set(mi, _("Stop Moving Gadgets")); else e_menu_item_label_set(mi, _("Begin Moving Gadgets")); e_util_menu_item_theme_icon_set(mi, "transform-move"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_edit, es); } static void _e_shelf_cb_menu_items_append(void *data, E_Gadcon_Client *gcc EINA_UNUSED, E_Menu *mn) { E_Shelf *es; es = data; _e_shelf_menu_append(es, mn); } static void _e_shelf_cb_locked_set(void *data, int lock) { E_Shelf *es; es = data; e_shelf_locked_set(es, lock); } static void _e_shelf_cb_urgent_show(void *data) { E_Shelf *es; es = data; e_shelf_urgent_show(es); } static void _e_shelf_cb_menu_autohide(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es = data; e_shelf_autohide_set(es, (!es->cfg->autohide) + (!es->cfg->autohide * es->cfg->autohide_show_action)); if ((es->cfg->autohide) && (!es->hidden)) e_shelf_toggle(es, 0); else if ((!es->cfg->autohide) && (es->hidden)) e_shelf_toggle(es, 1); e_zone_useful_geometry_dirty(es->zone); e_config_save_queue(); } static void _e_shelf_cb_menu_refresh(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es = data; e_gadcon_unpopulate(es->gadcon); e_gadcon_populate(es->gadcon); } static void _e_shelf_cb_menu_config(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es; es = data; if (!es->config_dialog) e_int_shelf_config(es); } static void _e_shelf_cb_menu_edit(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es; es = data; if (es->gadcon->editing) { e_gadcon_edit_end(es->gadcon); e_shelf_toggle(es, 0); } else { e_shelf_toggle(es, 1); e_gadcon_edit_begin(es->gadcon); } } static void _e_shelf_cb_menu_contents(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es; es = data; if (!es->gadcon->config_dialog) e_int_gadcon_config_shelf(es->gadcon); } static void _e_shelf_cb_confirm_dialog_destroy(void *data) { E_Shelf *es; es = data; e_object_unref(E_OBJECT(es)); } static void _e_shelf_cb_confirm_dialog_yes(void *data) { E_Shelf *es; es = data; if (e_object_is_del(E_OBJECT(es))) return; es->cfg_delete = 1; e_object_del(E_OBJECT(es)); } static void _e_shelf_cb_menu_delete(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es; es = data; if (e_config->cnfmdlg_disabled) { if (e_object_is_del(E_OBJECT(es))) return; es->cfg_delete = 1; e_object_del(E_OBJECT(es)); e_config_save_queue(); return; } e_object_ref(E_OBJECT(es)); e_confirm_dialog_show(_("Are you sure you want to delete this shelf?"), "enlightenment", _("You requested to delete this shelf." "" "Are you sure you want to delete it?"), _("Delete"), _("Keep"), _e_shelf_cb_confirm_dialog_yes, NULL, data, NULL, _e_shelf_cb_confirm_dialog_destroy, data); } static void _e_shelf_cb_menu_post(void *data, E_Menu *m) { E_Shelf *es; es = data; e_object_del(E_OBJECT(m)); if (m != es->menu) return; es->menu = NULL; } static void _e_shelf_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Down *ev; E_Shelf *es; E_Menu *mn; int cx, cy; es = data; ev = event_info; switch (ev->button) { case 1: if (es->cfg->autohide_show_action) e_shelf_toggle(es, 1); break; case 3: if (es->menu) return; mn = e_menu_new(); e_menu_post_deactivate_callback_set(mn, _e_shelf_cb_menu_post, es); es->menu = mn; _e_shelf_menu_pre_cb(es, mn); e_gadcon_canvas_zone_geometry_get(es->gadcon, &cx, &cy, NULL, NULL); e_menu_activate_mouse(mn, e_zone_current_get(), cx + ev->output.x, cy + ev->output.y, 1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp); break; } } static Eina_Bool _e_shelf_cb_mouse_in(void *data, int type, void *event) { E_Shelf *es; es = data; if (es->cfg->autohide_show_action) return ECORE_CALLBACK_PASS_ON; if (type == E_EVENT_ZONE_EDGE_MOVE) { E_Event_Zone_Edge *ev; E_Desk *desk; Eina_List *l; E_Client *ec; int show = 0; ev = event; if (es->zone != ev->zone) return ECORE_CALLBACK_PASS_ON; if (!_e_shelf_on_current_desk(es, ev)) return ECORE_CALLBACK_PASS_ON; desk = e_desk_current_get(ev->zone); EINA_LIST_FOREACH(desk->fullscreen_clients, l, ec) if (evas_object_visible_get(ec->frame)) return ECORE_CALLBACK_RENEW; ev->x -= es->zone->x, ev->y -= es->zone->y; switch (es->gadcon->orient) { case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_CORNER_LB: if (((ev->edge == E_ZONE_EDGE_LEFT) || (ev->edge == E_ZONE_EDGE_TOP_LEFT) || (ev->edge == E_ZONE_EDGE_BOTTOM_LEFT)) && (ev->y >= es->y) && (ev->y <= (es->y + es->h))) show = 1; break; case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RT: case E_GADCON_ORIENT_CORNER_RB: if (((ev->edge == E_ZONE_EDGE_RIGHT) || (ev->edge == E_ZONE_EDGE_TOP_RIGHT) || (ev->edge == E_ZONE_EDGE_BOTTOM_RIGHT)) && (ev->y >= es->y) && (ev->y <= (es->y + es->h))) show = 1; break; case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: if (((ev->edge == E_ZONE_EDGE_TOP) || (ev->edge == E_ZONE_EDGE_TOP_LEFT) || (ev->edge == E_ZONE_EDGE_TOP_RIGHT)) && (ev->x >= es->x) && (ev->x <= (es->x + es->w))) show = 1; break; case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: if (((ev->edge == E_ZONE_EDGE_BOTTOM) || (ev->edge == E_ZONE_EDGE_BOTTOM_LEFT) || (ev->edge == E_ZONE_EDGE_BOTTOM_RIGHT)) && (ev->x >= es->x) && (ev->x <= (es->x + es->w))) show = 1; break; case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_VERT: default: /* noop */ break; } if (show) { edje_object_signal_emit(es->o_base, "e,state,focused", "e"); e_shelf_toggle(es, 1); } else e_shelf_toggle(es, 0); } /* else if (type == ECORE_X_EVENT_MOUSE_IN) { Ecore_X_Event_Mouse_In *ev; ev = event; if ((!es->hidden) && (!es->menu)) { int x, y, w, h; evas_object_geometry_get(es->o_event, &x, &y, &w, &h); if (!E_INSIDE(ev->x, ev->y, x, y, w, h)) e_shelf_toggle(es, 0); } if (!es->popup) return ECORE_CALLBACK_PASS_ON; if (ev->win == es->popup->evas_win) { if (es->hidden || (!es->toggle)) { edje_object_signal_emit(es->o_base, "e,state,focused", "e"); e_shelf_toggle(es, 1); } } } */ else if (type == ECORE_EVENT_MOUSE_MOVE) { Ecore_Event_Mouse_Move *ev; int x, y; Eina_Bool inside = EINA_FALSE; ev = event; inside = E_INSIDE(e_comp_canvas_x_root_adjust(ev->root.x), e_comp_canvas_y_root_adjust(ev->root.y), es->zone->x, es->zone->y, es->zone->w + 4, es->zone->h + 4); x = e_comp_canvas_x_root_adjust(ev->root.x) - es->zone->x; y = e_comp_canvas_y_root_adjust(ev->root.y) - es->zone->y; if (inside) inside = ( ((E_INSIDE(x, y, es->x, es->y, es->w, es->h)) || (E_INSIDE(x, y, es->x - 2, es->y - 2, es->w + 4, es->h + 4)) || (E_INSIDE(x, y, es->x + 2, es->y + 2, es->w + 4, es->h + 4))) ); if (inside) { if (es->autohide_timer) ecore_timer_loop_reset(es->autohide_timer); } if (inside) { if (es->hidden || (!es->toggle)) { edje_object_signal_emit(es->o_base, "e,state,focused", "e"); e_shelf_toggle(es, 1); } } else { if ((!es->hidden) && (es->toggle)) e_shelf_toggle(es, 0); } } return ECORE_CALLBACK_PASS_ON; } #if 0 static void _e_shelf_cb_mouse_out2(E_Shelf *es, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Evas_Event_Mouse_Out *ev) { int x, y, w, h; evas_object_geometry_get(es->o_event, &x, &y, &w, &h); if (!E_INSIDE(ev->output.x, ev->output.y, x, y, w, h)) e_shelf_toggle(es, 0); } static Eina_Bool _e_shelf_cb_mouse_out(void *data, int type, void *event) { E_Shelf *es; Ecore_X_Window win; es = data; if (type == ECORE_X_EVENT_MOUSE_OUT) { Ecore_X_Event_Mouse_Out *ev = event; int x, y, w, h; if (ev->win != e_comp->ee_win) return ECORE_CALLBACK_PASS_ON; evas_object_geometry_get(es->o_event, &x, &y, &w, &h); if (!E_INSIDE(ev->x, ev->y, x, y, w, h)) { //fprintf(stderr, "EVENT: %d,%d %dx%d || MOUSE: %d,%d\n", x, y, w, h, ev->x, ev->y); e_shelf_toggle(es, 0); } } return ECORE_CALLBACK_PASS_ON; } #endif static void _e_shelf_cb_dummy_moveresize(E_Shelf *es, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { int x, y, w, h; evas_object_geometry_get(obj, &x, &y, &w, &h); if ((x != es->x) || (y != es->y) || (w != es->w) || (h != es->h)) { es->x = x, es->y = y, es->w = w, es->h = h; e_zone_useful_geometry_dirty(es->zone); } } static void _e_shelf_cb_dummy_del(E_Shelf *es, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { e_object_free(E_OBJECT(es)); } static int _e_shelf_cb_id_sort(const void *data1, const void *data2) { const E_Shelf *es1, *es2; es1 = data1; es2 = data2; if ((es1->id) < (es2->id)) return -1; else if (es1->id > es2->id) return 1; return 0; } static Eina_Bool _e_shelf_cb_hide_animator(void *data) { E_Shelf *es; int hide_max = 0; double pos; es = data; if (!es->gadcon) { es->hide_animator = NULL; return EINA_FALSE; } switch (es->gadcon->orient) { case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: hide_max = es->h - es->hidden_state_size - 1; if (es->hide_origin == -1) es->hide_origin = es->y; break; case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RB: case E_GADCON_ORIENT_CORNER_RT: hide_max = es->w - es->hidden_state_size; if (es->hide_origin == -1) es->hide_origin = es->x; break; case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_VERT: default: break; } pos = (ecore_loop_time_get() - es->hide_begin) / es->cfg->hide_duration; if (es->hidden) { es->hide_step = hide_max * pos; if (es->hide_step > hide_max) es->hide_step = hide_max; } else { es->hide_step = hide_max * (1.0 - pos); if (es->hide_step <= 0) es->hide_step = 0; } switch (es->gadcon->orient) { case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: e_shelf_move(es, es->x, es->hide_origin - es->hide_step); break; case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: e_shelf_move(es, es->x, es->hide_origin + es->hide_step); break; case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_LT: e_shelf_move(es, es->hide_origin - es->hide_step, es->y); break; case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RB: case E_GADCON_ORIENT_CORNER_RT: e_shelf_move(es, es->hide_origin + es->hide_step, es->y); break; case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_VERT: default: break; } if (es->hidden) { if (es->hide_step == hide_max) goto end; } else { if (es->hide_step == 0) goto end; } return ECORE_CALLBACK_RENEW; end: es->hide_animator = NULL; if (es->interrupted > -1) e_shelf_toggle(es, es->interrupted); else if (es->urgent_show) e_shelf_toggle(es, 0); else _e_shelf_toggle_client_fix(es); if ((!es->hidden) && es->cfg->autohide_show_action) { es->hidden = 1; if (!es->hide_timer) es->hide_timer = ecore_timer_loop_add(es->cfg->hide_timeout, _e_shelf_cb_hide_animator_timer, es); } if (es->hidden && (!es->hide_timer)) edje_object_signal_emit(es->o_base, "e,state,hidden", "e"); return ECORE_CALLBACK_CANCEL; } static Eina_Bool _e_shelf_cb_hide_animator_timer(void *data) { E_Shelf *es; es = data; if (!es->hide_animator) { es->hide_begin = ecore_loop_time_get(); es->hide_animator = ecore_animator_add(_e_shelf_cb_hide_animator, es); } es->hide_timer = NULL; return ECORE_CALLBACK_CANCEL; } static Eina_Bool _e_shelf_cb_hide_urgent_timer(void *data) { E_Shelf *es; es = data; es->hide_timer = NULL; if (es->urgent_show) e_shelf_toggle(es, 0); return ECORE_CALLBACK_CANCEL; } static Eina_Bool _e_shelf_cb_instant_hide_timer(void *data) { E_Shelf *es; es = data; switch (es->gadcon->orient) { case E_GADCON_ORIENT_TOP: case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_TR: if (es->hidden) e_shelf_move(es, es->x, es->y - es->h + es->hidden_state_size); else e_shelf_move(es, es->x, es->y + es->h - es->hidden_state_size); break; case E_GADCON_ORIENT_BOTTOM: case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_BR: if (es->hidden) e_shelf_move(es, es->x, es->y + es->h - es->hidden_state_size); else e_shelf_move(es, es->x, es->y - es->h + es->hidden_state_size); break; case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_LT: if (es->hidden) e_shelf_move(es, es->x - es->w + es->hidden_state_size, es->y); else e_shelf_move(es, es->x + es->w - es->hidden_state_size, es->y); break; case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_RB: case E_GADCON_ORIENT_CORNER_RT: if (es->hidden) e_shelf_move(es, es->x + es->w - es->hidden_state_size, es->y); else e_shelf_move(es, es->x - es->w + es->hidden_state_size, es->y); break; default: break; } es->instant_timer = NULL; _e_shelf_toggle_client_fix(es); return ECORE_CALLBACK_CANCEL; } static Eina_Bool _e_shelf_gadcon_populate_handler_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { E_Event_Gadcon_Populate *ev = event; Eina_List *l; E_Shelf *es; EINA_LIST_FOREACH(shelves, l, es) if (es->gadcon == ev->gc) { /* any shelf that's not already shown at this point will be * waiting for this event to show it so that we don't ever resize the shelf * object */ if (e_shelf_desk_visible(es, NULL)) e_shelf_show(es); break; } return ECORE_CALLBACK_RENEW; } static void _e_shelf_cb_menu_rename_yes_cb(void *data, char *text) { E_Shelf *es = data; Eina_List *l; E_Config_Shelf *cf_es; if ((!text) || (!text[0])) return; if (!strcmp(text, es->cfg->name)) return; EINA_LIST_FOREACH(e_config->shelves, l, cf_es) if (!strcmp(cf_es->name, text)) { e_util_dialog_internal(_("Error"), _("A shelf with that name and id already exists!")); return; } e_shelf_name_set(es, text); e_config_save_queue(); } static void _e_shelf_cb_menu_rename_cb(void *data) { E_Shelf *es = e_object_data_get(data); es->rename_dialog = NULL; } static void _e_shelf_cb_menu_rename(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) { E_Shelf *es = data; if (es->rename_dialog) return; es->rename_dialog = e_entry_dialog_show(NULL, _("Rename Shelf"), "edit-rename", _("Name:"), es->name, NULL, NULL, _e_shelf_cb_menu_rename_yes_cb, NULL, es); e_object_data_set(E_OBJECT(es->rename_dialog), es); e_object_del_attach_func_set(E_OBJECT(es->rename_dialog), _e_shelf_cb_menu_rename_cb); } static void _e_shelf_cb_menu_orient(void *data, E_Menu *m, E_Menu_Item *mi) { E_Shelf *es = data; E_Menu_Item *mii; int orient = E_GADCON_ORIENT_LEFT; Eina_List *l; EINA_LIST_FOREACH(m->items, l, mii) { if (mi == mii) { E_Zone *zone; E_Config_Shelf *cf_es; void *cfd; if (es->cfg->orient == orient) return; es->cfg->orient = orient; zone = es->zone; cf_es = es->cfg; cfd = es->config_dialog; es->config_dialog = NULL; e_gadcon_unpopulate(es->gadcon); e_object_del(E_OBJECT(es)); es = e_shelf_config_new(zone, cf_es); es->config_dialog = cfd; return; } orient++; } } static void _e_shelf_menu_orientation_pre_cb(void *data, E_Menu *m) { E_Menu_Item *mi; E_Shelf *es = data; int orient; if (m->items) return; for (orient = E_GADCON_ORIENT_LEFT; orient < E_GADCON_ORIENT_LAST; orient++) { mi = e_menu_item_new(m); e_util_gadcon_orient_menu_item_icon_set(orient, mi); e_menu_item_radio_set(mi, 1); e_menu_item_radio_group_set(mi, 1); e_menu_item_label_set(mi, _(orient_names[orient])); e_menu_item_callback_set(mi, _e_shelf_cb_menu_orient, es); if (es->cfg->orient == orient) e_menu_item_toggle_set(mi, 1); e_menu_item_disabled_set(mi, es->cfg->orient == orient); } } static void _e_shelf_menu_pre_cb(void *data, E_Menu *m) { E_Shelf *es; E_Menu_Item *mi; E_Menu *subm; es = data; e_menu_pre_activate_callback_set(m, NULL, NULL); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Contents")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_contents, es); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Settings")); e_util_menu_item_theme_icon_set(mi, "configure"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_config, es); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Orientation")); e_menu_item_callback_set(mi, _e_shelf_cb_menu_config, es); subm = e_menu_new(); e_menu_pre_activate_callback_set(subm, _e_shelf_menu_orientation_pre_cb, es); e_object_data_set(E_OBJECT(subm), es); e_menu_item_submenu_set(mi, subm); e_object_unref(E_OBJECT(subm)); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Autohide")); e_menu_item_check_set(mi, 1); e_menu_item_toggle_set(mi, es->cfg->autohide); //e_util_menu_item_theme_icon_set(mi, ""); FIXME e_menu_item_callback_set(mi, _e_shelf_cb_menu_autohide, es); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Refresh")); e_util_menu_item_theme_icon_set(mi, "view-refresh"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_refresh, es); 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, _("Rename")); e_util_menu_item_theme_icon_set(mi, "edit-rename"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_rename, es); mi = e_menu_item_new(m); e_menu_item_label_set(mi, _("Delete")); e_util_menu_item_theme_icon_set(mi, "list-remove"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_delete, es); if (m->parent_item) return; mi = e_menu_item_new(m); e_menu_item_separator_set(mi, 1); mi = e_menu_item_new(m); if (es->gadcon->editing) e_menu_item_label_set(mi, _("Stop Moving Gadgets")); else e_menu_item_label_set(mi, _("Begin Moving Gadgets")); e_util_menu_item_theme_icon_set(mi, "transform-scale"); e_menu_item_callback_set(mi, _e_shelf_cb_menu_edit, es); } static void _e_shelf_gadcon_client_remove(void *data, E_Gadcon_Client *gcc) { E_Shelf *s; E_Gadcon *gc; s = data; gc = s->gadcon; if (gcc->cf) e_gadcon_client_config_del(gc->cf, gcc->cf); e_gadcon_unpopulate(gc); e_gadcon_populate(gc); e_config_save_queue(); } static int _e_shelf_gadcon_client_add(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc) { E_Shelf *s; E_Gadcon *gc; s = data; gc = s->gadcon; if (gcc) { E_Config_Gadcon_Client *cf_gcc = gcc->cf; gcc->gadcon->cf->clients = eina_list_remove(gcc->gadcon->cf->clients, cf_gcc); if (gc->zone) cf_gcc->geom.res = gc->zone->w; else if (gc->o_container) { int w, h; evas_object_geometry_get(gc->o_container, NULL, NULL, &w, &h); switch (gc->orient) { case E_GADCON_ORIENT_VERT: case E_GADCON_ORIENT_LEFT: case E_GADCON_ORIENT_RIGHT: case E_GADCON_ORIENT_CORNER_LT: case E_GADCON_ORIENT_CORNER_RT: case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_RB: cf_gcc->geom.res = h; break; default: cf_gcc->geom.res = w; } } else cf_gcc->geom.res = 800; cf_gcc->geom.size = 80; cf_gcc->geom.pos = cf_gcc->geom.res - cf_gcc->geom.size; gc->cf->clients = eina_list_append(gc->cf->clients, cf_gcc); } else if (!e_gadcon_client_config_new(gc, cc->name)) return 0; e_gadcon_unpopulate(gc); e_gadcon_populate(gc); e_config_save_queue(); return 1; } static const char * _e_shelf_orient_icon_name_get(E_Shelf *s) { const char *name; name = NULL; switch (s->cfg->orient) { case E_GADCON_ORIENT_LEFT: name = "preferences-position-left"; break; case E_GADCON_ORIENT_RIGHT: name = "preferences-position-right"; break; case E_GADCON_ORIENT_TOP: name = "preferences-position-top"; break; case E_GADCON_ORIENT_BOTTOM: name = "preferences-position-bottom"; break; case E_GADCON_ORIENT_CORNER_TL: name = "preferences-position-top-left"; break; case E_GADCON_ORIENT_CORNER_TR: name = "preferences-position-top-right"; break; case E_GADCON_ORIENT_CORNER_BL: name = "preferences-position-bottom-left"; break; case E_GADCON_ORIENT_CORNER_BR: name = "preferences-position-bottom-right"; break; case E_GADCON_ORIENT_CORNER_LT: name = "preferences-position-left-top"; break; case E_GADCON_ORIENT_CORNER_RT: name = "preferences-position-right-top"; break; case E_GADCON_ORIENT_CORNER_LB: name = "preferences-position-left-bottom"; break; case E_GADCON_ORIENT_CORNER_RB: name = "preferences-position-right-bottom"; break; default: name = "preferences-desktop-shelf"; break; } return name; } static void _e_shelf_bindings_add(E_Shelf *es) { char buf[1024]; /* TODO: This might delete edge windows, and then add them again further down. Should prevent this. */ _e_shelf_bindings_del(es); /* Don't need edge binding if we don't hide shelf */ if ((es->cfg) && (!es->cfg->autohide) && (!es->cfg->autohide_show_action)) return; snprintf(buf, sizeof(buf), "shelf.%d", es->id); switch (es->gadcon->orient) { case E_GADCON_ORIENT_FLOAT: case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_VERT: default: /* noop */ break; case E_GADCON_ORIENT_LEFT: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_RIGHT: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_TOP: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_BOTTOM: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_CORNER_TL: case E_GADCON_ORIENT_CORNER_LT: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP_LEFT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_CORNER_TR: case E_GADCON_ORIENT_CORNER_RT: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP_RIGHT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_CORNER_BL: case E_GADCON_ORIENT_CORNER_LB: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM_LEFT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; case E_GADCON_ORIENT_CORNER_BR: case E_GADCON_ORIENT_CORNER_RB: e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM_RIGHT, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); break; } } static void _e_shelf_bindings_del(E_Shelf *es) { char buf[1024]; E_Zone_Edge edge; snprintf(buf, sizeof(buf), "shelf.%d", es->id); for (edge = E_ZONE_EDGE_LEFT; edge <= E_ZONE_EDGE_BOTTOM_LEFT; edge++) e_bindings_edge_del(E_BINDING_CONTEXT_ZONE, edge, 0, E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0); } static Eina_Bool _e_shelf_on_current_desk(E_Shelf *es, E_Event_Zone_Edge *ev) { E_Config_Shelf_Desk *sd; Eina_List *ll; int on_current_desk = 0; int on_all_desks = 1; if (ev->zone != es->zone) return EINA_FALSE; EINA_LIST_FOREACH(es->cfg->desk_list, ll, sd) { if (!sd) continue; on_all_desks = 0; if ((sd->x == ev->zone->desk_x_current) && (sd->y == ev->zone->desk_y_current)) { on_current_desk = 1; break; } } if ((!on_all_desks) && (!on_current_desk)) return EINA_FALSE; return EINA_TRUE; }