2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
22 * @brief EAIL initialization
29 #include <Elementary.h>
32 #include <atk-bridge.h>
35 #include "eail_priv.h"
36 #include "eail_clipboard.h"
38 /** @brief Struct definition for listener info*/
39 typedef struct _EailUtilListenerInfo EailUtilListenerInfo;
40 /** @brief Struct definition for event info*/
41 typedef struct _EailKeyEventInfo EailKeyEventInfo;
43 /** @brief Struct definition for listener info*/
44 struct _EailUtilListenerInfo
46 gint key; /**< @brief key of entry */
47 guint signal_id;/**< @brief id of the signal */
48 gulong hook_id;/**< @brief emit hook value returned on signal registration*/
51 /** @brief Struct definition for event info*/
52 struct _EailKeyEventInfo
54 AtkKeyEventStruct *key_event;/**< @brief key of event */
55 gpointer func_data;/**< @brief additional data passed to the event */
58 /** @brief Cache of objects used for listening and propagating signals */
59 static GHashTable *listener_list = NULL;
60 /** @brief Last added id of a listener */
61 static gint listener_idx = 1;
64 * @brief Domain index that will be used as the DOMAIN parameter on EINA log macros
66 * A negative value means a log occurred.
68 int _eail_log_dom = -1;
71 * @brief A variable for tracking the last focused AtkObject
73 static AtkObject *eail_atk_last_focused_obj = NULL;
76 * @brief Gets the name of the toolkit
77 * @return string representing the name of the toolkit
79 static const gchar * eail_get_toolkit_name(void)
85 * @brief Gets the version of the toolkit
87 * @return string representing the version of the toolkit
89 static const gchar * eail_get_toolkit_version(void)
91 return g_strdup(PACKAGE_VERSION);
95 * @brief Gets the accessible root container for the current application
97 * @return AtkObject representing the accessible root container
99 static AtkObject * eail_get_root(void)
101 static AtkObject *root = NULL;
105 root = g_object_new(EAIL_TYPE_APP, NULL);
106 atk_object_initialize(root, NULL);
113 * @brief Callback to be called when an object receives focus
115 * @param current_focused_obj AtkObject instance
118 eail_focus_listener_cb(AtkObject *current_focused_obj)
120 if (current_focused_obj == eail_atk_last_focused_obj)
123 if (eail_atk_last_focused_obj)
125 atk_object_notify_state_change
126 (eail_atk_last_focused_obj, ATK_STATE_FOCUSED, FALSE);
127 g_object_unref(eail_atk_last_focused_obj);
130 g_object_ref(current_focused_obj);
132 /* already notifying about focus in widget implementation so do not need
133 * to notify here for new focus*/
134 eail_atk_last_focused_obj = current_focused_obj;
138 * @brief Initializes object focus tracking
141 eail_app_focus_listener_init()
143 atk_add_focus_tracker(eail_focus_listener_cb);
147 * @brief Creates and adds a listener for the given object type
149 * @param listener GObject Emission Hook (a simple function pointer to get
150 * invoked when the signal is emitted)
151 * @param object_type name string representing object's type
152 * @param signal name string representing the signal to listen
153 * @param hook_data GObject 'hook' info
155 * @returns integer representing the id of the newly added listener
158 add_listener (GSignalEmissionHook listener,
159 const gchar *object_type,
161 const gchar *hook_data)
167 type = g_type_from_name (object_type);
170 signal_id = g_signal_lookup (signal, type);
173 EailUtilListenerInfo *listener_info;
177 listener_info = g_malloc(sizeof(EailUtilListenerInfo));
178 listener_info->key = listener_idx;
179 listener_info->hook_id =
180 g_signal_add_emission_hook (signal_id, 0, listener,
181 g_strdup (hook_data),
182 (GDestroyNotify) g_free);
183 listener_info->signal_id = signal_id;
185 g_hash_table_insert(listener_list, &(listener_info->key), listener_info);
190 DBG("Invalid signal type %s\n", signal);
195 DBG("Invalid object type %s\n", object_type);
201 * @brief Removes a listener for given object type
203 * @param remove_listener id of the listener to remove
206 eail_remove_global_event_listener (guint remove_listener)
208 if (remove_listener > 0)
210 EailUtilListenerInfo *listener_info;
211 gint tmp_idx = remove_listener;
213 listener_info = (EailUtilListenerInfo *)
214 g_hash_table_lookup(listener_list, &tmp_idx);
216 if (listener_info != NULL)
218 /* Hook id of 0 and signal id of 0 are invalid */
219 if (listener_info->hook_id != 0 && listener_info->signal_id != 0)
221 /* Remove the emission hook */
222 g_signal_remove_emission_hook(listener_info->signal_id,
223 listener_info->hook_id);
225 /* Remove the element from the hash */
226 g_hash_table_remove(listener_list, &tmp_idx);
230 DBG("Invalid listener hook_id %ld or signal_id %d\n",
231 listener_info->hook_id, listener_info->signal_id);
236 DBG("No listener with the specified listener id %d", remove_listener);
241 DBG("Invalid listener_id %d", remove_listener);
246 * @brief Initialization for global event listener
248 * @param listener GSignalEmissionHook (GObject 'signal invocation hint')
249 * @param event_type string representing the event's type
251 * @return integer representing the id of the added listener
254 eail_add_global_event_listener(GSignalEmissionHook listener,
255 const gchar *event_type)
258 gchar **split_string;
260 split_string = g_strsplit(event_type, ":", 3);
264 if (!strcmp("window", split_string[0]))
265 rc = add_listener /* window event handling */
266 (listener, "AtkWindow", split_string[1], event_type);
268 rc = add_listener /* regular event handling */
269 (listener, split_string[1], split_string[2], event_type);
271 g_strfreev(split_string);
278 * @brief Destructor for listener info object
280 * @param data data to be freed
283 eail_listener_info_destroy(gpointer data)
289 * @brief AtkUtil class initialization
291 static void atk_util_install(void)
293 AtkUtilClass *uclass;
295 uclass = ATK_UTIL_CLASS(g_type_class_ref(ATK_TYPE_UTIL));
296 uclass->get_toolkit_name = eail_get_toolkit_name;
297 uclass->get_toolkit_version = eail_get_toolkit_version;
298 uclass->get_root = eail_get_root;
300 eail_app_focus_listener_init();
302 uclass->add_global_event_listener = eail_add_global_event_listener;
303 uclass->remove_global_event_listener = eail_remove_global_event_listener;
304 uclass->add_key_event_listener = NULL;
305 uclass->remove_key_event_listener = NULL;
309 * @brief Function to be executed by Elementary when EAIL module is loaded
311 * @param m Elm_Module data
312 * @return 1 on success, 0 otherwise
315 elm_modapi_init(void *m)
317 static gboolean initialized = FALSE;
318 if (initialized) return 1;
320 _eail_log_dom = eina_log_domain_register("eail", EAIL_LOG_COLOR);
323 EINA_LOG_ERR("could not register eail log domain.");
324 _eail_log_dom = EINA_LOG_DOMAIN_GLOBAL;
327 if (!ecore_main_loop_glib_integrate())
329 ERR("Cannot integrate with glib main loop");
334 #if !GLIB_CHECK_VERSION(2,35,0)
337 listener_list = g_hash_table_new_full
338 (g_int_hash, g_int_equal, NULL, eail_listener_info_destroy);
342 atk_misc_instance = g_object_new(ATK_TYPE_MISC, NULL);
344 atk_bridge_adaptor_init(NULL, NULL);
350 * @brief Function to be executed by Elementary when EAIL module is unloaded
352 * @param m Elm_Module data
353 * @return always 1 - notifying success
356 elm_modapi_shutdown(void *m)
358 eail_clipboard_free();
360 if ((_eail_log_dom > -1) && (_eail_log_dom != EINA_LOG_DOMAIN_GLOBAL))
362 eina_log_domain_unregister(_eail_log_dom);