1 #include "edje_private.h"
3 static void _edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop);
6 static Ecore_Job *_job = NULL;
7 static Ecore_Timer *_job_loss_timer = NULL;
9 static Eina_List *msgq = NULL;
10 static Eina_List *tmp_msgq = NULL;
11 static int tmp_msgq_processing = 0;
12 static int tmp_msgq_restart = 0;
14 /*============================================================================*
16 *============================================================================*/
19 _edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop)
25 ed = _edje_fetch(obj);
27 _edje_message_propornot_send(ed, EDJE_QUEUE_SCRIPT, type, id, msg, prop);
28 EINA_LIST_FOREACH(ed->subobjs, l, o)
30 _edje_object_message_popornot_send(o, type, id, msg, EINA_TRUE);
35 edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg)
37 _edje_object_message_popornot_send(obj, type, id, msg, EINA_FALSE);
42 edje_object_message_handler_set(Evas_Object *obj, Edje_Message_Handler_Cb func, void *data)
46 ed = _edje_fetch(obj);
48 _edje_message_cb_set(ed, func, data);
52 edje_object_message_signal_process(Evas_Object *obj)
54 Eina_List *l, *ln, *tmpq = NULL;
59 Eina_List *groups = NULL;
62 ed = _edje_fetch(obj);
67 EINA_LIST_FOREACH_SAFE(msgq, l, ln, em)
69 EINA_LIST_FOREACH(groups, lg, lookup_ed)
70 if (em->edje == lookup_ed)
72 tmpq = eina_list_append(tmpq, em);
73 msgq = eina_list_remove_list(msgq, l);
77 /* a temporary message queue */
80 EINA_LIST_FREE(tmpq, em)
81 tmp_msgq = eina_list_append(tmp_msgq, em);
89 tmp_msgq_processing++;
91 EINA_LIST_FOREACH_SAFE(tmp_msgq, l, ln, em)
93 EINA_LIST_FOREACH(groups, lg, lookup_ed)
94 if (em->edje == lookup_ed)
96 if (em->edje != lookup_ed) continue;
97 tmp_msgq = eina_list_remove_list(tmp_msgq, l);
98 if (!lookup_ed->delete_me)
100 lookup_ed->processing_messages++;
101 _edje_message_process(em);
102 _edje_message_free(em);
103 lookup_ed->processing_messages--;
106 _edje_message_free(em);
107 if (lookup_ed->processing_messages == 0)
109 if (lookup_ed->delete_me) _edje_del(lookup_ed);
111 // if some child callback in _edje_message_process called
112 // edje_object_message_signal_process() or
113 // edje_message_signal_process() then those will mark the restart
114 // flag when they finish - it mabsicammyt means tmp_msgq and
115 // any item in it has potentially become invalid - so that means l
116 // and ln could be rogue pointers, so start again from the beginning
117 // and skip anything that is not this object and process only what is.
118 // to avoid self-feeding loops allow a max of 1024 loops.
119 if (tmp_msgq_restart)
121 tmp_msgq_restart = 0;
123 if (gotos < 1024) goto again;
126 WRN("Edje is in a self-feeding message loop (> 1024 gotos needed in a row)");
132 tmp_msgq_processing--;
133 if (tmp_msgq_processing == 0)
134 tmp_msgq_restart = 0;
136 tmp_msgq_restart = 1;
140 edje_message_signal_process(void)
142 _edje_message_queue_process();
147 _edje_dummy_timer(void *data __UNUSED__)
149 return ECORE_CALLBACK_CANCEL;
153 _edje_job(void *data __UNUSED__)
157 ecore_timer_del(_job_loss_timer);
158 _job_loss_timer = NULL;
162 _edje_message_queue_process();
167 _edje_job_loss_timer(void *data __UNUSED__)
169 _job_loss_timer = NULL;
172 _job = ecore_job_add(_edje_job, NULL);
174 return ECORE_CALLBACK_CANCEL;
178 _edje_message_init(void)
183 _edje_message_shutdown(void)
185 _edje_message_queue_clear();
188 ecore_timer_del(_job_loss_timer);
189 _job_loss_timer = NULL;
199 _edje_message_cb_set(Edje *ed, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data)
204 ed->message.func = func;
205 ed->message.data = data;
206 EINA_LIST_FOREACH(ed->subobjs, l, o)
208 Edje *edj2 = _edje_fetch(o);
210 _edje_message_cb_set(edj2, func, data);
215 _edje_message_new(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id)
219 em = calloc(1, sizeof(Edje_Message));
220 if (!em) return NULL;
225 em->edje->message.num++;
230 _edje_message_free(Edje_Message *em)
238 case EDJE_MESSAGE_STRING:
240 Edje_Message_String *emsg;
242 emsg = (Edje_Message_String *)em->msg;
247 case EDJE_MESSAGE_INT:
249 Edje_Message_Int *emsg;
251 emsg = (Edje_Message_Int *)em->msg;
255 case EDJE_MESSAGE_FLOAT:
257 Edje_Message_Float *emsg;
259 emsg = (Edje_Message_Float *)em->msg;
263 case EDJE_MESSAGE_INT_SET:
265 Edje_Message_Int_Set *emsg;
267 emsg = (Edje_Message_Int_Set *)em->msg;
271 case EDJE_MESSAGE_FLOAT_SET:
273 Edje_Message_Float_Set *emsg;
275 emsg = (Edje_Message_Float_Set *)em->msg;
279 case EDJE_MESSAGE_STRING_FLOAT:
281 Edje_Message_String_Float *emsg;
283 emsg = (Edje_Message_String_Float *)em->msg;
288 case EDJE_MESSAGE_STRING_INT:
290 Edje_Message_String_Int *emsg;
292 emsg = (Edje_Message_String_Int *)em->msg;
297 case EDJE_MESSAGE_STRING_FLOAT_SET:
299 Edje_Message_String_Float_Set *emsg;
301 emsg = (Edje_Message_String_Float_Set *)em->msg;
306 case EDJE_MESSAGE_STRING_INT_SET:
308 Edje_Message_String_Int_Set *emsg;
310 emsg = (Edje_Message_String_Int_Set *)em->msg;
315 case EDJE_MESSAGE_SIGNAL:
317 Edje_Message_Signal *emsg;
319 emsg = (Edje_Message_Signal *)em->msg;
320 if (emsg->sig) eina_stringshare_del(emsg->sig);
321 if (emsg->src) eina_stringshare_del(emsg->src);
322 if (emsg->data && (--(emsg->data->ref) == 0))
324 if (emsg->data->free_func)
326 emsg->data->free_func(emsg->data->data);
333 case EDJE_MESSAGE_STRING_SET:
335 Edje_Message_String_Set *emsg;
337 emsg = (Edje_Message_String_Set *)em->msg;
338 for (i = 0; i < emsg->count; i++)
343 case EDJE_MESSAGE_NONE:
352 _edje_message_propornot_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg, Eina_Bool prop)
354 /* FIXME: check all malloc & strdup fails and gracefully unroll and exit */
357 unsigned char *msg = NULL;
359 em = _edje_message_new(ed, queue, type, id);
361 em->propagated = prop;
369 if (!_job_loss_timer)
370 _job_loss_timer = ecore_timer_add(0.001, _edje_job_loss_timer, NULL);
376 _job = ecore_job_add(_edje_job, NULL);
380 ecore_timer_del(_job_loss_timer);
381 _job_loss_timer = NULL;
386 case EDJE_MESSAGE_NONE:
388 case EDJE_MESSAGE_SIGNAL:
390 Edje_Message_Signal *emsg2, *emsg3;
392 emsg2 = (Edje_Message_Signal *)emsg;
393 emsg3 = calloc(1, sizeof(Edje_Message_Signal));
394 if (emsg2->sig) emsg3->sig = eina_stringshare_add(emsg2->sig);
395 if (emsg2->src) emsg3->src = eina_stringshare_add(emsg2->src);
398 emsg3->data = emsg2->data;
401 msg = (unsigned char *)emsg3;
404 case EDJE_MESSAGE_STRING:
406 Edje_Message_String *emsg2, *emsg3;
408 emsg2 = (Edje_Message_String *)emsg;
410 emsg3 = malloc(sizeof(Edje_Message_String));
411 emsg3->str = strdup(emsg2->str);
412 msg = (unsigned char *)emsg3;
415 case EDJE_MESSAGE_INT:
417 Edje_Message_Int *emsg2, *emsg3;
419 emsg2 = (Edje_Message_Int *)emsg;
420 emsg3 = malloc(sizeof(Edje_Message_Int));
421 emsg3->val = emsg2->val;
422 msg = (unsigned char *)emsg3;
425 case EDJE_MESSAGE_FLOAT:
427 Edje_Message_Float *emsg2, *emsg3;
429 emsg2 = (Edje_Message_Float *)emsg;
430 emsg3 = malloc(sizeof(Edje_Message_Float));
431 emsg3->val = emsg2->val;
432 msg = (unsigned char *)emsg3;
435 case EDJE_MESSAGE_STRING_SET:
437 Edje_Message_String_Set *emsg2, *emsg3;
439 emsg2 = (Edje_Message_String_Set *)emsg;
440 emsg3 = malloc(sizeof(Edje_Message_String_Set) + ((emsg2->count - 1) * sizeof(char *)));
441 emsg3->count = emsg2->count;
442 for (i = 0; i < emsg3->count; i++)
443 emsg3->str[i] = strdup(emsg2->str[i]);
444 msg = (unsigned char *)emsg3;
447 case EDJE_MESSAGE_INT_SET:
449 Edje_Message_Int_Set *emsg2, *emsg3;
451 emsg2 = (Edje_Message_Int_Set *)emsg;
452 emsg3 = malloc(sizeof(Edje_Message_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
453 emsg3->count = emsg2->count;
454 for (i = 0; i < emsg3->count; i++)
455 emsg3->val[i] = emsg2->val[i];
456 msg = (unsigned char *)emsg3;
459 case EDJE_MESSAGE_FLOAT_SET:
461 Edje_Message_Float_Set *emsg2, *emsg3;
463 emsg2 = (Edje_Message_Float_Set *)emsg;
464 emsg3 = malloc(sizeof(Edje_Message_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
465 emsg3->count = emsg2->count;
466 for (i = 0; i < emsg3->count; i++)
467 emsg3->val[i] = emsg2->val[i];
468 msg = (unsigned char *)emsg3;
471 case EDJE_MESSAGE_STRING_INT:
473 Edje_Message_String_Int *emsg2, *emsg3;
475 emsg2 = (Edje_Message_String_Int *)emsg;
476 emsg3 = malloc(sizeof(Edje_Message_String_Int));
477 emsg3->str = strdup(emsg2->str);
478 emsg3->val = emsg2->val;
479 msg = (unsigned char *)emsg3;
482 case EDJE_MESSAGE_STRING_FLOAT:
484 Edje_Message_String_Float *emsg2, *emsg3;
486 emsg2 = (Edje_Message_String_Float *)emsg;
487 emsg3 = malloc(sizeof(Edje_Message_String_Float));
488 emsg3->str = strdup(emsg2->str);
489 emsg3->val = emsg2->val;
490 msg = (unsigned char *)emsg3;
493 case EDJE_MESSAGE_STRING_INT_SET:
495 Edje_Message_String_Int_Set *emsg2, *emsg3;
497 emsg2 = (Edje_Message_String_Int_Set *)emsg;
498 emsg3 = malloc(sizeof(Edje_Message_String_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
499 emsg3->str = strdup(emsg2->str);
500 emsg3->count = emsg2->count;
501 for (i = 0; i < emsg3->count; i++)
502 emsg3->val[i] = emsg2->val[i];
503 msg = (unsigned char *)emsg3;
506 case EDJE_MESSAGE_STRING_FLOAT_SET:
508 Edje_Message_String_Float_Set *emsg2, *emsg3;
510 emsg2 = (Edje_Message_String_Float_Set *)emsg;
511 emsg3 = malloc(sizeof(Edje_Message_String_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
512 emsg3->str = strdup(emsg2->str);
513 emsg3->count = emsg2->count;
514 for (i = 0; i < emsg3->count; i++)
515 emsg3->val[i] = emsg2->val[i];
516 msg = (unsigned char *)emsg3;
524 msgq = eina_list_append(msgq, em);
528 _edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg)
530 _edje_message_propornot_send(ed, queue, type, id, emsg, EINA_FALSE);
534 _edje_message_parameters_push(Edje_Message *em)
538 /* these params ALWAYS go on */
539 /* first param is the message type - always */
540 embryo_parameter_cell_push(em->edje->collection->script,
541 (Embryo_Cell)em->type);
542 /* 2nd param is the integer of the event id - always there */
543 embryo_parameter_cell_push(em->edje->collection->script,
544 (Embryo_Cell)em->id);
545 /* the rest is varags of whatever is in the msg */
548 case EDJE_MESSAGE_NONE:
550 case EDJE_MESSAGE_STRING:
551 embryo_parameter_string_push(em->edje->collection->script,
552 ((Edje_Message_String *)em->msg)->str);
554 case EDJE_MESSAGE_INT:
558 v = (Embryo_Cell)((Edje_Message_Int *)em->msg)->val;
559 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
562 case EDJE_MESSAGE_FLOAT:
567 fv = ((Edje_Message_Float *)em->msg)->val;
568 v = EMBRYO_FLOAT_TO_CELL(fv);
569 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
572 case EDJE_MESSAGE_STRING_SET:
573 for (i = 0; i < ((Edje_Message_String_Set *)em->msg)->count; i++)
574 embryo_parameter_string_push(em->edje->collection->script,
575 ((Edje_Message_String_Set *)em->msg)->str[i]);
577 case EDJE_MESSAGE_INT_SET:
578 for (i = 0; i < ((Edje_Message_Int_Set *)em->msg)->count; i++)
582 v = (Embryo_Cell)((Edje_Message_Int_Set *)em->msg)->val[i];
583 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
586 case EDJE_MESSAGE_FLOAT_SET:
587 for (i = 0; i < ((Edje_Message_Float_Set *)em->msg)->count; i++)
592 fv = ((Edje_Message_Float_Set *)em->msg)->val[i];
593 v = EMBRYO_FLOAT_TO_CELL(fv);
594 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
597 case EDJE_MESSAGE_STRING_INT:
598 embryo_parameter_string_push(em->edje->collection->script,
599 ((Edje_Message_String_Int *)em->msg)->str);
603 v = (Embryo_Cell)((Edje_Message_String_Int *)em->msg)->val;
604 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
607 case EDJE_MESSAGE_STRING_FLOAT:
608 embryo_parameter_string_push(em->edje->collection->script,
609 ((Edje_Message_String_Float *)em->msg)->str);
614 fv = ((Edje_Message_String_Float *)em->msg)->val;
615 v = EMBRYO_FLOAT_TO_CELL(fv);
616 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
619 case EDJE_MESSAGE_STRING_INT_SET:
620 embryo_parameter_string_push(em->edje->collection->script,
621 ((Edje_Message_String_Int_Set *)em->msg)->str);
622 for (i = 0; i < ((Edje_Message_String_Int_Set *)em->msg)->count; i++)
626 v = (Embryo_Cell)((Edje_Message_String_Int_Set *)em->msg)->val[i];
627 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
630 case EDJE_MESSAGE_STRING_FLOAT_SET:
631 embryo_parameter_string_push(em->edje->collection->script,
632 ((Edje_Message_String_Float_Set *)em->msg)->str);
633 for (i = 0; i < ((Edje_Message_String_Float_Set *)em->msg)->count; i++)
638 fv = ((Edje_Message_String_Float_Set *)em->msg)->val[i];
639 v = EMBRYO_FLOAT_TO_CELL(fv);
640 embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
649 _edje_message_process(Edje_Message *em)
655 /* signals are only handled one way */
656 if (em->type == EDJE_MESSAGE_SIGNAL)
658 _edje_emit_handle(em->edje,
659 ((Edje_Message_Signal *)em->msg)->sig,
660 ((Edje_Message_Signal *)em->msg)->src,
661 ((Edje_Message_Signal *)em->msg)->data,
665 /* if this has been queued up for the app then just call the callback */
666 if (em->queue == EDJE_QUEUE_APP)
668 if (em->edje->message.func)
669 em->edje->message.func(em->edje->message.data, em->edje->obj,
670 em->type, em->id, em->msg);
673 /* now this message is destined for the script message handler fn */
674 if (!(em->edje->collection)) return;
675 if ((em->edje->collection->script) && _edje_script_only (em->edje))
677 _edje_script_only_message(em->edje, em);
682 _edje_lua_script_only_message(em->edje, em);
685 fn = embryo_program_function_find(em->edje->collection->script, "message");
686 if (fn == EMBRYO_FUNCTION_NONE) return;
687 /* reset the engine */
688 _edje_embryo_script_reset(em->edje);
690 _edje_message_parameters_push(em);
692 embryo_program_vm_push(em->edje->collection->script);
693 _edje_embryo_globals_init(em->edje);
694 pdata = embryo_program_data_get(em->edje->collection->script);
695 embryo_program_data_set(em->edje->collection->script, em->edje);
696 embryo_program_max_cycle_run_set(em->edje->collection->script, 5000000);
697 ret = embryo_program_run(em->edje->collection->script, fn);
698 if (ret == EMBRYO_PROGRAM_FAIL)
700 ERR("ERROR with embryo script. "
701 "OBJECT NAME: '%s', "
702 "OBJECT FILE: '%s', "
703 "ENTRY POINT: '%s', "
705 em->edje->collection->part,
706 em->edje->file->path,
708 embryo_error_string_get(embryo_program_error_get(em->edje->collection->script)));
710 else if (ret == EMBRYO_PROGRAM_TOOLONG)
712 ERR("ERROR with embryo script. "
713 "OBJECT NAME: '%s', "
714 "OBJECT FILE: '%s', "
715 "ENTRY POINT: '%s', "
716 "ERROR: 'Script exceeded maximum allowed cycle count of %i'",
717 em->edje->collection->part,
718 em->edje->file->path,
720 embryo_program_max_cycle_run_get(em->edje->collection->script));
723 embryo_program_data_set(em->edje->collection->script, pdata);
724 embryo_program_vm_pop(em->edje->collection->script);
728 _edje_message_queue_process(void)
734 /* allow the message queue to feed itself up to 8 times before forcing */
735 /* us to go back to normal processing and let a 0 timeout deal with it */
736 for (i = 0; (i < 8) && (msgq); i++)
738 /* a temporary message queue */
743 tmp_msgq = eina_list_append(tmp_msgq, msgq->data);
744 msgq = eina_list_remove_list(msgq, msgq);
753 tmp_msgq_processing++;
761 tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq);
762 em->edje->message.num--;
765 ed->processing_messages++;
766 _edje_message_process(em);
767 _edje_message_free(em);
768 ed->processing_messages--;
771 _edje_message_free(em);
772 if (ed->processing_messages == 0)
774 if (ed->delete_me) _edje_del(ed);
777 tmp_msgq_processing--;
778 if (tmp_msgq_processing == 0)
779 tmp_msgq_restart = 0;
781 tmp_msgq_restart = 1;
784 /* if the message queue filled again set a timer to expire in 0.0 sec */
785 /* to get the idle enterer to be run again */
788 static int self_feed_debug = -1;
790 if (self_feed_debug == -1)
792 const char *s = getenv("EDJE_SELF_FEED_DEBUG");
793 if (s) self_feed_debug = atoi(s);
794 else self_feed_debug = 0;
798 WRN("Edje is in a self-feeding message loop (> 8 loops needed)");
800 ecore_timer_add(0.0, _edje_dummy_timer, NULL);
805 _edje_message_queue_clear(void)
812 msgq = eina_list_remove_list(msgq, msgq);
813 em->edje->message.num--;
814 _edje_message_free(em);
821 tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq);
822 em->edje->message.num--;
823 _edje_message_free(em);
828 _edje_message_del(Edje *ed)
832 if (ed->message.num <= 0) return;
833 /* delete any messages on the main queue for this edje object */
839 em = eina_list_data_get(l);
841 l = eina_list_next(l);
844 msgq = eina_list_remove_list(msgq, lp);
845 em->edje->message.num--;
846 _edje_message_free(em);
848 if (ed->message.num <= 0) return;
850 /* delete any on the processing queue */
851 for (l = tmp_msgq; l; )
856 em = eina_list_data_get(l);
858 l = eina_list_next(l);
861 tmp_msgq = eina_list_remove_list(tmp_msgq, lp);
862 em->edje->message.num--;
863 _edje_message_free(em);
865 if (ed->message.num <= 0) return;