elementary: when modal win appears another wins are blocked
authorBogdan Devichev <b.devichev@samsung.com>
Wed, 9 Apr 2014 10:04:55 +0000 (19:04 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Wed, 9 Apr 2014 10:04:55 +0000 (19:04 +0900)
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
src/lib/elm_menu.c
src/lib/elm_widget_menu.h
src/lib/elm_win.c

index 56af51fd128fd091538e84690ecf9d3638137dad..343de6c6e2f6b3ad7bfb643934c582111a9fc75f 100644 (file)
@@ -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";
+      }
    }
 }
index d13f4422e30a8a51401245f20d098341a3e9a977..5e8a356fdeddd183386c2269523ad40d1e6378d1 100644 (file)
@@ -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
index 04fe2448b02f1b0988e98ce38b9d77a8c6bf328c..0cede00d37a8c705d979861512db5ff398a6568e 100644 (file)
@@ -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;
 };
 
 /**
index c3a1651c6d5423fd22552886d9786c98ecc9ab23..227f0519dd33eef45b0f793e5e06935afefc6ac4 100644 (file)
@@ -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