e7ce99905942b081ae965689889f8fb5eb020e57
[platform/upstream/enlightenment.git] / src / bin / e_gadcon.c
1 #include "e.h"
2
3 /*
4  * TODO: gadcon client ordering on drop
5  */
6
7 #define E_LAYOUT_ITEM_DRAG_RESIST_LEVEL 10
8 static void                     _e_gadcon_event_populate(E_Gadcon *gc);
9 static Eina_Bool                _e_gadcon_client_populate(E_Gadcon *gc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf_gcc);
10 static void                     _e_gadcon_client_unpopulate(E_Gadcon_Client *gcc);
11 static void                     _e_gadcon_free(E_Gadcon *gc);
12 static void                     _e_gadcon_client_free(E_Gadcon_Client *gcc);
13
14 static void                     _e_gadcon_moveresize_handle(E_Gadcon_Client *gcc);
15 static Eina_Bool                _e_gadcon_cb_client_scroll_timer(void *data);
16 static Eina_Bool                _e_gadcon_cb_client_scroll_animator(void *data);
17 static void                     _e_gadcon_cb_client_frame_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
18 static void                     _e_gadcon_cb_client_frame_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
19 static void                     _e_gadcon_client_save(E_Gadcon_Client *gcc);
20 static void                     _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y);
21 static void                     _e_gadcon_client_inject(E_Gadcon *gc, E_Gadcon_Client *gcc, int x, int y);
22
23 static void                     _e_gadcon_cb_min_size_request(void *data, Evas_Object *obj, void *event_info);
24 static void                     _e_gadcon_cb_size_request(void *data, Evas_Object *obj, void *event_info);
25 static void                     _e_gadcon_cb_moveresize(void *data, Evas *evas, Evas_Object *obj, void *event_info);
26 static void                     _e_gadcon_parent_resize_cb(E_Gadcon *gc, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
27 static void                     _e_gadcon_cb_client_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
28 static void                     _e_gadcon_cb_client_mouse_in(void *data, Evas *evas, Evas_Object *obj, void *event_info);
29 static void                     _e_gadcon_cb_client_mouse_out(void *data, Evas *evas, Evas_Object *obj, void *event_info);
30 static void                     _e_gadcon_cb_client_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
31 static void                     _e_gadcon_cb_client_resize(void *data, Evas *evas, Evas_Object *obj, void *event_info);
32
33 static void                     _e_gadcon_client_move_start(E_Gadcon_Client *gcc);
34 static void                     _e_gadcon_client_move_stop(E_Gadcon_Client *gcc);
35 static void                     _e_gadcon_client_move_go(E_Gadcon_Client *gcc);
36
37 static void                     _e_gadcon_cb_signal_move_start(void *data, Evas_Object *obj, const char *emission, const char *source);
38 static void                     _e_gadcon_cb_signal_move_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
39 static void                     _e_gadcon_cb_signal_move_go(void *data, Evas_Object *obj, const char *emission, const char *source);
40 static void                     _e_gadcon_cb_signal_resize_left_start(void *data, Evas_Object *obj, const char *emission, const char *source);
41 static void                     _e_gadcon_cb_signal_resize_left_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
42 static void                     _e_gadcon_cb_signal_resize_left_go(void *data, Evas_Object *obj, const char *emission, const char *source);
43 static void                     _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj, const char *emission, const char *source);
44 static void                     _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
45 static void                     _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj, const char *emission, const char *source);
46 static void                     _e_gadcon_cb_dnd_enter(void *data, const char *type, void *event);
47 static void                     _e_gadcon_cb_dnd_move(void *data, const char *type, void *event);
48 static void                     _e_gadcon_cb_dnd_leave(void *data, const char *type, void *event);
49 static void                     _e_gadcon_cb_dnd_drop(void *data, const char *type, void *event);
50
51 static int                      _e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class *cc, const char *name, void *feature);
52 static void                     _e_gadcon_client_cb_menu_post(void *data, E_Menu *m);
53 static void                     _e_gadcon_client_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
54 static void                     _e_gadcon_client_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
55 static void                     _e_gadcon_client_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
56 static void                     _e_gadcon_client_cb_menu_style_plain(void *data, E_Menu *m, E_Menu_Item *mi);
57 static void                     _e_gadcon_client_cb_menu_style_inset(void *data, E_Menu *m, E_Menu_Item *mi);
58 static void                     _e_gadcon_client_cb_menu_autoscroll(void *data, E_Menu *m, E_Menu_Item *mi);
59 /*static void _e_gadcon_client_cb_menu_resizable(void *data, E_Menu *m, E_Menu_Item *mi);*/
60 static void                     _e_gadcon_client_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
61 static void                     _e_gadcon_client_cb_menu_remove(void *data, E_Menu *m, E_Menu_Item *mi);
62 static void                     _e_gadcon_client_cb_menu_pre(void *data, E_Menu *m, E_Menu_Item *mi);
63 static void                     _e_gadcon_client_delfn(void *d, void *o);
64 static void                     _e_gadcon_client_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
65 static void                     _e_gadcon_client_event_free(void *d, void *e);
66 static Evas_Object             *e_gadcon_layout_add(Evas *evas);
67 static void                     e_gadcon_layout_orientation_set(Evas_Object *obj, int horizontal);
68 static int                      e_gadcon_layout_orientation_get(Evas_Object *obj);
69 static void                     e_gadcon_layout_freeze(Evas_Object *obj);
70 static void                     e_gadcon_layout_thaw(Evas_Object *obj);
71 static void                     e_gadcon_layout_min_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
72 static void                     e_gadcon_layout_asked_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
73 static int                      e_gadcon_layout_pack(Evas_Object *obj, Evas_Object *child);
74 static void                     e_gadcon_layout_pack_size_set(Evas_Object *obj, int size);
75 static void                     e_gadcon_layout_pack_request_set(Evas_Object *obj, int pos, int size);
76 static void                     e_gadcon_layout_pack_options_set(Evas_Object *obj, E_Gadcon_Client *gcc);
77 static void                     e_gadcon_layout_pack_min_size_set(Evas_Object *obj, int w, int h);
78 static void                     e_gadcon_layout_pack_aspect_set(Evas_Object *obj, int w, int h);
79 static void                     e_gadcon_layout_pack_aspect_pad_set(Evas_Object *obj, int w, int h);
80 static void                     e_gadcon_layout_unpack(Evas_Object *obj);
81 static void                     _e_gadcon_provider_populate_request(E_Gadcon *gc, const E_Gadcon_Client_Class *cc);
82 static void                     _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc);
83 static void                     _e_gadcon_provider_populate_job(void *data);
84 static void                     _e_gadcon_event_populate_free(void *data __UNUSED__, void *event);
85 static void                     _e_gadcon_custom_populate_job(void *data);
86
87 static int                      _e_gadcon_location_change(E_Gadcon_Client *gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst);
88
89 typedef struct _E_Smart_Data            E_Smart_Data;
90 typedef struct _E_Layout_Item_Container E_Layout_Item_Container;
91
92 static void                     _e_gadcon_client_current_position_sync(E_Gadcon_Client *gcc);
93 static void                     _e_gadcon_layout_smart_sync_clients(E_Gadcon *gc);
94 static void                     _e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data *sd);
95 static void                     _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd);
96 static Eina_List               *_e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data *sd);
97 static void                     _e_gadcon_layout_smart_gadcons_position(E_Smart_Data *sd, Eina_List **list);
98 static void                     _e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data *sd, Eina_List **list);
99 static E_Layout_Item_Container *_e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2);
100 static void                     _e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data *sd, E_Layout_Item_Container *lc);
101 static void                     _e_gadcon_layout_smart_containers_merge(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2);
102 static void                     _e_gadcon_layout_smart_restore_gadcons_position_before_move(E_Smart_Data *sd, E_Layout_Item_Container **lc_moving, E_Layout_Item_Container *lc_back, Eina_List **con_list);
103
104 typedef enum _E_Gadcon_Layout_Item_State
105 {
106    E_LAYOUT_ITEM_STATE_NONE,
107    E_LAYOUT_ITEM_STATE_POS_INC,
108    E_LAYOUT_ITEM_STATE_POS_DEC,
109    E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC,
110    E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC,
111    E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC,
112    E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC,
113 } E_Gadcon_Layout_Item_State;
114
115 typedef enum _E_Gadcon_Layout_Item_Flags
116 {
117    E_GADCON_LAYOUT_ITEM_LOCK_NONE = 0x00000000,
118    E_GADCON_LAYOUT_ITEM_LOCK_POSITION = 0x00000001,
119    E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE = 0x00000002
120 } E_Gadcon_Layout_Item_Flags;
121
122 typedef enum _E_Layout_Item_Container_State
123 {
124    E_LAYOUT_ITEM_CONTAINER_STATE_NONE,
125    E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC,
126    E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC,
127    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC,
128    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC,
129    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC,
130    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC,
131    E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED
132 } E_Layout_Item_Container_State;
133
134 struct _E_Layout_Item_Container
135 {
136    int                           pos, size, prev_pos, prev_size;
137
138    struct
139    {
140       int min_seq, max_seq;
141    } state_info;
142
143    E_Smart_Data                 *sd;
144    Eina_List                    *items;
145
146    E_Layout_Item_Container_State state;
147 };
148
149 #define LC_FREE(__lc)             \
150   if (__lc->items)                \
151     eina_list_free(__lc->items);  \
152   E_FREE(__lc)
153
154 #define E_LAYOUT_ITEM_CONTAINER_STATE_SET(__con_state, __bi_state) \
155   if (__bi_state == E_LAYOUT_ITEM_STATE_NONE)                      \
156     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;              \
157   else if (__bi_state == E_LAYOUT_ITEM_STATE_POS_INC)              \
158     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC;           \
159   else if (__bi_state == E_LAYOUT_ITEM_STATE_POS_DEC)              \
160     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC;           \
161   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC)     \
162     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC;  \
163   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC)     \
164     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC;  \
165   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC)     \
166     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC;  \
167   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC)     \
168     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC
169
170 #define LC_OVERLAP(__lc, __lc2)                                                        \
171   ((((__lc2)->pos >= (__lc)->pos) && ((__lc2)->pos < ((__lc)->pos + (__lc)->size))) || \
172    (((__lc)->pos >= (__lc2)->pos) && ((__lc)->pos < ((__lc2)->pos + (__lc2)->size))))
173
174 #define E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(__lc, __bi, __increase) \
175   {                                                                    \
176      if (__increase)                                                   \
177        __lc->size += __bi->w;                                          \
178      else                                                              \
179        __lc->size -= __bi->w;                                          \
180   }
181
182 /********************/
183 EAPI int E_EVENT_GADCON_CLIENT_CLASS_ADD = -1;
184 EAPI int E_EVENT_GADCON_CLIENT_CLASS_DEL = -1;
185 EAPI int E_EVENT_GADCON_CLIENT_ADD = -1;
186 EAPI int E_EVENT_GADCON_CLIENT_DEL = -1;
187 EAPI int E_EVENT_GADCON_POPULATE = -1;
188
189 static Eina_Hash *providers = NULL;
190 static Eina_List *providers_list = NULL;
191 static Eina_List *gadcons = NULL;
192 static Eina_List *dummies = NULL;
193 static Ecore_Job *populate_job = NULL;
194 static Eina_List *custom_populate_requests = NULL;
195 static Ecore_Job *custom_populate_job = NULL;
196 static Eina_List *gadcon_locations = NULL;
197 static Ecore_Event_Handler *_module_init_end_handler = NULL;
198 static Eina_Bool _modules_loaded = EINA_FALSE;
199
200 static inline void
201 _eina_list_free(Eina_List *l)
202 {
203    eina_list_free(l);
204 }
205
206 static int
207 _e_gadcon_provider_list_sort_cb(E_Gadcon_Client_Class *a, E_Gadcon_Client_Class *b)
208 {
209    return strcasecmp(a->name, b->name);
210 }
211
212 static Eina_Bool
213 _module_init_end_cb(void *d __UNUSED__, int type __UNUSED__, void *ev __UNUSED__)
214 {
215    _modules_loaded = EINA_TRUE;
216    return ECORE_CALLBACK_RENEW;
217 }
218
219 /* externally accessible functions */
220 EINTERN int
221 e_gadcon_init(void)
222 {
223    E_EVENT_GADCON_CLIENT_CLASS_ADD = ecore_event_type_new();
224    E_EVENT_GADCON_CLIENT_CLASS_DEL = ecore_event_type_new();
225    E_EVENT_GADCON_CLIENT_ADD = ecore_event_type_new();
226    E_EVENT_GADCON_CLIENT_DEL = ecore_event_type_new();
227    E_EVENT_GADCON_POPULATE = ecore_event_type_new();
228    _module_init_end_handler = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _module_init_end_cb, NULL);
229    return 1;
230 }
231
232 EINTERN int
233 e_gadcon_shutdown(void)
234 {
235    if (populate_job)
236      {
237         ecore_job_del(populate_job);
238         populate_job = NULL;
239      }
240    custom_populate_requests = eina_list_free(custom_populate_requests);
241    if (custom_populate_job)
242      {
243         ecore_job_del(custom_populate_job);
244         custom_populate_job = NULL;
245      }
246    _modules_loaded = EINA_FALSE;
247    if (_module_init_end_handler)
248      ecore_event_handler_del(_module_init_end_handler);
249    _module_init_end_handler = NULL;
250
251    return 1;
252 }
253
254 /**
255  * Registers a new gadget class in e
256  *
257  * @param cc version of gadcon, name and callbacks to use
258  * for handling creation and destroying a gadget
259  */
260 EAPI void
261 e_gadcon_provider_register(const E_Gadcon_Client_Class *cc)
262 {
263    E_Gadcon *gc;
264    Eina_List *l, *ll, *lll;
265    E_Config_Gadcon_Client *cf_gcc;
266
267    EINA_SAFETY_ON_NULL_RETURN(cc->name);
268    if (!providers) providers = eina_hash_string_superfast_new(NULL);
269    eina_hash_direct_add(providers, cc->name, cc);
270    EINA_LIST_FOREACH(gadcons, l, gc)
271      {
272         e_gadcon_layout_freeze(gc->o_container);
273         if (gc->awaiting_classes)
274           {
275              ll = eina_hash_find(gc->awaiting_classes, cc->name);
276              EINA_LIST_FOREACH(ll, lll, cf_gcc)
277                _e_gadcon_client_populate(gc, cc, cf_gcc);
278           }
279         e_gadcon_layout_thaw(gc->o_container);
280      }
281    providers_list = eina_list_sorted_insert(providers_list, (Eina_Compare_Cb)_e_gadcon_provider_list_sort_cb, cc);
282    {
283       E_Event_Gadcon_Client_Class_Add *ev;
284       ev = E_NEW(E_Event_Gadcon_Client_Class_Add, 1);
285       ev->cc = cc;
286       ecore_event_add(E_EVENT_GADCON_CLIENT_CLASS_ADD, ev, NULL, NULL);
287    }
288 }
289
290 /**
291  * unregisters a gadget class in e
292  *
293  * @param cc the gadget class that was used to register the gadget
294  */
295 EAPI void
296 e_gadcon_provider_unregister(const E_Gadcon_Client_Class *cc)
297 {
298    Eina_List *l, *ll, *dlist = NULL;
299    E_Gadcon *gc;
300    E_Gadcon_Client *gcc;
301
302    _e_gadcon_provider_populate_unrequest(cc);
303
304    EINA_LIST_FOREACH(gadcons, l, gc)
305      {
306         EINA_LIST_FOREACH(gc->clients, ll, gcc)
307           {
308              if (gcc->client_class == cc)
309                dlist = eina_list_append(dlist, gcc);
310           }
311         gc->populated_classes = eina_list_remove(gc->populated_classes, cc);
312      }
313    EINA_LIST_FREE(dlist, gcc)
314      {
315         e_gadcon_client_queue(gcc->gadcon, gcc->cf);
316         gcc->hidden = 0;
317         e_gadcon_client_hide(gcc);
318         e_object_del(E_OBJECT(gcc));
319      }
320
321    eina_hash_del(providers, cc->name, cc);
322    providers_list = eina_list_remove(providers_list, cc);
323    {
324       E_Event_Gadcon_Client_Class_Add *ev;
325       ev = E_NEW(E_Event_Gadcon_Client_Class_Add, 1);
326       ev->cc = cc;
327       ecore_event_add(E_EVENT_GADCON_CLIENT_CLASS_DEL, ev, NULL, NULL);
328    }
329 }
330
331 EAPI void
332 e_gadcon_client_queue(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc)
333 {
334    Eina_List *l;
335    if (!gc->awaiting_classes)
336      gc->awaiting_classes = eina_hash_string_superfast_new((Eina_Free_Cb)_eina_list_free);
337    l = eina_hash_find(gc->awaiting_classes, cf_gcc->name);
338    if (eina_list_data_find(l, cf_gcc)) return;
339    l = eina_list_append(l, cf_gcc);
340    eina_hash_set(gc->awaiting_classes, cf_gcc->name, l);
341 }
342
343 EAPI Eina_List *
344 e_gadcon_provider_list(void)
345 {
346    return providers_list;
347 }
348
349 EAPI void
350 e_gadcon_custom_new(E_Gadcon *gc)
351 {
352    E_OBJECT_CHECK(gc);
353    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
354
355    gadcons = eina_list_append(gadcons, gc);
356
357    if (!custom_populate_job)
358      {
359         custom_populate_job =
360           ecore_job_add(_e_gadcon_custom_populate_job, NULL);
361      }
362    if (!eina_list_data_find(custom_populate_requests, gc))
363      custom_populate_requests = eina_list_append(custom_populate_requests, gc);
364    gc->custom = EINA_TRUE;
365 }
366
367 EAPI void
368 e_gadcon_custom_del(E_Gadcon *gc)
369 {
370    E_OBJECT_CHECK(gc);
371    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
372
373    if (eina_list_data_find(custom_populate_requests, gc))
374      custom_populate_requests = eina_list_remove(custom_populate_requests, gc);
375
376    gadcons = eina_list_remove(gadcons, gc);
377 }
378
379 EAPI void
380 e_gadcon_custom_populate_request(E_Gadcon *gc)
381 {
382    E_OBJECT_CHECK(gc);
383    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
384
385    if (!gc->custom) return;
386    if (!custom_populate_job)
387      {
388         custom_populate_job =
389           ecore_job_add(_e_gadcon_custom_populate_job, NULL);
390      }
391    if (!eina_list_data_find(custom_populate_requests, gc))
392      custom_populate_requests = eina_list_append(custom_populate_requests, gc);
393 }
394
395 EAPI E_Gadcon *
396 e_gadcon_dummy_new(int id)
397 {
398    E_Gadcon *gc;
399
400    gc = E_OBJECT_ALLOC(E_Gadcon, E_GADCON_DUMMY_TYPE, _e_gadcon_free);
401    if (!gc) return NULL;
402
403    gc->id = id;
404    gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
405    gc->location = NULL;
406    gc->dummy = 1;
407
408    gc->orient = E_GADCON_ORIENT_HORIZ;
409    dummies = eina_list_append(dummies, gc);
410    return gc;
411 }
412
413 EAPI void
414 e_gadcon_config_del(E_Gadcon *gc)
415 {
416    E_OBJECT_CHECK(gc);
417    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
418    gc->cfg_delete = 1;
419 }
420
421 EAPI void
422 e_gadcon_drop_handler_add(E_Gadcon *gc, E_Gadcon_DND_Cb enter, E_Gadcon_DND_Cb leave, E_Gadcon_DND_Cb move, E_Gadcon_DND_Cb drop, int x, int y, int w, int h)
423 {
424    const char *drop_types[] = { "enlightenment/gadcon_client" };
425
426    E_OBJECT_CHECK(gc);
427    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
428    if (gc->drop_handler) return;
429    gc->drop_handler =
430      e_drop_handler_add(E_OBJECT(gc), gc,
431                         _e_gadcon_cb_dnd_enter, _e_gadcon_cb_dnd_move,
432                         _e_gadcon_cb_dnd_leave, _e_gadcon_cb_dnd_drop,
433                         drop_types, 1, x, y, w, h);
434    gc->dnd_enter_cb = enter;
435    gc->dnd_leave_cb = leave;
436    gc->dnd_move_cb = move;
437    gc->dnd_drop_cb = drop;
438 }
439
440 EAPI E_Gadcon *
441 e_gadcon_swallowed_new(const char *name, int id, Evas_Object *obj, const char *swallow_name)
442 {
443    E_Gadcon *gc;
444    E_Config_Gadcon *cf_gc;
445    Eina_List *l;
446    Evas_Coord x, y, w, h;
447
448    gc = E_OBJECT_ALLOC(E_Gadcon, E_GADCON_TYPE, _e_gadcon_free);
449    if (!gc) return NULL;
450
451    gc->name = eina_stringshare_add(name);
452    gc->id = id;
453    gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
454    gc->location = NULL;
455
456    gc->edje.o_parent = obj;
457    gc->edje.swallow_name = eina_stringshare_add(swallow_name);
458
459    gc->orient = E_GADCON_ORIENT_HORIZ;
460    gc->evas = evas_object_evas_get(obj);
461    gc->o_container = e_gadcon_layout_add(gc->evas);
462    evas_object_geometry_get(gc->o_container, &x, &y, &w, &h);
463    e_gadcon_drop_handler_add(gc, NULL, NULL, NULL, NULL, x, y, w, h);
464    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_MOVE,
465                                   _e_gadcon_cb_moveresize, gc);
466    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
467                                   (Evas_Object_Event_Cb)_e_gadcon_parent_resize_cb, gc);
468    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_RESIZE,
469                                   _e_gadcon_cb_moveresize, gc);
470    evas_object_smart_callback_add(gc->o_container, "size_request",
471                                   _e_gadcon_cb_size_request, gc);
472    evas_object_smart_callback_add(gc->o_container, "min_size_request",
473                                   _e_gadcon_cb_min_size_request, gc);
474    evas_object_show(gc->o_container);
475    edje_object_part_swallow(gc->edje.o_parent, gc->edje.swallow_name,
476                             gc->o_container);
477    gadcons = eina_list_append(gadcons, gc);
478
479    EINA_LIST_FOREACH(e_config->gadcons, l, cf_gc)
480      {
481         if ((!strcmp(cf_gc->name, gc->name)) && (cf_gc->id == gc->id))
482           {
483              gc->cf = cf_gc;
484              break;
485           }
486      }
487    if (!gc->cf)
488      {
489         gc->cf = E_NEW(E_Config_Gadcon, 1);
490         gc->cf->name = eina_stringshare_add(gc->name);
491         gc->cf->id = gc->id;
492         e_config->gadcons = eina_list_append(e_config->gadcons, gc->cf);
493         e_config_save_queue();
494      }
495    return gc;
496 }
497
498 EAPI void
499 e_gadcon_swallowed_min_size_set(E_Gadcon *gc, Evas_Coord w, Evas_Coord h)
500 {
501    E_OBJECT_CHECK(gc);
502    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
503    if (gc->edje.o_parent)
504      {
505         edje_extern_object_min_size_set(gc->o_container, w, h);
506         edje_object_part_swallow(gc->edje.o_parent, gc->edje.swallow_name,
507                                  gc->o_container);
508      }
509 }
510
511 EAPI void
512 e_gadcon_min_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data)
513 {
514    E_OBJECT_CHECK(gc);
515    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
516    gc->min_size_request.func = func;
517    gc->min_size_request.data = data;
518 }
519
520 EAPI void
521 e_gadcon_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data)
522 {
523    E_OBJECT_CHECK(gc);
524    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
525    gc->resize_request.func = func;
526    gc->resize_request.data = data;
527 }
528
529 EAPI void
530 e_gadcon_frame_request_callback_set(E_Gadcon *gc, Evas_Object *(*func)(void *data, E_Gadcon_Client * gcc, const char *style), void *data)
531 {
532    E_OBJECT_CHECK(gc);
533    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
534    gc->frame_request.func = func;
535    gc->frame_request.data = data;
536 }
537
538 EAPI void
539 e_gadcon_populate_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, const E_Gadcon_Client_Class *cc), void *data)
540 {
541    E_OBJECT_CHECK(gc);
542    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
543    gc->populate_class.func = func;
544    gc->populate_class.data = data;
545 }
546
547 EAPI void
548 e_gadcon_layout_policy_set(E_Gadcon *gc, E_Gadcon_Layout_Policy layout_policy)
549 {
550    E_OBJECT_CHECK(gc);
551    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
552    if (gc->layout_policy == layout_policy) return;
553    gc->layout_policy = layout_policy;
554    /* FIXME: delete container obj, re-pack all clients */
555 }
556
557 EAPI Eina_Bool
558 e_gadcon_populate(E_Gadcon *gc)
559 {
560    Eina_List *l;
561    E_Config_Gadcon_Client *cf_gcc;
562
563    E_OBJECT_CHECK(gc);
564    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
565    e_gadcon_layout_freeze(gc->o_container);
566    EINA_LIST_FOREACH(gc->cf->clients, l, cf_gcc)
567      {
568         E_Gadcon_Client_Class *cc;
569
570         if (!cf_gcc->name) continue;
571         cc = eina_hash_find(providers, cf_gcc->name);
572         if (cc)
573           {
574              if (!eina_list_data_find(gc->populated_classes, cc))
575                {
576                   _e_gadcon_provider_populate_request(gc, cc);
577                   cc = NULL;
578                }
579           }
580         if (cc)
581           _e_gadcon_client_populate(gc, cc, cf_gcc);
582         else
583           e_gadcon_client_queue(gc, cf_gcc);
584      }
585    e_gadcon_layout_thaw(gc->o_container);
586    if (gc->populated_classes && (!gc->populate_requests))
587      _e_gadcon_event_populate(gc);
588    return EINA_TRUE;
589 }
590
591 EAPI void
592 e_gadcon_unpopulate(E_Gadcon *gc)
593 {
594    E_Gadcon_Client *gcc;
595
596    E_OBJECT_CHECK(gc);
597    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
598    /* Be careful, e_object_del does remove gcc from gc->clients */
599    if (gc->o_container) e_gadcon_layout_freeze(gc->o_container);
600    while (gc->clients)
601      {
602         gcc = eina_list_data_get(gc->clients);
603         _e_gadcon_client_unpopulate(gcc);
604         /* FIXME: this seems to happen under some rare and as-yet
605          * undetermined circumstances in gadman
606          */
607         if (gcc != eina_list_data_get(gc->clients)) continue;
608         CRI("DANGLING GADCON CLIENT %p! THIS IS A BUG!!!", gcc);
609         e_object_unref(E_OBJECT(gcc));
610      }
611    if (gc->awaiting_classes)
612      eina_hash_free(gc->awaiting_classes);
613    gc->awaiting_classes = NULL;
614    if (gc->o_container) e_gadcon_layout_thaw(gc->o_container);
615 }
616
617 EAPI void
618 e_gadcon_repopulate(E_Gadcon *gc)
619 {
620    E_OBJECT_CHECK(gc);
621    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
622    if (gc->o_container) e_gadcon_layout_freeze(gc->o_container);
623    e_gadcon_unpopulate(gc);
624    e_gadcon_populate(gc);
625    if (gc->o_container) e_gadcon_layout_thaw(gc->o_container);
626 }
627
628 EAPI void
629 e_gadcon_populate_class(E_Gadcon *gc, const E_Gadcon_Client_Class *cc)
630 {
631    Eina_List *l;
632    E_Config_Gadcon_Client *cf_gcc;
633
634    E_OBJECT_CHECK(gc);
635    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
636    e_gadcon_layout_freeze(gc->o_container);
637    EINA_LIST_FOREACH(gc->cf->clients, l, cf_gcc)
638      {
639         if (cf_gcc->name && (!strcmp(cf_gcc->name, cc->name)) &&
640             (cf_gcc->id) && (cf_gcc->style))
641           _e_gadcon_client_populate(gc, cc, cf_gcc);
642      }
643    e_gadcon_layout_thaw(gc->o_container);
644 }
645
646 EAPI void
647 e_gadcon_orient(E_Gadcon *gc, E_Gadcon_Orient orient)
648 {
649    Eina_List *l;
650    E_Gadcon_Client *gcc;
651    int horiz = 0;
652
653    E_OBJECT_CHECK(gc);
654    E_OBJECT_IF_NOT_TYPE(gc, E_GADCON_DUMMY_TYPE)
655    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
656    if (gc->orient == orient) return;
657    gc->orient = orient;
658    if (gc->dummy) return;
659    e_gadcon_layout_freeze(gc->o_container);
660    switch (gc->orient)
661      {
662       case E_GADCON_ORIENT_FLOAT:
663       case E_GADCON_ORIENT_HORIZ:
664       case E_GADCON_ORIENT_TOP:
665       case E_GADCON_ORIENT_BOTTOM:
666       case E_GADCON_ORIENT_CORNER_TL:
667       case E_GADCON_ORIENT_CORNER_TR:
668       case E_GADCON_ORIENT_CORNER_BL:
669       case E_GADCON_ORIENT_CORNER_BR:
670         horiz = 1;
671         break;
672
673       case E_GADCON_ORIENT_VERT:
674       case E_GADCON_ORIENT_LEFT:
675       case E_GADCON_ORIENT_RIGHT:
676       case E_GADCON_ORIENT_CORNER_LT:
677       case E_GADCON_ORIENT_CORNER_RT:
678       case E_GADCON_ORIENT_CORNER_LB:
679       case E_GADCON_ORIENT_CORNER_RB:
680         horiz = 0;
681         break;
682
683       default:
684         break;
685      }
686    e_gadcon_layout_orientation_set(gc->o_container, horiz);
687    EINA_LIST_FOREACH(gc->clients, l, gcc)
688      {
689         e_box_orientation_set(gcc->o_box, horiz);
690         if (gcc->client_class->func.orient)
691           gcc->client_class->func.orient(gcc, gc->orient);
692      }
693    e_gadcon_layout_thaw(gc->o_container);
694 }
695
696 EAPI void
697 e_gadcon_edit_begin(E_Gadcon *gc)
698 {
699    Eina_List *l;
700    E_Gadcon_Client *gcc;
701
702    E_OBJECT_CHECK(gc);
703    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
704    e_gadcon_layout_freeze(gc->o_container);
705    e_gadcon_locked_set(gc, 1);
706    gc->editing = 1;
707    EINA_LIST_FOREACH(gc->clients, l, gcc)
708      e_gadcon_client_edit_begin(gcc);
709    e_gadcon_layout_thaw(gc->o_container);
710 }
711
712 EAPI void
713 e_gadcon_edit_end(E_Gadcon *gc)
714 {
715    Eina_List *l;
716    E_Gadcon_Client *gcc;
717
718    E_OBJECT_CHECK(gc);
719    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
720    e_gadcon_layout_freeze(gc->o_container);
721    gc->editing = 0;
722    EINA_LIST_FOREACH(gc->clients, l, gcc)
723      e_gadcon_client_edit_end(gcc);
724    e_gadcon_layout_thaw(gc->o_container);
725    e_gadcon_locked_set(gc, 0);
726 }
727
728 EAPI void
729 e_gadcon_all_edit_begin(void)
730 {
731    Eina_List *l;
732    E_Gadcon *gc;
733
734    EINA_LIST_FOREACH(gadcons, l, gc)
735      e_gadcon_edit_begin(gc);
736 }
737
738 EAPI void
739 e_gadcon_all_edit_end(void)
740 {
741    Eina_List *l;
742    E_Gadcon *gc;
743
744    EINA_LIST_FOREACH(gadcons, l, gc)
745      e_gadcon_edit_end(gc);
746 }
747
748 EAPI void
749 e_gadcon_zone_set(E_Gadcon *gc, E_Zone *zone)
750 {
751    E_OBJECT_CHECK(gc);
752    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
753    gc->zone = zone;
754    if (gc->cf) gc->cf->zone = zone->num;
755 }
756
757 EAPI E_Zone *
758 e_gadcon_zone_get(E_Gadcon *gc)
759 {
760    E_OBJECT_CHECK_RETURN(gc, NULL);
761    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
762    if (gc->zone) return gc->zone;
763    if (!gc->toolbar) return NULL;
764    return gc->toolbar->fwin->client->zone;
765 }
766
767 EAPI void
768 e_gadcon_ecore_evas_set(E_Gadcon *gc, Ecore_Evas *ee)
769 {
770    E_OBJECT_CHECK(gc);
771    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
772    gc->ecore_evas = ee;
773 }
774
775 EAPI int
776 e_gadcon_canvas_zone_geometry_get(E_Gadcon *gc, int *x, int *y, int *w, int *h)
777 {
778    E_OBJECT_CHECK_RETURN(gc, 0);
779    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
780    if (!gc->ecore_evas) return 0;
781    ecore_evas_geometry_get(gc->ecore_evas, x, y, w, h);
782 // so much relies on this down here to have been broken... ie return comp-relative coords.
783 //   if (gc->zone)
784 //     {
785 //      if (x) *x = *x - gc->zone->x;
786 //      if (y) *y = *y - gc->zone->y;
787 //     }
788    return 1;
789 }
790
791 EAPI void
792 e_gadcon_util_menu_attach_func_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon_Client *gcc, E_Menu *menu), void *data)
793 {
794    E_OBJECT_CHECK(gc);
795    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
796    gc->menu_attach.func = func;
797    gc->menu_attach.data = data;
798 }
799
800 EAPI void
801 e_gadcon_util_lock_func_set(E_Gadcon *gc, void (*func)(void *data, int lock), void *data)
802 {
803    E_OBJECT_CHECK(gc);
804    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
805    gc->locked_set.func = func;
806    gc->locked_set.data = data;
807 }
808
809 EAPI void
810 e_gadcon_util_urgent_show_func_set(E_Gadcon *gc, void (*func)(void *data), void *data)
811 {
812    E_OBJECT_CHECK(gc);
813    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
814    gc->urgent_show.func = func;
815    gc->urgent_show.data = data;
816 }
817
818 EAPI void
819 e_gadcon_dnd_window_set(E_Gadcon *gc, Ecore_X_Window win)
820 {
821    E_OBJECT_CHECK(gc);
822    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
823    gc->dnd_win = win;
824 }
825
826 EAPI Ecore_X_Window
827 e_gadcon_dnd_window_get(E_Gadcon *gc)
828 {
829    E_OBJECT_CHECK_RETURN(gc, 0);
830    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
831    return gc->dnd_win;
832 }
833
834 EAPI void
835 e_gadcon_xdnd_window_set(E_Gadcon *gc, Ecore_X_Window win)
836 {
837    E_OBJECT_CHECK(gc);
838    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
839    gc->xdnd_win = win;
840 }
841
842 EAPI Ecore_X_Window
843 e_gadcon_xdnd_window_get(E_Gadcon *gc)
844 {
845    E_OBJECT_CHECK_RETURN(gc, 0);
846    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
847    return gc->xdnd_win;
848 }
849
850 EAPI void
851 e_gadcon_name_set(E_Gadcon *gc, const char *name)
852 {
853    if (!gc) return;
854    if (!name) return;
855    if (gc->name == name) return;
856    eina_stringshare_replace(&gc->name, name);
857    eina_stringshare_replace(&gc->cf->name, name);
858 }
859
860 EAPI void
861 e_gadcon_shelf_set(E_Gadcon *gc, E_Shelf *shelf)
862 {
863    E_OBJECT_CHECK(gc);
864    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
865    gc->shelf = shelf;
866 }
867
868 EAPI E_Shelf *
869 e_gadcon_shelf_get(E_Gadcon *gc)
870 {
871    E_OBJECT_CHECK_RETURN(gc, NULL);
872    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
873    return gc->shelf;
874 }
875
876 EAPI void
877 e_gadcon_toolbar_set(E_Gadcon *gc, E_Toolbar *toolbar)
878 {
879    E_OBJECT_CHECK(gc);
880    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
881    gc->toolbar = toolbar;
882 }
883
884 EAPI E_Toolbar *
885 e_gadcon_toolbar_get(E_Gadcon *gc)
886 {
887    E_OBJECT_CHECK_RETURN(gc, NULL);
888    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
889    return gc->toolbar;
890 }
891
892 EAPI E_Config_Gadcon_Client *
893 e_gadcon_client_config_new(E_Gadcon *gc, const char *name)
894 {
895    E_Gadcon_Client_Class *cc;
896    E_Config_Gadcon_Client *cf_gcc;
897
898    E_OBJECT_CHECK_RETURN(gc, NULL);
899    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
900    if (!name) return NULL;
901    cc = eina_hash_find(providers, name);
902    if (!cc) return NULL;
903    if (!_e_gadcon_client_class_feature_check(cc, "id_new", cc->func.id_new))
904      return NULL;
905
906    cf_gcc = E_NEW(E_Config_Gadcon_Client, 1);
907    if (!cf_gcc) return NULL;
908    cf_gcc->id = eina_stringshare_add(cc->func.id_new(cc));
909    if (!cf_gcc->id)
910      {
911         free(cf_gcc);
912         return NULL;
913      }
914    cf_gcc->name = eina_stringshare_add(name);
915    if (gc->zone)
916      cf_gcc->geom.res = gc->zone->w;
917    else if (gc->o_container)
918      {
919         int w, h;
920         evas_object_geometry_get(gc->o_container, NULL, NULL, &w, &h);
921         switch (gc->orient)
922           {
923            case E_GADCON_ORIENT_VERT:
924            case E_GADCON_ORIENT_LEFT:
925            case E_GADCON_ORIENT_RIGHT:
926            case E_GADCON_ORIENT_CORNER_LT:
927            case E_GADCON_ORIENT_CORNER_RT:
928            case E_GADCON_ORIENT_CORNER_LB:
929            case E_GADCON_ORIENT_CORNER_RB:
930              cf_gcc->geom.res = h;
931              break;
932
933            default:
934              cf_gcc->geom.res = w;
935           }
936      }
937    else
938      cf_gcc->geom.res = 800;
939    cf_gcc->geom.size = 80;
940    cf_gcc->geom.pos = cf_gcc->geom.res - cf_gcc->geom.size;
941    cf_gcc->style = NULL;
942    cf_gcc->autoscroll = 0;
943    cf_gcc->resizable = 0;
944    gc->cf->clients = eina_list_append(gc->cf->clients, cf_gcc);
945    e_config_save_queue();
946    return cf_gcc;
947 }
948
949 EAPI void
950 e_gadcon_client_config_del(E_Config_Gadcon *cf_gc, E_Config_Gadcon_Client *cf_gcc)
951 {
952    E_Gadcon *gc;
953    Eina_List *l, *ll;
954
955    if (!cf_gcc) return;
956    EINA_LIST_FOREACH(gadcons, l, gc)
957      {
958         if (!gc->awaiting_classes) continue;
959         ll = eina_hash_find(gc->awaiting_classes, cf_gcc->name);
960         eina_hash_set(gc->awaiting_classes, cf_gcc->name, eina_list_remove(ll, cf_gcc));
961      }
962
963    eina_stringshare_del(cf_gcc->name);
964    eina_stringshare_del(cf_gcc->id);
965    eina_stringshare_del(cf_gcc->style);
966    if (cf_gc) cf_gc->clients = eina_list_remove(cf_gc->clients, cf_gcc);
967    free(cf_gcc);
968 }
969
970 EAPI E_Gadcon_Client *
971 e_gadcon_client_find(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc)
972 {
973    E_Gadcon_Client *gcc;
974    Eina_List *l, *ll;
975
976    if (!cf_gcc) return NULL;
977    if (gc)
978      {
979         EINA_LIST_FOREACH(gc->clients, ll, gcc)
980           if (gcc->cf == cf_gcc) return gcc;
981         return NULL;
982      }
983    EINA_LIST_FOREACH(gadcons, l, gc)
984      EINA_LIST_FOREACH(gc->clients, ll, gcc)
985        if (gcc->cf == cf_gcc) return gcc;
986    return NULL;
987 }
988
989 static void
990 _e_gadcon_client_box_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
991 {
992    E_Gadcon_Client *gcc = data;
993    gcc->o_box = NULL;
994 }
995
996 static void
997 _e_gadcon_client_frame_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
998 {
999    E_Gadcon_Client *gcc = data;
1000    gcc->o_frame = NULL;
1001 }
1002
1003 EAPI void
1004 e_gadcon_drag_finished_cb(E_Drag *drag, int dropped)
1005 {
1006    E_Gadcon_Client *gcc;
1007
1008    gcc = drag->data;
1009    gcc->drag.drag = NULL;
1010    if (!dropped)
1011      {
1012         /* free client config */
1013         e_gadcon_client_config_del(NULL, gcc->cf);
1014         gcc->cf = NULL;
1015         /* delete the gadcon client */
1016         /* TODO: Clean up module config too? */
1017         e_object_del(E_OBJECT(gcc));
1018      }
1019    e_gadcon_client_drag_set(NULL);
1020    gcc->gadcon->new_gcc = NULL;
1021    e_object_unref(E_OBJECT(gcc));
1022 }
1023
1024 /**
1025  * Creates a new gadget
1026  *
1027  * @param gc gadcon pointer
1028  * @param name to use for gadget
1029  * @param id assigned to gadget
1030  * @param style to  for gadget
1031  * @param base_obj the evas object that will show up in the shelf or gadget module
1032  * @return returns pointer to created gadget, on failure returns null
1033  */
1034 EAPI E_Gadcon_Client *
1035 e_gadcon_client_new(E_Gadcon *gc, const char *name, const char *id __UNUSED__, const char *style, Evas_Object *base_obj)
1036 {
1037    E_Gadcon_Client *gcc;
1038
1039    E_OBJECT_CHECK_RETURN(gc, NULL);
1040    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
1041    gcc = E_OBJECT_ALLOC(E_Gadcon_Client, E_GADCON_CLIENT_TYPE,
1042                         _e_gadcon_client_free);
1043    if (!gcc) return NULL;
1044    e_object_delfn_add(E_OBJECT(gcc), _e_gadcon_client_delfn, NULL);
1045    gcc->name = eina_stringshare_add(name);
1046    gcc->gadcon = gc;
1047    gcc->o_base = base_obj;
1048    if (gc->clients)
1049      gcc->id = E_GADCON_CLIENT(eina_list_last_data_get(gc->clients))->id + 1;
1050    gc->clients = eina_list_append(gc->clients, gcc);
1051    /* This must only be unique during runtime */
1052    if (gcc->o_base)
1053      evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_DEL,
1054                                     _e_gadcon_client_del_hook, gcc);
1055    if ((gc->frame_request.func) && (style))
1056      {
1057         gcc->o_frame = gc->frame_request.func(gc->frame_request.data, gcc, style);
1058         gcc->style = eina_stringshare_add(style);
1059         if (gcc->o_frame)
1060           {
1061              edje_object_size_min_calc(gcc->o_frame, &(gcc->pad.w), &(gcc->pad.h));
1062              gcc->o_box = e_box_add(gcc->gadcon->evas);
1063              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_DEL, _e_gadcon_client_box_del, gcc);
1064              switch (gcc->gadcon->orient)
1065                {
1066                 case E_GADCON_ORIENT_FLOAT:
1067                 case E_GADCON_ORIENT_HORIZ:
1068                 case E_GADCON_ORIENT_TOP:
1069                 case E_GADCON_ORIENT_BOTTOM:
1070                 case E_GADCON_ORIENT_CORNER_TL:
1071                 case E_GADCON_ORIENT_CORNER_TR:
1072                 case E_GADCON_ORIENT_CORNER_BL:
1073                 case E_GADCON_ORIENT_CORNER_BR:
1074                   e_box_orientation_set(gcc->o_box, 1);
1075                   break;
1076
1077                 case E_GADCON_ORIENT_VERT:
1078                 case E_GADCON_ORIENT_LEFT:
1079                 case E_GADCON_ORIENT_RIGHT:
1080                 case E_GADCON_ORIENT_CORNER_LT:
1081                 case E_GADCON_ORIENT_CORNER_RT:
1082                 case E_GADCON_ORIENT_CORNER_LB:
1083                 case E_GADCON_ORIENT_CORNER_RB:
1084                   e_box_orientation_set(gcc->o_box, 0);
1085                   break;
1086
1087                 default:
1088                   break;
1089                }
1090              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_MOVE,
1091                                             _e_gadcon_cb_client_frame_moveresize, gcc);
1092              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_RESIZE,
1093                                             _e_gadcon_cb_client_frame_moveresize, gcc);
1094              evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1095                                             _e_gadcon_cb_client_frame_mouse_move, gcc);
1096              if (gcc->o_base)
1097                {
1098                   e_box_pack_end(gcc->o_box, gcc->o_base);
1099                   e_box_pack_options_set(gcc->o_base,
1100                                          1, 1, /* fill */
1101                                          1, 1, /* expand */
1102                                          0.5, 0.5, /* align */
1103                                          0, 0, /* min */
1104                                          -1, -1 /* max */
1105                                          );
1106                }
1107              edje_object_part_swallow(gcc->o_frame, gc->edje.swallow_name, gcc->o_box);
1108              evas_object_show(gcc->o_box);
1109              evas_object_show(gcc->o_frame);
1110           }
1111      }
1112    if (gcc->o_frame)
1113      {
1114         e_gadcon_layout_pack(gc->o_container, gcc->o_frame);
1115         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_DEL, _e_gadcon_client_frame_del, gcc);
1116      }
1117    else if (gcc->o_base)
1118      e_gadcon_layout_pack(gc->o_container, gcc->o_base);
1119    if (gcc->o_base) evas_object_show(gcc->o_base);
1120    {
1121       E_Event_Gadcon_Client_Add *ev;
1122
1123       ev = E_NEW(E_Event_Gadcon_Client_Add, 1);
1124       ev->gcc = gcc;
1125       e_object_ref(E_OBJECT(gcc));
1126       ecore_event_add(E_EVENT_GADCON_CLIENT_ADD, ev, _e_gadcon_client_event_free, NULL);
1127    }
1128    return gcc;
1129 }
1130
1131 EAPI void
1132 e_gadcon_client_edit_begin(E_Gadcon_Client *gcc)
1133 {
1134    Evas_Coord x, y, w, h;
1135    Evas_Object *base;
1136    int layer;
1137
1138    E_OBJECT_CHECK(gcc);
1139    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1140    if (gcc->o_control) return;
1141
1142    base = gcc->o_frame ?: gcc->o_base;
1143    if (!base) return;
1144    layer = evas_object_layer_get(base) + 1;
1145    evas_object_geometry_get(base, &x, &y, &w, &h);
1146
1147    gcc->o_control = edje_object_add(gcc->gadcon->evas);
1148    /* FIXME: should probably be in gadget theme or something */
1149    evas_object_layer_set(gcc->o_control, layer);
1150    e_gadcon_locked_set(gcc->gadcon, 1);
1151    gcc->gadcon->editing = 1;
1152
1153    evas_object_move(gcc->o_control, x, y);
1154    evas_object_resize(gcc->o_control, w, h);
1155    e_theme_edje_object_set(gcc->o_control, "base/theme/gadman",
1156                            "e/gadman/control");
1157
1158    if ((gcc->autoscroll) /* || (gcc->resizable)*/)
1159      {
1160         if (e_box_orientation_get(gcc->o_box))
1161           edje_object_signal_emit(gcc->o_control, "e,state,hsize,on", "e");
1162         else
1163           edje_object_signal_emit(gcc->o_control, "e,state,vsize,on", "e");
1164      }
1165    else
1166      {
1167         edje_object_signal_emit(gcc->o_control, "e,state,hsize,off", "e");
1168         edje_object_signal_emit(gcc->o_control, "e,state,vsize,off", "e");
1169      }
1170    edje_object_signal_emit(gcc->o_control, "e,state,move,on", "e");
1171
1172    gcc->o_event = evas_object_rectangle_add(gcc->gadcon->evas);
1173    evas_object_color_set(gcc->o_event, 0, 0, 0, 0);
1174    evas_object_repeat_events_set(gcc->o_event, 1);
1175    evas_object_layer_set(gcc->o_event, layer);
1176    evas_object_move(gcc->o_event, x, y);
1177    evas_object_resize(gcc->o_event, w, h);
1178
1179    edje_object_signal_callback_add(gcc->o_control, "e,action,move,start", "",
1180                                    _e_gadcon_cb_signal_move_start, gcc);
1181    edje_object_signal_callback_add(gcc->o_control, "e,action,move,stop", "",
1182                                    _e_gadcon_cb_signal_move_stop, gcc);
1183    edje_object_signal_callback_add(gcc->o_control, "e,action,move,go", "",
1184                                    _e_gadcon_cb_signal_move_go, gcc);
1185    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,start", "",
1186                                    _e_gadcon_cb_signal_resize_left_start, gcc);
1187    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,stop", "",
1188                                    _e_gadcon_cb_signal_resize_left_stop, gcc);
1189    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,go", "",
1190                                    _e_gadcon_cb_signal_resize_left_go, gcc);
1191    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,start", "",
1192                                    _e_gadcon_cb_signal_resize_right_start, gcc);
1193    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,stop", "",
1194                                    _e_gadcon_cb_signal_resize_right_stop, gcc);
1195    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,go", "",
1196                                    _e_gadcon_cb_signal_resize_right_go, gcc);
1197    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,start", "",
1198                                    _e_gadcon_cb_signal_resize_left_start, gcc);
1199    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,stop", "",
1200                                    _e_gadcon_cb_signal_resize_left_stop, gcc);
1201    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,go", "",
1202                                    _e_gadcon_cb_signal_resize_left_go, gcc);
1203    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,start", "",
1204                                    _e_gadcon_cb_signal_resize_right_start, gcc);
1205    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,stop", "",
1206                                    _e_gadcon_cb_signal_resize_right_stop, gcc);
1207    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,go", "",
1208                                    _e_gadcon_cb_signal_resize_right_go, gcc);
1209
1210    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_DOWN,
1211                                   _e_gadcon_cb_client_mouse_down, gcc);
1212    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_IN,
1213                                   _e_gadcon_cb_client_mouse_in, gcc);
1214    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_OUT,
1215                                   _e_gadcon_cb_client_mouse_out, gcc);
1216
1217    evas_object_event_callback_add(base, EVAS_CALLBACK_MOVE,
1218                                   _e_gadcon_cb_client_move, gcc);
1219    evas_object_event_callback_add(base, EVAS_CALLBACK_RESIZE,
1220                                   _e_gadcon_cb_client_resize, gcc);
1221
1222    evas_object_show(gcc->o_event);
1223    evas_object_show(gcc->o_control);
1224 }
1225
1226 EAPI void
1227 e_gadcon_client_edit_end(E_Gadcon_Client *gcc)
1228 {
1229    Eina_List *l = NULL;
1230    E_Gadcon_Client *client = NULL;
1231
1232    E_OBJECT_CHECK(gcc);
1233    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1234
1235    if (gcc->o_frame)
1236      {
1237         evas_object_event_callback_del(gcc->o_frame, EVAS_CALLBACK_MOVE,
1238                                        _e_gadcon_cb_client_move);
1239         evas_object_event_callback_del(gcc->o_frame, EVAS_CALLBACK_RESIZE,
1240                                        _e_gadcon_cb_client_resize);
1241      }
1242    else if (gcc->o_base)
1243      {
1244         evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_MOVE,
1245                                        _e_gadcon_cb_client_move);
1246         evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_RESIZE,
1247                                        _e_gadcon_cb_client_resize);
1248      }
1249
1250    if (gcc->moving)
1251      {
1252         gcc->moving = 0;
1253         if (gcc->cf) _e_gadcon_client_save(gcc);
1254      }
1255    if (gcc->o_event) evas_object_del(gcc->o_event);
1256    gcc->o_event = NULL;
1257    if (gcc->o_control) evas_object_del(gcc->o_control);
1258    gcc->o_control = NULL;
1259
1260    e_gadcon_locked_set(gcc->gadcon, 0);
1261    EINA_LIST_FOREACH(gcc->gadcon->clients, l, client)
1262      {
1263         if (!client) continue;
1264         if (client->o_control) return;
1265      }
1266    gcc->gadcon->editing = 0;
1267 }
1268
1269 EAPI void
1270 e_gadcon_client_show(E_Gadcon_Client *gcc)
1271 {
1272    E_OBJECT_CHECK(gcc);
1273    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1274
1275    if (!gcc->hidden) return;
1276    if (gcc->o_box) evas_object_show(gcc->o_box);
1277    if (gcc->o_frame) evas_object_show(gcc->o_frame);
1278    if (gcc->o_base) evas_object_show(gcc->o_base);
1279    if (gcc->o_control) evas_object_show(gcc->o_control);
1280    if (gcc->o_event) evas_object_show(gcc->o_event);
1281    if (gcc->o_frame)
1282      {
1283         e_gadcon_layout_pack(gcc->gadcon->o_container, gcc->o_frame);
1284         e_gadcon_layout_pack_options_set(gcc->o_frame, gcc);
1285      }
1286    else if (gcc->o_base)
1287      {
1288         e_gadcon_layout_pack(gcc->gadcon->o_container, gcc->o_base);
1289         e_gadcon_layout_pack_options_set(gcc->o_base, gcc);
1290      }
1291    gcc->hidden = 0;
1292 }
1293
1294 EAPI void
1295 e_gadcon_client_hide(E_Gadcon_Client *gcc)
1296 {
1297    E_OBJECT_CHECK(gcc);
1298    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1299
1300    if (gcc->hidden) return;
1301    if (gcc->o_box) evas_object_hide(gcc->o_box);
1302    if (gcc->o_frame) evas_object_hide(gcc->o_frame);
1303    if (gcc->o_base) evas_object_hide(gcc->o_base);
1304    if (gcc->o_control) evas_object_hide(gcc->o_control);
1305    if (gcc->o_event) evas_object_hide(gcc->o_event);
1306    if (gcc->o_frame)
1307      e_gadcon_layout_unpack(gcc->o_frame);
1308    else if (gcc->o_base)
1309      e_gadcon_layout_unpack(gcc->o_base);
1310    gcc->hidden = 1;
1311 }
1312
1313 EAPI void
1314 e_gadcon_client_size_request(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h)
1315 {
1316    E_OBJECT_CHECK(gcc);
1317    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1318    switch (gcc->gadcon->orient)
1319      {
1320       case E_GADCON_ORIENT_HORIZ:
1321       case E_GADCON_ORIENT_TOP:
1322       case E_GADCON_ORIENT_BOTTOM:
1323         if (gcc->o_frame)
1324           e_gadcon_layout_pack_size_set(gcc->o_frame, w + gcc->pad.w);
1325         else if (gcc->o_base)
1326           e_gadcon_layout_pack_size_set(gcc->o_base, w);
1327         break;
1328
1329       case E_GADCON_ORIENT_VERT:
1330       case E_GADCON_ORIENT_LEFT:
1331       case E_GADCON_ORIENT_RIGHT:
1332         if (gcc->o_frame)
1333           e_gadcon_layout_pack_size_set(gcc->o_frame, h + gcc->pad.h);
1334         else if (gcc->o_base)
1335           e_gadcon_layout_pack_size_set(gcc->o_base, h);
1336         break;
1337
1338       case E_GADCON_ORIENT_FLOAT:
1339       case E_GADCON_ORIENT_CORNER_TL:
1340       case E_GADCON_ORIENT_CORNER_TR:
1341       case E_GADCON_ORIENT_CORNER_BL:
1342       case E_GADCON_ORIENT_CORNER_BR:
1343       case E_GADCON_ORIENT_CORNER_LT:
1344       case E_GADCON_ORIENT_CORNER_RT:
1345       case E_GADCON_ORIENT_CORNER_LB:
1346       case E_GADCON_ORIENT_CORNER_RB:
1347       default:
1348         break;
1349      }
1350 }
1351
1352 EAPI void
1353 e_gadcon_client_min_size_set(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h)
1354 {
1355    E_OBJECT_CHECK(gcc);
1356    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1357    gcc->min.w = w;
1358    gcc->min.h = h;
1359 /*   if (!gcc->resizable)*/
1360    {
1361       if (gcc->o_frame)
1362         e_gadcon_layout_pack_min_size_set(gcc->o_frame, w + gcc->pad.w,
1363                                           h + gcc->pad.h);
1364       else if (gcc->o_base)
1365         e_gadcon_layout_pack_min_size_set(gcc->o_base, w, h);
1366    }
1367    _e_gadcon_moveresize_handle(gcc);
1368 }
1369
1370 EAPI void
1371 e_gadcon_client_aspect_set(E_Gadcon_Client *gcc, int w, int h)
1372 {
1373    E_OBJECT_CHECK(gcc);
1374    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1375    gcc->aspect.w = w;
1376    gcc->aspect.h = h;
1377 //   if ((!gcc->autoscroll)/* && (!gcc->resizable)*/)
1378    {
1379       if (gcc->o_frame)
1380         {
1381            e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1382                                                gcc->pad.h);
1383            e_gadcon_layout_pack_aspect_set(gcc->o_frame, w, h);
1384         }
1385       else if (gcc->o_base)
1386         e_gadcon_layout_pack_aspect_set(gcc->o_base, w, h);
1387    }
1388    _e_gadcon_moveresize_handle(gcc);
1389 }
1390
1391 EAPI void
1392 e_gadcon_client_autoscroll_toggle_disabled_set(E_Gadcon_Client *gcc, Eina_Bool disable)
1393 {
1394    disable = !!disable;
1395    if (gcc->autoscroll_disabled == disable) return;
1396    gcc->autoscroll_disabled = disable;
1397    if (disable) e_gadcon_client_autoscroll_set(gcc, 1);
1398 }
1399
1400 EAPI void
1401 e_gadcon_client_autoscroll_set(E_Gadcon_Client *gcc, int autoscroll)
1402 {
1403    E_OBJECT_CHECK(gcc);
1404    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1405
1406    if (gcc->autoscroll_disabled && (!autoscroll))
1407      {
1408         e_util_dialog_show(_("Gadget error"), _("%s does not support disabling autoscrolling"), gcc->name);
1409         return;
1410      }
1411    gcc->autoscroll = autoscroll;
1412    gcc->autoscroll_set = 1;
1413 /*
1414    if (gcc->autoscroll)
1415      {
1416         if (gcc->o_frame)
1417           {
1418              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1419                                                  gcc->pad.h);
1420              e_gadcon_layout_pack_aspect_set(gcc->o_frame, 0, 0);
1421              e_gadcon_layout_pack_min_size_set(gcc->o_frame, 0, 0);
1422           }
1423         else if (gcc->o_base)
1424           {
1425              e_gadcon_layout_pack_aspect_set(gcc->o_base, 0, 0);
1426              e_gadcon_layout_pack_min_size_set(gcc->o_base, 0, 0);
1427           }
1428      }
1429    else
1430  */
1431    {
1432       if (gcc->o_frame)
1433         {
1434            e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1435                                                gcc->pad.h);
1436            e_gadcon_layout_pack_aspect_set(gcc->o_frame, gcc->aspect.w,
1437                                            gcc->aspect.h);
1438            e_gadcon_layout_pack_min_size_set(gcc->o_frame, gcc->min.w,
1439                                              gcc->min.h);
1440         }
1441       else if (gcc->o_base)
1442         {
1443            e_gadcon_layout_pack_min_size_set(gcc->o_base, gcc->min.w,
1444                                              gcc->min.h);
1445            e_gadcon_layout_pack_aspect_set(gcc->o_base, gcc->aspect.w,
1446                                            gcc->aspect.h);
1447         }
1448    }
1449 }
1450
1451 EAPI void
1452 e_gadcon_client_resizable_set(E_Gadcon_Client *gcc __UNUSED__, int resizable __UNUSED__)
1453 {
1454    E_OBJECT_CHECK(gcc);
1455    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1456 /*
1457    gcc->resizable = resizable;
1458    if (gcc->resizable)
1459      {
1460         if (gcc->o_frame)
1461           {
1462              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1463                                                  gcc->pad.h);
1464              e_gadcon_layout_pack_aspect_set(gcc->o_frame, 0, 0);
1465              e_gadcon_layout_pack_min_size_set(gcc->o_frame, 0, 0);
1466           }
1467         else if (gcc->o_base)
1468           {
1469              e_gadcon_layout_pack_min_size_set(gcc->o_base, 0, 0);
1470              e_gadcon_layout_pack_aspect_set(gcc->o_base, 0, 0);
1471           }
1472      }
1473    else
1474      {
1475         if (gcc->o_frame)
1476           {
1477              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1478                                                  gcc->pad.h);
1479              e_gadcon_layout_pack_aspect_set(gcc->o_frame, gcc->aspect.w,
1480                                              gcc->aspect.h);
1481              e_gadcon_layout_pack_min_size_set(gcc->o_frame, gcc->min.w,
1482                                                gcc->min.h);
1483           }
1484         else if (gcc->o_base)
1485           {
1486              e_gadcon_layout_pack_min_size_set(gcc->o_base, gcc->min.w,
1487                                                gcc->min.h);
1488              e_gadcon_layout_pack_aspect_set(gcc->o_base, gcc->aspect.w,
1489                                              gcc->aspect.h);
1490           }
1491      }
1492  */
1493 }
1494
1495 EAPI int
1496 e_gadcon_client_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h)
1497 {
1498    int gx = 0, gy = 0;
1499
1500    E_OBJECT_CHECK(gcc);
1501    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1502    if (!e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &gx, &gy, NULL, NULL))
1503      return 0;
1504    if (gcc->o_base) evas_object_geometry_get(gcc->o_base, x, y, w, h);
1505    if (x) *x += gx;
1506    if (y) *y += gy;
1507    return 1;
1508 }
1509
1510 EAPI int
1511 e_gadcon_client_viewport_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h)
1512 {
1513    E_OBJECT_CHECK(gcc);
1514    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1515
1516    if (gcc->o_box) evas_object_geometry_get(gcc->o_base, x, y, w, h);
1517    else if (gcc->o_base)
1518      evas_object_geometry_get(gcc->o_base, x, y, w, h);
1519    else
1520      {
1521         if (x) *x = 0;
1522         if (y) *y = 0;
1523         if (w) *w = 0;
1524         if (h) *h = 0;
1525      }
1526    return 1;
1527 }
1528
1529 EAPI E_Zone *
1530 e_gadcon_client_zone_get(E_Gadcon_Client *gcc)
1531 {
1532    E_OBJECT_CHECK_RETURN(gcc, NULL);
1533    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, NULL);
1534    return e_gadcon_zone_get(gcc->gadcon);
1535 }
1536
1537 static Eina_Bool
1538 _e_gadcon_client_populate(E_Gadcon *gc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf_gcc)
1539 {
1540    E_Gadcon_Client *gcc;
1541
1542    if (!eina_list_data_find(gc->populated_classes, cc))
1543      {
1544         _e_gadcon_provider_populate_request(gc, cc);
1545         return EINA_TRUE;
1546      }
1547
1548    if ((!cf_gcc->id) &&
1549        (_e_gadcon_client_class_feature_check(cc, "id_new", cc->func.id_new)))
1550      cf_gcc->id = eina_stringshare_add(cc->func.id_new(cc));
1551
1552    if (!cf_gcc->style)
1553      gcc = cc->func.init(gc, cf_gcc->name, cf_gcc->id,
1554                          cc->default_style);
1555    else
1556      gcc = cc->func.init(gc, cf_gcc->name, cf_gcc->id,
1557                          cf_gcc->style);
1558
1559    if (!gcc) return EINA_FALSE;
1560    gcc->cf = cf_gcc;
1561    gcc->client_class = cc;
1562    gcc->config.pos = cf_gcc->geom.pos;
1563    gcc->config.size = cf_gcc->geom.size;
1564    gcc->config.res = cf_gcc->geom.res;
1565    gcc->state_info.seq = cf_gcc->state_info.seq;
1566    gcc->state_info.flags = cf_gcc->state_info.flags;
1567    gcc->config.pos_x = gcc->cf->geom.pos_x;
1568    gcc->config.pos_y = gcc->cf->geom.pos_y;
1569    gcc->config.size_w = gcc->cf->geom.size_w;
1570    gcc->config.size_h = gcc->cf->geom.size_h;
1571    gcc->cf->resizable = 0;
1572
1573    eina_stringshare_replace(&gcc->style, cf_gcc->style);
1574    if (gcc->o_frame)
1575      e_gadcon_layout_pack_options_set(gcc->o_frame, gcc);
1576    else if (gcc->o_base)
1577      e_gadcon_layout_pack_options_set(gcc->o_base, gcc);
1578
1579    if (!gcc->autoscroll_set)
1580      e_gadcon_client_autoscroll_set(gcc, cf_gcc->autoscroll);
1581    //             e_gadcon_client_resizable_set(gcc, cf_gcc->resizable);
1582    if (gcc->client_class->func.orient)
1583      gcc->client_class->func.orient(gcc, gc->orient);
1584
1585    e_config_save_queue();
1586    if (gc->editing) e_gadcon_client_edit_begin(gcc);
1587    if (gc->instant_edit)
1588      e_gadcon_client_util_menu_attach(gcc);
1589    return EINA_TRUE;
1590 }
1591
1592 static void
1593 _e_gadcon_client_unpopulate(E_Gadcon_Client *gcc)
1594 {
1595    if (gcc->menu)
1596      {
1597         if (gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
1598         e_menu_post_deactivate_callback_set(gcc->menu, NULL, NULL);
1599         e_menu_deactivate(gcc->menu);
1600         e_object_del(E_OBJECT(gcc->menu));
1601         gcc->menu = NULL;
1602      }
1603    e_object_del(E_OBJECT(gcc));
1604 }
1605
1606 static void
1607 _e_gadcon_client_change_gadcon(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi)
1608 {
1609    E_Gadcon_Location *src, *dst;
1610    E_Gadcon_Client *gcc;
1611
1612    gcc = data;
1613    src = gcc->gadcon->location;
1614    dst = e_object_data_get(E_OBJECT(mi));
1615    _e_gadcon_location_change(gcc, src, dst);
1616 }
1617
1618 static void
1619 _e_gadcon_add_locations_menu_for_site(E_Menu *m, E_Gadcon_Client *gcc, E_Gadcon_Site site, int *count)
1620 {
1621    E_Menu_Item *mi;
1622    const Eina_List *l;
1623    E_Gadcon_Location *loc;
1624    int k = *count;
1625
1626    EINA_LIST_FOREACH(gadcon_locations, l, loc)
1627      {
1628         if (loc->site == site)
1629           {
1630              if (loc == gcc->gadcon->location) continue;
1631              if (k)
1632                {
1633                   k = 0;
1634                   mi = e_menu_item_new(m);
1635                   e_menu_item_separator_set(mi, 1);
1636                   (*count) = 0;
1637                }
1638              mi = e_menu_item_new(m);
1639              e_menu_item_label_set(mi, loc->name);
1640              e_object_data_set(E_OBJECT(mi), loc);
1641              e_menu_item_callback_set(mi, _e_gadcon_client_change_gadcon, gcc);
1642              if (loc->icon_name)
1643                e_util_menu_item_theme_icon_set(mi, loc->icon_name);
1644              (*count)++;
1645           }
1646      }
1647 }
1648
1649 static void
1650 _e_gadcon_gadget_move_to_pre_cb(void *data, E_Menu *m)
1651 {
1652    E_Gadcon_Client *gcc;
1653    int n = 0;
1654
1655    gcc = data;
1656    e_menu_pre_activate_callback_set(m, NULL, NULL);
1657
1658    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_SHELF))
1659      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_SHELF, &n);
1660    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_DESKTOP))
1661      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_DESKTOP, &n);
1662    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_TOOLBAR))
1663      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_TOOLBAR, &n);
1664    //if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_EFM_TOOLBAR))
1665      //_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_EFM_TOOLBAR, &n);
1666    _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_UNKNOWN, &n);
1667 }
1668
1669 EAPI void
1670 e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu)
1671 {
1672    E_Menu *mn;
1673    E_Menu_Item *mi;
1674
1675    E_OBJECT_CHECK(gcc);
1676    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1677
1678    if (gcc->gadcon->location)
1679      {
1680         mn = e_menu_new();
1681         mi = e_menu_item_new(menu);
1682         e_menu_item_label_set(mi, _("Move to"));
1683         e_util_menu_item_theme_icon_set(mi, "preferences-look");
1684         e_menu_item_submenu_set(mi, mn);
1685         e_menu_pre_activate_callback_set(mn, _e_gadcon_gadget_move_to_pre_cb, gcc);
1686         e_object_unref(E_OBJECT(mn));
1687      }
1688 }
1689
1690 EAPI E_Menu *
1691 e_gadcon_client_menu_set(E_Gadcon_Client *gcc, E_Menu *m)
1692 {
1693    E_Menu *ret;
1694
1695    E_OBJECT_CHECK_RETURN(gcc, NULL);
1696    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, NULL);
1697
1698    ret = gcc->menu;
1699    if (ret)
1700      e_menu_post_deactivate_callback_set(ret, NULL, NULL);
1701    gcc->menu = m;
1702    if (gcc->gadcon->shelf) gcc->gadcon->shelf->menu = m;
1703    if (m)
1704      e_menu_post_deactivate_callback_set(m, _e_gadcon_client_cb_menu_post, gcc);
1705    return ret;
1706 }
1707
1708 EAPI E_Menu *
1709 e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu_gadget, int flags __UNUSED__)
1710 {
1711    E_Menu *mo, *menu_main = NULL;
1712    E_Menu_Item *mi;
1713    char buf[256];
1714
1715    E_OBJECT_CHECK(gcc);
1716    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1717
1718    if (e_config->menu_gadcon_client_toplevel)
1719      menu_main = menu_gadget;
1720    else
1721      menu_main = e_menu_new();
1722    e_menu_post_deactivate_callback_set(menu_main, _e_gadcon_client_cb_menu_post, gcc);
1723    gcc->menu = menu_main;
1724
1725    if (gcc->gadcon->shelf)
1726      {
1727         if (e_menu_item_nth(menu_gadget, 0))
1728           {
1729              mi = e_menu_item_new(menu_gadget);
1730              e_menu_item_separator_set(mi, 1);
1731           }
1732 /*
1733         if (!gcc->o_control)
1734           {
1735              mi = e_menu_item_new(menu_gadget);
1736              e_menu_item_label_set(mi, _("Move"));
1737              e_util_menu_item_theme_icon_set(mi, "transform-scale");
1738              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
1739           }
1740         mi = e_menu_item_new(menu_gadget);
1741         e_menu_item_label_set(mi, _("Resizeable"));
1742         e_util_menu_item_theme_icon_set(mi, "transform-scale");
1743         e_menu_item_check_set(mi, 1);
1744         if (gcc->resizable) e_menu_item_toggle_set(mi, 1);
1745         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_resizable, gcc);
1746  */
1747         if (!gcc->autoscroll_disabled)
1748           {
1749              mi = e_menu_item_new(menu_gadget);
1750              e_menu_item_label_set(mi, _("Automatically scroll contents"));
1751              e_util_menu_item_theme_icon_set(mi, "transform-move");
1752              e_menu_item_check_set(mi, 1);
1753              if (gcc->autoscroll) e_menu_item_toggle_set(mi, 1);
1754              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_autoscroll, gcc);
1755           }
1756
1757         if (gcc->gadcon->shelf)
1758           {
1759              mo = e_menu_new();
1760              gcc->gadcon->shelf->menu = menu_main;
1761
1762              mi = e_menu_item_new(mo);
1763              e_menu_item_label_set(mi, _("Plain"));
1764              e_util_menu_item_theme_icon_set(mi, "enlightenment/plain");
1765              e_menu_item_radio_group_set(mi, 1);
1766              e_menu_item_radio_set(mi, 1);
1767              if (!e_util_strcmp(gcc->style, E_GADCON_CLIENT_STYLE_PLAIN))
1768                e_menu_item_toggle_set(mi, 1);
1769              else if ((!gcc->style) &&
1770                       (!e_util_strcmp(gcc->client_class->default_style, E_GADCON_CLIENT_STYLE_PLAIN)))
1771                e_menu_item_toggle_set(mi, 1);
1772              e_menu_item_disabled_set(mi, mi->toggle);
1773              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_style_plain, gcc);
1774
1775              mi = e_menu_item_new(mo);
1776              e_menu_item_label_set(mi, _("Inset"));
1777              e_util_menu_item_theme_icon_set(mi, "enlightenment/inset");
1778              e_menu_item_radio_group_set(mi, 1);
1779              e_menu_item_radio_set(mi, 1);
1780              if (!e_util_strcmp(gcc->style, E_GADCON_CLIENT_STYLE_INSET))
1781                e_menu_item_toggle_set(mi, 1);
1782              else if ((!gcc->style) &&
1783                       (!e_util_strcmp(gcc->client_class->default_style, E_GADCON_CLIENT_STYLE_INSET)))
1784                e_menu_item_toggle_set(mi, 1);
1785              e_menu_item_disabled_set(mi, mi->toggle);
1786              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_style_inset, gcc);
1787
1788              mi = e_menu_item_new(menu_gadget);
1789              e_menu_item_label_set(mi, _("Look"));
1790              e_util_menu_item_theme_icon_set(mi, "preferences-look");
1791              e_menu_item_submenu_set(mi, mo);
1792              e_object_unref(E_OBJECT(mo));
1793           }
1794
1795         mi = e_menu_item_new(menu_gadget);
1796         e_menu_item_separator_set(mi, 1);
1797
1798         e_gadcon_client_add_location_menu(gcc, menu_gadget);
1799
1800         mi = e_menu_item_new(menu_gadget);
1801         e_menu_item_label_set(mi, _("Remove"));
1802         e_util_menu_item_theme_icon_set(mi, "list-remove");
1803         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_remove, gcc);
1804      }
1805
1806    if ((!e_config->menu_gadcon_client_toplevel) && (!gcc->gadcon->toolbar))
1807      {
1808         mi = e_menu_item_new(menu_main);
1809         if (gcc->client_class->func.label)
1810           snprintf(buf, sizeof(buf), "%s",
1811                    gcc->client_class->func.label((E_Gadcon_Client_Class *)gcc->client_class));
1812         else
1813           snprintf(buf, sizeof(buf), "%s", gcc->name);
1814
1815         e_menu_item_label_set(mi, _(buf));
1816         e_menu_item_realize_callback_set(mi, _e_gadcon_client_cb_menu_pre, gcc);
1817         e_menu_item_submenu_set(mi, menu_gadget);
1818         e_object_unref(E_OBJECT(menu_gadget));
1819      }
1820
1821    if (gcc->gadcon->menu_attach.func)
1822      {
1823         if ((gcc->gadcon->shelf) || (gcc->gadcon->toolbar))
1824           {
1825              if (e_config->menu_gadcon_client_toplevel)
1826                {
1827                   mi = e_menu_item_new(menu_main);
1828                   e_menu_item_separator_set(mi, 1);
1829                }
1830              gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data, gcc, menu_main);
1831           }
1832         else
1833           gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data, gcc, menu_gadget);
1834      }
1835
1836    return menu_main;
1837 }
1838
1839 EAPI void
1840 e_gadcon_client_util_menu_attach(E_Gadcon_Client *gcc)
1841 {
1842    E_OBJECT_CHECK(gcc);
1843    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1844    if (gcc->o_frame)
1845      {
1846         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_DOWN,
1847                                             _e_gadcon_client_cb_mouse_down, gcc);
1848         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_UP,
1849                                             _e_gadcon_client_cb_mouse_up, gcc);
1850         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1851                                             _e_gadcon_client_cb_mouse_move, gcc);
1852         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_DOWN,
1853                                        _e_gadcon_client_cb_mouse_down, gcc);
1854         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_UP,
1855                                        _e_gadcon_client_cb_mouse_up, gcc);
1856         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1857                                        _e_gadcon_client_cb_mouse_move, gcc);
1858      }
1859    else if (gcc->o_base)
1860      {
1861         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_DOWN,
1862                                             _e_gadcon_client_cb_mouse_down, gcc);
1863         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_UP,
1864                                             _e_gadcon_client_cb_mouse_up, gcc);
1865         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_MOVE,
1866                                             _e_gadcon_client_cb_mouse_move, gcc);
1867         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_DOWN,
1868                                        _e_gadcon_client_cb_mouse_down, gcc);
1869         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_UP,
1870                                        _e_gadcon_client_cb_mouse_up, gcc);
1871         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_MOVE,
1872                                        _e_gadcon_client_cb_mouse_move, gcc);
1873      }
1874 }
1875
1876 EAPI void
1877 e_gadcon_locked_set(E_Gadcon *gc, int lock)
1878 {
1879    E_OBJECT_CHECK(gc);
1880    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
1881    if (gc->locked_set.func)
1882      gc->locked_set.func(gc->locked_set.data, lock);
1883 }
1884
1885 EAPI void
1886 e_gadcon_urgent_show(E_Gadcon *gc)
1887 {
1888    E_OBJECT_CHECK(gc);
1889    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
1890    if (gc->urgent_show.func)
1891      gc->urgent_show.func(gc->urgent_show.data);
1892 }
1893
1894 /*
1895  * NOTE: x & y are relative to the o_box of the gadcon.
1896  */
1897 EAPI void
1898 e_gadcon_client_autoscroll_update(E_Gadcon_Client *gcc, Evas_Coord x, Evas_Coord y)
1899 {
1900    E_OBJECT_CHECK(gcc);
1901    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1902
1903    if (gcc->autoscroll)
1904      {
1905         Evas_Coord w, h;
1906         double d;
1907
1908         /* TODO: When using gadman there is no o_box! */
1909         evas_object_geometry_get(gcc->o_box, NULL, NULL, &w, &h);
1910         if (e_box_orientation_get(gcc->o_box))
1911           {
1912              if (w > 1) d = (double)x / (double)(w - 1);
1913              else d = 0;
1914           }
1915         else
1916           {
1917              if (h > 1) d = (double)y / (double)(h - 1);
1918              else d = 0;
1919           }
1920         if (d < 0.0) d = 0.0;
1921         else if (d > 1.0)
1922           d = 1.0;
1923         if (!gcc->scroll_timer)
1924           gcc->scroll_timer =
1925             ecore_timer_add(0.01, _e_gadcon_cb_client_scroll_timer, gcc);
1926         if (!gcc->scroll_animator)
1927           gcc->scroll_animator =
1928             ecore_animator_add(_e_gadcon_cb_client_scroll_animator, gcc);
1929         gcc->scroll_wanted = d;
1930      }
1931 }
1932
1933 EAPI void
1934 e_gadcon_client_autoscroll_cb_set(E_Gadcon_Client *gcc, void (*func)(void *data), void *data)
1935 {
1936    E_OBJECT_CHECK(gcc);
1937    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1938    gcc->scroll_cb.func = func;
1939    gcc->scroll_cb.data = data;
1940 }
1941
1942 EAPI Eina_Bool
1943 e_gadcon_site_is_shelf(E_Gadcon_Site site)
1944 {
1945    return site == E_GADCON_SITE_SHELF;
1946 }
1947
1948 EAPI Eina_Bool
1949 e_gadcon_site_is_desktop(E_Gadcon_Site site)
1950 {
1951    return site == E_GADCON_SITE_DESKTOP;
1952 }
1953
1954 EAPI Eina_Bool
1955 e_gadcon_site_is_efm_toolbar(E_Gadcon_Site site)
1956 {
1957    return site == E_GADCON_SITE_EFM_TOOLBAR;
1958 }
1959
1960 EAPI Eina_Bool
1961 e_gadcon_site_is_any_toolbar(E_Gadcon_Site site)
1962 {
1963    switch (site)
1964      {
1965       // there should be all toolbar sities identifiers
1966       case E_GADCON_SITE_TOOLBAR:
1967       case E_GADCON_SITE_EFM_TOOLBAR:
1968         return EINA_TRUE;
1969
1970       default:
1971         return EINA_FALSE;
1972      }
1973    return EINA_FALSE;
1974 }
1975
1976 EAPI Eina_Bool
1977 e_gadcon_site_is_not_toolbar(E_Gadcon_Site site)
1978 {
1979    switch (site)
1980      {
1981       // there should be all toolbar sities identifiers
1982       case E_GADCON_SITE_TOOLBAR:
1983       case E_GADCON_SITE_EFM_TOOLBAR:
1984         return EINA_FALSE;
1985
1986       default:
1987         return EINA_TRUE;
1988      }
1989    return EINA_TRUE;
1990 }
1991
1992 EAPI void
1993 e_gadcon_client_drag_set(E_Gadcon_Client *gcc)
1994 {
1995    Eina_List *l;
1996    E_Gadcon *gc;
1997
1998    EINA_LIST_FOREACH(gadcons, l, gc)
1999      gc->drag_gcc = gcc;
2000 }
2001
2002 /* local subsystem functions */
2003 static void
2004 _e_gadcon_free(E_Gadcon *gc)
2005 {
2006    if (gc->dummy)
2007      dummies = eina_list_remove(dummies, gc);
2008    else
2009      {
2010         e_gadcon_unpopulate(gc);
2011         gadcons = eina_list_remove(gadcons, gc);
2012      }
2013    eina_list_free(gc->populated_classes);
2014    if (custom_populate_requests)
2015      custom_populate_requests = eina_list_remove(custom_populate_requests, gc);
2016    if (gc->o_container) evas_object_del(gc->o_container);
2017    eina_stringshare_del(gc->name);
2018    eina_stringshare_del(gc->edje.swallow_name);
2019    if (gc->config_dialog) e_object_del(E_OBJECT(gc->config_dialog));
2020    if (gc->drop_handler) e_drop_handler_del(gc->drop_handler);
2021    if (gc->cfg_delete)
2022      {
2023         eina_stringshare_del(gc->cf->name);
2024         e_config->gadcons = eina_list_remove(e_config->gadcons, gc->cf);
2025         free(gc->cf);
2026         e_config_save_queue();
2027      }
2028    free(gc);
2029 }
2030
2031 static void
2032 _e_gadcon_client_event_free(void *d __UNUSED__, void *e)
2033 {
2034    E_Event_Gadcon_Client_Del *ev = e;
2035
2036    e_object_unref(E_OBJECT(ev->gcc));
2037    free(ev);
2038 }
2039
2040 static void
2041 _e_gadcon_event_populate(E_Gadcon *gc)
2042 {
2043    E_Event_Gadcon_Populate *ev;
2044
2045    ev = E_NEW(E_Event_Gadcon_Populate, 1);
2046    e_object_ref(E_OBJECT(gc));
2047    ev->gc = gc;
2048    ecore_event_add(E_EVENT_GADCON_POPULATE, ev, _e_gadcon_event_populate_free, NULL);
2049 }
2050
2051 static void
2052 _e_gadcon_client_delfn(void *d __UNUSED__, void *o)
2053 {
2054    E_Gadcon_Client *gcc = o;
2055    E_Event_Gadcon_Client_Add *ev;
2056
2057    if (gcc->instant_edit_timer)
2058      {
2059         ecore_timer_del(gcc->instant_edit_timer);
2060         gcc->instant_edit_timer = NULL;
2061      }
2062    if (gcc->o_base)
2063      evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_DEL,
2064                                     _e_gadcon_client_del_hook);
2065    if (gcc->menu)
2066      {
2067         if (gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
2068         e_menu_post_deactivate_callback_set(gcc->menu, NULL, NULL);
2069         e_menu_deactivate(gcc->menu);
2070         e_object_del(E_OBJECT(gcc->menu));
2071         gcc->menu = NULL;
2072      }
2073    e_gadcon_client_edit_end(gcc);
2074    gcc->client_class->func.shutdown(gcc);
2075    if ((gcc->client_class->func.id_del) && (gcc->cf))
2076      gcc->client_class->func.id_del((E_Gadcon_Client_Class *)gcc->client_class,
2077                                     gcc->cf->id);
2078    if (gcc->drag.drag)
2079      e_object_del(E_OBJECT(gcc->drag.drag));
2080    gcc->gadcon->clients = eina_list_remove(gcc->gadcon->clients, gcc);
2081    E_FREE_FUNC(gcc->scroll_timer, ecore_timer_del);
2082    E_FREE_FUNC(gcc->scroll_animator, ecore_animator_del);
2083    E_FREE_FUNC(gcc->o_box, evas_object_del);
2084    E_FREE_FUNC(gcc->o_frame, evas_object_del);
2085    e_object_ref(E_OBJECT(gcc));
2086    ev = E_NEW(E_Event_Gadcon_Client_Add, 1);
2087    ev->gcc = gcc;
2088    ecore_event_add(E_EVENT_GADCON_CLIENT_DEL, ev, _e_gadcon_client_event_free, NULL);
2089 }
2090
2091 static void
2092 _e_gadcon_client_free(E_Gadcon_Client *gcc)
2093 {
2094    if (gcc->o_box) evas_object_del(gcc->o_box);
2095    if (gcc->o_frame) evas_object_del(gcc->o_frame);
2096    eina_stringshare_del(gcc->name);
2097    eina_stringshare_del(gcc->style);
2098    if (gcc->menu)
2099      {
2100         e_menu_deactivate(gcc->menu);
2101         e_object_del(E_OBJECT(gcc->menu));
2102      }
2103    free(gcc);
2104 }
2105
2106 static void
2107 _e_gadcon_moveresize_handle(E_Gadcon_Client *gcc)
2108 {
2109    int w, h, mw, mh;
2110
2111    if (!gcc->o_base) return;
2112    evas_object_geometry_get(gcc->o_box, NULL, NULL, &w, &h);
2113    if (gcc->gadcon->edje.o_parent)
2114      evas_object_geometry_get(gcc->gadcon->edje.o_parent, NULL, NULL, &mw, &mh);
2115    else
2116      mw = w, mh = h;
2117    w = MIN(w, mw);
2118    h = MIN(h, mh);
2119 /*
2120    if (gcc->resizable)
2121      {
2122         if (e_box_orientation_get(gcc->o_box))
2123           {
2124              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2125                w = (h * gcc->aspect.w) / gcc->aspect.h;
2126           }
2127         else
2128           {
2129              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2130                h = (w * gcc->aspect.h) / gcc->aspect.w;
2131           }
2132      }
2133  */
2134    if (gcc->autoscroll)
2135      {
2136         if (e_box_orientation_get(gcc->o_box))
2137           {
2138              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2139                {
2140                   w = (h * gcc->aspect.w) / gcc->aspect.h; // ZZZZ
2141 //                  w = gcc->min.w;
2142                }
2143              else
2144                {
2145                   w = gcc->min.w;
2146                }
2147           }
2148         else
2149           {
2150              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2151                {
2152                   h = (w * gcc->aspect.h) / gcc->aspect.w; // ZZZZ
2153 //                  h = gcc->min.h;
2154                }
2155              else
2156                {
2157                   h = gcc->min.h;
2158                }
2159           }
2160      }
2161    e_box_pack_options_set(gcc->o_base,
2162                           1, 1, /* fill */
2163                           1, 1, /* expand */
2164                           0.5, 0.5, /* align */
2165                           w, h, /* min */
2166                           mw, mh /* max */
2167                           );
2168 }
2169
2170 static void
2171 _e_gadcon_parent_resize_cb(E_Gadcon *gc, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2172 {
2173    Eina_List *l;
2174    E_Gadcon_Client *gcc;
2175
2176    EINA_LIST_FOREACH(gc->clients, l, gcc)
2177      _e_gadcon_moveresize_handle(gcc);
2178 }
2179
2180 static Eina_Bool
2181 _e_gadcon_cb_client_scroll_timer(void *data)
2182 {
2183    E_Gadcon_Client *gcc;
2184    double d, v;
2185
2186    gcc = data;
2187    d = gcc->scroll_wanted - gcc->scroll_pos;
2188    if (d < 0) d = -d;
2189    if (d < 0.001)
2190      {
2191         gcc->scroll_pos = gcc->scroll_wanted;
2192         gcc->scroll_timer = NULL;
2193         return ECORE_CALLBACK_CANCEL;
2194      }
2195    v = 0.05;
2196    gcc->scroll_pos = (gcc->scroll_pos * (1.0 - v)) + (gcc->scroll_wanted * v);
2197    return ECORE_CALLBACK_RENEW;
2198 }
2199
2200 static Eina_Bool
2201 _e_gadcon_cb_client_scroll_animator(void *data)
2202 {
2203    E_Gadcon_Client *gcc;
2204
2205    gcc = data;
2206    if (e_box_orientation_get(gcc->o_box))
2207      e_box_align_set(gcc->o_box, 1.0 - gcc->scroll_pos, 0.5);
2208    else
2209      e_box_align_set(gcc->o_box, 0.5, 1.0 - gcc->scroll_pos);
2210    if (!gcc->scroll_timer)
2211      {
2212         gcc->scroll_animator = NULL;
2213         return ECORE_CALLBACK_CANCEL;
2214      }
2215
2216    if (gcc->scroll_cb.func)
2217      gcc->scroll_cb.func(gcc->scroll_cb.data);
2218
2219    return ECORE_CALLBACK_RENEW;
2220 }
2221
2222 static void
2223 _e_gadcon_cb_client_frame_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2224 {
2225    Evas_Event_Mouse_Move *ev;
2226    E_Gadcon_Client *gcc;
2227    Evas_Coord x, y;
2228
2229    ev = event_info;
2230    gcc = data;
2231    evas_object_geometry_get(gcc->o_box, &x, &y, NULL, NULL);
2232    e_gadcon_client_autoscroll_update(gcc, ev->cur.output.x - x,
2233                                      ev->cur.output.y - y);
2234 }
2235
2236 static void
2237 _e_gadcon_cb_client_frame_moveresize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2238 {
2239    E_Gadcon_Client *gcc;
2240
2241    gcc = data;
2242    _e_gadcon_moveresize_handle(gcc);
2243 }
2244
2245 static void
2246 _e_gadcon_client_save(E_Gadcon_Client *gcc)
2247 {
2248    gcc->cf->geom.pos = gcc->config.pos;
2249    gcc->cf->geom.size = gcc->config.size;
2250    gcc->cf->geom.res = gcc->config.res;
2251    gcc->cf->geom.pos_x = gcc->config.pos_x;
2252    gcc->cf->geom.pos_y = gcc->config.pos_y;
2253    gcc->cf->geom.size_w = gcc->config.size_w;
2254    gcc->cf->geom.size_h = gcc->config.size_h;
2255    gcc->cf->state_info.seq = gcc->state_info.seq;
2256    gcc->cf->state_info.flags = gcc->state_info.flags;
2257    gcc->cf->autoscroll = gcc->autoscroll;
2258    eina_stringshare_replace(&gcc->cf->style, gcc->style);
2259 /*   gcc->cf->resizable = gcc->resizable;*/
2260    gcc->cf->resizable = 0;
2261    e_config_save_queue();
2262 }
2263
2264 static void
2265 _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y)
2266 {
2267    E_Drag *drag;
2268    Evas_Object *o = NULL;
2269    Evas_Coord w = 0, h = 0;
2270    E_Zone *zone;
2271    const char *drag_types[] = { "enlightenment/gadcon_client" };
2272
2273    zone = e_gadcon_zone_get(gcc->gadcon);
2274    if (gcc->gadcon->drag_gcc) return;
2275    if (!zone) return;
2276
2277    if (!e_util_strcmp(gcc->client_class->name, "systray"))
2278      return;
2279
2280    e_gadcon_client_drag_set(gcc);
2281
2282    e_object_ref(E_OBJECT(gcc));
2283    /* Remove this config from the current gadcon */
2284    gcc->gadcon->cf->clients =
2285      eina_list_remove(gcc->gadcon->cf->clients, gcc->cf);
2286    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2287    gcc->state_info.resist = 0;
2288
2289    if (!e_drop_inside(gcc->gadcon->drop_handler, x, y))
2290      e_gadcon_client_hide(gcc);
2291
2292    ecore_evas_pointer_xy_get(zone->comp->ee, &x, &y);
2293
2294    gcc->drag.drag = drag = e_drag_new(zone->comp, x, y,
2295                                       drag_types, 1, gcc, -1, NULL,
2296                                       e_gadcon_drag_finished_cb);
2297    if (!drag) return;
2298
2299    o = gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class,
2300                                     e_drag_evas_get(drag));
2301    if (o)
2302      evas_object_geometry_get(o, NULL, NULL, &w, &h);
2303    else
2304      {
2305         /* FIXME: fallback icon for drag */
2306         o = evas_object_rectangle_add(e_drag_evas_get(drag));
2307         evas_object_color_set(o, 255, 255, 255, 100);
2308      }
2309    if (w < 10)
2310      w = h = 50;
2311    e_drag_object_set(drag, o);
2312    e_drag_resize(drag, w, h);
2313    e_drag_start(drag, x + w / 2, y + h / 2);
2314    e_drag_hide(drag);
2315 }
2316
2317 static void
2318 _e_gadcon_client_inject(E_Gadcon *gc, E_Gadcon_Client *gcc, int x, int y)
2319 {
2320    Eina_List *l;
2321    E_Gadcon_Client *gcc2;
2322    Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0;
2323    int i;
2324
2325    /* Check if the gadcon client is in place */
2326    if (!gcc->hidden)
2327      {
2328         if (gcc->o_frame)
2329           evas_object_geometry_get(gcc->o_frame, &cx, &cy, &cw, &ch);
2330         else if (gcc->o_base)
2331           evas_object_geometry_get(gcc->o_base, &cx, &cy, &cw, &ch);
2332         else return;  /* make clang happy */
2333
2334         if (E_INSIDE(x, y, cx, cy, cw, ch)) return;
2335      }
2336
2337    /* If x, y is not inside any gadcon client, seq will be 0 and it's position
2338     * will later be used for placement. */
2339    gcc->state_info.seq = 0;
2340    for (i = 0; i < 2; i++)
2341      {
2342         /* two passes:
2343          * - find sequence position to inject
2344          * - update other gadget sequences
2345          */
2346         EINA_LIST_FOREACH(gc->clients, l, gcc2)
2347           {
2348              if (gcc == gcc2) continue;
2349              if (i == 1)
2350                {
2351                   /* on second pass, increment all sequence numbers which are
2352                    * >= the injected gadget's sequence to get ordering right
2353                    */
2354                   if (gcc2->state_info.seq >= gcc->state_info.seq)
2355                     gcc2->state_info.seq++;
2356                   continue;
2357                }
2358              if (gcc2->hidden) continue;
2359              if (gcc2->o_frame)
2360                evas_object_geometry_get(gcc2->o_frame, &cx, &cy, &cw, &ch);
2361              else if (gcc2->o_base)
2362                evas_object_geometry_get(gcc2->o_base, &cx, &cy, &cw, &ch);
2363              else return;  /* make clang happy */
2364              if (e_gadcon_layout_orientation_get(gc->o_container))
2365                {
2366                   /* inside left half of gadget */
2367                   if (E_INSIDE(x, y, cx, cy, cw / 2, ch))
2368                     {
2369                        /* place before */
2370                        gcc->state_info.seq = gcc2->state_info.seq;
2371                        break;
2372                     }
2373                   /* inside right half of gadget */
2374                   else if (E_INSIDE(x, y, cx + cw / 2, cy, cw / 2, ch))
2375                     {
2376                        /* place after */
2377                        gcc->state_info.seq = gcc2->state_info.seq + 1;
2378                        break;
2379                     }
2380                }
2381              else
2382                {
2383                   /* top half of gadget */
2384                   if (E_INSIDE(x, y, cx, cy, cw, ch / 2))
2385                     {
2386                        /* place before */
2387                        gcc->state_info.seq = gcc2->state_info.seq;
2388                        break;
2389                     }
2390                   /* bottom half of gadget */
2391                   else if (E_INSIDE(x, y, cx, cy + ch / 2, cw, ch / 2))
2392                     {
2393                        /* place after */
2394                        gcc->state_info.seq = gcc2->state_info.seq + 1;
2395                        break;
2396                     }
2397                }
2398           }
2399      }
2400 }
2401
2402 static void
2403 _e_gadcon_cb_min_size_request(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2404 {
2405    E_Gadcon *gc;
2406
2407    gc = data;
2408    if (gc->min_size_request.func)
2409      {
2410         Evas_Coord w = 0, h = 0;
2411
2412         e_gadcon_layout_min_size_get(gc->o_container, &w, &h);
2413         gc->min_size_request.func(gc->min_size_request.data, gc, w, h);
2414      }
2415 }
2416
2417 static void
2418 _e_gadcon_cb_size_request(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2419 {
2420    E_Gadcon *gc;
2421
2422    gc = data;
2423    if (gc->resize_request.func)
2424      {
2425         Evas_Coord w = 0, h = 0;
2426
2427         e_gadcon_layout_asked_size_get(gc->o_container, &w, &h);
2428         gc->resize_request.func(gc->resize_request.data, gc, w, h);
2429      }
2430 }
2431
2432 static void
2433 _e_gadcon_cb_moveresize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2434 {
2435    E_Gadcon *gc;
2436    Evas_Coord x, y, w, h;
2437
2438    gc = data;
2439    evas_object_geometry_get(gc->o_container, &x, &y, &w, &h);
2440    if (gc->drop_handler)
2441      e_drop_handler_geometry_set(gc->drop_handler, x, y, w, h);
2442 }
2443
2444 static void
2445 _e_gadcon_cb_client_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2446 {
2447    Evas_Event_Mouse_Down *ev;
2448    E_Gadcon_Client *gcc;
2449
2450    gcc = data;
2451    ev = event_info;
2452    if (ev->button == 3)
2453      {
2454         E_Zone *zone;
2455         E_Menu *mn;
2456         E_Menu_Item *mi;
2457         int cx, cy;
2458
2459         zone = e_util_zone_current_get(e_manager_current_get());
2460
2461         e_gadcon_locked_set(gcc->gadcon, 1);
2462         mn = e_menu_new();
2463         e_menu_post_deactivate_callback_set(mn, _e_gadcon_client_cb_menu_post,
2464                                             gcc);
2465         gcc->menu = mn;
2466
2467         mi = e_menu_item_new(mn);
2468         e_menu_item_label_set(mi, _("Stop moving"));
2469         e_util_menu_item_theme_icon_set(mi, "enlightenment/edit");
2470         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
2471
2472         if (gcc->gadcon->menu_attach.func)
2473           {
2474              mi = e_menu_item_new(mn);
2475              e_menu_item_separator_set(mi, 1);
2476
2477              gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data,
2478                                            gcc, mn);
2479              if (gcc->gadcon->shelf) e_shelf_locked_set(gcc->gadcon->shelf, 0);
2480           }
2481
2482         if (gcc->gadcon->toolbar)
2483           ecore_evas_pointer_xy_get(zone->comp->ee, &cx, &cy);
2484         else
2485           {
2486              e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, NULL, NULL);
2487              cx = cx + ev->output.x;
2488              cy = cy + ev->output.y;
2489           }
2490         e_menu_activate_mouse(mn, zone, cx, cy, 1, 1,
2491                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
2492      }
2493 }
2494
2495 static void
2496 _e_gadcon_cb_client_mouse_in(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2497 {
2498    E_Gadcon_Client *gcc;
2499
2500    gcc = data;
2501    edje_object_signal_emit(gcc->o_control, "e,state,focused", "e");
2502 }
2503
2504 static void
2505 _e_gadcon_cb_client_mouse_out(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2506 {
2507    E_Gadcon_Client *gcc;
2508
2509    gcc = data;
2510    edje_object_signal_emit(gcc->o_control, "e,state,unfocused", "e");
2511 }
2512
2513 static void
2514 _e_gadcon_cb_client_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2515 {
2516    E_Gadcon_Client *gcc;
2517    Evas_Coord x, y;
2518
2519    gcc = data;
2520    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
2521    if (gcc->o_control) evas_object_move(gcc->o_control, x, y);
2522    if (gcc->o_event) evas_object_move(gcc->o_event, x, y);
2523 }
2524
2525 static void
2526 _e_gadcon_cb_client_resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2527 {
2528    E_Gadcon_Client *gcc;
2529    Evas_Coord w, h;
2530
2531    gcc = data;
2532    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2533    if (gcc->o_control) evas_object_resize(gcc->o_control, w, h);
2534    if (gcc->o_event) evas_object_resize(gcc->o_event, w, h);
2535 }
2536
2537 static void
2538 _e_gadcon_client_move_start(E_Gadcon_Client *gcc)
2539 {
2540    int x, y, gy, gx;
2541
2542    evas_object_raise(gcc->o_event);
2543    evas_object_stack_below(gcc->o_control, gcc->o_event);
2544    gcc->moving = 1;
2545    if (gcc->gadcon->toolbar)
2546      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2547    else
2548      {
2549         ecore_x_pointer_xy_get(e_comp_get(gcc)->ee_win, &gcc->dx, &gcc->dy);
2550         evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, NULL, NULL);
2551         gcc->dx -= gx;
2552         gcc->dy -= gy;
2553      }
2554
2555    if (gcc->o_frame)
2556      evas_object_geometry_get(gcc->o_frame, &x, &y, NULL, NULL);
2557    else if (gcc->o_base)
2558      evas_object_geometry_get(gcc->o_base, &x, &y, NULL, NULL);
2559    else
2560      return;
2561
2562    /* using drag pos to calc offset between pointer and gcc pos */
2563    gcc->drag.x = x - (gcc->dx + gx);
2564    gcc->drag.y = y - (gcc->dy + gy);
2565
2566    gcc->state_info.resist = 0;
2567 }
2568
2569 static void
2570 _e_gadcon_client_move_stop(E_Gadcon_Client *gcc)
2571 {
2572    gcc->moving = 0;
2573    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2574    gcc->state_info.resist = 0;
2575    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2576 }
2577
2578 static void
2579 _e_gadcon_client_move_go(E_Gadcon_Client *gcc)
2580 {
2581    Evas_Coord x, y, w, h;
2582    int cx, cy;
2583    int gx, gy, gw, gh;
2584    int changes = 0;
2585
2586    if (!gcc->moving) return;
2587    /* we need to get output not canvas because things like systray
2588       can reparent another window so we get no position here */
2589    /* maybe we should better grab mouse while move resize is active...*/
2590    //evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2591    if (gcc->gadcon->toolbar)
2592      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2593    else
2594      ecore_evas_pointer_xy_get(e_comp_get(gcc)->ee, &cx, &cy);
2595
2596    evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, &gw, &gh);
2597
2598    cx -= gx;
2599    cy -= gy;
2600
2601    x = cx - gcc->dx;
2602    y = cy - gcc->dy;
2603
2604    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION | E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2605    _e_gadcon_client_current_position_sync(gcc);
2606
2607    if ((cy + e_config->drag_resist < 0 || cy - e_config->drag_resist >= gh) ||
2608        (cx + e_config->drag_resist < 0 || cx - e_config->drag_resist > gw))
2609      {
2610         _e_gadcon_client_drag_begin(gcc, cx, cy);
2611         return;
2612      }
2613
2614    if (gcc->o_frame)
2615      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2616    else if (gcc->o_base)
2617      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2618    else
2619      return;  /* make clang happy */
2620
2621    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2622      {
2623         /* DRAG RIGHT */
2624         if (x > 0 && (cx + gcc->drag.x > gcc->config.pos))
2625           {
2626              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2627                gcc->state_info.resist = 0;
2628              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2629              changes = 1;
2630           }
2631         /* DRAG LEFT */
2632         else if (x < 0 && (cx + gcc->drag.x < gcc->config.pos))
2633           {
2634              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2635                gcc->state_info.resist = 0;
2636              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2637              changes = 1;
2638           }
2639
2640         if (changes)
2641           {
2642              if (gcc->o_frame)
2643                e_gadcon_layout_pack_request_set(gcc->o_frame, cx + gcc->drag.x, w);
2644              else if (gcc->o_base)
2645                e_gadcon_layout_pack_request_set(gcc->o_base, cx + gcc->drag.x, w);
2646
2647              gcc->config.size = w;
2648              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2649              gcc->config.res = w;
2650           }
2651      }
2652    else
2653      {
2654         /* DRAG DOWN */
2655         if (y > 0 && (cy + gcc->drag.y > gcc->config.pos))
2656           {
2657              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2658                gcc->state_info.resist = 0;
2659              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2660              changes = 1;
2661           }
2662         /* DRAG UP */
2663         else if (y < 0 && (cy + gcc->drag.y < gcc->config.pos))
2664           {
2665              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2666                gcc->state_info.resist = 0;
2667              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2668              changes = 1;
2669           }
2670
2671         if (changes)
2672           {
2673              if (gcc->o_frame)
2674                e_gadcon_layout_pack_request_set(gcc->o_frame, cy + gcc->drag.y, h);
2675              else if (gcc->o_base)
2676                e_gadcon_layout_pack_request_set(gcc->o_base, cy + gcc->drag.y, h);
2677
2678              gcc->config.size = h;
2679              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2680              gcc->config.res = h;
2681           }
2682      }
2683
2684    gcc->dx += x;
2685    gcc->dy += y;
2686 }
2687
2688 static void
2689 _e_gadcon_cb_signal_move_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2690 {
2691    _e_gadcon_client_move_start(data);
2692 }
2693
2694 static void
2695 _e_gadcon_cb_signal_move_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2696 {
2697    _e_gadcon_client_move_stop(data);
2698 }
2699
2700 static void
2701 _e_gadcon_cb_signal_move_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2702 {
2703    _e_gadcon_client_move_go(data);
2704 }
2705
2706 static void
2707 _e_gadcon_client_resize_start(E_Gadcon_Client *gcc)
2708 {
2709    evas_object_raise(gcc->o_event);
2710    evas_object_stack_below(gcc->o_control, gcc->o_event);
2711    gcc->resizing = 1;
2712    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2713 }
2714
2715 static void
2716 _e_gadconclient_resize_stop(E_Gadcon_Client *gcc)
2717 {
2718    gcc->resizing = 0;
2719    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2720    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2721    _e_gadcon_client_save(gcc);
2722 }
2723
2724 static void
2725 _e_gadcon_cb_signal_resize_left_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2726 {
2727    _e_gadcon_client_resize_start(data);
2728 }
2729
2730 static void
2731 _e_gadcon_cb_signal_resize_left_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2732 {
2733    _e_gadconclient_resize_stop(data);
2734 }
2735
2736 static void
2737 _e_gadcon_cb_signal_resize_left_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2738 {
2739    E_Gadcon_Client *gcc;
2740    Evas_Coord x, y, w, h;
2741
2742    gcc = data;
2743    if (!gcc->resizing) return;
2744    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2745    x = x - gcc->dx;
2746    y = y - gcc->dy;
2747
2748    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION |
2749      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2750
2751    if (gcc->o_frame)
2752      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2753    else if (gcc->o_base)
2754      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2755    else return;  /* make clang happy */
2756
2757    _e_gadcon_client_current_position_sync(gcc);
2758
2759    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2760      {
2761         if (x > 0)
2762           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2763         else if (x < 0)
2764           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2765      }
2766    else
2767      {
2768         if (y > 0)
2769           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2770         else if (y < 0)
2771           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2772      }
2773
2774    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2775      {
2776         if (gcc->o_frame)
2777           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + x, w - x);
2778         else if (gcc->o_base)
2779           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + x, w - x);
2780         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2781         gcc->config.res = w;
2782      }
2783    else
2784      {
2785         if (gcc->o_frame)
2786           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + y, h - y);
2787         else if (gcc->o_base)
2788           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + y, h - y);
2789         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2790         gcc->config.res = h;
2791      }
2792    gcc->dx += x;
2793    gcc->dy += y;
2794 }
2795
2796 static void
2797 _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2798 {
2799    _e_gadcon_client_resize_start(data);
2800 }
2801
2802 static void
2803 _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2804 {
2805    _e_gadconclient_resize_stop(data);
2806 }
2807
2808 static void
2809 _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2810 {
2811    E_Gadcon_Client *gcc;
2812    Evas_Coord x, y, w, h;
2813
2814    gcc = data;
2815    if (!gcc->resizing) return;
2816    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2817    x = x - gcc->dx;
2818    y = y - gcc->dy;
2819
2820    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION |
2821      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2822
2823    if (gcc->o_frame)
2824      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2825    else if (gcc->o_base)
2826      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2827    else return;  /* make clang happy */
2828
2829    _e_gadcon_client_current_position_sync(gcc);
2830
2831    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2832      {
2833         if (x > 0)
2834           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2835         else if (x < 0)
2836           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC;
2837      }
2838    else
2839      {
2840         if (y > 0)
2841           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2842         else if (y < 0)
2843           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2844      }
2845
2846    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2847      {
2848         if (gcc->o_frame)
2849           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, w + x);
2850         else if (gcc->o_base)
2851           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, w + x);
2852         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2853         gcc->config.res = w;
2854      }
2855    else
2856      {
2857         if (gcc->o_frame)
2858           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, h + y);
2859         else if (gcc->o_base)
2860           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, h + y);
2861         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2862         gcc->config.res = h;
2863      }
2864    gcc->dx += x;
2865    gcc->dy += y;
2866 }
2867
2868 static void
2869 _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event)
2870 {
2871    E_Event_Dnd_Enter *ev;
2872    E_Gadcon *gc;
2873    E_Gadcon_Client *gcc;
2874
2875    ev = event;
2876    gc = data;
2877    //INF("DND ENTER");
2878    gcc = gc->drag_gcc;
2879    if (!gcc) return;  // dnd from efm or something
2880    if ((!gcc->hidden) && (gcc->gadcon == gc))
2881      {
2882         if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
2883         e_drag_hide(gc->drag_gcc->drag.drag);
2884         return;
2885      }
2886    if (gcc->gadcon != gc)
2887      e_gadcon_client_hide(gc->drag_gcc);
2888    else if (e_gadcon_site_is_desktop(gcc->gadcon->location->site))
2889      {
2890         e_gadcon_client_show(gc->drag_gcc);
2891         e_drag_hide(gc->drag_gcc->drag.drag);
2892         if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
2893         return;
2894      }
2895    e_gadcon_layout_freeze(gc->o_container);
2896
2897    if (gc->new_gcc)
2898      {
2899         e_object_del(E_OBJECT(gc->new_gcc));
2900         gc->new_gcc = NULL;
2901      }
2902
2903    while (ev->data)
2904      {
2905         /* Create a new gadcon to show where the gadcon will end up */
2906         E_Gadcon_Client_Class *cc;
2907
2908         gcc = ev->data;
2909         cc = eina_hash_find(providers, gcc->name);
2910         if (!cc) break;
2911         if (!gcc->style)
2912           gc->new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
2913                                       cc->default_style);
2914         else
2915           gc->new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
2916                                       gcc->style);
2917
2918         if (!gc->new_gcc) break;
2919         gc->new_gcc->cf = gcc->cf;
2920         gc->new_gcc->client_class = cc;
2921         gc->new_gcc->config.pos = gcc->config.pos;
2922         gc->new_gcc->config.size = gcc->config.size;
2923         gc->new_gcc->config.res = gcc->config.res;
2924         gc->new_gcc->state_info.seq = gcc->state_info.seq;
2925         gc->new_gcc->state_info.flags = gcc->state_info.flags;
2926         gc->new_gcc->config.pos_x = gcc->config.pos_x;
2927         gc->new_gcc->config.pos_y = gcc->config.pos_y;
2928         gc->new_gcc->config.size_w = gcc->config.size_w;
2929         gc->new_gcc->config.size_h = gcc->config.size_h;
2930         if (gc->new_gcc->client_class->func.orient)
2931           {
2932              if (gc->orient == E_GADCON_ORIENT_FLOAT)
2933                {
2934                   gc->new_gcc->client_class->func.orient(gc->new_gcc, gcc->gadcon->orient);
2935                   gc->new_gcc->cf->orient = gcc->gadcon->orient;
2936                }
2937              else
2938                {
2939                   gc->new_gcc->client_class->func.orient(gc->new_gcc, gc->orient);
2940                   gc->new_gcc->cf->orient = gc->orient;
2941                }
2942           }
2943         if (gc->new_gcc->o_frame)
2944           e_gadcon_layout_pack_options_set(gc->new_gcc->o_frame, gc->new_gcc);
2945         else if (gc->new_gcc->o_base)
2946           {
2947              e_gadcon_layout_pack_options_set(gc->new_gcc->o_base, gc->new_gcc);
2948              if (!gc->o_container)
2949                {
2950                   int w, h, gw, gh;
2951
2952                   w = gc->zone->w;
2953                   h = gc->zone->h;
2954                   if ((!gc->new_gcc->config.pos_x) && (!gc->new_gcc->config.pos_y))
2955                     {
2956                        gc->new_gcc->config.pos_x = (double)ev->x / (double)w;
2957                        gc->new_gcc->config.pos_y = (double)ev->y / (double)h;
2958                     }
2959                   if ((!gc->new_gcc->config.size_w) && (!gc->new_gcc->config.size_h))
2960                     {
2961                        evas_object_geometry_get(gcc->o_frame ? : gcc->o_base, NULL, NULL, &gw, &gh);
2962                        gc->new_gcc->config.size_w = (double)gw / (double)w;
2963                        gc->new_gcc->config.size_h = (double)gh / (double)h;
2964                     }
2965                   else
2966                     {
2967                        gw = gc->new_gcc->config.size_w * w;
2968                        gh = gc->new_gcc->config.size_h * h;
2969                     }
2970                   evas_object_resize(gc->new_gcc->o_base, gw, gh);
2971                   evas_object_move(gc->new_gcc->o_base, ev->x, ev->y);
2972                }
2973           }
2974
2975         e_drag_hide(gc->drag_gcc->drag.drag);
2976         e_gadcon_client_edit_begin(gc->new_gcc);
2977         e_gadcon_client_autoscroll_set(gc->new_gcc, gcc->autoscroll);
2978 /*                e_gadcon_client_resizable_set(gc->new_gcc, gcc->resizable);*/
2979         gc->new_gcc->state_info.resist = 1;
2980         if (gc->instant_edit)
2981           e_gadcon_client_util_menu_attach(gc->new_gcc);
2982         break;
2983      }
2984    e_gadcon_layout_thaw(gc->o_container);
2985    if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
2986 }
2987
2988 static void
2989 _e_gadcon_cb_dnd_move(void *data, const char *type __UNUSED__, void *event)
2990 {
2991    E_Event_Dnd_Move *ev;
2992    E_Gadcon *gc;
2993    E_Gadcon_Client *gcc = NULL;
2994    int dx = 0, dy = 0;
2995    Evas_Object *o;
2996
2997    ev = event;
2998    gc = data;
2999    //INF("DND (%d,%d)", ev->x, ev->y);
3000    gcc = gc->new_gcc ? : gc->drag_gcc;
3001    if (!gcc) return;
3002
3003    if (gcc->state_info.resist > 0)
3004      {
3005         gcc->state_info.resist--;
3006         return;
3007      }
3008    e_gadcon_layout_freeze(gc->o_container);
3009
3010    if (e_gadcon_layout_orientation_get(gc->o_container))
3011      gcc->config.pos = ev->x - gcc->config.size / 2;
3012    else
3013      gcc->config.pos = ev->y - gcc->config.size / 2;
3014    if (!gcc->gadcon->o_container)
3015      {
3016         int w, h;
3017         w = gc->zone->w;
3018         h = gc->zone->h;
3019         gcc->config.pos_x = (double)ev->x / (double)w;
3020         gcc->config.pos_y = (double)ev->y / (double)h;
3021         if (gcc->o_frame) evas_object_move(gcc->o_frame, ev->x, ev->y);
3022         else if (gcc->o_base)
3023           evas_object_move(gcc->o_base, ev->x, ev->y);
3024      }
3025    _e_gadcon_client_inject(gc, gcc, ev->x + dx, ev->y + dy);
3026
3027    o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
3028    if (o)
3029      e_gadcon_layout_pack_request_set(o, gcc->config.pos,
3030                                       gcc->config.size);
3031    e_gadcon_layout_thaw(gc->o_container);
3032    if (gc->dnd_move_cb) gc->dnd_move_cb(gc, gcc);
3033 }
3034
3035 static void
3036 _e_gadcon_cb_dnd_leave(void *data, const char *type __UNUSED__, void *event __UNUSED__)
3037 {
3038    E_Gadcon *gc;
3039
3040    gc = data;
3041    //INF("DND LEAVE");
3042
3043    /* If we exit the starting container hide the gadcon visual */
3044    if (gc->drag_gcc->gadcon == gc) e_gadcon_client_hide(gc->drag_gcc);
3045
3046    /* Delete temporary object */
3047    if (!gc->new_gcc)
3048      {
3049         if (gc->dnd_leave_cb) gc->dnd_leave_cb(gc, gc->drag_gcc);
3050         return;
3051      }
3052
3053    //INF("DELETING new_gcc");
3054    e_object_del(E_OBJECT(gc->new_gcc));
3055    gc->new_gcc = NULL;
3056    e_drag_show(gc->drag_gcc->drag.drag);
3057    if (gc->dnd_leave_cb) gc->dnd_leave_cb(gc, gc->drag_gcc);
3058 }
3059
3060 static void
3061 _e_gadcon_cb_dnd_drop(void *data, const char *type __UNUSED__, void *event __UNUSED__)
3062 {
3063    E_Gadcon *gc;
3064    E_Gadcon_Client *gcc = NULL;
3065
3066    gc = data;
3067    //INF("DND DROP");
3068    gc->cf->clients = eina_list_append(gc->cf->clients, gc->drag_gcc->cf);
3069    if (!gc->new_gcc)
3070      {
3071         /* using drag_gcc, so do things a bit differently
3072          * this only happens with gadman dnd, broken on shelves
3073          */
3074         _e_gadcon_client_save(gc->drag_gcc);
3075         e_gadcon_client_show(gc->drag_gcc);
3076         if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3077         return;
3078      }
3079    /* still has refcount from drag */
3080    e_object_del(E_OBJECT(gc->drag_gcc));
3081    gcc = gc->new_gcc;
3082
3083    if (!gc->o_container)
3084      {
3085         /* FIXME: gadman sucks and should probably use a regular gadcon layout, but it doesn't
3086          * so we need to repop here
3087          */
3088         gcc->cf = gc->drag_gcc->cf;
3089         _e_gadcon_client_save(gc->new_gcc);
3090         e_object_del(E_OBJECT(gc->new_gcc));
3091         gc->new_gcc = NULL;
3092         /* this little hack prevents the dead gcc from overwriting our config */
3093         gc->drag_gcc->moving = 0;
3094         e_gadcon_custom_populate_request(gc);
3095         e_config_save_queue();
3096         if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3097         return;
3098      }
3099    if (gc->editing) e_gadcon_client_edit_begin(gc->new_gcc);
3100    gc->new_gcc = NULL;
3101    e_config_save_queue();
3102    if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3103 }
3104
3105 static int
3106 _e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class *cc, const char *name, void *feature)
3107 {
3108    if (!feature)
3109      {
3110         e_util_dialog_show(_("Insufficent gadcon support"),
3111                            _("Module %s needs to support %s"),
3112                            cc->name, name);
3113         return 0;
3114      }
3115    return 1;
3116 }
3117
3118 static void
3119 _e_gadcon_client_cb_menu_post(void *data, E_Menu *m __UNUSED__)
3120 {
3121    E_Gadcon_Client *gcc;
3122
3123    if (!(gcc = data)) return;
3124    if (gcc->gadcon) e_gadcon_locked_set(gcc->gadcon, 0);
3125    if (!gcc->menu) return;
3126    if (gcc->gadcon && gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
3127    e_object_del(E_OBJECT(gcc->menu));
3128    gcc->menu = NULL;
3129 }
3130
3131 static Eina_Bool
3132 _e_gadcon_client_cb_instant_edit_timer(void *data)
3133 {
3134    E_Gadcon_Client *gcc;
3135
3136    gcc = data;
3137    e_gadcon_client_edit_begin(gcc);
3138    _e_gadcon_client_move_start(gcc);
3139    gcc->instant_edit_timer = NULL;
3140    return ECORE_CALLBACK_CANCEL;
3141 }
3142
3143 static void
3144 _e_gadcon_client_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
3145 {
3146    Evas_Event_Mouse_Down *ev;
3147    E_Gadcon_Client *gcc;
3148
3149    ev = event_info;
3150    gcc = data;
3151    if (gcc->menu) return;
3152    if (ev->button == 3)
3153      {
3154         E_Menu *m;
3155         E_Zone *zone;
3156         int cx, cy, cw, ch;
3157
3158         e_gadcon_locked_set(gcc->gadcon, 1);
3159         m = e_menu_new();
3160
3161         m = e_gadcon_client_util_menu_items_append(gcc, m, 0);
3162         e_menu_post_deactivate_callback_set(m, _e_gadcon_client_cb_menu_post,
3163                                             gcc);
3164         gcc->menu = m;
3165         if (gcc->gadcon->shelf) gcc->gadcon->shelf->menu = m;
3166
3167         e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, &cw, &ch);
3168         zone = gcc->gadcon->zone;
3169         if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
3170         e_menu_activate_mouse(m, zone,
3171                               cx + ev->output.x,
3172                               cy + ev->output.y, 1, 1,
3173                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
3174      }
3175    else if (ev->button == 2)
3176      {
3177         if (gcc->instant_edit_timer)
3178           ecore_timer_del(gcc->instant_edit_timer);
3179         gcc->instant_edit_timer = NULL;
3180         e_gadcon_client_edit_begin(gcc);
3181         _e_gadcon_client_move_start(gcc);
3182      }
3183    else if (ev->button == 1)
3184      {
3185         if ((!gcc->o_control) && (gcc->gadcon->instant_edit))
3186           {
3187              if (gcc->instant_edit_timer)
3188                ecore_timer_del(gcc->instant_edit_timer);
3189              gcc->instant_edit_timer =
3190                ecore_timer_add(1.0, _e_gadcon_client_cb_instant_edit_timer,
3191                                gcc);
3192           }
3193      }
3194 }
3195
3196 static void
3197 _e_gadcon_client_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
3198 {
3199    Evas_Event_Mouse_Up *ev;
3200    E_Gadcon_Client *gcc;
3201
3202    ev = event_info;
3203    gcc = data;
3204    if ((ev->button == 1) && (gcc->gadcon->instant_edit))
3205      {
3206         if (gcc->instant_edit_timer)
3207           {
3208              ecore_timer_del(gcc->instant_edit_timer);
3209              gcc->instant_edit_timer = NULL;
3210           }
3211         if (gcc->o_control)
3212           {
3213              _e_gadcon_client_move_stop(gcc);
3214              e_gadcon_client_edit_end(gcc);
3215           }
3216      }
3217    else if (ev->button == 2)
3218      {
3219         if (gcc->o_control)
3220           {
3221              _e_gadcon_client_move_stop(gcc);
3222              e_gadcon_client_edit_end(gcc);
3223           }
3224      }
3225 }
3226
3227 static void
3228 _e_gadcon_client_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3229 {
3230    E_Gadcon_Client *gcc;
3231
3232    gcc = data;
3233    if ((gcc->gadcon->instant_edit))
3234      {
3235         if (gcc->o_control) _e_gadcon_client_move_go(gcc);
3236      }
3237 }
3238
3239 static void
3240 _e_gadcon_client_cb_menu_style_plain(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3241 {
3242    E_Gadcon_Client *gcc;
3243    E_Gadcon *gc;
3244
3245    gcc = data;
3246    gc = gcc->gadcon;
3247    eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_PLAIN);
3248    _e_gadcon_client_save(gcc);
3249    e_gadcon_unpopulate(gc);
3250    e_gadcon_populate(gc);
3251 }
3252
3253 static void
3254 _e_gadcon_client_cb_menu_style_inset(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3255 {
3256    E_Gadcon_Client *gcc;
3257    E_Gadcon *gc;
3258
3259    gcc = data;
3260    gc = gcc->gadcon;
3261    eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_INSET);
3262    _e_gadcon_client_save(gcc);
3263    e_gadcon_unpopulate(gc);
3264    e_gadcon_populate(gc);
3265 }
3266
3267 static void
3268 _e_gadcon_client_cb_menu_autoscroll(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3269 {
3270    E_Gadcon_Client *gcc;
3271
3272    gcc = data;
3273    e_gadcon_layout_freeze(gcc->gadcon->o_container);
3274    if (gcc->autoscroll) gcc->autoscroll = 0;
3275    else gcc->autoscroll = 1;
3276    e_gadcon_client_autoscroll_set(gcc, gcc->autoscroll);
3277    _e_gadcon_client_save(gcc);
3278    e_gadcon_layout_thaw(gcc->gadcon->o_container);
3279 }
3280
3281 /*
3282    static void
3283    _e_gadcon_client_cb_menu_resizable(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3284    {
3285    E_Gadcon_Client *gcc;
3286
3287    gcc = data;
3288    e_gadcon_layout_freeze(gcc->gadcon->o_container);
3289    if (gcc->resizable) gcc->resizable = 0;
3290    else gcc->resizable = 1;
3291    e_gadcon_client_resizable_set(gcc, gcc->resizable);
3292    _e_gadcon_client_save(gcc);
3293    e_gadcon_layout_thaw(gcc->gadcon->o_container);
3294    }
3295  */
3296 static void
3297 _e_gadcon_client_cb_menu_edit(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3298 {
3299    E_Gadcon_Client *gcc;
3300
3301    gcc = data;
3302    if (gcc->o_control)
3303      e_gadcon_client_edit_end(gcc);
3304    else
3305      e_gadcon_client_edit_begin(gcc);
3306 }
3307
3308 static void
3309 _e_gadcon_client_cb_menu_remove(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3310 {
3311    E_Gadcon *gc;
3312    E_Gadcon_Client *gcc;
3313
3314    gcc = data;
3315    gc = gcc->gadcon;
3316
3317    e_gadcon_client_config_del(gc->cf, gcc->cf);
3318    gcc->cf = NULL;
3319    e_object_del(E_OBJECT(gcc));
3320    if (!gc->custom)
3321      {
3322         e_gadcon_unpopulate(gc);
3323         e_gadcon_populate(gc);
3324      }
3325    e_config_save_queue();
3326 }
3327
3328 static void
3329 _e_gadcon_client_cb_menu_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi)
3330 {
3331    E_Gadcon_Client *gcc;
3332
3333    if (!(gcc = data)) return;
3334    if (gcc->client_class->func.icon)
3335      {
3336         // e menu ASSUMES... EXPECTS the icon to be an.... e_icon!
3337         // if it's not, spankies for whoever wrote the icon callback!
3338         mi->icon_object =
3339           gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class,
3340                                        mi->menu->evas);
3341      }
3342    else
3343      e_util_menu_item_theme_icon_set(mi, "preferences-gadget");  // FIXME: Needs icon in theme
3344 }
3345
3346 static void
3347 _e_gadcon_client_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3348 {
3349    E_Gadcon_Client *gcc;
3350
3351    gcc = data;
3352    gcc->o_base = NULL;
3353    e_object_del(E_OBJECT(gcc));
3354 }
3355
3356 /* a smart object JUST for gadcon */
3357
3358 typedef struct _E_Gadcon_Layout_Item E_Gadcon_Layout_Item;
3359
3360 struct _E_Smart_Data
3361 {
3362    Evas_Coord    x, y, w, h;
3363    Evas_Object  *obj, *clip;
3364    unsigned char horizontal : 1;
3365    unsigned char doing_config : 1;
3366    unsigned char redo_config : 1;
3367    Eina_List    *items;
3368    int           frozen;
3369    Evas_Coord    minw, minh, req;
3370 };
3371
3372 struct _E_Gadcon_Layout_Item
3373 {
3374    E_Smart_Data    *sd;
3375    struct
3376    {
3377       int pos, size, size2, res, prev_pos, prev_size;
3378    } ask;
3379    int              hookp;
3380    struct
3381    {
3382       int w, h;
3383    } min, aspect, aspect_pad;
3384
3385    E_Gadcon_Client *gcc;
3386
3387    Evas_Coord       x, y, w, h;
3388    Evas_Object     *obj;
3389    unsigned char    can_move : 1;
3390 };
3391
3392 /* local subsystem functions */
3393 static E_Gadcon_Layout_Item *_e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj);
3394 static void                  _e_gadcon_layout_smart_disown(Evas_Object *obj);
3395 static void                  _e_gadcon_layout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
3396 static void                  _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd);
3397 static void                  _e_gadcon_layout_smart_init(void);
3398 static void                  _e_gadcon_layout_smart_add(Evas_Object *obj);
3399 static void                  _e_gadcon_layout_smart_del(Evas_Object *obj);
3400 static void                  _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
3401 static void                  _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
3402 static void                  _e_gadcon_layout_smart_show(Evas_Object *obj);
3403 static void                  _e_gadcon_layout_smart_hide(Evas_Object *obj);
3404 static void                  _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
3405 static void                  _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
3406 static void                  _e_gadcon_layout_smart_clip_unset(Evas_Object *obj);
3407 static void                  _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur);
3408 static void                  _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur);
3409 static int                   _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2);
3410 static int                   _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2);
3411
3412 /* local subsystem globals */
3413 static Evas_Smart *_e_smart = NULL;
3414
3415 /* externally accessible functions */
3416 static Evas_Object *
3417 e_gadcon_layout_add(Evas *evas)
3418 {
3419    _e_gadcon_layout_smart_init();
3420    return evas_object_smart_add(evas, _e_smart);
3421 }
3422
3423 static void
3424 e_gadcon_layout_orientation_set(Evas_Object *obj, int horizontal)
3425 {
3426    E_Smart_Data *sd;
3427
3428    if (!obj) return;
3429    sd = evas_object_smart_data_get(obj);
3430    if (!sd) return;
3431    if (((sd->horizontal) && (horizontal)) ||
3432        ((!sd->horizontal) && (!horizontal))) return;
3433    sd->horizontal = horizontal;
3434    _e_gadcon_layout_smart_reconfigure(sd);
3435 }
3436
3437 static int
3438 e_gadcon_layout_orientation_get(Evas_Object *obj)
3439 {
3440    E_Smart_Data *sd;
3441
3442    if (!obj) return 0;
3443    sd = evas_object_smart_data_get(obj);
3444    if (!sd) return 0;
3445    return sd->horizontal;
3446 }
3447
3448 static void
3449 e_gadcon_layout_freeze(Evas_Object *obj)
3450 {
3451    E_Smart_Data *sd;
3452
3453    if (!obj) return;
3454    sd = evas_object_smart_data_get(obj);
3455    if (!sd) return;
3456    sd->frozen++;
3457 }
3458
3459 static void
3460 e_gadcon_layout_thaw(Evas_Object *obj)
3461 {
3462    E_Smart_Data *sd;
3463
3464    if (!obj) return;
3465    sd = evas_object_smart_data_get(obj);
3466    if (!sd) return;
3467    sd->frozen--;
3468    _e_gadcon_layout_smart_reconfigure(sd);
3469 }
3470
3471 static void
3472 e_gadcon_layout_min_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
3473 {
3474    E_Smart_Data *sd;
3475 /*
3476    Eina_List *l;
3477    Evas_Object *obj;
3478    Evas_Coord tw = 0, th = 0;
3479  */
3480    if (!obj) return;
3481    sd = evas_object_smart_data_get(obj);
3482    if (!sd) return;
3483    if (sd->horizontal)
3484      {
3485         if (w) *w = sd->minw;
3486         if (h) *h = sd->minh;
3487      }
3488    else
3489      {
3490         if (w) *w = sd->minh;
3491         if (h) *h = sd->minw;
3492      }
3493
3494 /*
3495    EINA_LIST_FOREACH(sd->items, l, obj)
3496      {
3497         E_Gadcon_Layout_Item *bi;
3498
3499         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3500         if (sd->horizontal)
3501           {
3502              tw += bi->min.w;
3503              if (bi->min.h > th) th = bi->min.h;
3504           }
3505         else
3506           {
3507              th += bi->min.h;
3508              if (bi->min.w > tw) tw = bi->min.w;
3509           }
3510      }
3511    if (w) *w = tw;
3512    if (h) *h = th;
3513  */
3514 }
3515
3516 static void
3517 e_gadcon_layout_asked_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
3518 {
3519    E_Smart_Data *sd;
3520    Evas_Coord tw = 0, th = 0;
3521
3522    if (!obj) return;
3523    sd = evas_object_smart_data_get(obj);
3524    if (!sd) return;
3525    if (sd->horizontal)
3526      tw = sd->req;
3527    else
3528      th = sd->req;
3529 /*
3530    Evas_Object *obj;
3531    EINA_LIST_FOREACH(sd->items, l, obj)
3532      {
3533         E_Gadcon_Layout_Item *bi;
3534
3535         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3536         if (sd->horizontal)
3537           {
3538              tw += bi->ask.size;
3539           }
3540         else
3541           {
3542              th += bi->ask.size;
3543           }
3544      }
3545  */
3546    if (w) *w = tw;
3547    if (h) *h = th;
3548 }
3549
3550 static int
3551 e_gadcon_layout_pack(Evas_Object *obj, Evas_Object *child)
3552 {
3553    E_Smart_Data *sd;
3554
3555    if (!obj) return 0;
3556    sd = evas_object_smart_data_get(obj);
3557    if (!sd) return 0;
3558    _e_gadcon_layout_smart_adopt(sd, child);
3559    sd->items = eina_list_prepend(sd->items, child);
3560    _e_gadcon_layout_smart_reconfigure(sd);
3561    return 0;
3562 }
3563
3564 static void
3565 e_gadcon_layout_pack_size_set(Evas_Object *obj, int size)
3566 {
3567    /*
3568     * FIXME:
3569     * simplify this function until the is redone
3570     * _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
3571     */
3572    E_Gadcon_Layout_Item *bi;
3573    int pos;
3574
3575    if (!obj) return;
3576    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3577    if (!bi) return;
3578    pos = bi->ask.pos + (bi->ask.size / 2);
3579    if (pos < (bi->ask.res / 3))
3580      {
3581         /* hooked to start */
3582         bi->ask.size = size;
3583      }
3584    else if (pos > ((2 * bi->ask.res) / 3))
3585      {
3586         /* hooked to end */
3587         bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3588         bi->ask.size = size;
3589      }
3590    else
3591      {
3592         /* hooked to middle */
3593         if ((bi->ask.pos <= (bi->ask.res / 2)) &&
3594             ((bi->ask.pos + bi->ask.size) > (bi->ask.res / 2)))
3595           {
3596              /* straddles middle */
3597              if (bi->ask.res > 2)
3598                bi->ask.pos = (bi->ask.res / 2) +
3599                  (((bi->ask.pos + (bi->ask.size / 2) -
3600                     (bi->ask.res / 2)) *
3601                    (bi->ask.res / 2)) /
3602                   (bi->ask.res / 2)) - (bi->ask.size / 2);
3603              else
3604                bi->x = bi->ask.res / 2;
3605              bi->ask.size = size;
3606           }
3607         else
3608           {
3609              if (pos < (bi->ask.res / 2))
3610                {
3611                   bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3612                   bi->ask.size = size;
3613                }
3614              else
3615                bi->ask.size = size;
3616           }
3617         bi->ask.size = size;
3618      }
3619    _e_gadcon_layout_smart_reconfigure(bi->sd);
3620 }
3621
3622 /* called when a users moves/resizes the gadcon client explicitly */
3623 static void
3624 e_gadcon_layout_pack_request_set(Evas_Object *obj, int pos, int size)
3625 {
3626    E_Gadcon_Layout_Item *bi;
3627
3628    if (!obj) return;
3629    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3630    if (!bi) return;
3631
3632    bi->ask.res = bi->sd->w;
3633    if (pos < 0) pos = 0;
3634    if ((bi->ask.res - pos) < size) pos = bi->ask.res - size;
3635    bi->ask.size = size;
3636    bi->ask.pos = pos;
3637    _e_gadcon_layout_smart_reconfigure(bi->sd);
3638 }
3639
3640 /* called when restoring config from saved config */
3641 static void
3642 e_gadcon_layout_pack_options_set(Evas_Object *obj, E_Gadcon_Client *gcc)
3643 {
3644    int ok, seq;
3645    Eina_List *l;
3646    Evas_Object *item;
3647    E_Gadcon_Layout_Item *bi, *bi2;
3648
3649    if (!obj) return;
3650    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3651    if (!bi) return;
3652    bi->ask.res = gcc->config.res;
3653    bi->ask.size = gcc->config.size;
3654    bi->ask.pos = gcc->config.pos;
3655    bi->gcc = gcc;
3656
3657    ok = 0;
3658    if (!gcc->state_info.seq) ok = 1;
3659
3660    seq = 1;
3661    EINA_LIST_FOREACH(bi->sd->items, l, item)
3662      {
3663         bi2 = evas_object_data_get(item, "e_gadcon_layout_data");
3664         if (bi == bi2) continue;
3665         if (bi->gcc->id == bi2->gcc->id) continue;
3666         if (bi->gcc->state_info.seq == bi2->gcc->state_info.seq)
3667           ok = 1;
3668
3669         if (bi2->gcc->state_info.seq > seq)
3670           seq = bi2->gcc->state_info.seq;
3671      }
3672
3673    if (ok)
3674      {
3675         gcc->state_info.seq = seq + 1;
3676         gcc->state_info.want_save = 1;
3677         gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_NONE;
3678      }
3679    _e_gadcon_layout_smart_reconfigure(bi->sd);
3680 }
3681
3682 static void
3683 e_gadcon_layout_pack_min_size_set(Evas_Object *obj, int w, int h)
3684 {
3685    E_Gadcon_Layout_Item *bi;
3686
3687    if (!obj) return;
3688    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3689    if (!bi)
3690      {
3691         evas_object_size_hint_min_set(obj, w, h);
3692         edje_extern_object_min_size_set(obj, w, h);
3693         return;
3694      }
3695    if (bi->sd->horizontal)
3696      {
3697         bi->min.w = w;
3698         bi->min.h = h;
3699      }
3700    else
3701      {
3702         bi->min.w = h;
3703         bi->min.h = w;
3704      }
3705
3706    _e_gadcon_layout_smart_reconfigure(bi->sd);
3707 }
3708
3709 static void
3710 e_gadcon_layout_pack_aspect_set(Evas_Object *obj, int w, int h)
3711 {
3712    E_Gadcon_Layout_Item *bi;
3713
3714    if (!obj) return;
3715    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3716    if (!bi)
3717      {
3718         evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, w, h);
3719         return;
3720      }
3721    if (bi->sd->horizontal)
3722      {
3723         bi->aspect.w = w;
3724         bi->aspect.h = h;
3725      }
3726    else
3727      {
3728         bi->aspect.w = h;
3729         bi->aspect.h = w;
3730      }
3731
3732    _e_gadcon_layout_smart_reconfigure(bi->sd);
3733 }
3734
3735 static void
3736 e_gadcon_layout_pack_aspect_pad_set(Evas_Object *obj, int w, int h)
3737 {
3738    E_Gadcon_Layout_Item *bi;
3739
3740    if (!obj) return;
3741    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3742    if (!bi) return;
3743    if (bi->sd->horizontal)
3744      {
3745         bi->aspect_pad.w = w;
3746         bi->aspect_pad.h = h;
3747      }
3748    else
3749      {
3750         bi->aspect_pad.w = h;
3751         bi->aspect_pad.h = w;
3752      }
3753 }
3754
3755 static void
3756 e_gadcon_layout_unpack(Evas_Object *obj)
3757 {
3758    E_Gadcon_Layout_Item *bi;
3759    E_Smart_Data *sd;
3760
3761    if (!obj) return;
3762    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3763    if (!bi) return;
3764    sd = bi->sd;
3765    if (!sd) return;
3766    sd->items = eina_list_remove(sd->items, obj);
3767    _e_gadcon_layout_smart_disown(obj);
3768    _e_gadcon_layout_smart_reconfigure(sd);
3769 }
3770
3771 /* local subsystem functions */
3772 static E_Gadcon_Layout_Item *
3773 _e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj)
3774 {
3775    E_Gadcon_Layout_Item *bi;
3776
3777    if (!obj) return NULL;
3778    bi = E_NEW(E_Gadcon_Layout_Item, 1);
3779    if (!bi) return NULL;
3780    bi->sd = sd;
3781    bi->obj = obj;
3782    /* defaults */
3783    evas_object_clip_set(obj, sd->clip);
3784    evas_object_smart_member_add(obj, bi->sd->obj);
3785    evas_object_data_set(obj, "e_gadcon_layout_data", bi);
3786    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
3787                                   _e_gadcon_layout_smart_item_del_hook, NULL);
3788    if ((!evas_object_visible_get(sd->clip)) &&
3789        (evas_object_visible_get(sd->obj)))
3790      evas_object_show(sd->clip);
3791    return bi;
3792 }
3793
3794 static void
3795 _e_gadcon_layout_smart_disown(Evas_Object *obj)
3796 {
3797    E_Gadcon_Layout_Item *bi;
3798
3799    if (!obj) return;
3800    bi = evas_object_data_del(obj, "e_gadcon_layout_data");
3801    if (!bi) return;
3802    if (!bi->sd->items)
3803      {
3804         if (evas_object_visible_get(bi->sd->clip))
3805           evas_object_hide(bi->sd->clip);
3806      }
3807    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
3808                                   _e_gadcon_layout_smart_item_del_hook);
3809    evas_object_smart_member_del(obj);
3810    evas_object_clip_unset(obj);
3811    free(bi);
3812 }
3813
3814 static void
3815 _e_gadcon_layout_smart_item_del_hook(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
3816 {
3817    if (!obj) return;
3818    e_gadcon_layout_unpack(obj);
3819 }
3820
3821 static void
3822 _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd)
3823 {
3824    Evas_Coord xx, yy;
3825    Eina_List *l;
3826    Evas_Object *obj;
3827    int min, mino, cur;
3828    Eina_List *list = NULL;
3829    E_Gadcon_Layout_Item *bi;
3830    E_Layout_Item_Container *lc;
3831    int i, set_prev_pos = 0;
3832    static int recurse = 0;
3833
3834    if (sd->frozen) return;
3835    if (sd->doing_config)
3836      {
3837         sd->redo_config = 1;
3838         return;
3839      }
3840
3841    recurse++;
3842    min = mino = cur = 0;
3843
3844    _e_gadcon_layout_smart_min_cur_size_calc(sd, &min, &mino, &cur);
3845
3846    if ((sd->minw != min) || (sd->minh != mino))
3847      {
3848         sd->minw = min;
3849         sd->minh = mino;
3850         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
3851      }
3852
3853    if (sd->req != cur)
3854      {
3855         if (cur >= sd->minw)
3856           {
3857              sd->req = cur;
3858              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
3859           }
3860         else
3861           {
3862              sd->req = sd->minw;
3863           }
3864      }
3865    if (recurse == 1) _e_gadcon_layout_smart_gadcons_width_adjust(sd, min, cur);
3866
3867    if (sd->w <= sd->req)
3868      {
3869         _e_gadcon_layout_smart_gadcon_position_shrinked_mode(sd);
3870         set_prev_pos = 0;
3871      }
3872    else
3873      {
3874         _e_gadcon_layout_smart_gadcons_asked_position_set(sd);
3875
3876         list = _e_gadcon_layout_smart_gadcons_wrap(sd);
3877
3878         _e_gadcon_layout_smart_gadcons_position(sd, &list);
3879
3880         EINA_LIST_FREE(list, lc)
3881           LC_FREE(lc);
3882
3883         set_prev_pos = 1;
3884      }
3885
3886    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
3887                               _e_gadcon_layout_smart_sort_by_position_cb);
3888    i = 1;
3889    EINA_LIST_FOREACH(sd->items, l, obj)
3890      {
3891         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3892         if (bi->gcc->gadcon->editing) bi->gcc->state_info.seq = i;
3893
3894         if (set_prev_pos)
3895           {
3896              bi->ask.prev_pos = bi->x;
3897              bi->ask.prev_size = bi->w;
3898           }
3899
3900         if ((bi->x == bi->ask.pos) &&
3901             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION))
3902           bi->gcc->state_info.flags |= E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3903
3904         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
3905             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
3906           {
3907              if (bi->x != bi->ask.pos)
3908                bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3909           }
3910         i++;
3911      }
3912
3913    EINA_LIST_FOREACH(sd->items, l, obj)
3914      {
3915         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3916         if (!bi) continue;
3917
3918         bi->h = sd->h;
3919         xx = sd->x + bi->x;
3920         yy = sd->y; // + ((sd->h - bi->h) / 2);
3921
3922         if (sd->horizontal)
3923           {
3924              evas_object_move(obj, xx, yy);
3925              evas_object_resize(obj, bi->w, bi->h);
3926           }
3927         else
3928           {
3929              evas_object_move(obj, yy, xx);
3930              evas_object_resize(obj, bi->h, bi->w);
3931           }
3932         if ((recurse == 1) && bi->gcc->state_info.want_save)
3933           {
3934              _e_gadcon_client_save(bi->gcc);
3935              bi->gcc->state_info.want_save = 0;
3936           }
3937      }
3938    sd->doing_config = 0;
3939    if (sd->redo_config)
3940      {
3941         _e_gadcon_layout_smart_reconfigure(sd);
3942         sd->redo_config = 0;
3943      }
3944
3945    if ((sd->minw != min) || (sd->minh != mino))
3946      {
3947         sd->minw = min;
3948         sd->minh = mino;
3949         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
3950      }
3951
3952    if (sd->req != cur)
3953      {
3954         if (cur >= sd->minw)
3955           {
3956              sd->req = cur;
3957              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
3958           }
3959      }
3960    recurse--;
3961 }
3962
3963 static void
3964 _e_gadcon_layout_smart_init(void)
3965 {
3966    if (_e_smart) return;
3967    {
3968       static const Evas_Smart_Class sc =
3969       {
3970          "e_gadcon_layout",
3971          EVAS_SMART_CLASS_VERSION,
3972          _e_gadcon_layout_smart_add,
3973          _e_gadcon_layout_smart_del,
3974          _e_gadcon_layout_smart_move,
3975          _e_gadcon_layout_smart_resize,
3976          _e_gadcon_layout_smart_show,
3977          _e_gadcon_layout_smart_hide,
3978          _e_gadcon_layout_smart_color_set,
3979          _e_gadcon_layout_smart_clip_set,
3980          _e_gadcon_layout_smart_clip_unset,
3981          NULL, NULL, NULL, NULL, NULL, NULL, NULL
3982       };
3983       _e_smart = evas_smart_class_new(&sc);
3984    }
3985 }
3986
3987 static void
3988 _e_gadcon_layout_smart_add(Evas_Object *obj)
3989 {
3990    E_Smart_Data *sd;
3991
3992    if (!obj) return;
3993    sd = calloc(1, sizeof(E_Smart_Data));
3994    if (!sd) return;
3995    sd->obj = obj;
3996    sd->x = 0;
3997    sd->y = 0;
3998    sd->w = 0;
3999    sd->h = 0;
4000    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
4001    sd->horizontal = 1;
4002    evas_object_smart_member_add(sd->clip, obj);
4003    evas_object_move(sd->clip, -100005, -100005);
4004    evas_object_resize(sd->clip, 200010, 200010);
4005    evas_object_color_set(sd->clip, 255, 255, 255, 255);
4006    evas_object_smart_data_set(obj, sd);
4007 }
4008
4009 static void
4010 _e_gadcon_layout_smart_del(Evas_Object *obj)
4011 {
4012    E_Smart_Data *sd;
4013
4014    if (!obj) return;
4015    sd = evas_object_smart_data_get(obj);
4016    if (!sd) return;
4017    while (sd->items)
4018      {
4019         Evas_Object *child;
4020
4021         child = eina_list_data_get(sd->items);
4022         e_gadcon_layout_unpack(child);
4023      }
4024    evas_object_del(sd->clip);
4025    free(sd);
4026    evas_object_smart_data_set(obj, NULL);
4027 }
4028
4029 static void
4030 _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
4031 {
4032    E_Smart_Data *sd;
4033
4034    if (!obj) return;
4035    sd = evas_object_smart_data_get(obj);
4036    if (!sd) return;
4037    if ((x == sd->x) && (y == sd->y)) return;
4038    {
4039       Eina_List *l;
4040       Evas_Object *item;
4041       Evas_Coord dx, dy;
4042
4043       if (sd->horizontal)
4044         {
4045            dx = x - sd->x;
4046            dy = y - sd->y;
4047         }
4048       else
4049         {
4050            dx = x - sd->y;
4051            dy = y - sd->x;
4052         }
4053
4054       EINA_LIST_FOREACH(sd->items, l, item)
4055         {
4056            Evas_Coord ox, oy;
4057
4058            evas_object_geometry_get(item, &ox, &oy, NULL, NULL);
4059            evas_object_move(item, ox + dx, oy + dy);
4060         }
4061    }
4062
4063    if (sd->horizontal)
4064      {
4065         sd->x = x;
4066         sd->y = y;
4067      }
4068    else
4069      {
4070         sd->x = y;
4071         sd->y = x;
4072      }
4073 }
4074
4075 static void
4076 _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
4077 {
4078    E_Smart_Data *sd;
4079
4080    if (!obj) return;
4081    sd = evas_object_smart_data_get(obj);
4082    if (!sd) return;
4083    if ((w == sd->w) && (h == sd->h)) return;
4084    if (sd->horizontal)
4085      {
4086         sd->w = w;
4087         sd->h = h;
4088      }
4089    else
4090      {
4091         sd->w = h;
4092         sd->h = w;
4093      }
4094
4095    _e_gadcon_layout_smart_reconfigure(sd);
4096 }
4097
4098 static void
4099 _e_gadcon_layout_smart_show(Evas_Object *obj)
4100 {
4101    E_Smart_Data *sd;
4102
4103    if (!obj) return;
4104    sd = evas_object_smart_data_get(obj);
4105    if (!sd) return;
4106    if (sd->items) evas_object_show(sd->clip);
4107 }
4108
4109 static void
4110 _e_gadcon_layout_smart_hide(Evas_Object *obj)
4111 {
4112    E_Smart_Data *sd;
4113
4114    if (!obj) return;
4115    sd = evas_object_smart_data_get(obj);
4116    if (!sd) return;
4117    evas_object_hide(sd->clip);
4118 }
4119
4120 static void
4121 _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
4122 {
4123    E_Smart_Data *sd;
4124
4125    if (!obj) return;
4126    sd = evas_object_smart_data_get(obj);
4127    if (!sd) return;
4128    evas_object_color_set(sd->clip, r, g, b, a);
4129 }
4130
4131 static void
4132 _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
4133 {
4134    E_Smart_Data *sd;
4135
4136    if (!obj) return;
4137    sd = evas_object_smart_data_get(obj);
4138    if (!sd) return;
4139    evas_object_clip_set(sd->clip, clip);
4140 }
4141
4142 static void
4143 _e_gadcon_layout_smart_clip_unset(Evas_Object *obj)
4144 {
4145    E_Smart_Data *sd;
4146
4147    if (!obj) return;
4148    sd = evas_object_smart_data_get(obj);
4149    if (!sd) return;
4150    evas_object_clip_unset(sd->clip);
4151 }
4152
4153 /*
4154  * @min - the minimum width required by all the gadcons
4155  * @cur - the current width required by all the gadcons
4156  * @mino - the smalest width/height among all the objects
4157  */
4158 static void
4159 _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur)
4160 {
4161    E_Gadcon_Layout_Item *bi;
4162    Eina_List *l;
4163    Evas_Object *item;
4164
4165    EINA_LIST_FOREACH(sd->items, l, item)
4166      {
4167         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4168         bi->ask.size2 = bi->ask.size;
4169
4170         if ((bi->aspect.w > 0) && (bi->aspect.h > 0))
4171           {
4172              bi->ask.size2 =
4173                (((sd->h - bi->aspect_pad.h) * bi->aspect.w) / bi->aspect.h) + bi->aspect_pad.w;
4174
4175              if (bi->ask.size2 > bi->min.w)
4176                {
4177                   *min += bi->ask.size2;
4178                   *cur += bi->ask.size2;
4179                }
4180              else
4181                {
4182                   *min += bi->min.w;
4183                   *cur += bi->min.w;
4184                }
4185           }
4186         else
4187           {
4188              bi->ask.size2 = bi->ask.size = bi->min.w;
4189              *min += bi->min.w;
4190              if (bi->min.h > *mino) *mino = bi->min.h;
4191              if (bi->ask.size < bi->min.w)
4192                *cur += bi->min.w;
4193              else
4194                *cur += bi->ask.size;
4195           }
4196      }
4197 }
4198
4199 static int
4200 _e_gadcon_layout_smart_width_smart_sort_reverse_cb(const void *d1, const void *d2)
4201 {
4202    const E_Gadcon_Layout_Item *bi, *bi2;
4203
4204    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4205    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4206
4207    if (bi->ask.size2 > bi->min.w)
4208      {
4209         if (bi2->ask.size2 > bi2->min.w)
4210           {
4211              if (bi->ask.size2 < bi2->ask.size2)
4212                return 1;
4213              else
4214                return -1;
4215           }
4216         else
4217           {
4218              if (bi->ask.size2 == bi2->ask.size2)
4219                return -1;
4220              else
4221                {
4222                   if (bi->ask.size2 < bi2->ask.size2)
4223                     return 1;
4224                   else
4225                     return -1;
4226                }
4227           }
4228      }
4229    else
4230      {
4231         if (bi2->ask.size2 > bi2->min.w)
4232           {
4233              if (bi->ask.size2 == bi2->ask.size2)
4234                return 1;
4235              else
4236                {
4237                   if (bi->ask.size2 < bi2->ask.size2)
4238                     return 1;
4239                   else
4240                     return -1;
4241                }
4242           }
4243         else
4244           {
4245              if (bi->ask.size2 < bi2->ask.size2)
4246                return 1;
4247              else if (bi->ask.size2 > bi2->ask.size2)
4248                return -1;
4249           }
4250      }
4251
4252    return 0;
4253 }
4254
4255 static void
4256 _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur)
4257 {
4258    E_Gadcon_Layout_Item *bi = NULL;
4259    Eina_List *l, *l2;
4260    Evas_Object *item;
4261    int needed = 0;
4262    int need = 0;
4263    int max_size, autosize = 0;
4264
4265    if (sd->w < cur)
4266      {
4267         if (sd->w < min) max_size = min;
4268         else max_size = cur;
4269         need = max_size - sd->w;
4270      }
4271    else
4272      return;
4273
4274    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
4275                               _e_gadcon_layout_smart_width_smart_sort_reverse_cb);
4276    EINA_LIST_FOREACH(sd->items, l, item)
4277      {
4278         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4279         if (bi->gcc->autoscroll) autosize += bi->ask.size2;
4280      }
4281
4282    if (autosize < 1) autosize = 1;
4283    while (need > 0)
4284      {
4285         needed = need;
4286         EINA_LIST_REVERSE_FOREACH(sd->items, l2, item)
4287           {
4288              if (need <= 0) break;
4289              bi = evas_object_data_get(item, "e_gadcon_layout_data");
4290              if (bi->gcc->autoscroll)
4291                {
4292                   int reduce_by;
4293
4294                   reduce_by = (need * bi->ask.size2) / autosize;
4295                   if (reduce_by < 1) reduce_by = 1;
4296                   if (bi->ask.size2 - reduce_by > 8)
4297                     {
4298                        bi->ask.size2 -= reduce_by;
4299                        need -= reduce_by;
4300                     }
4301                   else
4302                     {
4303                        need -= bi->ask.size2 - 8;
4304                        bi->ask.size2 = 8;
4305                     }
4306                }
4307           }
4308         /* If the 'needed' size change didn't get modified (no gadget has autoscroll)
4309            then we must break or we end up in an infinite loop */
4310         if (need == needed) break;
4311      }
4312 }
4313
4314 static int
4315 _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2)
4316 {
4317    const E_Gadcon_Layout_Item *bi, *bi2;
4318
4319    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4320    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4321
4322    if ((!bi->gcc->state_info.seq) && (!bi2->gcc->state_info.seq)) return 0;
4323    else if (!bi->gcc->state_info.seq)
4324      return 1;
4325    else if (!bi2->gcc->state_info.seq)
4326      return -1;
4327    return bi->gcc->state_info.seq - bi2->gcc->state_info.seq;
4328 }
4329
4330 static int
4331 _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2)
4332 {
4333    const E_Gadcon_Layout_Item *bi, *bi2;
4334
4335    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4336    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4337
4338    return bi->x - bi2->x;
4339 }
4340
4341 static int
4342 _e_gadcon_layout_smart_containers_sort_cb(const void *d1, const void *d2)
4343 {
4344    const E_Layout_Item_Container *lc, *lc2;
4345
4346    lc = d1;
4347    lc2 = d2;
4348    if (lc->pos < lc2->pos) return -1;
4349    else if (lc->pos > lc2->pos)
4350      return 1;
4351    return 0;
4352 }
4353
4354 static int
4355 _e_gadcon_layout_smart_seq_sort_cb(const void *d1, const void *d2)
4356 {
4357    const E_Gadcon_Layout_Item *bi, *bi2;
4358
4359    bi = d1;
4360    bi2 = d2;
4361    return bi->gcc->state_info.seq - bi2->gcc->state_info.seq;
4362 }
4363
4364 static void
4365 _e_gadcon_layout_smart_sync_clients(E_Gadcon *gc)
4366 {
4367    E_Gadcon_Client *gcc;
4368    Eina_List *l;
4369
4370    EINA_LIST_FOREACH(gc->clients, l, gcc)
4371      {
4372         _e_gadcon_client_save(gcc);
4373      }
4374 }
4375
4376 static void
4377 _e_gadcon_client_current_position_sync(E_Gadcon_Client *gcc)
4378 {
4379    E_Gadcon_Layout_Item *bi;
4380    Evas_Object *o;
4381
4382    o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
4383    if (o)
4384      {
4385         bi = evas_object_data_get(o, "e_gadcon_layout_data");
4386         if (!bi) return;
4387      }
4388    else return;  /* make clang happy */
4389
4390    gcc->state_info.prev_pos = gcc->config.pos;
4391    gcc->state_info.prev_size = gcc->config.size;
4392    gcc->config.pos = bi->x;
4393 }
4394
4395 static void
4396 _e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data *sd)
4397 {
4398    Eina_List *l;
4399    Evas_Object *item;
4400    E_Gadcon_Layout_Item *bi, *bi2;
4401    void *tp;
4402    int pos = 0;
4403
4404    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
4405                               _e_gadcon_layout_smart_sort_by_sequence_number_cb);
4406    EINA_LIST_FOREACH(sd->items, l, item)
4407      {
4408         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4409         if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC)
4410           {
4411              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4412                {
4413                   bi->gcc->state_info.resist++;
4414                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4415                }
4416              else
4417                {
4418                   bi->gcc->state_info.resist = 0;
4419                   if (eina_list_next(l))
4420                     {
4421                        tp = eina_list_data_get(eina_list_next(l));
4422                        l->next->data = eina_list_data_get(l);
4423                        l->data = tp;
4424
4425                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
4426
4427                        if (bi2->x + bi2->w / 2 > bi->ask.pos + bi->w)
4428                          {
4429                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4430                             return;
4431                          }
4432
4433                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
4434                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4435                        bi->gcc->state_info.want_save = 1;
4436                        bi2->gcc->state_info.want_save = 1;
4437                        break;
4438                     }
4439                   else
4440                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4441                }
4442           }
4443         else if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC)
4444           {
4445              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4446                {
4447                   bi->gcc->state_info.resist++;
4448                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4449                }
4450              else
4451                {
4452                   bi->gcc->state_info.resist = 0;
4453                   if (eina_list_prev(l))
4454                     {
4455                        tp = eina_list_data_get(eina_list_prev(l));
4456                        l->prev->data = eina_list_data_get(l);
4457
4458                        l->data = tp;
4459                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
4460
4461                        if (bi->ask.pos > bi2->x + bi2->w / 2)
4462                          {
4463                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4464                             return;
4465                          }
4466
4467                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
4468                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4469                        bi->gcc->state_info.want_save = 1;
4470                        bi2->gcc->state_info.want_save = 1;
4471                        break;
4472                     }
4473                   else
4474                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4475                }
4476           }
4477         else if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC) ||
4478                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC) ||
4479                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC) ||
4480                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC))
4481           {
4482              if (bi->w < bi->min.w)
4483                bi->gcc->config.size = bi->w = bi->min.w;
4484              else
4485                bi->gcc->config.size = bi->w;
4486
4487              bi->gcc->config.pos = bi->gcc->state_info.prev_pos;
4488           }
4489      }
4490
4491    EINA_LIST_FOREACH(sd->items, l, item)
4492      {
4493         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4494
4495         bi->x = pos;
4496         bi->w = bi->ask.size2;
4497         bi->gcc->config.size = bi->w;
4498         pos = bi->x + bi->w;
4499      }
4500 }
4501
4502 static void
4503 _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
4504 {
4505    E_Gadcon_Layout_Item *bi;
4506    Eina_List *l;
4507    Evas_Object *item;
4508
4509 #if 0
4510    EINA_LIST_FOREACH(sd->items, l, item)
4511      {
4512         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4513         if (!bi) continue;
4514
4515         bi->x = bi->ask.pos;
4516         bi->w = bi->ask.size2;
4517      }
4518 #else
4519    int pos;
4520    EINA_LIST_FOREACH(sd->items, l, item)
4521      {
4522         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4523         if (!bi) continue;
4524
4525         pos = bi->ask.pos + (bi->ask.size / 2);
4526         if (pos < (bi->ask.res / 3))
4527           {
4528              /* hooked to start */
4529              bi->x = bi->ask.pos;
4530              bi->w = bi->ask.size2;
4531              bi->hookp = 0;
4532           }
4533         else if (pos > ((2 * bi->ask.res) / 3))
4534           {
4535              /* hooked to end */
4536              bi->x = (bi->ask.pos - bi->ask.res) + sd->w;
4537              bi->w = bi->ask.size2;
4538              bi->hookp = bi->ask.res;
4539           }
4540         else
4541           {
4542              /* hooked to middle */
4543              if ((bi->ask.pos <= (bi->ask.res / 2)) &&
4544                  ((bi->ask.pos + bi->ask.size2) > (bi->ask.res / 2)))
4545                {
4546                   /* straddles middle */
4547                   if (bi->ask.res > 2)
4548                     bi->x = (sd->w / 2) +
4549                       (((bi->ask.pos + (bi->ask.size2 / 2) -
4550                          (bi->ask.res / 2)) *
4551                         (bi->ask.res / 2)) /
4552                        (bi->ask.res / 2)) - (bi->ask.size2 / 2);
4553                   else
4554                     bi->x = sd->w / 2;
4555                   bi->w = bi->ask.size2;
4556                }
4557              else
4558                {
4559                   /* either side of middle */
4560                   bi->x = (bi->ask.pos - (bi->ask.res / 2)) + (sd->w / 2);
4561                   bi->w = bi->ask.size2;
4562                }
4563              bi->hookp = bi->ask.res / 2;
4564           }
4565      }
4566 #endif
4567 }
4568
4569 /*
4570  * The function returns a list of E_Gadcon_Layout_Item_Container
4571  */
4572 static Eina_List *
4573 _e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data *sd)
4574 {
4575    Eina_List *l, *list = NULL;
4576    Evas_Object *item;
4577    E_Layout_Item_Container *lc;
4578    E_Gadcon_Layout_Item *bi;
4579
4580    EINA_LIST_FOREACH(sd->items, l, item)
4581      {
4582         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4583         lc = E_NEW(E_Layout_Item_Container, 1);
4584         lc->state_info.min_seq = lc->state_info.max_seq = bi->gcc->state_info.seq;
4585         lc->sd = sd;
4586
4587         lc->pos = bi->x;
4588         lc->size = bi->w;
4589
4590         lc->prev_pos = bi->ask.prev_pos;
4591         lc->prev_size = bi->ask.prev_size;
4592
4593         E_LAYOUT_ITEM_CONTAINER_STATE_SET(lc->state, bi->gcc->state_info.state);
4594
4595         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
4596             (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4597           lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4598
4599         lc->items = eina_list_append(lc->items, bi);
4600         list = eina_list_append(list, lc);
4601      }
4602    return list;
4603 }
4604
4605 static void
4606 _e_gadcon_layout_smart_gadcons_position(E_Smart_Data *sd, Eina_List **list)
4607 {
4608    int ok, lc_moving_prev_pos;
4609    Eina_List *l, *l2, *l3;
4610    E_Layout_Item_Container *lc_moving = NULL, *lc_back = NULL, *lc, *lc3;
4611    E_Gadcon_Layout_Item *bi, *bi_moving = NULL;
4612
4613    if ((!list) || (!*list)) return;
4614
4615    EINA_LIST_FOREACH(*list, l, lc_moving)
4616      {
4617         if ((lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4618             (lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
4619           {
4620              lc_back = E_NEW(E_Layout_Item_Container, 1);
4621              lc_back->pos = lc_moving->pos;
4622              lc_back->prev_pos = lc_moving->prev_pos;
4623              lc_back->size = lc_moving->size;
4624              lc_back->prev_size = lc_moving->prev_size;
4625              lc_back->state_info.min_seq = lc_moving->state_info.min_seq;
4626              lc_back->state_info.max_seq = lc_moving->state_info.max_seq;
4627              lc_back->sd = lc_moving->sd;
4628              EINA_LIST_FOREACH(lc_moving->items, l2, lc)
4629                lc_back->items = eina_list_append(lc_back->items, lc);
4630              lc_back->state = lc_moving->state;
4631              bi_moving = eina_list_data_get(lc_back->items);
4632
4633              break;
4634           }
4635         lc_moving = NULL;
4636      }
4637
4638    if (!lc_moving)
4639      {
4640         if (lc_back) LC_FREE(lc_back);
4641         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4642         return;
4643      }
4644
4645    lc_moving_prev_pos = lc_moving->prev_pos;
4646    if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)
4647      {
4648         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4649         EINA_LIST_FOREACH(*list, l, lc)
4650           if (lc == lc_moving) break;
4651
4652         ok = 0;
4653         if ((l) && eina_list_prev(l))
4654           {
4655              lc = eina_list_data_get(eina_list_prev(l));
4656
4657              if (lc_moving->pos < (lc->pos + lc->size))
4658                {
4659                   bi = eina_list_data_get(lc_moving->items);
4660                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4661                     {
4662                        if (lc_moving->prev_pos == (lc->pos + lc->size))
4663                          ok = 1;
4664                        bi->gcc->state_info.resist++;
4665                        lc_moving->pos = lc->pos + lc->size;
4666                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4667                     }
4668                   else
4669                     {
4670                        bi->gcc->state_info.resist = 0;
4671                        if (lc_moving->pos < lc->pos)
4672                          {
4673                             lc_moving->pos = (lc->pos + lc->size) - 1;
4674                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4675                          }
4676                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc_moving);
4677                        if (lc3)
4678                          {
4679                             if (lc_moving->prev_pos == (lc->pos + lc->size))
4680                               ok = 1;
4681
4682                             l->data = lc3;
4683                             *list = eina_list_remove_list(*list, eina_list_prev(l));
4684                             LC_FREE(lc_moving);
4685                             LC_FREE(lc);
4686                             lc_moving = lc3;
4687                          }
4688                     }
4689                }
4690           }
4691         if (!ok)
4692           {
4693              int pos, prev_pos, stop;
4694
4695              EINA_LIST_FOREACH(*list, l, lc)
4696                if (lc == lc_moving) break;
4697
4698              pos = lc_moving->pos + lc_moving->size;
4699              prev_pos = lc_moving_prev_pos;
4700              if ((l) && (eina_list_next(l)))
4701                {
4702                   stop = 0;
4703                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4704                     {
4705                        if (stop) break;
4706                        if (lc->pos != prev_pos) break;
4707                        prev_pos = lc->pos + lc->size;
4708
4709                        EINA_LIST_FOREACH(lc->items, l3, bi)
4710                          {
4711                             if (bi->ask.pos <= pos)
4712                               {
4713                                  bi->x = pos;
4714                                  pos = (bi->x) + (bi->w);
4715                               }
4716                             else if (bi->ask.pos < bi->x)
4717                               {
4718                                  bi->x = bi->ask.pos;
4719                                  pos = (bi->x) + (bi->w);
4720                               }
4721                             else if (bi->ask.pos == bi->x)
4722                               {
4723                                  stop = 1;
4724                                  break;
4725                               }
4726                          }
4727                     }
4728                }
4729           }
4730      }
4731    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
4732      {
4733         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4734         EINA_LIST_FOREACH(*list, l, lc)
4735           if (lc == lc_moving) break;
4736
4737         ok = 0;
4738         if ((l) && eina_list_next(l))
4739           {
4740              lc = eina_list_data_get(eina_list_next(l));
4741
4742              if ((lc_moving->pos + lc_moving->size) > lc->pos)
4743                {
4744                   bi = eina_list_data_get(lc_moving->items);
4745                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4746                     {
4747                        if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4748                          ok = 1;
4749                        bi->gcc->state_info.resist++;
4750                        lc_moving->pos = lc->pos - lc_moving->size;
4751                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4752                     }
4753                   else
4754                     {
4755                        bi->gcc->state_info.resist = 0;
4756                        if ((lc_moving->pos + lc_moving->size) > lc->pos)
4757                          {
4758                             lc_moving->pos = (lc->pos - lc_moving->size) + 1;
4759                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4760                          }
4761                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc_moving, lc);
4762                        if (lc3)
4763                          {
4764                             if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4765                               ok = 1;
4766
4767                             l->data = lc3;
4768                             *list = eina_list_remove_list(*list, eina_list_next(l));
4769                             LC_FREE(lc_moving);
4770                             LC_FREE(lc);
4771                             lc_moving = lc3;
4772                          }
4773                     }
4774                }
4775           }
4776
4777         if (!ok)
4778           {
4779              int pos, prev_pos, stop;
4780
4781              EINA_LIST_FOREACH(*list, l, lc)
4782                if (lc == lc_moving) break;
4783
4784              pos = lc_moving->pos;
4785              prev_pos = lc_moving_prev_pos;
4786
4787              if ((l) && eina_list_prev(l))
4788                {
4789                   stop = 0;
4790                   /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4791                   for (l2 = l->prev; l2; l2 = l2->prev)
4792                     {
4793                        lc = l2->data;
4794
4795                        if (stop) break;
4796                        if ((lc->pos + lc->size) == prev_pos) break;
4797                        prev_pos = lc->pos;
4798
4799                        EINA_LIST_REVERSE_FOREACH(lc->items, l3, bi)
4800                          {
4801                             if ((bi->ask.pos + bi->w) >= pos)
4802                               {
4803                                  bi->x = pos - bi->w;
4804                                  pos = bi->x;
4805                               }
4806                             else if (bi->ask.pos > bi->x)
4807                               {
4808                                  bi->x = bi->ask.pos;
4809                                  pos = bi->x;
4810                               }
4811                             else if (bi->ask.pos == bi->x)
4812                               {
4813                                  stop = 1;
4814                                  break;
4815                               }
4816                          }
4817                     }
4818                }
4819           }
4820      }
4821    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC)
4822      {
4823         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4824         EINA_LIST_FOREACH(*list, l, lc)
4825           if (lc == lc_moving) break;
4826
4827         if ((l) && eina_list_prev(l))
4828           {
4829              int new_pos = 0;
4830
4831              ok = 0;
4832              new_pos = lc_moving->pos;
4833              /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4834              for (l2 = l->prev; l2; l2 = l2->prev)
4835                {
4836                   lc = l2->data;
4837                   if (new_pos >= (lc->pos + lc->size)) break;
4838
4839                   ok = 1;
4840                   new_pos -= lc->size;
4841                }
4842
4843              if (new_pos < 0)
4844                {
4845                   lc_moving->size += new_pos;
4846                   lc_moving->pos -= new_pos;
4847
4848                   bi = eina_list_data_get(lc_moving->items);
4849                   bi->w = lc_moving->size;
4850                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4851
4852                   new_pos = 0;
4853                }
4854
4855              if (ok)
4856                {
4857                   if (!l2) l2 = *list;
4858                   else l2 = eina_list_next(l2);
4859
4860                   EINA_LIST_FOREACH(l2, l2, lc)
4861                     {
4862                        if (l2 == l) break;
4863                        lc->pos = new_pos;
4864                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4865                        EINA_LIST_FOREACH(lc->items, l3, bi)
4866                          {
4867                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4868                          }
4869                        new_pos += lc->size;
4870                     }
4871                }
4872           }
4873         else if ((l) && (!eina_list_prev(l)))
4874           {
4875              if (lc_moving->pos <= 0)
4876                {
4877                   lc_moving->size = lc_moving->prev_size;
4878                   lc_moving->pos = 0;
4879
4880                   bi = eina_list_data_get(lc_moving->items);
4881                   bi->w = lc_moving->size;
4882
4883                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4884                }
4885           }
4886      }
4887    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC)
4888      {
4889         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4890         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4891         if (lc_back) LC_FREE(lc_back);
4892      }
4893    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC)
4894      {
4895         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4896         EINA_LIST_FOREACH(*list, l, lc)
4897           if (lc == lc_moving) break;
4898
4899         if ((l) && eina_list_next(l))
4900           {
4901              Eina_List *stop = NULL;
4902              int new_pos = 0;
4903
4904              ok = 0;
4905              new_pos = lc_moving->pos + lc_moving->size;
4906              EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4907                {
4908                   if (new_pos <= lc->pos)
4909                     {
4910                        stop = l2;
4911                        break;
4912                     }
4913
4914                   ok = 1;
4915                   /* new_pos += lc->size; */
4916                }
4917
4918              if (new_pos > sd->w)
4919                {
4920                   lc_moving->size -= (new_pos - sd->w);
4921                   bi = eina_list_data_get(lc_moving->items);
4922                   bi->w = lc_moving->size;
4923
4924                   new_pos = lc_moving->pos + lc_moving->size;
4925                }
4926
4927              if (ok)
4928                {
4929                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4930                     {
4931                        if (l2 == stop) break;
4932                        lc->pos = new_pos;
4933                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4934                        EINA_LIST_FOREACH(lc->items, l3, bi)
4935                          {
4936                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4937                          }
4938                        new_pos += lc->size;
4939                     }
4940                }
4941           }
4942         else if ((l) && (!eina_list_next(l)))
4943           {
4944              if ((lc_moving->pos + lc_moving->size) >= sd->w)
4945                {
4946                   lc_moving->size = lc_moving->prev_size;
4947                   bi = eina_list_data_get(lc_moving->items);
4948                   bi->w = lc_moving->size;
4949                }
4950           }
4951      }
4952    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC)
4953      {
4954         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4955         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4956         if (lc_back) LC_FREE(lc_back);
4957      }
4958
4959    if (bi_moving)
4960      {
4961         bi_moving->gcc->config.pos = bi_moving->ask.pos = bi_moving->x;
4962         bi_moving->gcc->config.size = bi_moving->w;
4963      }
4964 }
4965
4966 static void
4967 _e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data *sd, Eina_List **list)
4968 {
4969    int ok;
4970    Eina_List *l;
4971    E_Layout_Item_Container *lc, *lc2, *lc3;
4972
4973    *list = eina_list_sort(*list, eina_list_count(*list), _e_gadcon_layout_smart_containers_sort_cb);
4974
4975 __reposition_again:
4976    EINA_LIST_FOREACH(*list, l, lc)
4977      {
4978         if (!eina_list_next(l)) continue;
4979
4980         lc2 = eina_list_data_get(eina_list_next(l));
4981
4982         if (LC_OVERLAP(lc, lc2))
4983           {
4984              lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc2);
4985              if (lc3)
4986                {
4987                   l->data = lc3;
4988                   *list = eina_list_remove_list(*list, eina_list_next(l));
4989                   LC_FREE(lc);
4990                   LC_FREE(lc2);
4991                   goto __reposition_again;
4992                }
4993           }
4994      }
4995
4996    ok = 1;
4997    EINA_LIST_FOREACH(*list, l, lc)
4998      {
4999         if (lc->pos < 0)
5000           {
5001              ok = 0;
5002              lc->pos = 0;
5003              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5004              continue;
5005           }
5006
5007         if (((lc->pos + lc->size) > sd->w) && (lc->size <= sd->w))
5008           {
5009              ok = 0;
5010              lc->pos = sd->w - lc->size;
5011              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5012           }
5013      }
5014    if (!ok)
5015      _e_gadcon_layout_smart_gadcons_position_static(sd, list);
5016 }
5017
5018 static E_Layout_Item_Container *
5019 _e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
5020 {
5021    int create_new = 0;
5022    Eina_List *l;
5023    E_Layout_Item_Container *lc3 = NULL;
5024    E_Layout_Item_Container_State new_state;
5025    E_Gadcon_Layout_Item *bi, *bi2;
5026
5027    if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5028        (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5029      {
5030         if (lc->state_info.max_seq <= lc2->state_info.min_seq)
5031           {
5032              lc2->pos = lc->pos + lc->size;
5033              _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5034           }
5035         else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5036           {
5037              lc->pos = lc2->pos + lc2->size;
5038              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5039           }
5040         else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5041                   (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5042                  ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5043                   (lc2->state_info.min_seq < lc->state_info.max_seq)))
5044           {
5045              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5046           }
5047         create_new = 1;
5048         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5049      }
5050    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5051             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5052      {
5053         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
5054           {
5055              int t;
5056
5057              bi = eina_list_data_get(lc->items);
5058              bi2 = eina_list_data_get(lc2->items);
5059
5060              bi->x = ((bi2->x) + (bi2->w)) - (bi->w);
5061              bi->gcc->config.pos = bi->ask.pos = bi->x;
5062              bi->gcc->config.size = bi->w;
5063              bi2->x = (bi->x) - (bi2->w);
5064
5065              bi2->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
5066
5067              t = bi->gcc->state_info.seq;
5068              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
5069              bi2->gcc->state_info.seq = t;
5070
5071              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5072           }
5073         else if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
5074           {
5075              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5076                {
5077                   lc2->pos = lc->pos + lc->size;
5078                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5079                }
5080              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5081                {
5082                   lc2->pos = lc->pos - lc2->size;
5083                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5084                }
5085              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5086                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5087                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5088                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5089                {
5090                   int shift = 0;
5091
5092                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5093
5094                   EINA_LIST_FOREACH(lc->items, l, bi)
5095                     {
5096                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
5097                          {
5098                             shift = bi->ask.pos - bi->x;
5099                          }
5100
5101                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5102                          break;
5103                     }
5104
5105                   if (shift)
5106                     {
5107                        EINA_LIST_FOREACH(lc->items, l, bi)
5108                          {
5109                             bi->x += shift;
5110
5111                             if (l == lc->items)
5112                               lc->pos = bi->x;
5113                          }
5114                     }
5115                }
5116           }
5117         create_new = 1;
5118         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5119      }
5120    else if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5121             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5122      {
5123         if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
5124           {
5125              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5126                {
5127                   lc->pos = lc2->pos - lc->size;
5128                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5129                }
5130              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5131                {
5132                   lc->pos = lc2->pos + lc2->size;
5133                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5134                }
5135              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5136                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5137                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5138                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5139                {
5140                   int shift = 0;
5141
5142                   EINA_LIST_FOREACH(lc->items, l, bi)
5143                     {
5144                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
5145                          {
5146                             shift = bi->ask.pos - bi->x;
5147                          }
5148
5149                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5150                          break;
5151                     }
5152
5153                   if (shift)
5154                     {
5155                        EINA_LIST_FOREACH(lc->items, l, bi)
5156                          {
5157                             bi->x += shift;
5158
5159                             if (l == lc->items)
5160                               lc->pos = bi->x;
5161                          }
5162                     }
5163                }
5164           }
5165         else if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)
5166           {
5167              int t;
5168
5169              bi = eina_list_last_data_get(lc->items);
5170              bi2 = eina_list_data_get(lc2->items);
5171
5172              bi2->gcc->config.pos = bi2->ask.pos = (bi2->x) = (bi->x);
5173              bi2->gcc->config.size = bi2->w;
5174              bi->x = bi2->x + bi2->w;
5175
5176              t = bi->gcc->state_info.seq;
5177              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
5178              bi2->gcc->state_info.seq = t;
5179
5180              lc->items = eina_list_remove_list(lc->items, eina_list_last(lc->items));
5181              lc->items = eina_list_append(lc->items, bi2);
5182              lc->items = eina_list_append(lc->items, bi);
5183              lc2->items = eina_list_free(lc2->items);
5184              E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc, bi2, 1);
5185              lc2->pos = lc->pos + lc->size;
5186              lc2->size = 0;
5187           }
5188         create_new = 1;
5189         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5190      }
5191    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5192             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5193      {
5194         if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED) &&
5195             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
5196           {
5197              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5198                {
5199                   int move_lc1 = 1;
5200                   int move_lc2 = 1;
5201
5202                   EINA_LIST_FOREACH(lc->items, l, bi)
5203                     {
5204                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5205                          {
5206                             move_lc1 = 0;
5207                             break;
5208                          }
5209                     }
5210                   EINA_LIST_FOREACH(lc2->items, l, bi)
5211                     {
5212                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5213                          {
5214                             move_lc2 = 0;
5215                             break;
5216                          }
5217                     }
5218
5219                   if ((move_lc1) && (!move_lc2))
5220                     {
5221                        lc->pos = lc2->pos - lc->size;
5222                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5223                     }
5224                   else
5225                     {
5226                        lc2->pos = lc->pos + lc->size;
5227                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5228                     }
5229                }
5230              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5231                {
5232                   int move_lc1 = 1;
5233                   int move_lc2 = 1;
5234
5235                   EINA_LIST_FOREACH(lc->items, l, bi)
5236                     {
5237                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5238                          {
5239                             move_lc1 = 0;
5240                             break;
5241                          }
5242                     }
5243                   EINA_LIST_FOREACH(lc2->items, l, bi)
5244                     {
5245                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5246                          {
5247                             move_lc2 = 0;
5248                             break;
5249                          }
5250                     }
5251
5252                   if ((!move_lc1) && (move_lc2))
5253                     {
5254                        lc2->pos = lc->pos - lc2->size;
5255                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5256                     }
5257                   else
5258                     {
5259                        lc->pos = lc2->pos + lc2->size;
5260                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5261                     }
5262                }
5263              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5264                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5265                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5266                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5267                {
5268                   int shift = 0;
5269
5270                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5271
5272                   EINA_LIST_FOREACH(lc->items, l, bi)
5273                     {
5274                        if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
5275                            (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
5276                          {
5277                             shift = bi->ask.pos - bi->x;
5278                             break;
5279                          }
5280                     }
5281
5282                   if (shift)
5283                     {
5284                        EINA_LIST_FOREACH(lc->items, l, bi)
5285                          {
5286                             bi->x += shift;
5287
5288                             if (l == lc->items)
5289                               lc->pos = bi->x;
5290                          }
5291                     }
5292                }
5293              create_new = 1;
5294              new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5295           }
5296      }
5297
5298    if (create_new)
5299      {
5300         lc3 = E_NEW(E_Layout_Item_Container, 1);
5301         lc3->sd = sd;
5302         if (lc->pos < lc2->pos)
5303           {
5304              lc3->pos = lc->pos;
5305              EINA_LIST_FOREACH(lc->items, l, bi)
5306                lc3->items = eina_list_append(lc3->items, bi);
5307              EINA_LIST_FOREACH(lc2->items, l, bi)
5308                lc3->items = eina_list_append(lc3->items, bi);
5309
5310              lc3->state_info.min_seq = lc->state_info.min_seq;
5311              if (lc2->items)
5312                lc3->state_info.max_seq = lc2->state_info.max_seq;
5313              else
5314                lc3->state_info.max_seq = lc->state_info.max_seq;
5315           }
5316         else
5317           {
5318              lc3->pos = lc2->pos;
5319              EINA_LIST_FOREACH(lc2->items, l, bi)
5320                lc3->items = eina_list_append(lc3->items, bi);
5321              EINA_LIST_FOREACH(lc->items, l, bi)
5322                lc3->items = eina_list_append(lc3->items, bi);
5323
5324              lc3->state_info.min_seq = lc2->state_info.min_seq;
5325              if (lc->items)
5326                lc3->state_info.max_seq = lc->state_info.max_seq;
5327              else
5328                lc3->state_info.max_seq = lc2->state_info.max_seq;
5329           }
5330         lc3->size = lc->size + lc2->size;
5331         lc3->state = new_state;
5332      }
5333
5334    return lc3;
5335 }
5336
5337 static void
5338 _e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data *sd __UNUSED__, E_Layout_Item_Container *lc)
5339 {
5340    int shift;
5341    Eina_List *l;
5342    E_Gadcon_Layout_Item *bi;
5343
5344    if (!lc->items) return;
5345
5346    bi = eina_list_data_get(lc->items);
5347    shift = lc->pos - bi->x;
5348
5349    if (!shift) return;
5350
5351    EINA_LIST_FOREACH(lc->items, l, bi)
5352      {
5353         bi->x += shift;
5354
5355         if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC) ||
5356             (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC))
5357           {
5358              bi->gcc->config.pos = bi->ask.pos = bi->x;
5359           }
5360      }
5361 }
5362
5363 static void
5364 _e_gadcon_layout_smart_containers_merge(E_Smart_Data *sd __UNUSED__, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
5365 {
5366    int start = 0, size = 0, next = 0, min_seq = 0, max_seq = 0;
5367    Eina_List *l, *nl = NULL;
5368    E_Gadcon_Layout_Item *bi;
5369
5370    EINA_LIST_FOREACH(lc->items, l, bi)
5371      nl = eina_list_append(nl, bi);
5372    EINA_LIST_FOREACH(lc2->items, l, bi)
5373      nl = eina_list_append(nl, bi);
5374
5375    nl = eina_list_sort(nl, eina_list_count(nl), _e_gadcon_layout_smart_seq_sort_cb);
5376
5377    EINA_LIST_FOREACH(nl, l, bi)
5378      {
5379         if (l == nl)
5380           {
5381              min_seq = max_seq = bi->gcc->state_info.seq;
5382              start = bi->x;
5383              size = bi->w;
5384              next = bi->x + bi->w;
5385
5386              continue;
5387           }
5388
5389         max_seq = bi->gcc->state_info.seq;
5390
5391         bi->x = next;
5392         size += bi->w;
5393         next = bi->x + bi->w;
5394      }
5395
5396    lc->items = eina_list_free(lc->items);
5397    lc2->items = eina_list_free(lc->items);
5398    lc->items = nl;
5399    lc->pos = start;
5400    lc->size = size;
5401    lc->state_info.min_seq = min_seq;
5402    lc->state_info.max_seq = max_seq;
5403    lc2->pos = lc->pos + lc->size;
5404    lc2->size = 0;
5405 }
5406
5407 static void
5408 _e_gadcon_layout_smart_restore_gadcons_position_before_move(E_Smart_Data *sd, E_Layout_Item_Container **lc_moving, E_Layout_Item_Container *lc_back, Eina_List **con_list)
5409 {
5410    int ok;
5411    Eina_List *l, *l2, *l3;
5412    E_Gadcon_Layout_Item *bi, *bi2;
5413    E_Layout_Item_Container *lc, *lc2, *lc3;
5414
5415    (*lc_moving)->pos = (*lc_moving)->prev_pos;
5416    if (((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC) ||
5417        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC) ||
5418        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC) ||
5419        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC))
5420      {
5421         (*lc_moving)->size = (*lc_moving)->prev_size;
5422         bi = eina_list_data_get((*lc_moving)->items);
5423
5424         bi->w = (*lc_moving)->prev_size;
5425      }
5426    _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
5427    (*lc_moving)->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5428    _e_gadcon_layout_smart_gadcons_position_static(sd, con_list);
5429
5430    lc2 = NULL;
5431    lc3 = NULL;
5432    ok = 0;
5433    EINA_LIST_FOREACH(*con_list, l, lc)
5434      {
5435         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) continue;
5436
5437         if (eina_list_count(lc->items) == 1)
5438           {
5439              bi = eina_list_data_get(lc->items);
5440              if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
5441                {
5442                   LC_FREE(lc);
5443                   l->data = *lc_moving = lc_back;
5444                   _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
5445
5446                   if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) &&
5447                       ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC))
5448                     {
5449                        bi = eina_list_data_get((*lc_moving)->items);
5450                        bi->w = (*lc_moving)->size;
5451                     }
5452                }
5453           }
5454         else
5455           {
5456              EINA_LIST_FOREACH(lc->items, l2, bi)
5457                {
5458                   if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
5459                     {
5460                        ok = 1;
5461                        if (l2 != lc->items)
5462                          {
5463                             lc2 = E_NEW(E_Layout_Item_Container, 1);
5464                             lc2->sd = sd;
5465                             lc2->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5466                             EINA_LIST_FOREACH(lc->items, l3, bi2)
5467                               {
5468                                  if (l2 == l3) break;
5469                                  lc2->items = eina_list_append(lc2->items, bi2);
5470                                  if (l3 == lc->items)
5471                                    {
5472                                       lc2->state_info.min_seq = bi2->gcc->state_info.seq;
5473                                       lc2->pos = lc2->prev_pos = bi2->x;
5474                                    }
5475                                  lc2->state_info.max_seq = bi2->gcc->state_info.seq;
5476                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc2, bi2, 1);
5477                               }
5478                          }
5479
5480                        if (eina_list_next(l2))
5481                          {
5482                             lc3 = E_NEW(E_Layout_Item_Container, 1);
5483                             lc3->sd = sd;
5484                             lc3->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5485                             EINA_LIST_FOREACH(eina_list_next(l2), l3, bi2)
5486                               {
5487                                  lc3->items = eina_list_append(lc3->items, bi2);
5488                                  if (l3 == eina_list_next(l2))
5489                                    {
5490                                       lc3->state_info.min_seq = bi2->gcc->state_info.seq;
5491                                       lc3->pos = lc3->prev_pos = bi2->x;
5492                                    }
5493                                  lc3->state_info.max_seq = bi2->gcc->state_info.seq;
5494                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc3, bi2, 1);
5495                               }
5496                          }
5497                        *lc_moving = lc_back;
5498                        _e_gadcon_layout_smart_position_items_inside_container(sd, *lc_moving);
5499
5500                        if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) &&
5501                            ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC))
5502                          {
5503                             bi = eina_list_data_get((*lc_moving)->items);
5504                             bi->w = (*lc_moving)->size;
5505                          }
5506                        break;
5507                     }
5508                }
5509              if (ok)
5510                {
5511                   LC_FREE(lc);
5512                   if (lc2)
5513                     {
5514                        l->data = lc2;
5515                        *con_list = eina_list_append(*con_list, *lc_moving);
5516                        if (lc3)
5517                          *con_list = eina_list_append(*con_list, lc3);
5518                        *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
5519                                                   _e_gadcon_layout_smart_containers_sort_cb);
5520                     }
5521                   else
5522                     {
5523                        l->data = *lc_moving;
5524                        if (lc3)
5525                          {
5526                             *con_list = eina_list_append(*con_list, lc3);
5527                             *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
5528                                                        _e_gadcon_layout_smart_containers_sort_cb);
5529                          }
5530                     }
5531                   break;
5532                }
5533           }
5534      }
5535
5536    EINA_LIST_FOREACH(*con_list, l, lc)
5537      {
5538         if (lc == *lc_moving) continue;
5539         lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5540      }
5541 }
5542
5543 static void
5544 _e_gadcon_event_populate_free(void *data __UNUSED__, void *event)
5545 {
5546    E_Event_Gadcon_Populate *ev = event;
5547
5548    e_object_unref(E_OBJECT(ev->gc));
5549    free(ev);
5550 }
5551
5552 static void
5553 _e_gadcon_custom_populate_job(void *data __UNUSED__)
5554 {
5555    const E_Gadcon_Client_Class *cc;
5556    E_Config_Gadcon_Client *cf_gcc;
5557    Eina_List *l, *ll;
5558    E_Gadcon *gc;
5559
5560 #ifndef E19_RELEASE_BUILD
5561    static Eina_Bool first = EINA_TRUE;
5562    if (first)
5563      e_main_ts("gadcon custom populate idler start");
5564 #endif
5565    EINA_LIST_FREE(custom_populate_requests, gc)
5566      {
5567         if (!gc->cf) continue;
5568         e_gadcon_layout_freeze(gc->o_container);
5569         EINA_LIST_FOREACH_SAFE(gc->cf->clients, l, ll, cf_gcc)
5570           {
5571              if ((!cf_gcc->name) || (!cf_gcc->name[0]) || (!cf_gcc->id) || (!cf_gcc->id[0]))
5572                {
5573                   e_gadcon_client_config_del(gc->cf, cf_gcc);
5574                   continue;
5575                }
5576              cc = eina_hash_find(providers, cf_gcc->name);
5577              if (!cc) continue;
5578              if (gc->populate_class.func)
5579                gc->populate_class.func(gc->populate_class.data, gc, cc);
5580              else
5581                e_gadcon_populate_class(gc, cc);
5582           }
5583         e_gadcon_layout_thaw(gc->o_container);
5584         _e_gadcon_event_populate(gc);
5585      }
5586
5587 #ifndef E19_RELEASE_BUILD
5588    if (first)
5589      e_main_ts("gadcon custom populate idler end");
5590 #endif
5591    if (!custom_populate_requests)
5592      {
5593         custom_populate_job = NULL;
5594 #ifndef E19_RELEASE_BUILD
5595         first = EINA_FALSE;
5596 #endif
5597      }
5598 }
5599
5600 static void
5601 _e_gadcon_provider_populate_job(void *data __UNUSED__)
5602 {
5603    E_Gadcon_Client_Class *cc;
5604    Eina_List *l;
5605    E_Gadcon *gc;
5606
5607 #ifndef E19_RELEASE_BUILD
5608    static Eina_Bool first = EINA_TRUE;
5609    if (first)
5610      e_main_ts("gadcon populate idler start");
5611 #endif
5612    EINA_LIST_FOREACH(gadcons, l, gc)
5613      {
5614         int x = 0;
5615         Eina_Bool freeze = EINA_FALSE;
5616         if (gc->populate_requests)
5617           {
5618              freeze = EINA_TRUE;
5619              e_gadcon_layout_freeze(gc->o_container);
5620           }
5621         EINA_LIST_FREE(gc->populate_requests, cc)
5622           {
5623 #ifndef E19_RELEASE_BUILD
5624              if (first) e_main_ts(cc->name);
5625 #endif
5626              if (gc->populate_class.func)
5627                gc->populate_class.func(gc->populate_class.data, gc, cc);
5628              else
5629                e_gadcon_populate_class(gc, cc);
5630              if (!eina_list_data_find(gc->populated_classes, cc))
5631                {
5632                   gc->populated_classes = eina_list_append(gc->populated_classes, cc);
5633                   if (gc->cf)
5634                     {
5635                        Eina_List *ll;
5636                        E_Config_Gadcon_Client *cf_gcc;
5637
5638                        if (!gc->awaiting_classes) continue;
5639                        ll = eina_hash_set(gc->awaiting_classes, cc->name, NULL);
5640                        EINA_LIST_FREE(ll, cf_gcc)
5641                          _e_gadcon_client_populate(gc, cc, cf_gcc);
5642                     }
5643                }
5644              x++;
5645           }
5646         if (freeze) e_gadcon_layout_thaw(gc->o_container);
5647         if (x && _modules_loaded) _e_gadcon_event_populate(gc);
5648      }
5649 //out:
5650 #ifndef E19_RELEASE_BUILD
5651    if (first)
5652      e_main_ts("gadcon populate idler end");
5653 #endif
5654
5655    populate_job = NULL;
5656 #ifndef E19_RELEASE_BUILD
5657    first = EINA_FALSE;
5658 #endif
5659 }
5660
5661 static void
5662 _e_gadcon_provider_populate_request(E_Gadcon *gc, const E_Gadcon_Client_Class *cc)
5663 {
5664    if (eina_list_data_find(gc->populate_requests, cc)) return;
5665    gc->populate_requests = eina_list_append(gc->populate_requests, cc);
5666    if (populate_job) ecore_job_del(populate_job);
5667    populate_job = ecore_job_add(_e_gadcon_provider_populate_job, NULL);
5668 }
5669
5670 static void
5671 _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc)
5672 {
5673    E_Gadcon *gc;
5674    Eina_List *l;
5675    unsigned int more = 0;
5676    EINA_LIST_FOREACH(gadcons, l, gc)
5677      {
5678         gc->populate_requests = eina_list_remove(gc->populate_requests, cc);
5679         more += eina_list_count(gc->populate_requests);
5680      }
5681    if ((!more) && (populate_job))
5682      {
5683         ecore_job_del(populate_job);
5684         populate_job = NULL;
5685      }
5686 }
5687
5688 /* gadgets movement between different gadcons */
5689
5690 EAPI E_Gadcon_Location *
5691 e_gadcon_location_new(const char *name,
5692                       E_Gadcon_Site site,
5693                       int (*add_func)(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc),
5694                       void *add_data,
5695                       void (*remove_func)(void *data, E_Gadcon_Client *cc),
5696                       void *remove_data)
5697 {
5698    E_Gadcon_Location *loc;
5699
5700    loc = E_NEW(E_Gadcon_Location, 1);
5701    loc->name = eina_stringshare_add(name);
5702    loc->site = site;
5703    loc->gadget_add.func = add_func;
5704    loc->gadget_add.data = add_data;
5705    loc->gadget_remove.func = remove_func;
5706    loc->gadget_remove.data = remove_data;
5707    loc->icon_name = NULL;
5708    return loc;
5709 }
5710
5711 EAPI void
5712 e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name)
5713 {
5714    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5715    if (name)
5716      loc->icon_name = eina_stringshare_add(name);
5717    else
5718      loc->icon_name = NULL;
5719 }
5720
5721 EAPI void
5722 e_gadcon_location_free(E_Gadcon_Location *loc)
5723 {
5724    eina_stringshare_del(loc->name);
5725    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5726    free(loc);
5727 }
5728
5729 EAPI void
5730 e_gadcon_location_register(E_Gadcon_Location *loc)
5731 {
5732    gadcon_locations = eina_list_append(gadcon_locations, loc);
5733 }
5734
5735 EAPI void
5736 e_gadcon_location_unregister(E_Gadcon_Location *loc)
5737 {
5738    gadcon_locations = eina_list_remove(gadcon_locations, loc);
5739 }
5740
5741 static int
5742 _e_gadcon_location_change(E_Gadcon_Client *gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst)
5743 {
5744    E_Gadcon_Client_Class *cc;
5745
5746    cc = eina_hash_find(providers, gcc->cf->name);
5747    if (!cc) return 0;
5748    if (!dst->gadget_add.func(dst->gadget_add.data, gcc, cc)) return 0;
5749    gcc->cf = NULL;
5750    src->gadget_remove.func(src->gadget_remove.data, gcc);
5751    return 1;
5752 }
5753
5754 EAPI Eina_Bool
5755 e_gadcon_client_visible_get(const E_Gadcon_Client *gcc, const E_Desk *desk)
5756 {
5757    const Eina_List *l, *ll;
5758    E_Comp *c;
5759    E_Zone *zone;
5760
5761    if (!gcc->gadcon) return EINA_FALSE;
5762    switch (gcc->gadcon->location->site)
5763      {
5764       case E_GADCON_SITE_DESKTOP:
5765         return EINA_TRUE; // FIXME for when gadman allows per-desk gadgets
5766       case E_GADCON_SITE_SHELF:
5767         if (desk) return e_shelf_desk_visible(gcc->gadcon->shelf, desk);
5768         EINA_LIST_FOREACH(e_comp_list(), l, c)
5769           EINA_LIST_FOREACH(c->zones, ll, zone)
5770             if (e_shelf_desk_visible(gcc->gadcon->shelf, e_desk_current_get(zone)))
5771               return EINA_TRUE;
5772       case E_GADCON_SITE_TOOLBAR:
5773       case E_GADCON_SITE_EFM_TOOLBAR:
5774         if (desk) return (gcc->gadcon->toolbar->fwin->client->desk == desk);
5775         EINA_LIST_FOREACH(e_comp_list(), l, c)
5776           EINA_LIST_FOREACH(c->zones, ll, zone)
5777             if (gcc->gadcon->toolbar->fwin->client->desk == e_desk_current_get(zone)) return EINA_TRUE;
5778       default:
5779         break;
5780      }
5781    return EINA_FALSE;
5782 }