2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #define LOG_TAG "TIZEN_N_EFL_UTIL"
24 #include <Elementary.h>
32 #include <Ecore_Wayland.h>
33 #include <wayland-client.h>
34 #include "tizen_notification-client-protocol.h"
37 typedef struct _notification_error_cb_info
40 efl_util_notification_window_level_error_cb err_cb;
42 } notification_error_cb_info;
44 Eina_List *_g_notification_error_cb_info_list;
45 static Ecore_Event_Handler* _noti_level_access_result_handler = NULL;
46 static int _noti_handler_count = 0;
48 static notification_error_cb_info *_notification_error_cb_info_find(Evas_Object *window);
49 static Eina_Bool _efl_util_notification_info_add(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data);
50 static Eina_Bool _efl_util_notification_info_del(Evas_Object *window);
53 static unsigned int _noti_level_access_result_atom = 0;
55 static Eina_Bool _efl_util_client_message(void *data, int type, void *event);
56 static notification_error_cb_info *_notification_error_cb_info_find_by_xwin(unsigned int xwin);
60 typedef struct _Surface_Level
62 struct wl_surface *surface;
64 Eina_Bool wait_set_level_done;
67 static void _cb_handle_registry_global(void *data, struct wl_registry *registry, unsigned int name, const char *interface, unsigned int version);
68 static void _cb_handle_registry_global_remove(void *data, struct wl_registry *registry, unsigned int name);
69 static void _notification_set_level_done(void *data, struct tizen_notification *tizen_notification, struct wl_surface *surface, int32_t level, uint32_t error_state);
70 static notification_error_cb_info *_notification_error_cb_info_find_by_wl_surface(struct wl_surface *surface);
72 static const struct wl_registry_listener _registry_listener =
74 _cb_handle_registry_global,
75 _cb_handle_registry_global_remove
78 struct tizen_notification_listener _tizen_notification_listener =
80 _notification_set_level_done,
83 static struct tizen_notification *_tizen_notification = NULL;
84 static Eina_Bool _efl_util_init_done = EINA_FALSE;
85 static Eina_Hash *hash_surface_levels = NULL;
88 _cb_handle_registry_global(void *data, struct wl_registry *registry, unsigned int name, const char *interface, unsigned int version)
90 if (!strcmp(interface, "tizen_notification"))
92 _tizen_notification = wl_registry_bind(registry, name, &tizen_notification_interface, 1);
93 if (!_tizen_notification) return;
94 tizen_notification_add_listener(_tizen_notification, &_tizen_notification_listener, NULL);
95 _efl_util_init_done = EINA_TRUE;
96 hash_surface_levels = eina_hash_pointer_new(free);
100 # define _FREE_FUNC(_h, _fn) do { if (_h) { _fn((void*)_h); _h = NULL; } } while (0)
102 _cb_handle_registry_global_remove(void *data, struct wl_registry *registry, unsigned int name)
104 _tizen_notification = NULL;
105 _efl_util_init_done = EINA_FALSE;
106 _FREE_FUNC(hash_surface_levels, eina_hash_free);
111 _notification_set_level_done(void *data,
112 struct tizen_notification *tizen_notification,
113 struct wl_surface *surface,
115 uint32_t error_state)
118 notification_error_cb_info *cb_info = NULL;
119 efl_util_error_e error_cb_state = EFL_UTIL_ERROR_NONE;
121 if (hash_surface_levels)
123 sl = eina_hash_find(hash_surface_levels, &surface);
127 sl->wait_set_level_done = EINA_FALSE;
131 cb_info = _notification_error_cb_info_find_by_wl_surface(surface);
136 case TIZEN_NOTIFICATION_ERROR_STATE_NONE:
137 error_cb_state = EFL_UTIL_ERROR_NONE;
139 case TIZEN_NOTIFICATION_ERROR_STATE_PERMISSION_DENIED:
141 error_cb_state = EFL_UTIL_ERROR_PERMISSION_DENIED;
145 cb_info->err_cb(cb_info->window, error_cb_state , cb_info->user_data);
150 _efl_util_wl_init(void)
152 static Eina_Bool init = EINA_FALSE;
155 wl_registry_add_listener(wl_display_get_registry(ecore_wl_display_get()),
156 &_registry_listener, NULL);
159 while (!_efl_util_init_done)
160 wl_display_dispatch(ecore_wl_display_get());
165 efl_util_set_notification_window_level(Evas_Object *window, efl_util_notification_level_e level)
167 EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
168 EINA_SAFETY_ON_FALSE_RETURN_VAL((level >= EFL_UTIL_NOTIFICATION_LEVEL_1) &&
169 (level <= EFL_UTIL_NOTIFICATION_LEVEL_TOP),
170 EFL_UTIL_ERROR_INVALID_PARAMETER);
173 Ecore_X_Window xwin = elm_win_xwindow_get(window);
176 Ecore_X_Window_Type window_type;
177 if(ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
179 // success to get window type
180 if(window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
182 // given EFL window's type is not notification type.
183 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
187 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
189 utilx_set_system_notification_level(ecore_x_display_get(), xwin,
191 return EFL_UTIL_ERROR_NONE;
196 Ecore_Wl_Window *wl_win = elm_win_wl_window_get(window);
201 if (hash_surface_levels)
204 struct wl_surface *surface = ecore_wl_window_surface_get(wl_win);
205 sl = eina_hash_find(hash_surface_levels, &surface);
208 sl = calloc(1, sizeof(Surface_Level));
211 sl->surface = surface;
212 sl->level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
213 sl->wait_set_level_done = EINA_TRUE;
214 eina_hash_add(hash_surface_levels, &surface, sl);
219 sl->wait_set_level_done = EINA_TRUE;
223 //Add notification window type check
224 tizen_notification_set_level(_tizen_notification,
225 ecore_wl_window_surface_get(wl_win),
227 return EFL_UTIL_ERROR_NONE;
231 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
235 efl_util_get_notification_window_level(Evas_Object *window, efl_util_notification_level_e *level)
238 EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
239 EINA_SAFETY_ON_NULL_RETURN_VAL(level, EFL_UTIL_ERROR_INVALID_PARAMETER);
242 Ecore_X_Window_Type window_type;
243 Utilx_Notification_Level utilx_level;
244 Ecore_X_Window xwin = elm_win_xwindow_get(window);
247 if(ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
249 // success to get window type
250 if(window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
252 // given EFL window's type is not notification type.
253 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
256 utilx_level = utilx_get_system_notification_level (ecore_x_display_get(), xwin);
258 if(utilx_level == UTILX_NOTIFICATION_LEVEL_LOW)
260 *level = EFL_UTIL_NOTIFICATION_LEVEL_1;
262 else if(utilx_level == UTILX_NOTIFICATION_LEVEL_NORMAL)
264 *level = EFL_UTIL_NOTIFICATION_LEVEL_2;
266 else if(utilx_level == UTILX_NOTIFICATION_LEVEL_HIGH)
268 *level = EFL_UTIL_NOTIFICATION_LEVEL_3;
272 return EFL_UTIL_ERROR_INVALID_PARAMETER;
278 // fail to get window type
279 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
282 return EFL_UTIL_ERROR_NONE;
287 Ecore_Wl_Window *wl_win = elm_win_wl_window_get(window);
291 struct wl_surface *surface = ecore_wl_window_surface_get(wl_win);
293 sl = eina_hash_find(hash_surface_levels, &surface);
296 if (sl->wait_set_level_done)
298 if (ecore_wl_window_shell_surface_get(wl_win) ||
299 ecore_wl_window_xdg_surface_get(wl_win))
301 while (sl->wait_set_level_done)
304 wl_display_dispatch(ecore_wl_display_get());
309 *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
310 return EFL_UTIL_ERROR_INVALID_PARAMETER;
316 case TIZEN_NOTIFICATION_LEVEL_1:
317 *level = EFL_UTIL_NOTIFICATION_LEVEL_1;
319 case TIZEN_NOTIFICATION_LEVEL_2:
320 *level = EFL_UTIL_NOTIFICATION_LEVEL_2;
322 case TIZEN_NOTIFICATION_LEVEL_3:
323 *level = EFL_UTIL_NOTIFICATION_LEVEL_3;
325 case TIZEN_NOTIFICATION_LEVEL_NONE:
326 *level = EFL_UTIL_NOTIFICATION_LEVEL_NONE;
328 case TIZEN_NOTIFICATION_LEVEL_DEFAULT:
329 *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
331 case TIZEN_NOTIFICATION_LEVEL_MEDIUM:
332 *level = EFL_UTIL_NOTIFICATION_LEVEL_MEDIUM;
334 case TIZEN_NOTIFICATION_LEVEL_HIGH:
335 *level = EFL_UTIL_NOTIFICATION_LEVEL_HIGH;
337 case TIZEN_NOTIFICATION_LEVEL_TOP:
338 *level = EFL_UTIL_NOTIFICATION_LEVEL_TOP;
341 *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
342 return EFL_UTIL_ERROR_INVALID_PARAMETER;
344 return EFL_UTIL_ERROR_NONE;
348 *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
352 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
356 efl_util_set_notification_window_level_error_cb(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data)
358 Eina_Bool ret = EINA_FALSE;
360 EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
361 EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
363 ret = _efl_util_notification_info_add(window, callback, user_data);
367 if (!_noti_level_access_result_atom)
368 _noti_level_access_result_atom = ecore_x_atom_get("_E_NOTIFICATION_LEVEL_ACCESS_RESULT");
370 if (!_noti_level_access_result_handler)
371 _noti_level_access_result_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _efl_util_client_message, NULL);
372 _noti_handler_count++;
374 return EFL_UTIL_ERROR_NONE;
378 return EFL_UTIL_ERROR_NONE;
381 return EFL_UTIL_ERROR_OUT_OF_MEMORY;
385 efl_util_unset_notification_window_level_error_cb(Evas_Object *window)
387 Eina_Bool ret = EINA_FALSE;
389 EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
391 ret = _efl_util_notification_info_del(window);
394 _noti_handler_count--;
395 if (_noti_handler_count == 0)
397 if (_noti_level_access_result_handler)
399 ecore_event_handler_del(_noti_level_access_result_handler);
400 _noti_level_access_result_handler = NULL;
403 return EFL_UTIL_ERROR_NONE;
406 return EFL_UTIL_ERROR_INVALID_PARAMETER;
411 _efl_util_client_message(void *data, int type, void *event)
413 Ecore_X_Event_Client_Message *ev;
416 if (!ev) return ECORE_CALLBACK_PASS_ON;
418 if (ev->message_type == _noti_level_access_result_atom)
423 notification_error_cb_info *cb_info = NULL;
424 cb_info = _notification_error_cb_info_find_by_xwin(xwin);
427 int access = ev->data.l[1];
428 if (access == 0) // permission denied
432 cb_info->err_cb(cb_info->window, EFL_UTIL_ERROR_PERMISSION_DENIED, cb_info->user_data);
438 return ECORE_CALLBACK_PASS_ON;
441 static notification_error_cb_info *
442 _notification_error_cb_info_find_by_xwin(unsigned int xwin)
445 notification_error_cb_info* temp;
446 unsigned int temp_xwin;
448 EINA_LIST_FOREACH(_g_notification_error_cb_info_list, l, temp)
452 temp_xwin = elm_win_xwindow_get(temp->window);
453 if (xwin == temp_xwin)
465 static notification_error_cb_info *
466 _notification_error_cb_info_find_by_wl_surface(struct wl_surface *surface)
469 notification_error_cb_info* temp;
470 struct wl_surface *temp_surface;
472 EINA_LIST_FOREACH(_g_notification_error_cb_info_list, l, temp)
476 temp_surface = ecore_wl_window_surface_get(elm_win_wl_window_get(temp->window));
477 if (surface == temp_surface)
488 static notification_error_cb_info *
489 _notification_error_cb_info_find(Evas_Object *window)
492 notification_error_cb_info* temp;
494 EINA_LIST_FOREACH(_g_notification_error_cb_info_list, l, temp)
496 if (temp->window == window)
506 _efl_util_notification_info_add(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data)
508 notification_error_cb_info* _err_info = _notification_error_cb_info_find(window);
512 _g_notification_error_cb_info_list = eina_list_remove(_g_notification_error_cb_info_list, _err_info);
517 _err_info = (notification_error_cb_info*)calloc(1, sizeof(notification_error_cb_info));
522 _err_info->window = window;
523 _err_info->err_cb = callback;
524 _err_info->user_data = user_data;
526 _g_notification_error_cb_info_list = eina_list_append(_g_notification_error_cb_info_list, _err_info);
532 _efl_util_notification_info_del(Evas_Object *window)
534 notification_error_cb_info* _err_info = _notification_error_cb_info_find(window);
540 _g_notification_error_cb_info_list = eina_list_remove(_g_notification_error_cb_info_list, _err_info);