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