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