efl

Форк
0
/
edje_program.c 
2565 строк · 80.3 Кб
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
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
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
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 *
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
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
167
_edje_signal_data_ref(Edje_Message_Signal_Data *mdata)
168
{
169
   if (mdata) mdata->ref++;
170
}
171

172
static void
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*
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 *
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
216
edje_frametime_set(double t)
217
{
218
   ecore_animator_frametime_set(t);
219
}
220

221
EAPI double
222
edje_frametime_get(void)
223
{
224
   return ecore_animator_frametime_get();
225
}
226

227
EAPI double
228
edje_transition_duration_factor_get(void)
229
{
230
   return _edje_transition_duration_scale;
231
}
232

233
EAPI void
234
edje_transition_duration_factor_set(double scale)
235
{
236
   _edje_transition_duration_scale = FROM_DOUBLE(scale);
237
}
238

239
Eina_Bool
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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*
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 *
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
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
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 *
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 *
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
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 *
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 *
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 *
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
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 *
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
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 &pi;
2233
               }
2234

2235
             return NULL;
2236
          }
2237
     }
2238

2239
   return NULL;
2240
}
2241

2242
static Edje_External_Param *
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
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
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
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.