tizen 2.3 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         int angles[2];
203
204         Atom atom_active_win;
205         Atom atom_win_rotate_angle;
206
207         root_win = XDefaultRootWindow(dpy);
208
209         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
210         ret = __utilx_ss_get_window_property(dpy, root_win, atom_active_win,
211                                              XA_WINDOW,
212                                              (unsigned int *)&active_win, 1);
213
214         /*printf("[SYSPOPUP] Active win : %x, Window %x\n", active_win, win);*/
215
216         /*active_win = get_active_win(dpy, root_win, atom_active_win);*/
217         if (ret < 0)
218                 return ret;
219
220         atom_win_rotate_angle =
221                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
222         ret = __utilx_ss_get_window_property(dpy, root_win,
223                                           atom_win_rotate_angle, XA_CARDINAL,
224                                           (unsigned int *)&rotation, 1);
225
226         /*printf("[SYSPOPUP] Rotation %d\n", rotation);*/
227
228         if (ret != -1)
229                 return rotation;
230
231         return -1;
232 }
233
234 int X_syspopup_process_keydown(int id, const char *keyname)
235 {
236         Display *d;
237         Window win;
238         syspopup *sp = NULL;
239
240         if (strcmp(keyname, KEY_END) == 0) {
241                 d = XOpenDisplay(NULL);
242                 sp = _syspopup_find_by_id(id);
243                 if (sp != NULL) {
244                         _D("find key down - %s", sp->name);
245                         if (sp->endkey_act == SYSPOPUP_KEYEND_TERM) {
246                                 if (sp->def_term_fn != NULL)
247                                         sp->def_term_fn(sp->dupped_bundle,
248                                                         sp->user_data);
249                                 win = (Window) sp->internal_data;
250                                 XKillClient(d, win);
251
252                         } else if (sp->endkey_act == SYSPOPUP_KEYEND_HIDE) {
253                                 if (sp->def_term_fn != NULL)
254                                         sp->def_term_fn(sp->dupped_bundle,
255                                                         sp->user_data);
256                                 win = (Window) sp->internal_data;
257                                 XUnmapWindow(d, win);
258                         }
259
260                 } else {
261                         _E("no find key down");
262                 }
263
264                 XCloseDisplay(d);
265         }
266
267         return 0;
268 }
269
270 #ifdef ROTATE_USING_X_CLIENT
271 int X_syspopup_process_rotate(int id)
272 {
273         Display *d;
274         Window win;
275         syspopup *sp = NULL;
276
277         sp = _syspopup_find_by_id(id);
278
279         if (sp == NULL)
280                 return -1;
281
282         win = (Window) sp->internal_data;
283
284         d = XOpenDisplay(NULL);
285         sp->rotate_cb(d, win, sp);
286         XCloseDisplay(d);
287
288         return 0;
289 }
290 #else
291 static void __efl_rotation_set(Evas_Object* win, Ecore_X_Window xwin)
292 {
293         ecore_x_icccm_name_class_set(xwin, WIN_PROP_NAME, WIN_PROP_NAME);
294         if (elm_win_wm_rotation_supported_get(win)) {
295                 int rots[4] = { 0, 90, 180, 270 };
296                 elm_win_wm_rotation_available_rotations_set(win, &rots, 4);
297         } else {
298                 _E("win rotation no supported");
299         }
300 }
301 #endif
302
303 int X_make_syspopup(bundle *b, Display *dpy, Window xwin, void *win,
304                     int (*rotate_func) (Display*, Window, syspopup*),
305                     syspopup_handler *handler, void *user_data)
306 {
307         syspopup *sp = NULL;
308         syspopup_info_t *info;
309         const char *popup_name = _syspopup_get_name_from_bundle(b);
310         XWindowAttributes attr;
311         int is_unviewable = 0;
312
313         if (popup_name == NULL || handler == NULL)
314                 return -1;
315
316         info = _syspopup_info_get(popup_name);
317         if (info == NULL)
318                 return -1;
319
320         if (_syspopup_init(__X_syspopup_term_handler,
321                            __X_syspopup_timeout_handler) < 0){
322                 _syspopup_info_free(info);
323                 return -1;
324         }
325
326         XGetWindowAttributes(dpy, xwin, &attr);
327
328         if (attr.map_state == IsViewable) {
329                 XUnmapWindow(dpy, xwin);
330                 is_unviewable = 1;
331         }
332
333         sp = (syspopup *) malloc(sizeof(syspopup));
334         if (sp == NULL) {
335                 _syspopup_info_free(info);
336                 return -1;
337         }
338         
339         sp->name = strdup(info->name);
340         sp->def_term_fn = handler->def_term_fn;
341         sp->def_timeout_fn = handler->def_timeout_fn;
342         sp->user_data = user_data;
343         sp->internal_data = (void *)xwin;
344         sp->win = (void *)win;
345         sp->rotate_cb = rotate_func;
346         sp->timeout_id = 0;
347         sp->dupped_bundle = bundle_dup(b);
348         _syspopup_add_new(sp);
349
350         _syspopup_set_term_type(sp, info);
351         _syspopup_set_endkey_type(sp, info);
352
353         _syspopup_reset_timeout(sp, info);
354
355         __X_syspopup_change_xwin_type(dpy, xwin);
356         utilx_set_system_notification_level(dpy, xwin, info->prio);
357
358         if (info->focus == 1) {
359                 __X_syspopup_disable_focus (dpy, xwin);
360         }
361
362 #ifdef ROTATE_USING_X_CLIENT
363         rotate_func(dpy, xwin, sp);
364 #else
365         __efl_rotation_set((Evas_Object* )win,(Ecore_X_Window)xwin);
366 #endif
367
368         if (is_unviewable == 1) {
369                 XMapWindow(dpy, xwin);
370         }
371
372         _syspopup_info_free(info);
373
374         return sp->id;
375 }
376
377 /**
378  * @brief       This API reset created the system popup's properties
379  *
380  *              This API reset created the system popup's properties based on
381  *              system popup information DB after extracting popup name from 
382  *              given bundle system popup properties to be reset : timeout, 
383  *              default action type, ....
384  *
385  * @param[in]   b               bundle received by app_reset handler
386  *                              (included system popup name)
387  * @return      0 if success, negative value(<0) if fail
388  * @retval      0               - success
389  * @retval      -1              - generic error
390  */
391 int X_syspopup_reset(bundle *b)
392 {
393         const char *popup_name;
394         syspopup_info_t *info;
395         syspopup *sp = NULL;
396
397         popup_name = _syspopup_get_name_from_bundle(b);
398         if (popup_name == NULL)
399                 return -1;
400
401         sp = _syspopup_find(popup_name);
402         if (!sp)
403                 return -1;
404         else {
405                 Display *d;
406                 Window win;
407
408                 info = _syspopup_info_get(popup_name);
409                 if (info == NULL)
410                         return -1;
411                 _syspopup_reset_timeout(sp, info);
412
413                 if (sp->dupped_bundle)
414                         free(sp->dupped_bundle);
415                 sp->dupped_bundle = bundle_dup(b);
416
417                 do {
418                         d = XOpenDisplay(NULL);
419                         win = (Window) sp->internal_data;
420                         if((!d) || (!win)) {
421                                 _E("X open is null");
422                                 break;
423                         }
424                         utilx_set_system_notification_level(d, win, info->prio);
425
426                         if (info->focus == 1) {
427                                 __X_syspopup_disable_focus (d, win);
428                         }
429
430 #ifdef ROTATE_USING_X_CLIENT
431                         int (*rotate_func) (Display *, Window, syspopup *);
432                         rotate_func = sp->rotate_cb;
433                         rotate_func(d, win, sp);
434 #else
435                         __efl_rotation_set((Evas_Object *)sp->win, (Ecore_X_Window)win);
436 #endif
437                         XMapWindow(d, win);
438                         /*XMapRaised(d,win);*/
439                         XCloseDisplay(d);
440                 } while (0);
441
442                 _syspopup_info_free(info);
443         }
444         return 0;
445 }
446
447 API int syspopup_has_popup(bundle *b)
448 {
449         const char *popup_name;
450         popup_name = _syspopup_get_name_from_bundle(b);
451         if (popup_name == NULL)
452                 return 0;
453
454         if (_syspopup_find(popup_name) != NULL)
455                 return 1;
456         else
457                 return 0;
458 }
459
460 API int syspopup_reset_timeout(bundle *b, unsigned int time)
461 {
462         const char *popup_name;
463         syspopup_info_t *info;
464         syspopup *sp = NULL;
465         int ret;
466
467         popup_name = _syspopup_get_name_from_bundle(b);
468         if (popup_name == NULL) {
469                 _E("popup_name is null");
470                 return -1;
471         }
472
473         sp = _syspopup_find(popup_name);
474         if (!sp) {
475                 _E("find syspopup error");
476                 return -1;
477         } else {
478                 info = _syspopup_info_get(popup_name);
479                 if (info == NULL) {
480                         _E("get syspopup info error");
481                         return -1;
482                 }
483                 info->timeout = time;
484                 ret = _syspopup_reset_timeout(sp, info);
485                 _syspopup_info_free(info);
486         }
487
488         return ret;
489 }
490