the repository of RSA merge with private repository.
[platform/core/uifw/e17.git] / src / bin / e_shelf.c
1 #include "e.h"
2
3 static void         _e_shelf_new_dialog_ok(void *data, char *text);
4 static void         _e_shelf_del_cb(void *d);
5 static void         _e_shelf_free(E_Shelf *es);
6 static void         _e_shelf_gadcon_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h);
7 static void         _e_shelf_gadcon_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h);
8 static Evas_Object *_e_shelf_gadcon_frame_request(void *data, E_Gadcon_Client *gcc, const char *style);
9 static void         _e_shelf_toggle_border_fix(E_Shelf *es);
10 static void         _e_shelf_cb_menu_config(void *data, E_Menu *m, E_Menu_Item *mi);
11 static void         _e_shelf_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
12 static void         _e_shelf_cb_menu_contents(void *data, E_Menu *m, E_Menu_Item *mi);
13 static void         _e_shelf_cb_confirm_dialog_yes(void *data);
14 static void         _e_shelf_cb_menu_delete(void *data, E_Menu *m, E_Menu_Item *mi);
15 static void         _e_shelf_menu_append(E_Shelf *es, E_Menu *mn);
16 static void         _e_shelf_cb_menu_items_append(void *data, E_Gadcon_Client *gcc, E_Menu *mn);
17 static void         _e_shelf_cb_locked_set(void *data, int lock);
18 static void         _e_shelf_cb_urgent_show(void *data);
19 static void         _e_shelf_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
20 static Eina_Bool    _e_shelf_cb_mouse_in(void *data, int type, void *event);
21 //static Eina_Bool    _e_shelf_cb_mouse_out(void *data, int type, void *event);
22 //static void          _e_shelf_cb_mouse_out2(E_Shelf *es, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Out *ev);
23 static int          _e_shelf_cb_id_sort(const void *data1, const void *data2);
24 static void         _e_shelf_cb_menu_rename(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__);
25 static Eina_Bool    _e_shelf_cb_hide_animator(void *data);
26 static Eina_Bool    _e_shelf_cb_hide_animator_timer(void *data);
27 static Eina_Bool    _e_shelf_cb_hide_urgent_timer(void *data);
28 static Eina_Bool    _e_shelf_cb_instant_hide_timer(void *data);
29 static void         _e_shelf_menu_pre_cb(void *data, E_Menu *m);
30 static void         _e_shelf_gadcon_client_remove(void *data, E_Gadcon_Client *gcc);
31 static int          _e_shelf_gadcon_client_add(void *data, const E_Gadcon_Client_Class *cc);
32 static const char  *_e_shelf_orient_icon_name_get(E_Shelf *s);
33 static void         _e_shelf_bindings_add(E_Shelf *es);
34 static void         _e_shelf_bindings_del(E_Shelf *es);
35 static Eina_Bool    _e_shelf_on_current_desk(E_Shelf *es, E_Event_Zone_Edge *ev);
36 static void          _e_shelf_cb_dummy_del(E_Shelf *, Evas *e, Evas_Object *obj, void *event_info);
37 static void          _e_shelf_cb_dummy_moveresize(E_Shelf *, Evas *e, Evas_Object *obj, void *event_info);
38
39 static Eina_List *shelves = NULL;
40 static Eina_List *dummies = NULL;
41 static Eina_Hash *winid_shelves = NULL;
42
43 static int orientations[] =
44 {
45    [E_GADCON_ORIENT_FLOAT] = 2,
46    [E_GADCON_ORIENT_HORIZ] = 2,
47    [E_GADCON_ORIENT_VERT] = 2,
48    [E_GADCON_ORIENT_LEFT] = 37,
49    [E_GADCON_ORIENT_RIGHT] = 31,
50    [E_GADCON_ORIENT_TOP] = 29,
51    [E_GADCON_ORIENT_BOTTOM] = 23,
52    [E_GADCON_ORIENT_CORNER_TL] = 19,
53    [E_GADCON_ORIENT_CORNER_TR] = 17,
54    [E_GADCON_ORIENT_CORNER_BL] = 13,
55    [E_GADCON_ORIENT_CORNER_BR] = 11,
56    [E_GADCON_ORIENT_CORNER_LT] = 7,
57    [E_GADCON_ORIENT_CORNER_RT] = 5,
58    [E_GADCON_ORIENT_CORNER_LB] = 3,
59    [E_GADCON_ORIENT_CORNER_RB] = 2
60 };
61
62 static const char *orient_names[] =
63 {
64    [E_GADCON_ORIENT_FLOAT] = "Float",
65    [E_GADCON_ORIENT_HORIZ] = "Horizontal",
66    [E_GADCON_ORIENT_VERT] = "Vertical",
67    [E_GADCON_ORIENT_LEFT] = "Left",
68    [E_GADCON_ORIENT_RIGHT] = "Right",
69    [E_GADCON_ORIENT_TOP] = "Top",
70    [E_GADCON_ORIENT_BOTTOM] = "Bottom",
71    [E_GADCON_ORIENT_CORNER_TL] = "Top-left Corner",
72    [E_GADCON_ORIENT_CORNER_TR] = "Top-right Corner",
73    [E_GADCON_ORIENT_CORNER_BL] = "Bottom-left Corner",
74    [E_GADCON_ORIENT_CORNER_BR] = "Bottom-right Corner",
75    [E_GADCON_ORIENT_CORNER_LT] = "Left-top Corner",
76    [E_GADCON_ORIENT_CORNER_RT] = "Right-top Corner",
77    [E_GADCON_ORIENT_CORNER_LB] = "Left-bottom Corner",
78    [E_GADCON_ORIENT_CORNER_RB] = "Right-bottom Corner"
79 };
80
81 EAPI int E_EVENT_SHELF_ADD = -1;
82 EAPI int E_EVENT_SHELF_DEL = -1;
83
84 /* externally accessible functions */
85 EINTERN int
86 e_shelf_init(void)
87 {
88    E_EVENT_SHELF_ADD = ecore_event_type_new();
89    E_EVENT_SHELF_DEL = ecore_event_type_new();
90    return 1;
91 }
92
93 EINTERN int
94 e_shelf_shutdown(void)
95 {
96    if (x_fatal) return 1;
97    while (shelves)
98      {
99         E_Shelf *es;
100
101         es = eina_list_data_get(shelves);
102         e_object_del(E_OBJECT(es));
103      }
104
105    return 1;
106 }
107
108 EAPI void
109 e_shelf_config_update(void)
110 {
111    Eina_List *l;
112    E_Config_Shelf *cf_es;
113    int id = 0;
114
115    while (shelves)
116      {
117         E_Shelf *es;
118
119         es = eina_list_data_get(shelves);
120         e_object_del(E_OBJECT(es));
121      }
122
123    EINA_LIST_FOREACH(e_config->shelves, l, cf_es)
124      {
125         E_Zone *zone;
126
127         if (cf_es->id <= 0) cf_es->id = id + 1;
128         zone = e_util_container_zone_number_get(cf_es->container, cf_es->zone);
129         if (zone)
130           e_shelf_config_new(zone, cf_es);
131         id = cf_es->id;
132      }
133 }
134
135 EAPI Eina_List *
136 e_shelf_list_all(void)
137 {
138    Eina_List *d = NULL, *s = NULL, *ret = NULL;
139
140    if (shelves)
141      s = eina_list_clone(shelves);
142    if (dummies)
143      d = eina_list_clone(dummies);
144    if (s && d)
145      ret = eina_list_merge(s, d);
146    else
147      ret = d ?: s;
148    return ret;
149 }
150
151 EAPI Eina_List *
152 e_shelf_list(void)
153 {
154    shelves = eina_list_sort(shelves, -1, _e_shelf_cb_id_sort);
155    return shelves;
156 }
157
158 EAPI E_Shelf *
159 e_shelf_zone_dummy_new(E_Zone *zone, Evas_Object *obj, int id)
160 {
161    E_Shelf *es;
162
163    es = E_OBJECT_ALLOC(E_Shelf, E_SHELF_DUMMY_TYPE, _e_shelf_free);
164    if (!es) return NULL;
165    es->id = id;
166    evas_object_geometry_get(obj, &es->x, &es->y, &es->w, &es->h);
167    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, 
168                                   (Evas_Object_Event_Cb)_e_shelf_cb_dummy_del, es);
169    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, 
170                                   (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es);
171    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, 
172                                   (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es);
173    es->zone = zone;
174    es->dummy = 1;
175    es->o_base = obj;
176    es->cfg = E_NEW(E_Config_Shelf, 1);
177    
178    e_object_del_attach_func_set(E_OBJECT(es), _e_shelf_del_cb);
179    dummies = eina_list_append(dummies, es);
180
181    return es;
182 }
183
184 EAPI E_Shelf *
185 e_shelf_zone_new(E_Zone *zone, const char *name, const char *style, int popup, int layer, int id)
186 {
187    E_Shelf *es;
188    char buf[1024];
189    const char *locname;
190
191    es = E_OBJECT_ALLOC(E_Shelf, E_SHELF_TYPE, _e_shelf_free);
192    if (!es) return NULL;
193    es->id = id;
194    es->x = 0;
195    es->y = 0;
196    es->w = 32;
197    es->h = 32;
198    es->zone = zone;
199    e_object_del_attach_func_set(E_OBJECT(es), _e_shelf_del_cb);
200    e_zone_useful_geometry_dirty(zone);
201    if (popup)
202      {
203         es->popup = e_popup_new(zone, es->x, es->y, es->w, es->h);
204         e_popup_name_set(es->popup, "shelf");
205         e_popup_layer_set(es->popup, layer);
206         es->ee = es->popup->ecore_evas;
207         es->evas = es->popup->evas;
208      }
209    else
210      {
211         es->ee = zone->container->bg_ecore_evas;
212         es->evas = zone->container->bg_evas;
213      }
214    es->fit_along = 1;
215    es->layer = layer;
216
217    es->o_event = evas_object_rectangle_add(es->evas);
218    evas_object_color_set(es->o_event, 0, 0, 0, 0);
219    evas_object_resize(es->o_event, es->w, es->h);
220    evas_object_event_callback_add(es->o_event, EVAS_CALLBACK_MOUSE_DOWN, 
221                                   _e_shelf_cb_mouse_down, es);
222
223    es->handlers = 
224      eina_list_append(es->handlers,
225                       ecore_event_handler_add(E_EVENT_ZONE_EDGE_MOVE, 
226                                               _e_shelf_cb_mouse_in, es));
227    es->o_base = edje_object_add(es->evas);
228    es->name = eina_stringshare_add(name);
229    evas_object_resize(es->o_base, es->w, es->h);
230    
231    e_shelf_style_set(es, style);
232    
233    if (es->popup)
234      {
235         evas_object_show(es->o_event);
236         evas_object_show(es->o_base);
237         ecore_x_netwm_window_type_set(es->popup->evas_win, 
238                                       ECORE_X_WINDOW_TYPE_DOCK);
239      }
240    else
241      {
242         evas_object_move(es->o_event, es->zone->x + es->x, es->zone->y + es->y);
243         evas_object_move(es->o_base, es->zone->x + es->x, es->zone->y + es->y);
244         evas_object_layer_set(es->o_event, layer);
245         evas_object_layer_set(es->o_base, layer);
246      }
247
248    es->gadcon = 
249      e_gadcon_swallowed_new(es->name, es->id, es->o_base, "e.swallow.content");
250    locname = es->name;
251    if (!name) locname = _("Shelf #");
252    snprintf(buf, sizeof(buf), "%s %i", locname, es->id);
253    es->gadcon->location = 
254      e_gadcon_location_new(buf, E_GADCON_SITE_SHELF, 
255                            _e_shelf_gadcon_client_add, es, 
256                            _e_shelf_gadcon_client_remove, es);
257    e_gadcon_location_register(es->gadcon->location);
258 // hmm dnd in ibar and ibox kill this. ok. need to look into this more
259 //   es->gadcon->instant_edit = 1;
260    e_gadcon_min_size_request_callback_set(es->gadcon,
261                                           _e_shelf_gadcon_min_size_request, es);
262
263    e_gadcon_size_request_callback_set(es->gadcon,
264                                       _e_shelf_gadcon_size_request, es);
265    e_gadcon_frame_request_callback_set(es->gadcon,
266                                        _e_shelf_gadcon_frame_request, es);
267    e_gadcon_orient(es->gadcon, E_GADCON_ORIENT_TOP);
268    snprintf(buf, sizeof(buf), "e,state,orientation,%s",
269             e_shelf_orient_string_get(es));
270    edje_object_signal_emit(es->o_base, buf, "e");
271    edje_object_message_signal_process(es->o_base);
272    e_gadcon_zone_set(es->gadcon, zone);
273    e_gadcon_ecore_evas_set(es->gadcon, es->ee);
274    e_gadcon_shelf_set(es->gadcon, es);
275    if (popup)
276      {
277         if (!winid_shelves)
278           winid_shelves = eina_hash_string_superfast_new(NULL);
279         eina_hash_add(winid_shelves,
280                       e_util_winid_str_get(es->popup->evas_win), es);
281         e_drop_xdnd_register_set(es->popup->evas_win, 1);
282         e_gadcon_xdnd_window_set(es->gadcon, es->popup->evas_win);
283         e_gadcon_dnd_window_set(es->gadcon, es->popup->evas_win);
284      }
285    else
286      {
287         e_drop_xdnd_register_set(es->zone->container->bg_win, 1);
288         e_gadcon_xdnd_window_set(es->gadcon, es->zone->container->bg_win);
289         e_gadcon_dnd_window_set(es->gadcon, es->zone->container->event_win);
290         evas_object_clip_set(es->o_base, es->zone->bg_clip_object);
291      }
292    e_gadcon_util_menu_attach_func_set(es->gadcon,
293                                       _e_shelf_cb_menu_items_append, es);
294
295    e_gadcon_util_lock_func_set(es->gadcon,
296                                _e_shelf_cb_locked_set, es);
297    e_gadcon_util_urgent_show_func_set(es->gadcon,
298                                       _e_shelf_cb_urgent_show, es);
299
300    shelves = eina_list_append(shelves, es);
301
302    es->hidden = 0;
303    es->hide_step = 0;
304    es->locked = 0;
305
306    es->hide_origin = -1;
307
308    {
309       E_Event_Shelf *ev;
310
311       ev = E_NEW(E_Event_Shelf, 1);
312       ev->shelf = es;
313       ecore_event_add(E_EVENT_SHELF_ADD, ev, NULL, NULL);
314    }
315
316    return es;
317 }
318
319 EAPI void
320 e_shelf_rename_dialog(E_Shelf *es)
321 {
322    if (!es) return;
323    if (es->rename_dialog) return;
324    _e_shelf_cb_menu_rename(es, NULL, NULL);
325 }
326
327 EAPI void
328 e_shelf_zone_move_resize_handle(E_Zone *zone)
329 {
330    Eina_List *l;
331    E_Shelf *es;
332    Evas_Coord w, h;
333
334    EINA_LIST_FOREACH(shelves, l, es)
335      {
336         if (es->zone == zone)
337           {
338              E_Gadcon *gc;
339
340              gc = es->gadcon;
341              if (gc->min_size_request.func)
342                {
343                   /* let gadcon container decrease to any size */
344                   edje_extern_object_min_size_set(gc->o_container, 0, 0);
345                }
346              evas_object_smart_callback_call(gc->o_container, "min_size_request", NULL);
347              e_shelf_position_calc(es);
348              if (gc->min_size_request.func)
349                {
350                   evas_object_geometry_get(gc->o_container, NULL, NULL, &w, &h);
351                   /* fix gadcon container min size to current geometry */
352                   edje_extern_object_min_size_set(gc->o_container, w, h);
353                }
354           }
355      }
356 }
357
358 EAPI void
359 e_shelf_populate(E_Shelf *es)
360 {
361    E_OBJECT_CHECK(es);
362    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
363    e_gadcon_populate(es->gadcon);
364 }
365
366 EAPI void
367 e_shelf_show(E_Shelf *es)
368 {
369    E_OBJECT_CHECK(es);
370    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
371    if (es->popup)
372      e_popup_show(es->popup);
373    else
374      {
375         evas_object_show(es->o_event);
376         evas_object_show(es->o_base);
377      }
378 }
379
380 EAPI void
381 e_shelf_hide(E_Shelf *es)
382 {
383    E_OBJECT_CHECK(es);
384    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
385    if (es->popup)
386      e_popup_hide(es->popup);
387    else
388      {
389         evas_object_hide(es->o_event);
390         evas_object_hide(es->o_base);
391      }
392 }
393
394 EAPI void
395 e_shelf_locked_set(E_Shelf *es, int lock)
396 {
397    if (lock)
398      {
399         e_shelf_toggle(es, 1);
400         es->locked++;
401      }
402    else
403      {
404         if (es->locked > 0)
405           es->locked--;
406         if (!es->locked)
407           e_shelf_toggle(es, es->toggle);
408      }
409 }
410
411 EAPI void
412 e_shelf_name_set(E_Shelf *es, const char *name)
413 {
414    if (!es) return;
415    if (!name) return;
416    if (es->name == name) return;
417    eina_stringshare_replace(&es->name, name);
418    eina_stringshare_replace(&es->cfg->name, name);
419    if (es->dummy) return;
420    e_gadcon_name_set(es->gadcon, name);
421 }
422
423 EAPI void
424 e_shelf_toggle(E_Shelf *es, int show)
425 {
426    E_OBJECT_CHECK(es);
427    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
428
429    es->toggle = show;
430    if (es->locked) return;
431    es->interrupted = -1;
432    es->urgent_show = 0;
433    if ((show) && (es->hidden))
434      {
435         es->hidden = 0;
436         edje_object_signal_emit(es->o_base, "e,state,visible", "e");
437         if (es->instant_delay >= 0.0)
438           {
439              _e_shelf_cb_instant_hide_timer(es);
440              es->hide_timer =
441                ecore_timer_add(es->cfg->hide_timeout,
442                                _e_shelf_cb_hide_urgent_timer, es);
443           }
444         else
445           {
446              if (es->hide_timer)
447                {
448                   ecore_timer_del(es->hide_timer);
449                   es->hide_timer = NULL;
450                }
451              if (!es->hide_animator)
452                es->hide_animator =
453                  ecore_animator_add(_e_shelf_cb_hide_animator, es);
454           }
455      }
456    else if ((!show) && (!es->hidden) && (!es->gadcon->editing) &&
457             (es->cfg->autohide))
458      {
459         edje_object_signal_emit(es->o_base, "e,state,hidden", "e");
460         if (es->instant_delay >= 0.0)
461           {
462              if (es->hide_timer)
463                {
464                   ecore_timer_del(es->hide_timer);
465                   es->hide_timer = NULL;
466                }
467              es->hidden = 1;
468              if (!es->instant_timer)
469                es->instant_timer =
470                  ecore_timer_add(es->instant_delay,
471                                  _e_shelf_cb_instant_hide_timer, es);
472           }
473         else
474           {
475              if (es->hide_animator)
476                {
477                   es->interrupted = show;
478                   return;
479                }
480              es->hidden = 1;
481              if (es->hide_timer) ecore_timer_del(es->hide_timer);
482              es->hide_timer =
483                ecore_timer_add(es->cfg->hide_timeout,
484                                _e_shelf_cb_hide_animator_timer, es);
485           }
486      }
487 }
488
489 EAPI void
490 e_shelf_urgent_show(E_Shelf *es)
491 {
492    e_shelf_toggle(es, 1);
493    es->urgent_show = 1;
494 }
495
496 EAPI void
497 e_shelf_move(E_Shelf *es, int x, int y)
498 {
499    E_OBJECT_CHECK(es);
500    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
501    es->x = x;
502    es->y = y;
503    if (es->popup)
504      e_popup_move(es->popup, es->x, es->y);
505    else
506      {
507         evas_object_move(es->o_event, es->zone->x + es->x, es->zone->y + es->y);
508         evas_object_move(es->o_base, es->zone->x + es->x, es->zone->y + es->y);
509      }
510 }
511
512 EAPI void
513 e_shelf_resize(E_Shelf *es, int w, int h)
514 {
515    E_OBJECT_CHECK(es);
516    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
517    es->w = w;
518    es->h = h;
519    if (es->popup) e_popup_resize(es->popup, es->w, es->h);
520    evas_object_resize(es->o_event, es->w, es->h);
521    evas_object_resize(es->o_base, es->w, es->h);
522 }
523
524 EAPI void
525 e_shelf_move_resize(E_Shelf *es, int x, int y, int w, int h)
526 {
527    E_OBJECT_CHECK(es);
528    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
529    es->x = x;
530    es->y = y;
531    es->w = w;
532    es->h = h;
533    if (es->popup)
534      e_popup_move_resize(es->popup, es->x, es->y, es->w, es->h);
535    else
536      {
537         evas_object_move(es->o_event, es->zone->x + es->x, es->zone->y + es->y);
538         evas_object_move(es->o_base, es->zone->x + es->x, es->zone->y + es->y);
539      }
540    evas_object_resize(es->o_event, es->w, es->h);
541    evas_object_resize(es->o_base, es->w, es->h);
542 }
543
544 EAPI void
545 e_shelf_layer_set(E_Shelf *es, int layer)
546 {
547    E_OBJECT_CHECK(es);
548    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
549
550    es->layer = layer;
551    if (es->popup)
552      e_popup_layer_set(es->popup, es->layer);
553    else
554      {
555         evas_object_layer_set(es->o_event, es->layer);
556         evas_object_layer_set(es->o_base, es->layer);
557      }
558 }
559
560 EAPI void
561 e_shelf_save(E_Shelf *es)
562 {
563    E_OBJECT_CHECK(es);
564    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
565    if (es->cfg)
566      {
567         es->cfg->orient = es->gadcon->orient;
568         if (es->cfg->style) eina_stringshare_del(es->cfg->style);
569         es->cfg->style = eina_stringshare_add(es->style);
570      }
571    else
572      {
573         E_Config_Shelf *cf_es;
574
575         cf_es = E_NEW(E_Config_Shelf, 1);
576         cf_es->name = eina_stringshare_add(es->name);
577         cf_es->container = es->zone->container->num;
578         cf_es->zone = es->zone->num;
579         if (es->popup) cf_es->popup = 1;
580         cf_es->layer = es->layer;
581         e_config->shelves = eina_list_append(e_config->shelves, cf_es);
582         cf_es->orient = es->gadcon->orient;
583         cf_es->style = eina_stringshare_add(es->style);
584         cf_es->fit_along = es->fit_along;
585         cf_es->fit_size = es->fit_size;
586         cf_es->overlap = 0;
587         cf_es->autohide = 0;
588         cf_es->hide_timeout = 1.0;
589         cf_es->hide_duration = 1.0;
590 #ifdef _F_SHELF_INPUT_CONTROL_
591         cf_es->disable_menu = 0;
592 #endif
593         es->cfg = cf_es;
594      }
595    e_config_save_queue();
596 }
597
598 EAPI void
599 e_shelf_unsave(E_Shelf *es)
600 {
601    E_OBJECT_CHECK(es);
602    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
603    es->cfg_delete = 1;
604 }
605
606 EAPI void
607 e_shelf_orient(E_Shelf *es, E_Gadcon_Orient orient)
608 {
609    char buf[4096];
610
611    E_OBJECT_CHECK(es);
612    E_OBJECT_IF_NOT_TYPE(es, E_SHELF_DUMMY_TYPE)
613      E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
614
615    if (!es->dummy)
616      {
617         e_gadcon_orient(es->gadcon, orient);
618         snprintf(buf, sizeof(buf), "e,state,orientation,%s",
619                  e_shelf_orient_string_get(es));
620         edje_object_signal_emit(es->o_base, buf, "e");
621         edje_object_message_signal_process(es->o_base);
622         e_gadcon_location_set_icon_name(es->gadcon->location, 
623                                         _e_shelf_orient_icon_name_get(es));
624      }
625    e_zone_useful_geometry_dirty(es->zone);
626 }
627
628 EAPI const char *
629 e_shelf_orient_string_get(E_Shelf *es)
630 {
631    const char *sig = "";
632
633    switch (es->gadcon->orient)
634      {
635       case E_GADCON_ORIENT_FLOAT:
636         sig = "float";
637         break;
638
639       case E_GADCON_ORIENT_HORIZ:
640         sig = "horizontal";
641         break;
642
643       case E_GADCON_ORIENT_VERT:
644         sig = "vertical";
645         break;
646
647       case E_GADCON_ORIENT_LEFT:
648         sig = "left";
649         break;
650
651       case E_GADCON_ORIENT_RIGHT:
652         sig = "right";
653         break;
654
655       case E_GADCON_ORIENT_TOP:
656         sig = "top";
657         break;
658
659       case E_GADCON_ORIENT_BOTTOM:
660         sig = "bottom";
661         break;
662
663       case E_GADCON_ORIENT_CORNER_TL:
664         sig = "top_left";
665         break;
666
667       case E_GADCON_ORIENT_CORNER_TR:
668         sig = "top_right";
669         break;
670
671       case E_GADCON_ORIENT_CORNER_BL:
672         sig = "bottom_left";
673         break;
674
675       case E_GADCON_ORIENT_CORNER_BR:
676         sig = "bottom_right";
677         break;
678
679       case E_GADCON_ORIENT_CORNER_LT:
680         sig = "left_top";
681         break;
682
683       case E_GADCON_ORIENT_CORNER_RT:
684         sig = "right_top";
685         break;
686
687       case E_GADCON_ORIENT_CORNER_LB:
688         sig = "left_bottom";
689         break;
690
691       case E_GADCON_ORIENT_CORNER_RB:
692         sig = "right_bottom";
693         break;
694
695       default:
696         break;
697      }
698    return sig;
699 }
700
701 EAPI void
702 e_shelf_position_calc(E_Shelf *es)
703 {
704    E_Gadcon_Orient orient = E_GADCON_ORIENT_FLOAT;
705    int size = (40 * e_scale);
706
707    if (es->cfg)
708      {
709         orient = es->cfg->orient;
710         size = es->cfg->size * e_scale;
711      }
712    else
713      orient = es->gadcon->orient;
714    switch (orient)
715      {
716       case E_GADCON_ORIENT_FLOAT:
717         if (!es->fit_along) es->w = es->zone->w;
718         if (!es->fit_size) es->h = size;
719         break;
720
721       case E_GADCON_ORIENT_HORIZ:
722         if (!es->fit_along) es->w = es->zone->w;
723         if (!es->fit_size) es->h = size;
724         es->x = (es->zone->w - es->w) / 2;
725         break;
726
727       case E_GADCON_ORIENT_VERT:
728         if (!es->fit_along) es->h = es->zone->h;
729         if (!es->fit_size) es->w = size;
730         es->y = (es->zone->h - es->h) / 2;
731         break;
732
733       case E_GADCON_ORIENT_LEFT:
734         if (!es->fit_along) es->h = es->zone->h;
735         if (!es->fit_size) es->w = size;
736         es->x = 0;
737         es->y = (es->zone->h - es->h) / 2;
738         break;
739
740       case E_GADCON_ORIENT_RIGHT:
741         if (!es->fit_along) es->h = es->zone->h;
742         if (!es->fit_size) es->w = size;
743         es->x = es->zone->w - es->w;
744         es->y = (es->zone->h - es->h) / 2;
745         break;
746
747       case E_GADCON_ORIENT_TOP:
748         if (!es->fit_along) es->w = es->zone->w;
749         if (!es->fit_size) es->h = size;
750         es->x = (es->zone->w - es->w) / 2;
751         es->y = 0;
752         break;
753
754       case E_GADCON_ORIENT_BOTTOM:
755         if (!es->fit_along) es->w = es->zone->w;
756         if (!es->fit_size) es->h = size;
757         es->x = (es->zone->w - es->w) / 2;
758         es->y = es->zone->h - es->h;
759         break;
760
761       case E_GADCON_ORIENT_CORNER_TL:
762         if (!es->fit_along) es->w = es->zone->w;
763         if (!es->fit_size) es->h = size;
764         es->x = 0;
765         es->y = 0;
766         break;
767
768       case E_GADCON_ORIENT_CORNER_TR:
769         if (!es->fit_along) es->w = es->zone->w;
770         if (!es->fit_size) es->h = size;
771         es->x = es->zone->w - es->w;
772         es->y = 0;
773         break;
774
775       case E_GADCON_ORIENT_CORNER_BL:
776         if (!es->fit_along) es->w = es->zone->w;
777         if (!es->fit_size) es->h = size;
778         es->x = 0;
779         es->y = es->zone->h - es->h;
780         break;
781
782       case E_GADCON_ORIENT_CORNER_BR:
783         if (!es->fit_along) es->w = es->zone->w;
784         if (!es->fit_size) es->h = size;
785         es->x = es->zone->w - es->w;
786         es->y = es->zone->h - es->h;
787         break;
788
789       case E_GADCON_ORIENT_CORNER_LT:
790         if (!es->fit_along) es->h = es->zone->h;
791         if (!es->fit_size) es->w = size;
792         es->x = 0;
793         es->y = 0;
794         break;
795
796       case E_GADCON_ORIENT_CORNER_RT:
797         if (!es->fit_along) es->h = es->zone->h;
798         if (!es->fit_size) es->w = size;
799         es->x = es->zone->w - es->w;
800         es->y = 0;
801         break;
802
803       case E_GADCON_ORIENT_CORNER_LB:
804         if (!es->fit_along) es->h = es->zone->h;
805         if (!es->fit_size) es->w = size;
806         es->x = 0;
807         es->y = es->zone->h - es->h;
808         break;
809
810       case E_GADCON_ORIENT_CORNER_RB:
811         if (!es->fit_along) es->h = es->zone->h;
812         if (!es->fit_size) es->w = size;
813         es->x = es->zone->w - es->w;
814         es->y = es->zone->h - es->h;
815         break;
816
817       default:
818         break;
819      }
820    es->hide_step = 0;
821    es->hide_origin = -1;
822
823    e_shelf_move_resize(es, es->x, es->y, es->w, es->h);
824    if (es->hidden)
825      {
826         es->hidden = 0;
827         e_shelf_toggle(es, 0);
828      }
829    e_zone_useful_geometry_dirty(es->zone);
830    _e_shelf_bindings_add(es);
831
832    do
833      {
834         Eina_Bool err = EINA_FALSE;
835
836         if (!es->cfg) break;
837         if (!es->zone) break;
838         if ((!es->cfg->popup) || (!es->cfg->autohide)) break;
839         switch (es->cfg->orient)
840           {
841            case E_GADCON_ORIENT_LEFT:
842            case E_GADCON_ORIENT_CORNER_LT:
843            case E_GADCON_ORIENT_CORNER_LB:
844              if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_LEFT)) break;
845              err = EINA_TRUE;
846              break;
847            case E_GADCON_ORIENT_RIGHT:
848            case E_GADCON_ORIENT_CORNER_RT:
849            case E_GADCON_ORIENT_CORNER_RB:
850              if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_RIGHT)) break;
851              err = EINA_TRUE;
852              break;
853            case E_GADCON_ORIENT_TOP:
854            case E_GADCON_ORIENT_CORNER_TL:
855            case E_GADCON_ORIENT_CORNER_TR:
856              if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_TOP)) break;
857              err = EINA_TRUE;
858              break;
859            case E_GADCON_ORIENT_BOTTOM:
860            case E_GADCON_ORIENT_CORNER_BL:
861            case E_GADCON_ORIENT_CORNER_BR:
862              if (!e_zone_exists_direction(es->zone, E_ZONE_EDGE_BOTTOM)) break;
863              err = EINA_TRUE;
864              break;
865           }
866         if (err)
867           e_util_dialog_show(_("Shelf Autohide Error"), _("Shelf autohiding will not work properly<br>"
868                                                           "with the current configuration; set your shelf to<br>"
869                                                           "\"Below Everything\" or disable autohiding."));
870         break;
871      } while (0);
872 }
873
874 EAPI void
875 e_shelf_style_set(E_Shelf *es, const char *style)
876 {
877    const char *option;
878    char buf[1024];
879
880    E_OBJECT_CHECK(es);
881    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
882
883    if (!es->o_base) return;
884    if (style != es->style)
885      eina_stringshare_replace(&es->style, style);
886
887    if (style)
888      snprintf(buf, sizeof(buf), "e/shelf/%s/base", style);
889    else
890      snprintf(buf, sizeof(buf), "e/shelf/%s/base", "default");
891
892    if (!e_theme_edje_object_set(es->o_base, "base/theme/shelf", buf))
893      e_theme_edje_object_set(es->o_base, "base/theme/shelf",
894                              "e/shelf/default/base");
895
896    option = edje_object_data_get(es->o_base, "hidden_state_size");
897    if (option)
898      es->hidden_state_size = atoi(option);
899    else
900      es->hidden_state_size = 4;
901    option = edje_object_data_get(es->o_base, "instant_delay");
902    if (option)
903      es->instant_delay = atof(option);
904    else
905      es->instant_delay = -1.0;
906
907    if (es->popup) e_popup_edje_bg_object_set(es->popup, es->o_base);
908    
909    if (!es->gadcon) return;
910    e_gadcon_unpopulate(es->gadcon);
911    e_gadcon_populate(es->gadcon);
912 }
913
914 EAPI void
915 e_shelf_popup_set(E_Shelf *es, int popup)
916 {
917    /* FIXME: Needs to recreate the evas objects. */
918    E_OBJECT_CHECK(es);
919    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
920
921    if (!es->cfg) return;
922    if (((popup) && (es->popup)) || ((!popup) && (!es->popup))) return;
923
924    if (popup)
925      {
926         evas_object_clip_unset(es->o_base);
927         es->popup = e_popup_new(es->zone, es->x, es->y, es->w, es->h);
928         e_popup_name_set(es->popup, "shelf");
929         e_popup_layer_set(es->popup, es->cfg->layer);
930
931         es->ee = es->popup->ecore_evas;
932         es->evas = es->popup->evas;
933         evas_object_show(es->o_event);
934         evas_object_show(es->o_base);
935         e_popup_edje_bg_object_set(es->popup, es->o_base);
936         ecore_x_netwm_window_type_set(es->popup->evas_win, 
937                                       ECORE_X_WINDOW_TYPE_DOCK);
938
939         e_drop_xdnd_register_set(es->popup->evas_win, 1);
940         e_gadcon_xdnd_window_set(es->gadcon, es->popup->evas_win);
941         e_gadcon_dnd_window_set(es->gadcon, es->popup->evas_win);
942      }
943    else
944      {
945         e_drop_xdnd_register_set(es->popup->evas_win, 0);
946         e_object_del(E_OBJECT(es->popup));
947         es->popup = NULL;
948
949         es->ee = es->zone->container->bg_ecore_evas;
950         es->evas = es->zone->container->bg_evas;
951
952         evas_object_move(es->o_event, es->zone->x + es->x, es->zone->y + es->y);
953         evas_object_move(es->o_base, es->zone->x + es->x, es->zone->y + es->y);
954         evas_object_layer_set(es->o_event, es->cfg->layer);
955         evas_object_layer_set(es->o_base, es->cfg->layer);
956
957         e_drop_xdnd_register_set(es->zone->container->bg_win, 1);
958         e_gadcon_xdnd_window_set(es->gadcon, es->zone->container->bg_win);
959         e_gadcon_dnd_window_set(es->gadcon, es->zone->container->event_win);
960         evas_object_clip_set(es->o_base, es->zone->bg_clip_object);
961      }
962 }
963
964 EAPI void
965 e_shelf_autohide_set(E_Shelf *es, Eina_Bool autohide)
966 {
967    E_OBJECT_CHECK(es);
968    E_OBJECT_TYPE_CHECK(es, E_SHELF_TYPE);
969
970    autohide = !!autohide;
971    if ((es->cfg->autohide == autohide) && ((!!es->autohide) == autohide)) return;
972    es->cfg->autohide = autohide;
973    if (!es->cfg->autohide)
974      {
975         if (!es->autohide) return;
976         ecore_event_handler_del(es->autohide);
977         es->autohide = NULL;
978         return;
979      }
980 /*
981  * see FIXME in _e_shelf_cb_mouse_in() for why these are commented out
982    es->handlers = 
983      eina_list_append(es->handlers,
984                       ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, 
985                                               _e_shelf_cb_mouse_in, es));
986 */
987    es->autohide = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, 
988                                           _e_shelf_cb_mouse_in, es);
989 /*
990    es->handlers = 
991      eina_list_append(es->handlers,
992                       ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, 
993                                               _e_shelf_cb_mouse_out, es));
994    if (!popup)
995      evas_object_event_callback_add(es->o_event, EVAS_CALLBACK_MOUSE_OUT, 
996                                     (Evas_Object_Event_Cb)_e_shelf_cb_mouse_out2, es);
997 */
998 }
999
1000 EAPI E_Shelf *
1001 e_shelf_config_new(E_Zone *zone, E_Config_Shelf *cf_es)
1002 {
1003    E_Shelf *es;
1004
1005    es = e_shelf_zone_new(zone, cf_es->name, cf_es->style,
1006                          cf_es->popup, cf_es->layer, cf_es->id);
1007    if (!es) return NULL;
1008
1009    if (!cf_es->hide_timeout) cf_es->hide_timeout = 1.0;
1010    if (!cf_es->hide_duration) cf_es->hide_duration = 1.0;
1011    es->cfg = cf_es;
1012    es->fit_along = cf_es->fit_along;
1013    es->fit_size = cf_es->fit_size;
1014 #ifdef _F_SHELF_INPUT_CONTROL_
1015    es->disable_menu = cf_es->disable_menu;
1016 #endif
1017
1018    e_shelf_autohide_set(es, cf_es->autohide);
1019    e_shelf_orient(es, cf_es->orient);
1020    e_shelf_position_calc(es);
1021    e_shelf_populate(es);
1022
1023    if (cf_es->desk_show_mode)
1024      {
1025         E_Desk *desk;
1026         Eina_List *ll;
1027         E_Config_Shelf_Desk *sd;
1028
1029         desk = e_desk_current_get(zone);
1030         EINA_LIST_FOREACH(cf_es->desk_list, ll, sd)
1031           {
1032              if ((desk->x == sd->x) && (desk->y == sd->y))
1033                {
1034                   e_shelf_show(es);
1035                   break;
1036                }
1037           }
1038      }
1039    else
1040      e_shelf_show(es);
1041
1042    e_shelf_toggle(es, 0);
1043    return es;
1044 }
1045
1046 EAPI E_Entry_Dialog *
1047 e_shelf_new_dialog(E_Zone *zone)
1048 {
1049    char buf[256];
1050
1051    snprintf(buf, sizeof(buf), "%s #%d", _("Shelf"), eina_list_count(e_config->shelves));
1052    return e_entry_dialog_show(_("Add New Shelf"), "preferences-desktop-shelf",
1053                                _("Name:"), buf, NULL, NULL,
1054                                _e_shelf_new_dialog_ok, NULL, zone);
1055 }
1056
1057 /* local subsystem functions */
1058
1059 static void
1060 _e_shelf_new_dialog_ok(void *data, char *text)
1061 {
1062    E_Config_Shelf *cfg, *es_cf;
1063    E_Zone *zone = data;
1064    Eina_List *l;
1065    unsigned int x;
1066    unsigned long orient = 1;
1067    E_Shelf *es;
1068
1069    if ((!text) || (!text[0])) return;
1070    EINA_LIST_FOREACH(e_config->shelves, l, es_cf)
1071      {
1072         if (strcmp(es_cf->name, text)) continue;
1073         e_util_dialog_internal(_("Shelf Error"), _("A shelf with that name already exists!"));
1074         return;
1075      }
1076
1077    cfg = E_NEW(E_Config_Shelf, 1);
1078    cfg->name = eina_stringshare_add(text);
1079    cfg->container = zone->container->num;
1080    cfg->zone = zone->num;
1081    cfg->popup = 1;
1082    cfg->layer = 200;
1083    EINA_LIST_FOREACH(e_config->shelves, l, es_cf)
1084      orient *= orientations[es_cf->orient];
1085    for (x = 3; x < (sizeof(orientations) / sizeof(orientations[0])); x++)
1086      if (orient % orientations[x])
1087        {
1088           cfg->orient = x;
1089           break;
1090        }
1091    cfg->fit_along = 1;
1092    cfg->fit_size = 0;
1093    cfg->style = eina_stringshare_add("default");
1094    cfg->size = 40;
1095    cfg->overlap = 0;
1096    cfg->autohide = 0;
1097 #ifdef _F_SHELF_INPUT_CONTROL_
1098    cfg->disable_menu = 0;
1099 #endif
1100
1101    e_config->shelves = eina_list_append(e_config->shelves, cfg);
1102    e_config_save_queue();
1103
1104    es_cf = eina_list_data_get(eina_list_last(e_config->shelves));
1105    cfg->id = es_cf->id + 1;
1106    es = e_shelf_config_new(zone, cfg);
1107    if (es && es->gadcon)
1108      e_int_gadcon_config_shelf(es->gadcon);
1109 }
1110
1111 static void
1112 _e_shelf_del_cb(void *d)
1113 {
1114    E_Shelf *es;
1115
1116    es = d;
1117    if (es->dummy)
1118      {
1119         dummies = eina_list_remove(dummies, es);
1120         E_FREE(es->cfg);
1121      }
1122    else
1123      shelves = eina_list_remove(shelves, es);
1124 }
1125
1126 static void
1127 _e_shelf_free_cb(void *data __UNUSED__, void *event)
1128 {
1129    E_Event_Shelf *ev = event;
1130    E_Shelf *es = ev->shelf;
1131
1132    eina_stringshare_del(es->name);
1133    eina_stringshare_del(es->style);
1134
1135    if (es->cfg_delete)
1136      {
1137         if (es->cfg)
1138           {
1139              e_config->shelves = eina_list_remove(e_config->shelves, es->cfg);
1140              eina_stringshare_del(es->cfg->name);
1141              eina_stringshare_del(es->cfg->style);
1142              free(es->cfg);
1143           }
1144         e_config_save_queue();
1145      }
1146    free(es);
1147    free(ev);
1148 }
1149
1150 static void
1151 _e_shelf_free(E_Shelf *es)
1152 {
1153    E_Event_Shelf *ev;
1154
1155    if (!es->dummy)
1156      _e_shelf_bindings_del(es);
1157
1158    e_zone_useful_geometry_dirty(es->zone);
1159    E_FREE_LIST(es->handlers, ecore_event_handler_del);
1160
1161    if (es->autohide)
1162      {
1163         ecore_event_handler_del(es->autohide);
1164         es->autohide = NULL;
1165      }
1166
1167    if (es->hide_timer)
1168      {
1169         ecore_timer_del(es->hide_timer);
1170         es->hide_timer = NULL;
1171      }
1172    if (es->hide_animator)
1173      {
1174         ecore_animator_del(es->hide_animator);
1175         es->hide_animator = NULL;
1176      }
1177    if (es->instant_timer)
1178      {
1179         ecore_timer_del(es->instant_timer);
1180         es->instant_timer = NULL;
1181      }
1182
1183    if (es->menu)
1184      {
1185         e_menu_post_deactivate_callback_set(es->menu, NULL, NULL);
1186         e_object_del(E_OBJECT(es->menu));
1187         es->menu = NULL;
1188      }
1189    if (es->dummy)
1190      {
1191         evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_DEL, 
1192                                             (Evas_Object_Event_Cb)_e_shelf_cb_dummy_del, es);
1193         evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_MOVE, 
1194                                             (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es);
1195         evas_object_event_callback_del_full(es->o_base, EVAS_CALLBACK_RESIZE, 
1196                                             (Evas_Object_Event_Cb)_e_shelf_cb_dummy_moveresize, es);
1197      }
1198    else
1199      {
1200         e_gadcon_location_unregister(es->gadcon->location);
1201         e_gadcon_location_free(es->gadcon->location);
1202         if (es->cfg_delete) e_gadcon_config_del(es->gadcon);
1203         e_object_del(E_OBJECT(es->gadcon));
1204         es->gadcon = NULL;
1205      }
1206    if (es->config_dialog) e_object_del(E_OBJECT(es->config_dialog));
1207    es->config_dialog = NULL;
1208    evas_object_del(es->o_event);
1209    evas_object_del(es->o_base);
1210    es->o_base = es->o_event = NULL;
1211    if (es->popup)
1212      {
1213         e_drop_xdnd_register_set(es->popup->evas_win, 0);
1214         eina_hash_del(winid_shelves,
1215                       e_util_winid_str_get(es->popup->evas_win), es);
1216         if (!eina_hash_population(winid_shelves))
1217           {
1218              eina_hash_free(winid_shelves);
1219              winid_shelves = NULL;
1220           }
1221         e_object_del(E_OBJECT(es->popup));
1222      }
1223    es->popup = NULL;
1224
1225    ev = E_NEW(E_Event_Shelf, 1);
1226    ev->shelf = es;
1227    ecore_event_add(E_EVENT_SHELF_DEL, ev, _e_shelf_free_cb, NULL);
1228 }
1229
1230 static void
1231 _e_shelf_gadcon_min_size_request(void *data __UNUSED__, E_Gadcon *gc __UNUSED__, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__)
1232 {
1233    return;
1234 }
1235
1236 static void
1237 _e_shelf_gadcon_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h)
1238 {
1239    E_Shelf *es;
1240    Evas_Coord nx, ny, nw, nh, ww, hh, wantw, wanth;
1241
1242    es = data;
1243    nx = es->x;
1244    ny = es->y;
1245    nw = es->w;
1246    nh = es->h;
1247    ww = hh = 0;
1248    evas_object_geometry_get(gc->o_container, NULL, NULL, &ww, &hh);
1249    switch (gc->orient)
1250      {
1251       case E_GADCON_ORIENT_FLOAT:
1252       case E_GADCON_ORIENT_HORIZ:
1253       case E_GADCON_ORIENT_TOP:
1254       case E_GADCON_ORIENT_BOTTOM:
1255       case E_GADCON_ORIENT_CORNER_TL:
1256       case E_GADCON_ORIENT_CORNER_TR:
1257       case E_GADCON_ORIENT_CORNER_BL:
1258       case E_GADCON_ORIENT_CORNER_BR:
1259         if (!es->fit_along) w = ww;
1260         if (!es->fit_size) h = hh;
1261         break;
1262
1263       case E_GADCON_ORIENT_VERT:
1264       case E_GADCON_ORIENT_LEFT:
1265       case E_GADCON_ORIENT_RIGHT:
1266       case E_GADCON_ORIENT_CORNER_LT:
1267       case E_GADCON_ORIENT_CORNER_RT:
1268       case E_GADCON_ORIENT_CORNER_LB:
1269       case E_GADCON_ORIENT_CORNER_RB:
1270         if (!es->fit_along) h = hh;
1271         if (!es->fit_size) w = ww;
1272         break;
1273
1274       default:
1275         break;
1276      }
1277    e_gadcon_swallowed_min_size_set(gc, w, h);
1278    edje_object_size_min_calc(es->o_base, &nw, &nh);
1279    wantw = nw;
1280    wanth = nh;
1281    switch (gc->orient)
1282      {
1283       case E_GADCON_ORIENT_FLOAT:
1284         if (!es->fit_along) nw = es->w;
1285         if (!es->fit_size) nh = es->h;
1286         if (nw > es->zone->w) nw = es->zone->w;
1287         if (nh > es->zone->h) nh = es->zone->h;
1288         /*if (nw != es->w)*/ nx = es->x + ((es->w - nw) / 2);
1289         /*if (nh != es->h)*/ ny = es->y + ((es->h - nh) / 2);
1290         break;
1291
1292       case E_GADCON_ORIENT_HORIZ:
1293         if (!es->fit_along) nw = es->w;
1294         if (!es->fit_size) nh = es->h;
1295         if (nw > es->zone->w) nw = es->zone->w;
1296         if (nh > es->zone->h) nh = es->zone->h;
1297         /*if (nw != es->w)*/ nx = es->x + ((es->w - nw) / 2);
1298         break;
1299
1300       case E_GADCON_ORIENT_VERT:
1301         if (!es->fit_along) nh = es->h;
1302         if (!es->fit_size) nw = es->w;
1303         if (nw > es->zone->w) nw = es->zone->w;
1304         if (nh > es->zone->h) nh = es->zone->h;
1305         /*if (nh != es->h)*/ ny = es->y + ((es->h - nh) / 2);
1306         break;
1307
1308       case E_GADCON_ORIENT_LEFT:
1309         if (!es->fit_along) nh = es->h;
1310         if (!es->fit_size) nw = es->w;
1311         if (nw > es->zone->w) nw = es->zone->w;
1312         if (nh > es->zone->h) nh = es->zone->h;
1313         /*if (nh != es->h)*/ ny = (es->zone->h - nh) / 2;
1314         //nx = 0;
1315         break;
1316
1317       case E_GADCON_ORIENT_RIGHT:
1318         if (!es->fit_along) nh = es->h;
1319         if (!es->fit_size) nw = es->w;
1320         if (nw > es->zone->w) nw = es->zone->w;
1321         if (nh > es->zone->h) nh = es->zone->h;
1322         /*if (nh != es->h)*/ ny = (es->zone->h - nh) / 2;
1323         //nx = es->zone->w - nw;
1324         break;
1325
1326       case E_GADCON_ORIENT_TOP:
1327         if (!es->fit_along) nw = es->w;
1328         if (!es->fit_size) nh = es->h;
1329         if (nw > es->zone->w) nw = es->zone->w;
1330         if (nh > es->zone->h) nh = es->zone->h;
1331         /*if (nw != es->w)*/ nx = (es->zone->w - nw) / 2;
1332         //ny = 0;
1333         break;
1334
1335       case E_GADCON_ORIENT_BOTTOM:
1336         if (!es->fit_along) nw = es->w;
1337         if (!es->fit_size) nh = es->h;
1338         if (nw > es->zone->w) nw = es->zone->w;
1339         if (nh > es->zone->h) nh = es->zone->h;
1340         /*if (nw != es->w)*/ nx = (es->zone->w - nw) / 2;
1341         //ny = es->zone->h - nh;
1342         break;
1343
1344       case E_GADCON_ORIENT_CORNER_TL:
1345         if (!es->fit_along) nw = es->w;
1346         if (!es->fit_size) nh = es->h;
1347         if (nw > es->zone->w) nw = es->zone->w;
1348         if (nh > es->zone->h) nh = es->zone->h;
1349         /*if (nw != es->w)*/ nx = 0;
1350         //ny = 0;
1351         break;
1352
1353       case E_GADCON_ORIENT_CORNER_TR:
1354         if (!es->fit_along) nw = es->w;
1355         if (!es->fit_size) nh = es->h;
1356         if (nw > es->zone->w) nw = es->zone->w;
1357         if (nh > es->zone->h) nh = es->zone->h;
1358         /*if (nw != es->w)*/ nx = es->zone->w - nw;
1359         //ny = 0;
1360         break;
1361
1362       case E_GADCON_ORIENT_CORNER_BL:
1363         if (!es->fit_along) nw = es->w;
1364         if (!es->fit_size) nh = es->h;
1365         if (nw > es->zone->w) nw = es->zone->w;
1366         if (nh > es->zone->h) nh = es->zone->h;
1367         /*if (nw != es->w)*/ nx = 0;
1368         //ny = es->zone->h - nh;
1369         break;
1370
1371       case E_GADCON_ORIENT_CORNER_BR:
1372         if (!es->fit_along) nw = es->w;
1373         if (!es->fit_size) nh = es->h;
1374         if (nw > es->zone->w) nw = es->zone->w;
1375         if (nh > es->zone->h) nh = es->zone->h;
1376         /*if (nw != es->w)*/ nx = es->zone->w - nw;
1377         //ny = es->zone->h - nh;
1378         break;
1379
1380       case E_GADCON_ORIENT_CORNER_LT:
1381         if (!es->fit_along) nh = es->h;
1382         if (!es->fit_size) nw = es->w;
1383         if (nw > es->zone->w) nw = es->zone->w;
1384         if (nh > es->zone->h) nh = es->zone->h;
1385         /*if (nh != es->h)*/ ny = 0;
1386         //nx = 0;
1387         break;
1388
1389       case E_GADCON_ORIENT_CORNER_RT:
1390         if (!es->fit_along) nh = es->h;
1391         if (!es->fit_size) nw = es->w;
1392         if (nw > es->zone->w) nw = es->zone->w;
1393         if (nh > es->zone->h) nh = es->zone->h;
1394         /*if (nh != es->h)*/ ny = 0;
1395         //nx = es->zone->w - nw;
1396         break;
1397
1398       case E_GADCON_ORIENT_CORNER_LB:
1399         if (!es->fit_along) nh = es->h;
1400         if (!es->fit_size) nw = es->w;
1401         if (nw > es->zone->w) nw = es->zone->w;
1402         if (nh > es->zone->h) nh = es->zone->h;
1403         /*if (nh != es->h)*/ ny = es->zone->h - nh;
1404         //nx = 0;
1405         break;
1406
1407       case E_GADCON_ORIENT_CORNER_RB:
1408         if (!es->fit_along) nh = es->h;
1409         if (!es->fit_size) nw = es->w;
1410         if (nw > es->zone->w) nw = es->zone->w;
1411         if (nh > es->zone->h) nh = es->zone->h;
1412         /*if (nh != es->h)*/ ny = es->zone->h - nh;
1413         //nx = es->zone->w - nw;
1414         break;
1415
1416       default:
1417         break;
1418      }
1419    w -= (wantw - nw);
1420    h -= (wanth - nh);
1421    e_gadcon_swallowed_min_size_set(gc, w, h);
1422    e_shelf_move_resize(es, nx, ny, nw, nh);
1423    e_zone_useful_geometry_dirty(es->zone);
1424 }
1425
1426 static Evas_Object *
1427 _e_shelf_gadcon_frame_request(void *data, E_Gadcon_Client *gcc, const char *style)
1428 {
1429    E_Shelf *es;
1430    Evas_Object *o;
1431    char buf[4096];
1432
1433    es = data;
1434    o = edje_object_add(gcc->gadcon->evas);
1435
1436    snprintf(buf, sizeof(buf), "e/shelf/%s/%s", es->style, style);
1437    if (!e_theme_edje_object_set(o, "base/theme/shelf", buf))
1438      {
1439         /* if an inset style (e.g. plain) isn't implemented for a given
1440          * shelf style, fall back to the default one. no need for every
1441          * theme to implement the plain style */
1442         snprintf(buf, sizeof(buf), "e/shelf/default/%s", style);
1443         if (!e_theme_edje_object_set(o, "base/theme/shelf", buf))
1444           {
1445              evas_object_del(o);
1446              return NULL;
1447           }
1448      }
1449    snprintf(buf, sizeof(buf), "e,state,orientation,%s",
1450             e_shelf_orient_string_get(es));
1451    edje_object_signal_emit(es->o_base, buf, "e");
1452    edje_object_message_signal_process(o);
1453    return o;
1454 }
1455
1456 static void
1457 _e_shelf_toggle_border_fix(E_Shelf *es)
1458 {
1459    Eina_List *l;
1460    E_Border *bd;
1461
1462    if ((es->cfg->overlap) || (!e_config->border_fix_on_shelf_toggle))
1463      return;
1464
1465    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1466      {
1467         if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
1468           {
1469              if (bd->lock_client_location) continue;
1470              if (es->hidden)
1471                {
1472                   if (!bd->shelf_fix.modified) continue;
1473                   if (!--bd->shelf_fix.modified)
1474                     {
1475                        e_border_move(bd, bd->shelf_fix.x, bd->shelf_fix.y);
1476                        continue;
1477                     }
1478                }
1479
1480              if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
1481                                es->x, es->y, es->w, es->h))
1482                continue;
1483
1484              if (!es->hidden)
1485                {
1486                   if (!bd->shelf_fix.modified++)
1487                     bd->shelf_fix.x = bd->x;
1488                   bd->shelf_fix.y = bd->y;
1489                }
1490
1491              switch (es->gadcon->orient)
1492                {
1493                 case E_GADCON_ORIENT_TOP:
1494                 case E_GADCON_ORIENT_CORNER_TL:
1495                 case E_GADCON_ORIENT_CORNER_TR:
1496                   if (!es->hidden)
1497                     e_border_move(bd, bd->x, bd->y + es->h);
1498                   break;
1499
1500                 case E_GADCON_ORIENT_BOTTOM:
1501                 case E_GADCON_ORIENT_CORNER_BL:
1502                 case E_GADCON_ORIENT_CORNER_BR:
1503                   if (!es->hidden)
1504                     e_border_move(bd, bd->x, bd->y - es->h);
1505                   break;
1506
1507                 case E_GADCON_ORIENT_LEFT:
1508                 case E_GADCON_ORIENT_CORNER_LB:
1509                 case E_GADCON_ORIENT_CORNER_LT:
1510                   if (!es->hidden)
1511                     e_border_move(bd, bd->x + es->w, bd->y);
1512                   break;
1513
1514                 case E_GADCON_ORIENT_RIGHT:
1515                 case E_GADCON_ORIENT_CORNER_RB:
1516                 case E_GADCON_ORIENT_CORNER_RT:
1517                   if (!es->hidden)
1518                     e_border_move(bd, bd->x - es->w, bd->y);
1519                   break;
1520
1521                 default:
1522                   break;
1523                }
1524           }
1525         else
1526           {
1527              E_Maximize max;
1528
1529              max = bd->maximized;
1530              e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
1531              e_border_maximize(bd, max);
1532           }
1533      }
1534 }
1535
1536 static void
1537 _e_shelf_menu_item_free(void *data)
1538 {
1539    E_Shelf *es;
1540
1541    es = e_object_data_get(data);
1542    e_shelf_locked_set(es, 0);
1543    e_object_unref(E_OBJECT(es));
1544 }
1545
1546 static void
1547 _e_shelf_menu_append(E_Shelf *es, E_Menu *mn)
1548 {
1549    E_Menu_Item *mi;
1550    E_Menu *subm;
1551    char buf[256];
1552
1553    if (es->name)
1554      snprintf(buf, sizeof(buf), "%s", es->name);
1555    else
1556      snprintf(buf, sizeof(buf), "%s %s", _("Shelf"), 
1557               e_shelf_orient_string_get(es));
1558
1559    e_shelf_locked_set(es, 1);
1560
1561    subm = e_menu_new();
1562    mi = e_menu_item_new(mn);
1563    e_menu_item_label_set(mi, buf);
1564    e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf");
1565    e_menu_pre_activate_callback_set(subm, _e_shelf_menu_pre_cb, es);
1566    e_object_ref(E_OBJECT(es));
1567    e_object_free_attach_func_set(E_OBJECT(mi), _e_shelf_menu_item_free);
1568    e_object_data_set(E_OBJECT(mi), es);
1569    e_menu_item_submenu_set(mi, subm);
1570    e_object_unref(E_OBJECT(subm));
1571
1572    mi = e_menu_item_new(mn);
1573    e_menu_item_separator_set(mi, 1);
1574
1575    mi = e_menu_item_new(mn);
1576    if (es->gadcon->editing)
1577      e_menu_item_label_set(mi, _("Stop Moving Gadgets"));
1578    else
1579      e_menu_item_label_set(mi, _("Begin Moving Gadgets"));
1580    e_util_menu_item_theme_icon_set(mi, "transform-scale");
1581    e_menu_item_callback_set(mi, _e_shelf_cb_menu_edit, es);
1582 }
1583
1584 static void
1585 _e_shelf_cb_menu_items_append(void *data, E_Gadcon_Client *gcc __UNUSED__, E_Menu *mn)
1586 {
1587    E_Shelf *es;
1588
1589    es = data;
1590    _e_shelf_menu_append(es, mn);
1591 }
1592
1593 static void
1594 _e_shelf_cb_locked_set(void *data, int lock)
1595 {
1596    E_Shelf *es;
1597
1598    es = data;
1599    e_shelf_locked_set(es, lock);
1600 }
1601
1602 static void
1603 _e_shelf_cb_urgent_show(void *data)
1604 {
1605    E_Shelf *es;
1606
1607    es = data;
1608    e_shelf_urgent_show(es);
1609 }
1610
1611 static void
1612 _e_shelf_cb_menu_config(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1613 {
1614    E_Shelf *es;
1615
1616    es = data;
1617    if (!es->config_dialog) e_int_shelf_config(es);
1618 }
1619
1620 static void
1621 _e_shelf_cb_menu_edit(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1622 {
1623    E_Shelf *es;
1624
1625    es = data;
1626    if (es->gadcon->editing)
1627      {
1628         e_gadcon_edit_end(es->gadcon);
1629         e_shelf_toggle(es, 0);
1630      }
1631    else
1632      {
1633         e_shelf_toggle(es, 1);
1634         e_gadcon_edit_begin(es->gadcon);
1635      }
1636 }
1637
1638 static void
1639 _e_shelf_cb_menu_contents(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1640 {
1641    E_Shelf *es;
1642
1643    es = data;
1644    if (!es->gadcon->config_dialog) e_int_gadcon_config_shelf(es->gadcon);
1645 }
1646
1647 static void
1648 _e_shelf_cb_confirm_dialog_destroy(void *data)
1649 {
1650    E_Shelf *es;
1651
1652    es = data;
1653    e_object_unref(E_OBJECT(es));
1654 }
1655
1656 static void
1657 _e_shelf_cb_confirm_dialog_yes(void *data)
1658 {
1659    E_Shelf *es;
1660
1661    es = data;
1662    if (e_object_is_del(E_OBJECT(es))) return;
1663    es->cfg_delete = 1;
1664    e_object_del(E_OBJECT(es));
1665 }
1666
1667 static void
1668 _e_shelf_cb_menu_delete(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
1669 {
1670    E_Shelf *es;
1671
1672    es = data;
1673    if (e_config->cnfmdlg_disabled)
1674      {
1675         if (e_object_is_del(E_OBJECT(es))) return;
1676         es->cfg_delete = 1;
1677         e_object_del(E_OBJECT(es));
1678
1679         e_config_save_queue();
1680         return;
1681      }
1682
1683    e_object_ref(E_OBJECT(es));
1684    e_confirm_dialog_show(_("Are you sure you want to delete this shelf?"), 
1685                          "enlightenment",
1686                          _("You requested to delete this shelf.<br>"
1687                            "<br>"
1688                            "Are you sure you want to delete it?"), 
1689                          _("Delete"), _("Keep"),
1690                          _e_shelf_cb_confirm_dialog_yes, NULL, data, NULL,
1691                          _e_shelf_cb_confirm_dialog_destroy, data);
1692 }
1693
1694 static void
1695 _e_shelf_cb_menu_post(void *data, E_Menu *m __UNUSED__)
1696 {
1697    E_Shelf *es;
1698
1699    es = data;
1700    if (!es->menu) return;
1701    e_object_del(E_OBJECT(es->menu));
1702    es->menu = NULL;
1703 }
1704
1705 static void
1706 _e_shelf_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1707 {
1708    Evas_Event_Mouse_Down *ev;
1709    E_Shelf *es;
1710    E_Menu *mn;
1711    int cx, cy;
1712
1713    es = data;
1714    ev = event_info;
1715    switch (ev->button)
1716      {
1717       case 1:
1718         if (es->cfg->autohide_show_action) e_shelf_toggle(es, 1);
1719         break;
1720
1721       case 3:
1722 #ifdef _F_SHELF_INPUT_CONTROL_
1723         if (es->cfg->disable_menu) return;
1724 #endif
1725
1726         mn = e_menu_new();
1727         e_menu_post_deactivate_callback_set(mn, _e_shelf_cb_menu_post, es);
1728         es->menu = mn;
1729
1730         _e_shelf_menu_pre_cb(es, mn);
1731
1732         e_gadcon_canvas_zone_geometry_get(es->gadcon, &cx, &cy, NULL, NULL);
1733         e_menu_activate_mouse(mn,
1734                               e_util_zone_current_get(e_manager_current_get()),
1735                               cx + ev->output.x,
1736                               cy + ev->output.y, 1, 1,
1737                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
1738         break;
1739      }
1740 }
1741
1742 static Eina_Bool
1743 _e_shelf_cb_mouse_in(void *data, int type, void *event)
1744 {
1745    E_Shelf *es;
1746
1747    es = data;
1748    if (es->cfg->autohide_show_action) return ECORE_CALLBACK_PASS_ON;
1749
1750    if (type == E_EVENT_ZONE_EDGE_MOVE)
1751      {
1752         E_Event_Zone_Edge *ev;
1753         int show = 0;
1754
1755         ev = event;
1756         if (es->zone != ev->zone) return ECORE_CALLBACK_PASS_ON;
1757         if (!_e_shelf_on_current_desk(es, ev)) return ECORE_CALLBACK_PASS_ON;
1758
1759         switch (es->gadcon->orient)
1760           {
1761            case E_GADCON_ORIENT_LEFT:
1762            case E_GADCON_ORIENT_CORNER_LT:
1763            case E_GADCON_ORIENT_CORNER_LB:
1764              if (((ev->edge == E_ZONE_EDGE_LEFT) ||
1765                   (ev->edge == E_ZONE_EDGE_TOP_LEFT) ||
1766                   (ev->edge == E_ZONE_EDGE_BOTTOM_LEFT)) &&
1767                  (ev->y >= es->y) && (ev->y <= (es->y + es->h)))
1768                show = 1;
1769              break;
1770
1771            case E_GADCON_ORIENT_RIGHT:
1772            case E_GADCON_ORIENT_CORNER_RT:
1773            case E_GADCON_ORIENT_CORNER_RB:
1774              if (((ev->edge == E_ZONE_EDGE_RIGHT) ||
1775                   (ev->edge == E_ZONE_EDGE_TOP_RIGHT) ||
1776                   (ev->edge == E_ZONE_EDGE_BOTTOM_RIGHT)) &&
1777                  (ev->y >= es->y) && (ev->y <= (es->y + es->h)))
1778                show = 1;
1779              break;
1780
1781            case E_GADCON_ORIENT_TOP:
1782            case E_GADCON_ORIENT_CORNER_TL:
1783            case E_GADCON_ORIENT_CORNER_TR:
1784              if (((ev->edge == E_ZONE_EDGE_TOP) ||
1785                   (ev->edge == E_ZONE_EDGE_TOP_LEFT) ||
1786                   (ev->edge == E_ZONE_EDGE_TOP_RIGHT)) &&
1787                  (ev->x >= es->x) && (ev->x <= (es->x + es->w)))
1788                show = 1;
1789              break;
1790
1791            case E_GADCON_ORIENT_BOTTOM:
1792            case E_GADCON_ORIENT_CORNER_BL:
1793            case E_GADCON_ORIENT_CORNER_BR:
1794              if (((ev->edge == E_ZONE_EDGE_BOTTOM) ||
1795                   (ev->edge == E_ZONE_EDGE_BOTTOM_LEFT) ||
1796                   (ev->edge == E_ZONE_EDGE_BOTTOM_RIGHT)) &&
1797                  (ev->x >= es->x) && (ev->x <= (es->x + es->w)))
1798                show = 1;
1799              break;
1800
1801            case E_GADCON_ORIENT_FLOAT:
1802            case E_GADCON_ORIENT_HORIZ:
1803            case E_GADCON_ORIENT_VERT:
1804            default:
1805              /* noop */
1806              break;
1807           }
1808
1809         if (show)
1810           {
1811              edje_object_signal_emit(es->o_base, "e,state,focused", "e");
1812              e_shelf_toggle(es, 1);
1813           }
1814         else
1815           e_shelf_toggle(es, 0);
1816      }
1817      /*
1818    else if (type == ECORE_X_EVENT_MOUSE_IN)
1819      {
1820         Ecore_X_Event_Mouse_In *ev;
1821
1822         ev = event;
1823         if ((!es->hidden) && (!es->menu))
1824           {
1825              int x, y, w, h;
1826              evas_object_geometry_get(es->o_event, &x, &y, &w, &h);
1827              if (!E_INSIDE(ev->x, ev->y, x, y, w, h))
1828                e_shelf_toggle(es, 0);
1829           }
1830         if (!es->popup) return ECORE_CALLBACK_PASS_ON;
1831         if (ev->win == es->popup->evas_win)
1832           {
1833              if (es->hidden || (!es->toggle))
1834                {
1835                   edje_object_signal_emit(es->o_base, "e,state,focused", "e");
1836                   e_shelf_toggle(es, 1);
1837                }
1838           }
1839      }
1840      */
1841    else if (type == ECORE_EVENT_MOUSE_MOVE)
1842      {
1843         Ecore_Event_Mouse_Move *ev;
1844         Eina_Bool inside = EINA_FALSE;
1845
1846         ev = event;
1847         /* FIXME: checking every mouse movement here is only necessary because of
1848          * shitty systray embedding xwindows into itself which generates inreliable
1849          * mouse in/out events. in the future, when we remove systray, we should go
1850          * back to mouse in/out events
1851          */
1852         inside = (es->popup && ((ev->event_window == es->popup->evas_win)));
1853         if (!inside)
1854           inside = (
1855                     (E_INSIDE(ev->root.x, ev->root.y, es->zone->x, es->zone->y, es->zone->w + 4, es->zone->h + 4)) &&
1856                     (E_INSIDE(ev->root.x, ev->root.y, es->x, es->y, es->w, es->h))
1857                    );
1858         if (inside)
1859           {
1860              if (es->hidden || (!es->toggle))
1861                {
1862                   edje_object_signal_emit(es->o_base, "e,state,focused", "e");
1863                   e_shelf_toggle(es, 1);
1864                }
1865           }
1866         else
1867           {
1868              if ((!es->hidden) && (es->toggle))
1869                e_shelf_toggle(es, 0);
1870           }
1871      }
1872    return ECORE_CALLBACK_PASS_ON;
1873 }
1874 #if 0
1875 static void
1876 _e_shelf_cb_mouse_out2(E_Shelf *es, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Out *ev)
1877 {
1878    int x, y, w, h;
1879
1880    evas_object_geometry_get(es->o_event, &x, &y, &w, &h);
1881    if (!E_INSIDE(ev->output.x, ev->output.y, x, y, w, h))
1882      e_shelf_toggle(es, 0);
1883 }
1884
1885 static Eina_Bool
1886 _e_shelf_cb_mouse_out(void *data, int type, void *event)
1887 {
1888    E_Shelf *es;
1889    Ecore_X_Window win;
1890
1891    es = data;
1892
1893    if (type == ECORE_X_EVENT_MOUSE_OUT)
1894      {
1895         Ecore_X_Event_Mouse_Out *ev;
1896         int x, y, w, h;
1897
1898         ev = event;
1899
1900         if (es->popup) win = es->popup->evas_win;
1901         else win = es->zone->container->event_win;
1902         if (ev->win != win) return ECORE_CALLBACK_PASS_ON;
1903
1904         /*
1905          * ECORE_X_EVENT_DETAIL_INFERIOR means focus went to children windows
1906          * so do not hide shelf on this case (ie: systray base window, or
1907          * embedded icons).
1908          *
1909          * Problem: when child window get mouse out, shelf window will
1910          * not get mouse out itself, so it will stay visible and
1911          * autohide will fail.
1912          */
1913         if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
1914           {
1915              //fprintf(stderr, "SYSTRAYED\n");
1916              return ECORE_CALLBACK_PASS_ON;
1917           }
1918
1919         evas_object_geometry_get(es->o_event, &x, &y, &w, &h);
1920         if (!E_INSIDE(ev->x, ev->y, x, y, w, h))
1921           {
1922              //fprintf(stderr, "EVENT: %d,%d %dx%d || MOUSE: %d,%d\n", x, y, w, h, ev->x, ev->y);
1923              e_shelf_toggle(es, 0);
1924           }
1925      }
1926    return ECORE_CALLBACK_PASS_ON;
1927 }
1928 #endif
1929 static void
1930 _e_shelf_cb_dummy_moveresize(E_Shelf *es, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1931 {
1932    int x, y, w, h;
1933
1934    evas_object_geometry_get(obj, &x, &y, &w, &h);
1935    if ((x != es->x) || (y != es->y) || (w != es->w) || (h != es->h))
1936      {
1937         es->x = x, es->y = y, es->w = w, es->h = h;
1938         e_zone_useful_geometry_dirty(es->zone);
1939      }
1940 }
1941
1942 static void
1943 _e_shelf_cb_dummy_del(E_Shelf *es, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1944 {
1945    e_object_free(E_OBJECT(es));
1946 }
1947
1948 static int
1949 _e_shelf_cb_id_sort(const void *data1, const void *data2)
1950 {
1951    const E_Shelf *es1, *es2;
1952
1953    es1 = data1;
1954    es2 = data2;
1955    if ((es1->id) < (es2->id)) return -1;
1956    else if (es1->id > es2->id)
1957      return 1;
1958    return 0;
1959 }
1960
1961 static Eina_Bool
1962 _e_shelf_cb_hide_animator(void *data)
1963 {
1964    E_Shelf *es;
1965    int step, hide_max = 0;
1966
1967    es = data;
1968    switch (es->gadcon->orient)
1969      {
1970       case E_GADCON_ORIENT_TOP:
1971       case E_GADCON_ORIENT_CORNER_TL:
1972       case E_GADCON_ORIENT_CORNER_TR:
1973       case E_GADCON_ORIENT_BOTTOM:
1974       case E_GADCON_ORIENT_CORNER_BL:
1975       case E_GADCON_ORIENT_CORNER_BR:
1976         hide_max = es->h - es->hidden_state_size - 1;
1977         if (es->hide_origin == -1) es->hide_origin = es->y;
1978         break;
1979
1980       case E_GADCON_ORIENT_LEFT:
1981       case E_GADCON_ORIENT_CORNER_LB:
1982       case E_GADCON_ORIENT_CORNER_LT:
1983       case E_GADCON_ORIENT_RIGHT:
1984       case E_GADCON_ORIENT_CORNER_RB:
1985       case E_GADCON_ORIENT_CORNER_RT:
1986         hide_max = es->w - es->hidden_state_size;
1987         if (es->hide_origin == -1) es->hide_origin = es->x;
1988         break;
1989
1990       case E_GADCON_ORIENT_FLOAT:
1991       case E_GADCON_ORIENT_HORIZ:
1992       case E_GADCON_ORIENT_VERT:
1993       default:
1994         break;
1995      }
1996
1997    step = (hide_max / e_config->framerate) / es->cfg->hide_duration;
1998    if (!step) step = 1;
1999
2000    if (es->hidden)
2001      {
2002         if (es->hide_step < hide_max)
2003           {
2004              if (es->hide_step + step > hide_max)
2005                es->hide_step = hide_max;
2006              else
2007                es->hide_step += step;
2008           }
2009         else goto end;
2010      }
2011    else
2012      {
2013         if (es->hide_step > 0)
2014           {
2015              if (es->hide_step < step)
2016                es->hide_step = 0;
2017              else
2018                es->hide_step -= step;
2019           }
2020         else goto end;
2021      }
2022
2023    switch (es->gadcon->orient)
2024      {
2025       case E_GADCON_ORIENT_TOP:
2026       case E_GADCON_ORIENT_CORNER_TL:
2027       case E_GADCON_ORIENT_CORNER_TR:
2028         e_shelf_move(es, es->x, es->hide_origin - es->hide_step);
2029         break;
2030
2031       case E_GADCON_ORIENT_BOTTOM:
2032       case E_GADCON_ORIENT_CORNER_BL:
2033       case E_GADCON_ORIENT_CORNER_BR:
2034         e_shelf_move(es, es->x, es->hide_origin + es->hide_step);
2035         break;
2036
2037       case E_GADCON_ORIENT_LEFT:
2038       case E_GADCON_ORIENT_CORNER_LB:
2039       case E_GADCON_ORIENT_CORNER_LT:
2040         e_shelf_move(es, es->hide_origin - es->hide_step, es->y);
2041         break;
2042
2043       case E_GADCON_ORIENT_RIGHT:
2044       case E_GADCON_ORIENT_CORNER_RB:
2045       case E_GADCON_ORIENT_CORNER_RT:
2046         e_shelf_move(es, es->hide_origin + es->hide_step, es->y);
2047         break;
2048
2049       case E_GADCON_ORIENT_FLOAT:
2050       case E_GADCON_ORIENT_HORIZ:
2051       case E_GADCON_ORIENT_VERT:
2052       default:
2053         break;
2054      }
2055
2056    return ECORE_CALLBACK_RENEW;
2057
2058 end:
2059    es->hide_animator = NULL;
2060    if (es->interrupted > -1)
2061      e_shelf_toggle(es, es->interrupted);
2062    else if (es->urgent_show)
2063      e_shelf_toggle(es, 0);
2064    else
2065      _e_shelf_toggle_border_fix(es);
2066    return ECORE_CALLBACK_CANCEL;
2067 }
2068
2069 static Eina_Bool
2070 _e_shelf_cb_hide_animator_timer(void *data)
2071 {
2072    E_Shelf *es;
2073
2074    es = data;
2075    if (!es->hide_animator)
2076      es->hide_animator = ecore_animator_add(_e_shelf_cb_hide_animator, es);
2077    es->hide_timer = NULL;
2078    return ECORE_CALLBACK_CANCEL;
2079 }
2080
2081 static Eina_Bool
2082 _e_shelf_cb_hide_urgent_timer(void *data)
2083 {
2084    E_Shelf *es;
2085
2086    es = data;
2087    es->hide_timer = NULL;
2088    if (es->urgent_show) e_shelf_toggle(es, 0);
2089    return ECORE_CALLBACK_CANCEL;
2090 }
2091
2092 static Eina_Bool
2093 _e_shelf_cb_instant_hide_timer(void *data)
2094 {
2095    E_Shelf *es;
2096
2097    es = data;
2098    switch (es->gadcon->orient)
2099      {
2100       case E_GADCON_ORIENT_TOP:
2101       case E_GADCON_ORIENT_CORNER_TL:
2102       case E_GADCON_ORIENT_CORNER_TR:
2103         if (es->hidden)
2104           e_shelf_move(es, es->x, es->y - es->h + es->hidden_state_size);
2105         else
2106           e_shelf_move(es, es->x, es->y + es->h - es->hidden_state_size);
2107         break;
2108
2109       case E_GADCON_ORIENT_BOTTOM:
2110       case E_GADCON_ORIENT_CORNER_BL:
2111       case E_GADCON_ORIENT_CORNER_BR:
2112         if (es->hidden)
2113           e_shelf_move(es, es->x, es->y + es->h - es->hidden_state_size);
2114         else
2115           e_shelf_move(es, es->x, es->y - es->h + es->hidden_state_size);
2116         break;
2117
2118       case E_GADCON_ORIENT_LEFT:
2119       case E_GADCON_ORIENT_CORNER_LB:
2120       case E_GADCON_ORIENT_CORNER_LT:
2121         if (es->hidden)
2122           e_shelf_move(es, es->x - es->w + es->hidden_state_size, es->y);
2123         else
2124           e_shelf_move(es, es->x + es->w - es->hidden_state_size, es->y);
2125         break;
2126
2127       case E_GADCON_ORIENT_RIGHT:
2128       case E_GADCON_ORIENT_CORNER_RB:
2129       case E_GADCON_ORIENT_CORNER_RT:
2130         if (es->hidden)
2131           e_shelf_move(es, es->x + es->w - es->hidden_state_size, es->y);
2132         else
2133           e_shelf_move(es, es->x - es->w + es->hidden_state_size, es->y);
2134         break;
2135
2136       default:
2137         break;
2138      }
2139    es->instant_timer = NULL;
2140    _e_shelf_toggle_border_fix(es);
2141    return ECORE_CALLBACK_CANCEL;
2142 }
2143
2144 static void
2145 _e_shelf_cb_menu_rename_yes_cb(void *data, char *text)
2146 {
2147    E_Shelf *es = data;
2148    Eina_List *l;
2149    E_Config_Shelf *cf_es;
2150
2151    if ((!text) || (!text[0])) return;
2152    if (!strcmp(text, es->cfg->name)) return;
2153    EINA_LIST_FOREACH(e_config->shelves, l, cf_es)
2154      if (!strcmp(cf_es->name, text))
2155        {
2156           e_util_dialog_internal(_("Error"), _("A shelf with that name and id already exists!"));
2157           return;
2158        }
2159    e_shelf_name_set(es, text);
2160    e_config_save_queue();
2161 }
2162
2163 static void
2164 _e_shelf_cb_menu_rename_cb(void *data)
2165 {
2166    E_Shelf *es = e_object_data_get(data);
2167    es->rename_dialog = NULL;
2168 }
2169
2170 static void
2171 _e_shelf_cb_menu_rename(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2172 {
2173    E_Shelf *es = data;
2174    if (es->rename_dialog) return;
2175    es->rename_dialog = e_entry_dialog_show(_("Rename Shelf"), "edit-rename",
2176                                           _("Name:"), es->name, NULL, NULL,
2177                                           _e_shelf_cb_menu_rename_yes_cb,
2178                                           NULL, es);
2179    e_object_data_set(E_OBJECT(es->rename_dialog), es);
2180    e_object_del_attach_func_set(E_OBJECT(es->rename_dialog),
2181                                 _e_shelf_cb_menu_rename_cb);
2182 }
2183
2184 static void
2185 _e_shelf_cb_menu_orient(void *data, E_Menu *m, E_Menu_Item *mi)
2186 {
2187    E_Shelf *es = data;
2188    E_Menu_Item *mii;
2189    int orient = E_GADCON_ORIENT_LEFT;
2190    Eina_List *l;
2191
2192    EINA_LIST_FOREACH(m->items, l, mii)
2193      {
2194         if (mi == mii)
2195           {
2196              E_Zone *zone;
2197              E_Config_Shelf *cf_es;
2198              void *cfd;
2199              if (es->cfg->orient == orient) return;
2200              es->cfg->orient = orient;
2201              zone = es->zone;
2202              cf_es = es->cfg;
2203              cfd = es->config_dialog;
2204              es->config_dialog = NULL;
2205              e_object_del(E_OBJECT(es));
2206              es = e_shelf_config_new(zone, cf_es);
2207              es->config_dialog = cfd;
2208              return;
2209           }
2210         orient++;
2211      }
2212 }
2213
2214 static void
2215 _e_shelf_menu_orientation_pre_cb(void *data, E_Menu *m)
2216 {
2217    E_Menu_Item *mi;
2218    E_Shelf *es = data;
2219    int orient;
2220
2221    if (m->items) return;
2222
2223    for (orient = E_GADCON_ORIENT_LEFT; orient < E_GADCON_ORIENT_LAST; orient++)
2224      {
2225         mi = e_menu_item_new(m);
2226         e_util_gadcon_orient_menu_item_icon_set(orient, mi);
2227         e_menu_item_radio_set(mi, 1);
2228         e_menu_item_radio_group_set(mi, 1);
2229         e_menu_item_label_set(mi, _(orient_names[orient]));
2230         e_menu_item_callback_set(mi, _e_shelf_cb_menu_orient, es);
2231         if (es->cfg->orient == orient)
2232           e_menu_item_toggle_set(mi, 1);
2233      }
2234 }
2235
2236 static void
2237 _e_shelf_menu_pre_cb(void *data, E_Menu *m)
2238 {
2239    E_Shelf *es;
2240    E_Menu_Item *mi;
2241    E_Menu *subm;
2242
2243    es = data;
2244    e_menu_pre_activate_callback_set(m, NULL, NULL);
2245
2246    mi = e_menu_item_new(m);
2247    e_menu_item_label_set(mi, _("Contents"));
2248    e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf");
2249    e_menu_item_callback_set(mi, _e_shelf_cb_menu_contents, es);
2250
2251    mi = e_menu_item_new(m);
2252    e_menu_item_label_set(mi, _("Settings"));
2253    e_util_menu_item_theme_icon_set(mi, "configure");
2254    e_menu_item_callback_set(mi, _e_shelf_cb_menu_config, es);
2255
2256    mi = e_menu_item_new(m);
2257    e_menu_item_label_set(mi, _("Orientation"));
2258    e_menu_item_callback_set(mi, _e_shelf_cb_menu_config, es);
2259    subm = e_menu_new();
2260    e_menu_pre_activate_callback_set(subm, _e_shelf_menu_orientation_pre_cb, es);
2261    e_object_data_set(E_OBJECT(subm), es);
2262    e_menu_item_submenu_set(mi, subm);
2263    e_object_unref(E_OBJECT(subm));
2264
2265    mi = e_menu_item_new(m);
2266    e_menu_item_separator_set(mi, 1);
2267
2268    mi = e_menu_item_new(m);
2269    e_menu_item_label_set(mi, _("Rename"));
2270    e_util_menu_item_theme_icon_set(mi, "edit-rename");
2271    e_menu_item_callback_set(mi, _e_shelf_cb_menu_rename, es);
2272
2273    mi = e_menu_item_new(m);
2274    e_menu_item_label_set(mi, _("Delete"));
2275    e_util_menu_item_theme_icon_set(mi, "list-remove");
2276    e_menu_item_callback_set(mi, _e_shelf_cb_menu_delete, es);
2277
2278    if (m->parent_item) return;
2279
2280    mi = e_menu_item_new(m);
2281    e_menu_item_separator_set(mi, 1);
2282
2283    mi = e_menu_item_new(m);
2284    if (es->gadcon->editing)
2285      e_menu_item_label_set(mi, _("Stop Moving Gadgets"));
2286    else
2287      e_menu_item_label_set(mi, _("Begin Moving Gadgets"));
2288    e_util_menu_item_theme_icon_set(mi, "transform-scale");
2289    e_menu_item_callback_set(mi, _e_shelf_cb_menu_edit, es);
2290 }
2291
2292 static void
2293 _e_shelf_gadcon_client_remove(void *data, E_Gadcon_Client *gcc)
2294 {
2295    E_Shelf *s;
2296    E_Gadcon *gc;
2297
2298    s = data;
2299    gc = s->gadcon;
2300    e_gadcon_client_config_del(gc->cf, gcc->cf);
2301    e_gadcon_unpopulate(gc);
2302    e_gadcon_populate(gc);
2303    e_config_save_queue();
2304 }
2305
2306 static int
2307 _e_shelf_gadcon_client_add(void *data, const E_Gadcon_Client_Class *cc)
2308 {
2309    E_Shelf *s;
2310    E_Gadcon *gc;
2311
2312    s = data;
2313    gc = s->gadcon;
2314    if (!e_gadcon_client_config_new(gc, cc->name)) return 0;
2315    e_gadcon_unpopulate(gc);
2316    e_gadcon_populate(gc);
2317    e_config_save_queue();
2318    return 1;
2319 }
2320
2321 static const char *
2322 _e_shelf_orient_icon_name_get(E_Shelf *s)
2323 {
2324    const char *name;
2325
2326    name = NULL;
2327    switch (s->cfg->orient)
2328      {
2329       case E_GADCON_ORIENT_LEFT:
2330         name = "preferences-position-left";
2331         break;
2332
2333       case E_GADCON_ORIENT_RIGHT:
2334         name = "preferences-position-right";
2335         break;
2336
2337       case E_GADCON_ORIENT_TOP:
2338         name = "preferences-position-top";
2339         break;
2340
2341       case E_GADCON_ORIENT_BOTTOM:
2342         name = "preferences-position-bottom";
2343         break;
2344
2345       case E_GADCON_ORIENT_CORNER_TL:
2346         name = "preferences-position-top-left";
2347         break;
2348
2349       case E_GADCON_ORIENT_CORNER_TR:
2350         name = "preferences-position-top-right";
2351         break;
2352
2353       case E_GADCON_ORIENT_CORNER_BL:
2354         name = "preferences-position-bottom-left";
2355         break;
2356
2357       case E_GADCON_ORIENT_CORNER_BR:
2358         name = "preferences-position-bottom-right";
2359         break;
2360
2361       case E_GADCON_ORIENT_CORNER_LT:
2362         name = "preferences-position-left-top";
2363         break;
2364
2365       case E_GADCON_ORIENT_CORNER_RT:
2366         name = "preferences-position-right-top";
2367         break;
2368
2369       case E_GADCON_ORIENT_CORNER_LB:
2370         name = "preferences-position-left-bottom";
2371         break;
2372
2373       case E_GADCON_ORIENT_CORNER_RB:
2374         name = "preferences-position-right-bottom";
2375         break;
2376
2377       default:
2378         name = "preferences-desktop-shelf";
2379         break;
2380      }
2381    return name;
2382 }
2383
2384 static void
2385 _e_shelf_bindings_add(E_Shelf *es)
2386 {
2387    char buf[1024];
2388
2389    /* TODO: This might delete edge windows, and then add them again further down. Should prevent this. */
2390    _e_shelf_bindings_del(es);
2391
2392    /* Don't need edge binding if we don't hide shelf */
2393    if ((es->cfg) && (!es->cfg->autohide) &&
2394        (!es->cfg->autohide_show_action))
2395      return;
2396
2397    snprintf(buf, sizeof(buf), "shelf.%d", es->id);
2398    switch (es->gadcon->orient)
2399      {
2400       case E_GADCON_ORIENT_FLOAT:
2401       case E_GADCON_ORIENT_HORIZ:
2402       case E_GADCON_ORIENT_VERT:
2403       default:
2404         /* noop */
2405         break;
2406
2407       case E_GADCON_ORIENT_LEFT:
2408         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 
2409                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2410         break;
2411
2412       case E_GADCON_ORIENT_RIGHT:
2413         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 
2414                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2415         break;
2416
2417       case E_GADCON_ORIENT_TOP:
2418         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 
2419                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2420         break;
2421
2422       case E_GADCON_ORIENT_BOTTOM:
2423         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 
2424                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2425         break;
2426
2427       case E_GADCON_ORIENT_CORNER_TL:
2428       case E_GADCON_ORIENT_CORNER_LT:
2429         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 
2430                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2431         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 
2432                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2433         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP_LEFT, 
2434                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2435         break;
2436
2437       case E_GADCON_ORIENT_CORNER_TR:
2438       case E_GADCON_ORIENT_CORNER_RT:
2439         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP, 
2440                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2441         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 
2442                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2443         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_TOP_RIGHT, 
2444                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2445         break;
2446
2447       case E_GADCON_ORIENT_CORNER_BL:
2448       case E_GADCON_ORIENT_CORNER_LB:
2449         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 
2450                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2451         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_LEFT, 
2452                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2453         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM_LEFT, 
2454                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2455         break;
2456
2457       case E_GADCON_ORIENT_CORNER_BR:
2458       case E_GADCON_ORIENT_CORNER_RB:
2459         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM, 
2460                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2461         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_RIGHT, 
2462                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2463         e_bindings_edge_add(E_BINDING_CONTEXT_ZONE, E_ZONE_EDGE_BOTTOM_RIGHT, 
2464                             E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2465         break;
2466      }
2467 }
2468
2469 static void
2470 _e_shelf_bindings_del(E_Shelf *es)
2471 {
2472    char buf[1024];
2473    E_Zone_Edge edge;
2474
2475    snprintf(buf, sizeof(buf), "shelf.%d", es->id);
2476    for (edge = E_ZONE_EDGE_LEFT; edge <= E_ZONE_EDGE_BOTTOM_LEFT; edge++)
2477      e_bindings_edge_del(E_BINDING_CONTEXT_ZONE, edge, 
2478                          E_BINDING_MODIFIER_NONE, 1, buf, NULL, 0);
2479 }
2480
2481 static Eina_Bool
2482 _e_shelf_on_current_desk(E_Shelf *es, E_Event_Zone_Edge *ev)
2483 {
2484    E_Config_Shelf_Desk *sd;
2485    Eina_List *ll;
2486    int on_current_desk = 0;
2487    int on_all_desks = 1;
2488
2489
2490    if (ev->zone != es->zone) return EINA_FALSE;
2491    EINA_LIST_FOREACH(es->cfg->desk_list, ll, sd)
2492      {
2493         if (!sd) continue;
2494         on_all_desks = 0;
2495         if ((sd->x == ev->zone->desk_x_current) && 
2496             (sd->y == ev->zone->desk_y_current))
2497           {
2498              on_current_desk = 1;
2499              break;
2500           }
2501      }
2502    if ((!on_all_desks) && (!on_current_desk))
2503      return EINA_FALSE;
2504
2505    return EINA_TRUE;
2506 }