Initialize Tizen 2.3
[framework/base/syspopup.git] / mobile / 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;
96         Window win;
97
98         _D("enter syspopup term handler");
99
100         d = XOpenDisplay(NULL);
101         tmp = _syspopup_get_head();
102         while (tmp) {
103
104                 _D("term action %d - %s", tmp->term_act, tmp->name);
105                 next = tmp->next;
106
107                 switch (tmp->term_act) {
108                 case SYSPOPUP_TERM:
109                         win = (Window) tmp->internal_data;
110
111                         if (tmp->def_term_fn != NULL)
112                                 tmp->def_term_fn(tmp->dupped_bundle,
113                                                  tmp->user_data);
114                         XKillClient(d, win);
115                         /*XDestroyWindow(d, win);*/
116                         /* TODO :modify for multi popup */
117                         break;
118                 case SYSPOPUP_HIDE:
119                         win = (Window) tmp->internal_data;
120
121                         if (tmp->def_term_fn != NULL)
122                                 tmp->def_term_fn(tmp->dupped_bundle,
123                                                  tmp->user_data);
124                         XUnmapWindow(d, win);
125                         break;
126                 default:
127                         _D("term action IGNORED - %s", tmp->name);
128                 }
129                 tmp = next;
130         }
131
132         XCloseDisplay(d);
133         /*TODO : if there is no popup window, kill client*/
134 }
135
136 static gboolean __X_syspopup_timeout_handler(void *user_data)
137 {
138         syspopup *sp = NULL;
139         Display *d;
140         int id;
141         Window win;
142
143         id = (int)user_data;
144
145         d = XOpenDisplay(NULL);
146
147         sp = _syspopup_find_by_id(id);
148         if (sp != NULL) {
149                 _D("find timeout - %s", sp->name);
150                 if (sp->def_timeout_fn != NULL)
151                         sp->def_timeout_fn(sp->dupped_bundle, sp->user_data);
152                 win = (Window) sp->internal_data;
153                 XKillClient(d, win);
154         } else {
155                 _E("no find timeout");
156         }
157
158         XCloseDisplay(d);
159
160         return 0;
161 }
162
163 static int __X_syspopup_change_xwin_type(Display *dpy, Window win)
164 {
165         Atom win_type_atom;
166         Atom win_type_utility_atom;
167
168         win_type_atom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
169         win_type_utility_atom =
170             XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False);
171         XChangeProperty(dpy, win, win_type_atom, XA_ATOM, 32, PropModeReplace,
172                         (unsigned char *)&win_type_utility_atom, 1);
173
174         return 0;
175 }
176
177 static int __X_syspopup_disable_focus(Display *dpy, Window win)
178 {
179         XWMHints *hints;
180
181         hints = XAllocWMHints();
182         if (!hints) return -1;
183
184         hints->flags = InputHint | StateHint;
185         hints->input = 0;
186         hints->initial_state = NormalState;
187
188         XSetWMHints(dpy, win, hints);
189         XFree(hints);
190
191         return 0;
192 }
193
194 int X_syspopup_rotation_get(Display *dpy, Window win)
195 {
196         Window active_win;
197         Window root_win;
198         int rotation = -1;
199         int ret;
200
201         int angles[2];
202
203         Atom atom_active_win;
204         Atom atom_win_rotate_angle;
205
206         root_win = XDefaultRootWindow(dpy);
207
208         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
209         ret = __utilx_ss_get_window_property(dpy, root_win, atom_active_win,
210                                              XA_WINDOW,
211                                              (unsigned int *)&active_win, 1);
212
213         /*printf("[SYSPOPUP] Active win : %x, Window %x\n", active_win, win);*/
214
215         /*active_win = get_active_win(dpy, root_win, atom_active_win);*/
216         if (ret < 0)
217                 return ret;
218
219         atom_win_rotate_angle =
220                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
221         ret = __utilx_ss_get_window_property(dpy, root_win,
222                                           atom_win_rotate_angle, XA_CARDINAL,
223                                           (unsigned int *)&rotation, 1);
224
225         /*printf("[SYSPOPUP] Rotation %d\n", rotation);*/
226
227         if (ret != -1)
228                 return rotation;
229
230         return -1;
231 }
232
233 int X_syspopup_process_keypress(int id, const char *keyname)
234 {
235         Display *d;
236         Window win;
237         syspopup *sp = NULL;
238
239         _D("key press - %s", keyname);
240
241         if ((strcmp(keyname, KEY_END) == 0) ||
242                 (strcmp(keyname, "Escape") == 0))
243         {
244                 d = XOpenDisplay(NULL);
245                 sp = _syspopup_find_by_id(id);
246                 if (sp != NULL) {
247                         _D("find - %s / endkey_act - %d", sp->name, sp->endkey_act);
248                         if (sp->endkey_act == SYSPOPUP_KEYEND_TERM) {
249                                 if (sp->def_term_fn != NULL)
250                                         sp->def_term_fn(sp->dupped_bundle,
251                                                         sp->user_data);
252                                 win = (Window) sp->internal_data;
253                                 XKillClient(d, win);
254
255                         } else if (sp->endkey_act == SYSPOPUP_KEYEND_HIDE) {
256                                 if (sp->def_term_fn != NULL)
257                                         sp->def_term_fn(sp->dupped_bundle,
258                                                         sp->user_data);
259                                 win = (Window) sp->internal_data;
260                                 XUnmapWindow(d, win);
261                         }
262                 } else {
263                         _E("no find key down");
264                 }
265
266                 XCloseDisplay(d);
267         }
268
269         return 0;
270 }
271
272 #ifdef ROTATE_USING_X_CLIENT
273 int X_syspopup_process_rotate(int id)
274 {
275         Display *d;
276         Window win;
277         syspopup *sp = NULL;
278
279         sp = _syspopup_find_by_id(id);
280
281         if (sp == NULL)
282                 return -1;
283
284         win = (Window) sp->internal_data;
285
286         d = XOpenDisplay(NULL);
287         sp->rotate_cb(d, win, sp);
288         XCloseDisplay(d);
289
290         return 0;
291 }
292 #else
293 static void __efl_rotation_set(Evas_Object* win, Ecore_X_Window xwin)
294 {
295         ecore_x_icccm_name_class_set(xwin, WIN_PROP_NAME, WIN_PROP_NAME);
296         if (elm_win_wm_rotation_supported_get(win)) {
297                 int rots[4] = { 0, 90, 180, 270 };
298                 elm_win_wm_rotation_available_rotations_set(win, &rots, 4);
299         } else {
300                 _E("win rotation no supported");
301         }
302 }
303 #endif
304
305 int X_make_syspopup(bundle *b, Display *dpy, Window xwin, void *win,
306                     int (*rotate_func) (Display*, Window, syspopup*),
307                     syspopup_handler *handler, void *user_data)
308 {
309         syspopup *sp = NULL;
310         syspopup_info_t *info;
311         const char *popup_name = _syspopup_get_name_from_bundle(b);
312         XWindowAttributes attr;
313         int is_unviewable = 0;
314
315         if (popup_name == NULL || handler == NULL)
316                 return -1;
317
318         info = _syspopup_info_get(popup_name);
319         if (info == NULL)
320                 return -1;
321
322         if (_syspopup_init(__X_syspopup_term_handler,
323                            __X_syspopup_timeout_handler) < 0){
324                 _syspopup_info_free(info);
325                 return -1;
326         }
327
328         XGetWindowAttributes(dpy, xwin, &attr);
329
330         if (attr.map_state == IsViewable) {
331                 XUnmapWindow(dpy, xwin);
332                 is_unviewable = 1;
333         }
334
335         sp = (syspopup *) malloc(sizeof(syspopup));
336         if (sp == NULL) {
337                 _syspopup_info_free(info);
338                 return -1;
339         }
340
341         sp->name = strdup(info->name);
342         sp->def_term_fn = handler->def_term_fn;
343         sp->def_timeout_fn = handler->def_timeout_fn;
344         sp->user_data = user_data;
345         sp->internal_data = (void *)xwin;
346         sp->win = (void *)win;
347         sp->rotate_cb = rotate_func;
348         sp->timeout_id = 0;
349         sp->dupped_bundle = bundle_dup(b);
350         _syspopup_add_new(sp);
351
352         _syspopup_set_term_type(sp, info);
353         _syspopup_set_endkey_type(sp, info);
354
355         _syspopup_reset_timeout(sp, info);
356
357         __X_syspopup_change_xwin_type(dpy, xwin);
358         utilx_set_system_notification_level(dpy, xwin, info->prio);
359
360         utilx_grab_key(dpy, xwin, KEY_END, TOP_POSITION_GRAB);
361
362         if (info->focus == 1) {
363                 __X_syspopup_disable_focus (dpy, xwin);
364         }
365
366 #ifdef ROTATE_USING_X_CLIENT
367         rotate_func(dpy, xwin, sp);
368 #else
369         __efl_rotation_set((Evas_Object* )win,(Ecore_X_Window)xwin);
370 #endif
371
372         if (is_unviewable == 1) {
373                 XMapWindow(dpy, xwin);
374         }
375
376         _syspopup_info_free(info);
377
378         return sp->id;
379 }
380
381 /**
382  * @brief       This API reset created the system popup's properties
383  *
384  *              This API reset created the system popup's properties based on
385  *              system popup information DB after extracting popup name from
386  *              given bundle system popup properties to be reset : timeout,
387  *              default action type, ....
388  *
389  * @param[in]   b               bundle received by app_reset handler
390  *                              (included system popup name)
391  * @return      0 if success, negative value(<0) if fail
392  * @retval      0               - success
393  * @retval      -1              - generic error
394  */
395 int X_syspopup_reset(bundle *b)
396 {
397         const char *popup_name;
398         syspopup_info_t *info;
399         syspopup *sp = NULL;
400
401         popup_name = _syspopup_get_name_from_bundle(b);
402         if (popup_name == NULL)
403                 return -1;
404
405         sp = _syspopup_find(popup_name);
406         if (!sp)
407                 return -1;
408         else {
409                 Display *d;
410                 Window win;
411
412                 info = _syspopup_info_get(popup_name);
413                 if (info == NULL)
414                         return -1;
415                 _syspopup_reset_timeout(sp, info);
416
417                 if (sp->dupped_bundle)
418                         free(sp->dupped_bundle);
419                 sp->dupped_bundle = bundle_dup(b);
420
421                 d = XOpenDisplay(NULL);
422                 win = (Window) sp->internal_data;
423                 utilx_set_system_notification_level(d, win, info->prio);
424
425                 if (info->focus == 1) {
426                         __X_syspopup_disable_focus (d, win);
427                 }
428
429 #ifdef ROTATE_USING_X_CLIENT
430                 int (*rotate_func) (Display *, Window, syspopup *);
431                 rotate_func = sp->rotate_cb;
432                 rotate_func(d, win, sp);
433 #else
434                 __efl_rotation_set((Evas_Object *)sp->win, (Ecore_X_Window)win);
435 #endif
436                 XMapWindow(d, win);
437                 /*XMapRaised(d,win);*/
438                 XCloseDisplay(d);
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