summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2015-05-06 14:25:15 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-05-06 14:25:15 +0200
commitfdb7147872f9f6f97c7ea2a179be3d92e0c6cb99 (patch)
tree0dd69818062e9dfbbaf6997b1d3c2fe5fd3f5d60
parentcbba58bf0e24fb731fc139c08debb892bcf6186b (diff)
naviframe: fix poping top item continuously to empty the naviframe stack.
This should be a proper fix for T1717. Idea is that we build a list of operation that needs to be deferred in order (including pop and push) so that we are sure we can pop and push in any order without the need to wait for any event.
-rw-r--r--src/lib/elc_naviframe.c111
-rw-r--r--src/lib/elm_widget_naviframe.h12
2 files changed, 75 insertions, 48 deletions
diff --git a/src/lib/elc_naviframe.c b/src/lib/elc_naviframe.c
index b14d20333..9cee5bc96 100644
--- a/src/lib/elc_naviframe.c
+++ b/src/lib/elc_naviframe.c
@@ -530,6 +530,8 @@ _elm_naviframe_item_elm_widget_item_part_text_get(Eo *nit EINA_UNUSED,
530EOLIAN static void 530EOLIAN static void
531_elm_naviframe_item_eo_base_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it) 531_elm_naviframe_item_eo_base_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
532{ 532{
533 Eina_List *l;
534 Elm_Naviframe_Op *nfo;
533 Elm_Naviframe_Item_Data *nit = it, *prev_it = NULL; 535 Elm_Naviframe_Item_Data *nit = it, *prev_it = NULL;
534 Eina_Bool top; 536 Eina_Bool top;
535 537
@@ -537,8 +539,6 @@ _elm_naviframe_item_eo_base_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
537 539
538 nit->delete_me = EINA_TRUE; 540 nit->delete_me = EINA_TRUE;
539 541
540 ecore_animator_del(nit->animator);
541
542 top = (eo_item == elm_naviframe_top_item_get(WIDGET(nit))); 542 top = (eo_item == elm_naviframe_top_item_get(WIDGET(nit)));
543 if (evas_object_data_get(VIEW(nit), "out_of_list")) 543 if (evas_object_data_get(VIEW(nit), "out_of_list"))
544 goto end; 544 goto end;
@@ -566,6 +566,14 @@ _elm_naviframe_item_eo_base_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
566 } 566 }
567 567
568end: 568end:
569 // This should not happen, but just in case and by security
570 // make sure there is no more reference to this item.
571 EINA_LIST_FOREACH(sd->ops, l, nfo)
572 {
573 if (nfo->related == nit) nfo->related = NULL;
574 if (nfo->self == nit) nfo->self = NULL;
575 }
576
569 _item_free(nit); 577 _item_free(nit);
570 578
571 eo_do_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS, eo_destructor()); 579 eo_do_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS, eo_destructor());
@@ -1366,26 +1374,42 @@ _elm_naviframe_evas_object_smart_add(Eo *obj, Elm_Naviframe_Data *priv)
1366 elm_widget_can_focus_set(obj, EINA_TRUE); 1374 elm_widget_can_focus_set(obj, EINA_TRUE);
1367} 1375}
1368 1376
1369static Eina_Bool 1377static void
1370_pop_transition_cb(void *data) 1378_send_signal(Elm_Naviframe_Item_Data *it, const char *signal)
1371{ 1379{
1372 Elm_Object_Item *eo_prev_it; 1380 if (!it) return ;
1373 Elm_Naviframe_Item_Data *it; 1381 elm_object_signal_emit(VIEW(it), signal, "elm");
1374 it = (Elm_Naviframe_Item_Data *)data; 1382 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1383}
1375 1384
1376 it->animator = NULL; 1385static Eina_Bool
1386_deferred(void *data)
1387{
1388 Elm_Naviframe_Data *nfd = data;
1389 Elm_Naviframe_Op *nfo;
1390 Elm_Naviframe_Item_Data *last = NULL;
1377 1391
1378 eo_prev_it = elm_naviframe_top_item_get(WIDGET(it)); 1392 EINA_LIST_FREE(nfd->ops, nfo)
1379 if (eo_prev_it)
1380 { 1393 {
1381 ELM_NAVIFRAME_ITEM_DATA_GET(eo_prev_it, prev_it); 1394 const char *signals_cur[] = {
1382 elm_object_signal_emit(VIEW(prev_it), "elm,state,prev,popped,deferred", 1395 "elm,state,cur,popped,deferred",
1383 "elm"); 1396 "elm,state,cur,pushed,deferred"
1384 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it))); 1397 };
1398 const char *signals_prev = "elm,state,prev,popped,deferred";
1399 const char *signals_new = "elm,state,new,pushed,deferred";
1400 Elm_Naviframe_Item_Data *cur;
1401 Elm_Naviframe_Item_Data *other;
1402
1403 cur = nfo->push ? nfo->related : nfo->self;
1404 other = nfo->push ? nfo->self : nfo->related;
1405
1406 _send_signal(cur, signals_cur[nfo->push]);
1407 _send_signal(other, nfo->push ? signals_new : signals_prev);
1408
1409 free(nfo);
1385 } 1410 }
1386 elm_object_signal_emit(VIEW(it), "elm,state,cur,popped,deferred", "elm");
1387 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1388 1411
1412 nfd->animator = NULL;
1389 return ECORE_CALLBACK_CANCEL; 1413 return ECORE_CALLBACK_CANCEL;
1390} 1414}
1391 1415
@@ -1393,6 +1417,7 @@ EOLIAN static void
1393_elm_naviframe_evas_object_smart_del(Eo *obj, Elm_Naviframe_Data *sd) 1417_elm_naviframe_evas_object_smart_del(Eo *obj, Elm_Naviframe_Data *sd)
1394{ 1418{
1395 Elm_Naviframe_Item_Data *it; 1419 Elm_Naviframe_Item_Data *it;
1420 Elm_Naviframe_Op *nfo;
1396 1421
1397 sd->on_deletion = EINA_TRUE; 1422 sd->on_deletion = EINA_TRUE;
1398 1423
@@ -1403,11 +1428,11 @@ _elm_naviframe_evas_object_smart_del(Eo *obj, Elm_Naviframe_Data *sd)
1403 } 1428 }
1404 1429
1405 //All popping items which are not called yet by animator. 1430 //All popping items which are not called yet by animator.
1431 if (sd->animator) ecore_animator_del(sd->animator);
1432 EINA_LIST_FREE(sd->ops, nfo)
1433 free(nfo);
1406 EINA_LIST_FREE(sd->popping, it) 1434 EINA_LIST_FREE(sd->popping, it)
1407 { 1435 eo_do(EO_OBJ(it), elm_wdg_item_del());
1408 ecore_animator_del(it->animator);
1409 eo_do(EO_OBJ(it), elm_wdg_item_del());
1410 }
1411 1436
1412 evas_object_del(sd->dummy_edje); 1437 evas_object_del(sd->dummy_edje);
1413 1438
@@ -1466,27 +1491,6 @@ _elm_naviframe_elm_widget_access(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Ei
1466 _access_obj_process(it, is_access); 1491 _access_obj_process(it, is_access);
1467} 1492}
1468 1493
1469static Eina_Bool
1470_push_transition_cb(void *data)
1471{
1472 Elm_Naviframe_Item_Data *prev_it, *it = data;
1473
1474 it->animator = NULL;
1475
1476 if (EINA_INLIST_GET(it)->prev)
1477 {
1478 prev_it = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(it)->prev,
1479 Elm_Naviframe_Item_Data);
1480 elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed,deferred",
1481 "elm");
1482 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1483 }
1484 elm_object_signal_emit(VIEW(it), "elm,state,new,pushed,deferred", "elm");
1485 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1486
1487 return ECORE_CALLBACK_CANCEL;
1488}
1489
1490static void 1494static void
1491_item_push_helper(Elm_Naviframe_Item_Data *item) 1495_item_push_helper(Elm_Naviframe_Item_Data *item)
1492{ 1496{
@@ -1501,6 +1505,8 @@ _item_push_helper(Elm_Naviframe_Item_Data *item)
1501 _resize_object_reset(obj, item); 1505 _resize_object_reset(obj, item);
1502 if (top_item) 1506 if (top_item)
1503 { 1507 {
1508 Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1509
1504 elm_widget_tree_unfocusable_set(VIEW(item), EINA_FALSE); 1510 elm_widget_tree_unfocusable_set(VIEW(item), EINA_FALSE);
1505 elm_widget_tree_unfocusable_set(VIEW(top_item), EINA_TRUE); 1511 elm_widget_tree_unfocusable_set(VIEW(top_item), EINA_TRUE);
1506 1512
@@ -1514,8 +1520,12 @@ _item_push_helper(Elm_Naviframe_Item_Data *item)
1514 edje_object_message_signal_process(elm_layout_edje_get(VIEW(top_item))); 1520 edje_object_message_signal_process(elm_layout_edje_get(VIEW(top_item)));
1515 edje_object_message_signal_process(elm_layout_edje_get(VIEW(item))); 1521 edje_object_message_signal_process(elm_layout_edje_get(VIEW(item)));
1516 1522
1517 ecore_animator_del(item->animator); 1523 nfo->self = item;
1518 item->animator = ecore_animator_add(_push_transition_cb, item); 1524 nfo->related = top_item;
1525 nfo->push = EINA_TRUE;
1526
1527 sd->ops = eina_list_append(sd->ops, nfo);
1528 if (!sd->animator) sd->animator = ecore_animator_add(_deferred, sd);
1519 } 1529 }
1520 else 1530 else
1521 { 1531 {
@@ -1653,8 +1663,6 @@ _elm_naviframe_item_pop(Eo *obj, Elm_Naviframe_Data *sd)
1653 Elm_Naviframe_Item_Data *prev_it = NULL; 1663 Elm_Naviframe_Item_Data *prev_it = NULL;
1654 Evas_Object *content = NULL; 1664 Evas_Object *content = NULL;
1655 1665
1656 if (sd->freeze_events && sd->popping) return NULL;
1657
1658 eo_item = elm_naviframe_top_item_get(obj); 1666 eo_item = elm_naviframe_top_item_get(obj);
1659 if (!eo_item) return NULL; 1667 if (!eo_item) return NULL;
1660 1668
@@ -1694,6 +1702,8 @@ _elm_naviframe_item_pop(Eo *obj, Elm_Naviframe_Data *sd)
1694 1702
1695 if (prev_it) 1703 if (prev_it)
1696 { 1704 {
1705 Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1706
1697 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE); 1707 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1698 elm_widget_tree_unfocusable_set(VIEW(prev_it), EINA_FALSE); 1708 elm_widget_tree_unfocusable_set(VIEW(prev_it), EINA_FALSE);
1699 1709
@@ -1713,13 +1723,20 @@ _elm_naviframe_item_pop(Eo *obj, Elm_Naviframe_Data *sd)
1713 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it))); 1723 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1714 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it))); 1724 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1715 1725
1716 ecore_animator_del(it->animator); 1726 if (!nfo) goto on_error;
1717 it->animator = ecore_animator_add(_pop_transition_cb, it); 1727
1728 nfo->self = it;
1729 nfo->related = prev_it;
1730 nfo->push = EINA_FALSE;
1731
1718 sd->popping = eina_list_append(sd->popping, it); 1732 sd->popping = eina_list_append(sd->popping, it);
1733 sd->ops = eina_list_append(sd->ops, nfo);
1734 if (!sd->animator) sd->animator = ecore_animator_add(_deferred, sd);
1719 } 1735 }
1720 else 1736 else
1721 eo_do(eo_item, elm_wdg_item_del()); 1737 eo_do(eo_item, elm_wdg_item_del());
1722 1738
1739 on_error:
1723 return content; 1740 return content;
1724} 1741}
1725 1742
diff --git a/src/lib/elm_widget_naviframe.h b/src/lib/elm_widget_naviframe.h
index 684d14863..8b2e49b87 100644
--- a/src/lib/elm_widget_naviframe.h
+++ b/src/lib/elm_widget_naviframe.h
@@ -28,7 +28,9 @@ struct _Elm_Naviframe_Data
28{ 28{
29 Eina_Inlist *stack; /* top item is the list's LAST item */ 29 Eina_Inlist *stack; /* top item is the list's LAST item */
30 Eina_List *popping; 30 Eina_List *popping;
31 Eina_List *ops;
31 Evas_Object *dummy_edje; 32 Evas_Object *dummy_edje;
33 Ecore_Animator *animator;
32 Evas_Display_Mode dispmode; 34 Evas_Display_Mode dispmode;
33 35
34 Eina_Bool preserve : 1; 36 Eina_Bool preserve : 1;
@@ -49,7 +51,6 @@ struct _Elm_Naviframe_Item_Data
49 Evas_Object *title_prev_btn; 51 Evas_Object *title_prev_btn;
50 Evas_Object *title_next_btn; 52 Evas_Object *title_next_btn;
51 Evas_Object *title_icon; 53 Evas_Object *title_icon;
52 Ecore_Animator *animator;
53 Evas_Display_Mode dispmode; 54 Evas_Display_Mode dispmode;
54 Elm_Naviframe_Item_Pop_Cb pop_cb; 55 Elm_Naviframe_Item_Pop_Cb pop_cb;
55 void *pop_data; 56 void *pop_data;
@@ -65,6 +66,15 @@ struct _Elm_Naviframe_Item_Data
65 Eina_Bool delete_me : 1; /**< a flag to notify the item is on deletion. this flag is set true at the start of item deletion. */ 66 Eina_Bool delete_me : 1; /**< a flag to notify the item is on deletion. this flag is set true at the start of item deletion. */
66}; 67};
67 68
69typedef struct _Elm_Naviframe_Op Elm_Naviframe_Op;
70struct _Elm_Naviframe_Op
71{
72 Elm_Naviframe_Item_Data *self;
73 Elm_Naviframe_Item_Data *related;
74
75 Eina_Bool push : 1;
76};
77
68typedef struct _Elm_Naviframe_Content_Item_Pair Elm_Naviframe_Content_Item_Pair; 78typedef struct _Elm_Naviframe_Content_Item_Pair Elm_Naviframe_Content_Item_Pair;
69struct _Elm_Naviframe_Content_Item_Pair 79struct _Elm_Naviframe_Content_Item_Pair
70{ 80{