tizen 2.4 release
[framework/base/syspopup.git] / syspopup / syspopup.c
1 /*
2  * syspopup
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23
24 #include "syspopup_core.h"
25 #include "syspopup.h"
26 #include "syspopup_api.h"
27 #include "simple_util.h"
28 #include <X11/Xatom.h>
29 #include <X11/Xutil.h>
30
31 #define WIN_PROP_NAME "SYSTEM_POPUP"
32
33 static int __utilx_ss_get_window_property(Display *dpy, Window win, Atom atom,
34                                           Atom type, unsigned int *val,
35                                           unsigned int len)
36 {
37         unsigned char *prop_ret;
38         Atom type_ret;
39         unsigned long bytes_after;
40         unsigned long  num_ret;
41         int format_ret;
42         unsigned int i;
43         int num;
44
45         prop_ret = NULL;
46         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
47                                type, &type_ret, &format_ret, &num_ret,
48                                &bytes_after, &prop_ret) != Success)
49                 return -1;
50
51         if (type_ret != type || format_ret != 32)
52                 num = -1;
53         else if (num_ret == 0 || !prop_ret)
54                 num = 0;
55         else {
56                 if (num_ret < len)
57                         len = num_ret;
58                 for (i = 0; i < len; i++) {
59                         val[i] = ((unsigned long *)prop_ret)[i];
60                 }
61                 num = len;
62         }
63
64         if (prop_ret)
65                 XFree(prop_ret);
66
67         return num;
68 }
69
70 /*
71 static Window get_active_win(Display *dpy, Window win, Atom property)
72 {
73     Window active_win = None;
74     Atom actual_type;
75     int actual_format;
76     unsigned long nitems, bytes_after;
77     unsigned char *prop_return = NULL;
78
79     if(Success == XGetWindowProperty(dpy, win, property, 0L, sizeof(Window),
80                                      False, XA_WINDOW, &actual_type,
81                                      &actual_format, &nitems, &bytes_after,
82                                      &prop_return) && prop_return) {
83         active_win = *(Window *)prop_return;
84         XFree(prop_return);
85     }
86
87     return active_win;
88 }
89 */
90
91 static void __X_syspopup_term_handler(void *data)
92 {
93         syspopup *tmp;
94         syspopup *next;
95         Display *d = NULL;
96         Window win;
97
98         _I("enter syspopup term handler");
99
100         d = XOpenDisplay(NULL);
101         if(!d){
102                 _E("XOpenDisplay return null");
103         }
104
105         tmp = _syspopup_get_head();
106         while (tmp) {
107
108                 _I("term action %d - %s", tmp->term_act, tmp->name);
109                 next = tmp->next;
110
111                 switch (tmp->term_act) {
112                 case SYSPOPUP_TERM:
113                         win = (Window) tmp->internal_data;
114
115                         if (tmp->def_term_fn != NULL)
116                                 tmp->def_term_fn(tmp->dupped_bundle, tmp->user_data);
117
118                         if(d) XKillClient(d, win);
119                         break;
120                 case SYSPOPUP_HIDE:
121                         win = (Window) tmp->internal_data;
122
123                         if (tmp->def_term_fn != NULL)
124                                 tmp->def_term_fn(tmp->dupped_bundle, tmp->user_data);
125
126                         if(d) XUnmapWindow(d, win);
127                         break;
128                 default:
129                         _I("term action IGNORED - %s", tmp->name);
130                 }
131                 tmp = next;
132         }
133
134         if(d) XCloseDisplay(d);
135 }
136
137 static gboolean __X_syspopup_timeout_handler(void *user_data)
138 {
139         syspopup *sp = NULL;
140         Display *d;
141         int id;
142         Window win;
143
144         id = (int)user_data;
145
146         d = XOpenDisplay(NULL);
147
148         sp = _syspopup_find_by_id(id);
149         if (sp != NULL) {
150                 _D("find timeout - %s", sp->name);
151                 if (sp->def_timeout_fn != NULL)
152                         sp->def_timeout_fn(sp->dupped_bundle, sp->user_data);
153                 win = (Window) sp->internal_data;
154                 XKillClient(d, win);
155         } else {
156                 _E("no find timeout");
157         }
158
159         XCloseDisplay(d);
160
161         return 0;
162 }
163
164 static int __X_syspopup_change_xwin_type(Display *dpy, Window win)
165 {
166         Atom win_type_atom;
167         Atom win_type_utility_atom;
168
169         win_type_atom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
170         win_type_utility_atom =
171             XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False);
172         XChangeProperty(dpy, win, win_type_atom, XA_ATOM, 32, PropModeReplace,
173                         (unsigned char *)&win_type_utility_atom, 1);
174
175         return 0;
176 }
177
178 static int __X_syspopup_disable_focus(Display *dpy, Window win)
179 {
180         XWMHints *hints;
181
182         hints = XAllocWMHints();
183         if (!hints) return -1;
184
185         hints->flags = InputHint | StateHint;
186         hints->input = 0;
187         hints->initial_state = NormalState;
188
189         XSetWMHints(dpy, win, hints);
190         XFree(hints);
191
192         return 0;
193 }
194
195 int X_syspopup_rotation_get(Display *dpy, Window win)
196 {
197         Window active_win;
198         Window root_win;
199         int rotation = -1;
200         int ret;
201
202         Atom atom_active_win;
203         Atom atom_win_rotate_angle;
204
205         root_win = XDefaultRootWindow(dpy);
206
207         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
208         ret = __utilx_ss_get_window_property(dpy, root_win, atom_active_win,
209                                              XA_WINDOW,
210                                              (unsigned int *)&active_win, 1);
211
212         /*printf("[SYSPOPUP] Active win : %x, Window %x\n", active_win, win);*/
213
214         /*active_win = get_active_win(dpy, root_win, atom_active_win);*/
215         if (ret < 0)
216                 return ret;
217
218         atom_win_rotate_angle =
219                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
220         ret = __utilx_ss_get_window_property(dpy, root_win,
221                                           atom_win_rotate_angle, XA_CARDINAL,
222                                           (unsigned int *)&rotation, 1);
223
224         /*printf("[SYSPOPUP] Rotation %d\n", rotation);*/
225
226         if (ret != -1)
227                 return rotation;
228
229         return -1;
230 }
231
232 int X_syspopup_process_keydown(int id, const char *keyname)
233 {
234         Display *d;
235         Window win;
236         syspopup *sp = NULL;
237
238         if (strcmp(keyname, KEY_END) == 0) {
239                 d = XOpenDisplay(NULL);
240                 sp = _syspopup_find_by_id(id);
241                 if (sp != NULL) {
242                         _D("find key down - %s", sp->name);
243                         if (sp->endkey_act == SYSPOPUP_KEYEND_TERM) {
244                                 if (sp->def_term_fn != NULL)
245                                         sp->def_term_fn(sp->dupped_bundle,
246                                                         sp->user_data);
247                                 win = (Window) sp->internal_data;
248                                 XKillClient(d, win);
249
250                         } else if (sp->endkey_act == SYSPOPUP_KEYEND_HIDE) {
251                                 if (sp->def_term_fn != NULL)
252                                         sp->def_term_fn(sp->dupped_bundle,
253                                                         sp->user_data);
254                                 win = (Window) sp->internal_data;
255                                 XUnmapWindow(d, win);
256                         }
257
258                 } else {
259                         _E("no find key down");
260                 }
261
262                 XCloseDisplay(d);
263         }
264
265         return 0;
266 }
267
268 #ifdef ROTATE_USING_X_CLIENT
269 int X_syspopup_process_rotate(int id)
270 {
271         Display *d;
272         Window win;
273         syspopup *sp = NULL;
274
275         sp = _syspopup_find_by_id(id);
276
277         if (sp == NULL)
278                 return -1;
279
280         win = (Window) sp->internal_data;
281
282         d = XOpenDisplay(NULL);
283         sp->rotate_cb(d, win, sp);
284         XCloseDisplay(d);
285
286         return 0;
287 }
288 #else
289 static void __efl_rotation_set(Evas_Object* win, Ecore_X_Window xwin)
290 {
291         ecore_x_icccm_name_class_set(xwin, WIN_PROP_NAME, WIN_PROP_NAME);
292         if (elm_win_wm_rotation_supported_get(win)) {
293                 int rots[4] = { 0, 90, 180, 270 };
294                 elm_win_wm_rotation_available_rotations_set(win, (const int*)(&rots), 4);
295         } else {
296                 _E("win rotation no supported");
297         }
298 }
299 #endif
300
301 int X_make_syspopup(bundle *b, Display *dpy, Window xwin, void *win,
302                     int (*rotate_func) (Display*, Window, syspopup*),
303                     syspopup_handler *handler, void *user_data)
304 {
305         syspopup *sp = NULL;
306         syspopup_info_t *info;
307         const char *popup_name = _syspopup_get_name_from_bundle(b);
308         XWindowAttributes attr;
309         int is_unviewable = 0;
310
311         if (popup_name == NULL || handler == NULL)
312                 return -1;
313
314         info = _syspopup_info_get(popup_name);
315         if (info == NULL)
316                 return -1;
317
318         if (_syspopup_init(__X_syspopup_term_handler,
319                            __X_syspopup_timeout_handler) < 0){
320                 _syspopup_info_free(info);
321                 return -1;
322         }
323
324         XGetWindowAttributes(dpy, xwin, &attr);
325
326         if (attr.map_state == IsViewable) {
327                 XUnmapWindow(dpy, xwin);
328                 is_unviewable = 1;
329         }
330
331         sp = (syspopup *) malloc(sizeof(syspopup));
332         if (sp == NULL) {
333                 _syspopup_info_free(info);
334                 return -1;
335         }
336         
337         sp->name = strdup(info->name);
338         sp->def_term_fn = handler->def_term_fn;
339         sp->def_timeout_fn = handler->def_timeout_fn;
340         sp->user_data = user_data;
341         sp->internal_data = (void *)xwin;
342         sp->win = (void *)win;
343         sp->rotate_cb = rotate_func;
344         sp->timeout_id = 0;
345         sp->dupped_bundle = bundle_dup(b);
346         _syspopup_add_new(sp);
347
348         _syspopup_set_term_type(sp, info);
349         _syspopup_set_endkey_type(sp, info);
350
351         _syspopup_reset_timeout(sp, info);
352
353         __X_syspopup_change_xwin_type(dpy, xwin);
354         utilx_set_system_notification_level(dpy, xwin, info->prio);
355
356         if (info->focus == 1) {
357                 __X_syspopup_disable_focus (dpy, xwin);
358         }
359
360 #ifdef ROTATE_USING_X_CLIENT
361         rotate_func(dpy, xwin, sp);
362 #else
363         __efl_rotation_set((Evas_Object* )win,(Ecore_X_Window)xwin);
364 #endif
365
366         if (is_unviewable == 1) {
367                 XMapWindow(dpy, xwin);
368         }
369
370         _syspopup_info_free(info);
371
372         return sp->id;
373 }
374
375 /**
376  * @brief       This API reset created the system popup's properties
377  *
378  *              This API reset created the system popup's properties based on
379  *              system popup information DB after extracting popup name from 
380  *              given bundle system popup properties to be reset : timeout, 
381  *              default action type, ....
382  *
383  * @param[in]   b               bundle received by app_reset handler
384  *                              (included system popup name)
385  * @return      0 if success, negative value(<0) if fail
386  * @retval      0               - success
387  * @retval      -1              - generic error
388  */
389 int X_syspopup_reset(bundle *b)
390 {
391         const char *popup_name;
392         syspopup_info_t *info;
393         syspopup *sp = NULL;
394
395         popup_name = _syspopup_get_name_from_bundle(b);
396         if (popup_name == NULL)
397                 return -1;
398
399         sp = _syspopup_find(popup_name);
400         if (!sp)
401                 return -1;
402         else {
403                 Display *d;
404                 Window win;
405
406                 info = _syspopup_info_get(popup_name);
407                 if (info == NULL)
408                         return -1;
409                 _syspopup_reset_timeout(sp, info);
410
411                 if (sp->dupped_bundle)
412                         free(sp->dupped_bundle);
413                 sp->dupped_bundle = bundle_dup(b);
414
415                 do {
416                         d = XOpenDisplay(NULL);
417                         win = (Window) sp->internal_data;
418                         if((!d) || (!win)) {
419                                 _E("X open is null");
420                                 break;
421                         }
422                         utilx_set_system_notification_level(d, win, info->prio);
423
424                         if (info->focus == 1) {
425                                 __X_syspopup_disable_focus (d, win);
426                         }
427
428 #ifdef ROTATE_USING_X_CLIENT
429                         int (*rotate_func) (Display *, Window, syspopup *);
430                         rotate_func = sp->rotate_cb;
431                         rotate_func(d, win, sp);
432 #else
433                         __efl_rotation_set((Evas_Object *)sp->win, (Ecore_X_Window)win);
434 #endif
435                         XMapWindow(d, win);
436                         /*XMapRaised(d,win);*/
437                         XCloseDisplay(d);
438                 } while (0);
439
440                 _syspopup_info_free(info);
441         }
442         return 0;
443 }
444
445 API int syspopup_has_popup(bundle *b)
446 {
447         const char *popup_name;
448         popup_name = _syspopup_get_name_from_bundle(b);
449         if (popup_name == NULL)
450                 return 0;
451
452         if (_syspopup_find(popup_name) != NULL)
453                 return 1;
454         else
455                 return 0;
456 }
457
458 API int syspopup_reset_timeout(bundle *b, unsigned int time)
459 {
460         const char *popup_name;
461         syspopup_info_t *info;
462         syspopup *sp = NULL;
463         int ret;
464
465         popup_name = _syspopup_get_name_from_bundle(b);
466         if (popup_name == NULL) {
467                 _E("popup_name is null");
468                 return -1;
469         }
470
471         sp = _syspopup_find(popup_name);
472         if (!sp) {
473                 _E("find syspopup error");
474                 return -1;
475         } else {
476                 info = _syspopup_info_get(popup_name);
477                 if (info == NULL) {
478                         _E("get syspopup info error");
479                         return -1;
480                 }
481                 info->timeout = time;
482                 ret = _syspopup_reset_timeout(sp, info);
483                 _syspopup_info_free(info);
484         }
485
486         return ret;
487 }
488