raster pushed a commit to branch master. http://git.enlightenment.org/core/elementary.git/commit/?id=aedef31eddf38567e27abcb4f753cf803c4f7b47
commit aedef31eddf38567e27abcb4f753cf803c4f7b47 Author: Bogdan Devichev <b.devic...@samsung.com> Date: Wed Apr 9 19:04:55 2014 +0900 elementary: when modal win appears another wins are blocked Summary: In win.edc add blocker for its content and programs for it. Add Eina_Bool blocked and was_enabled to _Elm_Menu_Item for correctly blocking and unblocking of main_menu. They used for saving state which was before modal win was apeared. Add callbacks and private functions in menu.c for blocking and unblocking menu. Add integer modal_count to Elm_Win_Smart_Data for creating enum of modal wins. Add changes in win.c for blocking content, in_focus callback and menu while modal win is exist. Reviewers: cedric, seoz, raster Reviewed By: raster CC: reutskiy.v.v, raster Differential Revision: https://phab.enlightenment.org/D607 --- data/themes/edc/elm/win.edc | 24 +++++++++++++ src/lib/elm_menu.c | 31 +++++++++++++++++ src/lib/elm_widget_menu.h | 2 ++ src/lib/elm_win.c | 83 +++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 138 insertions(+), 2 deletions(-) diff --git a/data/themes/edc/elm/win.edc b/data/themes/edc/elm/win.edc index 56af51f..343de6c 100644 --- a/data/themes/edc/elm/win.edc +++ b/data/themes/edc/elm/win.edc @@ -28,6 +28,18 @@ group { name: "elm/win/base/default"; } } } + part { name: "blocker"; type: RECT; + description { state: "default" 0.0; + rel1.relative : 0.0 0.0; + rel2.relative : 1.0 1.0; + color: 64 64 64 150; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } } programs { program { name: "show_menu"; @@ -42,5 +54,17 @@ group { name: "elm/win/base/default"; action: STATE_SET "default" 0.0; target: "elm.swallow.menu"; } + program { name: "hide_blocker"; + signal: "elm,action,hide_blocker"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "blocker"; + } + program { name: "show_blocker"; + signal: "elm,action,show_blocker"; + source: "elm"; + action: STATE_SET "visible" 0.0; + target: "blocker"; + } } } diff --git a/src/lib/elm_menu.c b/src/lib/elm_menu.c index d13f442..5e8a356 100644 --- a/src/lib/elm_menu.c +++ b/src/lib/elm_menu.c @@ -492,6 +492,33 @@ _menu_item_inactivate_cb(void *data, if (item->submenu.open) _submenu_hide(item); } +static void +_block_menu(Elm_Menu_Data * sd, Evas_Object *obj EINA_UNUSED, ...) +{ + const Eina_List *l; + Elm_Menu_Item *current; + Eina_List *items = sd->items; + EINA_LIST_FOREACH(items, l, current) + { + if (!current->blocked) current->was_enabled = !elm_widget_item_disabled_get(current); + current->blocked = EINA_TRUE; + elm_object_item_disabled_set(current, EINA_TRUE); + } +} + +static void +_unblock_menu(Elm_Menu_Data * sd, Evas_Object *obj EINA_UNUSED, ...) +{ + const Eina_List *l; + Elm_Menu_Item *current; + Eina_List *items = sd->items; + EINA_LIST_FOREACH(items, l, current) + { + elm_object_item_disabled_set(current, !current->was_enabled); + current->blocked = EINA_FALSE; + } +} + EOLIAN static void _elm_menu_evas_smart_show(Eo *obj EINA_UNUSED, Elm_Menu_Data *sd) { @@ -736,6 +763,10 @@ _elm_menu_eo_base_constructor(Eo *obj, Elm_Menu_Data *sd) (sd->hv, ELM_HOVER_AXIS_VERTICAL), sd->bx); _sizing_eval(obj); + evas_object_smart_callback_add(obj, "elm,action,block_menu", + _block_menu, sd); + evas_object_smart_callback_add(obj, "elm,action,unblock_menu", + _unblock_menu, sd); } EAPI void diff --git a/src/lib/elm_widget_menu.h b/src/lib/elm_widget_menu.h index 04fe244..0cede00 100644 --- a/src/lib/elm_widget_menu.h +++ b/src/lib/elm_widget_menu.h @@ -53,6 +53,8 @@ struct _Elm_Menu_Item Eina_Bool separator : 1; Eina_Bool selected : 1; Eina_Bool object_item : 1; + Eina_Bool was_enabled : 1; + Eina_Bool blocked : 1; }; /** diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c index c3a1651..227f051 100644 --- a/src/lib/elm_win.c +++ b/src/lib/elm_win.c @@ -50,6 +50,40 @@ static const Elm_Win_Trap *trap = NULL; if (!obj || !eo_isa(obj, MY_CLASS)) \ return +#define DECREMENT_MODALITY() \ + EINA_LIST_FOREACH(_elm_win_list, l, current) \ + { \ + ELM_WIN_DATA_GET_OR_RETURN(current, cursd); \ + if ((obj != current) && (cursd->modal_count > 0)) \ + { \ + cursd->modal_count--; \ + } \ + if (cursd->modal_count == 0) \ + { \ + edje_object_signal_emit(cursd->layout, \ + "elm,action,hide_blocker", "elm"); \ + evas_object_smart_callback_call(cursd->main_menu, \ + "elm,action,unblock_menu", NULL); \ + } \ + } + +#define INCREMENT_MODALITY() \ + EINA_LIST_FOREACH(_elm_win_list, l, current) \ + { \ + ELM_WIN_DATA_GET_OR_RETURN(current, cursd); \ + if (obj != current) \ + { \ + cursd->modal_count++; \ + } \ + if (cursd->modal_count > 0) \ + { \ + edje_object_signal_emit(cursd->layout, \ + "elm,action,show_blocker", "elm"); \ + evas_object_smart_callback_call(cursd->main_menu, \ + "elm,action,block_menu", NULL); \ + } \ + } + #define ENGINE_GET() (_elm_preferred_engine ? _elm_preferred_engine : (_elm_config->engine ? _elm_config->engine : "")) #define ENGINE_COMPARE(name) (!strcmp(ENGINE_GET(), name)) @@ -158,6 +192,7 @@ struct _Elm_Win_Data int size_base_w, size_base_h; int size_step_w, size_step_h; int norender; + int modal_count; Eina_Bool urgent : 1; Eina_Bool modal : 1; Eina_Bool demand_attention : 1; @@ -858,7 +893,7 @@ _elm_win_focus_in(Ecore_Evas *ee) Evas_Object *obj; unsigned int order = 0; - if (!sd) return; + if ((!sd) || (sd->modal_count)) return; obj = sd->obj; @@ -1249,10 +1284,19 @@ _deferred_ecore_evas_free(void *data) EOLIAN static void _elm_win_evas_smart_show(Eo *obj, Elm_Win_Data *sd) { + if (sd->modal_count) return; + const Eina_List *l; + Evas_Object *current; + if (!evas_object_visible_get(obj)) _elm_win_state_eval_queue(); eo_do_super(obj, MY_CLASS, evas_obj_smart_show()); + if ((sd->modal) && (!evas_object_visible_get(obj))) + { + INCREMENT_MODALITY() + } + TRAP(sd, show); if (sd->shot.info) _shot_handle(sd); @@ -1261,10 +1305,19 @@ _elm_win_evas_smart_show(Eo *obj, Elm_Win_Data *sd) EOLIAN static void _elm_win_evas_smart_hide(Eo *obj, Elm_Win_Data *sd) { + if (sd->modal_count) return; + const Eina_List *l; + Evas_Object *current; + if (evas_object_visible_get(obj)) _elm_win_state_eval_queue(); eo_do_super(obj, MY_CLASS, evas_obj_smart_hide()); + if ((sd->modal) && (evas_object_visible_get(obj))) + { + DECREMENT_MODALITY() + } + TRAP(sd, hide); if (sd->frame_obj) @@ -1512,6 +1565,17 @@ _elm_win_img_callbacks_del(Evas_Object *obj, Evas_Object *imgobj) EOLIAN static void _elm_win_evas_smart_del(Eo *obj, Elm_Win_Data *sd) { + const Eina_List *l; + Evas_Object *current; + + if ((sd->modal) && (evas_object_visible_get(obj))) + { + DECREMENT_MODALITY() + } + + if ((sd->modal) && (sd->modal_count > 0)) + ERR("Deleted modal win was blocked by another modal win which was created after creation of that win."); + evas_object_event_callback_del_full(sd->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _elm_win_on_resize_obj_changed_size_hints, @@ -3111,6 +3175,7 @@ _elm_win_constructor(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_Type t sd->type = type; sd->parent = parent; + sd->modal_count = 0; if (sd->parent) evas_object_event_callback_add @@ -3834,8 +3899,22 @@ _elm_win_demand_attention_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd) } EOLIAN static void -_elm_win_modal_set(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, Eina_Bool modal) +_elm_win_modal_set(Eo *obj, Elm_Win_Data *sd, Eina_Bool modal) { + if (sd->modal_count) return; + + const Eina_List *l; + Evas_Object *current; + + if ((modal) && (!sd->modal) && (evas_object_visible_get(obj))) + { + INCREMENT_MODALITY() + } + else if ((!modal) && (sd->modal) && (evas_object_visible_get(obj))) + { + DECREMENT_MODALITY() + } + sd->modal = modal; TRAP(sd, modal_set, modal); #ifdef HAVE_ELEMENTARY_X --