#include #include "e_mod_main.h" /* Local Function Prototypes */ static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style); static void _gc_shutdown(E_Gadcon_Client *gcc); static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient); static char *_gc_label(E_Gadcon_Client_Class *client_class); static const char *_gc_id_new(E_Gadcon_Client_Class *client_class); static Evas_Object *_gc_icon(E_Gadcon_Client_Class *client_class, Evas *evas); static void _scale_conf_new(void); static void _scale_conf_free(void); static Eina_Bool _scale_conf_timer(void *data); static Config_Item *_scale_conf_item_get(const char *id); static void _scale_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event); static void _scale_cb_menu_post(void *data, E_Menu *menu); static void _scale_cb_menu_configure(void *data, E_Menu *mn, E_Menu_Item *mi); static void movorig(void *data, Evas *e, Evas_Object *obj, void *event_info); static void reszorig(void *data, Evas *e, Evas_Object *obj, void *event_info); static void delorig(void *data, Evas *e, Evas_Object *obj, void *event_info); static E_Action *act = NULL; typedef struct _Item Item; typedef struct _E_Comp_Win E_Comp_Win; struct _Item { Evas_Object *o; E_Border *bd; E_Comp_Win *cw; double factor; int x; int y; int w; int h; int mx; int my; }; static Eina_List *items = NULL; static Eina_List *handlers = NULL; static Ecore_Timer *timer = NULL; static int max_x; static int max_y; static int min_x; static int min_y; static int width, height; static int cnt = 0; static double factor; static double advance = 0.0; static double zoom = 0.00; static Ecore_X_Window input_win = 0; static E_Msg_Handler *msg_handler = NULL; /* static Evas *comp_evas = NULL; */ struct _E_Comp_Win { EINA_INLIST; void *c; // parent compositor Ecore_X_Window win; // raw window - for menus etc. E_Border *bd; // if its a border - later E_Popup *pop; // if its a popup - later E_Menu *menu; // if it is a menu - later int x, y, w, h; // geometry struct { int x, y, w, h; // hidden geometry (used when its unmapped and re-instated on map) } hidden; int pw, ph; // pixmap w/h int border; // border width Ecore_X_Pixmap pixmap; // the compositing pixmap Ecore_X_Damage damage; // damage region Ecore_X_Visual vis; // window visual int depth; // window depth Evas_Object *obj; // composite object Evas_Object *shobj; // shadow object Eina_List *obj_mirror; // extra mirror objects Ecore_X_Image *xim; // x image - software fallback void *up; // update handler E_Object_Delfn *dfn; // delete function handle for objects being tracked Ecore_X_Sync_Counter counter; // sync counter for syncronised drawing Ecore_Timer *update_timeout; // max time between damage and "done" event Ecore_Timer *ready_timeout; // max time on show (new window draw) to wait for window contents to be ready if sync protocol not handled. this is fallback. int dmg_updates; // num of damage event updates since a redirect Ecore_X_Rectangle *rects; // shape rects... if shaped :( int rects_num; // num rects above Ecore_X_Pixmap cache_pixmap; // the cached pixmap (1/nth the dimensions) int cache_w, cache_h; // cached pixmap size int update_count; // how many updates have happened to this win double last_visible_time; // last time window was visible double last_draw_time; // last time window was damaged int pending_count; // pending event count char *title, *name, *clas, *role; // fetched for override-redirect windowa Ecore_X_Window_Type primary_type; // fetched for override-redirect windowa Eina_Bool delete_pending : 1; // delete pendig Eina_Bool hidden_override : 1; // hidden override Eina_Bool animating : 1; // it's busy animating - defer hides/dels Eina_Bool force : 1; // force del/hide even if animating Eina_Bool defer_hide : 1; // flag to get hide to work on deferred hide Eina_Bool delete_me : 1; // delete me! Eina_Bool visible : 1; // is visible Eina_Bool input_only : 1; // is input_only Eina_Bool override : 1; // is override-redirect Eina_Bool argb : 1; // is argb Eina_Bool shaped : 1; // is shaped Eina_Bool update : 1; // has updates to fetch Eina_Bool redirected : 1; // has updates to fetch Eina_Bool shape_changed : 1; // shape changed Eina_Bool native : 1; // native Eina_Bool drawme : 1; // drawme flag fo syncing rendering Eina_Bool invalid : 1; // invalid depth used - just use as marker Eina_Bool nocomp : 1; // nocomp applied Eina_Bool needpix : 1; // need new pixmap Eina_Bool needxim : 1; // need new xim Eina_Bool real_hid : 1; // last hide was a real window unmap Eina_Bool inhash : 1; // is in the windows hash Eina_Bool show_ready : 1; // is this window ready for its first show }; static int _grow() { Item *it, *ot; Eina_List *l, *ll; int cont = 0; int overlap; int grow_l, grow_r, grow_d, grow_u; EINA_LIST_FOREACH(items, l, it) { if (it->w >= it->bd->w) continue; if (it->h >= it->bd->h) continue; overlap = 0; grow_l = grow_r = 2; grow_u = grow_d = 2.0 * (double)it->bd->h/(double)it->bd->w; if (it->x - grow_l < 0) grow_l = 0; if (it->y - grow_u < 0) grow_u = 0; if (it->x + it->w + grow_r > width) grow_r = 0; if (it->y + it->h + grow_d > height) grow_d = 0; if (!(grow_l || grow_r)) continue; if (!(grow_u || grow_d)) continue; EINA_LIST_FOREACH(items, ll, ot) { if (it == ot) continue; if (grow_l && E_INTERSECTS(it->x-grow_l*2, it->y, it->w, it->h, ot->x, ot->y, ot->w, ot->h)) grow_l = 0; if (grow_u && E_INTERSECTS(it->x, it->y-grow_u*2, it->w, it->h, ot->x, ot->y, ot->w, ot->h)) grow_u = 0; if (grow_r && E_INTERSECTS(it->x, it->y, it->w+grow_r*2, it->h, ot->x, ot->y, ot->w, ot->h)) grow_r = 0; if (grow_d && E_INTERSECTS(it->x, it->y, it->w, it->h+grow_d*2, ot->x, ot->y, ot->w, ot->h)) grow_d = 0; if (!((grow_l || grow_r) && (grow_u || grow_d))) { overlap = 1; break; } } if (!overlap) { cont++; it->w += (grow_u && grow_d) ? 4 : 2; it->h = it->w * (double)it->bd->h/(double)it->bd->w; it->x -= grow_l; it->y -= grow_u; } } return cont; } static int _place() { Item *it, *ot; Eina_List *l, *ll; int overlap = 0; int outside = 0; cnt++; EINA_LIST_FOREACH(items, l, it) { it->mx = it->x; it->my = it->y; } EINA_LIST_FOREACH(items, l, it) { EINA_LIST_FOREACH(l->next, ll, ot) { int w = it->w; int h = it->h; if (!E_INTERSECTS(it->x-2, it->y-2, it->w+4, it->h+4, ot->x, ot->y, ot->w, ot->h)) continue; overlap += 1; if (it->x < ot->x) w += it->x - ot->x; if (w < 0) w = 0; if (it->x + it->w > ot->x + ot->w) w = ot->x + ot->w - it->x; if (it->y < ot->y) h += it->y - ot->y; if (h < 0) h = 0; if (it->y + it->h > ot->y + ot->h) h = ot->y + ot->h - it->y; int dist_y = (it->y + it->h/2) - (ot->y + ot->h/2); int dist_x = (it->x + it->w/2) - (ot->x + ot->w/2); if (dist_x == 0 && dist_y == 0) { ot->x +=1; ot->y +=1; } if (w > h) { if (dist_y) { dist_y = (dist_y > 0 ? 2 : -2); it->my += dist_y; ot->my -= dist_y; } if (dist_x) { dist_x = (dist_x > 0 ? 1 : -1); it->mx += dist_x; ot->mx -= dist_x; } } else //if (w < h) { if (dist_y) { dist_y = (dist_y > 0 ? 1 : -1); it->my += dist_y; ot->my -= dist_y; } if (dist_x) { dist_x = (dist_x > 0 ? 2 : -2); it->mx += dist_x; ot->mx -= dist_x; } } } } if (!overlap) return 0; EINA_LIST_FOREACH(items, l, it) { it->x = it->mx; it->y = it->my; if (it->x < 0) { outside = 1; it->x = 0; } if (it->y < min_y) { outside = 1; it->y = min_y; } if (it->x + it->w > max_x) { outside = 1; it->x = max_x - it->w; } if (it->y + it->h > max_y) { outside = 1; it->y = max_y - it->h; } } if (outside) { if (cnt > 20) { /* printf("resize %f\n", factor); */ cnt = 0; factor -= 0.02; EINA_LIST_FOREACH(items, l, it) { it->w = it->bd->w * factor; it->h = it->bd->h * factor; } } return 1; } return overlap; } static void _finish() { Ecore_Event_Handler *handler; /* Eina_List *l; */ Item *it; e_grabinput_release(input_win, input_win); ecore_x_window_free(input_win); input_win = 0; EINA_LIST_FREE(items, it) { evas_object_event_callback_del(it->o, EVAS_CALLBACK_MOVE, movorig); evas_object_event_callback_del(it->o, EVAS_CALLBACK_RESIZE, reszorig); evas_object_event_callback_del(it->o, EVAS_CALLBACK_DEL, delorig); E_FREE(it); } EINA_LIST_FREE(handlers, handler) ecore_event_handler_del(handler); e_msg_handler_del(msg_handler); msg_handler = NULL; e_manager_comp_evas_update(e_manager_current_get()); } static Eina_Bool _redraw(void *blah) { Eina_List *l; Item *it; advance += zoom; /* evas_event_freeze(comp_evas); */ if (advance <= 1.0 && advance >= 0.0) { EINA_LIST_FOREACH(items, l, it) { it->cw->x = it->bd->x * (1.0 - advance) + it->x * advance; it->cw->y = it->bd->y * (1.0 - advance) + it->y * advance; double scaling = (double)(it->bd->w * (1.0 - advance) + it->w * advance) / (double)(it->cw->pw); evas_object_move(it->o, it->bd->x * (1.0 - advance) + it->x * advance, it->bd->y * (1.0 - advance) + it->y * advance); evas_object_resize(it->o, it->cw->pw * scaling, it->cw->ph * scaling); } } /* evas_event_thaw(comp_evas); */ e_manager_comp_evas_update(e_manager_current_get()); if (advance <= 1.0 && advance >= 0.0) return 1; if (advance <= 0.0) _finish(); timer = NULL; return 0; } static void delorig(void *data, Evas *e, Evas_Object *obj, void *event_info) { /* Eina_List *l; */ Item *it = data; items = eina_list_remove(items, it); evas_object_event_callback_del(it->o, EVAS_CALLBACK_MOVE, movorig); evas_object_event_callback_del(it->o, EVAS_CALLBACK_RESIZE, reszorig); evas_object_event_callback_del(it->o, EVAS_CALLBACK_DEL, delorig); E_FREE(it); if (!timer) timer = ecore_timer_add(0.01, _redraw, NULL); zoom = -0.10; } static void movorig(void *data, Evas *e, Evas_Object *obj, void *event_info) { /* Item *it = data; */ /* printf("move\n"); */ } // FIXME static void reszorig(void *data, Evas *e, Evas_Object *obj, void *event_info) { Item *it = data; int w, h; double adv; evas_object_geometry_get(obj, NULL, NULL, &w, &h); if (advance > 1.0) adv = 1.0; else if (advance < 0.0) adv = 0.0; else adv = advance; double scaling = (double)(it->bd->w * (1.0 - adv) + it->w * adv) / (double)(it->cw->pw); if (!((it->cw->pw * scaling == w) && (it->cw->ph * scaling == h))) { evas_object_resize(it->o, it->cw->pw * scaling, it->cw->ph * scaling); } } static void newwin(Evas *e, E_Manager *man, E_Manager_Comp_Source *src, E_Desk *desk) { Evas_Object *o; Item *it; if (!e_manager_comp_src_image_get(man, src)) return; E_Comp_Win *cw = (void*)src; if (!cw->bd) return; if (cw->bd->desk != desk) return; it = E_NEW(Item, 1); o = e_manager_comp_src_shadow_get(man, src); /* evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, movorig, it); */ evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, reszorig, it); evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, delorig, it); /* it->x = cw->bd->x; * it->y = cw->bd->y; */ it->x = cw->bd->x + (cw->bd->desk->x - desk->x) * width; it->y = cw->bd->y + (cw->bd->desk->y - desk->y) * height; it->w = cw->bd->w; it->h = cw->bd->h; it->o = o; it->bd = cw->bd; it->cw = cw; /* if (cw->bd->desk != desk) * { * cw->visible = EINA_TRUE; * evas_object_show(o); * evas_object_move(o, it->x, it->y); * } */ /* * e_manager_comp_src_hidden_set(man, src, EINA_FALSE); * evas_object_show(o); */ items = eina_list_append(items, it); } static Eina_Bool _cb_mouse_down(void *data, int type, void *event) { Ecore_Event_Mouse_Button *ev; ev = event; if (ev->window != input_win) return ECORE_CALLBACK_PASS_ON; if (!timer) timer = ecore_timer_add(0.01, _redraw, NULL); zoom = -0.10; Item *it; Eina_List *l; EINA_LIST_FOREACH(items, l, it) { if (E_INTERSECTS(ev->x, ev->y, 1, 1, it->x, it->y, it->w, it->h)) { e_border_raise(it->bd); break; } } return ECORE_CALLBACK_PASS_ON; } static void setup(E_Manager *man) { Eina_List *list, *l; E_Manager_Comp_Source *src; Evas *e; int i = 0; E_Zone *zone = e_util_zone_current_get(e_manager_current_get()); E_Desk *desk = e_desk_current_get(zone); input_win = ecore_x_window_input_new(zone->container->win, 0, 0, 1, 1); ecore_x_window_show(input_win); if (!e_grabinput_get(input_win, 0, input_win)) { ecore_x_window_free(input_win); input_win = 0; return; } e_zone_useful_geometry_get(zone, &min_x, &min_y, &width, &height); handlers = eina_list_append (handlers, ecore_event_handler_add (ECORE_EVENT_MOUSE_BUTTON_DOWN, _cb_mouse_down, NULL)); e = e_manager_comp_evas_get(man); /* comp_evas = e; */ list = (Eina_List *)e_manager_comp_src_list(man); EINA_LIST_FOREACH(list, l, src) { newwin(e, man, src, desk); } max_x = width; max_y = height; factor = 1.0; while (i++ < 10000 && _place()); printf("place %d\n", i); if (i == 1) { _finish(); return; } i = 0; while (i++ < 10000 && _grow()) { int k = 0; cnt = 0; while (k++ < 10 && _place()); } printf("grow %d\n", i); advance = 0.0; zoom = 0.1; if (!timer) timer = ecore_timer_add(0.01, _redraw, NULL); } static void handler(void *data, const char *name, const char *info, int val, E_Object *obj, void *msgdata) { E_Manager *man = (E_Manager *)obj; E_Manager_Comp_Source *src = (E_Manager_Comp_Source *)msgdata; Evas *e; printf("handler... '%s' '%s'\n", name, info); if (strcmp(name, "comp.manager")) return; e = e_manager_comp_evas_get(man); if (!strcmp(info, "change.comp")) { if (!e) printf("TTT: No comp manager\n"); else printf("TTT: comp canvas = %p\n", e); if (e) setup(man); } else if (!strcmp(info, "resize.comp")) { printf("%s: %p | %p\n", info, man, src); } else if (!strcmp(info, "add.src")) { printf("%s: %p | %p\n", info, man, src); newwin(e, man, src, e_desk_current_get(e_util_zone_current_get(man))); } else if (!strcmp(info, "del.src")) { printf("%s: %p | %p\n", info, man, src); } else if (!strcmp(info, "config.src")) { printf("%s: %p | %p\n", info, man, src); } else if (!strcmp(info, "visible.src")) { printf("%s: %p | %p\n", info, man, src); } } /* Local Structures */ typedef struct _Instance Instance; struct _Instance { /* An instance of our item (module) with its elements */ /* pointer to this gadget's container */ E_Gadcon_Client *gcc; /* evas_object used to display */ Evas_Object *o_scale; /* popup anyone ? */ E_Menu *menu; /* Config_Item structure. Every gadget should have one :) */ Config_Item *conf_item; }; /* Local Variables */ static int uuid = 0; static Eina_List *instances = NULL; static E_Config_DD *conf_edd = NULL; static E_Config_DD *conf_item_edd = NULL; Config *scale_conf = NULL; static const E_Gadcon_Client_Class _gc_class = { GADCON_CLIENT_CLASS_VERSION, "scale", {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL}, E_GADCON_CLIENT_STYLE_PLAIN }; /* We set the version and the name, check e_mod_main.h for more details */ EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Scale"}; /* * Module Functions */ static void _e_mod_action_cb_edge(E_Object *obj, const char *params, E_Event_Zone_Edge *ev) { Eina_List *list, *l; E_Manager *man; msg_handler = e_msg_handler_add(handler, NULL); list = e_manager_list(); EINA_LIST_FOREACH(list, l, man) { Evas *e = e_manager_comp_evas_get(man); if (e) setup(man); } } /* Function called when the module is initialized */ EAPI void * e_modapi_init(E_Module *m) { char buf[4096]; /* Location of message catalogs for localization */ snprintf(buf, sizeof(buf), "%s/locale", e_module_dir_get(m)); bindtextdomain(PACKAGE, buf); bind_textdomain_codeset(PACKAGE, "UTF-8"); /* Location of theme to load for this module */ snprintf(buf, sizeof(buf), "%s/e-module-scale.edj", m->dir); /* Display this Modules config info in the main Config Panel */ /* starts with a category, create it if not already exists */ e_configure_registry_category_add("advanced", 80, "Advanced", NULL, "preferences-advanced"); /* add right-side item */ e_configure_registry_item_add("advanced/scale", 110, D_("Scale"), NULL, buf, e_int_config_scale_module); /* Define EET Data Storage for the config file */ conf_item_edd = E_CONFIG_DD_NEW("Config_Item", Config_Item); #undef T #undef D #define T Config_Item #define D conf_item_edd E_CONFIG_VAL(D, T, id, STR); E_CONFIG_VAL(D, T, switch2, INT); conf_edd = E_CONFIG_DD_NEW("Config", Config); #undef T #undef D #define T Config #define D conf_edd E_CONFIG_VAL(D, T, version, INT); E_CONFIG_VAL(D, T, switch1, UCHAR); /* our var from header */ E_CONFIG_LIST(D, T, conf_items, conf_item_edd); /* the list */ /* Tell E to find any existing module data. First run ? */ scale_conf = e_config_domain_load("module.scale", conf_edd); if (scale_conf) { /* Check config version */ if ((scale_conf->version >> 16) < MOD_CONFIG_FILE_EPOCH) { /* config too old */ _scale_conf_free(); ecore_timer_add(1.0, _scale_conf_timer, D_("Scale Module Configuration data needed " "upgrading. Your old configuration
has been" " wiped and a new set of defaults initialized. " "This
will happen regularly during " "development, so don't report a
bug. " "This simply means the module needs " "new configuration
data by default for " "usable functionality that your old
" "configuration simply lacks. This new set of " "defaults will fix
that by adding it in. " "You can re-configure things now to your
" "liking. Sorry for the inconvenience.
")); } /* Ardvarks */ else if (scale_conf->version > MOD_CONFIG_FILE_VERSION) { /* config too new...wtf ? */ _scale_conf_free(); ecore_timer_add(1.0, _scale_conf_timer, D_("Your Scale Module configuration is NEWER " "than the module version. This is " "very
strange. This should not happen unless" " you downgraded
the module or " "copied the configuration from a place where" "
a newer version of the module " "was running. This is bad and
as a " "precaution your configuration has been now " "restored to
defaults. Sorry for the " "inconvenience.
")); } } /* if we don't have a config yet, or it got erased above, * then create a default one */ if (!scale_conf) _scale_conf_new(); /* create a link from the modules config to the module * this is not written */ scale_conf->module = m; /* Tell any gadget containers (shelves, etc) that we provide a module * for the user to enjoy */ e_gadcon_provider_register(&_gc_class); act = e_action_add("scale"); if (act) { /* act->func.go = _e_mod_action_cb; */ act->func.go_edge = _e_mod_action_cb_edge; e_action_predef_name_set (D_("Desktop"), D_("Scale Windows"), "scale", "", NULL, 0); } /* Give E the module */ return m; } /* * Function to unload the module */ EAPI int e_modapi_shutdown(E_Module *m) { /* Unregister the config dialog from the main panel */ e_configure_registry_item_del("advanced/scale"); /* Remove the config panel category if we can. E will tell us. category stays if other items using it */ e_configure_registry_category_del("advanced"); /* Kill the config dialog */ if (scale_conf->cfd) e_object_del(E_OBJECT(scale_conf->cfd)); scale_conf->cfd = NULL; /* Tell E the module is now unloaded. Gets removed from shelves, etc. */ scale_conf->module = NULL; e_gadcon_provider_unregister(&_gc_class); /* Cleanup our item list */ while (scale_conf->conf_items) { Config_Item *ci = NULL; /* Grab an item from the list */ ci = scale_conf->conf_items->data; /* remove it */ scale_conf->conf_items = eina_list_remove_list(scale_conf->conf_items, scale_conf->conf_items); /* cleanup stringshares */ if (ci->id) eina_stringshare_del(ci->id); /* keep the planet green */ E_FREE(ci); } /* Cleanup the main config structure */ E_FREE(scale_conf); /* Clean EET */ E_CONFIG_DD_FREE(conf_item_edd); E_CONFIG_DD_FREE(conf_edd); if (act) { e_action_predef_name_del(D_("Desktop"), D_("Scale Windows")); e_action_del("scale"); } return 1; } /* * Function to Save the modules config */ EAPI int e_modapi_save(E_Module *m) { e_config_domain_save("module.scale", conf_edd, scale_conf); return 1; } /* Local Functions */ /* Called when Gadget Controller (gadcon) says to appear in scene */ static E_Gadcon_Client * _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) { Instance *inst = NULL; char buf[4096]; /* theme file */ snprintf(buf, sizeof(buf), "%s/e-module-scale.edj", scale_conf->module->dir); /* New visual instance, any config ? */ inst = E_NEW(Instance, 1); inst->conf_item = _scale_conf_item_get(id); /* create on-screen object */ inst->o_scale = edje_object_add(gc->evas); /* we have a theme ? */ if (!e_theme_edje_object_set(inst->o_scale, "base/theme/modules/scale", "modules/scale/main")) edje_object_file_set(inst->o_scale, buf, "modules/scale/main"); /* Start loading our module on screen via container */ inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->o_scale); inst->gcc->data = inst; /* hook a mouse down. we want/have a popup menu, right ? */ evas_object_event_callback_add(inst->o_scale, EVAS_CALLBACK_MOUSE_DOWN, _scale_cb_mouse_down, inst); /* add to list of running instances so we can cleanup later */ instances = eina_list_append(instances, inst); /* return the Gadget_Container Client */ return inst->gcc; } /* Called when Gadget_Container says stop */ static void _gc_shutdown(E_Gadcon_Client *gcc) { Instance *inst = NULL; if (!(inst = gcc->data)) return; instances = eina_list_remove(instances, inst); /* kill popup menu */ if (inst->menu) { e_menu_post_deactivate_callback_set(inst->menu, NULL, NULL); e_object_del(E_OBJECT(inst->menu)); inst->menu = NULL; } /* delete the visual */ if (inst->o_scale) { /* remove mouse down callback hook */ evas_object_event_callback_del(inst->o_scale, EVAS_CALLBACK_MOUSE_DOWN, _scale_cb_mouse_down); evas_object_del(inst->o_scale); } E_FREE(inst); } /* For when container says we are changing position */ static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient) { e_gadcon_client_aspect_set(gcc, 16, 16); e_gadcon_client_min_size_set(gcc, 16, 16); } /* Gadget/Module label, name for our module */ static char * _gc_label(E_Gadcon_Client_Class *client_class) { return D_("Scale"); } /* so E can keep a unique instance per-container */ static const char * _gc_id_new(E_Gadcon_Client_Class *client_class) { Config_Item *ci = NULL; ci = _scale_conf_item_get(NULL); return ci->id; } static Evas_Object * _gc_icon(E_Gadcon_Client_Class *client_class, Evas *evas) { Evas_Object *o = NULL; char buf[4096]; /* theme */ snprintf(buf, sizeof(buf), "%s/e-module-scale.edj", scale_conf->module->dir); /* create icon object */ o = edje_object_add(evas); /* load icon from theme */ edje_object_file_set(o, buf, "icon"); return o; } /* new module needs a new config :), or config too old and we need one anyway */ static void _scale_conf_new(void) { /* Config_Item *ci = NULL; */ /* char buf[128]; */ scale_conf = E_NEW(Config, 1); scale_conf->version = (MOD_CONFIG_FILE_EPOCH << 16); #define IFMODCFG(v) if ((scale_conf->version & 0xffff) < v) { #define IFMODCFGEND } /* setup defaults */ IFMODCFG(0x008d); scale_conf->switch1 = 1; _scale_conf_item_get(NULL); IFMODCFGEND; /* update the version */ scale_conf->version = MOD_CONFIG_FILE_VERSION; /* setup limits on the config properties here (if needed) */ /* save the config to disk */ e_config_save_queue(); } /* This is called when we need to cleanup the actual configuration, * for example when our configuration is too old */ static void _scale_conf_free(void) { /* cleanup any stringshares here */ while (scale_conf->conf_items) { Config_Item *ci = NULL; ci = scale_conf->conf_items->data; scale_conf->conf_items = eina_list_remove_list(scale_conf->conf_items, scale_conf->conf_items); /* EPA */ if (ci->id) eina_stringshare_del(ci->id); E_FREE(ci); } E_FREE(scale_conf); } /* timer for the config oops dialog (old configuration needs update) */ static Eina_Bool _scale_conf_timer(void *data) { e_util_dialog_internal( D_("Scale Windows Configuration Updated"), data); return EINA_FALSE; } /* function to search for any Config_Item struct for this Item * create if needed */ static Config_Item * _scale_conf_item_get(const char *id) { Eina_List *l = NULL; Config_Item *ci = NULL; char buf[128]; if (!id) { /* nothing passed, return a new id */ snprintf(buf, sizeof(buf), "%s.%d", _gc_class.name, ++uuid); id = buf; } else { uuid++; for (l = scale_conf->conf_items; l; l = l->next) { if (!(ci = l->data)) continue; if ((ci->id) && (!strcmp(ci->id, id))) return ci; } } ci = E_NEW(Config_Item, 1); ci->id = eina_stringshare_add(id); ci->switch2 = 0; scale_conf->conf_items = eina_list_append(scale_conf->conf_items, ci); return ci; } /* Pants On */ static void _scale_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event) { Instance *inst = NULL; Evas_Event_Mouse_Down *ev; E_Zone *zone = NULL; E_Menu_Item *mi = NULL; int x, y; if (!(inst = data)) return; ev = event; if (ev->button == 1) { _e_mod_action_cb_edge(NULL, NULL, NULL); } else if ((ev->button == 3) && (!inst->menu)) { E_Menu *ma, *mg; /* grab current zone */ zone = e_util_zone_current_get(e_manager_current_get()); /* create popup menu */ ma = e_menu_new(); e_menu_post_deactivate_callback_set(ma, _scale_cb_menu_post, inst); inst->menu = ma; mg = e_menu_new(); mi = e_menu_item_new(mg); e_menu_item_label_set(mi, D_("Settings")); e_util_menu_item_theme_icon_set(mi, "preferences-system"); e_menu_item_callback_set(mi, _scale_cb_menu_configure, NULL); /* Each Gadget Client has a utility menu from the Container */ e_gadcon_client_util_menu_items_append(inst->gcc, ma, mg, 0); e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL); /* show the menu relative to gadgets position */ e_menu_activate_mouse(ma, zone, (x + ev->output.x), (y + ev->output.y), 1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp); evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button, EVAS_BUTTON_NONE, ev->timestamp, NULL); } } /* popup menu closing, cleanup */ static void _scale_cb_menu_post(void *data, E_Menu *menu) { Instance *inst = NULL; if (!(inst = data)) return; if (!inst->menu) return; e_object_del(E_OBJECT(inst->menu)); inst->menu = NULL; } /* call configure from popup */ static void _scale_cb_menu_configure(void *data, E_Menu *mn, E_Menu_Item *mi) { if (!scale_conf) return; if (scale_conf->cfd) return; e_int_config_scale_module(mn->zone->container, NULL); }