Fix bug in dead timer cb
[apps/native/starter.git] / src / mobile / window_mgr.c
1 /*
2  * Copyright (c) 2000 - 2015 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 #include <Elementary.h>
18 #include <vconf.h>
19 #include <bundle.h>
20 #include <appcore-efl.h>
21 #include <app.h>
22
23 #ifdef HAVE_X11
24 #include <Ecore_X.h>
25 #include <utilX.h>
26 #include <ui-gadget.h>
27 #endif
28
29 #include "window_mgr.h"
30 #include "util.h"
31 #include "lock_pwd_util.h"
32
33 #define STR_ATOM_PANEL_SCROLLABLE_STATE         "_E_MOVE_PANEL_SCROLLABLE_STATE"
34
35
36
37 #ifdef HAVE_X11
38 struct _lockw_data {
39         Eina_Bool is_registered;
40         Ecore_X_Window lock_x_window;
41
42         Ecore_Event_Handler *h_wincreate;
43         Ecore_Event_Handler *h_winshow;
44         Ecore_Event_Handler *h_winhide;
45 };
46
47
48
49 static int _is_on_screen(Ecore_X_Display * dpy, Ecore_X_Window window)
50 {
51         Ecore_X_Window root;
52         Window child;
53         Window win;
54
55         int rel_x = 0;
56         int rel_y = 0;
57         int abs_x = 0;
58         int abs_y = 0;
59
60         unsigned int width = 0;
61         unsigned int height = 0;
62         unsigned int border = 0;
63         unsigned int depth = 0;
64         unsigned int root_w = 0;
65         unsigned int root_h = 0;
66
67         Eina_Bool ret = FALSE;
68
69         root = ecore_x_window_root_first_get();
70         XGetGeometry(dpy, root, &win, &rel_x, &rel_y, &root_w, &root_h, &border, &depth);
71         _D("root rel_x[%d] rel_y[%d] border[%d] width[%d] height[%d]", rel_x, rel_y, border, root_w, root_h);
72
73         if (XGetGeometry(dpy, window, &win, &rel_x, &rel_y, &width, &height, &border, &depth)) {
74                 if (XTranslateCoordinates(dpy, window, root, 0, 0, &abs_x, &abs_y, &child)) {
75                     _D("abs_x[%d] abs_y[%d] border[%d] width[%d] height[%d]", abs_x, abs_y, border, width, height);
76                         if ((abs_x - border) >= root_w
77                                 || (abs_y - border) >= root_h
78                             || (width + abs_x) <= 0 || (height + abs_y) <= 0)
79                         {
80                                 ret = FALSE;
81                         } else {
82                                 ret = (width == root_w) && (height == root_h);
83                         }
84                 }
85         }
86
87         return ret;
88 }
89
90
91
92 static Window _get_user_created_window(Window win)
93 {
94         Atom type_ret = 0;
95         int ret, size_ret = 0;
96         unsigned long num_ret = 0, bytes = 0;
97         unsigned char *prop_ret = NULL;
98         unsigned int xid;
99         Atom prop_user_created_win;
100
101         prop_user_created_win = XInternAtom(ecore_x_display_get(), "_E_USER_CREATED_WINDOW", False);
102
103         ret = XGetWindowProperty(ecore_x_display_get()
104                                                         , win, prop_user_created_win
105                                                         , 0L, 1L
106                                                         , False, 0
107                                                         , &type_ret, &size_ret
108                                                         , &num_ret, &bytes
109                                                         , &prop_ret);
110         if (ret != Success) {
111                 if (prop_ret)
112                         XFree((void *) prop_ret);
113                 return win;
114         } else if (!prop_ret) {
115                 return win;
116         }
117
118         memcpy(&xid, prop_ret, sizeof(unsigned int));
119         XFree((void *)prop_ret);
120
121         return xid;
122
123 }
124
125
126
127 int window_mgr_get_focus_window_pid(void)
128 {
129         Ecore_X_Window x_win_focused = 0;
130         int pid = 0;
131         int ret = -1;
132
133         _D("%s, %d", __func__, __LINE__);
134
135         x_win_focused = ecore_x_window_focus_get();
136         ret = ecore_x_netwm_pid_get(x_win_focused, &pid);
137         if(ret != 1) {
138                 _E("Can't get pid for focus x window (%x)\n", x_win_focused);
139                 return -1;
140         }
141         _D("PID(%d) for focus x window (%x)\n", pid, x_win_focused);
142
143         return pid;
144 }
145
146
147
148 static void _pwd_transient_set(Ecore_X_Window win, Ecore_X_Window for_win)
149 {
150         _W("%p is transient for %p", win, for_win);
151
152         ecore_x_icccm_transient_for_set(win, for_win);
153 }
154
155
156
157 static void _pwd_transient_unset(Ecore_X_Window xwin)
158 {
159         ret_if(!xwin);
160
161         _W("%p is not transient", xwin);
162         ecore_x_icccm_transient_for_unset(xwin);
163 }
164
165
166
167 Eina_Bool window_mgr_pwd_transient_set(void *data)
168 {
169         Evas_Object *pwd_win = NULL;
170         Ecore_X_Window pwd_x_win;
171         lockw_data *lockw = (lockw_data *) data;
172         retv_if(!lockw, EINA_FALSE);
173
174         pwd_win = lock_pwd_util_win_get();
175         retv_if(!pwd_win, EINA_FALSE);
176
177         pwd_x_win = elm_win_xwindow_get(pwd_win);
178         retv_if(!pwd_x_win, EINA_FALSE);
179
180         retv_if(!lockw->lock_x_window, EINA_FALSE);
181
182         /* unset transient */
183         _pwd_transient_unset(lockw->lock_x_window);
184
185         /* set transient */
186         _pwd_transient_set(lockw->lock_x_window, pwd_x_win);
187
188         return EINA_TRUE;
189 }
190
191
192
193 Eina_Bool window_mgr_set_prop(lockw_data * data, int lock_app_pid, void *event)
194 {
195         Ecore_X_Event_Window_Create *e = event;
196         Ecore_X_Window user_window = 0;
197         lockw_data *lockw = (lockw_data *) data;
198         int pid = 0;
199         int ret = 0;
200
201         retv_if(!lockw, EINA_FALSE);
202
203         user_window = _get_user_created_window((Window) (e->win));
204
205         ret = ecore_x_netwm_pid_get(user_window, &pid);
206         retv_if(ret != 1, EINA_FALSE);
207
208         _D("Check PID(%d) window. (lock_app_pid : %d)", pid, lock_app_pid);
209
210         if (lock_app_pid == pid) {
211                 if (_is_on_screen(ecore_x_display_get(), user_window) == TRUE) {
212                         lockw->lock_x_window = user_window;
213                         /* window effect : fade in /out */
214                         ecore_x_icccm_name_class_set(user_window, "LOCK_SCREEN", "LOCK_SCREEN");
215                         ecore_x_netwm_window_type_set(user_window, ECORE_X_WINDOW_TYPE_NOTIFICATION);
216                         utilx_set_system_notification_level(ecore_x_display_get(), user_window, UTILX_NOTIFICATION_LEVEL_NORMAL);
217                         utilx_set_window_opaque_state(ecore_x_display_get(), user_window, UTILX_OPAQUE_STATE_ON);
218
219                         /* set transient */
220                         if (!window_mgr_pwd_transient_set(lockw)) {
221                                 _E("Failed to set transient");
222                         }
223
224                         return EINA_TRUE;
225                 }
226         }
227         return EINA_FALSE;
228 }
229
230
231
232 Eina_Bool window_mgr_set_effect(lockw_data * data, int lock_app_pid, void *event)
233 {
234         Ecore_X_Event_Window_Create *e = event;
235         Ecore_X_Window user_window = 0;
236         int pid = 0;
237         int ret = 0;
238
239         user_window = _get_user_created_window((Window) (e->win));
240         ret = ecore_x_netwm_pid_get(user_window, &pid);
241         retv_if(ret != 1, EINA_FALSE);
242
243         if (lock_app_pid == pid) {
244                 if (_is_on_screen(ecore_x_display_get(), user_window) == TRUE) {
245                         Ecore_X_Atom ATOM_WINDOW_EFFECT_ENABLE = 0;
246                         unsigned int effect_state = 0;
247
248                         ATOM_WINDOW_EFFECT_ENABLE = ecore_x_atom_get("_NET_CM_WINDOW_EFFECT_ENABLE");
249                         if (ATOM_WINDOW_EFFECT_ENABLE) {
250                                 ecore_x_window_prop_card32_set(user_window, ATOM_WINDOW_EFFECT_ENABLE, &effect_state, 1);
251                         } else {
252                                 _E("ecore_x_atom_get() failed");
253                         }
254                         return EINA_TRUE;
255                 }
256         }
257         return EINA_FALSE;
258 }
259
260
261
262 void window_mgr_set_scroll_prop(lockw_data *data, int lock_type)
263 {
264         lockw_data *lockw = (lockw_data *) data;
265         Ecore_X_Atom ATOM_PANEL_SCROLLABLE_STATE = 0;
266         unsigned int val[3] = { 0, };
267
268         ret_if(!lockw);
269
270         ATOM_PANEL_SCROLLABLE_STATE = ecore_x_atom_get(STR_ATOM_PANEL_SCROLLABLE_STATE);
271         if (lock_type == SETTING_SCREEN_LOCK_TYPE_SIMPLE_PASSWORD ||
272                         lock_type == SETTING_SCREEN_LOCK_TYPE_PASSWORD) {
273                 val[0] = 0; // always enable F
274                 val[1] = 0; // quickpanel enable F
275                 val[2] = 0; // apptray enable F
276         } else {
277                 val[0] = 0; // always enable F
278                 val[1] = 1; // quickpanel enable T
279                 val[2] = 0; // apptray enable F
280         }
281         ecore_x_window_prop_card32_set(lockw->lock_x_window, ATOM_PANEL_SCROLLABLE_STATE, val, 3);
282 }
283
284
285
286 void window_mgr_register_event(void *data, lockw_data * lockw,
287                             Eina_Bool (*create_cb) (void *, int, void *),
288                             Eina_Bool (*show_cb) (void *, int, void *))
289 {
290         Ecore_X_Window root_window;
291
292         ret_if(!lockw);
293
294         if (lockw->is_registered) {
295                 _E("Already register event cb");
296                 return;
297         }
298
299         /* For getting window x event */
300         root_window = ecore_x_window_root_first_get();
301         ecore_x_window_client_sniff(root_window);
302
303         lockw->h_wincreate = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, create_cb, data);
304         lockw->h_winshow = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, show_cb, data);
305
306         lockw->is_registered = EINA_TRUE;
307 }
308
309
310
311 static inline void _unregister_event(lockw_data *lockw)
312 {
313         Ecore_X_Window root_window;
314
315         /* unset transient */
316         _pwd_transient_unset(lockw->lock_x_window);
317
318         /* delete getting window x event */
319         root_window = ecore_x_window_root_first_get();
320         ecore_x_window_client_sniff(root_window);
321
322         /* delete window create event handler */
323         if (lockw->h_wincreate) {
324                 ecore_event_handler_del(lockw->h_wincreate);
325                 lockw->h_wincreate = NULL;
326         }
327         if (lockw->h_winshow) {
328                 ecore_event_handler_del(lockw->h_winshow);
329                 lockw->h_winshow = NULL;
330         }
331         if (lockw->h_winhide) {
332                 ecore_event_handler_del(lockw->h_winhide);
333                 lockw->h_winhide = NULL;
334         }
335
336         ecore_x_pointer_ungrab();
337
338         lockw->is_registered = EINA_FALSE;
339 }
340
341
342
343 void window_mgr_unregister_event(lockw_data *lockw)
344 {
345         ret_if(!lockw);
346
347         if (!lockw->is_registered) {
348                 _E("event cb is not registered");
349                 return;
350         }
351
352         _unregister_event(lockw);
353 }
354
355
356
357 lockw_data *window_mgr_init(void)
358 {
359         lockw_data *lockw = NULL;
360
361         lockw = calloc(1, sizeof(*lockw));
362
363         return lockw;
364 }
365
366
367
368 void window_mgr_fini(lockw_data *lockw)
369 {
370         ret_if(!lockw);
371
372         if (lockw->is_registered) {
373                 _unregister_event(lockw);
374         }
375
376         free(lockw);
377 }
378 #endif
379
380 Evas_Object *window_mgr_pwd_lock_win_create(void)
381 {
382         Evas_Object *win = elm_win_add(NULL, "LOCKSCREEN_PWD", ELM_WIN_NOTIFICATION);
383         retv_if(!win, NULL);
384
385         elm_win_alpha_set(win, EINA_TRUE);
386         elm_win_borderless_set(win, EINA_TRUE);
387         elm_win_autodel_set(win, EINA_TRUE);
388         elm_win_role_set(win, "no-dim");
389
390 #ifdef HAVE_X11
391         Ecore_X_Window xwin = elm_win_xwindow_get(win);
392         if (xwin) {
393                 ecore_x_netwm_window_type_set(xwin, ECORE_X_WINDOW_TYPE_NOTIFICATION);
394                 utilx_set_system_notification_level(ecore_x_display_get(), xwin, UTILX_NOTIFICATION_LEVEL_NORMAL);
395                 utilx_set_window_opaque_state(ecore_x_display_get(), xwin, UTILX_OPAQUE_STATE_ON);
396
397                 Ecore_X_Atom ATOM_PANEL_SCROLLABLE_STATE = ecore_x_atom_get(STR_ATOM_PANEL_SCROLLABLE_STATE);
398                 unsigned int val[3] = { 0, };
399
400                 ecore_x_window_prop_card32_set(xwin, ATOM_PANEL_SCROLLABLE_STATE, val, 3);
401         }
402 #endif
403
404
405         return win;
406 }