apply new active window rotation guide
[platform/core/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
29 #ifndef WAYLAND
30 #include <X11/Xatom.h>
31 #include <X11/Xutil.h>
32 #endif
33
34 #ifndef WAYLAND
35 static int __utilx_ss_get_window_property(Display *dpy, Window win, Atom atom,
36                                           Atom type, unsigned int *val,
37                                           unsigned int len)
38 {
39         unsigned char *prop_ret;
40         Atom type_ret;
41         unsigned long bytes_after;
42         unsigned long  num_ret;
43         int format_ret;
44         unsigned int i;
45         int num;
46
47         prop_ret = NULL;
48         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
49                                type, &type_ret, &format_ret, &num_ret,
50                                &bytes_after, &prop_ret) != Success)
51                 return -1;
52
53         if (type_ret != type || format_ret != 32)
54                 num = -1;
55         else if (num_ret == 0 || !prop_ret)
56                 num = 0;
57         else {
58                 if (num_ret < len)
59                         len = num_ret;
60                 for (i = 0; i < len; i++) {
61                         val[i] = ((unsigned long *)prop_ret)[i];
62                 }
63                 num = len;
64         }
65
66         if (prop_ret)
67                 XFree(prop_ret);
68
69         return num;
70 }
71 #endif
72
73 /*
74 static Window get_active_win(Display *dpy, Window win, Atom property)
75 {
76     Window active_win = None;
77     Atom actual_type;
78     int actual_format;
79     unsigned long nitems, bytes_after;
80     unsigned char *prop_return = NULL;
81
82     if(Success == XGetWindowProperty(dpy, win, property, 0L, sizeof(Window),
83                                      False, XA_WINDOW, &actual_type,
84                                      &actual_format, &nitems, &bytes_after,
85                                      &prop_return) && prop_return) {
86         active_win = *(Window *)prop_return;
87         XFree(prop_return);
88     }
89
90     return active_win;
91 }
92 */
93
94 static void __X_syspopup_term_handler(void *data)
95 {
96 #ifndef WAYLAND
97         syspopup *tmp;
98         syspopup *next;
99         Display *d;
100         Window win;
101
102         _D("enter syspopup term handler");
103
104         d = XOpenDisplay(NULL);
105         tmp = _syspopup_get_head();
106         while (tmp) {
107
108                 _D("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,
117                                                  tmp->user_data);
118                         XKillClient(d, win);
119                         /*XDestroyWindow(d, win);*/
120                         /* TODO :modify for multi popup */
121                         break;
122                 case SYSPOPUP_HIDE:
123                         win = (Window) tmp->internal_data;
124
125                         if (tmp->def_term_fn != NULL)
126                                 tmp->def_term_fn(tmp->dupped_bundle,
127                                                  tmp->user_data);
128                         XUnmapWindow(d, win);
129                         break;
130                 default:
131                         _D("term action IGNORED - %s", tmp->name);
132                 }
133                 tmp = next;
134         }
135
136         XCloseDisplay(d);
137         /*TODO : if there is no popup window, kill client*/
138 #endif
139 }
140
141 static gboolean __X_syspopup_timeout_handler(void *user_data)
142 {
143 #ifndef WAYLAND
144         syspopup *sp = NULL;
145         Display *d;
146         int id;
147         Window win;
148
149         id = (int)user_data;
150         d = XOpenDisplay(NULL);
151
152         sp = _syspopup_find_by_id(id);
153         if (sp != NULL) {
154                 _D("find timeout - %s", sp->name);
155                 if (sp->def_timeout_fn != NULL)
156                         sp->def_timeout_fn(sp->dupped_bundle, sp->user_data);
157                 win = (Window) sp->internal_data;
158                 XKillClient(d, win);
159         } else {
160                 _E("no find timeout");
161         }
162
163         XCloseDisplay(d);
164 #endif
165
166         return 0;
167 }
168
169 #ifndef WAYLAND
170 static int __X_syspopup_change_xwin_type(Display *dpy, Window win)
171 {
172         Atom win_type_atom;
173         Atom win_type_utility_atom;
174
175         win_type_atom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
176         win_type_utility_atom =
177             XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False);
178         XChangeProperty(dpy, win, win_type_atom, XA_ATOM, 32, PropModeReplace,
179                         (unsigned char *)&win_type_utility_atom, 1);
180
181         return 0;
182 }
183 #endif
184
185 #ifndef WAYLAND
186 static int __X_syspopup_disable_focus(Display *dpy, Window win)
187 {
188         XWMHints *hints;
189
190         hints = XAllocWMHints();
191         if (!hints) return -1;
192
193         hints->flags = InputHint | StateHint;
194         hints->input = 0;
195         hints->initial_state = NormalState;
196
197         XSetWMHints(dpy, win, hints);
198         XFree(hints);
199
200         return 0;
201 }
202 #endif
203
204 #ifndef WAYLAND
205 int X_syspopup_rotation_get(Display *dpy, Window win)
206 {
207         Window active_win;
208         Window root_win;
209         int rotation = -1;
210         int ret;
211
212         int angles[2];
213
214         Atom atom_active_win;
215         Atom atom_win_rotate_angle;
216
217         root_win = XDefaultRootWindow(dpy);
218
219         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
220         ret = __utilx_ss_get_window_property(dpy, root_win, atom_active_win,
221                                              XA_WINDOW,
222                                              (unsigned int *)&active_win, 1);
223
224         /*printf("[SYSPOPUP] Active win : %x, Window %x\n", active_win, win);*/
225
226         /*active_win = get_active_win(dpy, root_win, atom_active_win);*/
227         if (ret < 0)
228                 return ret;
229
230         atom_win_rotate_angle =
231                 XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
232         ret = __utilx_ss_get_window_property(dpy, root_win,
233                                           atom_win_rotate_angle, XA_CARDINAL,
234                                           (unsigned int *)&rotation, 1);
235
236         /*printf("[SYSPOPUP] Rotation %d\n", rotation);*/
237
238         if (ret != -1)
239                 return rotation;
240
241         return -1;
242 }
243 #endif
244
245 int X_syspopup_process_keydown(int id, const char *keyname)
246 {
247 #ifndef WAYLAND
248         Display *d;
249         Window win;
250         syspopup *sp = NULL;
251
252         if (strcmp(keyname, KEY_END) == 0) {
253                 d = XOpenDisplay(NULL);
254                 sp = _syspopup_find_by_id(id);
255                 if (sp != NULL) {
256                         _D("find key down - %s", sp->name);
257                         if (sp->endkey_act == SYSPOPUP_KEYEND_TERM) {
258                                 if (sp->def_term_fn != NULL)
259                                         sp->def_term_fn(sp->dupped_bundle,
260                                                         sp->user_data);
261                                 win = (Window) sp->internal_data;
262                                 XKillClient(d, win);
263
264                         } else if (sp->endkey_act == SYSPOPUP_KEYEND_HIDE) {
265                                 if (sp->def_term_fn != NULL)
266                                         sp->def_term_fn(sp->dupped_bundle,
267                                                         sp->user_data);
268                                 win = (Window) sp->internal_data;
269                                 XUnmapWindow(d, win);
270                         }
271
272                 } else {
273                         _E("no find key down");
274                 }
275
276                 XCloseDisplay(d);
277         }
278 #endif
279
280         return 0;
281 }
282
283 #ifdef ROTATE_USING_X_CLIENT
284 int X_syspopup_process_rotate(int id)
285 {
286 #ifndef WAYLAND
287         Display *d;
288         Window win;
289         syspopup *sp = NULL;
290
291         sp = _syspopup_find_by_id(id);
292
293         if (sp == NULL)
294                 return -1;
295
296         win = (Window) sp->internal_data;
297
298         d = XOpenDisplay(NULL);
299         sp->rotate_cb(d, win, sp);
300         XCloseDisplay(d);
301 #endif
302
303         return 0;
304 }
305 #endif
306
307 #ifndef WAYLAND
308 int X_make_syspopup(bundle *b, Display *dpy, Window xwin, void *win,
309                     int (*rotate_func) (Display*, Window, syspopup*),
310                     syspopup_handler *handler, void *user_data)
311 {
312         syspopup *sp = NULL;
313         syspopup_info_t *info;
314         const char *popup_name = _syspopup_get_name_from_bundle(b);
315         XWindowAttributes attr;
316         int is_unviewable = 0;
317
318         if (popup_name == NULL || handler == NULL)
319                 return -1;
320
321         info = _syspopup_info_get(popup_name);
322         if (info == NULL)
323                 return -1;
324
325         if (_syspopup_init(__X_syspopup_term_handler,
326                            __X_syspopup_timeout_handler) < 0){
327                 _syspopup_info_free(info);
328                 return -1;
329         }
330
331         XGetWindowAttributes(dpy, xwin, &attr);
332
333         if (attr.map_state == IsViewable) {
334                 XUnmapWindow(dpy, xwin);
335                 is_unviewable = 1;
336         }
337
338         sp = (syspopup *) malloc(sizeof(syspopup));
339         if (sp == NULL) {
340                 _syspopup_info_free(info);
341                 return -1;
342         }
343         
344         sp->name = strdup(info->name);
345         sp->def_term_fn = handler->def_term_fn;
346         sp->def_timeout_fn = handler->def_timeout_fn;
347         sp->user_data = user_data;
348         sp->internal_data = (void *)xwin;
349         sp->win = (void *)win;
350         sp->rotate_cb = rotate_func;
351         sp->timeout_id = 0;
352         sp->dupped_bundle = bundle_dup(b);
353         _syspopup_add_new(sp);
354
355         _syspopup_set_term_type(sp, info);
356         _syspopup_set_endkey_type(sp, info);
357
358         _syspopup_reset_timeout(sp, info);
359
360         __X_syspopup_change_xwin_type(dpy, xwin);
361         utilx_set_system_notification_level(dpy, xwin, info->prio);
362
363         utilx_grab_key(dpy, xwin, KEY_END, TOP_POSITION_GRAB);
364
365         if (info->focus == 1) {
366                 __X_syspopup_disable_focus (dpy, xwin);
367         }
368
369         rotate_func(dpy, xwin, sp);
370
371         if (is_unviewable == 1) {
372                 XMapWindow(dpy, xwin);
373         }
374
375         _syspopup_info_free(info);
376
377         return sp->id;
378 }
379 #endif
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 #ifndef WAYLAND
398         const char *popup_name;
399         syspopup_info_t *info;
400         syspopup *sp = NULL;
401         int (*rotate_func) (Display *, Window, syspopup *);
402
403         popup_name = _syspopup_get_name_from_bundle(b);
404         if (popup_name == NULL)
405                 return -1;
406
407         sp = _syspopup_find(popup_name);
408         if (!sp)
409                 return -1;
410         else {
411                 Display *d;
412                 Window win;
413
414                 info = _syspopup_info_get(popup_name);
415                 if (info == NULL)
416                         return -1;
417                 _syspopup_reset_timeout(sp, info);
418
419                 if (sp->dupped_bundle)
420                         free(sp->dupped_bundle);
421                 sp->dupped_bundle = bundle_dup(b);
422
423                 d = XOpenDisplay(NULL);
424                 win = (Window) sp->internal_data;
425                 utilx_set_system_notification_level(d, win, info->prio);
426
427                 if (info->focus == 1) {
428                         __X_syspopup_disable_focus (d, win);
429                 }
430                 rotate_func = sp->rotate_cb;
431                 rotate_func(d, win, sp);
432
433                 XMapWindow(d, win);
434                 /*XMapRaised(d,win);*/
435                 XCloseDisplay(d);
436
437                 _syspopup_info_free(info);
438         }
439 #endif
440
441         return 0;
442 }
443
444 API int syspopup_has_popup(bundle *b)
445 {
446         const char *popup_name;
447         popup_name = _syspopup_get_name_from_bundle(b);
448         if (popup_name == NULL)
449                 return 0;
450
451         if (_syspopup_find(popup_name) != NULL)
452                 return 1;
453         else
454                 return 0;
455 }
456
457 API int syspopup_reset_timeout(bundle *b, unsigned int time)
458 {
459         const char *popup_name;
460         syspopup_info_t *info;
461         syspopup *sp = NULL;
462         int ret;
463
464         popup_name = _syspopup_get_name_from_bundle(b);
465         if (popup_name == NULL) {
466                 _E("popup_name is null");
467                 return -1;
468         }
469
470         sp = _syspopup_find(popup_name);
471         if (!sp) {
472                 _E("find syspopup error");
473                 return -1;
474         } else {
475                 info = _syspopup_info_get(popup_name);
476                 if (info == NULL) {
477                         _E("get syspopup info error");
478                         return -1;
479                 }
480                 info->timeout = time;
481                 ret = _syspopup_reset_timeout(sp, info);
482                 _syspopup_info_free(info);
483         }
484
485         return ret;
486 }
487