Add support for callback to check whether application can be accepted to show on...
[platform/core/api/efl-util.git] / src / efl_util.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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. 
15  */
16
17
18 #define LOG_TAG "TIZEN_N_EFL_UTIL"
19
20 #include <efl_util.h>
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <Elementary.h>
26
27 #if ECORE_X_FOUND
28 #include <Ecore_X.h>
29 #include <utilX.h>
30 #endif
31
32 typedef struct _notification_error_cb_info
33 {
34         Evas_Object *window;
35         efl_util_notification_window_level_error_cb err_cb;
36         void *user_data;
37 } notification_error_cb_info;
38
39 Eina_List *_g_notification_error_cb_info_list;
40 static Ecore_Event_Handler* _noti_level_access_result_handler = NULL;
41 static int _noti_handler_count = 0;
42 static unsigned int _noti_level_access_result_atom = 0;
43
44 static Eina_Bool _efl_util_client_message(void *data, int type, void *event);
45 static notification_error_cb_info *_notification_error_cb_info_find(Evas_Object *window);
46 static notification_error_cb_info *_notification_error_cb_info_find_by_xwin(unsigned int xwin);
47 static Eina_Bool _efl_util_notification_info_add(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data);
48 static Eina_Bool _efl_util_notification_info_del(Evas_Object *window);
49
50
51 int efl_util_set_notification_window_level (Evas_Object* window, efl_util_notification_level_e level)
52 {
53         EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
54         EINA_SAFETY_ON_FALSE_RETURN_VAL(level >= EFL_UTIL_NOTIFICATION_LEVEL_1 &&
55                                         level <= EFL_UTIL_NOTIFICATION_LEVEL_3,
56                                         EFL_UTIL_ERROR_INVALID_PARAMETER);
57
58 #if ECORE_X_FOUND
59         Ecore_X_Window xwin = elm_win_xwindow_get(window);
60         if (xwin)
61         {
62                 Ecore_X_Window_Type window_type;
63                 if(ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
64                 {
65                         // success to get window type
66                         if(window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
67                         {
68                                 // given EFL window's type is not notification type.
69                                 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
70                         }
71                 }
72                 else
73                         return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
74
75                 utilx_set_system_notification_level(ecore_x_display_get(), xwin,
76                                                     level);
77                 return EFL_UTIL_ERROR_NONE;
78         }
79 #endif
80
81 #if ECORE_WAYLAND_FOUND
82         Ecore_Wl_Window wl_win = elm_win_wl_window_get(window);
83         if (wl_win)
84         {
85                 printf("not implemented for wayland yet\n");
86                 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
87         }
88 #endif
89
90        return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
91 }
92
93
94
95 int efl_util_get_notification_window_level (Evas_Object* window, efl_util_notification_level_e* level)
96 {
97         
98         EINA_SAFETY_ON_NULL_RETURN_VAL(window,
99                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
100         EINA_SAFETY_ON_NULL_RETURN_VAL(level,
101                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
102
103 #if ECORE_X_FOUND
104         Ecore_X_Window_Type window_type;
105         Utilx_Notification_Level utilx_level;
106         Ecore_X_Window xwin = elm_win_xwindow_get(window);
107         if (xwin)
108         {
109                 if(ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
110                 {
111                         // success to get window type
112                         if(window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
113                         {
114                                 // given EFL window's type is not notification type.
115                                 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
116                         }
117                 
118                         utilx_level = utilx_get_system_notification_level (ecore_x_display_get(), xwin);
119
120                         if(utilx_level == UTILX_NOTIFICATION_LEVEL_LOW)
121                         {
122                                 *level = EFL_UTIL_NOTIFICATION_LEVEL_1;
123                         }
124                         else if(utilx_level == UTILX_NOTIFICATION_LEVEL_NORMAL)
125                         {
126                                 *level = EFL_UTIL_NOTIFICATION_LEVEL_2;
127                         }
128                         else if(utilx_level == UTILX_NOTIFICATION_LEVEL_HIGH)
129                         {
130                                 *level = EFL_UTIL_NOTIFICATION_LEVEL_3;
131                         }
132                         else
133                         {
134                                 return EFL_UTIL_ERROR_INVALID_PARAMETER;
135                         }
136                 
137                 }
138                 else
139                 {
140                         // fail to get window type
141                         return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
142                 }
143         
144                 return EFL_UTIL_ERROR_NONE;
145         }
146 #endif
147
148 #if ECORE_WAYLAND_FOUND
149         Ecore_Wl_Window wl_win = elm_win_wl_window_get(window);
150         if (wl_win)
151         {
152                 printf("not implemented for wayland yet\n");
153                 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
154         }
155 #endif
156         return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
157 }
158
159 int efl_util_set_notification_window_level_error_cb(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data)
160 {
161         Eina_Bool ret = EINA_FALSE;
162
163         EINA_SAFETY_ON_NULL_RETURN_VAL(window,
164                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
165         EINA_SAFETY_ON_NULL_RETURN_VAL(callback,
166                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
167
168         ret = _efl_util_notification_info_add(window, callback, user_data);
169         if (ret)
170         {
171 #if ECORE_X_FOUND
172                 if (!_noti_level_access_result_atom)
173                         _noti_level_access_result_atom = ecore_x_atom_get("_E_NOTIFICATION_LEVEL_ACCESS_RESULT");
174
175                 if (!_noti_level_access_result_handler)
176                         _noti_level_access_result_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _efl_util_client_message, NULL);
177                 _noti_handler_count++;
178
179                 return EFL_UTIL_ERROR_NONE;
180 #endif
181
182 #if ECORE_WAYLAND_FOUND
183                 printf("not implemented for wayland yet\n");
184                 return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
185 #endif
186         }
187
188         return EFL_UTIL_ERROR_OUT_OF_MEMORY;
189 }
190
191 int efl_util_unset_notification_window_level_error_cb(Evas_Object *window)
192 {
193         Eina_Bool ret = EINA_FALSE;
194
195         EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
196
197         ret = _efl_util_notification_info_del(window);
198         if (ret)
199         {
200                 _noti_handler_count--;
201                 if (_noti_handler_count == 0)
202                 {
203                         if (_noti_level_access_result_handler)
204                         {
205                                 ecore_event_handler_del(_noti_level_access_result_handler);
206                                 _noti_level_access_result_handler = NULL;
207                         }
208                 }
209                 return EFL_UTIL_ERROR_NONE;
210         }
211
212         return EFL_UTIL_ERROR_INVALID_PARAMETER;
213 }
214
215 int efl_util_grab_key (Evas_Object *obj, const char* key, int grab_mode)
216 {
217         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0);
218
219 #if ECORE_X_FOUND
220         Ecore_X_Window x_win;
221         Ecore_X_Display *x_disp;
222
223         x_win = elm_win_xwindow_get(obj);
224         if (x_win)
225         {
226                 x_disp = ecore_x_display_get();
227                 return utilx_grab_key(x_disp, x_win, key, grab_mode);
228         }
229
230 #endif
231
232 #if ECORE_WAYLAND_FOUND
233         Ecore_Wl_Window wl_win = elm_win_wl_window_get(obj);
234         if (wl_win)
235         {
236                 printf("not implemented for wayland yet\n");
237                 return 0;
238         }
239 #endif
240
241         return 0;
242 }
243
244 int efl_util_ungrab_key (Evas_Object *obj, const char* key)
245 {
246         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0);
247
248 #if ECORE_X_FOUND
249         Ecore_X_Window x_win;
250         Ecore_X_Display *x_disp;
251
252         x_win = elm_win_xwindow_get(obj);
253         if (x_win)
254         {
255                 x_disp = ecore_x_display_get();
256                 return utilx_ungrab_key (x_disp, x_win, key);
257         }
258 #endif
259
260 #if ECORE_WAYLAND_FOUND
261         Ecore_Wl_Window wl_win = elm_win_wl_window_get(obj);
262         if (wl_win)
263         {
264                 printf("not implemented for wayland yet\n");
265                 return 0;
266         }
267 #endif
268
269         return 0;
270 }
271
272 void efl_util_set_system_notification_level (Evas_Object *obj, Efl_Util_Notification_Level level)
273 {
274         EINA_SAFETY_ON_NULL_RETURN(obj);
275         EINA_SAFETY_ON_FALSE_RETURN(level >= EFL_UTIL_NOTIFICATION_LEVEL_LOW &&
276                                     level <= EFL_UTIL_NOTIFICATION_LEVEL_UNKNOWN);
277
278 #if ECORE_X_FOUND
279         Ecore_X_Window x_win;
280         Ecore_X_Display *x_disp;
281
282         x_win = elm_win_xwindow_get(obj);
283         if (x_win)
284         {
285                 x_disp = ecore_x_display_get();
286                 utilx_set_system_notification_level(x_disp, x_win, level);
287                 return;
288         }
289 #endif
290
291 #if ECORE_WAYLAND_FOUND
292         Ecore_Wl_Window wl_win = elm_win_wl_window_get(obj);
293         if (wl_win)
294         {
295                 printf("not implemented for wayland yet\n");
296         }
297 #endif
298 }
299
300 Efl_Util_Notification_Level efl_util_get_system_notification_level (Evas_Object *obj)
301 {
302         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EFL_UTIL_NOTIFICATION_LEVEL_UNKNOWN);
303
304 #if ECORE_X_FOUND
305         Ecore_X_Window x_win;
306         Ecore_X_Display *x_disp;
307
308         x_win = elm_win_xwindow_get(obj);
309         if (x_win)
310         {
311                 x_disp = ecore_x_display_get();
312                 return utilx_get_system_notification_level(x_disp, x_win);
313         }
314
315 #endif
316
317 #if ECORE_WAYLAND_FOUND
318         Ecore_Wl_Window wl_win = elm_win_wl_window_get(obj);
319         if (wl_win)
320         {
321                 printf("not implemented for wayland yet\n");
322                 return EFL_UTIL_NOTIFICATION_LEVEL_UNKNOWN;
323         }
324 #endif
325
326         return EFL_UTIL_NOTIFICATION_LEVEL_UNKNOWN;
327 }
328
329 void efl_util_netwm_window_type_set(Evas_Object *obj, Efl_Util_Window_Type type)
330 {
331         EINA_SAFETY_ON_NULL_RETURN(obj);
332         EINA_SAFETY_ON_FALSE_RETURN(type == EFL_UTIL_WINDOW_TYPE_NORMAL ||
333                                     type == EFL_UTIL_WINDOW_TYPE_NOTIFICATION);
334
335 #if ECORE_X_FOUND
336         Ecore_X_Window x_win;
337
338         x_win = elm_win_xwindow_get(obj);
339         if (x_win)
340         {
341                 ecore_x_netwm_window_type_set(x_win, type);
342                 return;
343         }
344
345 #endif
346
347 #if ECORE_WAYLAND_FOUND
348         Ecore_Wl_Window wl_win = elm_win_wl_window_get(obj);
349         if (wl_win)
350                 printf("not implemented for wayland yet\n");
351 #endif
352 }
353
354 void efl_util_set_window_effect_style(Evas_Object *win, Efl_Util_Effect_Type type, Efl_Util_Effect_Style style)
355 {
356
357         EINA_SAFETY_ON_NULL_RETURN(win);
358
359 #if ECORE_X_FOUND
360         Ecore_X_Window x_win;
361         Ecore_X_Display *x_disp;
362
363         x_win = elm_win_xwindow_get(win);
364         if (x_win)
365         {
366                 x_disp = ecore_x_display_get();
367                 utilx_set_window_effect_style(x_disp, x_win, type, style);
368                 return;
369         }
370 #endif
371
372 #if ECORE_WAYLAND_FOUND
373         Ecore_Wl_Window wl_win = elm_win_wl_window_get(win);
374         if (wl_win)
375                 printf("not implemented for wayland yet\n");
376 #endif
377 }
378
379 int efl_util_set_window_opaque_state (Evas_Object *win, Efl_Util_Opaque_State state)
380 {
381    EINA_SAFETY_ON_NULL_RETURN_VAL(win, 0);
382
383 #if ECORE_X_FOUND
384         Ecore_X_Window x_win;
385         Ecore_X_Display *x_disp;
386
387         x_win = elm_win_xwindow_get(win);
388         if (x_win)
389         {
390                 x_disp = ecore_x_display_get();
391                 return utilx_set_window_opaque_state(x_disp, x_win, state);
392         }
393 #endif
394
395 #if ECORE_WAYLAND_FOUND
396         Ecore_Wl_Window wl_win = elm_win_wl_window_get(win);
397         if (wl_win)
398                 printf("not implemented for wayland yet\n");
399 #endif
400
401         return 0;
402 }
403
404 static Eina_Bool _efl_util_client_message(void *data, int type, void *event)
405 {
406 #if ECORE_X_FOUND
407         Ecore_X_Event_Client_Message *ev;
408
409         ev = event;
410         if (!ev) return ECORE_CALLBACK_PASS_ON;
411
412         if (ev->message_type == _noti_level_access_result_atom)
413         {
414                 Ecore_X_Window xwin;
415                 xwin = ev->win;
416
417                 notification_error_cb_info *cb_info = NULL;
418                 cb_info = _notification_error_cb_info_find_by_xwin(xwin);
419                 if (cb_info)
420                 {
421                         int access = ev->data.l[1];
422                         if (access == 0) // permission denied
423                         {
424                                 if (cb_info->err_cb)
425                                 {
426                                         cb_info->err_cb(cb_info->window, EFL_UTIL_ERROR_PERMISSION_DENIED, cb_info->user_data);
427                                 }
428                         }
429                 }
430         }
431 #endif
432
433         return ECORE_CALLBACK_PASS_ON;
434 }
435
436 static notification_error_cb_info *_notification_error_cb_info_find_by_xwin(unsigned int xwin)
437 {
438         Eina_List *l;
439         notification_error_cb_info* temp;
440         unsigned int temp_xwin;
441
442         EINA_LIST_FOREACH(_g_notification_error_cb_info_list, l, temp)
443         {
444                 if (temp->window)
445                 {
446                         temp_xwin = elm_win_xwindow_get(temp->window);
447                         if (xwin == temp_xwin)
448                         {
449                                 return temp;
450                         }
451                 }
452         }
453
454         return NULL;
455 }
456
457 static notification_error_cb_info *_notification_error_cb_info_find(Evas_Object *window)
458 {
459         Eina_List *l;
460         notification_error_cb_info* temp;
461
462         EINA_LIST_FOREACH(_g_notification_error_cb_info_list, l, temp)
463         {
464                 if (temp->window == window)
465                 {
466                         return temp;
467                 }
468         }
469
470         return NULL;
471 }
472
473 static Eina_Bool _efl_util_notification_info_add(Evas_Object *window, efl_util_notification_window_level_error_cb callback, void *user_data)
474 {
475         notification_error_cb_info* _err_info = _notification_error_cb_info_find(window);
476
477         if (_err_info)
478         {
479                 _g_notification_error_cb_info_list = eina_list_remove(_g_notification_error_cb_info_list, _err_info);
480                 free(_err_info);
481                 _err_info = NULL;
482         }
483
484         _err_info = (notification_error_cb_info*)calloc(1, sizeof(notification_error_cb_info));
485         if (!_err_info)
486         {
487                 return EINA_FALSE;
488         }
489         _err_info->window = window;
490         _err_info->err_cb = callback;
491         _err_info->user_data = user_data;
492
493         _g_notification_error_cb_info_list = eina_list_append(_g_notification_error_cb_info_list, _err_info);
494
495         return EINA_TRUE;
496 }
497
498 static Eina_Bool _efl_util_notification_info_del(Evas_Object *window)
499 {
500         notification_error_cb_info* _err_info = _notification_error_cb_info_find(window);
501         if (!_err_info)
502         {
503                 return EINA_FALSE;
504         }
505
506         _g_notification_error_cb_info_list = eina_list_remove(_g_notification_error_cb_info_list, _err_info);
507         free(_err_info);
508
509         return EINA_TRUE;
510 }