Initialize efl-assist
authorSungho Kwak <sungho1.kwak@samsung.com>
Thu, 20 Jun 2013 10:47:15 +0000 (19:47 +0900)
committerSungho Kwak <sungho1.kwak@samsung.com>
Thu, 20 Jun 2013 10:47:15 +0000 (19:47 +0900)
Change-Id: Ida7e933065bd1b2193e1ddebce23f889a65ffa8a

src/CMakeLists.txt [new file with mode: 0644]
src/include/CMakeLists.txt [new file with mode: 0644]
src/include/efl_assist.h [new file with mode: 0644]
src/include/efl_assist_editfield.h [new file with mode: 0644]
src/include/efl_assist_events.h [new file with mode: 0644]
src/include/efl_assist_private.h [new file with mode: 0644]
src/lib/CMakeLists.txt [new file with mode: 0644]
src/lib/efl_assist.c [new file with mode: 0644]
src/lib/efl_assist_editfield.c [new file with mode: 0644]
src/lib/efl_assist_events.c [new file with mode: 0644]

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..502ae8b
--- /dev/null
@@ -0,0 +1,8 @@
+SET(LIB_NAME ${PROJECT_NAME})
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
+LINK_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+ADD_SUBDIRECTORY(include)
+ADD_SUBDIRECTORY(lib)
+#ADD_SUBDIRECTORY(examples)
diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b9f586f
--- /dev/null
@@ -0,0 +1,6 @@
+INSTALL(
+        DIRECTORY ./ DESTINATION include/${LIB_NAME}
+        FILES_MATCHING
+        PATTERN "*_private.h" EXCLUDE
+        PATTERN "*.h"
+        )
diff --git a/src/include/efl_assist.h b/src/include/efl_assist.h
new file mode 100644 (file)
index 0000000..f914dce
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+#ifndef __EFL_ASSIST_H__
+#define __EFL_ASSIST_H__
+
+
+#include "efl_assist_editfield.h"
+#include "efl_assist_events.h"
+
+#endif /* __EFL_ASSIST_H__ */
+
diff --git a/src/include/efl_assist_editfield.h b/src/include/efl_assist_editfield.h
new file mode 100644 (file)
index 0000000..3f99d22
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+#ifndef __EFL_ASSIST_EDITFIELD_H__
+#define __EFL_ASSIST_EDITFIELD_H__
+
+#include <Elementary.h>
+#include <stdbool.h>
+#ifndef DESKTOP
+       #include <tizen.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @typedef Ea_Editfield_Type
+ *
+ * Editfield Entry types.
+ *
+ * @see ea_editfield_add()
+ */
+typedef enum
+{
+   EA_EDITFIELD_SINGLELINE,
+   EA_EDITFIELD_MULTILINE,
+   EA_EDITFIELD_SCROLL_SINGLELINE,
+   EA_EDITFIELD_SCROLL_MULTILINE,
+   EA_EDITFIELD_SCROLL_SINGLELINE_PASSWORD,
+   EA_EDITFIELD_SEARCHBAR
+} Ea_Editfield_Type;
+
+/**
+ * @brief Add an elementary entry widget with clear button and rename icon.
+ *
+ * @details Add an elementary entry widget with some special features.
+ *          The first is clear button that will delete all characters in current entry widget.
+ *          The second is rename icon which symbolizes the editable field in dialogue view.
+ *          Visible state of each clear button and rename icon will be changed automatically.
+ *          This API will return an elementary entry widget, and some elm_entry APIs can change
+ *          the internal state of this widget. For maintaining the original states of entry widget,
+ *          following signal emitting is needed :
+ *
+ *          1. For maintaining visible state of rename icon :
+ *                 "elm,state,rename,visible", "elm,state,rename,hidden"
+ *
+ *          2. For maintaining visible state of clear button :
+ *                 "elm,state,clear,visible", "elm,state,clear,hidden"
+ *
+ *          3. For maintaining scrollable state of entry :
+ *                 "elm,state,scroll,enabled", "elm,state,scroll,disabled"
+ *
+ *
+ * @param [in] parent The parent widget object
+ * @param [in] type Types for supporting different entry widget modes.
+ *
+ * @return elementary entry widget
+ *
+ */
+Evas_Object *ea_editfield_add(Evas_Object *parent, Ea_Editfield_Type type);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EFL_ASSIST_EDITFIELD_H__ */
diff --git a/src/include/efl_assist_events.h b/src/include/efl_assist_events.h
new file mode 100644 (file)
index 0000000..c0441d0
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+#ifndef __EFL_ASSIST_EVENTS_H__
+#define __EFL_ASSIST_EVENTS_H__
+
+#include <Elementary.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Convenient macro function that sends back key events to the popup
+ *        to be removed.
+ *
+ * @see   ea_object_event_callback_add()
+ */
+static inline void
+ea_popup_back_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_del(obj);
+}
+
+/**
+ * @brief Convenient macro function that sends back key events to the ctxpopup
+ *        to be dismissed.
+ *
+ * @see   ea_object_event_callback_add()
+ */
+static inline void
+ea_ctxpopup_back_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_ctxpopup_dismiss(obj);
+}
+
+/**
+ * @brief Convenient macro function that sends more key events to the naviframe
+ *        top item.
+ * @see   ea_object_event_callback_add()
+ */
+static inline void
+ea_naviframe_more_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   Elm_Object_Item *top = elm_naviframe_top_item_get(obj);
+   if (!top) return;
+   Evas_Object *more_btn = elm_object_item_part_content_get(top, "toolbar_more_btn");
+   if (more_btn)
+     evas_object_smart_callback_call(more_btn, "clicked", NULL);
+}
+
+/**
+ * @brief Convenient macro function that pop the naviframe item.
+ * @see   ea_object_event_callback_add()
+ */
+static inline void
+ea_naviframe_back_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_naviframe_item_pop(obj);
+}
+
+/**
+ * Identifier of callbacks to be set for Ea events.
+ *
+ * @see ea_object_event_callback_add()
+ * @see ea_object_event_callback_del()
+ */
+typedef enum _Ea_Callback_Type
+{
+   EA_CALLBACK_BACK,
+   EA_CALLBACK_MORE,
+   EA_CALLBACK_LAST
+} Ea_Callback_Type;
+
+/** <Ea event callback function signature */
+typedef void (*Ea_Event_Cb)(void *data, Evas_Object *obj, void *event_info);
+
+/**
+ * Delete a callback function from an object.
+ *
+ * @param[in] obj Object to remove a callback from.
+ * @param[in] type The type of event that was triggering the callback.
+ * @param[in] func The function that was to be called when the event was
+ *            triggered
+ * @return    data The data pointer that was to be passed to the callback.
+ *
+ * @brief     This function removes the most recently added callback from the
+ *            object @p obj which was triggered by the type @p type and
+ *            was calling the function @p func when triggered. If the removal is
+ *            successful it will also return the data pointer that was passed to
+ *            ea_object_event_callback_add() when the callback was added to
+ *            the object. If not successful @c NULl will be returned.
+ *
+ * @see ea_object_event_callback_add()
+ */
+
+EAPI void *ea_object_event_callback_del(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb);
+
+/**
+ * Add (register) a callback function to a given evas object.
+ *
+ * @param[in] obj evas object.
+ * @param[in] type The type of event that will trigger the callback.
+ * @param[in] func The function to be called when the key event is triggered.
+ * @param[in] data The data pointer to be passed to @p func.
+ *
+ * @brief This function adds a function callback to an object when the key event
+ *        occurs on object @p obj. The key event on the object is only triggered
+ *        when the object is the most top in objects stack and visible. This
+ *        means, like the naviframe widget, if your application needs to have
+ *        the events based on the view but not focus, you can use this callback.
+ *
+ *        A callback function must have the Ea_Event_Cb prototype definition.
+ *        The first parameter (@p data) in this definition will have the same
+ *        value passed to ea_object_event_callback_add() as the @p data
+ *        parameter, at runtime. The second parameter @p obj is the evas object
+ *        on which event occurred. Finally, the third parameter @p event_info is
+ *        a pointer to a data structure that may or may not be passed to the
+ *        callback, depending on the event type that triggered the callback.
+ *        This is so because some events don't carry extra context with them,
+ *        but others do.
+ *
+ * @see ea_object_event_callback_del()
+ */
+
+EAPI void ea_object_event_callback_add(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb func, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EFL_ASSIST_EVENTS_H__ */
diff --git a/src/include/efl_assist_private.h b/src/include/efl_assist_private.h
new file mode 100644 (file)
index 0000000..61995a4
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+#ifndef __EFL_ASSIST_PRIVATE_H__
+#define __EFL_ASSIST_PRIVATE_H__
+
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "efl-assist"
+#define __CONSTRUCTOR__ __attribute__ ((constructor))
+#define __DESTRUCTOR__ __attribute__ ((destructor))
+
+/* eina magic types */
+#define EA_MAGIC_NONE 0x87657890
+#define EA_MAGIC_CUTLINK 0x78908765
+
+typedef unsigned int ea_magic;
+#define EA_MAGIC                ea_magic __magic
+
+#define EA_MAGIC_SET(d, m)      (d)->__magic = (m)
+#define EA_MAGIC_CHECK(d, m)    ((d) && ((d)->__magic == (m)))
+#define EA_MAGIC_FAIL(d, m, fn) \
+               _ea_magic_fail((d), (d) ? (d)->__magic : 0, (m), (fn));
+
+void _ea_magic_fail(const void *d, ea_magic m,
+                   ea_magic req_m, const char *fname);
+
+#define CRITICAL(...) EINA_LOG_DOM_CRIT(_ea.ea_log_dom, __VA_ARGS__)
+#define ERR(...)      EINA_LOG_DOM_ERR(_ea.ea_log_dom, __VA_ARGS__)
+#define WRN(...)      EINA_LOG_DOM_WARN(_ea.ea_log_dom, __VA_ARGS__)
+#define INF(...)      EINA_LOG_DOM_INFO(_ea.ea_log_dom, __VA_ARGS__)
+#define DBG(...)      EINA_LOG_DOM_DBG(_ea.ea_log_dom, __VA_ARGS__)
+
+typedef struct _Ea Ea;
+typedef struct _Ea_Event_Mgr Ea_Event_Mgr;
+
+struct _Ea
+{
+   Eina_List *event_mgrs;
+   int ea_log_dom;
+};
+
+extern Ea _ea;
+
+void ea_event_mgr_clear(Ea_Event_Mgr *event_mgr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EFL_ASSIST_PRIVATE_H__ */
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3e3656c
--- /dev/null
@@ -0,0 +1,35 @@
+option(DESKTOP "Build for i386 linux desktop" OFF)
+
+if (DESKTOP)
+       SET(LIB_SRCS
+               efl_assist.c
+               efl_assist_editfield.c
+               efl_assist_events.c)
+else (DESKTOP)
+       SET(LIB_SRCS
+               efl_assist.c
+               efl_assist_editfield.c
+               efl_assist_events.c)
+endif (DESKTOP)
+
+ADD_LIBRARY(${LIB_NAME} SHARED ${LIB_SRCS})
+
+if (DESKTOP)
+       PKG_CHECK_MODULES(LIB_PKGS REQUIRED elementary)
+       ADD_DEFINITIONS("-DDESKTOP=1")
+       ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))")
+else (DESKTOP)
+       PKG_CHECK_MODULES(LIB_PKGS REQUIRED elementary capi-base-common capi-appfw-application)
+endif (DESKTOP)
+
+FOREACH(flag ${LIB_PKGS_CFLAGS})
+       SET(LIB_CFLAGS "${LIB_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES COMPILE_FLAGS "${LIB_CFLAGS}")
+SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+TARGET_LINK_LIBRARIES(${LIB_NAME} ${LIB_PKGS_LDFLAGS} ${LIB_TARGET_PKGS_LDFLAGS})
+
+INSTALL(TARGETS ${LIB_NAME} DESTINATION lib)
+
diff --git a/src/lib/efl_assist.c b/src/lib/efl_assist.c
new file mode 100644 (file)
index 0000000..8d92501
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+#include "efl_assist.h"
+#include "efl_assist_private.h"
+
+/*===========================================================================*
+ *                                 Local                                     *
+ *===========================================================================*/
+
+Ea _ea;
+
+static void
+ea_init(void)
+{
+   memset(&_ea, 0x00, sizeof(_ea));
+
+   _ea.ea_log_dom = eina_log_domain_register("efl-assist",
+                                             EINA_COLOR_LIGHTBLUE);
+   if (!_ea.ea_log_dom)
+     {
+        EINA_LOG_ERR("could not register efl-assist log domain");
+        _ea.ea_log_dom = EINA_LOG_DOMAIN_GLOBAL;
+     }
+}
+
+static void
+ea_shutdown(void)
+{
+   Eina_List *l;
+   Ea_Event_Mgr *event_mgr;
+
+   //Remove Event Managers
+   EINA_LIST_FOREACH(_ea.event_mgrs, l, event_mgr)
+     ea_event_mgr_clear(event_mgr);
+   _ea.event_mgrs = eina_list_free(_ea.event_mgrs);
+
+   if ((_ea.ea_log_dom > - 1) && (_ea.ea_log_dom != EINA_LOG_DOMAIN_GLOBAL))
+     {
+        eina_log_domain_unregister(_ea.ea_log_dom);
+        _ea.ea_log_dom = -1;
+     }
+}
+
+static const char *
+_magic_string_get(ea_magic m)
+{
+       switch (m) {
+       case EA_MAGIC_NONE:
+               return "None (Freed Object)";
+
+       case EA_MAGIC_CUTLINK:
+               return "cutlink";
+
+       default:
+               return "<UNKNOWN>";
+     }
+}
+
+__CONSTRUCTOR__ static void
+ea_mod_init(void)
+{
+       if (!elm_init(0, NULL)) {
+               fprintf(stderr, "could not initialize elementary.\n");
+               return;
+       }
+
+       ea_init();
+
+       DBG("loaded");
+}
+
+__DESTRUCTOR__ static void
+ea_mod_shutdown(void)
+{
+       DBG("unloaded");
+
+       ea_shutdown();
+       elm_shutdown();
+}
+
+
+/*===========================================================================*
+ *                                Global                                     *
+ *===========================================================================*/
+
+void
+_ea_magic_fail(const void *d, ea_magic m, ea_magic req_m, const char *fname)
+{
+       ERR("\n*** MAGIC FAIL (%s) ***\n", fname);
+
+       if (!d)
+               ERR("  Input handle pointer is NULL!");
+       else if (m == EA_MAGIC_NONE)
+               ERR("  Input handle has already been freed!");
+       else if (m != req_m)
+               ERR("  Input handle is wrong type\n"
+                   "    Expected: %08x - %s\n"
+                   "    Supplied: %08x - %s",
+                   (unsigned int)req_m, _magic_string_get(req_m),
+                   (unsigned int)m, _magic_string_get(m));
+
+   if (getenv("EA_ERROR_ABORT")) abort();
+}
+
+/*===========================================================================*
+ *                                  API                                      *
+ *===========================================================================*/
+
diff --git a/src/lib/efl_assist_editfield.c b/src/lib/efl_assist_editfield.c
new file mode 100644 (file)
index 0000000..9fe6d2c
--- /dev/null
@@ -0,0 +1,141 @@
+#include "efl_assist.h"
+#include "efl_assist_private.h"
+
+static void _editfield_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   if (elm_object_part_content_get(obj, "elm.swallow.clear"))
+     {
+        if (elm_object_focus_get(obj))
+          {
+             if (elm_entry_is_empty(obj))
+               elm_object_signal_emit(obj, "elm,state,clear,hidden", "");
+             else
+               elm_object_signal_emit(obj, "elm,state,clear,visible", "");
+          }
+     }
+}
+
+static void _editfield_focused_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   if (elm_object_part_content_get(obj, "elm.swallow.clear"))
+     {
+        if (!elm_entry_is_empty(obj))
+          elm_object_signal_emit(obj, "elm,state,clear,visible", "");
+        else
+          elm_object_signal_emit(obj, "elm,state,clear,hidden", "");
+     }
+   elm_object_signal_emit(obj, "elm,state,focus,on", "");
+}
+
+static void _editfield_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   if (elm_object_part_content_get(obj, "elm.swallow.clear"))
+     elm_object_signal_emit(obj, "elm,state,clear,hidden", "");
+   elm_object_signal_emit(obj, "elm,state,focus,off", "");
+}
+
+static void _eraser_btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_entry_entry_set(data, "");
+}
+
+static void _editfield_searchbar_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   if (elm_object_part_content_get(obj, "elm.swallow.clear"))
+     {
+        if (elm_entry_is_empty(obj))
+          elm_object_signal_emit(obj, "elm,state,clear,hidden", "");
+        else
+          elm_object_signal_emit(obj, "elm,state,clear,visible", "");
+     }
+}
+
+static void _editfield_searchbar_focused_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_object_signal_emit(obj, "elm,state,focus,on", "");
+}
+
+static void _editfield_searchbar_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   elm_object_signal_emit(obj, "elm,state,focus,off", "");
+}
+
+EXPORT_API Evas_Object *
+ea_editfield_add(Evas_Object *parent, Ea_Editfield_Type type)
+{
+   Evas_Object *entry, *button;
+
+   entry = elm_entry_add(parent);
+
+   if (type == EA_EDITFIELD_SINGLELINE)
+     {
+        elm_object_style_set(entry, "editfield");
+        elm_entry_single_line_set(entry, EINA_TRUE);
+     }
+   else if (type == EA_EDITFIELD_SCROLL_SINGLELINE)
+     {
+        elm_object_style_set(entry, "editfield");
+        elm_entry_single_line_set(entry, EINA_TRUE);
+        elm_entry_scrollable_set(entry, EINA_TRUE);
+        elm_object_signal_emit(entry, "elm,state,scroll,enabled", "");
+     }
+   else if (type == EA_EDITFIELD_SCROLL_SINGLELINE_PASSWORD)
+     {
+        elm_object_style_set(entry, "editfield");
+        elm_entry_single_line_set(entry, EINA_TRUE);
+        elm_entry_password_set(entry, EINA_TRUE);
+        elm_entry_scrollable_set(entry, EINA_TRUE);
+        elm_object_signal_emit(entry, "elm,state,scroll,enabled", "");
+     }
+   else if (type == EA_EDITFIELD_SCROLL_MULTILINE)
+     {
+        elm_object_style_set(entry, "editfield");
+        elm_entry_scrollable_set(entry, EINA_TRUE);
+        elm_object_signal_emit(entry, "elm,state,scroll,enabled", "");
+     }
+   else if (type == EA_EDITFIELD_SEARCHBAR)
+     {
+        elm_object_style_set(entry, "editfield/searchbar/default");
+        elm_entry_single_line_set(entry, EINA_TRUE);
+        elm_entry_scrollable_set(entry, EINA_TRUE);
+        elm_object_signal_emit(entry, "elm,state,scroll,enabled", "");
+     }
+   else
+     {
+        elm_object_style_set(entry, "editfield");
+     }
+
+   if (type == EA_EDITFIELD_SEARCHBAR)
+     {
+        button = elm_button_add(parent);
+        elm_object_style_set(button, "search_icon");
+        elm_object_focus_allow_set(button, EINA_FALSE);
+        elm_object_part_content_set(entry, "elm.swallow.icon", button);
+
+        button = elm_button_add(parent);
+        elm_object_style_set(button, "search_clear");
+        elm_object_focus_allow_set(button, EINA_FALSE);
+        elm_object_part_content_set(entry, "elm.swallow.clear", button);
+        evas_object_smart_callback_add(button, "clicked", _eraser_btn_clicked_cb, entry);
+
+        evas_object_smart_callback_add(entry, "changed", _editfield_searchbar_changed_cb, NULL);
+        evas_object_smart_callback_add(entry, "preedit,changed", _editfield_searchbar_changed_cb, NULL);
+        evas_object_smart_callback_add(entry, "focused", _editfield_searchbar_focused_cb, NULL);
+        evas_object_smart_callback_add(entry, "unfocused", _editfield_searchbar_unfocused_cb, NULL);
+     }
+   else
+     {
+        button = elm_button_add(parent);
+        elm_object_style_set(button, "editfield_clear");
+        elm_object_focus_allow_set(button, EINA_FALSE);
+        elm_object_part_content_set(entry, "elm.swallow.clear", button);
+        evas_object_smart_callback_add(button, "clicked", _eraser_btn_clicked_cb, entry);
+
+        evas_object_smart_callback_add(entry, "changed", _editfield_changed_cb, NULL);
+        evas_object_smart_callback_add(entry, "preedit,changed", _editfield_changed_cb, NULL);
+        evas_object_smart_callback_add(entry, "focused", _editfield_focused_cb, NULL);
+        evas_object_smart_callback_add(entry, "unfocused", _editfield_unfocused_cb, NULL);
+     }
+
+   return entry;
+}
diff --git a/src/lib/efl_assist_events.c b/src/lib/efl_assist_events.c
new file mode 100644 (file)
index 0000000..fc4a8e1
--- /dev/null
@@ -0,0 +1,408 @@
+#include "efl_assist.h"
+#include "efl_assist_private.h"
+
+struct _Ea_Event_Mgr
+{
+   Eina_List *obj_events;
+   Evas *e;
+   Evas_Object *key_grab_rect;
+};
+
+typedef struct _Ea_Object_Event
+{
+   Evas_Object *obj;
+   Evas_Object *parent;
+   Eina_List *callbacks;
+} Ea_Object_Event;
+
+typedef struct _Ea_Event_Callback
+{
+   Ea_Callback_Type type;
+   void (*func)(void *data, Evas_Object *obj, void *event_info);
+   void *data;
+} Ea_Event_Callback;
+
+const char *EA_OBJ_KEY_EVENT_MGR = "_ea_obj_key_event_mgr";
+const char *EA_OBJ_KEY_OBJ_EVENT = "_ea_obj_key_obj_event";
+const char *EA_KEY_BACK = "XF86Stop";
+const char *EA_KEY_BACK2 = "Escape";
+const char *EA_KEY_SEND = "XF86Send";
+
+static void
+_ea_event_mgr_del(Ea_Event_Mgr *event_mgr)
+{
+   if (event_mgr->obj_events) return;
+
+   //Redundant Event Mgr. Remove it.
+   evas_object_del(event_mgr->key_grab_rect);
+   _ea.event_mgrs = eina_list_remove(_ea.event_mgrs, event_mgr);
+   free(event_mgr);
+}
+
+static void
+_ea_object_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Ea_Event_Mgr *event_mgr = evas_object_data_get(obj, EA_OBJ_KEY_EVENT_MGR);
+   Ea_Object_Event *obj_event = data;
+   Eina_List *l;
+   Ea_Event_Callback *callback;
+
+   l = eina_list_data_find_list(event_mgr->obj_events, obj_event);
+   if (!l) return;
+
+   event_mgr->obj_events = eina_list_remove_list(event_mgr->obj_events, l);
+
+   EINA_LIST_FOREACH(obj_event->callbacks, l, callback)
+      free(callback);
+   obj_event->callbacks = eina_list_free(obj_event->callbacks);
+
+   free(obj_event);
+
+   _ea_event_mgr_del(event_mgr);
+}
+
+static int
+_ea_layer_sort_cb(const void *data1, const void *data2)
+{
+   const Ea_Object_Event *obj_event = data1;
+   const Ea_Object_Event *obj_event2 = data2;
+
+   //1. Layer Compare
+   int layer1 = evas_object_layer_get(obj_event->obj);
+   int layer2 = evas_object_layer_get(obj_event2->obj);
+
+   return (layer1 < layer2) ? -1 : 1;
+}
+
+static Evas_Object *
+_ea_top_parent_candidates(Eina_List **candidates, Evas *e)
+{
+   Evas_Object *temp;
+   Evas_Object *parent;
+   Eina_List *l, *l_next;
+   Ea_Object_Event *obj_event;
+   Eina_List *_candidates = *candidates;
+   Eina_Bool found = EINA_FALSE;
+
+   //Get the top parent lists
+   EINA_LIST_FOREACH(_candidates, l, obj_event)
+     {
+        temp = obj_event->obj;
+        parent = obj_event->obj;
+        while (temp)
+          {
+             parent = temp;
+             temp = evas_object_smart_parent_get(temp);
+          }
+        obj_event->parent = parent;
+     }
+
+   //Leave only parent candidates.
+   parent = evas_object_top_get(e);
+
+   while (parent)
+     {
+        EINA_LIST_FOREACH(_candidates, l, obj_event)
+          {
+             if (parent == obj_event->parent)
+               {
+                  found = EINA_TRUE;
+                  obj_event->parent = NULL;
+               }
+          }
+        if (found) break;
+        parent = evas_object_below_get(parent);
+     }
+
+   //Redundant parents (no candidates)
+   EINA_LIST_FOREACH_SAFE(_candidates, l, l_next, obj_event)
+     {
+        if (!obj_event->parent) continue;
+        _candidates = eina_list_remove_list(_candidates, l);
+     }
+
+   *candidates = _candidates;
+   return parent;
+}
+
+static Ea_Object_Event *
+_ea_find_event_target(Eina_List *candidates, Evas_Object *parent)
+{
+   Ea_Object_Event *obj_event = NULL;
+   Eina_List *l;
+   Evas_Object *obj;
+   Eina_List *members = evas_object_smart_members_get(parent);
+   if (members)
+     {
+        EINA_LIST_REVERSE_FOREACH(members, l, obj)
+          {
+             obj_event = _ea_find_event_target(candidates, obj);
+             //got you!
+             if (obj_event)
+               {
+                  eina_list_free(members);
+                  return obj_event;
+               }
+          }
+        eina_list_free(members);
+     }
+
+   EINA_LIST_REVERSE_FOREACH(candidates, l, obj_event)
+     {
+        //got you!
+        if (parent == obj_event->obj) return obj_event;
+     }
+
+   return NULL;
+}
+
+static Ea_Object_Event *
+_ea_top_obj_event_find(Ea_Event_Mgr *event_mgr)
+{
+   Ea_Object_Event *obj_event = NULL;
+   Eina_List *l, *l_next;
+   Eina_List *candidates = NULL;
+   Evas_Object *parent;
+   int top_layer;
+   Eina_Bool invisible;
+
+   //1. filter the invisible objs
+   EINA_LIST_FOREACH(event_mgr->obj_events, l, obj_event)
+     {
+        parent = obj_event->obj;
+        invisible = EINA_FALSE;
+
+        while (parent)
+          {
+             if (!evas_object_visible_get(parent))
+               {
+                  invisible = EINA_TRUE;
+                  break;
+               }
+             parent = evas_object_smart_parent_get(parent);
+          }
+        if (invisible) continue;
+        candidates = eina_list_append(candidates, obj_event);
+     }
+   if (!candidates) return NULL;   //no visible objects.
+   if (eina_list_count(candidates) == 1) goto found;
+
+   //2.1. sort by layer order
+   candidates = eina_list_sort(candidates, eina_list_count(candidates),
+                               _ea_layer_sort_cb);
+
+   //2.2. leave the only top layer
+   obj_event = eina_list_data_get(eina_list_last(candidates));
+   top_layer = evas_object_layer_get(obj_event->obj);
+
+   EINA_LIST_FOREACH_SAFE(candidates, l, l_next, obj_event)
+     {
+        if (evas_object_layer_get(obj_event->obj) < top_layer)
+          candidates = eina_list_remove_list(candidates, l);
+     }
+   if (eina_list_count(candidates) == 1) goto found;
+
+   //3. find the top parent candidate.
+   parent = _ea_top_parent_candidates(&candidates, event_mgr->e);
+   if (eina_list_count(candidates) == 1) goto found;
+
+   //4. find the target in this parent tree.
+   return _ea_find_event_target(candidates, parent);
+
+found:
+   obj_event = eina_list_data_get(candidates);
+   eina_list_free(candidates);
+   return obj_event;
+}
+
+static void
+_ea_key_grab_rect_key_up_cb(void *data, Evas *e, Evas_Object *obj,
+                            void *event_info)
+{
+   Evas_Event_Key_Down *ev = event_info;
+   Ea_Event_Mgr *event_mgr = data;
+   Ea_Object_Event *obj_event;
+   Ea_Event_Callback *callback;
+   Ea_Callback_Type type;
+   Eina_List *l;
+
+   obj_event = _ea_top_obj_event_find(event_mgr);
+   if (!obj_event) return;
+
+   if (!strcmp(ev->keyname, EA_KEY_BACK) || !strcmp(ev->keyname, EA_KEY_BACK2))
+     type = EA_CALLBACK_BACK;
+   else if (!strcmp(ev->keyname, EA_KEY_SEND))
+     type = EA_CALLBACK_MORE;
+
+   EINA_LIST_FOREACH(obj_event->callbacks, l, callback)
+     {
+        if (callback->type != type) continue;
+        callback->func(callback->data, obj_event->obj, (void*) type);
+     }
+}
+
+static void
+_ea_key_grab_obj_create(Ea_Event_Mgr *event_mgr)
+{
+   Evas_Object *key_grab_rect = evas_object_rectangle_add(event_mgr->e);
+
+   evas_object_event_callback_add(key_grab_rect, EVAS_CALLBACK_KEY_UP,
+                                  _ea_key_grab_rect_key_up_cb, event_mgr);
+   if (!evas_object_key_grab(key_grab_rect, EA_KEY_BACK, 0, 0, EINA_FALSE))
+     CRITICAL("Failed to grab END KEY\n");
+
+   if (!evas_object_key_grab(key_grab_rect, EA_KEY_BACK2, 0, 0, EINA_FALSE))
+     CRITICAL("Failed to grab END KEY\n");
+
+   if (!evas_object_key_grab(key_grab_rect, EA_KEY_SEND, 0, 0, EINA_FALSE))
+     CRITICAL("Failed to grab MORE KEY\n");
+   event_mgr->key_grab_rect = key_grab_rect;
+}
+
+static Ea_Event_Mgr *
+_ea_event_mgr_new(Evas *e)
+{
+   Ea_Event_Mgr *event_mgr = calloc(1, sizeof(Ea_Event_Mgr));
+   if (!event_mgr)
+     {
+        ERR("Failed to allocate event manager");
+        return NULL;
+     }
+   event_mgr->e = e;
+   _ea_key_grab_obj_create(event_mgr);
+
+   return event_mgr;
+}
+
+void
+ea_event_mgr_clear(Ea_Event_Mgr *event_mgr)
+{
+   Ea_Object_Event *obj_event;
+   Ea_Event_Callback *callback;
+   Eina_List *l, *l2;
+
+   //Remove Object Events
+   EINA_LIST_FOREACH(event_mgr->obj_events, l, obj_event)
+     {
+        evas_object_event_callback_del(obj_event->obj, EVAS_CALLBACK_DEL,
+                                       _ea_object_del_cb);
+        //Remove Callbacks
+        EINA_LIST_FOREACH(obj_event->callbacks, l2, callback)
+           free(callback);
+        obj_event->callbacks = eina_list_free(obj_event->callbacks);
+
+        free(obj_event);
+     }
+   event_mgr->obj_events = eina_list_free(event_mgr->obj_events);
+
+   evas_object_del(event_mgr->key_grab_rect);
+
+   free(event_mgr);
+}
+
+EAPI void *
+ea_object_event_callback_del(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb func)
+{
+   Ea_Object_Event *obj_event;
+   Ea_Event_Mgr *event_mgr;
+   Eina_List *l;
+   Ea_Event_Callback *callback;
+   void *data;
+
+   //Check the validation
+   event_mgr = evas_object_data_get(obj, EA_OBJ_KEY_EVENT_MGR);
+   obj_event = evas_object_data_get(obj, EA_OBJ_KEY_OBJ_EVENT);
+
+   if (!event_mgr || !obj_event)
+     {
+        WRN("This object(%p) hasn't been registered before", obj);
+        return NULL;
+     }
+
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _ea_object_del_cb);
+
+   //Remove the callback data
+   EINA_LIST_REVERSE_FOREACH(obj_event->callbacks, l, callback)
+     {
+        if ((callback->func == func) && (callback->type == type)) break;
+     }
+
+   data = callback->data;
+   obj_event->callbacks = eina_list_remove_list(obj_event->callbacks, l);
+   free(callback);
+
+   //This object is not managed anymore.
+   if (!obj_event->callbacks)
+     {
+        evas_object_data_set(obj, EA_OBJ_KEY_OBJ_EVENT, NULL);
+        evas_object_data_set(obj, EA_OBJ_KEY_EVENT_MGR, NULL);
+     }
+
+   _ea_event_mgr_del(event_mgr);
+
+   return data;
+}
+
+EAPI void
+ea_object_event_callback_add(Evas_Object *obj, Ea_Callback_Type type, Ea_Event_Cb func, void *data)
+{
+   Ea_Event_Mgr *event_mgr;
+   Evas *e;
+   Ea_Object_Event *obj_event = NULL;
+   Eina_List *l;
+   Ea_Event_Callback *callback;
+   Eina_Bool new_event_mgr = EINA_TRUE;
+
+   //Check the registered event manager for this Evas.
+   e = evas_object_evas_get(obj);
+
+   EINA_LIST_FOREACH(_ea.event_mgrs, l, event_mgr)
+     {
+        if (event_mgr->e == e)
+          {
+             new_event_mgr = EINA_FALSE;
+             break;
+          }
+     }
+
+   //New Evas comes. Create new event manager for this Evas.
+   if (new_event_mgr)
+     {
+        if (!(event_mgr = _ea_event_mgr_new(e))) return;
+        _ea.event_mgrs = eina_list_append(_ea.event_mgrs, event_mgr);
+     }
+
+   obj_event = evas_object_data_get(obj, EA_OBJ_KEY_OBJ_EVENT);
+
+   //New Object Event. Probably user adds ea_object_event_callback first time.
+   if (!obj_event)
+     {
+        obj_event = calloc(1, sizeof(Ea_Object_Event));
+        if (!obj_event)
+          {
+             ERR("Failed to allocate object event");
+             return;
+          }
+        evas_object_data_set(obj, EA_OBJ_KEY_OBJ_EVENT, obj_event);
+        evas_object_data_set(obj, EA_OBJ_KEY_EVENT_MGR, event_mgr);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                       _ea_object_del_cb,
+                                       obj_event);
+        event_mgr->obj_events = eina_list_append(event_mgr->obj_events,
+                                                 obj_event);
+        obj_event->obj = obj;
+     }
+
+   //Append this callback.
+   callback = calloc(1, sizeof(Ea_Event_Callback));
+   if (!callback)
+     {
+        ERR("Failed to allocate event callback");
+        return;
+     }
+   callback->type = type;
+   callback->func = func;
+   callback->data = data;
+
+   obj_event->callbacks = eina_list_append(obj_event->callbacks, callback);
+}