elementary key binding feature implementation
authorJaeun Choi <jaeun12.choi@samsung.com>
Fri, 28 Feb 2014 01:36:15 +0000 (10:36 +0900)
committerChunEon Park <hermet@hermet.pe.kr>
Fri, 28 Feb 2014 01:47:03 +0000 (10:47 +0900)
Summary: This patch implements elementary key binding feature.

Test Plan: None

Reviewers: Hermet, raster

CC: seoz
Differential Revision: https://phab.enlightenment.org/D506

Conflicts:

src/lib/elm_config.c

config/default/base.src
config/standard/Makefile.am
config/standard/base.src
src/lib/elm_config.c
src/lib/elm_panel.c
src/lib/elm_priv.h
src/lib/elm_widget.h

index 124f5bf..edce1e6 100644 (file)
@@ -244,4 +244,35 @@ group "Elm_Config" struct {
         }
      }
   }
+  group "bindings" list {
+     group "Elm_Config_Bindings_Widget" struct {
+        value "name" string: "Elm_Panel";
+        group "key_bindings" list {
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "Return";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "KP_Enter";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "space";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+        }
+     }
+  }
 }
index 60ce44b..b84899d 100644 (file)
@@ -5,13 +5,13 @@ EET_EET = @eet_eet@
 EXTRA_DIST = \
         profile.desktop \
         icon.png \
-       base.src
+        base.src
 
 filesdir = $(datadir)/elementary/config/standard
 files_DATA = \
         profile.desktop \
         icon.png \
-       base.cfg
+        base.cfg
 
 %.cfg: %.src
        $(EET_EET) -e \
index cf61b79..bd7ae56 100644 (file)
@@ -245,4 +245,35 @@ group "Elm_Config" struct {
         }
      }
   }
+  group "bindings" list {
+     group "Elm_Config_Bindings_Widget" struct {
+        value "name" string: "Elm_Panel";
+        group "key_bindings" list {
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "Return";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "KP_Enter";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "modifiers" string: "None";
+              value "key" string: "space";
+              value "action" string: "toggle";
+              value "params" string: "";
+              value "any_mod" uchar: 1;
+           }
+        }
+     }
+  }
 }
index 7a93b90..daa67aa 100644 (file)
@@ -19,12 +19,16 @@ static Eet_Data_Descriptor *_config_font_overlay_edd = NULL;
 static Eet_Data_Descriptor *_config_color_edd = NULL;
 static Eet_Data_Descriptor *_config_color_palette_edd = NULL;
 static Eet_Data_Descriptor *_config_color_overlay_edd = NULL;
+static Eet_Data_Descriptor *_config_bindings_widget_edd = NULL;
+static Eet_Data_Descriptor *_config_binding_key_edd = NULL;
 const char *_elm_preferred_engine = NULL;
 Eina_List  *_font_overlays_del = NULL;
 Eina_List  *_color_overlays_del = NULL;
 
 static Ecore_Poller *_elm_cache_flush_poller = NULL;
 
+Eina_Hash *_elm_key_bindings = NULL;
+
 const char *_elm_engines[] = {
    "software_x11",
    "fb",
@@ -359,6 +363,31 @@ _desc_init(void)
         return;
      }
 
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config_Bindings_Widget);
+   eddc.func.str_direct_alloc = NULL;
+   eddc.func.str_direct_free = NULL;
+
+   _config_bindings_widget_edd = eet_data_descriptor_stream_new(&eddc);
+   if (!_config_bindings_widget_edd)
+     {
+        ERR("EEEK! eet_data_descriptor_stream_new() failed.");
+        eet_data_descriptor_free(_config_edd);
+        return;
+     }
+
+   memset(&eddc, 0, sizeof(eddc)); /* just in case... */
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config_Binding_Key);
+   eddc.func.str_direct_alloc = NULL;
+   eddc.func.str_direct_free = NULL;
+
+   _config_binding_key_edd = eet_data_descriptor_stream_new(&eddc);
+   if (!_config_binding_key_edd)
+     {
+        ERR("EEEK! eet_data_descriptor_stream_new() failed.");
+        eet_data_descriptor_free(_config_edd);
+        return;
+     }
+
 #define T_INT    EET_T_INT
 #define T_DOUBLE EET_T_DOUBLE
 #define T_STRING EET_T_STRING
@@ -406,6 +435,24 @@ _desc_init(void)
 #undef T
 #undef D
 
+#define T        Elm_Config_Bindings_Widget
+#define D        _config_bindings_widget_edd
+   ELM_CONFIG_VAL(D, T, name, EET_T_STRING);
+   ELM_CONFIG_LIST(D, T, key_bindings, _config_binding_key_edd);
+#undef T
+#undef D
+
+#define T        Elm_Config_Binding_Key
+#define D        _config_binding_key_edd
+   ELM_CONFIG_VAL(D, T, context, EET_T_INT);
+   ELM_CONFIG_VAL(D, T, modifiers, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, key, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, action, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, params, EET_T_STRING);
+   ELM_CONFIG_VAL(D, T, any_mod, EET_T_UCHAR);
+#undef T
+#undef D
+
 #define T Elm_Config
 #define D _config_edd
    ELM_CONFIG_VAL(D, T, config_version, T_INT);
