1 #include "e.h"
2 
3 
4 #ifdef HAVE_WAYLAND
5 EINTERN void e_gadget_runner_init(void);
6 EINTERN void e_gadget_runner_shutdown(void);
7 EINTERN void e_gadget_runner_save(void);
8 #endif
9 
10 #define SNAP_DISTANCE 5
11 #define E_GADGET_TYPE 0xE31337
12 
13 #define IS_HORIZ(orient) \
14   ((orient) == E_GADGET_SITE_ORIENT_HORIZONTAL)
15 
16 #define IS_VERT(orient) \
17   ((orient) == E_GADGET_SITE_ORIENT_VERTICAL)
18 
19 #define ZGS_GET(obj) \
20    E_Gadget_Site *zgs; \
21    zgs = evas_object_data_get((obj), "__e_gadget_site"); \
22    if (!zgs) abort()
23 
24 typedef struct E_Gadget_Config E_Gadget_Config;
25 
26 typedef struct E_Gadget_Site
27 {
28    Eina_Stringshare *name;
29    Eina_Bool autoadd;
30    E_Gadget_Site_Gravity gravity;
31    E_Gadget_Site_Orient orient;
32    E_Gadget_Site_Anchor anchor;
33    Eina_List *gadgets;
34    Eina_Inlist *gadget_list;
35 
36    Eina_Bool longpressed : 1;
37    Eina_Bool dragged : 1;
38    Evas_Coord down_1_x, down_1_y, down_3_x, down_3_y;
39    Ecore_Timer *down_timer;
40 
41    Evas_Object *layout;
42    Evas_Object *events;
43    E_Gadget_Style_Cb style_cb;
44    E_Gadget_Context_Cb context_cb;
45    E_Gadget_Context_Cb context_cancel_cb;
46    int cur_size;
47    Ecore_Job *calc_job;
48 
49    E_Gadget_Config *action;
50    Ecore_Event_Handler *move_handler;
51    Ecore_Event_Handler *mouse_up_handler;
52 
53    Evas_Object *editor;
54 } E_Gadget_Site;
55 
56 
57 struct E_Gadget_Config
58 {
59    EINA_INLIST;
60    int id;
61    struct
62    {
63       Eina_Stringshare *domain;
64       Eina_Stringshare *type;
65    } external;
66    int zone;
67    Eina_Stringshare *type;
68    E_Object *e_obj_inherit;
69    Evas_Object *display;
70    Evas_Object *gadget;
71    struct
72    {
73       Evas_Object *obj;
74       int minw, minh;
75       Eina_Stringshare *name;
76    } style;
77    E_Gadget_Configure_Cb configure;
78    Evas_Object *cfg_object;
79    E_Gadget_Menu_Populate_Cb populate;
80    Eina_List *popups;
81    E_Gadget_Site *site;
82    E_Menu *menu;
83 
84    struct
85    {
86       Evas_Object *popup;
87       Evas_Smart_Cb allow;
88       Evas_Smart_Cb deny;
89       void *data;
90    } allow_deny;
91 
92    Eina_Hash *drop_handlers;
93 
94    double x, y; //fixed % positioning
95    double w, h; //fixed % sizing
96    Evas_Point offset; //offset from mouse down
97    Evas_Point down; //coords from mouse down
98    E_Gadget_Config *orig; //gadget is a copy of the original gadget during a move
99    E_Gadget_Site_Anchor resizing;
100    Eina_Bool moving E_BITFIELD;
101    Eina_Bool display_del E_BITFIELD; //deleted using ->display
102 };
103 
104 typedef struct E_Gadget_Sites
105 {
106    Eina_List *sites;
107 } E_Gadget_Sites;
108 
109 typedef struct E_Gadget_External_Type
110 {
111    E_Gadget_External_Create_Cb cb;
112    E_Gadget_External_Wizard_Cb wizard;
113    E_Gadget_External_Name_Cb name;
114 } E_Gadget_External_Type;
115 
116 typedef struct E_Gadget_Type
117 {
118    E_Gadget_Create_Cb cb;
119    E_Gadget_Wizard_Cb wizard;
120 } E_Gadget_Type;
121 
122 typedef struct Gadget_Item
123 {
124    Evas_Object *box;
125    Evas_Object *editor;
126    Evas_Object *gadget;
127    Evas_Object *site;
128    Elm_Object_Item *it;
129 } Gadget_Item;
130 
131 #define DESKLOCK_DEMO_LAYER (E_LAYER_CLIENT_POPUP - 100)
132 
133 static Eina_List *desktop_handlers;
134 static Evas_Object *desktop_rect;
135 static Evas_Object *desktop_editor;
136 static Eina_Bool added;
137 
138 static Evas_Object *pointer_site;
139 static Eina_List *pointer_site_handlers;
140 
141 static Eina_Hash *gadget_external_domains;
142 static Eina_Hash *gadget_types;
143 static E_Gadget_Sites *sites;
144 static Eina_List *handlers;
145 
146 static Evas_Object *comp_site;
147 
148 static E_Action *move_act;
149 static E_Action *resize_act;
150 static E_Action *configure_act;
151 
152 static E_Config_DD *edd_sites;
153 static E_Config_DD *edd_site;
154 static E_Config_DD *edd_gadget;
155 
156 static void _gadget_object_finalize(E_Gadget_Config *zgc);
157 static Eina_Bool _gadget_object_create(E_Gadget_Config *zgc);
158 static void _editor_pointer_site_init(E_Gadget_Site_Orient orient, Evas_Object *site, Evas_Object *editor, Eina_Bool );
159 static void _gadget_drop_handler_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
160 static void _edit_site_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
161 
162 static void
_site_recalc_job_cb(E_Gadget_Site * zgs)163 _site_recalc_job_cb(E_Gadget_Site *zgs)
164 {
165    zgs->calc_job = NULL;
166    evas_object_smart_need_recalculate_set(zgs->layout, 1);
167 }
168 
169 static void
_site_recalc_job(E_Gadget_Site * zgs)170 _site_recalc_job(E_Gadget_Site *zgs)
171 {
172    if (zgs->calc_job) ecore_job_del(zgs->calc_job);
173    zgs->calc_job = ecore_job_add((Ecore_Cb)_site_recalc_job_cb, zgs);
174 }
175 
176 static E_Gadget_External_Type *
_gadget_external_type_get(const char * domain,const char * type)177 _gadget_external_type_get(const char *domain, const char *type)
178 {
179    Eina_Hash *h;
180    if (!gadget_external_domains) return NULL;
181    h = eina_hash_find(gadget_external_domains, domain);
182    if (!h) return NULL;
183    return eina_hash_find(h, type);
184 }
185 
186 static Eina_Bool
_editor_site_visible(void)187 _editor_site_visible(void)
188 {
189    Eina_List *l;
190    E_Gadget_Site *zgs;
191 
192    if (desktop_editor) return evas_object_visible_get(desktop_editor);
193    EINA_LIST_FOREACH(sites->sites, l, zgs)
194      if (zgs->editor && evas_object_visible_get(zgs->editor)) return EINA_TRUE;
195    return EINA_FALSE;
196 }
197 
198 static void
_comp_site_resize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)199 _comp_site_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
200 {
201    Eina_List *l;
202    E_Gadget_Config *zgc;
203 
204    evas_object_resize(data, e_comp->w, e_comp->h);
205    ZGS_GET(comp_site);
206    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
207      {
208         if (!zgc->display)
209           _gadget_object_create(zgc);
210         else if (!e_comp_zone_number_get(zgc->zone))
211           evas_object_del(zgc->display);
212      }
213 }
214 
215 static void
_gadget_free(E_Gadget_Config * zgc)216 _gadget_free(E_Gadget_Config *zgc)
217 {
218    if (zgc->menu)
219      {
220         e_menu_deactivate(zgc->menu);
221         e_object_del(E_OBJECT(zgc->menu));
222         zgc->menu = NULL;
223      }
224    evas_object_del(zgc->display);
225    eina_stringshare_del(zgc->type);
226    eina_stringshare_del(zgc->external.type);
227    eina_stringshare_del(zgc->external.domain);
228    eina_stringshare_del(zgc->style.name);
229    free(zgc);
230 }
231 
232 static E_Gadget_Config *
_gadget_at_xy(E_Gadget_Site * zgs,int x,int y,E_Gadget_Config * exclude)233 _gadget_at_xy(E_Gadget_Site *zgs, int x, int y, E_Gadget_Config *exclude)
234 {
235    Eina_List *l;
236    E_Gadget_Config *zgc, *saved = NULL;
237 
238    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
239      {
240         int ox, oy, ow, oh;
241 
242         if (!zgc->gadget) continue;
243 
244         evas_object_geometry_get(zgc->display, &ox, &oy, &ow, &oh);
245         if (E_INSIDE(x, y, ox, oy, ow, oh))
246           {
247              if (zgc == exclude) saved = zgc;
248              else return zgc;
249           }
250      }
251    return saved;
252 }
253 
254 static void
_gravity_apply(E_Gadget_Site * zgs,E_Gadget_Site_Gravity gravity)255 _gravity_apply(E_Gadget_Site *zgs, E_Gadget_Site_Gravity gravity)
256 {
257    double ax = 0.5, ay = 0.5;
258 
259    switch (gravity)
260      {
261       case E_GADGET_SITE_GRAVITY_LEFT:
262         ax = 0;
263         break;
264       case E_GADGET_SITE_GRAVITY_RIGHT:
265         ax = 1;
266         break;
267       default: break;
268      }
269    switch (gravity)
270      {
271       case E_GADGET_SITE_GRAVITY_TOP:
272         ay = 0;
273         break;
274       case E_GADGET_SITE_GRAVITY_BOTTOM:
275         ay = 1;
276         break;
277       default: break;
278      }
279    elm_box_align_set(zgs->layout, ax, ay);
280    evas_object_smart_callback_call(zgs->layout, "gadget_site_gravity", NULL);
281 }
282 
283 static void
_gadget_reparent(E_Gadget_Site * zgs,E_Gadget_Config * zgc)284 _gadget_reparent(E_Gadget_Site *zgs, E_Gadget_Config *zgc)
285 {
286    Eina_Inlist *l = EINA_INLIST_GET(zgc);
287    E_Gadget_Config *z;
288 
289    if (!zgs->orient)
290      {
291         evas_object_layer_set(zgc->display, evas_object_layer_get(zgs->layout));
292         evas_object_stack_below(zgc->display, zgs->events);
293         if (evas_object_visible_get(zgs->events))
294           evas_object_show(zgc->display);
295         return;
296      }
297    switch (zgs->gravity)
298      {
299       case E_GADGET_SITE_GRAVITY_NONE:
300         /* fake */
301         break;
302       case E_GADGET_SITE_GRAVITY_LEFT:
303       case E_GADGET_SITE_GRAVITY_TOP:
304         for (l = l->prev; l; l = l->prev)
305           {
306              z = EINA_INLIST_CONTAINER_GET(l, E_Gadget_Config);
307              if (!z->display) continue;
308              elm_box_pack_after(zgs->layout, zgc->display, z->display);
309              return;
310           }
311         elm_box_pack_end(zgs->layout, zgc->display);
312         break;
313       default:
314         for (l = l->next; l; l = l->next)
315           {
316              z = EINA_INLIST_CONTAINER_GET(l, E_Gadget_Config);
317              if (!z->display) continue;
318              elm_box_pack_before(zgs->layout, zgc->display, z->display);
319              return;
320           }
321         /* right aligned: pack on left */
322         elm_box_pack_start(zgs->layout, zgc->display);
323      }
324 }
325 
326 static void
_desktop_rect_obj_add(Evas_Object * obj)327 _desktop_rect_obj_add(Evas_Object *obj)
328 {
329    if (!desktop_rect) return;
330    evas_object_smart_member_add(obj, desktop_rect);
331    evas_object_propagate_events_set(obj, 0);
332    if (e_comp->autoclose.obj != obj) return;
333    evas_object_smart_member_add(e_comp->autoclose.rect, desktop_rect);
334    evas_object_propagate_events_set(e_comp->autoclose.rect, 0);
335 }
336 
337 static void
_gadget_popup_hide(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)338 _gadget_popup_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
339 {
340    E_Gadget_Config *zgc = data;
341    if (desktop_editor) evas_object_show(desktop_editor);
342    zgc->popups = eina_list_remove(zgc->popups, event_info);
343 }
344 
345 static void
_gadget_popup(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)346 _gadget_popup(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
347 {
348    E_Gadget_Config *zgc = data;
349    E_Gadget_Site *zgs = zgc->site;
350 
351    if (event_info && elm_object_widget_check(event_info))
352      elm_object_tree_focus_allow_set(event_info, 0);
353    if (event_info) _desktop_rect_obj_add(event_info);
354    evas_object_smart_callback_call(zgs->layout, "gadget_site_popup", event_info);
355    if (!event_info) return;
356    evas_object_event_callback_add(event_info, EVAS_CALLBACK_HIDE, _gadget_popup_hide, zgc);
357    if (desktop_editor) evas_object_hide(desktop_editor);
358    if (eina_list_data_find(zgc->popups, event_info))
359      ERR("gadget_popup called multiple times for same popup");
360    zgc->popups = eina_list_append(zgc->popups, event_info);
361 }
362 
363 static void
_gadget_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)364 _gadget_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
365 {
366    E_Gadget_Config *zgc = data;
367 
368    zgc->display_del = obj == zgc->display;
369    if (!e_object_is_del(zgc->e_obj_inherit))
370      e_object_del(zgc->e_obj_inherit);
371 }
372 
373 static void
_gadget_util_allow_deny_cleanup(E_Gadget_Config * zgc)374 _gadget_util_allow_deny_cleanup(E_Gadget_Config *zgc)
375 {
376    zgc->allow_deny.allow = zgc->allow_deny.deny = NULL;
377    zgc->allow_deny.data = NULL;
378    evas_object_hide(zgc->allow_deny.popup);
379    E_FREE_FUNC(zgc->allow_deny.popup, evas_object_del);
380 }
381 
382 static void
_gadget_drop_handler_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)383 _gadget_drop_handler_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
384 {
385    E_Gadget_Config *zgc = data;
386 
387    if (zgc->drop_handlers)//may be calling during object_free
388      eina_hash_del_by_key(zgc->drop_handlers, &obj);
389 }
390 
391 static void
_gadget_object_free(E_Object * eobj)392 _gadget_object_free(E_Object *eobj)
393 {
394    E_Gadget_Config *zgc;
395    Evas_Object *g;
396 
397    g = e_object_data_get(eobj);
398    zgc = evas_object_data_get(g, "__e_gadget");
399    evas_object_smart_callback_call(zgc->site->layout, "gadget_destroyed", zgc->gadget);
400    evas_object_event_callback_del_full(zgc->gadget, EVAS_CALLBACK_DEL, _gadget_del, zgc);
401    if (zgc->display_del || (zgc->gadget == zgc->display))
402      zgc->display = NULL;
403    else
404      {
405         evas_object_event_callback_del_full(zgc->display, EVAS_CALLBACK_DEL, _gadget_del, zgc);
406         E_FREE_FUNC(zgc->display, evas_object_del);
407      }
408    zgc->gadget = NULL;
409 
410    if (zgc->drop_handlers)
411      {
412         Evas_Object **drop_object;
413         Eina_Iterator *it = eina_hash_iterator_key_new(zgc->drop_handlers);
414 
415         EINA_ITERATOR_FOREACH(it, drop_object)
416           {
417              evas_object_event_callback_del(*drop_object, EVAS_CALLBACK_MOVE, _gadget_drop_handler_moveresize);
418              evas_object_event_callback_del(*drop_object, EVAS_CALLBACK_RESIZE, _gadget_drop_handler_moveresize);
419              evas_object_event_callback_del(*drop_object, EVAS_CALLBACK_DEL, _gadget_drop_handler_del);
420           }
421         eina_iterator_free(it);
422      }
423 
424    E_FREE_FUNC(zgc->drop_handlers, eina_hash_free);
425    E_FREE_FUNC(zgc->gadget, evas_object_del);
426    E_FREE_FUNC(zgc->cfg_object, evas_object_del);
427    E_FREE_FUNC(zgc->style.obj, evas_object_del);
428    _gadget_util_allow_deny_cleanup(zgc);
429    E_FREE(zgc->e_obj_inherit);
430    zgc->configure = NULL;
431    zgc->display_del = zgc->moving = zgc->resizing = 0;
432    if (zgc->id == -1) _gadget_free(zgc);
433 }
434 
435 static void
_gadget_remove(E_Gadget_Config * zgc)436 _gadget_remove(E_Gadget_Config *zgc)
437 {
438    int id = zgc->id;
439    evas_object_smart_callback_call(zgc->site->layout, "gadget_removed", zgc->gadget);
440    zgc->site->gadget_list = eina_inlist_remove(zgc->site->gadget_list, EINA_INLIST_GET(zgc));
441    zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
442    if (id >= 0)
443      {
444         _gadget_free(zgc);
445         e_config_save_queue();
446      }
447    else
448      evas_object_del(zgc->display);
449 }
450 
451 static void
_gadget_wizard_end(void * data,int id)452 _gadget_wizard_end(void *data, int id)
453 {
454    E_Gadget_Config *zgc = data;
455 
456    zgc->id = id;
457    evas_object_smart_callback_call(zgc->site->layout, "gadget_site_unlocked", NULL);
458    e_comp_ungrab_input(1, 1);
459    if (id > 0)
460      {
461         _gadget_object_finalize(zgc);
462         added = 0;
463      }
464    else
465      _gadget_remove(zgc);
466 }
467 
468 static void
_gadget_wizard_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)469 _gadget_wizard_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
470 {
471    E_Gadget_Config *zgc = data;
472 
473    if (zgc->cfg_object == obj) zgc->cfg_object = NULL;
474    if (desktop_editor) evas_object_show(desktop_editor);
475 }
476 
477 static void
_gadget_object_hints(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)478 _gadget_object_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
479 {
480    E_Gadget_Config *zgc = data;
481    _site_recalc_job(zgc->site);
482 }
483 
484 static Eina_Bool
_gadget_object_create(E_Gadget_Config * zgc)485 _gadget_object_create(E_Gadget_Config *zgc)
486 {
487    E_Gadget_Type *t = NULL;
488    E_Gadget_External_Type *te = NULL;
489    Evas_Object *g;
490 
491    if (zgc->external.domain)
492      {
493         te = _gadget_external_type_get(zgc->external.domain, zgc->external.type);
494         if (!te) return EINA_TRUE; //can't create yet
495      }
496    else
497      {
498         t = eina_hash_find(gadget_types, zgc->type);
499         if (!t) return EINA_TRUE; //can't create yet
500      }
501 
502    if (!zgc->id)
503      {
504         if ((t && t->wizard) || (te && te->wizard))
505           {
506              if (t)
507                zgc->cfg_object = t->wizard(_gadget_wizard_end, zgc, zgc->site->layout);
508              else
509                zgc->cfg_object = te->wizard(_gadget_wizard_end, zgc, zgc->external.type, zgc->site->layout);
510              if (!zgc->cfg_object)
511                {
512                   added = 1;
513                   if (desktop_editor) evas_object_show(desktop_editor);
514                   return EINA_FALSE;
515                }
516              e_comp_grab_input(1, 1);
517              evas_object_event_callback_add(zgc->cfg_object, EVAS_CALLBACK_DEL, _gadget_wizard_del, zgc);
518              _desktop_rect_obj_add(zgc->cfg_object);
519              evas_object_smart_callback_call(zgc->site->layout, "gadget_site_popup", zgc->cfg_object);
520              evas_object_smart_callback_call(zgc->site->layout, "gadget_site_locked", NULL);
521              return EINA_TRUE;
522           }
523      }
524    if (desktop_editor) evas_object_show(desktop_editor);
525    if ((zgc->zone >= 0) && (!e_comp_zone_number_get(zgc->zone))) return EINA_FALSE;
526    /* if id is < 0, gadget creates dummy config for demo use
527     * if id is 0, gadget creates new config and returns id
528     * otherwise, config of `id` is applied to created object
529     *
530     * a gadget should return NULL for any demo instance where it
531     * should not be shown
532     */
533    if (t)
534      g = t->cb(zgc->site->layout, &zgc->id, zgc->site->orient);
535    else
536      g = te->cb(zgc->site->layout, zgc->external.type, &zgc->id, zgc->site->orient);
537    if (zgc->id < 0)
538      {
539         if (!g) return EINA_FALSE;
540      }
541    EINA_SAFETY_ON_NULL_RETURN_VAL(g, EINA_FALSE);
542    added = 1;
543 
544    zgc->e_obj_inherit = E_OBJECT_ALLOC(E_Object, E_GADGET_TYPE, _gadget_object_free);
545    e_object_data_set(zgc->e_obj_inherit, g);
546    zgc->gadget = zgc->display = g;
547    evas_object_event_callback_add(g, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _gadget_object_hints, zgc);
548    evas_object_smart_callback_add(g, "gadget_popup", _gadget_popup, zgc);
549    evas_object_data_set(g, "__e_gadget", zgc);
550    if (zgc->site->style_cb)
551      zgc->site->style_cb(zgc->site->layout, zgc->style.name, g);
552 
553    if (!zgc->site->orient)
554      evas_object_smart_need_recalculate_set(zgc->site->layout, 1);
555    evas_object_event_callback_priority_add(g, EVAS_CALLBACK_DEL, EVAS_CALLBACK_PRIORITY_AFTER, _gadget_del, zgc);
556    _gadget_reparent(zgc->site, zgc);
557    if (elm_object_widget_check(zgc->gadget))
558      elm_object_tree_focus_allow_set(zgc->gadget, 0);
559    evas_object_raise(zgc->site->events);
560 
561    evas_object_smart_callback_call(zgc->site->layout, "gadget_created", g);
562    evas_object_show(zgc->display);
563    if (zgc->site->editor) _desktop_rect_obj_add(zgc->display);
564    return EINA_TRUE;
565 }
566 
567 static void
_gadget_object_finalize(E_Gadget_Config * zgc)568 _gadget_object_finalize(E_Gadget_Config *zgc)
569 {
570    zgc->moving = 0;
571    if (_gadget_object_create(zgc))
572      {
573         if (!zgc->display) return;
574         evas_object_smart_callback_call(zgc->site->layout, "gadget_added", zgc->gadget);
575         e_config_save_queue();
576         return;
577      }
578    zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
579    zgc->site->gadget_list = eina_inlist_remove(zgc->site->gadget_list, EINA_INLIST_GET(zgc));
580    eina_stringshare_del(zgc->type);
581    eina_stringshare_del(zgc->external.type);
582    eina_stringshare_del(zgc->external.domain);
583    free(zgc);
584 }
585 
586 static void
_site_gadget_aspect(E_Gadget_Config * zgc,Evas_Coord * ww,Evas_Coord * hh,int ax,int ay,Evas_Aspect_Control aspect)587 _site_gadget_aspect(E_Gadget_Config *zgc, Evas_Coord *ww, Evas_Coord *hh, int ax, int ay, Evas_Aspect_Control aspect)
588 {
589    if (aspect && ax && ay)
590      {
591         switch (aspect)
592           {
593            case EVAS_ASPECT_CONTROL_HORIZONTAL:
594              *hh = (*ww * (double)ay / ax) + 0.99999999;
595              break;
596            case EVAS_ASPECT_CONTROL_VERTICAL:
597              *ww = (*hh * (double)ax / ay) + 0.99999999;
598              break;
599            default:
600              if (IS_HORIZ(zgc->site->orient))
601                *ww = (*hh * (double)ax / ay) + 0.99999999;
602              else if (IS_VERT(zgc->site->orient))
603                *hh = (*ww * (double)ay / ax) + 0.99999999;
604              else if (aspect)
605                {
606                   double ar = ax / (double) ay;
607 
608                   if (ax == ay)
609                     {
610                        if (*ww > *hh)
611                          *hh = *ww;
612                        else
613                          *ww = *hh;
614                     }
615                   else if (ar > 1.0)
616                     *hh = (*ww * (double)ay / ax) + 0.99999999;
617                   else
618                     *ww = (*hh * (double)ax / ay) + 0.99999999;
619                }
620           }
621      }
622 }
623 
624 static Eina_Bool
_site_gadget_resize(Evas_Object * g,int w,int h,Evas_Coord * ww,Evas_Coord * hh,Evas_Coord * ow,Evas_Coord * oh)625 _site_gadget_resize(Evas_Object *g, int w, int h, Evas_Coord *ww, Evas_Coord *hh, Evas_Coord *ow, Evas_Coord *oh)
626 {
627    Evas_Coord mnw, mnh, mxw, mxh;
628    E_Gadget_Config *zgc;
629    Evas_Aspect_Control aspect;
630    int ax, ay;
631    double ex, ey;
632    Eina_Bool ret = EINA_FALSE;
633 
634    zgc = evas_object_data_get(g, "__e_gadget");
635    w -= zgc->style.minw;
636    h -= zgc->style.minh;
637 
638    evas_object_size_hint_min_get(g, &mnw, &mnh);
639    evas_object_size_hint_max_get(g, &mxw, &mxh);
640    evas_object_size_hint_aspect_get(g, &aspect, &ax, &ay);
641    evas_object_size_hint_weight_get(g, &ex, &ey);
642 
643    if (IS_HORIZ(zgc->site->orient))
644      {
645         *ww = mnw, *hh = h;
646         if (!(*ww)) *ww = *hh;
647         if (dblequal(ex, EVAS_HINT_EXPAND) && (!aspect)) ret = EINA_TRUE;
648      }
649    else if (IS_VERT(zgc->site->orient))
650      {
651         *hh = mnh, *ww = w;
652         if (!(*hh)) *hh = *ww;
653         if (dblequal(ey, EVAS_HINT_EXPAND) && (!aspect)) ret = EINA_TRUE;
654      }
655    else
656      {
657         *ww = mnw, *hh = mnh;
658         if ((!(*ww)) || ((*ww) < w)) *ww = w;
659         if ((!(*hh)) || ((*hh) < h)) *hh = h;
660      }
661    _site_gadget_aspect(zgc, ww, hh, ax, ay, aspect);
662    *ww += zgc->style.minw;
663    *hh += zgc->style.minh;
664    *ow = *ww, *oh = *hh;
665    if ((!ax) && (!ay))
666      {
667         if ((mxw >= 0) && (mxw < *ow)) *ow = mxw;
668         if ((mxh >= 0) && (mxh < *oh)) *oh = mxh;
669      }
670    if (!zgc->site->orient)
671      {
672         if ((w < (*ow)) || (h < (*oh)))
673           {
674              if (evas_smart_objects_calculating_get(e_comp->evas))
675                _site_recalc_job(zgc->site);
676              else
677                evas_object_smart_need_recalculate_set(zgc->site->layout, 1);
678           }
679      }
680    //fprintf(stderr, "%s: %dx%d\n", zgc->type, *ow, *oh);
681    evas_object_resize(zgc->display, *ow, *oh);
682    return ret;
683 }
684 
685 static void
_site_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)686 _site_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
687 {
688    int x, y, w, h;
689    E_Gadget_Site *zgs = data;
690 
691    evas_object_geometry_get(obj, &x, &y, &w, &h);
692    evas_object_geometry_set(zgs->events, x, y, w, h);
693    evas_object_raise(zgs->events);
694    if (!zgs->orient)
695      evas_object_smart_need_recalculate_set(zgs->layout, 1);
696 }
697 
698 static void
_site_layout_orient(Evas_Object * o,E_Gadget_Site * zgs)699 _site_layout_orient(Evas_Object *o, E_Gadget_Site *zgs)
700 {
701    Evas_Coord x, y, w, h, xx, yy;
702    Eina_List *l;
703    double ax, ay;
704    E_Gadget_Config *zgc;
705    int mw, mh, sw, sh, rw, rh, bw, bh, prev_w = 0, prev_h = 0;
706    int groups = 0, avg;
707    Eina_Bool prev_ex = 0, after = 0;
708    struct Size
709    {
710       Evas_Coord_Size size;
711       Evas_Coord_Size clipped;
712       Evas_Coord_Size before;
713       Evas_Coord_Size after;
714       Eina_Bool expand;
715       Evas_Object *obj;
716    } *size, *psize = NULL;
717    Eina_List *expand = NULL, *gadgets = NULL;
718    Evas_Coord_Size parent_size;
719 
720    evas_object_geometry_get(o, &x, &y, &w, &h);
721    if ((!w) && (!h)) return;
722    parent_size.w = parent_size.h = -1;
723    evas_object_smart_callback_call(elm_object_parent_widget_get(zgs->layout), "gadget_site_parent_size_request", &parent_size);
724    if ((parent_size.w < 0) || (parent_size.h < 0))
725      evas_object_geometry_get(elm_object_parent_widget_get(zgs->layout), NULL, NULL, &bw, &bh);
726    else
727      bw = parent_size.w, bh = parent_size.h;
728    rw = bw, rh = bh;
729    evas_object_size_hint_min_get(o, &mw, &mh);
730    evas_object_size_hint_min_get(zgs->layout, &sw, &sh);
731    evas_object_geometry_set(zgs->events, x, y, w, h);
732 
733    evas_object_box_align_get(o, &ax, &ay);
734 
735    xx = x;
736    yy = y;
737 
738    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
739      {
740         int ww, hh, ow, oh;
741         Eina_Bool ex;
742 
743         if (!zgc->display) continue;
744         ex = _site_gadget_resize(zgc->gadget, w, h, &ww, &hh, &ow, &oh);
745         if (ex && prev_ex)
746           {
747              /* multiple spacers */
748              evas_object_resize(zgc->display, 0, 0);
749              continue;
750           }
751         size = E_NEW(struct Size, 1);
752         size->size.w = ww;
753         size->size.h = hh;
754         size->clipped.w = ow;
755         size->clipped.h = oh;
756         size->expand = ex;
757         if (ex)
758           {
759              if (psize)
760                {
761                   psize->after.w = prev_w, psize->after.h = prev_h;
762                   groups++;
763                }
764              psize = size;
765              size->before.w = prev_w;
766              size->before.h = prev_h;
767              prev_w = prev_h = 0;
768           }
769         size->obj = zgc->display;
770         prev_w += ow;
771         prev_h += oh;
772         prev_ex = ex;
773         gadgets = eina_list_append(gadgets, size);
774         if (ex)
775           {
776              expand = eina_list_append(expand, size);
777              continue;
778           }
779         if (IS_HORIZ(zgs->orient))
780           rw = MAX(rw - ow, 0);
781         else if (IS_VERT(zgs->orient))
782           rh = MAX(rh - oh, 0);
783      }
784    if (expand)
785      {
786         size = eina_list_last_data_get(expand);
787         psize = eina_list_last_data_get(gadgets);
788         if (size != psize)
789           {
790              if ((!size->after.w) && (!size->after.h))
791                {
792                   size->after.w = prev_w, size->after.h = prev_h;
793                   groups++;
794                }
795           }
796         if (!groups) groups++;
797 
798         size = eina_list_data_get(expand);
799         if (IS_HORIZ(zgs->orient))
800           {
801              after = !size->before.w;
802              avg = (bw - rw) / groups;
803           }
804         else
805           {
806              after = !size->before.h;
807              avg = (bh - rh) / groups;
808           }
809      }
810    EINA_LIST_FREE(expand, size)
811      {
812         if (IS_HORIZ(zgs->orient))
813           {
814              if (rw)
815                {
816                   size->size.w = size->clipped.w = rw / eina_list_count(expand);
817                   if (eina_list_count(expand) > 1)
818                     {
819                        int gw;
820                        if (after)
821                          gw = size->after.w;
822                        else
823                          gw = size->before.w;
824                        if (gw > avg)
825                          size->size.w = size->clipped.w -= (gw - avg);
826                        else
827                          size->size.w = size->clipped.w += abs(gw - avg);
828                        size->size.w = size->clipped.w -= size->after.w / 2;
829                        size->size.w = size->clipped.w = MAX(size->size.w, 0);
830                        rw -= size->size.w;
831                     }
832                }
833              else
834                size->size.w = size->clipped.w = 0;
835           }
836         else if (IS_VERT(zgs->orient))
837           {
838              if (rh)
839                {
840                   size->size.h = size->clipped.h = rh / eina_list_count(expand);
841                   if (eina_list_count(expand) > 1)
842                     {
843                        int gh;
844                        if (after)
845                          gh = size->after.h;
846                        else
847                          gh = size->before.h;
848                        if (gh > avg)
849                          size->size.h = size->clipped.h -= (gh - avg);
850                        else
851                          size->size.h = size->clipped.h += abs(gh - avg);
852                        size->size.h = size->clipped.h -= size->after.h / 2;
853                        size->size.h = size->clipped.h = MAX(size->size.h, 0);
854                        rh -= size->size.h;
855                     }
856                }
857              else
858                size->size.h = size->clipped.h = 0;
859           }
860         evas_object_resize(size->obj, size->clipped.w, size->clipped.h);
861      }
862 
863    if (zgs->gravity % 2)//left/top
864      {
865         EINA_LIST_FREE(gadgets, size)
866           {
867              Evas_Coord gx = xx, gy = yy;
868 
869              if (IS_HORIZ(zgs->orient))
870                gx += (Evas_Coord)(((double)(size->size.w - size->clipped.w)) * 0.5),
871                gy += (h / 2) - (size->clipped.h / 2);
872              else if (IS_VERT(zgs->orient))
873                gy += (Evas_Coord)(((double)(size->size.h - size->clipped.h)) * 0.5),
874                gx += (w / 2) - (size->clipped.w / 2);
875              evas_object_move(size->obj, gx, gy);
876              if (IS_HORIZ(zgs->orient))
877                xx += size->clipped.w;
878              else
879                yy += size->clipped.h;
880              free(size);
881           }
882      }
883    else if (zgs->gravity)
884      {
885         if (IS_HORIZ(zgs->orient))
886           xx += w;
887         else
888           yy += h;
889 
890         E_LIST_REVERSE_FREE(gadgets, size)
891           {
892              Evas_Coord gx = xx, gy = yy;
893 
894              if (IS_HORIZ(zgs->orient))
895                gx -= (Evas_Coord)(((double)(size->size.w - size->clipped.w)) * 0.5) + size->clipped.w,
896                gy += (h / 2) - (size->clipped.h / 2);
897              else
898                gy -= (Evas_Coord)(((double)(size->size.h - size->clipped.h)) * 0.5) + size->clipped.h,
899                gx += (w / 2) - (size->clipped.w / 2);
900              evas_object_move(size->obj, gx, gy);
901              if (IS_HORIZ(zgs->orient))
902                xx -= size->clipped.w;
903              else
904                yy -= size->clipped.h;
905              free(size);
906           }
907      }
908 
909    if (IS_HORIZ(zgs->orient))
910      zgs->cur_size = abs(xx - x);
911    else if (IS_VERT(zgs->orient))
912      zgs->cur_size = abs(yy - y);
913 
914    w = IS_HORIZ(zgs->orient) ? zgs->cur_size : w;
915    h = IS_VERT(zgs->orient) ? zgs->cur_size : h;
916    if ((w == mw) && (h == mh) && (sw == sh) && (sw == -1))
917      {
918         /* FIXME: https://phab.enlightenment.org/T4747 */
919         evas_object_size_hint_min_set(o, -1, -1);
920      }
921    evas_object_size_hint_min_set(o, w, h);
922 }
923 
924 static void
_site_layout(Evas_Object * o,Evas_Object_Box_Data * priv EINA_UNUSED,void * data)925 _site_layout(Evas_Object *o, Evas_Object_Box_Data *priv EINA_UNUSED, void *data)
926 {
927    E_Gadget_Site *zgs = data;
928    Evas_Coord x, y, w, h;//, px, py;
929    Eina_List *l;
930    double ax, ay;
931    E_Gadget_Config *zgc;
932 
933    evas_object_geometry_get(o, &x, &y, &w, &h);
934    evas_object_geometry_set(zgs->events, x, y, w, h);
935 
936    evas_object_box_align_get(o, &ax, &ay);
937 
938    if (zgs->orient)
939      {
940         _site_layout_orient(o, zgs);
941         return;
942      }
943    if ((!w) || (!h)) return;
944    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
945      {
946         Evas_Coord gx = x, gy = y;
947         int ww, hh, ow, oh;
948         E_Zone *zone;
949 
950         if (!zgc->display) continue;
951         if (zgc->moving)
952           {
953              if (zgs->layout != pointer_site) continue;
954              _site_gadget_resize(zgc->gadget, w, h, &ww, &hh, &ow, &oh);
955           }
956         else
957           {
958              if (zgc->zone >= 0)
959                {
960                   zone = e_comp_zone_number_get(zgc->zone);
961                   x = gx = zone->x;
962                   y = gy = zone->y;
963                   w = zone->w;
964                   h = zone->h;
965                }
966 
967              _site_gadget_resize(zgc->gadget, w * zgc->w, h * zgc->h, &ww, &hh, &ow, &oh);
968              if (zgc->x > -1.0)
969                {
970                   gx = x + zgc->x * w;
971                   gx += (Evas_Coord)(((double)(ww - ow)) * 0.5 * -ax);
972                }
973              if (zgc->y > -1.0)
974                {
975                   gy = y + zgc->y * h;
976                   gy += (Evas_Coord)(((double)(hh - oh)) * 0.5 * -ay);
977                }
978           }
979         if (zgs->gravity)
980           {
981 #if 0//FIXME
982              if (zgs->gravity % 2)//left/top
983                {
984                   if (gx < px) gx = px;
985                }
986              else if ()
987                {
988                   if (gx > px) gx = px;
989                }
990 
991              if (zgs->gravity % 2)//left/top
992                {
993                   if (gy < py) gy = py;
994                }
995              else
996                {
997                   if (gy > py) gy = py;
998                }
999 #endif
1000           }
1001 
1002              evas_object_move(zgc->display, gx, gy);
1003 #if 0//FIXME
1004         if (zgs->gravity is horizontal or something)
1005           px = gx + (-ax * ow);
1006         else
1007           py = gy + (-ay * oh);
1008 #endif
1009         if (eina_list_count(zgs->gadgets) == 1)
1010           {
1011              int mw, mh, sw, sh;
1012 
1013              evas_object_size_hint_min_get(o, &mw, &mh);
1014              evas_object_size_hint_min_get(zgs->layout, &sw, &sh);
1015              if ((ow == mw) && (oh == mh) && (sw == sh) && (sw == -1))
1016                {
1017                   /* FIXME: https://phab.enlightenment.org/T4747 */
1018                   evas_object_size_hint_min_set(o, -1, -1);
1019                }
1020              evas_object_size_hint_min_set(o, ow, oh);
1021           }
1022      }
1023 }
1024 
1025 static Eina_Bool
_gadget_mouse_resize(E_Gadget_Config * zgc,int t EINA_UNUSED,Ecore_Event_Mouse_Move * ev)1026 _gadget_mouse_resize(E_Gadget_Config *zgc, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
1027 {
1028    int x, y, w, h;//site geom
1029    int ox, oy, ow, oh;//gadget geom
1030    double gw, gh;
1031    int dx, dy;
1032    int ax, ay;
1033    Evas_Aspect_Control aspect;
1034 
1035    evas_object_geometry_get(zgc->display, &ox, &oy, &ow, &oh);
1036    evas_object_size_hint_aspect_get(zgc->gadget, &aspect, &ax, &ay);
1037    if (zgc->zone >= 0)
1038      {
1039         E_Zone *zone;
1040 
1041         zone = e_comp_zone_number_get(zgc->zone);
1042         x = zone->x, y = zone->y, w = zone->w, h = zone->h;
1043      }
1044    else
1045      evas_object_geometry_get(zgc->site->layout, &x, &y, &w, &h);
1046    /* restore screen-based geometry to canvas size */
1047    gw = zgc->w * w;
1048    gh = zgc->h * h;
1049 
1050    /* apply mouse movement to canvas size */
1051    dx = ev->x - zgc->down.x, dy = ev->y - zgc->down.y;
1052    if (zgc->resizing & E_GADGET_SITE_ANCHOR_LEFT)
1053      gw -= dx;
1054    else
1055      gw += dx;
1056    if (zgc->resizing & E_GADGET_SITE_ANCHOR_TOP)
1057      gh -= dy;
1058    else
1059      gh += dy;
1060 
1061    /* apply aspect based on mouse position change */
1062    dx = abs(ev->x - zgc->down.x);
1063    dy = abs(ev->y - zgc->down.y);
1064    if (dx > dy)
1065      {
1066         /* use horizontal motion if most of event is horizontal */
1067         int ww = lround(gw), hh = lround(gh);
1068         _site_gadget_aspect(zgc, &ww, &hh, ax, ay, EVAS_ASPECT_CONTROL_HORIZONTAL);
1069         gh = hh;
1070      }
1071    else if (dy > dx)
1072      {
1073         /* use vertical motion if most of event is vertical */
1074         int ww = lround(gw), hh = lround(gh);
1075         _site_gadget_aspect(zgc, &ww, &hh, ax, ay, EVAS_ASPECT_CONTROL_VERTICAL);
1076         gw = ww;
1077      }
1078    else if ((dx == dy) && (ax != ay))
1079      {
1080         /* use aspect values to calculate equal motion on both axes */
1081         int ww = lround(gw), hh = lround(gh);
1082         if (ax > ay)
1083           {
1084              _site_gadget_aspect(zgc, &ww, &hh, ax, ay, EVAS_ASPECT_CONTROL_VERTICAL);
1085              gw = ww;
1086           }
1087         else
1088           {
1089              _site_gadget_aspect(zgc, &ww, &hh, ax, ay, EVAS_ASPECT_CONTROL_HORIZONTAL);
1090              gh = hh;
1091           }
1092      }
1093 
1094    /* calculate new position based on resize amount */
1095    dx = ev->x - zgc->down.x, dy = ev->y - zgc->down.y;
1096    if (zgc->resizing & E_GADGET_SITE_ANCHOR_LEFT)
1097      {
1098         zgc->x = (((zgc->x + zgc->w) * (double)w) - gw) / (double)w;
1099      }
1100    if (zgc->resizing & E_GADGET_SITE_ANCHOR_TOP)
1101      {
1102         zgc->y = (((zgc->y + zgc->h) * (double)h) - gh) / (double)h;
1103      }
1104 
1105    zgc->w = gw / w;
1106    zgc->h = gh / h;
1107    zgc->down.x = ev->x;
1108    zgc->down.y = ev->y;
1109    evas_object_smart_need_recalculate_set(zgc->site->layout, 1);
1110    e_config_save_queue();
1111    return ECORE_CALLBACK_RENEW;
1112 }
1113 
1114 static void
_gadget_util_add(E_Gadget_Site * zgs,const char * domain,const char * type,int id)1115 _gadget_util_add(E_Gadget_Site *zgs, const char *domain, const char *type, int id)
1116 {
1117    E_Gadget_Config *zgc;
1118 
1119    zgc = E_NEW(E_Gadget_Config, 1);
1120    zgc->id = id;
1121    if (domain)
1122      {
1123         zgc->external.domain = eina_stringshare_add(domain);
1124         zgc->external.type = eina_stringshare_add(type);
1125      }
1126    else
1127      zgc->type = eina_stringshare_add(type);
1128    zgc->x = zgc->y = -1;
1129    zgc->site = zgs;
1130    zgc->zone = -1;
1131    if (zgc->site->orient)
1132      zgc->w = zgc->h = -1;
1133    else
1134      {
1135         E_Zone *zone = e_zone_current_get();
1136         zgc->w = (96 * e_scale) / (double)zone->w;
1137         zgc->h = (96 * e_scale) / (double)zone->h;
1138      }
1139    zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);
1140    zgs->gadget_list = eina_inlist_append(zgs->gadget_list, EINA_INLIST_GET(zgc));
1141    _gadget_object_finalize(zgc);
1142 }
1143 
1144 static Eina_Bool
_gadget_act_resize_end(E_Object * obj,const char * params EINA_UNUSED,E_Binding_Event_Mouse_Button * ev EINA_UNUSED)1145 _gadget_act_resize_end(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
1146 {
1147    E_Gadget_Config *zgc;
1148    Evas_Object *g;
1149 
1150    if (obj->type != E_GADGET_TYPE) return EINA_FALSE;
1151    g = e_object_data_get(obj);
1152    zgc = evas_object_data_get(g, "__e_gadget");
1153    zgc->resizing = 0;
1154 
1155    E_FREE_FUNC(zgc->site->move_handler, ecore_event_handler_del);
1156    evas_object_smart_need_recalculate_set(zgc->site->layout, 1);
1157    return EINA_TRUE;
1158 }
1159 
1160 static void
_gadget_popups_clear(E_Gadget_Config * zgc)1161 _gadget_popups_clear(E_Gadget_Config *zgc)
1162 {
1163    Eina_List *l, *ll;
1164    Evas_Object *popup;
1165 
1166    EINA_LIST_FOREACH_SAFE(zgc->popups, l, ll, popup)
1167      evas_object_del(popup);
1168 }
1169 
1170 static Eina_Bool
_gadget_act_move(E_Object * obj,const char * params EINA_UNUSED,E_Binding_Event_Mouse_Button * ev EINA_UNUSED)1171 _gadget_act_move(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
1172 {
1173    E_Gadget_Config *zgc, *z;
1174    Evas_Object *g;
1175    int w, h;
1176 
1177    if (obj->type != E_GADGET_TYPE) return EINA_FALSE;
1178 
1179    g = e_object_data_get(obj);
1180    zgc = evas_object_data_get(g, "__e_gadget");
1181    zgc->moving = 1;
1182    _editor_pointer_site_init(zgc->site->orient, NULL, NULL, 1);
1183    e_gadget_site_owner_setup(pointer_site, zgc->site->anchor, NULL, NULL, NULL);
1184    ZGS_GET(pointer_site);
1185    if (zgc->external.domain)
1186      _gadget_util_add(zgs, zgc->external.domain, zgc->external.type, zgc->id);
1187    else
1188      _gadget_util_add(zgs, NULL, zgc->type, zgc->id);
1189    z = eina_list_data_get(zgs->gadgets);
1190    if (!z)
1191      {
1192         E_FREE_FUNC(pointer_site, evas_object_del);
1193         zgc->moving = 0;
1194         return EINA_TRUE;
1195      }
1196    _gadget_popups_clear(zgc);
1197    z->moving = 1;
1198    evas_object_pass_events_set(zgc->site->layout, 1);
1199    evas_object_geometry_get(g, NULL, NULL, &w, &h);
1200    evas_object_resize(pointer_site, w, h);
1201    eina_stringshare_refplace(&z->style.name, zgc->style.name);
1202    z->orig = zgc;
1203    return EINA_TRUE;
1204 }
1205 
1206 static Eina_Bool
_gadget_act_resize(E_Object * obj,const char * params EINA_UNUSED,E_Binding_Event_Mouse_Button * ev)1207 _gadget_act_resize(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev)
1208 {
1209    E_Gadget_Config *zgc;
1210    Evas_Object *g;
1211    int x, y, w, h;
1212 
1213    if (obj->type != E_GADGET_TYPE) return EINA_FALSE;
1214 
1215    g = e_object_data_get(obj);
1216    zgc = evas_object_data_get(g, "__e_gadget");
1217    if (zgc->site->orient) return EINA_FALSE;
1218    _gadget_popups_clear(zgc);
1219    evas_object_geometry_get(g, &x, &y, &w, &h);
1220    if (ev->canvas.x < x + (w / 3))
1221      zgc->resizing = E_GADGET_SITE_ANCHOR_LEFT;
1222    else if (ev->canvas.x > x + (w * 2 / 3))
1223      zgc->resizing = E_GADGET_SITE_ANCHOR_RIGHT;
1224    if (ev->canvas.y < y + (h / 3))
1225      zgc->resizing |= E_GADGET_SITE_ANCHOR_TOP;
1226    else if (ev->canvas.y > y + (h * 2 / 3))
1227      zgc->resizing |= E_GADGET_SITE_ANCHOR_BOTTOM;
1228    if (!zgc->site->move_handler)
1229      zgc->site->move_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, (Ecore_Event_Handler_Cb)_gadget_mouse_resize, zgc);
1230    return EINA_TRUE;
1231 }
1232 
1233 static void
_gadget_act_configure_object_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1234 _gadget_act_configure_object_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1235 {
1236    E_Gadget_Config *zgc = data;
1237 
1238    zgc->cfg_object = NULL;
1239 }
1240 
1241 static void
_gadget_configure(E_Gadget_Config * zgc)1242 _gadget_configure(E_Gadget_Config *zgc)
1243 {
1244    if (!zgc->configure) return;
1245    if (zgc->cfg_object)
1246      {
1247         evas_object_raise(zgc->cfg_object);
1248         evas_object_show(zgc->cfg_object);
1249         return;
1250      }
1251    zgc->cfg_object = zgc->configure(zgc->gadget);
1252    if (!zgc->cfg_object) return;
1253    evas_object_event_callback_add(zgc->cfg_object, EVAS_CALLBACK_DEL, _gadget_act_configure_object_del, zgc);
1254    evas_object_smart_callback_call(zgc->display, "gadget_popup", zgc->cfg_object);
1255 }
1256 
1257 static void
_gadget_menu_populate(E_Gadget_Config * zgc,E_Menu * m)1258 _gadget_menu_populate(E_Gadget_Config *zgc, E_Menu *m)
1259 {
1260    if (!zgc->populate) return;
1261    zgc->populate(zgc->gadget, m);
1262 }
1263 
1264 static Eina_Bool
_gadget_act_configure(E_Object * obj,const char * params EINA_UNUSED,E_Binding_Event_Mouse_Button * ev EINA_UNUSED)1265 _gadget_act_configure(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
1266 {
1267    E_Gadget_Config *zgc;
1268    Evas_Object *g;
1269 
1270    if (obj->type != E_GADGET_TYPE) return EINA_FALSE;
1271 
1272    g = e_object_data_get(obj);
1273    zgc = evas_object_data_get(g, "__e_gadget");
1274    _gadget_configure(zgc);
1275    return EINA_TRUE;
1276 }
1277 
1278 static void
_gadget_menu_remove(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)1279 _gadget_menu_remove(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
1280 {
1281    E_Gadget_Config *zgc = data;
1282 
1283    _gadget_remove(zgc);
1284 }
1285 
1286 static void
_gadget_menu_configure(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)1287 _gadget_menu_configure(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
1288 {
1289    _gadget_configure(data);
1290 }
1291 
1292 static void
_gadget_style_menu_item_del(void * mi)1293 _gadget_style_menu_item_del(void *mi)
1294 {
1295    eina_stringshare_del(e_object_data_get(mi));
1296 }
1297 
1298 static void
_gadget_menu_style(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)1299 _gadget_menu_style(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
1300 {
1301    E_Gadget_Config *zgc = data;
1302    Eina_Stringshare *style = e_object_data_get(E_OBJECT(mi));
1303 
1304    eina_stringshare_refplace(&zgc->style.name, style);
1305    if (zgc->site->style_cb)
1306      zgc->site->style_cb(zgc->site->layout, style, zgc->gadget);
1307 }
1308 
1309 static void
_gadget_menu(Evas_Object * g,unsigned int timestamp)1310 _gadget_menu(Evas_Object *g, unsigned int timestamp)
1311 {
1312    E_Gadget_Config *zgc;
1313    E_Menu_Item *mi;
1314    E_Menu *subm;
1315    int x, y;
1316 
1317    zgc = evas_object_data_get(g, "__e_gadget");
1318    _gadget_popups_clear(zgc);
1319 
1320    zgc->menu = e_menu_new();
1321    e_menu_hold_mode_set(zgc->menu, EINA_FALSE);
1322    if (zgc->type)
1323      {
1324         char buf[1024];
1325 
1326         strncpy(buf, zgc->type, sizeof(buf) - 1);
1327         buf[0] = toupper(buf[0]);
1328         e_menu_title_set(zgc->menu, buf);
1329      }
1330    evas_object_smart_callback_call(g, "gadget_menu", zgc->menu);
1331    if (zgc->configure)
1332      {
1333         mi = e_menu_item_new(zgc->menu);
1334         e_menu_item_label_set(mi, _("Settings"));
1335         e_util_menu_item_theme_icon_set(mi, "configure");
1336         e_menu_item_callback_set(mi, _gadget_menu_configure, zgc);
1337      }
1338    if (zgc->menu->items)
1339      {
1340         mi = e_menu_item_new(zgc->menu);
1341         e_menu_item_separator_set(mi, 1);
1342      }
1343    subm = e_menu_new();
1344    e_menu_hold_mode_set(subm, EINA_FALSE);
1345    evas_object_smart_callback_call(zgc->site->layout, "gadget_site_style_menu", subm);
1346    if (e_object_data_get(E_OBJECT(subm)))
1347      {
1348         Eina_List *styles = e_object_data_get(E_OBJECT(subm));
1349         Eina_Stringshare *style;
1350 
1351         mi = e_menu_item_new(zgc->menu);
1352         e_menu_item_label_set(mi, _("Look"));
1353         e_util_menu_item_theme_icon_set(mi, "preferences-look");
1354         e_menu_item_submenu_set(mi, subm);
1355         e_object_unref(E_OBJECT(subm));
1356 
1357         EINA_LIST_FREE(styles, style)
1358           {
1359              char buf[1024];
1360 
1361              if (eina_streq(style, "base"))
1362                {
1363                   eina_stringshare_del(style);
1364                   continue;
1365                }
1366              mi = e_menu_item_new(subm);
1367              strncpy(buf, style, sizeof(buf) - 1);
1368              buf[0] = toupper(buf[0]);
1369              e_menu_item_label_set(mi, buf);
1370              snprintf(buf, sizeof(buf), "enlightenment/%s", style);
1371              e_util_menu_item_theme_icon_set(mi, buf);
1372              e_menu_item_radio_group_set(mi, 1);
1373              e_menu_item_radio_set(mi, 1);
1374              e_menu_item_toggle_set(mi, style == zgc->style.name);
1375              e_menu_item_disabled_set(mi, mi->toggle);
1376              e_object_data_set(E_OBJECT(mi), style);
1377              E_OBJECT_DEL_SET(mi, _gadget_style_menu_item_del);
1378              e_menu_item_callback_set(mi, _gadget_menu_style, zgc);
1379           }
1380      }
1381    else
1382      e_object_del(E_OBJECT(subm));
1383 
1384 
1385    mi = e_menu_item_new(zgc->menu);
1386    evas_object_smart_callback_call(zgc->site->layout, "gadget_site_owner_menu", mi);
1387    if (mi->label)
1388      {
1389         mi = e_menu_item_new(zgc->menu);
1390         e_menu_item_separator_set(mi, 1);
1391      }
1392    else
1393      e_object_del(E_OBJECT(mi));
1394 
1395    mi = e_menu_item_new(zgc->menu);
1396    e_menu_item_label_set(mi, _("Delete"));
1397    e_util_menu_item_theme_icon_set(mi, "list-remove");
1398    e_menu_item_callback_set(mi, _gadget_menu_remove, zgc);
1399 
1400    evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
1401    e_menu_activate_mouse(zgc->menu,
1402                          e_zone_current_get(),
1403                          x, y, 1, 1,
1404                          E_MENU_POP_DIRECTION_AUTO, timestamp);
1405    _desktop_rect_obj_add(zgc->menu->comp_object);
1406    evas_object_smart_callback_call(zgc->site->layout, "gadget_site_popup", zgc->menu->comp_object);
1407 }
1408 
1409 static void
_gadget_menu_cancel(Evas_Object * g,unsigned int timestamp EINA_UNUSED)1410 _gadget_menu_cancel(Evas_Object *g, unsigned int timestamp EINA_UNUSED)
1411 {
1412    E_Gadget_Config *zgc;
1413 
1414    zgc = evas_object_data_get(g, "__e_gadget");
1415    if (zgc->menu)
1416      {
1417         e_menu_deactivate(zgc->menu);
1418         e_object_del(E_OBJECT(zgc->menu));
1419         zgc->menu = NULL;
1420      }
1421 }
1422 
1423 static Eina_Bool
_site_longpress_menu(void * data)1424 _site_longpress_menu(void *data)
1425 {
1426    E_Gadget_Site *zgs = data;
1427    E_Gadget_Config *zgc;
1428    Evas_Object *g = NULL;
1429 
1430    zgs->down_timer = NULL;
1431    zgs->longpressed = EINA_TRUE;
1432    zgc = _gadget_at_xy(zgs, zgs->down_1_x, zgs->down_1_y, NULL);
1433    if (zgc) g = zgc->gadget;
1434    if (zgs->context_cb) zgs->context_cb(zgs->layout, g, ecore_loop_time_get() * 1000);
1435    return EINA_FALSE;
1436 }
1437 
1438 static Eina_Bool
_site_mouse_up_handle(E_Gadget_Site * zgs,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)1439 _site_mouse_up_handle(E_Gadget_Site *zgs, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
1440 {
1441    if (e_bindings_mouse_up_ecore_event_handle(E_BINDING_CONTEXT_ANY, zgs->action->e_obj_inherit, ev))
1442      {
1443         evas_object_pointer_mode_set(zgs->events, EVAS_OBJECT_POINTER_MODE_NOGRAB);
1444         zgs->action = NULL;
1445         E_FREE_FUNC(zgs->mouse_up_handler, ecore_event_handler_del);
1446      }
1447    return ECORE_CALLBACK_RENEW;
1448 }
1449 
1450 static void
_site_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1451 _site_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1452 {
1453    E_Gadget_Site *zgs = data;
1454    E_Gadget_Config *zgc;
1455    Evas_Event_Mouse_Down *ev = event_info;
1456    E_Action *act;
1457 
1458    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1459    zgc = _gadget_at_xy(zgs, ev->output.x, ev->output.y, NULL);
1460    if (zgc)
1461      {
1462         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1463         act = e_bindings_mouse_down_evas_event_handle(E_BINDING_CONTEXT_ANY, zgc->e_obj_inherit, event_info);
1464         if (!act) ev->event_flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
1465 	else if (act->func.end_mouse)
1466           {
1467              int x, y;
1468 
1469              evas_object_pointer_mode_set(obj, EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN);
1470              zgs->action = zgc;
1471              if (!zgs->mouse_up_handler)
1472                zgs->mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, (Ecore_Event_Handler_Cb)_site_mouse_up_handle, zgs);
1473 
1474              evas_object_geometry_get(zgc->display, &x, &y, NULL, NULL);
1475              zgc->offset.x = ev->canvas.x - x;
1476              zgc->offset.y = ev->canvas.y - y;
1477              zgc->down.x = ev->canvas.x;
1478              zgc->down.y = ev->canvas.y;
1479           }
1480 	if (act) return;
1481      }
1482    if (ev->button == 1)
1483      {
1484         zgs->longpressed = EINA_FALSE;
1485         zgs->dragged = EINA_FALSE;
1486         zgs->down_1_x = ev->canvas.x;
1487         zgs->down_1_y = ev->canvas.y;
1488         E_FREE_FUNC(zgs->down_timer, ecore_timer_del);
1489         zgs->down_timer = ecore_timer_add(1.0, _site_longpress_menu, zgs);
1490      }
1491    else if (ev->button == 3)
1492      {
1493         zgs->down_3_x = ev->canvas.x;
1494         zgs->down_3_y = ev->canvas.y;
1495      }
1496 }
1497 
1498 static void
_site_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1499 _site_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1500 {
1501    E_Gadget_Site *zgs = data;
1502    Evas_Event_Mouse_Up *ev = event_info;
1503 
1504    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1505    if (ev->button == 1)
1506      {
1507         E_FREE_FUNC(zgs->down_timer, ecore_timer_del);
1508         if ((zgs->longpressed) || (zgs->dragged))
1509           {
1510              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1511              zgs->longpressed = EINA_FALSE;
1512              zgs->dragged = EINA_FALSE;
1513           }
1514      }
1515    else if (ev->button == 3)
1516      {
1517         if (!is_dragged(ev->canvas.x - zgs->down_3_x,
1518                         ev->canvas.y - zgs->down_3_y))
1519           {
1520              E_Gadget_Config *zgc;
1521              Evas_Object *g = NULL;
1522 
1523              zgc = _gadget_at_xy(zgs, zgs->down_3_x, zgs->down_3_y, NULL);
1524              if (zgc) g = zgc->gadget;
1525              if (zgs->context_cb) zgs->context_cb(zgs->layout, g, ev->timestamp);
1526              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1527           }
1528      }
1529 }
1530 
1531 static void
_site_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1532 _site_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1533 {
1534    E_Gadget_Site *zgs = data;
1535    Evas_Event_Mouse_Move *ev = event_info;
1536 
1537    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1538 
1539    if ((zgs->down_timer) || (zgs->longpressed))
1540      {
1541         if (is_dragged(ev->cur.canvas.x - zgs->down_1_x,
1542                        ev->cur.canvas.y - zgs->down_1_y))
1543           {
1544              if (zgs->down_timer)
1545                {
1546                   E_FREE_FUNC(zgs->down_timer, ecore_timer_del);
1547                }
1548              if (!zgs->dragged)
1549                {
1550                   E_Gadget_Config *zgc;
1551                   Evas_Object *g = NULL;
1552 
1553                   zgs->dragged = EINA_TRUE;
1554                   zgc = _gadget_at_xy(zgs, zgs->down_1_x, zgs->down_1_y, NULL);
1555                   if (zgc) g = zgc->gadget;
1556                   if (zgs->context_cancel_cb) zgs->context_cancel_cb(zgs->layout, g, ev->timestamp);
1557                }
1558           }
1559      }
1560 }
1561 
1562 static void
_site_drop(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)1563 _site_drop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
1564 {
1565    E_Gadget_Site *zgs = data, *drop;
1566    Eina_List *l;
1567    E_Gadget_Config *zgc, *dzgc;
1568    int mx, my;
1569    int x, y, w, h;
1570 
1571    drop = evas_object_data_get(event_info, "__e_gadget_site");
1572    evas_pointer_canvas_xy_get(e_comp->evas, &mx, &my);
1573    evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
1574    if (!E_INSIDE(mx, my, x, y, w, h)) return;
1575 
1576    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
1577      {
1578         if (!zgc->display) continue;
1579 
1580         evas_object_geometry_get(zgc->display, &x, &y, &w, &h);
1581         if (E_INSIDE(mx, my, x, y, w, h)) break;
1582      }
1583    if (zgc)
1584      {
1585         Eina_Bool pre = EINA_FALSE;
1586         if (IS_HORIZ(zgs->orient))
1587           {
1588              if (mx <= x + (w / 2))
1589                pre = EINA_TRUE;
1590           }
1591         else if (IS_VERT(zgs->orient))
1592           {
1593              if (my <= y + (h / 2))
1594                pre = EINA_TRUE;
1595           }
1596         else {} //FIXME
1597         if (zgs->orient)
1598           {
1599              Eina_List *ll;
1600 
1601              if (pre)
1602                EINA_LIST_REVERSE_FOREACH(drop->gadgets, ll, dzgc)
1603                  {
1604                     evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->gadget);
1605                     if (dzgc->id == -1) dzgc->id = 0;
1606                     evas_object_del(dzgc->gadget);
1607                     zgs->gadget_list = eina_inlist_prepend_relative(zgs->gadget_list,
1608                       EINA_INLIST_GET(dzgc), EINA_INLIST_GET(zgc));
1609                     zgs->gadgets = eina_list_prepend_relative_list(zgs->gadgets, dzgc, l);
1610                     dzgc->site = zgs;
1611                     dzgc->zone = -1;
1612                     _gadget_object_finalize(dzgc);
1613                  }
1614              else
1615                EINA_LIST_REVERSE_FOREACH(drop->gadgets, ll, dzgc)
1616                  {
1617                     evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->gadget);
1618                     if (dzgc->id == -1) dzgc->id = 0;
1619                     evas_object_del(dzgc->gadget);
1620                     zgs->gadget_list = eina_inlist_append_relative(zgs->gadget_list,
1621                       EINA_INLIST_GET(dzgc), EINA_INLIST_GET(zgc));
1622                     zgs->gadgets = eina_list_append_relative_list(zgs->gadgets, dzgc, l);
1623                     dzgc->site = zgs;
1624                     dzgc->zone = -1;
1625                     _gadget_object_finalize(dzgc);
1626                  }
1627           }
1628         else
1629           {
1630              int dx, dy, dw, dh, gx, gy, gw, gh;
1631 
1632              /* FIXME: this should place _(around)_ the gadget that got dropped on */
1633              evas_object_geometry_get(drop->layout, &dx, &dy, &dw, &dh);
1634              evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
1635              EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
1636                {
1637                   E_Zone *zone;
1638                   /* calculate positioning offsets and normalize based on drop point */
1639                   evas_object_geometry_get(dzgc->display, &gx, &gy, &gw, &gh);
1640                   evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->display);
1641                   if ((w == e_comp->w) && (h == e_comp->h))
1642                     {
1643                        zone = e_comp_object_util_zone_get(dzgc->display);
1644                        dzgc->zone = zone->num;
1645                        x = zone->x, y = zone->y, w = zone->w, h = zone->h;
1646                     }
1647                   else
1648                     dzgc->zone = -1;
1649                   if (dzgc->id == -1) dzgc->id = 0;
1650                   evas_object_del(dzgc->gadget);
1651                   zgs->gadget_list = eina_inlist_append(zgs->gadget_list,
1652                       EINA_INLIST_GET(dzgc));
1653                   zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
1654                   dzgc->x = ((gx - dx) / (double)dw) + ((mx - x) / (double)w);
1655                   dzgc->y = ((gy - dy) / (double)dh) + ((my - y) / (double)h);
1656                   dzgc->w = gw / (double)w;
1657                   dzgc->h = gh / (double)h;
1658                   dzgc->site = zgs;
1659                   _gadget_object_finalize(dzgc);
1660                }
1661           }
1662      }
1663    else
1664      {
1665         if (zgs->orient)
1666           {
1667              if (mx >= x) //right of all exiting gadgets
1668                {
1669                   EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
1670                     {
1671                        evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->gadget);
1672                        if (dzgc->id == -1) dzgc->id = 0;
1673                        evas_object_del(dzgc->gadget);
1674                        zgs->gadget_list = eina_inlist_append(zgs->gadget_list,
1675                          EINA_INLIST_GET(dzgc));
1676                        zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
1677                        dzgc->site = zgs;
1678                        dzgc->zone = -1;
1679                        _gadget_object_finalize(dzgc);
1680                     }
1681                }
1682              else
1683                {
1684                   EINA_LIST_REVERSE_FOREACH(drop->gadgets, l, dzgc)
1685                     {
1686                        evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->gadget);
1687                        evas_object_del(dzgc->gadget);
1688                        zgs->gadget_list = eina_inlist_prepend(zgs->gadget_list,
1689                          EINA_INLIST_GET(dzgc));
1690                        zgs->gadgets = eina_list_prepend(zgs->gadgets, dzgc);
1691                        dzgc->site = zgs;
1692                        if (dzgc->id == -1) dzgc->id = 0;
1693                        dzgc->zone = -1;
1694                        _gadget_object_finalize(dzgc);
1695                     }
1696                }
1697           }
1698         else
1699           {
1700              int dx, dy, dw, dh, gx, gy, gw, gh;
1701 
1702              evas_object_geometry_get(drop->layout, &dx, &dy, &dw, &dh);
1703              evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
1704              EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
1705                {
1706                   E_Zone *zone;
1707                   /* calculate positioning offsets and normalize based on drop point */
1708                   evas_object_geometry_get(dzgc->display, &gx, &gy, &gw, &gh);
1709                   evas_object_smart_callback_call(zgs->layout, "gadget_moved", dzgc->display);
1710                   if ((w == e_comp->w) && (h == e_comp->h))
1711                     {
1712                        zone = e_comp_object_util_zone_get(dzgc->display);
1713                        dzgc->zone = zone->num;
1714                        x = zone->x, y = zone->y, w = zone->w, h = zone->h;
1715                     }
1716                   else
1717                     dzgc->zone = -1;
1718                   if (dzgc->id == -1) dzgc->id = 0;
1719                   evas_object_del(dzgc->gadget);
1720                   zgs->gadget_list = eina_inlist_append(zgs->gadget_list,
1721                     EINA_INLIST_GET(dzgc));
1722                   zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
1723                   dzgc->x = ((gx - dx) / (double)dw) + ((mx - x - (mx - gx)) / (double)w);
1724                   dzgc->y = ((gy - dy) / (double)dh) + ((my - y - (my - gy)) / (double)h);
1725                   dzgc->w = gw / (double)w;
1726                   dzgc->h = gh / (double)h;
1727                   dzgc->site = zgs;
1728                   _gadget_object_finalize(dzgc);
1729                }
1730           }
1731      }
1732    drop->gadget_list = NULL;
1733    drop->gadgets = eina_list_free(drop->gadgets);
1734    evas_object_smart_need_recalculate_set(zgs->layout, 1);
1735    e_config_save_queue();
1736 }
1737 
1738 static void
_site_restack(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1739 _site_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1740 {
1741    E_Gadget_Site *zgs = data;
1742 
1743    if (!evas_object_smart_parent_get(zgs->layout))
1744      {
1745         Eina_List *l;
1746         E_Gadget_Config *zgc;
1747         int layer;
1748 
1749         layer = evas_object_layer_get(obj);
1750         if (!zgs->orient)
1751           {
1752              EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
1753                if (zgc->display)
1754                  evas_object_layer_set(zgc->display, layer);
1755           }
1756         evas_object_layer_set(zgs->events, layer);
1757      }
1758    evas_object_raise(zgs->events);
1759 }
1760 
1761 static void
_site_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1762 _site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1763 {
1764    E_Gadget_Site *zgs = data;
1765    E_Gadget_Config *zgc;
1766    Eina_List *l, *ll;
1767 
1768    E_FREE_FUNC(zgs->events, evas_object_del);
1769    E_FREE_FUNC(zgs->move_handler, ecore_event_handler_del);
1770    E_FREE_FUNC(zgs->mouse_up_handler, ecore_event_handler_del);
1771    E_FREE_FUNC(zgs->calc_job, ecore_job_del);
1772    EINA_LIST_FOREACH_SAFE(zgs->gadgets, l, ll, zgc)
1773      evas_object_del(zgc->display);
1774    zgs->layout = NULL;
1775    zgs->cur_size = 0;
1776    zgs->action = NULL;
1777    zgs->style_cb = NULL;
1778    if (zgs->name) return;
1779    eina_stringshare_del(zgs->name);
1780    E_FREE_FUNC(zgs->down_timer, ecore_timer_del);
1781    free(zgs);
1782 }
1783 
1784 static void
_site_style(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1785 _site_style(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1786 {
1787    E_Gadget_Site *zgs = data;
1788    E_Gadget_Config *zgc;
1789    Eina_List *l;
1790 
1791    if (!zgs->style_cb) return;
1792    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
1793      if (zgc->display)
1794        zgc->site->style_cb(zgc->site->layout, zgc->style.name, zgc->gadget);
1795 }
1796 
1797 static void
_site_visibility(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1798 _site_visibility(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1799 {
1800    E_Gadget_Site *zgs = data;
1801    E_Gadget_Config *zgc;
1802    Eina_List *l;
1803    Eina_Bool vis = evas_object_visible_get(obj);
1804 
1805    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
1806      if (zgc->display)
1807        {
1808           if (vis) evas_object_show(zgc->display);
1809           else evas_object_hide(zgc->display);
1810        }
1811 }
1812 
1813 static void
_site_create(E_Gadget_Site * zgs)1814 _site_create(E_Gadget_Site *zgs)
1815 {
1816    zgs->layout = elm_box_add(e_comp->elm);
1817    evas_object_name_set(zgs->layout, zgs->name);
1818    elm_box_horizontal_set(zgs->layout, zgs->orient == E_GADGET_SITE_ORIENT_HORIZONTAL);
1819    _gravity_apply(zgs, zgs->gravity);
1820    if (!zgs->orient)
1821      {
1822         /* add dummy content to allow recalc to work */
1823         elm_box_pack_end(zgs->layout, elm_box_add(zgs->layout));
1824      }
1825    elm_box_layout_set(zgs->layout, _site_layout, zgs, NULL);
1826    evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_DEL, _site_del, zgs);
1827    evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_RESTACK, _site_restack, zgs);
1828 
1829    zgs->events = evas_object_rectangle_add(e_comp->evas);
1830    evas_object_name_set(zgs->events, "zgs->events");
1831    evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_MOVE, _site_move, zgs);
1832    evas_object_smart_callback_add(zgs->layout, "gadget_site_dropped", _site_drop, zgs);
1833    evas_object_smart_callback_add(zgs->layout, "gadget_site_style", _site_style, zgs);
1834    evas_object_pointer_mode_set(zgs->events, EVAS_OBJECT_POINTER_MODE_NOGRAB);
1835    evas_object_color_set(zgs->events, 0, 0, 0, 0);
1836    evas_object_repeat_events_set(zgs->events, 1);
1837    evas_object_show(zgs->events);
1838    evas_object_event_callback_add(zgs->events, EVAS_CALLBACK_MOUSE_DOWN, _site_mouse_down, zgs);
1839    evas_object_event_callback_add(zgs->events, EVAS_CALLBACK_MOUSE_UP, _site_mouse_up, zgs);
1840    evas_object_event_callback_add(zgs->events, EVAS_CALLBACK_MOUSE_MOVE, _site_mouse_move, zgs);
1841    if (!zgs->orient)
1842      {
1843         evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_SHOW, _site_visibility, zgs);
1844         evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_HIDE, _site_visibility, zgs);
1845      }
1846 
1847    evas_object_data_set(zgs->layout, "__e_gadget_site", zgs);
1848    E_LIST_FOREACH(zgs->gadgets, _gadget_object_create);
1849    evas_object_layer_set(zgs->events, evas_object_layer_get(zgs->layout));
1850    evas_object_raise(zgs->events);
1851 }
1852 
1853 static void
_site_auto_add_comp_object_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1854 _site_auto_add_comp_object_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1855 {
1856    E_Gadget_Site *zgs = data;
1857    Eina_List *l, *ll;
1858    E_Gadget_Config *zgc;
1859 
1860    /* prune unconfigured gadgets */
1861    EINA_LIST_FOREACH_SAFE(zgs->gadgets, l, ll, zgc)
1862      if (zgc->id <= 0) _gadget_remove(zgc);
1863    e_config_save_queue();
1864    evas_object_del(zgs->layout);
1865 }
1866 
1867 static void
_site_auto_add(E_Gadget_Site * zgs,Evas_Object * comp_object)1868 _site_auto_add(E_Gadget_Site *zgs, Evas_Object *comp_object)
1869 {
1870    int x, y, w, h;
1871 
1872    _site_create(zgs);
1873    evas_object_event_callback_add(comp_object, EVAS_CALLBACK_DEL, _site_auto_add_comp_object_del, zgs);
1874    evas_object_layer_set(zgs->layout, evas_object_layer_get(comp_object));
1875    evas_object_stack_above(zgs->layout, comp_object);
1876    evas_object_geometry_get(comp_object, &x, &y, &w, &h);
1877    evas_object_geometry_set(zgs->layout, x, y, w, h);
1878 }
1879 
1880 static Eina_Bool
_site_auto_comp_object_handler(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Comp_Object * ev)1881 _site_auto_comp_object_handler(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
1882 {
1883    const char *name;
1884    Eina_List *l;
1885    E_Gadget_Site *zgs;
1886 
1887    name = evas_object_name_get(ev->comp_object);
1888    if (!name) return ECORE_CALLBACK_RENEW;
1889    EINA_LIST_FOREACH(sites->sites, l, zgs)
1890      if (zgs->autoadd && eina_streq(zgs->name, name))
1891        {
1892           if (!zgs->layout)
1893             _site_auto_add(zgs, ev->comp_object);
1894           break;
1895        }
1896    return ECORE_CALLBACK_RENEW;
1897 }
1898 
1899 static void
_site_zone_hover_update(Evas_Object * r,E_Zone * zone)1900 _site_zone_hover_update(Evas_Object *r, E_Zone *zone)
1901 {
1902    int zx, zy, zw, zh;
1903 
1904    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
1905    evas_object_geometry_set(r, zx, zy, zw, zh);
1906 }
1907 
1908 static void
_site_zone_hover_rect_new(E_Zone * zone)1909 _site_zone_hover_rect_new(E_Zone *zone)
1910 {
1911    Evas_Object *r = elm_box_add(e_comp->elm);
1912    _site_zone_hover_update(r, zone);
1913    e_comp_object_util_del_list_append(zone->bg_event_object, r);
1914    evas_object_data_set(zone->bg_event_object, "gadget_hover_rect", r);
1915 }
1916 
1917 static Eina_Bool
_site_zones_update(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Zone_Move_Resize * ev)1918 _site_zones_update(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Move_Resize *ev)
1919 {
1920    Evas_Object *r;
1921 
1922    r = evas_object_data_get(ev->zone->bg_event_object, "gadget_hover_rect");
1923    _site_zone_hover_update(r, ev->zone);
1924    return ECORE_CALLBACK_RENEW;
1925 }
1926 
1927 static Eina_Bool
_site_auto_comp_update()1928 _site_auto_comp_update()
1929 {
1930    E_Gadget_Site *zgs;
1931    Eina_List *l;
1932    Evas_Object *r;
1933    E_Zone *zone;
1934 
1935    EINA_LIST_FOREACH(sites->sites, l, zgs)
1936      {
1937         E_Gadget_Config *zgc = eina_list_data_get(zgs->gadgets);
1938 
1939         if (!zgc) continue;
1940         if (zgc->zone == -1) continue;
1941         evas_object_smart_need_recalculate_set(zgs->layout, 1);
1942      }
1943    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1944      {
1945         r = evas_object_data_get(zone->bg_event_object, "gadget_hover_rect");
1946         if (!r) _site_zone_hover_rect_new(zone);
1947      }
1948    return ECORE_CALLBACK_RENEW;
1949 }
1950 
1951 static Evas_Object *
_site_util_add(E_Gadget_Site_Orient orient,const char * name,Eina_Bool autoadd)1952 _site_util_add(E_Gadget_Site_Orient orient, const char *name, Eina_Bool autoadd)
1953 {
1954    E_Gadget_Site *zgs;
1955    Eina_List *l;
1956    Evas_Object *parent;
1957 
1958    if (name)
1959      {
1960         EINA_LIST_FOREACH(sites->sites, l, zgs)
1961           if (eina_streq(zgs->name, name))
1962             {
1963                if (zgs->layout) return zgs->layout;
1964                goto out;
1965             }
1966      }
1967    zgs = E_NEW(E_Gadget_Site, 1);
1968 
1969    zgs->name = eina_stringshare_add(name);
1970    zgs->autoadd = autoadd;
1971 
1972    if (name)
1973      sites->sites = eina_list_append(sites->sites, zgs);
1974 out:
1975    zgs->orient = orient;
1976    switch (orient)
1977      {
1978       case E_GADGET_SITE_ORIENT_HORIZONTAL:
1979         zgs->gravity = E_GADGET_SITE_GRAVITY_LEFT;
1980         break;
1981       case E_GADGET_SITE_ORIENT_VERTICAL:
1982         zgs->gravity = E_GADGET_SITE_GRAVITY_TOP;
1983         break;
1984       default: break;
1985      }
1986    if (autoadd)
1987      {
1988         parent = evas_object_name_find(e_comp->evas, name);
1989         if (parent)
1990           _site_auto_add(zgs, parent);
1991      }
1992    else
1993      _site_create(zgs);
1994 
1995    return zgs->layout;
1996 }
1997 
1998 E_API Evas_Object *
e_gadget_site_add(E_Gadget_Site_Orient orient,const char * name)1999 e_gadget_site_add(E_Gadget_Site_Orient orient, const char *name)
2000 {
2001    return _site_util_add(orient, name, 0);
2002 }
2003 
2004 E_API Evas_Object *
e_gadget_site_auto_add(E_Gadget_Site_Orient orient,const char * name)2005 e_gadget_site_auto_add(E_Gadget_Site_Orient orient, const char *name)
2006 {
2007    return _site_util_add(orient, name, 1);
2008 }
2009 
2010 E_API void
e_gadget_site_del(Evas_Object * obj)2011 e_gadget_site_del(Evas_Object *obj)
2012 {
2013    Eina_List *l, *ll;
2014    E_Gadget_Config *zgc;
2015 
2016    ZGS_GET(obj);
2017 
2018    EINA_LIST_FOREACH_SAFE(zgs->gadgets, l, ll, zgc)
2019      _gadget_remove(zgc);
2020    sites->sites = eina_list_remove(sites->sites, zgs);
2021    evas_object_del(zgs->layout);
2022    eina_stringshare_del(zgs->name);
2023    free(zgs);
2024 }
2025 
2026 E_API E_Gadget_Site_Anchor
e_gadget_site_anchor_get(Evas_Object * obj)2027 e_gadget_site_anchor_get(Evas_Object *obj)
2028 {
2029    ZGS_GET(obj);
2030 
2031    return zgs->anchor;
2032 }
2033 
2034 E_API void
e_gadget_site_owner_setup(Evas_Object * obj,E_Gadget_Site_Anchor an,E_Gadget_Style_Cb cb,E_Gadget_Context_Cb context_cb,E_Gadget_Context_Cb context_cancel_cb)2035 e_gadget_site_owner_setup(Evas_Object *obj, E_Gadget_Site_Anchor an, E_Gadget_Style_Cb cb, E_Gadget_Context_Cb context_cb, E_Gadget_Context_Cb context_cancel_cb)
2036 {
2037    Evas_Object *parent;
2038    ZGS_GET(obj);
2039 
2040    zgs->anchor = an;
2041    zgs->style_cb = cb;
2042    zgs->context_cb = context_cb;
2043    zgs->context_cancel_cb = context_cancel_cb;
2044    evas_object_smart_callback_call(zgs->layout, "gadget_site_anchor", NULL);
2045    parent = evas_object_smart_parent_get(obj);
2046    if (parent)
2047      evas_object_smart_member_add(zgs->events, parent);
2048    else
2049      evas_object_smart_member_del(zgs->events);
2050 }
2051 
2052 E_API E_Gadget_Site_Orient
e_gadget_site_orient_get(Evas_Object * obj)2053 e_gadget_site_orient_get(Evas_Object *obj)
2054 {
2055    ZGS_GET(obj);
2056    return zgs->orient;
2057 }
2058 
2059 E_API E_Gadget_Site_Gravity
e_gadget_site_gravity_get(Evas_Object * obj)2060 e_gadget_site_gravity_get(Evas_Object *obj)
2061 {
2062    ZGS_GET(obj);
2063    return zgs->gravity;
2064 }
2065 
2066 E_API void
e_gadget_site_gravity_set(Evas_Object * obj,E_Gadget_Site_Gravity gravity)2067 e_gadget_site_gravity_set(Evas_Object *obj, E_Gadget_Site_Gravity gravity)
2068 {
2069    ZGS_GET(obj);
2070    if (zgs->gravity == gravity) return;
2071    zgs->gravity = gravity;
2072    _gravity_apply(zgs, gravity);
2073    evas_object_smart_need_recalculate_set(zgs->layout, 1);
2074 }
2075 
2076 E_API Eina_List *
e_gadget_site_gadgets_list(Evas_Object * obj)2077 e_gadget_site_gadgets_list(Evas_Object *obj)
2078 {
2079    Eina_List *l, *list = NULL;
2080    E_Gadget_Config *zgc;
2081 
2082    ZGS_GET(obj);
2083    EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
2084      if (zgc->display)
2085        list = eina_list_append(list, zgc->gadget);
2086    return list;
2087 }
2088 
2089 E_API void
e_gadget_site_gadget_add(Evas_Object * obj,const char * type,Eina_Bool demo)2090 e_gadget_site_gadget_add(Evas_Object *obj, const char *type, Eina_Bool demo)
2091 {
2092    int id = 0;
2093 
2094    demo = !!demo;
2095    id -= demo;
2096    EINA_SAFETY_ON_NULL_RETURN(gadget_types);
2097    ZGS_GET(obj);
2098    _gadget_util_add(zgs, NULL, type, id);
2099 }
2100 
2101 E_API void
e_gadget_site_gadget_external_add(Evas_Object * obj,const char * domain,const char * type,Eina_Bool demo)2102 e_gadget_site_gadget_external_add(Evas_Object *obj, const char *domain, const char *type, Eina_Bool demo)
2103 {
2104    int id = 0;
2105 
2106    demo = !!demo;
2107    id -= demo;
2108    EINA_SAFETY_ON_NULL_RETURN(gadget_types);
2109    ZGS_GET(obj);
2110    _gadget_util_add(zgs, domain, type, id);
2111 }
2112 
2113 E_API Evas_Object *
e_gadget_site_get(Evas_Object * g)2114 e_gadget_site_get(Evas_Object *g)
2115 {
2116    E_Gadget_Config *zgc;
2117 
2118    EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
2119    zgc = evas_object_data_get(g, "__e_gadget");
2120    EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
2121    return zgc->site->layout;
2122 }
2123 
2124 E_API Eina_Bool
e_gadget_site_is_desklock(Evas_Object * obj)2125 e_gadget_site_is_desklock(Evas_Object *obj)
2126 {
2127    const char *name;
2128    ZGS_GET(obj);
2129    name = evas_object_name_get(obj);
2130    return name && strstr(name, "desklock");
2131 }
2132 
2133 E_API void
e_gadget_configure_cb_set(Evas_Object * g,E_Gadget_Configure_Cb cb)2134 e_gadget_configure_cb_set(Evas_Object *g, E_Gadget_Configure_Cb cb)
2135 {
2136    E_Gadget_Config *zgc;
2137 
2138    EINA_SAFETY_ON_NULL_RETURN(g);
2139    zgc = evas_object_data_get(g, "__e_gadget");
2140    EINA_SAFETY_ON_NULL_RETURN(zgc);
2141    zgc->configure = cb;
2142 }
2143 
2144 E_API void
e_gadget_configure(Evas_Object * g)2145 e_gadget_configure(Evas_Object *g)
2146 {
2147    E_Gadget_Config *zgc;
2148 
2149    if (e_desklock_state_get()) return;
2150    EINA_SAFETY_ON_NULL_RETURN(g);
2151    zgc = evas_object_data_get(g, "__e_gadget");
2152    EINA_SAFETY_ON_NULL_RETURN(zgc);
2153    _gadget_configure(zgc);
2154 }
2155 
2156 E_API void
e_gadget_menu_populate_cb_set(Evas_Object * g,E_Gadget_Menu_Populate_Cb cb)2157 e_gadget_menu_populate_cb_set(Evas_Object *g, E_Gadget_Menu_Populate_Cb cb)
2158 {
2159    E_Gadget_Config *zgc;
2160 
2161    EINA_SAFETY_ON_NULL_RETURN(g);
2162    zgc = evas_object_data_get(g, "__e_gadget");
2163    EINA_SAFETY_ON_NULL_RETURN(zgc);
2164    zgc->populate = cb;
2165 }
2166 
2167 E_API void
e_gadget_menu_populate(Evas_Object * g,E_Menu * m)2168 e_gadget_menu_populate(Evas_Object *g, E_Menu *m)
2169 {
2170    E_Gadget_Config *zgc;
2171 
2172    if (e_desklock_state_get()) return;
2173    EINA_SAFETY_ON_NULL_RETURN(g);
2174    zgc = evas_object_data_get(g, "__e_gadget");
2175    EINA_SAFETY_ON_NULL_RETURN(zgc);
2176    _gadget_menu_populate(zgc, m);
2177 }
2178 
2179 E_API Eina_Stringshare *
e_gadget_type_get(Evas_Object * g)2180 e_gadget_type_get(Evas_Object *g)
2181 {
2182    E_Gadget_Config *zgc;
2183 
2184    EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
2185    zgc = evas_object_data_get(g, "__e_gadget");
2186    EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
2187    return zgc->external.type ?: zgc->type;
2188 }
2189 
2190 E_API void
e_gadget_type_add(const char * type,E_Gadget_Create_Cb callback,E_Gadget_Wizard_Cb wizard)2191 e_gadget_type_add(const char *type, E_Gadget_Create_Cb callback, E_Gadget_Wizard_Cb wizard)
2192 {
2193    E_Gadget_Type *t;
2194    Eina_List *l, *ll;
2195    E_Gadget_Site *zgs;
2196    E_Gadget_Config *zgc;
2197 
2198    EINA_SAFETY_ON_TRUE_RETURN(!!eina_hash_find(gadget_types, type));
2199    t = E_NEW(E_Gadget_Type, 1);
2200    t->cb = callback;
2201    t->wizard = wizard;
2202    eina_hash_add(gadget_types, type, t);
2203    EINA_LIST_FOREACH(sites->sites, l, zgs)
2204      if (zgs->layout)
2205        EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
2206          if (eina_streq(type, zgc->type))
2207            _gadget_object_create(zgc);
2208 }
2209 
2210 E_API void
e_gadget_type_del(const char * type)2211 e_gadget_type_del(const char *type)
2212 {
2213    Eina_List *l, *ll;
2214    E_Gadget_Site *zgs;
2215    E_Gadget_Config *zgc;
2216    char buf[1024];
2217 
2218    strncpy(buf, type, sizeof(buf) - 1);
2219 
2220    if (!gadget_types) return;
2221 
2222    EINA_LIST_FOREACH(sites->sites, l, zgs)
2223      {
2224         EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
2225           if (eina_streq(buf, zgc->type))
2226             evas_object_del(zgc->gadget);
2227      }
2228    eina_hash_del_by_key(gadget_types, type);
2229 }
2230 
2231 E_API void
e_gadget_external_type_add(const char * domain,const char * type,E_Gadget_External_Create_Cb callback,E_Gadget_External_Wizard_Cb wizard)2232 e_gadget_external_type_add(const char *domain, const char *type, E_Gadget_External_Create_Cb callback, E_Gadget_External_Wizard_Cb wizard)
2233 {
2234    E_Gadget_External_Type *te;
2235    Eina_List *l, *ll;
2236    E_Gadget_Site *zgs;
2237    E_Gadget_Config *zgc;
2238    Eina_Hash *h = NULL;
2239 
2240    if (gadget_external_domains)
2241      {
2242         h = eina_hash_find(gadget_external_domains, domain);
2243         if (h)
2244           EINA_SAFETY_ON_TRUE_RETURN(!!eina_hash_find(h, type));
2245      }
2246    else
2247      gadget_external_domains = eina_hash_string_superfast_new((Eina_Free_Cb)eina_hash_free);
2248    if (!h)
2249      {
2250         h = eina_hash_string_superfast_new(free);
2251         eina_hash_add(gadget_external_domains, domain, h);
2252      }
2253    te = E_NEW(E_Gadget_External_Type, 1);
2254    te->cb = callback;
2255    te->wizard = wizard;
2256    eina_hash_add(h, type, te);
2257    EINA_LIST_FOREACH(sites->sites, l, zgs)
2258      if (zgs->layout)
2259        EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
2260          if (eina_streq(domain, zgc->external.domain) && eina_streq(type, zgc->external.type))
2261            _gadget_object_create(zgc);
2262 }
2263 
2264 E_API void
e_gadget_external_type_name_cb_set(const char * domain,const char * type,E_Gadget_External_Name_Cb name)2265 e_gadget_external_type_name_cb_set(const char *domain, const char *type, E_Gadget_External_Name_Cb name)
2266 {
2267    E_Gadget_External_Type *te;
2268 
2269    te = _gadget_external_type_get(domain, type);
2270    EINA_SAFETY_ON_NULL_RETURN(te);
2271    te->name = name;
2272 }
2273 
2274 E_API void
e_gadget_external_type_del(const char * domain,const char * type)2275 e_gadget_external_type_del(const char *domain, const char *type)
2276 {
2277    Eina_List *l, *ll;
2278    E_Gadget_Site *zgs;
2279    E_Gadget_Config *zgc;
2280 
2281    if (!gadget_external_domains) return;
2282    if (!sites) return;
2283 
2284    EINA_LIST_FOREACH(sites->sites, l, zgs)
2285      {
2286         EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
2287           if (eina_streq(domain, zgc->external.domain))
2288             {
2289                if ((!type) || eina_streq(type, zgc->external.type))
2290                  evas_object_del(zgc->gadget);
2291             }
2292      }
2293    if (type)
2294      {
2295         Eina_Hash *h;
2296 
2297         h = eina_hash_find(gadget_external_domains, domain);
2298         EINA_SAFETY_ON_NULL_RETURN(h);
2299         eina_hash_del_by_key(h, type);
2300         if (!eina_hash_population(h))
2301           eina_hash_del_by_key(gadget_external_domains, domain);
2302      }
2303    else
2304      eina_hash_del_by_key(gadget_external_domains, domain);
2305 }
2306 
2307 E_API Eina_Iterator *
e_gadget_type_iterator_get(void)2308 e_gadget_type_iterator_get(void)
2309 {
2310    return gadget_types ? eina_hash_iterator_key_new(gadget_types) : NULL;
2311 }
2312 
2313 E_API void
e_gadget_del(Evas_Object * g)2314 e_gadget_del(Evas_Object *g)
2315 {
2316    E_Gadget_Config *zgc;
2317    EINA_SAFETY_ON_NULL_RETURN(g);
2318    zgc = evas_object_data_get(g, "__e_gadget");
2319    EINA_SAFETY_ON_NULL_RETURN(zgc);
2320    _gadget_remove(zgc);
2321 }
2322 
2323 static void
_gadget_drop_handler_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2324 _gadget_drop_handler_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2325 {
2326    int x, y, w, h;
2327 
2328    evas_object_geometry_get(obj, &x, &y, &w, &h);
2329    e_drop_handler_geometry_set(data, x, y, w, h);
2330 }
2331 
2332 E_API Evas_Object *
e_gadget_drop_handler_add(Evas_Object * g,void * data,void (* enter_cb)(void * data,const char * type,void * event),void (* move_cb)(void * data,const char * type,void * event),void (* leave_cb)(void * data,const char * type,void * event),void (* drop_cb)(void * data,const char * type,void * event),const char ** types,unsigned int num_types)2333 e_gadget_drop_handler_add(Evas_Object *g, void *data,
2334                                         void (*enter_cb)(void *data, const char *type, void *event),
2335                                         void (*move_cb)(void *data, const char *type, void *event),
2336                                         void (*leave_cb)(void *data, const char *type, void *event),
2337                                         void (*drop_cb)(void *data, const char *type, void *event),
2338                                         const char **types, unsigned int num_types)
2339 {
2340    E_Gadget_Config *zgc;
2341    int x, y, w, h;
2342    Evas_Object *drop_object;
2343    E_Drop_Handler *drop_handler;
2344 
2345    EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
2346    zgc = evas_object_data_get(g, "__e_gadget");
2347    EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
2348 
2349    if (!zgc->drop_handlers)
2350      zgc->drop_handlers = eina_hash_pointer_new((Eina_Free_Cb)e_drop_handler_del);
2351 
2352    evas_object_geometry_get(zgc->display, &x, &y, &w, &h);
2353    drop_handler = e_drop_handler_add(zgc->e_obj_inherit, NULL, data,
2354                         enter_cb, move_cb, leave_cb, drop_cb,
2355                         types, num_types, x, y, w, h);
2356    drop_object = evas_object_rectangle_add(e_comp->evas);
2357    drop_handler->base = drop_object;
2358    evas_object_color_set(drop_object, 0, 0, 0, 0);
2359    e_object_data_set(E_OBJECT(drop_handler), drop_object);
2360    evas_object_data_set(drop_object, "gadget_drop_handler", drop_handler);
2361    evas_object_geometry_set(drop_object, x, y, w, h);
2362    evas_object_pass_events_set(drop_object, 1);
2363    evas_object_layer_set(drop_object, evas_object_layer_get(zgc->display));
2364    evas_object_event_callback_add(drop_object, EVAS_CALLBACK_MOVE, _gadget_drop_handler_moveresize, drop_handler);
2365    evas_object_event_callback_add(drop_object, EVAS_CALLBACK_RESIZE, _gadget_drop_handler_moveresize, drop_handler);
2366    evas_object_event_callback_add(drop_object, EVAS_CALLBACK_DEL, _gadget_drop_handler_del, zgc);
2367    eina_hash_add(zgc->drop_handlers, &drop_object, drop_handler);
2368    return drop_object;
2369 }
2370 
2371 static void
_gadget_style_hints(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2372 _gadget_style_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2373 {
2374    E_Gadget_Config *zgc = data;
2375    evas_object_smart_need_recalculate_set(zgc->site->layout, 1);
2376 }
2377 
2378 E_API Evas_Object *
e_gadget_util_layout_style_init(Evas_Object * g,Evas_Object * style)2379 e_gadget_util_layout_style_init(Evas_Object *g, Evas_Object *style)
2380 {
2381    E_Gadget_Config *zgc;
2382    Evas_Object *prev;
2383    const char *grp;
2384 
2385    EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
2386    zgc = evas_object_data_get(g, "__e_gadget");
2387    EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
2388 
2389    prev = zgc->style.obj;
2390    if ((!prev) && (!style)) return NULL;
2391    zgc->style.obj = style;
2392    if (style)
2393      {
2394         elm_layout_file_get(style, NULL, &grp);
2395         eina_stringshare_replace(&zgc->style.name, strrchr(grp, '/') + 1);
2396         evas_object_event_callback_priority_add(style, EVAS_CALLBACK_DEL, EVAS_CALLBACK_PRIORITY_AFTER, _gadget_del, zgc);
2397      }
2398    else
2399      eina_stringshare_replace(&zgc->style.name, NULL);
2400    if (prev)
2401      evas_object_event_callback_del_full(prev, EVAS_CALLBACK_DEL, _gadget_del, zgc);
2402    e_config_save_queue();
2403    zgc->display = style ?: zgc->gadget;
2404    E_FILL(zgc->display);
2405    E_EXPAND(zgc->display);
2406    if (zgc->site->gravity)
2407      {
2408         elm_box_pack_before(zgc->site->layout, zgc->display, prev ?: zgc->gadget);
2409         if (prev)
2410           elm_box_unpack(zgc->site->layout, prev);
2411      }
2412    evas_object_raise(zgc->site->events);
2413    if (prev) evas_object_event_callback_del(prev, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _gadget_style_hints);
2414    if (!style) return prev;
2415 
2416    evas_object_data_set(style, "__e_gadget", zgc);
2417 
2418    elm_layout_sizing_eval(style);
2419    evas_object_smart_calculate(style);
2420    evas_object_size_hint_min_get(style, &zgc->style.minw, &zgc->style.minh);
2421    evas_object_event_callback_add(style, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _gadget_style_hints, zgc);
2422    evas_object_show(style);
2423    if (zgc->display != zgc->gadget)
2424      evas_object_smart_callback_add(zgc->display, "gadget_popup", _gadget_popup, zgc);
2425    return prev;
2426 }
2427 
2428 static void
_gadget_util_ctxpopup_visibility(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2429 _gadget_util_ctxpopup_visibility(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2430 {
2431    e_comp_shape_queue();
2432 }
2433 
2434 static void
_gadget_util_ctxpopup_moveresize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2435 _gadget_util_ctxpopup_moveresize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2436 {
2437    e_comp_shape_queue();
2438 }
2439 
2440 E_API void
e_gadget_util_ctxpopup_place(Evas_Object * g,Evas_Object * ctx,Evas_Object * pos_obj)2441 e_gadget_util_ctxpopup_place(Evas_Object *g, Evas_Object *ctx, Evas_Object *pos_obj)
2442 {
2443    int x, y, w, h;
2444    E_Layer layer;
2445    E_Gadget_Config *zgc;
2446    Evas_Object *content;
2447    E_Zone *zone;
2448    Elm_Ctxpopup_Direction first, second;
2449 
2450    EINA_SAFETY_ON_NULL_RETURN(g);
2451    zgc = evas_object_data_get(g, "__e_gadget");
2452    EINA_SAFETY_ON_NULL_RETURN(zgc);
2453 
2454    content = elm_object_content_get(ctx);
2455    zone = e_comp_object_util_zone_get(g);
2456    elm_ctxpopup_hover_parent_set(ctx, evas_object_data_get(zone->bg_event_object, "gadget_hover_rect"));
2457    layer = MAX(evas_object_layer_get(pos_obj ?: g), E_LAYER_POPUP);
2458    evas_object_layer_set(ctx, layer);
2459 
2460    evas_object_geometry_get(pos_obj ?: g, &x, &y, &w, &h);
2461    if (zgc->site->anchor & E_GADGET_SITE_ANCHOR_TOP)
2462      y += h;
2463    if (zgc->site->anchor & E_GADGET_SITE_ANCHOR_LEFT)
2464      x += w;
2465    if (zgc->site->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
2466      {
2467         x += w / 2;
2468         first = ELM_CTXPOPUP_DIRECTION_UP, second = ELM_CTXPOPUP_DIRECTION_DOWN;
2469         if (zgc->site->anchor & E_GADGET_SITE_ANCHOR_TOP)
2470           first = ELM_CTXPOPUP_DIRECTION_DOWN, second = ELM_CTXPOPUP_DIRECTION_UP;
2471      }
2472    else if (zgc->site->orient == E_GADGET_SITE_ORIENT_VERTICAL)
2473      {
2474         y += h / 2;
2475         first = ELM_CTXPOPUP_DIRECTION_LEFT, second = ELM_CTXPOPUP_DIRECTION_RIGHT;
2476         if (zgc->site->anchor & E_GADGET_SITE_ANCHOR_LEFT)
2477           first = ELM_CTXPOPUP_DIRECTION_RIGHT, second = ELM_CTXPOPUP_DIRECTION_LEFT;
2478      }
2479    else
2480      {
2481         int zx, zy, zw, zh;
2482         e_zone_useful_geometry_get(e_comp_object_util_zone_get(pos_obj ?: g), &zx, &zy, &zw, &zh);
2483         if (x < zx + (zw / 2))
2484           {
2485              second = ELM_CTXPOPUP_DIRECTION_RIGHT;
2486              x += w / 2;
2487           }
2488         else
2489           second = ELM_CTXPOPUP_DIRECTION_LEFT;
2490         if (y < zy + (zh / 2))
2491           {
2492              first = ELM_CTXPOPUP_DIRECTION_DOWN;
2493              y += h;
2494           }
2495         else
2496           first = ELM_CTXPOPUP_DIRECTION_UP;
2497      }
2498    elm_ctxpopup_direction_priority_set(ctx, first, second, 0, 0);
2499    evas_object_move(ctx, x, y);
2500    evas_object_event_callback_add(ctx, EVAS_CALLBACK_SHOW, _gadget_util_ctxpopup_visibility, NULL);
2501    evas_object_event_callback_add(ctx, EVAS_CALLBACK_HIDE, _gadget_util_ctxpopup_visibility, NULL);
2502    if (content)
2503      {
2504         evas_object_event_callback_add(content, EVAS_CALLBACK_MOVE, _gadget_util_ctxpopup_moveresize, NULL);
2505         evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE, _gadget_util_ctxpopup_moveresize, NULL);
2506      }
2507    _desktop_rect_obj_add(ctx);
2508    evas_object_smart_callback_call(g, "gadget_popup", ctx);
2509    if (evas_object_visible_get(ctx))
2510      e_comp_shape_queue();
2511 }
2512 
2513 static void
_gadget_util_allow(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2514 _gadget_util_allow(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2515 {
2516    E_Gadget_Config *zgc = data;
2517 
2518    zgc->allow_deny.allow(zgc->allow_deny.data, zgc->gadget, NULL);
2519    _gadget_util_allow_deny_cleanup(zgc);
2520 }
2521 
2522 static void
_gadget_util_deny(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2523 _gadget_util_deny(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2524 {
2525    E_Gadget_Config *zgc = data;
2526 
2527    zgc->allow_deny.deny(zgc->allow_deny.data, zgc->gadget, NULL);
2528    _gadget_util_allow_deny_cleanup(zgc);
2529 }
2530 
2531 E_API void
e_gadget_util_allow_deny_ctxpopup(Evas_Object * g,const char * text,Evas_Smart_Cb allow_cb,Evas_Smart_Cb deny_cb,const void * data)2532 e_gadget_util_allow_deny_ctxpopup(Evas_Object *g, const char *text, Evas_Smart_Cb allow_cb, Evas_Smart_Cb deny_cb, const void *data)
2533 {
2534    Evas_Object *ctx, *tb, *lbl, *bt;
2535    E_Gadget_Config *zgc;
2536 
2537    EINA_SAFETY_ON_NULL_RETURN(g);
2538    zgc = evas_object_data_get(g, "__e_gadget");
2539    EINA_SAFETY_ON_NULL_RETURN(zgc);
2540 
2541    /* FIXME */
2542    EINA_SAFETY_ON_TRUE_RETURN(!!zgc->allow_deny.popup);
2543 
2544    EINA_SAFETY_ON_NULL_RETURN(allow_cb);
2545    EINA_SAFETY_ON_NULL_RETURN(deny_cb);
2546    EINA_SAFETY_ON_NULL_RETURN(text);
2547 
2548    zgc->allow_deny.allow = allow_cb;
2549    zgc->allow_deny.deny = deny_cb;
2550    zgc->allow_deny.data = (void*)data;
2551 
2552    ctx = elm_ctxpopup_add(e_comp->elm);
2553    elm_object_style_set(ctx, "noblock");
2554 
2555    tb = elm_table_add(ctx);
2556    E_EXPAND(tb);
2557    E_FILL(tb);
2558    evas_object_show(tb);
2559    lbl = elm_label_add(ctx);
2560    E_FILL(lbl);
2561    elm_object_text_set(lbl, text);
2562    evas_object_show(lbl);
2563    elm_table_pack(tb, lbl, 0, 0, 2, 2);
2564 
2565    bt = elm_button_add(ctx);
2566    evas_object_show(bt);
2567    E_EXPAND(bt);
2568    E_FILL(bt);
2569    elm_object_text_set(bt, _("Deny"));
2570    evas_object_smart_callback_add(bt, "clicked", _gadget_util_deny, zgc);
2571    elm_table_pack(tb, bt, 0, 2, 1, 1);
2572 
2573    bt = elm_button_add(ctx);
2574    evas_object_show(bt);
2575    E_EXPAND(bt);
2576    E_FILL(bt);
2577    elm_object_text_set(bt, _("Allow"));
2578    evas_object_smart_callback_add(bt, "clicked", _gadget_util_allow, zgc);
2579    elm_table_pack(tb, bt, 1, 2, 1, 1);
2580 
2581    elm_object_content_set(ctx, tb);
2582 
2583    e_gadget_util_ctxpopup_place(g, ctx, NULL);
2584    zgc->allow_deny.popup = e_comp_object_util_add(ctx, E_COMP_OBJECT_TYPE_NONE);
2585    evas_object_layer_set(zgc->allow_deny.popup, E_LAYER_POPUP);
2586    evas_object_show(zgc->allow_deny.popup);
2587 }
2588 
2589 EINTERN void
e_gadget_save(void)2590 e_gadget_save(void)
2591 {
2592    e_config_domain_save("e_gadget_sites", edd_sites, sites);
2593 #ifdef HAVE_WAYLAND
2594    e_gadget_runner_save();
2595 #endif
2596 }
2597 
2598 EINTERN void
e_gadget_site_rename(const char * name,const char * newname)2599 e_gadget_site_rename(const char *name, const char *newname)
2600 {
2601    Eina_List *l;
2602    E_Gadget_Site *zgs;
2603 
2604    EINA_LIST_FOREACH(sites->sites, l, zgs)
2605      if (eina_streq(zgs->name, name))
2606        {
2607           eina_stringshare_replace(&zgs->name, newname);
2608           e_config_save_queue();
2609           break;
2610        }
2611 }
2612 
2613 static void
_desktop_gadget_context(Evas_Object * site EINA_UNUSED,Evas_Object * g,unsigned int timestamp)2614 _desktop_gadget_context(Evas_Object *site EINA_UNUSED, Evas_Object *g, unsigned int timestamp)
2615 {
2616    if (g) _gadget_menu(g, timestamp);
2617 }
2618 
2619 static void
_desktop_gadget_context_cancel(Evas_Object * site EINA_UNUSED,Evas_Object * g,unsigned int timestamp)2620 _desktop_gadget_context_cancel(Evas_Object *site EINA_UNUSED, Evas_Object *g, unsigned int timestamp)
2621 {
2622    if (g) _gadget_menu_cancel(g, timestamp);
2623 }
2624 
2625 EINTERN void
e_gadget_init(void)2626 e_gadget_init(void)
2627 {
2628    gadget_types = eina_hash_string_superfast_new(free);
2629    edd_gadget = E_CONFIG_DD_NEW("E_Gadget_Config", E_Gadget_Config);
2630    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, id, INT);
2631    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, zone, INT);
2632    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, type, STR);
2633    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, external.domain, STR);
2634    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, external.type, STR);
2635    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, style.name, STR);
2636    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, x, DOUBLE);
2637    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, y, DOUBLE);
2638    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, w, DOUBLE);
2639    E_CONFIG_VAL(edd_gadget, E_Gadget_Config, h, DOUBLE);
2640 
2641    edd_site = E_CONFIG_DD_NEW("E_Gadget_Site", E_Gadget_Site);
2642    E_CONFIG_VAL(edd_site, E_Gadget_Site, gravity, UINT);
2643    E_CONFIG_VAL(edd_site, E_Gadget_Site, orient, UINT);
2644    E_CONFIG_VAL(edd_site, E_Gadget_Site, anchor, UINT);
2645    E_CONFIG_VAL(edd_site, E_Gadget_Site, autoadd, UCHAR);
2646    E_CONFIG_VAL(edd_site, E_Gadget_Site, name, STR);
2647 
2648    E_CONFIG_LIST(edd_site, E_Gadget_Site, gadgets, edd_gadget);
2649 
2650    edd_sites = E_CONFIG_DD_NEW("E_Gadget_Sites", E_Gadget_Sites);
2651    E_CONFIG_LIST(edd_sites, E_Gadget_Sites, sites, edd_site);
2652    sites = e_config_domain_load("e_gadget_sites", edd_sites);
2653    if (sites)
2654      {
2655         Eina_List *l;
2656         E_Gadget_Site *zgs;
2657 
2658         EINA_LIST_FOREACH(sites->sites, l, zgs)
2659           {
2660              Eina_List *ll;
2661              E_Gadget_Config *zgc;
2662 
2663              EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
2664                {
2665                   zgs->gadget_list = eina_inlist_append(zgs->gadget_list, EINA_INLIST_GET(zgc));
2666                   zgc->site = zgs;
2667                }
2668           }
2669      }
2670    else
2671      sites = E_NEW(E_Gadget_Sites, 1);
2672 
2673    move_act = e_action_add("gadget_move");
2674    e_action_predef_name_set(_("Gadgets"), _("Move gadget"), "gadget_move", NULL, NULL, 0);
2675    move_act->func.go_mouse = _gadget_act_move;
2676 
2677    resize_act = e_action_add("gadget_resize");
2678    e_action_predef_name_set(_("Gadgets"), _("Resize gadget"), "gadget_resize", NULL, NULL, 0);
2679    resize_act->func.go_mouse = _gadget_act_resize;
2680    resize_act->func.end_mouse = _gadget_act_resize_end;
2681 
2682    configure_act = e_action_add("gadget_configure");
2683    e_action_predef_name_set(_("Gadgets"), _("Configure gadget"), "gadget_configure", NULL, NULL, 0);
2684    configure_act->func.go_mouse = _gadget_act_configure;
2685 
2686    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _site_auto_comp_object_handler, NULL);
2687    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMPOSITOR_UPDATE, _site_auto_comp_update, NULL);
2688    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGED, _site_zones_update, NULL);
2689 
2690    E_LIST_FOREACH(e_comp->zones, _site_zone_hover_rect_new);
2691 
2692    comp_site = e_comp->canvas->gadget_site = e_gadget_site_add(E_GADGET_SITE_ORIENT_NONE, "__desktop");
2693    evas_object_event_callback_add(e_comp->canvas->resize_object, EVAS_CALLBACK_RESIZE, _comp_site_resize, comp_site);
2694    ZGS_GET(comp_site);
2695    zgs->context_cb = _desktop_gadget_context;
2696    zgs->context_cancel_cb = _desktop_gadget_context_cancel;
2697    evas_object_layer_set(comp_site, E_LAYER_DESKTOP);
2698    evas_object_resize(comp_site, e_comp->w, e_comp->h);
2699 #ifdef HAVE_WAYLAND
2700    e_gadget_runner_init();
2701 #endif
2702 }
2703 
2704 EINTERN void
e_gadget_shutdown(void)2705 e_gadget_shutdown(void)
2706 {
2707    E_Gadget_Site *zgs;
2708 
2709 #ifdef HAVE_WAYLAND
2710    e_gadget_runner_shutdown();
2711 #endif
2712    E_FREE_LIST(handlers, ecore_event_handler_del);
2713    E_CONFIG_DD_FREE(edd_gadget);
2714    E_CONFIG_DD_FREE(edd_site);
2715    E_CONFIG_DD_FREE(edd_sites);
2716    EINA_LIST_FREE(sites->sites, zgs)
2717      {
2718         E_FREE_LIST(zgs->gadgets, _gadget_free);
2719         evas_object_del(zgs->layout);
2720         eina_stringshare_del(zgs->name);
2721         free(zgs);
2722      }
2723    E_FREE(sites);
2724 
2725    e_action_del("gadget_move");
2726    e_action_del("gadget_resize");
2727    e_action_del("gadget_configure");
2728    e_action_predef_name_del(_("Gadgets"), _("Move gadget"));
2729    e_action_predef_name_del(_("Gadgets"), _("Resize gadget"));
2730    e_action_predef_name_del(_("Gadgets"), _("Configure gadget"));
2731    move_act = resize_act = configure_act = NULL;
2732    E_FREE_FUNC(gadget_types, eina_hash_free);
2733    E_FREE_FUNC(gadget_external_domains, eina_hash_free);
2734 }
2735 
2736 //////////////////////////////////////////////////////
2737 ////         EDITOR                              /////
2738 //////////////////////////////////////////////////////
2739 
2740 static void
_editor_resize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2741 _editor_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2742 {
2743    int w, h, size;
2744    Elm_Object_Item *it;
2745 
2746    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2747    size = MAX(w, h);
2748    size = MAX(size / 4, 100);
2749    elm_gengrid_item_size_set(obj, size, size);
2750    for (it = elm_gengrid_first_item_get(obj); it; it = elm_gengrid_item_next_get(it))
2751      {
2752         Gadget_Item *gi = elm_object_item_data_get(it);
2753         evas_object_size_hint_max_set(gi->gadget, lround(size * 0.95), lround(size * 0.95));
2754      }
2755 }
2756 
2757 static void
_editor_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2758 _editor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2759 {
2760    Evas_Object *site = evas_object_data_get(obj, "__gadget_site");
2761    if (site)
2762      {
2763         evas_object_event_callback_del(site, EVAS_CALLBACK_DEL, _edit_site_del);
2764         ZGS_GET(site);
2765         zgs->editor = NULL;
2766      }
2767    evas_object_event_callback_del_full(data, EVAS_CALLBACK_RESIZE, _editor_resize, obj);
2768 }
2769 
2770 static void
_editor_item_del(void * data,Evas_Object * obj EINA_UNUSED)2771 _editor_item_del(void *data, Evas_Object *obj EINA_UNUSED)
2772 {
2773    Gadget_Item *gi = data;
2774    elm_box_unpack_all(gi->box);
2775    free(data);
2776 }
2777 
2778 static void
_editor_pointer_site_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2779 _editor_pointer_site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2780 {
2781    e_comp_ungrab_input(1, 1);
2782    free(data);
2783    pointer_site = NULL;
2784    E_FREE_LIST(pointer_site_handlers, ecore_event_handler_del);
2785 }
2786 
2787 static void
_editor_site_hints(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2788 _editor_site_hints(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2789 {
2790    int x, y, w, h;
2791 
2792    evas_object_size_hint_min_get(obj, &w, &h);
2793    evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
2794    evas_object_geometry_set(pointer_site, x - (w / 2), y - (h / 2), w, h);
2795 }
2796 
2797 static Eina_Bool
_editor_pointer_button(Gadget_Item * active,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)2798 _editor_pointer_button(Gadget_Item *active, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2799 {
2800    int x, y, w, h;
2801    E_Gadget_Site *zgs, *zzgs = NULL;
2802 
2803    if (active->site)
2804      {
2805         evas_object_geometry_get(active->site, &x, &y, &w, &h);
2806         if (evas_object_smart_need_recalculate_get(active->site))
2807           evas_object_smart_calculate(active->site);
2808         if ((ev->buttons == 1) && E_INSIDE(ev->x, ev->y, x, y, w, h))
2809           evas_object_smart_callback_call(active->site, "gadget_site_dropped", pointer_site);
2810         e_comp_canvas_feed_mouse_up(0);
2811         evas_object_pass_events_set(active->site, 0);
2812         evas_object_pass_events_set(desktop_editor, 0);
2813         elm_object_disabled_set(active->editor, 1);
2814         e_comp_object_util_del_list_remove(active->editor, pointer_site);
2815      }
2816    else
2817      {
2818         E_Gadget_Config *zgc, *z;
2819         Eina_List *l;
2820 
2821         if (ev->buttons == 1)
2822           {
2823              EINA_LIST_FOREACH(sites->sites, l, zgs)
2824                {
2825                   if (!zgs->layout) continue;
2826                   if (!evas_object_visible_get(zgs->events)) continue;
2827                   evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
2828                   if (!E_INSIDE(ev->x, ev->y, x, y, w, h)) continue;
2829                   /* FIXME: technically not accurate since objects on the same layer
2830                    * will have different stacking, but walking object trees sucks
2831                    */
2832                   if ((!zzgs) ||
2833                     (evas_object_layer_get(zzgs->layout) < evas_object_layer_get(zgs->layout)))
2834                     zzgs = zgs;
2835                }
2836           }
2837         zgs = evas_object_data_get(pointer_site, "__e_gadget_site");
2838         zgc = eina_list_data_get(zgs->gadgets);
2839         e_comp_canvas_feed_mouse_up(0);
2840         evas_object_pass_events_set(zgc->orig->site->layout, 0);
2841         evas_object_pass_events_set(desktop_editor, 0);
2842         if (zzgs)
2843           {
2844              /* fake the moving gadget as being on the pointer site */
2845              z = zgc->orig;
2846              zgc->site->gadget_list = eina_inlist_remove(zgc->site->gadget_list, EINA_INLIST_GET(zgc));
2847              zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
2848              if (evas_object_smart_need_recalculate_get(zzgs->layout))
2849                evas_object_smart_calculate(zzgs->layout);
2850              evas_object_geometry_get(zgc->display, &x, &y, NULL, NULL);
2851              evas_object_move(z->display, x, y);
2852              z->site->gadget_list = eina_inlist_remove(z->site->gadget_list, EINA_INLIST_GET(z));
2853              z->site->gadgets = eina_list_remove(z->site->gadgets, z);
2854              zgs->gadgets = eina_list_append(zgs->gadgets, z);
2855              z->site = zgs;
2856              evas_object_smart_callback_call(zzgs->layout, "gadget_site_dropped", pointer_site);
2857              _gadget_free(zgc);
2858           }
2859 
2860      }
2861    E_FREE_FUNC(pointer_site, evas_object_del);
2862    return ECORE_CALLBACK_RENEW;
2863 }
2864 
2865 static Eina_Bool
_editor_pointer_move(Gadget_Item * active EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Move * ev)2866 _editor_pointer_move(Gadget_Item *active EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
2867 {
2868    int w, h;
2869 
2870    evas_object_geometry_get(pointer_site, NULL, NULL, &w, &h);
2871    evas_object_move(pointer_site, ev->x - (w / 2), ev->y - (h / 2));
2872    if (!e_gadget_site_orient_get(pointer_site))
2873      evas_object_smart_need_recalculate_set(pointer_site, 1);
2874    return ECORE_CALLBACK_RENEW;
2875 }
2876 
2877 static Eina_Bool
_editor_pointer_wheel(Gadget_Item * active EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Wheel * ev)2878 _editor_pointer_wheel(Gadget_Item *active EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Wheel *ev)
2879 {
2880    int w, h;
2881 
2882    evas_object_geometry_get(pointer_site, NULL, NULL, &w, &h);
2883    evas_object_resize(pointer_site, w - (ev->z * 10 * e_scale), h - (ev->z * 10 * e_scale));
2884    evas_object_smart_need_recalculate_set(pointer_site, 1);
2885    return ECORE_CALLBACK_RENEW;
2886 }
2887 
2888 static void
_editor_pointer_site_init(E_Gadget_Site_Orient orient,Evas_Object * site,Evas_Object * editor,Eina_Bool up)2889 _editor_pointer_site_init(E_Gadget_Site_Orient orient, Evas_Object *site, Evas_Object *editor, Eina_Bool up)
2890 {
2891    Gadget_Item *active;
2892    Evas_Object *rect;
2893    int size;
2894 
2895    pointer_site = e_gadget_site_add(orient, NULL);
2896    if (site && (orient == E_GADGET_SITE_ORIENT_HORIZONTAL))
2897      evas_object_geometry_get(site, NULL, NULL, NULL, &size);
2898    else if (site && (orient == E_GADGET_SITE_ORIENT_VERTICAL))
2899      evas_object_geometry_get(site, NULL, NULL, &size, NULL);
2900    else
2901      size = 96 * e_scale;
2902    evas_object_resize(pointer_site, size, size);
2903    evas_object_layer_set(pointer_site, E_LAYER_MENU);
2904    evas_object_pass_events_set(pointer_site, 1);
2905    evas_object_show(pointer_site);
2906    active = E_NEW(Gadget_Item, 1);
2907    active->editor = editor;
2908    active->site = site;
2909    if (active->site)
2910      evas_object_pass_events_set(active->site, 1);
2911    evas_object_event_callback_add(pointer_site, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _editor_site_hints, active);
2912    evas_object_event_callback_add(pointer_site, EVAS_CALLBACK_DEL, _editor_pointer_site_del, active);
2913    E_LIST_HANDLER_APPEND(pointer_site_handlers, ECORE_EVENT_MOUSE_MOVE, _editor_pointer_move, active);
2914    if (!orient)
2915      E_LIST_HANDLER_APPEND(pointer_site_handlers, ECORE_EVENT_MOUSE_WHEEL, _editor_pointer_wheel, active);
2916    E_LIST_HANDLER_APPEND(pointer_site_handlers,
2917      up ? ECORE_EVENT_MOUSE_BUTTON_UP : ECORE_EVENT_MOUSE_BUTTON_DOWN, _editor_pointer_button, active);
2918 
2919    rect = evas_object_rectangle_add(e_comp->evas);
2920    evas_object_resize(rect, e_comp->w, e_comp->h);
2921    evas_object_color_set(rect, 0, 0, 0, 0);
2922    evas_object_layer_set(rect, E_LAYER_MENU + 1);
2923    e_comp_object_util_del_list_append(pointer_site, rect);
2924    evas_object_show(rect);
2925    e_comp_grab_input(1, 1);
2926 }
2927 
2928 static void
_editor_gadget_new(void * data,Evas_Object * obj,void * event_info)2929 _editor_gadget_new(void *data, Evas_Object *obj, void *event_info)
2930 {
2931    Gadget_Item *gi = data;
2932    E_Gadget_Site_Orient orient;
2933    E_Gadget_Config *zgc;
2934 
2935    zgc = evas_object_data_get(gi->gadget, "__e_gadget");
2936 
2937    evas_object_hide(desktop_editor);
2938    evas_object_pass_events_set(desktop_editor, 1);
2939    orient = e_gadget_site_orient_get(gi->site);
2940    _editor_pointer_site_init(orient, gi->site, gi->editor, 0);
2941 
2942    if (zgc->external.domain)
2943      e_gadget_site_gadget_external_add(pointer_site, zgc->external.domain, e_gadget_type_get(gi->gadget), 1);
2944    else
2945      e_gadget_site_gadget_add(pointer_site, e_gadget_type_get(gi->gadget), 1);
2946    ZGS_GET(pointer_site);
2947    {
2948       zgc = eina_list_data_get(zgs->gadgets);
2949       zgc->moving = 1;
2950    }
2951    elm_object_disabled_set(gi->editor, 1);
2952    if (eina_streq(evas_object_type_get(obj), "elm_genlist"))
2953      elm_genlist_item_selected_set(event_info, 0);
2954    else
2955      elm_gengrid_item_selected_set(event_info, 0);
2956 }
2957 
2958 static Evas_Object *
_editor_content_get(void * data,Evas_Object * obj,const char * part,Evas_Object * old)2959 _editor_content_get(void *data, Evas_Object *obj, const char *part, Evas_Object *old)
2960 {
2961    Gadget_Item *gi = data;
2962    Eina_Bool gl = eina_streq(evas_object_type_get(obj), "elm_genlist");
2963 
2964    if (eina_streq(part, "elm.swallow.icon"))
2965      {
2966         if (gl) return NULL;
2967      }
2968    else if (!gl) return NULL;
2969    if (old)
2970      {
2971         if (gi->box == old) return old;
2972         elm_box_unpack_all(old);
2973         elm_box_unpack(gi->box, gi->gadget);
2974         elm_box_pack_end(old, gi->gadget);
2975         gi->box = old;
2976         return old;
2977      }
2978    gi->box = elm_box_add(obj);
2979    elm_box_horizontal_set(gi->box, 1);
2980    elm_box_pack_end(gi->box, gi->gadget);
2981    return gi->box;
2982 }
2983 
2984 static char *
_editor_text_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part EINA_UNUSED)2985 _editor_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
2986 {
2987    char buf[1024];
2988    Gadget_Item *gi = data;
2989    E_Gadget_Config *zgc;
2990 
2991    zgc = evas_object_data_get(gi->gadget, "__e_gadget");
2992    if (zgc->external.domain)
2993      {
2994         E_Gadget_External_Type *te;
2995 
2996         te = _gadget_external_type_get(zgc->external.domain, zgc->external.type);
2997         if (te->name)
2998           return te->name(zgc->external.type);
2999         ERR("No name cb for external gadget provider!");
3000         return strdup(_("ERROR: NO NAME PROVIDED"));
3001      }
3002    strncpy(buf, e_gadget_type_get(gi->gadget), sizeof(buf) - 1);
3003    buf[0] = toupper(buf[0]);
3004    return strdup(buf);
3005 }
3006 
3007 static void
_editor_gadget_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3008 _editor_gadget_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3009 {
3010    Gadget_Item *gi = data;
3011    elm_object_item_del(gi->it);
3012 }
3013 
3014 static int
_editor_sort(Elm_Object_Item * ita,Elm_Object_Item * itb)3015 _editor_sort(Elm_Object_Item *ita, Elm_Object_Item *itb)
3016 {
3017    Gadget_Item *a = elm_object_item_data_get(ita);
3018    Gadget_Item *b = elm_object_item_data_get(itb);
3019 
3020    return strcasecmp(e_gadget_type_get(a->gadget), e_gadget_type_get(b->gadget));
3021 }
3022 
3023 E_API Evas_Object *
e_gadget_editor_add(Evas_Object * parent,Evas_Object * site)3024 e_gadget_editor_add(Evas_Object *parent, Evas_Object *site)
3025 {
3026    Evas_Object *list, *tempsite, *g;
3027    Eina_Iterator *it;
3028    Eina_List *gadgets;
3029    const char *type;
3030    E_Gadget_Site_Orient orient = e_gadget_site_orient_get(site);
3031    static Elm_Genlist_Item_Class gli =
3032    {
3033     .version = ELM_GENLIST_ITEM_CLASS_VERSION,
3034     .func =
3035     {
3036        .text_get = _editor_text_get,
3037        .reusable_content_get = _editor_content_get,
3038        .del = _editor_item_del,
3039     },
3040    };
3041 
3042    if (orient)
3043      {
3044         orient = E_GADGET_SITE_ORIENT_HORIZONTAL;
3045         list = elm_genlist_add(parent);
3046         elm_genlist_homogeneous_set(list, 1);
3047         elm_genlist_mode_set(list, ELM_LIST_COMPRESS);
3048      }
3049    else
3050      {
3051         list = elm_gengrid_add(parent);
3052         evas_object_event_callback_add(list, EVAS_CALLBACK_RESIZE, _editor_resize, NULL);
3053      }
3054    elm_scroller_bounce_set(list, 0, 0);
3055    elm_scroller_policy_set(list, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3056    tempsite = e_gadget_site_add(orient, NULL);
3057    evas_object_name_set(tempsite, evas_object_name_get(site));
3058    e_gadget_site_gravity_set(tempsite, E_GADGET_SITE_GRAVITY_NONE);
3059 
3060    it = e_gadget_type_iterator_get();
3061    /* FIXME: no types available */
3062    EINA_ITERATOR_FOREACH(it, type)
3063      {
3064         E_Gadget_Config *zgc;
3065         e_gadget_site_gadget_add(tempsite, type, 1);
3066         ZGS_GET(tempsite);
3067         zgc = eina_list_last_data_get(zgs->gadgets);
3068         if ((zgc) && (!zgc->gadget)) _gadget_remove(zgc);
3069      }
3070    eina_iterator_free(it);
3071 
3072    if (gadget_external_domains)
3073      {
3074         Eina_Hash_Tuple *tup;
3075 
3076         it = eina_hash_iterator_tuple_new(gadget_external_domains);
3077         EINA_ITERATOR_FOREACH(it, tup)
3078           {
3079              const char *domain = tup->key;
3080              Eina_Hash *h = tup->data;
3081              E_Gadget_Config *zgc;
3082              Eina_Iterator *typeit = eina_hash_iterator_key_new(h);
3083 
3084              EINA_ITERATOR_FOREACH(typeit, type)
3085                {
3086                   e_gadget_site_gadget_external_add(tempsite, domain, type, 1);
3087                   ZGS_GET(tempsite);
3088                   zgc = eina_list_last_data_get(zgs->gadgets);
3089                   if (!zgc->gadget) _gadget_remove(zgc);
3090                }
3091              eina_iterator_free(typeit);
3092           }
3093         eina_iterator_free(it);
3094      }
3095 
3096    gadgets = e_gadget_site_gadgets_list(tempsite);
3097    EINA_LIST_FREE(gadgets, g)
3098      {
3099         Gadget_Item *gi;
3100 
3101         gi = E_NEW(Gadget_Item, 1);
3102         gi->editor = list;
3103         gi->gadget = g;
3104         gi->site = site;
3105         E_EXPAND(g);
3106         E_FILL(g);
3107         evas_object_pass_events_set(g, 1);
3108         evas_object_event_callback_add(g, EVAS_CALLBACK_DEL, _editor_gadget_del, gi);
3109         if (orient)
3110           gi->it = elm_genlist_item_sorted_insert(list, &gli, gi, NULL, 0, (Eina_Compare_Cb)_editor_sort, _editor_gadget_new, gi);
3111         else
3112           gi->it = elm_gengrid_item_sorted_insert(list, &gli, gi, (Eina_Compare_Cb)_editor_sort, _editor_gadget_new, gi);
3113      }
3114    evas_object_event_callback_add(list, EVAS_CALLBACK_DEL, _editor_del, parent);
3115    e_comp_object_util_del_list_append(list, tempsite);
3116    ZGS_GET(site);
3117    evas_object_event_callback_add(site, EVAS_CALLBACK_DEL, _edit_site_del, zgs);
3118    evas_object_data_set(list, "__gadget_site", site);
3119    /* FIXME: embedded editors? */
3120    zgs->editor = list;
3121    if (desktop_rect)
3122      {
3123         Eina_List *l;
3124         E_Gadget_Config *zgc;
3125 
3126         EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
3127           _desktop_rect_obj_add(zgc->display);
3128      }
3129    added = 0;
3130    return list;
3131 }
3132 
3133 static void
_editor_show(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)3134 _editor_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3135 {
3136    if (obj == desktop_editor)
3137      evas_object_pass_events_set(desktop_editor, 0);
3138 }
3139 
3140 E_API Evas_Object *
e_gadget_site_edit(Evas_Object * site)3141 e_gadget_site_edit(Evas_Object *site)
3142 {
3143    Evas_Object *comp_object, *popup, *editor, *tb, *r;
3144    E_Zone *zone, *czone;
3145 
3146    ZGS_GET(site);
3147    EINA_SAFETY_ON_TRUE_RETURN_VAL(!!zgs->editor, NULL);
3148    zone = e_comp_object_util_zone_get(site);
3149    czone = e_zone_current_get();
3150    if (zone != czone)
3151      {
3152         int x, y, w, h;
3153 
3154         evas_object_geometry_get(site, &x, &y, &w, &h);
3155         if (E_INTERSECTS(x, y, w, h, czone->x, czone->y, czone->w, czone->h))
3156           zone = czone;
3157      }
3158 
3159    popup = elm_popup_add(e_comp->elm);
3160    elm_popup_scrollable_set(popup, EINA_FALSE);
3161    elm_popup_allow_events_set(popup, 1);
3162 
3163    tb = elm_table_add(popup);
3164    elm_object_content_set(popup, tb);
3165    r = evas_object_rectangle_add(e_comp->evas);
3166    evas_object_size_hint_min_set(r, zone->w / 2, 1);
3167    e_comp_object_util_del_list_append(tb, r);
3168    elm_table_pack(tb, r, 0, 0, 2, 1);
3169    r = evas_object_rectangle_add(e_comp->evas);
3170    evas_object_size_hint_min_set(r, 1, zone->h / 2);
3171    e_comp_object_util_del_list_append(tb, r);
3172    elm_table_pack(tb, r, 0, 1, 1, 1);
3173 
3174    editor = e_gadget_editor_add(e_comp->elm, site);
3175    elm_table_pack(tb, editor, 0, 1, 2, 2);
3176    evas_object_show(editor);
3177    E_EXPAND(editor);
3178    E_FILL(editor);
3179    comp_object = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
3180    evas_object_layer_set(comp_object, E_LAYER_POPUP);
3181    evas_object_show(comp_object);
3182    evas_object_event_callback_add(comp_object, EVAS_CALLBACK_SHOW, _editor_show, NULL);
3183    evas_object_resize(comp_object, zone->w / 2, zone->h / 2);
3184    e_comp_object_util_center_on_zone(comp_object, zone);
3185 
3186    return comp_object;
3187 }
3188 
3189 static void
_edit_end()3190 _edit_end()
3191 {
3192    if (desktop_editor)
3193      {
3194         E_Action *act;
3195 
3196         act = e_action_find("desk_deskshow_toggle");
3197         if (act) act->func.go(E_OBJECT(e_comp_object_util_zone_get(desktop_editor)), NULL);
3198         evas_object_hide(desktop_editor);
3199         E_FREE_FUNC(desktop_editor, evas_object_del);
3200      }
3201    E_FREE_FUNC(desktop_rect, evas_object_del);
3202    E_FREE_LIST(desktop_handlers, ecore_event_handler_del);
3203    e_comp_ungrab_input(1, 1);
3204 }
3205 
3206 static void
_edit_site_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3207 _edit_site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3208 {
3209    E_Gadget_Site *zgs = data;
3210 
3211    evas_object_data_del(zgs->editor, "__gadget_site");
3212    zgs->editor = NULL;
3213    _edit_end();
3214 }
3215 
3216 static void
_gadget_desklock_del(void)3217 _gadget_desklock_del(void)
3218 {
3219    e_desklock_hide();
3220    desktop_editor = NULL;
3221    _edit_end();
3222 }
3223 
3224 static void
_gadget_desklock_clear(void)3225 _gadget_desklock_clear(void)
3226 {
3227    Eina_List *l;
3228    E_Gadget_Site *zgs;
3229 
3230    EINA_LIST_FOREACH(sites->sites, l, zgs)
3231      if (zgs->autoadd && zgs->layout && strstr(zgs->name, "desklock."))
3232        {
3233           E_LIST_FOREACH(zgs->gadgets, _gadget_remove);
3234        }
3235 }
3236 
3237 static Eina_Bool
_gadget_desklock_key_handler(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Key * ev)3238 _gadget_desklock_key_handler(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Key *ev)
3239 {
3240    if ((!_editor_site_visible()) && (!pointer_site)) return ECORE_CALLBACK_RENEW;
3241    if (eina_streq(ev->key, "Escape"))
3242      {
3243         if (pointer_site)
3244           {
3245              E_FREE_FUNC(pointer_site, evas_object_del);
3246              if (desktop_editor) evas_object_show(desktop_editor);
3247           }
3248         else
3249           _gadget_desklock_del();
3250      }
3251    else if (eina_streq(ev->key, "Delete") || eina_streq(ev->key, "BackSpace"))
3252      _gadget_desklock_clear();
3253    return ECORE_CALLBACK_DONE;
3254 }
3255 
3256 static void
_gadget_desklock_mouse_up_handler(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3257 _gadget_desklock_mouse_up_handler(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
3258 {
3259    Evas_Event_Mouse_Down *ev = event_info;
3260    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
3261    if (ev->button != 1) return;
3262    if (!_editor_site_visible()) return;
3263    if (!added)
3264      _gadget_desklock_del();
3265    added = 0;
3266 }
3267 
3268 static void
_gadget_moved()3269 _gadget_moved()
3270 {
3271    added = 1;
3272 }
3273 
3274 static Eina_List *desktop_editor_move_handlers;
3275 static Evas_Point desktop_editor_move_point;
3276 static E_Zone *desktop_editor_move_zone;
3277 
3278 static void
_desktop_editor_mouse_up_job(void * d)3279 _desktop_editor_mouse_up_job(void *d)
3280 {
3281    evas_object_repeat_events_set(d, 1);
3282 }
3283 
3284 static Eina_Bool
_desktop_editor_mouse_up(void * d,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev EINA_UNUSED)3285 _desktop_editor_mouse_up(void *d, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev EINA_UNUSED)
3286 {
3287    E_FREE_LIST(desktop_editor_move_handlers, ecore_event_handler_del);
3288    evas_object_pointer_mode_set(d, EVAS_OBJECT_POINTER_MODE_NOGRAB);
3289    ecore_job_add(_desktop_editor_mouse_up_job, d);
3290    return ECORE_CALLBACK_RENEW;
3291 }
3292 
3293 static Eina_Bool
_desktop_editor_mouse_move(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Move * ev)3294 _desktop_editor_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
3295 {
3296    int x, y, w, h;
3297    int nx, ny;
3298 
3299    evas_object_geometry_get(desktop_editor, &x, &y, &w, &h);
3300    nx = x + ev->x - desktop_editor_move_point.x;
3301    ny = y + ev->y - desktop_editor_move_point.y;
3302    desktop_editor_move_point.x = ev->x;
3303    desktop_editor_move_point.y = ev->y;
3304    if (!E_CONTAINS(desktop_editor_move_zone->x, desktop_editor_move_zone->y, desktop_editor_move_zone->w, desktop_editor_move_zone->h,
3305                    nx, ny, w, h))
3306      {
3307         if (nx < desktop_editor_move_zone->x) nx = desktop_editor_move_zone->x;
3308         if (ny < desktop_editor_move_zone->y) ny = desktop_editor_move_zone->y;
3309         if (nx + w > desktop_editor_move_zone->x + desktop_editor_move_zone->w)
3310           nx = desktop_editor_move_zone->x + desktop_editor_move_zone->w - w;
3311         if (ny + h > desktop_editor_move_zone->y + desktop_editor_move_zone->h)
3312           ny = desktop_editor_move_zone->y + desktop_editor_move_zone->h - h;
3313      }
3314    evas_object_move(desktop_editor, nx, ny);
3315    return ECORE_CALLBACK_RENEW;
3316 }
3317 
3318 static void
_desktop_editor_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)3319 _desktop_editor_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
3320 {
3321    Evas_Event_Mouse_Down *ev = event_info;
3322    uintptr_t button = (uintptr_t)(uintptr_t*)data;
3323    uintptr_t modifiers = button % 10000;
3324    int i;
3325    const char *names[] =
3326    {
3327       "Shift",
3328       "Control",
3329       "Alt",
3330       "Win",
3331       "AltGr",
3332    };
3333 
3334    button = (button - modifiers) / 10000;
3335    if (button != (unsigned int)ev->button) return;
3336    for (i = 0; modifiers && i < 5; i++)
3337      {
3338         if (!(modifiers & (1 << i))) continue;
3339         if (evas_key_modifier_is_set(ev->modifiers, names[i]))
3340           modifiers &= ~(1 << i);
3341      }
3342    if (modifiers) return;
3343    desktop_editor_move_point.x = ev->output.x;
3344    desktop_editor_move_point.y = ev->output.y;
3345    desktop_editor_move_zone = e_comp_object_util_zone_get(obj);
3346    evas_object_pointer_mode_set(obj, EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN);
3347    evas_object_repeat_events_set(obj, 0);
3348    E_LIST_HANDLER_APPEND(desktop_editor_move_handlers, ECORE_EVENT_MOUSE_MOVE, _desktop_editor_mouse_move, obj);
3349    E_LIST_HANDLER_APPEND(desktop_editor_move_handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _desktop_editor_mouse_up, obj);
3350 }
3351 
3352 static void
_desktop_editor_restack(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)3353 _desktop_editor_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3354 {
3355    evas_object_layer_set(data, evas_object_layer_get(obj));
3356 }
3357 
3358 static void
_desktop_editor_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)3359 _desktop_editor_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3360 {
3361    int x, y, w, h;
3362 
3363    evas_object_geometry_get(obj, &x, &y, &w, &h);
3364    evas_object_geometry_set(data, x, y, w, h);
3365 }
3366 
3367 static void
_desktop_editor_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3368 _desktop_editor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3369 {
3370    evas_object_del(data);
3371    E_FREE_LIST(desktop_editor_move_handlers, ecore_event_handler_del);
3372 }
3373 
3374 static void
_desktop_editor_visibility(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)3375 _desktop_editor_visibility(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3376 {
3377    if (evas_object_visible_get(obj))
3378      {
3379         evas_object_show(data);
3380         evas_object_pointer_mode_set(data, EVAS_OBJECT_POINTER_MODE_NOGRAB);
3381      }
3382    else
3383      {
3384         evas_object_hide(data);
3385         evas_object_pointer_mode_set(data, EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN);
3386      }
3387 }
3388 
3389 static void
_desktop_editor_text_add(void)3390 _desktop_editor_text_add(void)
3391 {
3392    Evas_Object *txt, *tb, *popup = e_comp_object_util_get(desktop_editor);
3393    unsigned int button, modifiers;
3394    char *hotkeys;
3395 
3396    hotkeys = e_bindings_mouse_action_modifiers_text_generate(E_BINDING_CONTEXT_ANY, "gadget_move", &modifiers, &button);
3397    tb = elm_object_content_get(popup);
3398    if (hotkeys)
3399      {
3400         char buf[4096];
3401         Evas_Object *bx, *r;
3402 
3403         elm_object_content_unset(popup);
3404         r = evas_object_rectangle_add(e_comp->evas);
3405         evas_object_repeat_events_set(r, 1);
3406         _desktop_rect_obj_add(r);
3407         evas_object_layer_set(r, evas_object_layer_get(desktop_editor));
3408         evas_object_color_set(r, 0, 0, 0, 0);
3409         evas_object_show(r);
3410         bx = elm_box_add(popup);
3411         evas_object_event_callback_add(bx, EVAS_CALLBACK_MOVE, _desktop_editor_moveresize, r);
3412         evas_object_event_callback_add(bx, EVAS_CALLBACK_RESIZE, _desktop_editor_moveresize, r);
3413         evas_object_event_callback_add(desktop_editor, EVAS_CALLBACK_RESTACK, _desktop_editor_restack, r);
3414         evas_object_event_callback_add(desktop_editor, EVAS_CALLBACK_DEL, _desktop_editor_del, r);
3415         evas_object_event_callback_add(desktop_editor, EVAS_CALLBACK_SHOW, _desktop_editor_visibility, r);
3416         evas_object_event_callback_add(desktop_editor, EVAS_CALLBACK_HIDE, _desktop_editor_visibility, r);
3417         evas_object_show(bx);
3418         elm_object_content_set(popup, bx);
3419         elm_box_pack_end(bx, tb);
3420         txt = elm_label_add(tb);
3421         elm_box_pack_start(bx, txt);
3422         evas_object_show(txt);
3423         snprintf(buf, sizeof(buf), _("The current binding to move gadgets and this dialog is %s+<hilight>Mouse %d</hilight>"), hotkeys, button);
3424         elm_object_text_set(txt, buf);
3425         evas_object_pointer_mode_set(r, EVAS_OBJECT_POINTER_MODE_NOGRAB);
3426         button = (button * 10000) + modifiers;
3427         evas_object_event_callback_add(r, EVAS_CALLBACK_MOUSE_DOWN, _desktop_editor_mouse_down, (uintptr_t*)(uintptr_t)button);
3428      }
3429    txt = elm_label_add(tb);
3430    evas_object_show(txt);
3431    elm_object_text_set(txt, _("Press <hilight>Escape</hilight> or click the background to exit.<ps/>"
3432               "Use <hilight>Backspace</hilight> or <hilight>Delete</hilight> to remove all gadgets from this screen"));
3433    elm_table_pack(tb, txt, 0, 3, 2, 1);
3434 }
3435 
3436 static Eina_Bool
_gadget_desklock_handler(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Comp_Object * ev)3437 _gadget_desklock_handler(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
3438 {
3439    const char *name;
3440    Evas_Object *site, *comp_object;
3441 
3442    name = evas_object_name_get(ev->comp_object);
3443    if (!name) return ECORE_CALLBACK_RENEW;
3444    if (strncmp(name, "desklock", 8)) return ECORE_CALLBACK_RENEW;
3445    evas_object_layer_set(ev->comp_object, DESKLOCK_DEMO_LAYER - 1);
3446    site = e_gadget_site_auto_add(E_GADGET_SITE_ORIENT_NONE, name);
3447    _desktop_rect_obj_add(site);
3448    evas_object_smart_callback_add(site, "gadget_moved", _gadget_moved, NULL);
3449    evas_object_layer_set(site, DESKLOCK_DEMO_LAYER);
3450    ZGS_GET(site);
3451    desktop_editor = comp_object = e_gadget_site_edit(site);
3452    _desktop_editor_text_add();
3453    _desktop_rect_obj_add(zgs->events);
3454    _desktop_rect_obj_add(comp_object);
3455    e_comp_object_util_del_list_append(ev->comp_object, comp_object);
3456 
3457    return ECORE_CALLBACK_RENEW;
3458 }
3459 
3460 E_API void
e_gadget_site_desklock_edit(void)3461 e_gadget_site_desklock_edit(void)
3462 {
3463    desktop_rect = evas_object_event_grabber_add(e_comp->evas);
3464    evas_object_resize(desktop_rect, e_comp->w, e_comp->h);
3465    evas_object_layer_set(desktop_rect, E_LAYER_MAX - 100);
3466    evas_object_show(desktop_rect);
3467    E_LIST_HANDLER_APPEND(desktop_handlers, E_EVENT_COMP_OBJECT_ADD, _gadget_desklock_handler, NULL);
3468    E_LIST_HANDLER_APPEND(desktop_handlers, ECORE_EVENT_KEY_DOWN, _gadget_desklock_key_handler, NULL);
3469    evas_object_event_callback_add(desktop_rect, EVAS_CALLBACK_MOUSE_UP, _gadget_desklock_mouse_up_handler, NULL);
3470    e_desklock_demo();
3471    e_comp_grab_input(1, 1);
3472 }
3473 
3474 static Eina_Bool
_gadget_desktop_key_handler(void * data,int t EINA_UNUSED,Ecore_Event_Key * ev)3475 _gadget_desktop_key_handler(void *data, int t EINA_UNUSED, Ecore_Event_Key *ev)
3476 {
3477    if ((!_editor_site_visible()) && (!pointer_site)) return ECORE_CALLBACK_RENEW;
3478    if (eina_streq(ev->key, "Escape"))
3479      {
3480         if (pointer_site)
3481           {
3482              E_FREE_FUNC(pointer_site, evas_object_del);
3483              if (desktop_editor) evas_object_show(desktop_editor);
3484           }
3485         else
3486           _edit_end();
3487      }
3488    else if (eina_streq(ev->key, "Delete") || eina_streq(ev->key, "BackSpace"))
3489      {
3490         E_Gadget_Site *zgs = data;
3491         E_LIST_FOREACH(zgs->gadgets, _gadget_remove);
3492      }
3493    return ECORE_CALLBACK_DONE;
3494 }
3495 
3496 static void
_gadget_desktop_mouse_up_handler(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3497 _gadget_desktop_mouse_up_handler(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
3498 {
3499    Evas_Event_Mouse_Down *ev = event_info;
3500    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
3501    if (ev->button != 1) return;
3502    if (!_editor_site_visible()) return;
3503    if (!added)
3504      _edit_end();
3505    added = 0;
3506 }
3507 
3508 E_API void
e_gadget_site_desktop_edit(Evas_Object * site)3509 e_gadget_site_desktop_edit(Evas_Object *site)
3510 {
3511    E_Action *act;
3512 
3513    ZGS_GET(site);
3514 
3515    desktop_rect = evas_object_event_grabber_add(e_comp->evas);
3516    evas_object_event_callback_add(desktop_rect, EVAS_CALLBACK_DEL, _edit_end, NULL);
3517    evas_object_resize(desktop_rect, e_comp->w, e_comp->h);
3518    evas_object_layer_set(desktop_rect, E_LAYER_MAX - 100);
3519    evas_object_show(desktop_rect);
3520 
3521    _desktop_rect_obj_add(site);
3522 
3523    E_LIST_HANDLER_APPEND(desktop_handlers, ECORE_EVENT_KEY_DOWN, _gadget_desktop_key_handler, zgs);
3524    evas_object_event_callback_add(desktop_rect, EVAS_CALLBACK_MOUSE_UP, _gadget_desktop_mouse_up_handler, NULL);
3525 
3526    desktop_editor = e_gadget_site_edit(site);
3527    _desktop_editor_text_add();
3528    _desktop_rect_obj_add(desktop_editor);
3529    evas_object_smart_callback_add(site, "gadget_moved", _gadget_moved, NULL);
3530    evas_object_show(desktop_editor);
3531 
3532    act = e_action_find("desk_deskshow_toggle");
3533    if (act) act->func.go(E_OBJECT(e_comp_object_util_zone_get(desktop_editor)), NULL);
3534    e_comp_grab_input(1, 1);
3535 }
3536