1 #include "edje_private.h"
2
3 static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);
4 static void _edje_param_copy(Edje *ed, Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param);
5 static void _edje_param_set(Edje *ed, Edje_Real_Part *part, const char *param, const char *value);
6
7 static double _edje_transition_duration_scale = 0;
8
9 static Eina_Bool
_edje_animator_cb(void * data)10 _edje_animator_cb(void *data)
11 {
12 const Efl_Event event = { NULL, NULL, NULL };
13 _edje_timer_cb(data, &event);
14 return EINA_TRUE;
15 }
16
17 static Eina_Bool
_edje_emit_aliased(Edje * ed,const char * part,const char * sig,const char * src)18 _edje_emit_aliased(Edje *ed, const char *part, const char *sig, const char *src)
19 {
20 char *alias, *aliased;
21 int alien, nslen, length;
22
23 /* lookup for alias */
24 if ((!ed->collection) || (!ed->collection->alias)) return EINA_FALSE;
25 alias = eina_hash_find(ed->collection->alias, part);
26 if (!alias) return EINA_FALSE;
27
28 alien = strlen(alias);
29 nslen = strlen(sig);
30 length = alien + nslen + 2;
31
32 aliased = alloca(length);
33 memcpy(aliased, alias, alien);
34 aliased[alien] = EDJE_PART_PATH_SEPARATOR;
35 memcpy(aliased + alien + 1, sig, nslen + 1);
36
37 _edje_emit(ed, aliased, src);
38 return EINA_TRUE;
39 }
40
41 static Eina_Bool
_edje_emit_child(Edje * ed,Edje_Real_Part * rp,const char * part,const char * sig,const char * src)42 _edje_emit_child(Edje *ed, Edje_Real_Part *rp, const char *part, const char *sig, const char *src)
43 {
44 Edje *ed2;
45 char *idx;
46
47 /* search for the index if present and remove it from the part */
48 idx = strchr(part, EDJE_PART_PATH_SEPARATOR_INDEXL);
49 if (idx)
50 {
51 char *end;
52
53 end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
54 if (end && end != idx + 1)
55 {
56 char *tmp;
57
58 tmp = alloca(end - idx);
59 memcpy(tmp, idx + 1, end - idx - 1);
60 tmp[end - idx - 1] = '\0';
61 *idx = '\0';
62 idx = tmp;
63 }
64 else
65 {
66 idx = NULL;
67 }
68 }
69
70 /* search for the right part now */
71 if (!rp)
72 rp = _edje_real_part_get(ed, part);
73 if (!rp) return ed->collection->broadcast_signal;
74
75 switch (rp->part->type)
76 {
77 case EDJE_PART_TYPE_GROUP:
78 if (((rp->type != EDJE_RP_TYPE_SWALLOW) ||
79 (!rp->typedata.swallow)) ||
80 (!rp->typedata.swallow->swallowed_object))
81 break;
82 ed2 = _edje_fetch(rp->typedata.swallow->swallowed_object);
83 if (!ed2) break;
84
85 _edje_emit(ed2, sig, src);
86 return EINA_FALSE;
87
88 case EDJE_PART_TYPE_EXTERNAL:
89 if (((rp->type != EDJE_RP_TYPE_SWALLOW) ||
90 (!rp->typedata.swallow)) ||
91 (!rp->typedata.swallow->swallowed_object))
92 break;
93
94 if (!idx)
95 {
96 _edje_external_signal_emit(rp->typedata.swallow->swallowed_object, sig, src);
97 }
98 else
99 {
100 Evas_Object *child;
101
102 child = _edje_children_get(rp, idx);
103 ed2 = _edje_fetch(child);
104 if (!ed2) break;
105 _edje_emit(ed2, sig, src);
106 }
107 return EINA_FALSE;
108
109 case EDJE_PART_TYPE_BOX:
110 case EDJE_PART_TYPE_TABLE:
111 if (idx)
112 {
113 Evas_Object *child;
114
115 child = _edje_children_get(rp, idx);
116 ed2 = _edje_fetch(child);
117 if (!ed2) break;
118 _edje_emit(ed2, sig, src);
119 return EINA_FALSE;
120 }
121 break;
122
123 default:
124 // ERR("Unknown part type. You should never be here!");
125 break;
126 }
127 return ed->collection->broadcast_signal;
128 }
129
130 static Edje_Message_Signal_Data *
_edje_signal_data_setup(void * data,Ecore_Cb free_func,void * seat_data,Ecore_Cb seat_free_func)131 _edje_signal_data_setup(void *data, Ecore_Cb free_func, void *seat_data, Ecore_Cb seat_free_func)
132 {
133 Edje_Message_Signal_Data *out = NULL;
134
135 if (data || seat_data)
136 {
137 out = calloc(1, sizeof(*out));
138 if (!out) return NULL;
139
140 out->ref = 1;
141 out->data = data;
142 out->free_func = free_func;
143 out->seat_data = seat_data;
144 out->seat_free_func = seat_free_func;
145 }
146 return out;
147 }
148
149 void
_edje_signal_data_free(Edje_Message_Signal_Data * mdata)150 _edje_signal_data_free(Edje_Message_Signal_Data *mdata)
151 {
152 if (!mdata) return;
153 if (--(mdata->ref)) return;
154
155 if (mdata->free_func)
156 {
157 mdata->free_func(mdata->data);
158 }
159 if (mdata->seat_free_func)
160 {
161 mdata->seat_free_func(mdata->seat_data);
162 }
163 free(mdata);
164 }
165
166 void
_edje_signal_data_ref(Edje_Message_Signal_Data * mdata)167 _edje_signal_data_ref(Edje_Message_Signal_Data *mdata)
168 {
169 if (mdata) mdata->ref++;
170 }
171
172 static void
_edje_emit_send(Edje * ed,Eina_Bool broadcast,const char * sig,const char * src,Edje_Message_Signal_Data * mdata)173 _edje_emit_send(Edje *ed, Eina_Bool broadcast, const char *sig, const char *src, Edje_Message_Signal_Data *mdata)
174 {
175 Edje_Message_Signal emsg;
176
177 emsg.sig = sig;
178 emsg.src = src;
179 emsg.data = mdata;
180 /* new sends code */
181 if (broadcast)
182 edje_object_message_send(ed->obj, EDJE_MESSAGE_SIGNAL, 0, &emsg);
183 else
184 _edje_util_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
185 /* old send code - use api now
186 _edje_util_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
187 EINA_LIST_FOREACH(ed->subobjs, l, obj)
188 {
189 Edje *ed2;
190
191 ed2 = _edje_fetch(obj);
192 if (!ed2) continue;
193 if (ed2->delete_me) continue;
194 _edje_util_message_send(ed2, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
195 }
196 */
197 }
198
199 /*============================================================================*
200 * API *
201 *============================================================================*/
202
203 EOLIAN Eina_Stringshare*
_efl_canvas_layout_seat_name_get(const Eo * obj EINA_UNUSED,Edje * ed,Efl_Input_Device * device)204 _efl_canvas_layout_seat_name_get(const Eo *obj EINA_UNUSED, Edje *ed, Efl_Input_Device *device)
205 {
206 return _edje_seat_name_get(ed, device);
207 }
208
209 EOLIAN Efl_Input_Device *
_efl_canvas_layout_seat_get(const Eo * obj EINA_UNUSED,Edje * ed,Eina_Stringshare * name)210 _efl_canvas_layout_seat_get(const Eo *obj EINA_UNUSED, Edje *ed, Eina_Stringshare *name)
211 {
212 return _edje_seat_get(ed, name);
213 }
214
215 EAPI void
edje_frametime_set(double t)216 edje_frametime_set(double t)
217 {
218 ecore_animator_frametime_set(t);
219 }
220
221 EAPI double
edje_frametime_get(void)222 edje_frametime_get(void)
223 {
224 return ecore_animator_frametime_get();
225 }
226
227 EAPI double
edje_transition_duration_factor_get(void)228 edje_transition_duration_factor_get(void)
229 {
230 return _edje_transition_duration_scale;
231 }
232
233 EAPI void
edje_transition_duration_factor_set(double scale)234 edje_transition_duration_factor_set(double scale)
235 {
236 _edje_transition_duration_scale = FROM_DOUBLE(scale);
237 }
238
239 Eina_Bool
_edje_object_signal_callback_add(Evas_Object * obj,Edje * ed,const char * emission,const char * source,Edje_Signal_Cb func_legacy,Efl_Signal_Cb func_eo,Eina_Free_Cb func_free_cb,void * data)240 _edje_object_signal_callback_add(Evas_Object *obj, Edje *ed,
241 const char *emission, const char *source,
242 Edje_Signal_Cb func_legacy,
243 Efl_Signal_Cb func_eo, Eina_Free_Cb func_free_cb, void *data)
244 {
245 Edje_Signal_Callback_Group *gp;
246 const char *sig;
247 const char *src;
248 Eina_Bool ok;
249
250 if (!ed->callbacks)
251 ed->callbacks = _edje_signal_callback_alloc();
252 if (!ed->callbacks) return EINA_FALSE;
253
254 sig = eina_stringshare_add(emission);
255 src = eina_stringshare_add(source);
256
257 // Only load seat callbacks and trigger events just before we might need them.
258 if (!ed->need_seat && sig && !strncmp(sig, "seat,", 5))
259 {
260 ed->need_seat = EINA_TRUE;
261 if (ed->collection)
262 _edje_devices_add(ed, evas_object_evas_get(obj));
263 }
264
265 gp = (Edje_Signal_Callback_Group *) ed->callbacks;
266 ok = _edje_signal_callback_push(gp, sig, src, func_legacy, func_eo, func_free_cb, data, EINA_TRUE);
267
268 eina_stringshare_del(sig);
269 eina_stringshare_del(src);
270
271 return ok;
272 }
273
274 void
edje_object_propagate_callback_add(Evas_Object * obj,Efl_Signal_Cb func,void * data)275 edje_object_propagate_callback_add(Evas_Object *obj, Efl_Signal_Cb func, void *data)
276 {
277 Edje *ed;
278
279 ed = _edje_fetch(obj);
280 if (!ed || ed->delete_me) return;
281 _edje_object_signal_callback_add(obj, ed, "*", "*", func, NULL, NULL, data);
282 }
283
284 Eina_Bool
_efl_canvas_layout_efl_layout_signal_signal_callback_add(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)285 _efl_canvas_layout_efl_layout_signal_signal_callback_add(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
286 {
287 return _edje_object_signal_callback_add(obj, ed, emission, source, NULL, func, func_free_cb, func_data);
288 }
289
290 Eina_Bool
_efl_canvas_layout_efl_layout_signal_signal_callback_del(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)291 _efl_canvas_layout_efl_layout_signal_signal_callback_del(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
292 {
293 Edje_Signal_Callback_Group *gp;
294 Eina_Bool ok;
295
296 if (ed->delete_me) return EINA_FALSE;
297 if ((!emission) || (!source) || (!func)) return EINA_FALSE;
298
299 gp = (Edje_Signal_Callback_Group *) ed->callbacks;
300 if (!gp) return EINA_FALSE;
301
302 emission = eina_stringshare_add(emission);
303 source = eina_stringshare_add(source);
304
305 ok = _edje_signal_callback_disable(gp, emission, source, NULL, func, func_free_cb, func_data);
306
307 eina_stringshare_del(emission);
308 eina_stringshare_del(source);
309
310 return ok;
311 }
312
313 EOLIAN void
_efl_canvas_layout_efl_layout_signal_signal_emit(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source)314 _efl_canvas_layout_efl_layout_signal_signal_emit(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source)
315 {
316 if (ed->delete_me) return;
317 if ((!emission) || (!source)) return;
318 _edje_emit(ed, emission, source);
319 }
320
321 /* FIXDOC: Verify/Expand */
322 EOLIAN void
_efl_canvas_layout_animated_set(Eo * obj,Edje * ed,Eina_Bool on)323 _efl_canvas_layout_animated_set(Eo *obj, Edje *ed, Eina_Bool on)
324 {
325 Eina_List *l;
326 unsigned short i;
327
328 if (!ed) return;
329 if (ed->delete_me) return;
330 _edje_block(ed);
331 ed->no_anim = !on;
332 _edje_util_freeze(ed);
333 if (!on)
334 {
335 Eina_List *newl = NULL;
336 Edje_Running_Program *data;
337
338 EINA_LIST_FOREACH(ed->actions, l, data)
339 {
340 data->ref++;
341 newl = eina_list_append(newl, data);
342 }
343 while (newl)
344 {
345 Edje_Running_Program *runp;
346
347 runp = eina_list_data_get(newl);
348 newl = eina_list_remove(newl, eina_list_data_get(newl));
349 runp->ref--;
350 _edje_program_run_iterate(runp, runp->start_time + TO_DOUBLE(runp->program->tween.time));
351 if (_edje_block_break(ed))
352 {
353 EINA_LIST_FREE(newl, data)
354 {
355 data->ref--;
356 if ((data->delete_me) && (data->ref == 0))
357 {
358 _edje_program_run_cleanup(ed, data);
359 free(data);
360 }
361 }
362 goto break_prog;
363 }
364 }
365 }
366 else
367 {
368 _edje_emit(ed, "load", NULL);
369 if (evas_object_visible_get(obj))
370 {
371 evas_object_hide(obj);
372 evas_object_show(obj);
373 }
374 }
375 break_prog:
376
377 for (i = 0; i < ed->table_parts_size; i++)
378 {
379 Edje_Real_Part *rp;
380 rp = ed->table_parts[i];
381 if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
382 ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
383 (rp->typedata.swallow)) &&
384 (rp->typedata.swallow->swallowed_object))
385 edje_object_animation_set(rp->typedata.swallow->swallowed_object, on);
386 }
387
388 _edje_util_thaw(ed);
389 _edje_unblock(ed);
390 }
391
392 EOLIAN Eina_Bool
_efl_canvas_layout_animated_get(const Eo * obj EINA_UNUSED,Edje * ed)393 _efl_canvas_layout_animated_get(const Eo *obj EINA_UNUSED, Edje *ed)
394 {
395 if (!ed) return EINA_FALSE;
396 if (ed->delete_me) return EINA_FALSE;
397 if (ed->no_anim) return EINA_FALSE;
398
399 return EINA_TRUE;
400 }
401
402 /* Private Routines */
403 void
_edje_program_run_cleanup(Edje * ed,Edje_Running_Program * runp)404 _edje_program_run_cleanup(Edje *ed, Edje_Running_Program *runp)
405 {
406 ed->actions = eina_list_remove(ed->actions, runp);
407 if (!ed->actions)
408 {
409 efl_event_callback_del(ed->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _edje_timer_cb, ed);
410 ecore_animator_del(ed->animator);
411 ed->animator = NULL;
412 }
413 }
414
415 Eina_Bool
_edje_program_run_iterate(Edje_Running_Program * runp,double tim)416 _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
417 {
418 FLOAT_T t, total, t_scale = runp->edje->duration_scale;
419 Eina_List *l;
420 Edje *ed;
421 Edje_Program_Target *pt;
422 Edje_Real_Part *rp;
423
424 ed = runp->edje;
425 if (ed->delete_me) return EINA_FALSE;
426 _edje_block(ed);
427 _edje_ref(ed);
428 _edje_util_freeze(ed);
429
430 if (runp->program->tween.use_duration_factor)
431 t_scale = _edje_transition_duration_scale;
432 t = FROM_DOUBLE(tim - runp->start_time);
433 total = runp->program->tween.time * t_scale;
434 t = DIV(t, total);
435 if (t > FROM_INT(1)) t = FROM_INT(1);
436 EINA_LIST_FOREACH(runp->program->targets, l, pt)
437 {
438 if (pt->id >= 0)
439 {
440 rp = ed->table_parts[pt->id % ed->table_parts_size];
441 if (rp)
442 _edje_part_pos_set(ed, rp,
443 runp->program->tween.mode, t,
444 runp->program->tween.v1,
445 runp->program->tween.v2,
446 runp->program->tween.v3,
447 runp->program->tween.v4);
448 }
449 }
450 if (t >= FROM_INT(1))
451 {
452 Edje_Program_After *pa;
453
454 EINA_LIST_FOREACH(runp->program->targets, l, pt)
455 {
456 if (pt->id >= 0)
457 {
458 rp = ed->table_parts[pt->id % ed->table_parts_size];
459 if (rp)
460 {
461 _edje_part_description_apply(ed, rp,
462 runp->program->state,
463 runp->program->value,
464 NULL,
465 0.0);
466 _edje_part_pos_set(ed, rp,
467 runp->program->tween.mode, ZERO,
468 runp->program->tween.v1,
469 runp->program->tween.v2,
470 runp->program->tween.v3,
471 runp->program->tween.v4);
472 rp->program = NULL;
473 }
474 }
475 }
476 _edje_recalc(ed);
477 runp->delete_me = EINA_TRUE;
478 if (!ed->walking_actions)
479 _edje_program_run_cleanup(ed, runp);
480 // _edje_emit(ed, "program,stop", runp->program->name);
481 if (_edje_block_break(ed))
482 {
483 if (!ed->walking_actions)
484 {
485 if (runp->ref == 0)
486 {
487 _edje_program_run_cleanup(ed, runp);
488 free(runp);
489 }
490 }
491 goto break_prog;
492 }
493 EINA_LIST_FOREACH(runp->program->after, l, pa)
494 {
495 Edje_Program *pr;
496
497 if (pa->id >= 0)
498 {
499 pr = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
500 if (pr) _edje_program_run(ed, pr, 0, "", "", NULL);
501 if (_edje_block_break(ed))
502 {
503 if ((!ed->walking_actions) && (runp->ref == 0))
504 {
505 _edje_program_run_cleanup(ed, runp);
506 free(runp);
507 }
508 goto break_prog;
509 }
510 }
511 }
512 _edje_util_thaw(ed);
513 _edje_unref(ed);
514 if ((!ed->walking_actions) && (runp->ref == 0))
515 {
516 _edje_program_run_cleanup(ed, runp);
517 free(runp);
518 }
519 _edje_unblock(ed);
520 return EINA_FALSE;
521 }
522 break_prog:
523 _edje_recalc(ed);
524 _edje_util_thaw(ed);
525 _edje_unref(ed);
526 _edje_unblock(ed);
527 return EINA_TRUE;
528 }
529
530 void
_edje_program_end(Edje * ed,Edje_Running_Program * runp)531 _edje_program_end(Edje *ed, Edje_Running_Program *runp)
532 {
533 Eina_List *l;
534 Edje_Program_Target *pt;
535 // const char *pname = NULL;
536 int free_runp = 0;
537
538 if (ed->delete_me) return;
539 _edje_ref(ed);
540 _edje_util_freeze(ed);
541 EINA_LIST_FOREACH(runp->program->targets, l, pt)
542 {
543 Edje_Real_Part *rp;
544
545 if (pt->id >= 0)
546 {
547 rp = ed->table_parts[pt->id % ed->table_parts_size];
548 if (rp)
549 {
550 _edje_part_description_apply(ed, rp,
551 runp->program->state,
552 runp->program->value,
553 NULL,
554 0.0);
555 _edje_part_pos_set(ed, rp,
556 runp->program->tween.mode, ZERO,
557 runp->program->tween.v1,
558 runp->program->tween.v2,
559 runp->program->tween.v3,
560 runp->program->tween.v4);
561
562 rp->program = NULL;
563 }
564 }
565 }
566 _edje_recalc(ed);
567 runp->delete_me = EINA_TRUE;
568 // pname = runp->program->name;
569 if (!ed->walking_actions)
570 {
571 _edje_program_run_cleanup(ed, runp);
572 free_runp = 1;
573 }
574 // _edje_emit(ed, "program,stop", pname);
575 _edje_util_thaw(ed);
576 _edje_unref(ed);
577 if ((free_runp) && (runp->ref == 0)) free(runp);
578 }
579
580 #ifdef HAVE_EPHYSICS
581 static Eina_Bool
_edje_physics_action_set(Edje * ed,Edje_Program * pr,void (* func)(EPhysics_Body * body,double x,double y,double z))582 _edje_physics_action_set(Edje *ed, Edje_Program *pr, void (*func)(EPhysics_Body *body, double x, double y, double z))
583 {
584 Edje_Program_Target *pt;
585 Edje_Real_Part *rp;
586 Eina_List *l;
587
588 if (_edje_block_break(ed)) return EINA_FALSE;
589
590 EINA_LIST_FOREACH(pr->targets, l, pt)
591 {
592 if (pt->id >= 0)
593 {
594 rp = ed->table_parts[pt->id % ed->table_parts_size];
595 if ((rp) && (rp->body))
596 func(rp->body, pr->physics.x, pr->physics.y, pr->physics.z);
597 }
598 }
599
600 return EINA_TRUE;
601 }
602
603 #endif
604
605 static void
_edje_seat_name_emit(Edje * ed,const char * name,const char * sig,const char * src)606 _edje_seat_name_emit(Edje *ed, const char *name, const char *sig, const char *src)
607 {
608 char buf[128];
609
610 /* keep sending signals without seat information for legacy compatibility */
611 _edje_emit_full(ed, sig, src, NULL, NULL);
612
613 if (!name) return;
614
615 snprintf(buf, sizeof(buf), "seat,%s,%s", name, sig);
616 _edje_emit_full(ed, buf, src, NULL, NULL);
617 }
618
619 void
_edje_part_focus_set(Edje * ed,const char * seat_name,Edje_Real_Part * rp)620 _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp)
621 {
622 Edje_Real_Part *focused_part;
623 Eina_Stringshare *sname;
624 Efl_Input_Device *seat;
625 Evas *e;
626
627 if (seat_name)
628 sname = eina_stringshare_add(seat_name);
629 else /* Use default seat name */
630 {
631 e = evas_object_evas_get(ed->obj);
632 seat = evas_default_device_get(e, EVAS_DEVICE_CLASS_SEAT);
633 sname = eina_stringshare_ref(_edje_seat_name_get(ed, seat));
634 }
635
636 focused_part = _edje_focused_part_get(ed, sname);
637
638 if (focused_part != rp)
639 {
640 if (rp && (rp->part->allowed_seats) &&
641 (!_edje_part_allowed_seat_find(rp, sname)))
642 goto not_allowed;
643
644 if (focused_part)
645 _edje_seat_name_emit(ed, sname, "focus,part,out",
646 focused_part->part->name);
647 _edje_focused_part_set(ed, sname, rp);
648 if (rp)
649 _edje_seat_name_emit(ed, sname, "focus,part,in", rp->part->name);
650 }
651
652 not_allowed:
653 eina_stringshare_del(sname);
654 }
655
656 void
_edje_program_run(Edje * ed,Edje_Program * pr,Eina_Bool force,const char * ssig,const char * ssrc,Edje_Message_Signal_Data * mdata)657 _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc, Edje_Message_Signal_Data *mdata)
658 {
659 Eina_List *l;
660 Edje_Real_Part *rp;
661 Edje_Program_Target *pt;
662 Edje_Program *pr2;
663 Edje_Program_After *pa;
664 /* limit self-feeding loops in programs to 64 levels */
665 static int recursions = 0;
666 static int recursion_limit = 0;
667
668 if (ed->delete_me) return;
669 if ((pr->in.from > 0.0) && (pr->in.range >= 0.0) && (!force))
670 {
671 Edje_Pending_Program *pp;
672 double r = 0.0;
673
674 pp = calloc(1, sizeof(Edje_Pending_Program));
675 if (!pp) return;
676 if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
677 pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
678 _edje_pending_timer_cb, pp);
679 if (!pp->timer)
680 {
681 free(pp);
682 return;
683 }
684 pp->edje = ed;
685 pp->program = pr;
686 ed->pending_actions = eina_list_append(ed->pending_actions, pp);
687 return;
688 }
689 if ((recursions >= 64) || (recursion_limit))
690 {
691 ERR("Programs recursing up to recursion limit of %i in '%s' with sig='%s', src='%s' from '%s', '%s'. Disabled.",
692 64, pr->name, ssig, ssrc, ed->path, ed->group);
693 if (pr->action == EDJE_ACTION_TYPE_STATE_SET && (EQ(pr->tween.time, ZERO) || (ed->no_anim)))
694 ERR("Possible solution: try adding transition time to prevent Schrödinger's part state");
695 recursion_limit = 1;
696 return;
697 }
698 recursions++;
699 _edje_block(ed);
700 _edje_ref(ed);
701 _edje_util_freeze(ed);
702 switch (pr->action)
703 {
704 case EDJE_ACTION_TYPE_STATE_SET:
705 if ((pr->tween.time > ZERO) && (!ed->no_anim))
706 {
707 Edje_Running_Program *runp;
708
709 runp = calloc(1, sizeof(Edje_Running_Program));
710 EINA_LIST_FOREACH(pr->targets, l, pt)
711 {
712 if (pt->id >= 0)
713 {
714 rp = ed->table_parts[pt->id % ed->table_parts_size];
715 if (rp)
716 {
717 if ((rp->object) && (pr->tween.mode & EDJE_TWEEN_MODE_OPT_FROM_CURRENT))
718 {
719 Edje_Calc_Params *tmp;
720
721 tmp = calloc(1, sizeof(Edje_Calc_Params));
722 if (!tmp) goto low_mem_current;
723 _edje_part_recalc(ed, rp, FLAG_XY, tmp);
724
725 if (rp->current)
726 {
727 #ifdef EDJE_CALC_CACHE
728 _edje_calc_params_clear(rp->current);
729 #endif
730 free(rp->current);
731 }
732 rp->current = tmp;
733 }
734 else
735 {
736 low_mem_current:
737 if (rp->current)
738 {
739 #ifdef EDJE_CALC_CACHE
740 _edje_calc_params_clear(rp->current);
741 #endif
742 free(rp->current);
743 }
744 rp->current = NULL;
745 }
746
747 if (rp->program)
748 _edje_program_end(ed, rp->program);
749 _edje_part_description_apply(ed, rp,
750 rp->param1.description->state.name,
751 rp->param1.description->state.value,
752 pr->state,
753 pr->value);
754 _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
755 pr->tween.v1,
756 pr->tween.v2,
757 pr->tween.v3,
758 pr->tween.v4);
759 rp->program = runp;
760 }
761 }
762 }
763 // _edje_emit(ed, "program,start", pr->name);
764 if (_edje_block_break(ed))
765 {
766 ed->actions = eina_list_append(ed->actions, runp);
767 goto break_prog;
768 }
769
770 if (!ed->actions)
771 {
772 if (ed->canvas_animator)
773 efl_event_callback_add(ed->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _edje_timer_cb, ed);
774 else
775 ed->animator = ecore_animator_add(_edje_animator_cb, ed);
776 }
777 ed->actions = eina_list_append(ed->actions, runp);
778
779 runp->start_time = ecore_loop_time_get();
780 runp->edje = ed;
781 runp->program = pr;
782 }
783 else
784 {
785 EINA_LIST_FOREACH(pr->targets, l, pt)
786 {
787 if (pt->id >= 0)
788 {
789 rp = ed->table_parts[pt->id % ed->table_parts_size];
790 if (rp)
791 {
792 if (rp->program)
793 _edje_program_end(ed, rp->program);
794 _edje_part_description_apply(ed, rp,
795 pr->state,
796 pr->value,
797 NULL,
798 0.0);
799 _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
800 pr->tween.v1,
801 pr->tween.v2,
802 pr->tween.v3,
803 pr->tween.v4);
804 }
805 }
806 }
807 // _edje_emit(ed, "program,start", pr->name);
808 if (_edje_block_break(ed)) goto break_prog;
809 // _edje_emit(ed, "program,stop", pr->name);
810 if (_edje_block_break(ed)) goto break_prog;
811
812 EINA_LIST_FOREACH(pr->after, l, pa)
813 {
814 if (pa->id >= 0)
815 {
816 pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
817 if (pr2) _edje_program_run(ed, pr2, 0, "", "", mdata);
818 if (_edje_block_break(ed)) goto break_prog;
819 }
820 }
821 _edje_recalc(ed);
822 }
823 break;
824
825 case EDJE_ACTION_TYPE_ACTION_STOP:
826 // _edje_emit(ed, "program,start", pr->name);
827 EINA_LIST_FOREACH(pr->targets, l, pt)
828 {
829 Eina_List *ll;
830 Edje_Running_Program *runp;
831 Edje_Pending_Program *pp;
832
833 for (ll = ed->actions; ll; )
834 {
835 runp = ll->data;
836 ll = ll->next;
837 if (pt->id == runp->program->id)
838 {
839 _edje_program_end(ed, runp);
840 // goto done;
841 }
842 }
843 for (ll = ed->pending_actions; ll; )
844 {
845 pp = ll->data;
846 ll = ll->next;
847 if (pt->id == pp->program->id)
848 {
849 ed->pending_actions = eina_list_remove(ed->pending_actions, pp);
850 ecore_timer_del(pp->timer);
851 pp->timer = NULL;
852 free(pp);
853 // goto done;
854 }
855 }
856 // done:
857 // continue;
858 }
859 // _edje_emit(ed, "program,stop", pr->name);
860 if (_edje_block_break(ed)) goto break_prog;
861 break;
862
863 case EDJE_ACTION_TYPE_SIGNAL_EMIT:
864 // _edje_emit(ed, "program,start", pr->name);
865 if (_edje_block_break(ed)) goto break_prog;
866 if (pr->targets)
867 {
868 EINA_LIST_FOREACH(pr->targets, l, pt)
869 {
870 if (pt->id < 0) continue;
871 rp = ed->table_parts[pt->id % ed->table_parts_size];
872 if (!rp) continue;
873 if (!_edje_emit_aliased(ed, rp->part->name, pr->state, pr->state2))
874 {
875 Eina_Bool broadcast;
876
877 broadcast = _edje_emit_child(ed, rp, rp->part->name, pr->state, pr->state2);
878 _edje_emit_send(ed, broadcast, pr->state, pr->state2, mdata);
879 }
880 }
881 }
882 else
883 _edje_emit_full_data(ed, pr->state, pr->state2, mdata);
884 if (_edje_block_break(ed)) goto break_prog;
885 // _edje_emit(ed, "program,stop", pr->name);
886 if (_edje_block_break(ed)) goto break_prog;
887 break;
888
889 case EDJE_ACTION_TYPE_DRAG_VAL_SET:
890 // _edje_emit(ed, "program,start", pr->name);
891 if (_edje_block_break(ed)) goto break_prog;
892 EINA_LIST_FOREACH(pr->targets, l, pt)
893 {
894 if (pt->id >= 0)
895 {
896 rp = ed->table_parts[pt->id % ed->table_parts_size];
897 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
898 {
899 rp->drag->val.x = pr->value;
900 rp->drag->val.y = pr->value2;
901 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
902 else if (rp->drag->val.x > 1.0)
903 rp->drag->val.x = 1.0;
904 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
905 else if (rp->drag->val.y > 1.0)
906 rp->drag->val.y = 1.0;
907 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
908 _edje_emit(ed, "drag,set", rp->part->name);
909 if (_edje_block_break(ed)) goto break_prog;
910 }
911 }
912 }
913 // _edje_emit(ed, "program,stop", pr->name);
914 if (_edje_block_break(ed)) goto break_prog;
915 break;
916
917 case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
918 // _edje_emit(ed, "program,start", pr->name);
919 if (_edje_block_break(ed)) goto break_prog;
920 EINA_LIST_FOREACH(pr->targets, l, pt)
921 {
922 if (pt->id >= 0)
923 {
924 rp = ed->table_parts[pt->id % ed->table_parts_size];
925 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
926 {
927 rp->drag->val.x += pr->value * rp->drag->step.x * rp->part->dragable.x;
928 rp->drag->val.y += pr->value2 * rp->drag->step.y * rp->part->dragable.y;
929 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
930 else if (rp->drag->val.x > 1.0)
931 rp->drag->val.x = 1.0;
932 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
933 else if (rp->drag->val.y > 1.0)
934 rp->drag->val.y = 1.0;
935 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
936 _edje_emit(ed, "drag,step", rp->part->name);
937 if (_edje_block_break(ed)) goto break_prog;
938 }
939 }
940 }
941 // _edje_emit(ed, "program,stop", pr->name);
942 if (_edje_block_break(ed)) goto break_prog;
943 break;
944
945 case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
946 // _edje_emit(ed, "program,start", pr->name);
947 if (_edje_block_break(ed)) goto break_prog;
948 EINA_LIST_FOREACH(pr->targets, l, pt)
949 {
950 if (pt->id >= 0)
951 {
952 rp = ed->table_parts[pt->id % ed->table_parts_size];
953 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
954 {
955 rp->drag->val.x += pr->value * rp->drag->page.x * rp->part->dragable.x;
956 rp->drag->val.y += pr->value2 * rp->drag->page.y * rp->part->dragable.y;
957 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
958 else if (rp->drag->val.x > 1.0)
959 rp->drag->val.x = 1.0;
960 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
961 else if (rp->drag->val.y > 1.0)
962 rp->drag->val.y = 1.0;
963 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
964 _edje_emit(ed, "drag,page", rp->part->name);
965 if (_edje_block_break(ed)) goto break_prog;
966 }
967 }
968 }
969 // _edje_emit(ed, "program,stop", pr->name);
970 if (_edje_block_break(ed)) goto break_prog;
971 break;
972
973 case EDJE_ACTION_TYPE_SCRIPT:
974 {
975 // _edje_emit(ed, "program,start", pr->name);
976 if (_edje_block_break(ed)) goto break_prog;
977 _edje_embryo_test_run(ed, pr, ssig, ssrc);
978 // _edje_emit(ed, "program,stop", pr->name);
979 if (_edje_block_break(ed)) goto break_prog;
980 _edje_recalc_do(ed);
981 }
982 break;
983
984 case EDJE_ACTION_TYPE_FOCUS_SET:
985 {
986 if (!pr->targets)
987 _edje_part_focus_set(ed, pr->seat, NULL);
988 else
989 {
990 EINA_LIST_FOREACH(pr->targets, l, pt)
991 {
992 if (pt->id >= 0)
993 {
994 rp = ed->table_parts[pt->id % ed->table_parts_size];
995 if (rp)
996 _edje_part_focus_set(ed, pr->seat, rp);
997 }
998 }
999 }
1000 }
1001 break;
1002
1003 case EDJE_ACTION_TYPE_FOCUS_OBJECT:
1004 {
1005 Efl_Input_Device *seat = NULL;
1006
1007 if (pr->seat)
1008 {
1009 Eina_Stringshare *seat_name;
1010
1011 seat_name = eina_stringshare_add(pr->seat);
1012 seat = _edje_seat_get(ed, seat_name);
1013 eina_stringshare_del(seat_name);
1014 }
1015 if (!seat)
1016 {
1017 Evas *e;
1018
1019 e = evas_object_evas_get(ed->obj);
1020 seat = evas_default_device_get(e, EVAS_DEVICE_CLASS_SEAT);
1021 }
1022 if (!pr->targets)
1023 {
1024 Evas_Object *focused;
1025
1026 focused = evas_seat_focus_get(evas_object_evas_get(ed->obj), seat);
1027 if (focused)
1028 {
1029 unsigned int i;
1030
1031 /* Check if the current swallowed object is one of my child. */
1032 for (i = 0; i < ed->table_parts_size; ++i)
1033 {
1034 rp = ed->table_parts[i];
1035 if ((rp) &&
1036 ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1037 (rp->typedata.swallow)) &&
1038 (rp->typedata.swallow->swallowed_object == focused))
1039 {
1040 efl_canvas_object_seat_focus_del(focused, seat);
1041 break;
1042 }
1043 }
1044 }
1045 }
1046 else
1047 {
1048 EINA_LIST_FOREACH(pr->targets, l, pt)
1049 {
1050 if (pt->id >= 0)
1051 {
1052 rp = ed->table_parts[pt->id % ed->table_parts_size];
1053 if (rp &&
1054 ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1055 (rp->typedata.swallow)) &&
1056 (rp->typedata.swallow->swallowed_object))
1057 efl_canvas_object_seat_focus_add(
1058 rp->typedata.swallow->swallowed_object, seat);
1059 }
1060 }
1061 }
1062 }
1063 break;
1064
1065 case EDJE_ACTION_TYPE_SOUND_SAMPLE:
1066 if (_edje_block_break(ed))
1067 goto break_prog;
1068 _edje_multisense_internal_sound_sample_play(ed, pr->sample_name, pr->speed, pr->channel);
1069 break;
1070
1071 case EDJE_ACTION_TYPE_SOUND_TONE:
1072 if (_edje_block_break(ed))
1073 goto break_prog;
1074 _edje_multisense_internal_sound_tone_play(ed, pr->tone_name, pr->duration, pr->channel);
1075 break;
1076
1077 case EDJE_ACTION_TYPE_VIBRATION_SAMPLE:
1078 if (_edje_block_break(ed))
1079 goto break_prog;
1080 _edje_multisense_internal_vibration_sample_play(ed, pr->vibration_name, pr->vibration_repeat);
1081 break;
1082
1083 case EDJE_ACTION_TYPE_PARAM_COPY:
1084 {
1085 Edje_Real_Part *src_part, *dst_part;
1086
1087 // _edje_emit(ed, "program,start", pr->name);
1088 if (_edje_block_break(ed)) goto break_prog;
1089
1090 src_part = ed->table_parts[pr->param.src % ed->table_parts_size];
1091 dst_part = ed->table_parts[pr->param.dst % ed->table_parts_size];
1092 _edje_param_copy(ed, src_part, pr->state, dst_part, pr->state2);
1093
1094 if (_edje_block_break(ed)) goto break_prog;
1095 // _edje_emit(ed, "program,stop", pr->name);
1096 if (_edje_block_break(ed)) goto break_prog;
1097 }
1098 break;
1099
1100 case EDJE_ACTION_TYPE_PARAM_SET:
1101 {
1102 Edje_Real_Part *part;
1103
1104 // _edje_emit(ed, "program,start", pr->name);
1105 if (_edje_block_break(ed)) goto break_prog;
1106
1107 part = ed->table_parts[pr->param.dst % ed->table_parts_size];
1108 _edje_param_set(ed, part, pr->state, pr->state2);
1109
1110 if (_edje_block_break(ed)) goto break_prog;
1111 // _edje_emit(ed, "program,stop", pr->name);
1112 if (_edje_block_break(ed)) goto break_prog;
1113 }
1114 break;
1115
1116 #ifdef HAVE_EPHYSICS
1117 case EDJE_ACTION_TYPE_PHYSICS_IMPULSE:
1118 if (EPH_LOAD())
1119 {
1120 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_central_impulse_apply)))
1121 goto break_prog;
1122 }
1123 break;
1124
1125 case EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE:
1126 if (EPH_LOAD())
1127 {
1128 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_torque_impulse_apply)))
1129 goto break_prog;
1130 }
1131 break;
1132
1133 case EDJE_ACTION_TYPE_PHYSICS_FORCE:
1134 if (EPH_LOAD())
1135 {
1136 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_central_force_apply)))
1137 goto break_prog;
1138 }
1139 break;
1140
1141 case EDJE_ACTION_TYPE_PHYSICS_TORQUE:
1142 if (EPH_LOAD())
1143 {
1144 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_torque_apply)))
1145 goto break_prog;
1146 }
1147 break;
1148
1149 case EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR:
1150 if (EPH_LOAD())
1151 {
1152 if (_edje_block_break(ed))
1153 goto break_prog;
1154 EINA_LIST_FOREACH(pr->targets, l, pt)
1155 {
1156 if (pt->id >= 0)
1157 {
1158 rp = ed->table_parts[pt->id % ed->table_parts_size];
1159 if ((rp) && (rp->body))
1160 EPH_CALL(ephysics_body_forces_clear)(rp->body);
1161 }
1162 }
1163 }
1164 break;
1165
1166 case EDJE_ACTION_TYPE_PHYSICS_VEL_SET:
1167 if (EPH_LOAD())
1168 {
1169 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_linear_velocity_set)))
1170 goto break_prog;
1171 }
1172 break;
1173
1174 case EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET:
1175 if (EPH_LOAD())
1176 {
1177 if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_angular_velocity_set)))
1178 goto break_prog;
1179 }
1180 break;
1181
1182 case EDJE_ACTION_TYPE_PHYSICS_STOP:
1183 if (EPH_LOAD())
1184 {
1185 if (_edje_block_break(ed))
1186 goto break_prog;
1187 EINA_LIST_FOREACH(pr->targets, l, pt)
1188 {
1189 if (pt->id >= 0)
1190 {
1191 rp = ed->table_parts[pt->id % ed->table_parts_size];
1192 if ((rp) && (rp->body))
1193 EPH_CALL(ephysics_body_stop)(rp->body);
1194 }
1195 }
1196 }
1197 break;
1198
1199 case EDJE_ACTION_TYPE_PHYSICS_ROT_SET:
1200 if (EPH_LOAD())
1201 {
1202 if (_edje_block_break(ed))
1203 goto break_prog;
1204 EINA_LIST_FOREACH(pr->targets, l, pt)
1205 {
1206 if (pt->id >= 0)
1207 {
1208 rp = ed->table_parts[pt->id % ed->table_parts_size];
1209 if ((rp) && (rp->body))
1210 {
1211 EPhysics_Quaternion quat;
1212 EPH_CALL(ephysics_quaternion_set)(&quat, pr->physics.x,
1213 pr->physics.y, pr->physics.z,
1214 pr->physics.w);
1215 EPH_CALL(ephysics_quaternion_normalize)(&quat);
1216 EPH_CALL(ephysics_body_rotation_set)(rp->body, &quat);
1217 }
1218 }
1219 }
1220 }
1221 break;
1222
1223 #endif
1224
1225 #ifdef BUILD_VG_LOADER_JSON
1226 case EDJE_ACTION_TYPE_VG_ANIM_STOP:
1227 if (_edje_block_break(ed))
1228 goto break_prog;
1229 EINA_LIST_FOREACH(pr->targets, l, pt)
1230 {
1231 if (pt->id >= 0)
1232 {
1233 rp = ed->table_parts[pt->id % ed->table_parts_size];
1234 if (rp)
1235 _edje_part_vector_anim_stop(ed, rp);
1236 }
1237 }
1238 break;
1239
1240 case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
1241 if (_edje_block_break(ed))
1242 goto break_prog;
1243 EINA_LIST_FOREACH(pr->targets, l, pt)
1244 {
1245 if (pt->id >= 0)
1246 {
1247 rp = ed->table_parts[pt->id % ed->table_parts_size];
1248 if (rp)
1249 _edje_part_vector_anim_pause(ed, rp);
1250 }
1251 }
1252 break;
1253
1254 case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
1255 if (_edje_block_break(ed))
1256 goto break_prog;
1257 EINA_LIST_FOREACH(pr->targets, l, pt)
1258 {
1259 if (pt->id >= 0)
1260 {
1261 rp = ed->table_parts[pt->id % ed->table_parts_size];
1262 if (rp)
1263 _edje_part_vector_anim_resume(ed, rp);
1264 }
1265 }
1266 break;
1267
1268 case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
1269 case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
1270 case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
1271 if (_edje_block_break(ed))
1272 goto break_prog;
1273 EINA_LIST_FOREACH(pr->targets, l, pt)
1274 {
1275 if (pt->id >= 0)
1276 {
1277 rp = ed->table_parts[pt->id % ed->table_parts_size];
1278 if (rp)
1279 {
1280 Eina_Bool vector_anim_backward = EINA_FALSE;
1281 Eina_Bool vector_anim_loop = EINA_FALSE;
1282
1283 if (pr->action == EDJE_ACTION_TYPE_VG_ANIM_REWIND)
1284 vector_anim_backward = EINA_TRUE;
1285
1286 if (pr->action == EDJE_ACTION_TYPE_VG_ANIM_LOOP)
1287 vector_anim_loop = EINA_TRUE;
1288
1289 _edje_part_vector_anim_play(ed, rp,
1290 vector_anim_backward,
1291 vector_anim_loop);
1292 }
1293 }
1294 }
1295 break;
1296 #else
1297 case EDJE_ACTION_TYPE_VG_ANIM_STOP:
1298 case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
1299 case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
1300 case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
1301 case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
1302 case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
1303 ERR("Evas Vg Json (Lottie) Loader is not supported, Only Static Vector Image(SVG) is available!");
1304 break;
1305 #endif
1306
1307 default:
1308 // _edje_emit(ed, "program,start", pr->name);
1309 // _edje_emit(ed, "program,stop", pr->name);
1310 break;
1311 }
1312 if (!((pr->action == EDJE_ACTION_TYPE_STATE_SET)
1313 /* hmm this fucks somethgin up. must look into it later */
1314 /* && (pr->tween.time > ZERO) && (!ed->no_anim))) */
1315 ))
1316 {
1317 EINA_LIST_FOREACH(pr->after, l, pa)
1318 {
1319 if (pa->id >= 0)
1320 {
1321 pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
1322 if (pr2) _edje_program_run(ed, pr2, 0, "", "", mdata);
1323 if (_edje_block_break(ed)) goto break_prog;
1324 }
1325 }
1326 }
1327 break_prog:
1328 _edje_util_thaw(ed);
1329 _edje_unref(ed);
1330 recursions--;
1331 if (recursions == 0) recursion_limit = 0;
1332 _edje_unblock(ed);
1333 }
1334
1335 void
_edje_emit(Edje * ed,const char * sig,const char * src)1336 _edje_emit(Edje *ed, const char *sig, const char *src)
1337 {
1338 _edje_emit_full(ed, sig, src, NULL, NULL);
1339 }
1340
1341 void
_edje_seat_emit(Edje * ed,Efl_Input_Device * dev,const char * sig,const char * src)1342 _edje_seat_emit(Edje *ed, Efl_Input_Device *dev, const char *sig, const char *src)
1343 {
1344 Edje_Message_Signal_Data *mdata = NULL;
1345 Efl_Input_Device *seat = NULL;
1346 char buf[128];
1347 char *sname;
1348 const char *s;
1349
1350 if (dev) seat = efl_input_device_seat_get(dev);
1351 if (seat)
1352 {
1353 sname = eina_strdup(efl_name_get(seat));
1354 mdata = _edje_signal_data_setup(NULL, NULL, sname, free);
1355 }
1356 /* keep sending old style signals for legacy compatibility, but provide */
1357 /* queryable seat data for callers that can make use of it. */
1358 _edje_emit_full_data(ed, sig, src, mdata);
1359
1360 /* send extra signal with ",$SEAT" suffix if the input device originating
1361 * the signal belongs to a seat */
1362 if (!seat) return;
1363
1364 s = _edje_seat_name_get(ed, seat);
1365 if (!s) s = "";
1366 snprintf(buf, sizeof(buf), "seat,%s,%s", s, sig);
1367 _edje_emit_full_data(ed, buf, src, mdata);
1368 _edje_signal_data_free(mdata);
1369 }
1370
1371 /* data should either be NULL or a malloc allocated data */
1372 void
_edje_emit_full(Edje * ed,const char * sig,const char * src,void * data,void (* free_func)(void *))1373 _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *))
1374 {
1375 Edje_Message_Signal_Data *mdata;
1376
1377 mdata = _edje_signal_data_setup(data, free_func, NULL, NULL);
1378 _edje_emit_full_data(ed, sig, src, mdata);
1379 _edje_signal_data_free(mdata);
1380 }
1381
1382 void
_edje_emit_full_data(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * mdata)1383 _edje_emit_full_data(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *mdata)
1384 {
1385 const char *sep;
1386 Eina_Bool broadcast;
1387
1388 if (!ed->collection) return;
1389 if (ed->delete_me) return;
1390
1391 _edje_signal_data_ref(mdata);
1392
1393 sep = strchr(sig, EDJE_PART_PATH_SEPARATOR);
1394 /* If we are not sending the signal to a part of the child, the
1395 * signal if for ourself
1396 */
1397 if (sep)
1398 {
1399 const char *newsig;
1400 char *part;
1401 unsigned int length;
1402
1403 /* the signal contains a colon, split the signal into "parts:signal" */
1404 length = sep - sig + 1;
1405 part = alloca(length);
1406 memcpy(part, sig, length - 1);
1407 part[length - 1] = '\0';
1408
1409 newsig = sep + 1;
1410
1411 if (_edje_emit_aliased(ed, part, newsig, src)) goto out;
1412
1413 broadcast = _edje_emit_child(ed, NULL, part, newsig, src);
1414 }
1415 else
1416 broadcast = ed->collection->broadcast_signal;
1417
1418 _edje_emit_send(ed, broadcast, sig, src, mdata);
1419 out:
1420 _edje_signal_data_free(mdata);
1421 }
1422
1423 void
_edje_focused_part_set(Edje * ed,Eina_Stringshare * seat_name,Edje_Real_Part * rp)1424 _edje_focused_part_set(Edje *ed, Eina_Stringshare *seat_name, Edje_Real_Part *rp)
1425 {
1426 Edje_Seat *seat;
1427 Eina_List *l;
1428
1429 //defaulting seat NULL to seat1
1430 if (!seat_name) seat_name = eina_stringshare_add("seat1");
1431
1432 EINA_LIST_FOREACH(ed->seats, l, seat)
1433 {
1434 if (seat_name == seat->name)
1435 {
1436 seat->focused_part = rp;
1437 return;
1438 }
1439 }
1440
1441 /* A part to be set for a seat not yet announced by Evas */
1442 seat = calloc(1, sizeof(Edje_Seat));
1443 EINA_SAFETY_ON_NULL_RETURN(seat);
1444
1445 seat->name = eina_stringshare_ref(seat_name);
1446 seat->focused_part = rp;
1447 ed->seats = eina_list_append(ed->seats, seat);
1448
1449 return;
1450 }
1451
1452 Edje_Real_Part *
_edje_focused_part_get(Edje * ed,Eina_Stringshare * seat_name)1453 _edje_focused_part_get(Edje *ed, Eina_Stringshare *seat_name)
1454 {
1455 Edje_Seat *seat;
1456 Eina_List *l;
1457
1458 //defaulting seat NULL to seat1
1459 if (!seat_name) seat_name = eina_stringshare_add("seat1");
1460
1461 EINA_LIST_FOREACH(ed->seats, l, seat)
1462 {
1463 if (seat_name == seat->name)
1464 return seat->focused_part;
1465 }
1466
1467 return NULL;
1468 }
1469
1470 Eina_Stringshare*
_edje_seat_name_get(Edje * ed,Efl_Input_Device * device)1471 _edje_seat_name_get(Edje *ed, Efl_Input_Device *device)
1472 {
1473 Edje_Seat *seat;
1474 Eina_List *l;
1475
1476 EINA_LIST_FOREACH(ed->seats, l, seat)
1477 {
1478 if (seat->device == device)
1479 return seat->name;
1480 }
1481
1482 return NULL;
1483 }
1484
1485 Efl_Input_Device *
_edje_seat_get(Edje * ed,Eina_Stringshare * name)1486 _edje_seat_get(Edje *ed, Eina_Stringshare *name)
1487 {
1488 Edje_Seat *seat;
1489 Eina_List *l;
1490
1491 EINA_LIST_FOREACH(ed->seats, l, seat)
1492 {
1493 if (seat->name == name)
1494 return seat->device;
1495 }
1496
1497 return NULL;
1498 }
1499
1500 struct _Edje_Program_Data
1501 {
1502 Eina_List *matches;
1503 Edje *ed;
1504 const char *source;
1505 };
1506
1507 static Eina_Bool
_edje_glob_callback(Edje_Program * pr,void * dt)1508 _edje_glob_callback(Edje_Program *pr, void *dt)
1509 {
1510 struct _Edje_Program_Data *data = dt;
1511 Edje_Real_Part *rp = NULL;
1512 Eina_Bool exec = EINA_TRUE;
1513
1514 if (pr->filter.state)
1515 {
1516 rp = _edje_real_part_get(data->ed, pr->filter.part ? pr->filter.part : data->source);
1517 if (rp)
1518 exec = !strcmp(rp->chosen_description->state.name, pr->filter.state);
1519 }
1520
1521 pr->exec = exec;
1522
1523 data->matches = eina_list_append(data->matches, pr);
1524
1525 return EINA_FALSE;
1526 }
1527
1528 /* FIXME: what if we delete the evas object??? */
1529 void
_edje_emit_handle(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * sdata,Eina_Bool prop)1530 _edje_emit_handle(Edje *ed, const char *sig, const char *src,
1531 Edje_Message_Signal_Data *sdata, Eina_Bool prop)
1532 {
1533 if (ed->delete_me) return;
1534 if (!sig) sig = "";
1535 if (!src) src = "";
1536 DBG("EDJE EMIT: (%p) signal: \"%s\" source: \"%s\"", ed, sig, src);
1537 _edje_block(ed);
1538 _edje_ref(ed);
1539 _edje_util_freeze(ed);
1540
1541 if (ed->collection && ed->L)
1542 _edje_lua2_script_func_signal(ed, sig, src);
1543
1544 if (ed->collection)
1545 {
1546 #ifdef EDJE_PROGRAM_CACHE
1547 Edje_Part_Collection *ec;
1548 char *tmps;
1549 int l1, l2;
1550 #endif
1551 int done;
1552
1553 #ifdef EDJE_PROGRAM_CACHE
1554 ec = ed->collection;
1555 l1 = strlen(sig);
1556 l2 = strlen(src);
1557 tmps = alloca(l1 + l2 + 3); /* \0, \337, \0 */
1558 strcpy(tmps, sig);
1559 tmps[l1] = '\377';
1560 strcpy(&(tmps[l1 + 1]), src);
1561 #endif
1562 done = 0;
1563
1564 #ifdef EDJE_PROGRAM_CACHE
1565 {
1566 Eina_List *matches;
1567 Eina_List *l;
1568 Edje_Program *pr;
1569
1570 if (eina_hash_find(ec->prog_cache.no_matches, tmps))
1571 {
1572 done = 1;
1573 }
1574 else if ((matches = eina_hash_find(ec->prog_cache.matches, tmps)))
1575 {
1576 EINA_LIST_FOREACH(matches, l, pr)
1577 {
1578 Eina_Bool exec = EINA_TRUE;
1579
1580 if (pr->filter.state)
1581 {
1582 Edje_Real_Part *rp;
1583
1584 rp = _edje_real_part_get(ed, pr->filter.part ? pr->filter.part : src);
1585 if (rp)
1586 {
1587 if (rp->program)
1588 exec = EINA_FALSE;
1589 else
1590 exec = (rp->chosen_description->state.name != pr->filter.state) ?
1591 !strcmp(rp->chosen_description->state.name, pr->filter.state) : EINA_TRUE;
1592 }
1593 }
1594
1595 pr->exec = exec;
1596 }
1597
1598 EINA_LIST_FOREACH(matches, l, pr)
1599 if (pr->exec)
1600 {
1601 _edje_program_run(ed, pr, 0, sig, src, sdata);
1602 if (_edje_block_break(ed))
1603 {
1604 goto break_prog;
1605 }
1606 }
1607
1608 done = 1;
1609 }
1610 }
1611 #endif
1612 if (!done)
1613 {
1614 struct _Edje_Program_Data data;
1615
1616 data.ed = ed;
1617 data.source = src;
1618 data.matches = NULL;
1619
1620 if (ed->collection->patterns.table_programs_size > 0)
1621 {
1622 const Eina_Inarray *match;
1623 #ifdef EDJE_PROGRAM_CACHE
1624 const Eina_List *l;
1625 #endif
1626 Edje_Program *pr;
1627
1628 if (ed->collection->patterns.programs.u.programs.globing)
1629 if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns,
1630 ed->collection->patterns.programs.sources_patterns,
1631 sig,
1632 src,
1633 ed->collection->patterns.programs.u.programs.globing,
1634 _edje_glob_callback,
1635 &data,
1636 prop) == 0)
1637 goto break_prog;
1638
1639 match = edje_match_signal_source_hash_get(sig, src,
1640 ed->collection->patterns.programs.exact_match);
1641 if (match)
1642 {
1643 Edje_Program **tpr;
1644
1645 EINA_INARRAY_FOREACH(match, tpr)
1646 _edje_glob_callback(*tpr, &data);
1647 }
1648
1649 #ifdef EDJE_PROGRAM_CACHE
1650 EINA_LIST_FOREACH(data.matches, l, pr)
1651 #else
1652 EINA_LIST_FREE(data.matches, pr)
1653 #endif
1654 {
1655 if (pr->exec)
1656 _edje_program_run(ed, pr, 0, sig, src, sdata);
1657
1658 if (_edje_block_break(ed))
1659 {
1660 eina_list_free(data.matches);
1661 data.matches = NULL;
1662 goto break_prog;
1663 }
1664 }
1665 }
1666
1667 #ifdef EDJE_PROGRAM_CACHE
1668 if (tmps)
1669 {
1670 if (data.matches == NULL)
1671 {
1672 if (!ec->prog_cache.no_matches)
1673 ec->prog_cache.no_matches = eina_hash_string_superfast_new(NULL);
1674 eina_hash_add(ec->prog_cache.no_matches, tmps, ed);
1675 }
1676 else
1677 {
1678 if (!ec->prog_cache.matches)
1679 ec->prog_cache.matches = eina_hash_string_superfast_new(NULL);
1680 eina_hash_add(ec->prog_cache.matches, tmps, data.matches);
1681 }
1682 }
1683 #endif
1684 }
1685 _edje_emit_cb(ed, sig, src, sdata, prop);
1686 if (_edje_block_break(ed))
1687 {
1688 goto break_prog;
1689 }
1690 }
1691 break_prog:
1692 _edje_util_thaw(ed);
1693 _edje_unref(ed);
1694 _edje_unblock(ed);
1695 }
1696
1697 /* Extra data for callbacks */
1698 static void *callback_extra_data = NULL;
1699 static void *callback_seat_data = NULL;
1700
1701 EAPI void *
edje_object_signal_callback_extra_data_get(void)1702 edje_object_signal_callback_extra_data_get(void)
1703 {
1704 return callback_extra_data;
1705 }
1706
1707 #ifdef EFL_BETA_API_SUPPORT
1708 EAPI void *
edje_object_signal_callback_seat_data_get(void)1709 edje_object_signal_callback_seat_data_get(void)
1710 {
1711 return callback_seat_data;
1712 }
1713 #endif
1714
1715 /* FIXME: what if we delete the evas object??? */
1716 static void
_edje_emit_cb(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * data,Eina_Bool prop)1717 _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
1718 {
1719 const Edje_Signals_Sources_Patterns *ssp;
1720 Edje_Signal_Callback_Matches *m;
1721 const Eina_Inarray *match;
1722 int r = 1;
1723
1724 if (ed->delete_me) return;
1725 if (!ed->callbacks || !ed->callbacks->matches) return;
1726
1727 _edje_ref(ed);
1728 _edje_util_freeze(ed);
1729 _edje_block(ed);
1730
1731 ed->walking_callbacks++;
1732
1733 ssp = _edje_signal_callback_patterns_ref
1734 ((Edje_Signal_Callback_Group *)ed->callbacks);
1735 if (ssp)
1736 {
1737 m = (Edje_Signal_Callback_Matches *)ed->callbacks->matches;
1738 EINA_REFCOUNT_REF(m);
1739
1740 callback_extra_data = (data) ? data->data : NULL;
1741 callback_seat_data = (data) ? data->seat_data : NULL;
1742
1743 if (eina_inarray_count(&ssp->u.callbacks.globing))
1744 r = edje_match_callback_exec(ssp,
1745 m->matches,
1746 sig,
1747 src,
1748 ed,
1749 prop);
1750
1751 if (!r) goto break_prog;
1752
1753 match = edje_match_signal_source_hash_get(sig, src,
1754 ssp->exact_match);
1755 if (match)
1756 {
1757 const Edje_Signal_Callback_Match *cb;
1758 unsigned int *i;
1759
1760 EINA_INARRAY_FOREACH(match, i)
1761 {
1762 if (ed->callbacks->flags[*i].delete_me) continue;
1763 if ((prop) && (ed->callbacks->flags[*i].propagate)) continue;
1764
1765 cb = &m->matches[*i];
1766
1767 if (ed->callbacks->flags[*i].legacy)
1768 cb->legacy((void *)ed->callbacks->custom_data[*i], ed->obj, sig, src);
1769 else
1770 cb->eo((void *)ed->callbacks->custom_data[*i], ed->obj, sig, src);
1771 if (_edje_block_break(ed)) break;
1772 }
1773 }
1774
1775 break_prog:
1776 _edje_signal_callback_matches_unref(m, ed->callbacks->flags, ed->callbacks->custom_data);
1777
1778 _edje_signal_callback_patterns_unref(ssp);
1779 }
1780
1781 ed->walking_callbacks--;
1782
1783 if (ed->walking_callbacks == 0)
1784 _edje_signal_callback_reset(ed->callbacks->flags,
1785 ed->callbacks->matches->matches_count);
1786
1787 _edje_unblock(ed);
1788 _edje_util_thaw(ed);
1789 _edje_unref(ed);
1790 }
1791
1792 static const Edje_External_Param_Info *
_edje_external_param_info_get(const Evas_Object * obj,const char * name)1793 _edje_external_param_info_get(const Evas_Object *obj, const char *name)
1794 {
1795 const Edje_External_Type *type;
1796 const Edje_External_Param_Info *info;
1797
1798 type = evas_object_data_get(obj, "Edje_External_Type");
1799 if (!type) return NULL;
1800 for (info = type->parameters_info; info->name; info++)
1801 if (!strcmp(info->name, name)) return info;
1802
1803 return NULL;
1804 }
1805
1806 static Edje_External_Param *
_edje_param_external_get(Edje_Real_Part * rp,const char * name,Edje_External_Param * param)1807 _edje_param_external_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param)
1808 {
1809 Evas_Object *swallowed_object;
1810 const Edje_External_Param_Info *info;
1811
1812 if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
1813 (!rp->typedata.swallow)) return NULL;
1814 swallowed_object = rp->typedata.swallow->swallowed_object;
1815
1816 info = _edje_external_param_info_get(swallowed_object, name);
1817 if (!info) return NULL;
1818
1819 memset(param, 0, sizeof(*param));
1820 param->name = info->name;
1821 param->type = info->type;
1822 if (!_edje_external_param_get(NULL, rp, param)) return NULL;
1823 return param;
1824 }
1825
1826 /* simulate external properties for native objects */
1827 static Edje_External_Param *
_edje_param_native_get(Edje * ed,Edje_Real_Part * rp,const char * name,Edje_External_Param * param,void ** free_ptr)1828 _edje_param_native_get(Edje *ed, Edje_Real_Part *rp, const char *name, Edje_External_Param *param, void **free_ptr)
1829 {
1830 *free_ptr = NULL;
1831 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1832 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1833 {
1834 if (!strcmp(name, "text"))
1835 {
1836 param->name = name;
1837 param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1838
1839 _edje_recalc_do(ed);
1840 if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1841 param->s = _edje_entry_text_get(rp);
1842 else if ((rp->part->type == EDJE_PART_TYPE_TEXT) &&
1843 ((rp->type == EDJE_RP_TYPE_TEXT) &&
1844 (rp->typedata.text)))
1845 param->s = rp->typedata.text->text;
1846 else
1847 param->s = evas_object_textblock_text_markup_get(rp->object);
1848 return param;
1849 }
1850 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1851 {
1852 if (!strcmp(name, "text_unescaped"))
1853 {
1854 param->name = name;
1855 param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1856
1857 _edje_recalc_do(ed);
1858 if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1859 {
1860 const char *tmp = _edje_entry_text_get(rp);
1861 char *unescaped = _edje_text_unescape(tmp);
1862 *free_ptr = unescaped;
1863 param->s = unescaped;
1864 }
1865 else if ((rp->part->type == EDJE_PART_TYPE_TEXT) &&
1866 ((rp->type == EDJE_RP_TYPE_TEXT) &&
1867 (rp->typedata.text)))
1868 param->s = rp->typedata.text->text;
1869 else
1870 {
1871 const char *tmp;
1872 char *unescaped;
1873
1874 tmp = evas_object_textblock_text_markup_get(rp->object);
1875 unescaped = _edje_text_unescape(tmp);
1876 *free_ptr = unescaped;
1877 param->s = unescaped;
1878 }
1879
1880 return param;
1881 }
1882
1883 if (((rp->type == EDJE_RP_TYPE_TEXT) &&
1884 (rp->typedata.text)) &&
1885 ((rp->typedata.text->entry_data) &&
1886 (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1887 (!strcmp(name, "select_allow"))))
1888 {
1889 param->name = name;
1890 param->type = EDJE_EXTERNAL_PARAM_TYPE_BOOL;
1891 param->i = _edje_entry_select_allow_get(rp);
1892 return param;
1893 }
1894 }
1895 }
1896
1897 if ((rp->drag) && (rp->drag->down.count == 0))
1898 {
1899 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1900 {
1901 const char *sub_name = name + sizeof("drag_") - 1;
1902 if (!strcmp(sub_name, "value_x"))
1903 {
1904 double d;
1905
1906 _edje_recalc_do(ed);
1907 d = TO_DOUBLE(rp->drag->val.x);
1908 if (rp->part->dragable.x < 0) d = 1.0 - d;
1909 param->name = name;
1910 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1911 param->d = d;
1912 return param;
1913 }
1914 if (!strcmp(sub_name, "value_y"))
1915 {
1916 double d;
1917
1918 _edje_recalc_do(ed);
1919 d = TO_DOUBLE(rp->drag->val.y);
1920 if (rp->part->dragable.y < 0) d = 1.0 - d;
1921 param->name = name;
1922 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1923 param->d = d;
1924 return param;
1925 }
1926
1927 if (!strcmp(sub_name, "size_w"))
1928 {
1929 _edje_recalc_do(ed);
1930 param->name = name;
1931 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1932 param->d = TO_DOUBLE(rp->drag->size.x);
1933 return param;
1934 }
1935 if (!strcmp(sub_name, "size_h"))
1936 {
1937 _edje_recalc_do(ed);
1938 param->name = name;
1939 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1940 param->d = TO_DOUBLE(rp->drag->size.y);
1941 return param;
1942 }
1943
1944 if (!strcmp(sub_name, "step_x"))
1945 {
1946 _edje_recalc_do(ed);
1947 param->name = name;
1948 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1949 param->d = TO_DOUBLE(rp->drag->step.x);
1950 return param;
1951 }
1952 if (!strcmp(sub_name, "step_y"))
1953 {
1954 _edje_recalc_do(ed);
1955 param->name = name;
1956 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1957 param->d = TO_DOUBLE(rp->drag->step.y);
1958 return param;
1959 }
1960
1961 if (!strcmp(sub_name, "page_x"))
1962 {
1963 _edje_recalc_do(ed);
1964 param->name = name;
1965 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1966 param->d = TO_DOUBLE(rp->drag->page.x);
1967 return param;
1968 }
1969 if (!strcmp(sub_name, "page_y"))
1970 {
1971 _edje_recalc_do(ed);
1972 param->name = name;
1973 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1974 param->d = TO_DOUBLE(rp->drag->page.y);
1975 return param;
1976 }
1977
1978 return NULL;
1979 }
1980 }
1981
1982 return NULL;
1983 }
1984
1985 static Eina_Bool
_edje_param_native_set(Edje * ed,Edje_Real_Part * rp,const char * name,const Edje_External_Param * param)1986 _edje_param_native_set(Edje *ed, Edje_Real_Part *rp, const char *name, const Edje_External_Param *param)
1987 {
1988 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1989 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1990 {
1991 if (!strcmp(name, "text"))
1992 {
1993 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1994 return EINA_FALSE;
1995
1996 _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, param->s);
1997 return EINA_TRUE;
1998 }
1999 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2000 {
2001 if (!strcmp(name, "text_unescaped"))
2002 {
2003 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
2004 return EINA_FALSE;
2005
2006 if (rp->part->type == EDJE_PART_TYPE_TEXT)
2007 _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, param->s);
2008 else
2009 {
2010 char *escaped = _edje_text_escape(param->s);
2011 _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, escaped);
2012 free(escaped);
2013 }
2014
2015 return EINA_TRUE;
2016 }
2017
2018 if (((rp->type == EDJE_RP_TYPE_TEXT) &&
2019 (rp->typedata.text)) &&
2020 ((rp->typedata.text->entry_data) &&
2021 (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
2022 (!strcmp(name, "select_allow"))))
2023 {
2024 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_BOOL)
2025 return EINA_FALSE;
2026 _edje_entry_select_allow_set(rp, param->i);
2027 return EINA_TRUE;
2028 }
2029 }
2030 }
2031
2032 if ((rp->drag) && (rp->drag->down.count == 0))
2033 {
2034 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
2035 {
2036 const char *sub_name = name + sizeof("drag_") - 1;
2037 if (!strcmp(sub_name, "value_x"))
2038 {
2039 double d;
2040 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2041 return EINA_FALSE;
2042 d = param->d;
2043 if (rp->part->dragable.confine_id != -1)
2044 d = CLAMP(d, 0.0, 1.0);
2045 if (rp->part->dragable.x < 0) d = 1.0 - d;
2046 if (EQ(rp->drag->val.x, FROM_DOUBLE(d))) return EINA_TRUE;
2047 rp->drag->val.x = FROM_DOUBLE(d);
2048 #ifdef EDJE_CALC_CACHE
2049 rp->invalidate = EINA_TRUE;
2050 #endif
2051 _edje_dragable_pos_set
2052 (ed, rp, rp->drag->val.x, rp->drag->val.y);
2053 _edje_emit(ed, "drag,set", rp->part->name);
2054 return EINA_TRUE;
2055 }
2056 if (!strcmp(sub_name, "value_y"))
2057 {
2058 double d;
2059 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2060 return EINA_FALSE;
2061 d = param->d;
2062 if (rp->part->dragable.confine_id != -1)
2063 d = CLAMP(d, 0.0, 1.0);
2064 if (rp->part->dragable.y < 0) d = 1.0 - d;
2065 if (EQ(rp->drag->val.y, FROM_DOUBLE(d))) return EINA_TRUE;
2066 rp->drag->val.y = FROM_DOUBLE(d);
2067 #ifdef EDJE_CALC_CACHE
2068 rp->invalidate = EINA_TRUE;
2069 #endif
2070 _edje_dragable_pos_set
2071 (ed, rp, rp->drag->val.x, rp->drag->val.y);
2072 _edje_emit(ed, "drag,set", rp->part->name);
2073 return EINA_TRUE;
2074 }
2075
2076 if (!strcmp(sub_name, "size_w"))
2077 {
2078 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2079 return EINA_FALSE;
2080 rp->drag->size.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2081 ed->recalc_call = EINA_TRUE;
2082 ed->dirty = EINA_TRUE;
2083 #ifdef EDJE_CALC_CACHE
2084 rp->invalidate = EINA_TRUE;
2085 #endif
2086 _edje_recalc(ed);
2087 return EINA_TRUE;
2088 }
2089 if (!strcmp(sub_name, "size_h"))
2090 {
2091 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2092 return EINA_FALSE;
2093 rp->drag->size.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2094 ed->recalc_call = EINA_TRUE;
2095 ed->dirty = EINA_TRUE;
2096 #ifdef EDJE_CALC_CACHE
2097 rp->invalidate = EINA_TRUE;
2098 #endif
2099 _edje_recalc(ed);
2100 return EINA_TRUE;
2101 }
2102
2103 if (!strcmp(sub_name, "step_x"))
2104 {
2105 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2106 return EINA_FALSE;
2107 rp->drag->step.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2108 #ifdef EDJE_CALC_CACHE
2109 rp->invalidate = EINA_TRUE;
2110 #endif
2111 return EINA_TRUE;
2112 }
2113 if (!strcmp(sub_name, "step_y"))
2114 {
2115 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2116 return EINA_FALSE;
2117 rp->drag->step.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2118 #ifdef EDJE_CALC_CACHE
2119 rp->invalidate = EINA_TRUE;
2120 #endif
2121 return EINA_TRUE;
2122 }
2123
2124 if (!strcmp(sub_name, "page_x"))
2125 {
2126 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2127 return EINA_FALSE;
2128 rp->drag->page.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2129 #ifdef EDJE_CALC_CACHE
2130 rp->invalidate = EINA_TRUE;
2131 #endif
2132 return EINA_TRUE;
2133 }
2134 if (!strcmp(sub_name, "page_y"))
2135 {
2136 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2137 return EINA_FALSE;
2138 rp->drag->page.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2139 #ifdef EDJE_CALC_CACHE
2140 rp->invalidate = EINA_TRUE;
2141 #endif
2142 return EINA_TRUE;
2143 }
2144
2145 return EINA_FALSE;
2146 }
2147 }
2148
2149 return EINA_FALSE;
2150 }
2151
2152 static const Edje_External_Param_Info *
_edje_native_param_info_get(const Edje_Real_Part * rp,const char * name)2153 _edje_native_param_info_get(const Edje_Real_Part *rp, const char *name)
2154 {
2155 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
2156 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
2157 {
2158 if (!strcmp(name, "text"))
2159 {
2160 static const Edje_External_Param_Info pi =
2161 EDJE_EXTERNAL_PARAM_INFO_STRING("text");
2162 return π
2163 }
2164 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2165 {
2166 if (!strcmp(name, "text_unescaped"))
2167 {
2168 static const Edje_External_Param_Info pi =
2169 EDJE_EXTERNAL_PARAM_INFO_STRING("text_unescaped");
2170 return π
2171 }
2172 if (!strcmp(name, "select_allow"))
2173 {
2174 static const Edje_External_Param_Info pi =
2175 EDJE_EXTERNAL_PARAM_INFO_BOOL("text_unescaped");
2176 return π
2177 }
2178 }
2179 }
2180
2181 if ((rp->drag) && (rp->drag->down.count == 0))
2182 {
2183 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
2184 {
2185 name += sizeof("drag_") - 1;
2186 if (!strcmp(name, "value_x"))
2187 {
2188 static const Edje_External_Param_Info pi =
2189 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_x");
2190 return π
2191 }
2192 if (!strcmp(name, "value_y"))
2193 {
2194 static const Edje_External_Param_Info pi =
2195 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_y");
2196 return π
2197 }
2198 if (!strcmp(name, "size_w"))
2199 {
2200 static const Edje_External_Param_Info pi =
2201 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_w");
2202 return π
2203 }
2204 if (!strcmp(name, "size_h"))
2205 {
2206 static const Edje_External_Param_Info pi =
2207 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_h");
2208 return π
2209 }
2210 if (!strcmp(name, "step_x"))
2211 {
2212 static const Edje_External_Param_Info pi =
2213 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_x");
2214 return π
2215 }
2216 if (!strcmp(name, "step_y"))
2217 {
2218 static const Edje_External_Param_Info pi =
2219 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_y");
2220 return π
2221 }
2222 if (!strcmp(name, "page_x"))
2223 {
2224 static const Edje_External_Param_Info pi =
2225 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_x");
2226 return π
2227 }
2228 if (!strcmp(name, "page_y"))
2229 {
2230 static const Edje_External_Param_Info pi =
2231 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_y");
2232 return π
2233 }
2234
2235 return NULL;
2236 }
2237 }
2238
2239 return NULL;
2240 }
2241
2242 static Edje_External_Param *
_edje_param_convert(Edje_External_Param * param,const Edje_External_Param_Info * dst_info)2243 _edje_param_convert(Edje_External_Param *param, const Edje_External_Param_Info *dst_info)
2244 {
2245 if (param->type == dst_info->type) return param;
2246
2247 switch (dst_info->type)
2248 {
2249 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2250 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2251 {
2252 int i;
2253 switch (param->type)
2254 {
2255 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2256 i = (int)param->d;
2257 break;
2258
2259 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2260 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2261 i = (param->s) ? atoi(param->s) : 0;
2262 break;
2263
2264 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2265 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2266 i = param->i;
2267 break;
2268
2269 default:
2270 return NULL;
2271 }
2272 if (dst_info->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
2273 i = !!i;
2274 param->type = dst_info->type;
2275 param->i = i;
2276 return param;
2277 }
2278
2279 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2280 {
2281 double d;
2282 switch (param->type)
2283 {
2284 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2285 d = (double)param->i;
2286 break;
2287
2288 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2289 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2290 d = (param->s) ? atof(param->s) : 0.0;
2291 break;
2292
2293 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2294 d = (double)param->i;
2295 break;
2296
2297 default:
2298 return NULL;
2299 }
2300 param->type = dst_info->type;
2301 param->d = d;
2302 return param;
2303 }
2304
2305 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2306 {
2307 static char s[64];
2308 switch (param->type)
2309 {
2310 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2311 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2312 if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
2313 break;
2314
2315 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2316 if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
2317 break;
2318
2319 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2320 param->type = dst_info->type;
2321 return param;
2322
2323 default:
2324 return NULL;
2325 }
2326 param->type = dst_info->type;
2327 param->s = s;
2328 return param;
2329 }
2330
2331 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2332 {
2333 static char s[64];
2334 const char *val;
2335 switch (param->type)
2336 {
2337 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2338 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2339 if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
2340 val = s;
2341 break;
2342
2343 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2344 if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
2345 val = s;
2346 break;
2347
2348 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2349 val = param->s;
2350 break;
2351
2352 default:
2353 return NULL;
2354 }
2355
2356 param->type = dst_info->type;
2357 if (param->s != val) param->s = val;
2358 return param;
2359 }
2360
2361 default: return NULL;
2362 }
2363 }
2364
2365 static Eina_Bool
_edje_param_validate(const Edje_External_Param * param,const Edje_External_Param_Info * info)2366 _edje_param_validate(const Edje_External_Param *param, const Edje_External_Param_Info *info)
2367 {
2368 switch (info->type)
2369 {
2370 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2371 return (param->i == 0) || (param->i == 1);
2372
2373 case EDJE_EXTERNAL_PARAM_TYPE_INT:
2374 if ((info->info.i.min != EDJE_EXTERNAL_INT_UNSET) &&
2375 (info->info.i.min > param->i))
2376 return EINA_FALSE;
2377
2378 if ((info->info.i.max != EDJE_EXTERNAL_INT_UNSET) &&
2379 (info->info.i.max < param->i))
2380 return EINA_FALSE;
2381
2382 return EINA_TRUE;
2383
2384 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2385 if (!EINA_DBL_EQ(info->info.d.min, EDJE_EXTERNAL_DOUBLE_UNSET) &&
2386 (info->info.d.min > param->d))
2387 return EINA_FALSE;
2388
2389 if (!EINA_DBL_EQ(info->info.d.max, EDJE_EXTERNAL_DOUBLE_UNSET) &&
2390 (info->info.d.max < param->d))
2391 return EINA_FALSE;
2392
2393 return EINA_TRUE;
2394
2395 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2396 if (!param->s) return EINA_FALSE;
2397 if (info->info.s.accept_fmt)
2398 INF("string 'accept_fmt' validation not implemented.");
2399 if (info->info.s.deny_fmt)
2400 INF("string 'deny_fmt' validation not implemented.");
2401 return EINA_TRUE;
2402
2403 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2404 {
2405 const char **itr = info->info.c.choices;
2406 if (!itr) return EINA_FALSE;
2407 for (; *itr; itr++)
2408 if (!strcmp(*itr, param->s))
2409 return EINA_TRUE;
2410 return EINA_FALSE;
2411 }
2412
2413 default: return EINA_FALSE;
2414 }
2415 }
2416
2417 static void
_edje_param_copy(Edje * ed,Edje_Real_Part * src_part,const char * src_param,Edje_Real_Part * dst_part,const char * dst_param)2418 _edje_param_copy(Edje *ed, Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param)
2419 {
2420 Edje_External_Param val;
2421 const Edje_External_Param_Info *dst_info;
2422 void *free_ptr = NULL;
2423
2424 if ((!src_part) || (!src_param) || (!dst_part) || (!dst_param))
2425 return;
2426
2427 if ((dst_part->part->type == EDJE_PART_TYPE_EXTERNAL) &&
2428 (dst_part->type == EDJE_RP_TYPE_SWALLOW) &&
2429 (dst_part->typedata.swallow))
2430 dst_info = _edje_external_param_info_get
2431 (dst_part->typedata.swallow->swallowed_object, dst_param);
2432 else
2433 dst_info = _edje_native_param_info_get(dst_part, dst_param);
2434
2435 if (!dst_info)
2436 {
2437 ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2438 dst_param, dst_part->part->name);
2439 return;
2440 }
2441
2442 if (src_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2443 {
2444 if (!_edje_param_external_get
2445 (src_part, src_param, &val))
2446 {
2447 ERR("cannot get parameter '%s' of part '%s'",
2448 src_param, src_part->part->name);
2449 return;
2450 }
2451 }
2452 else
2453 {
2454 if (!_edje_param_native_get(ed, src_part, src_param, &val, &free_ptr))
2455 {
2456 ERR("cannot get parameter '%s' of part '%s'",
2457 src_param, src_part->part->name);
2458 return;
2459 }
2460 }
2461
2462 if (!_edje_param_convert(&val, dst_info))
2463 {
2464 ERR("cannot convert parameter type %s to requested type %s",
2465 edje_external_param_type_str(val.type),
2466 edje_external_param_type_str(dst_info->type));
2467 goto end;
2468 }
2469
2470 if (!_edje_param_validate(&val, dst_info))
2471 {
2472 ERR("incorrect parameter value failed validation for type %s",
2473 edje_external_param_type_str(dst_info->type));
2474 goto end;
2475 }
2476
2477 if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2478 {
2479 val.name = dst_param;
2480 if (!_edje_external_param_set(NULL, dst_part, &val))
2481 {
2482 ERR("failed to set parameter '%s' (%s) of part '%s'",
2483 dst_param, edje_external_param_type_str(dst_info->type),
2484 dst_part->part->name);
2485 goto end;
2486 }
2487 }
2488 else
2489 {
2490 if (!_edje_param_native_set(ed, dst_part, dst_param, &val))
2491 {
2492 ERR("failed to set parameter '%s' (%s) of part '%s'",
2493 dst_param, edje_external_param_type_str(dst_info->type),
2494 dst_part->part->name);
2495 goto end;
2496 }
2497 }
2498
2499 end:
2500 free(free_ptr);
2501 }
2502
2503 static void
_edje_param_set(Edje * ed,Edje_Real_Part * part,const char * param,const char * value)2504 _edje_param_set(Edje *ed, Edje_Real_Part *part, const char *param, const char *value)
2505 {
2506 Edje_External_Param val;
2507 const Edje_External_Param_Info *info;
2508
2509 if ((!part) || (!param) || (!value))
2510 return;
2511
2512 if ((part->part->type == EDJE_PART_TYPE_EXTERNAL) &&
2513 (part->type == EDJE_RP_TYPE_SWALLOW) &&
2514 (part->typedata.swallow))
2515 info = _edje_external_param_info_get(part->typedata.swallow->swallowed_object, param);
2516 else
2517 info = _edje_native_param_info_get(part, param);
2518
2519 if (!info)
2520 {
2521 ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2522 param, part->part->name);
2523 return;
2524 }
2525
2526 val.name = "(temp)";
2527 val.type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
2528 val.s = value;
2529
2530 if (!_edje_param_convert(&val, info))
2531 {
2532 ERR("cannot convert parameter type STRING to requested type %s",
2533 edje_external_param_type_str(info->type));
2534 return;
2535 }
2536
2537 if (!_edje_param_validate(&val, info))
2538 {
2539 ERR("incorrect parameter value failed validation for type %s",
2540 edje_external_param_type_str(info->type));
2541 return;
2542 }
2543
2544 if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2545 {
2546 val.name = param;
2547 if (!_edje_external_param_set(NULL, part, &val))
2548 {
2549 ERR("failed to set parameter '%s' (%s) of part '%s'",
2550 param, edje_external_param_type_str(info->type),
2551 part->part->name);
2552 return;
2553 }
2554 }
2555 else
2556 {
2557 if (!_edje_param_native_set(ed, part, param, &val))
2558 {
2559 ERR("failed to set parameter '%s' (%s) of part '%s'",
2560 param, edje_external_param_type_str(info->type),
2561 part->part->name);
2562 return;
2563 }
2564 }
2565 }
2566
2567