@@ -510,6 +557,7 @@ _desc_init(void)
    ELM_CONFIG_VAL(D, T, audio_mute_input, T_UCHAR);
    ELM_CONFIG_VAL(D, T, audio_mute_alert, T_UCHAR);
    ELM_CONFIG_VAL(D, T, audio_mute_all, T_UCHAR);
+   ELM_CONFIG_LIST(D, T, bindings, _config_bindings_widget_edd);
 #undef T
 #undef D
 #undef T_INT
@@ -550,6 +598,18 @@ _desc_shutdown(void)
         eet_data_descriptor_free(_config_color_overlay_edd);
         _config_color_overlay_edd = NULL;
      }
+
+   if (_config_bindings_widget_edd)
+     {
+        eet_data_descriptor_free(_config_bindings_widget_edd);
+        _config_bindings_widget_edd = NULL;
+     }
+
+   if (_config_binding_key_edd)
+     {
+        eet_data_descriptor_free(_config_binding_key_edd);
+        _config_binding_key_edd = NULL;
+     }
 }
 
 static int
@@ -1208,6 +1268,8 @@ _config_free(Elm_Config *cfg)
    Elm_Custom_Palette *palette;
    Elm_Color_RGBA *color;
    char *color_class;
+   Elm_Config_Bindings_Widget *wb;
+   Elm_Config_Binding_Key *kb;
 
    if (!cfg) return;
    EINA_LIST_FREE(cfg->font_dirs, fontdir)
@@ -1234,6 +1296,19 @@ _config_free(Elm_Config *cfg)
         EINA_LIST_FREE(palette->color_list, color) free(color);
         free(palette);
      }
+   EINA_LIST_FREE(cfg->bindings, wb)
+     {
+        eina_stringshare_del(wb->name);
+        EINA_LIST_FREE(wb->key_bindings, kb)
+          {
+             eina_stringshare_del(kb->modifiers);
+             eina_stringshare_del(kb->key);
+             eina_stringshare_del(kb->action);
+             eina_stringshare_del(kb->params);
+             free(kb);
+          }
+        free(wb);
+     }
    eina_stringshare_del(cfg->theme);
    eina_stringshare_del(cfg->modules);
    eina_stringshare_del(cfg->indicator_service_0);
@@ -2041,6 +2116,58 @@ _env_get(void)
    if (s) _elm_config->magnifier_scale = _elm_atof(s);
 }
 
+void
+_elm_config_key_binding_hash(void)
+{
+   Elm_Config_Bindings_Widget *wb;
+   Eina_List *l;
+
+   if (_elm_key_bindings)
+     eina_hash_free(_elm_key_bindings);
+
+   _elm_key_bindings = eina_hash_string_superfast_new(NULL);
+   EINA_LIST_FOREACH(_elm_config->bindings, l, wb)
+     {
+        eina_hash_add(_elm_key_bindings, wb->name, wb->key_bindings);
+     }
+}
+
+Eina_Bool
+_elm_config_key_binding_call(Evas_Object *obj,
+                             const Evas_Event_Key_Down *ev,
+                             const Elm_Action *actions)
+{
+   Elm_Config_Binding_Key *binding;
+   Eina_List *binding_list, *l;
+   int i = 0;
+
+   binding_list = eina_hash_find(_elm_key_bindings, elm_widget_type_get(obj));
+
+   if (binding_list)
+     {
+        EINA_LIST_FOREACH(binding_list, l, binding)
+          {
+             if (binding->key && (!strcmp(binding->key, ev->keyname))
+                 && ((evas_key_modifier_is_set
+                      (ev->modifiers, binding->modifiers)
+                      || (binding->any_mod))))
+               {
+                  while (actions[i].name)
+                    {
+                       if (!strcmp(binding->action, actions[i].name))
+                         {
+                            actions[i].func(obj, binding->params);
+                            return EINA_TRUE;
+                         }
+                       i++;
+                    }
+                  break;
+               }
+          }
+     }
+   return EINA_FALSE;
+}
+
 EAPI Eina_Bool
 elm_config_mirrored_get(void)
 {
@@ -2884,6 +3011,7 @@ _elm_config_init(void)
    _elm_config_color_overlay_apply();
    _elm_recache();
    _elm_clouseau_reload();
+   _elm_config_key_binding_hash();
 }
 
 void
@@ -2987,6 +3115,7 @@ _elm_config_reload(void)
    _elm_rescale();
    _elm_recache();
    _elm_clouseau_reload();
+   _elm_config_key_binding_hash();
    ecore_event_add(ELM_EVENT_CONFIG_ALL_CHANGED, NULL, NULL, NULL);
 }
 
@@ -3059,6 +3188,7 @@ _elm_config_profile_set(const char *profile)
    _elm_rescale();
    _elm_recache();
    _elm_clouseau_reload();
+   _elm_config_key_binding_hash();
 }
 
 void
@@ -3084,4 +3214,7 @@ _elm_config_shutdown(void)
 #endif
 
    _desc_shutdown();
+
+   if (_elm_key_bindings)
+     eina_hash_free(_elm_key_bindings);
 }
index 060c82f..a6d3072 100644 (file)
@@ -20,6 +20,13 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
    {NULL, NULL}
 };
 
+void _key_action_toggle(Evas_Object *obj, const char *params);
+
+static const Elm_Action key_actions[] = {
+   {"toggle", _key_action_toggle},
+   {NULL, NULL}
+};
+
 static void
 _mirrored_set(Evas_Object *obj,
               Eina_Bool rtl)
@@ -247,10 +254,14 @@ _panel_toggle(void *data EINA_UNUSED,
    edje_object_message_signal_process(wd->resize_obj);
 }
 
+void _key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED)
+{
+   _panel_toggle(NULL, obj, NULL, NULL);
+}
+
 static void
 _elm_panel_smart_event(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
 {
-
    Evas_Object *src = va_arg(*list, Evas_Object *);
    Evas_Callback_Type type = va_arg(*list, Evas_Callback_Type);
    Evas_Event_Key_Down *ev = va_arg(*list, void *);
@@ -263,12 +274,7 @@ _elm_panel_smart_event(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
    if (src != obj) return;
 
-   if ((strcmp(ev->key, "Return")) &&
-       (strcmp(ev->key, "KP_Enter")) &&
-       (strcmp(ev->key, "space")))
-     return;
-
-   _panel_toggle(NULL, obj, NULL, NULL);
+   _elm_config_key_binding_call(obj, ev, key_actions);
 
    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
    if (ret) *ret = EINA_TRUE;
index 5d18a9f..e1081e3 100644 (file)
@@ -76,6 +76,8 @@
 typedef struct _Elm_Theme_Files          Elm_Theme_Files;
 typedef struct _Edje_Signal_Data         Edje_Signal_Data;
 typedef struct _Elm_Config               Elm_Config;
+typedef struct _Elm_Config_Bindings_Widget   Elm_Config_Bindings_Widget;
+typedef struct _Elm_Config_Binding_Key   Elm_Config_Binding_Key;
 typedef struct _Elm_Module               Elm_Module;
 typedef struct _Elm_Datetime_Module_Data Elm_Datetime_Module_Data;
 
@@ -275,12 +277,29 @@ struct _Elm_Config
    unsigned char audio_mute_input;
    unsigned char audio_mute_alert;
    unsigned char audio_mute_all;
+   Eina_List    *bindings;
 
    /* Not part of the EET file */
    Eina_Bool     is_mirrored : 1;
    Eina_Bool     translate : 1;
 };
 
+struct _Elm_Config_Bindings_Widget
+{
+   const char   *name;
+   Eina_List    *key_bindings;
+};
+
+struct _Elm_Config_Binding_Key
+{
+   int           context;
+   const char   *modifiers;
+   const char   *key;
+   const char   *action;
+   const char   *params;
+   unsigned char any_mod;
+};
+
 struct _Elm_Module
 {
    int          version;
@@ -421,6 +440,10 @@ void                 _elm_config_color_overlay_apply(void);
 Eina_Bool            _elm_config_access_get(void);
 void                 _elm_config_access_set(Eina_Bool is_access);
 
+Eina_Bool            _elm_config_key_binding_call(Evas_Object *obj,
+                                                  const Evas_Event_Key_Down *ev,
+                                                  const Elm_Action *actions);
+
 Elm_Font_Properties *_elm_font_properties_get(Eina_Hash **font_hash,
                                               const char *font);
 Eina_Hash           *_elm_font_available_hash_add(Eina_Hash *font_hash,
index 1377179..a205ed9 100644 (file)
@@ -456,6 +456,8 @@ typedef struct _Elm_Access_Info Elm_Access_Info;
 /**< accessibility info item */
 typedef struct _Elm_Access_Item Elm_Access_Item;
 
+typedef struct _Elm_Action Elm_Action;
+
 typedef void                  (*Elm_Widget_Text_Set_Cb)(void *data, const char *part, const char *text);
 typedef void                  (*Elm_Widget_Content_Set_Cb)(void *data, const char *part, Evas_Object *content);
 typedef const char           *(*Elm_Widget_Text_Get_Cb)(const void *data, const char *part);
@@ -503,6 +505,12 @@ struct _Elm_Access_Info
    Evas_Object               *prev;
 };
 
+struct _Elm_Action
+{
+   const char *name;
+   void (*func)(Evas_Object *obj, const char *params);
+};
+
 void                  _elm_access_shutdown();
 void                  _elm_access_mouse_event_enabled_set(Eina_Bool enabled);