apply app svc start info to home key case
[apps/core/preloaded/app-selector.git] / app-selector.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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
18 #include <stdio.h>
19 #include <appcore-efl.h>
20 #include <Ecore_X.h>
21 #include <utilX.h>
22 #include <aul.h>
23 #include <appsvc.h>
24 #include <X11/Xatom.h>
25 #include <X11/Xutil.h>
26 #include <Ecore.h>
27 #include <Ecore_Input.h>
28
29 #include "app-selector.h"
30 #include "app-selector-view.h"
31 #include "app-selector-util.h"
32
33 #ifndef EXPORT_API
34 #define EXPORT_API __attribute__ ((visibility("default")))
35 #endif
36
37 int is_reset = 0;
38
39 static void __win_del(void *data, Evas_Object * obj, void *event)
40 {
41         elm_exit();
42 }
43
44 static Evas_Object *__create_win(const char *name)
45 {
46         Evas_Object *eo;
47         int w;
48         int h;
49
50         eo = elm_win_add(NULL, name, ELM_WIN_DIALOG_BASIC);
51         if (eo) {
52                 elm_win_title_set(eo, name);
53                 elm_win_borderless_set(eo, EINA_TRUE);
54
55                 elm_win_alpha_set(eo, EINA_TRUE);
56
57                 evas_object_smart_callback_add(eo, "delete,request",
58                                                __win_del, NULL);
59                 ecore_x_window_size_get(ecore_x_window_root_first_get(),
60                                         &w, &h);
61                 evas_object_resize(eo, w, h);
62         }
63
64         return eo;
65 }
66
67 static Evas_Object *__create_layout_main(Evas_Object * parent)
68 {
69         Evas_Object *layout;
70
71         if (!parent)
72                 return NULL;
73
74         layout = elm_layout_add(parent);
75         if (!layout)
76                 return NULL;
77
78         elm_layout_theme_set(layout, "standard", "window", "integration");
79         evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND,
80                                          EVAS_HINT_EXPAND);
81
82         edje_object_signal_emit(_EDJ(layout), "elm,state,show,indicator",
83                                 "elm");
84         edje_object_signal_emit(_EDJ(layout), "elm,state,show,content", "elm");
85
86         evas_object_show(layout);
87
88         return layout;
89 }
90
91 static int __get_window_property(Display *dpy, Window win, Atom atom,
92                                           Atom type, unsigned int *val,
93                                           unsigned int len)
94 {
95         unsigned char *prop_ret;
96         Atom type_ret;
97         unsigned long bytes_after;
98         unsigned long  num_ret;
99         int format_ret;
100         unsigned int i;
101         int num;
102
103         prop_ret = NULL;
104         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
105                                type, &type_ret, &format_ret, &num_ret,
106                                &bytes_after, &prop_ret) != Success)
107                 return -1;
108
109         if (type_ret != type || format_ret != 32)
110                 num = -1;
111         else if (num_ret == 0 || !prop_ret)
112                 num = 0;
113         else {
114                 if (num_ret < len)
115                         len = num_ret;
116                 for (i = 0; i < len; i++) {
117                         val[i] = ((unsigned long *)prop_ret)[i];
118                 }
119                 num = len;
120         }
121
122         if (prop_ret)
123                 XFree(prop_ret);
124
125         return num;
126 }
127
128
129 static int __x_rotation_get(Display *dpy, Window win)
130 {
131         Window active_win;
132         Window root_win;
133         int rotation = -1;
134         int ret;
135
136         Atom atom_active_win;
137         Atom atom_win_rotate_angle;
138
139         root_win = XDefaultRootWindow(dpy);
140
141         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
142         ret = __get_window_property(dpy, root_win, atom_active_win,
143                                              XA_WINDOW,
144                                              (unsigned int *)&active_win, 1);
145
146         /*printf("[SYSPOPUP] Active win : %x, Window %x\n", active_win, win);*/
147
148         /*active_win = get_active_win(dpy, root_win, atom_active_win);*/
149         if (ret < 0)
150                 return ret;
151
152         atom_win_rotate_angle =
153                 XInternAtom(dpy, "_E_ILLUME_ROTATE_WINDOW_ANGLE", False);
154         ret = __get_window_property(dpy, active_win,
155                                           atom_win_rotate_angle, XA_CARDINAL,
156                                           (unsigned int *)&rotation, 1);
157
158         /*printf("[SYSPOPUP] Rotation %d\n", rotation);*/
159
160         if (ret != -1)
161                 return rotation;
162
163         return -1;
164 }
165
166 static int __as_rotate(Display *dpy, Window xwin, Evas_Object *win, void *data)
167 {
168         int rotation;
169         struct appdata *ad = data;
170
171         ecore_x_icccm_hints_set(xwin, 0, 0, 0, 0, 0, 0, 0);
172
173         rotation = __x_rotation_get(dpy, xwin);
174
175         if (rotation == -1) {
176                 rotation = 0;
177         }
178
179         if (rotation >= 0 && ad->rotate != NULL)
180                 elm_win_rotation_with_resize_set(win, rotation);
181
182         return 0;
183 }
184
185 static Eina_Bool __rotate(void *data, int type, void *event)
186 {
187         struct appdata *ad = data;
188
189         Ecore_X_Event_Client_Message *ev = event;
190
191         if (!event)
192                 return ECORE_CALLBACK_RENEW;
193
194         if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE)
195                 __as_rotate(ad->dpy, ad->xwin, ad->win, ad);
196
197         return 0;
198 }
199
200 static Eina_Bool s_key_registered;
201
202 static
203 Eina_Bool __key_press_cb(void *data, int type, void *event)
204 {
205         Evas_Event_Key_Down *ev = event;
206         struct appdata *ad = (struct appdata *)data;
207                 char *val = NULL;
208
209         _D("__key_press_cb");
210
211         if (!s_key_registered) {
212                 _E("Key is not registered");
213                 return ECORE_CALLBACK_RENEW;
214         }
215
216         if (!ev) {
217                 _E("Invalid event object");
218                 return ECORE_CALLBACK_RENEW;
219         }
220
221         val = bundle_get_val(ad->kb, "__APP_SVC_CALLER_NOTI__");
222         if(val) {
223                         bundle_add(ad->kb, "__APP_SVC_START_INFO__", "c");
224                 _D("before aul_launch_app");
225                         aul_launch_app(val, ad->kb);
226         }
227
228                 ecore_event_handler_del(ad->rotate);
229                 ad->rotate = NULL;
230                 elm_exit();
231
232         return ECORE_CALLBACK_RENEW;
233 }
234
235 static void __register_key_handler(void *data)
236 {
237         struct appdata *ad = (struct appdata *)data;
238
239         ad->key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP,
240                                                                                          __key_press_cb, ad);
241         if (!ad->key_up) {
242                 _E("Failed to register a key down event handler");
243         }
244
245         _D("Key handler is registered");
246         s_key_registered = EINA_TRUE;
247 }
248
249 static void __unregister_key_handler(void *data)
250 {
251         struct appdata *ad = (struct appdata *)data;
252
253         if (ad->key_up) {
254                 ecore_event_handler_del(ad->key_up);
255                 ad->key_up = NULL;
256         }
257
258         _D("Unregister key handler is invoked");
259         s_key_registered = EINA_FALSE;
260 }
261
262 static void __grab_home_key(void *data)
263 {
264         struct appdata *ad = (struct appdata *)data;
265
266         _D("Grab home key.");
267
268         utilx_grab_key(ad->dpy, ad->xwin, KEY_HOME, SHARED_GRAB);
269
270         __register_key_handler(ad);
271 }
272
273 static void __ungrab_home_key(void *data)
274 {
275         struct appdata *ad = (struct appdata *)data;
276
277         __unregister_key_handler(ad);
278
279         _D("Ungrab home key.");
280
281         utilx_ungrab_key(ad->dpy, ad->xwin, KEY_HOME);
282 }
283
284 static int __app_create(void *data)
285 {
286         struct appdata *ad = (struct appdata *)data;
287         Evas_Object *win;
288         Evas_Object *ly;
289         int r;
290
291         /* create window */
292         win = __create_win(PACKAGE);
293         if (win == NULL)
294                 return -1;
295         ad->win = win;
296
297         /* Base Layout */
298         ly = __create_layout_main(ad->win);
299         if (!ly)
300                 return -1;
301
302         edje_object_signal_emit(_EDJ(ly), "elm,bg,show,transparent", "elm");
303
304         elm_win_resize_object_add(win, ly);
305
306         ad->dpy = ecore_x_display_get();
307         ad->xwin = elm_win_xwindow_get(win);
308
309         ad->rotate = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
310                                                          __rotate, (void *)ad);
311
312         __as_rotate(ad->dpy, ad->xwin, win, ad);
313
314         evas_object_show(win);
315
316         /* init internationalization */
317         r = appcore_set_i18n(PACKAGE, LOCALEDIR);
318         if (r)
319                 return -1;
320
321         __grab_home_key(ad);
322
323         return 0;
324 }
325
326 static int __app_init_with_bundle(void *data)
327 {
328         struct appdata *ad = data;
329
330 /*      Ecore_X_Display *display = ecore_x_display_get();
331         Ecore_X_Window xwin = elm_win_xwindow_get(ad->win);
332         Ecore_X_Window prev_win =
333             tm_get_user_created_win_with_pid(ad->parent_pid);
334
335         set_transient(display, xwin, prev_win);
336 */
337         load_app_select_popup(ad);
338
339         return 0;
340 }
341
342 static int __app_terminate(void *data)
343 {
344         struct appdata *ad = data;
345
346         _D("app_terminate");
347
348         if (ad->popup)
349                 evas_object_del(ad->popup);
350
351         if (ad->win)
352                 evas_object_del(ad->win);
353
354         if(ad->rotate) {
355                 ecore_event_handler_del(ad->rotate);
356                 ad->rotate = NULL;
357         }
358
359         __ungrab_home_key(ad);
360
361         return 0;
362 }
363
364 static int __app_pause(void *data)
365 {
366         struct appdata *ad = data;
367         char *val = NULL;
368
369         _D("app_pause");
370
371         ecore_event_handler_del(ad->rotate);
372         ad->rotate = NULL;
373
374         val = bundle_get_val(ad->kb, "__APP_SVC_CALLER_NOTI__");
375         if(val) {
376                 bundle_add(ad->kb, "__APP_SVC_START_INFO__", "c");
377                 aul_launch_app(val, ad->kb);
378         }
379
380         sleep(1);
381         elm_exit();
382
383         return 0;
384 }
385
386 static int __app_resume(void *data)
387 {
388         return 0;
389 }
390
391 static int __app_reset(bundle *b, void *data)
392 {
393         struct appdata *ad = data;
394         char *str = NULL;
395
396         if (ad->kb)
397                 bundle_free(ad->kb);
398
399         ad->kb = bundle_dup(b);
400
401         ad->mime_type = (char *)bundle_get_val(ad->kb, AUL_K_MIME_TYPE);
402         str = (char *)bundle_get_val(ad->kb, AUL_K_CALLER_PID);
403
404         ad->control_op = (char *)appsvc_get_operation(ad->kb);
405         ad->control_uri = (char *)appsvc_get_uri(ad->kb);
406         ad->control_mime = (char *)appsvc_get_mime(ad->kb);
407
408         if (str)
409                 ad->parent_pid = atoi(str);
410         else
411                 ad->parent_pid = -1;
412
413         if (!ad->mime_type && !ad->control_op) {
414                 load_info_popup(ad, _("Cannot get mimetype!"));
415                 return 0;
416         }
417         /*
418            If AUL_K_ARGV0 is not NULL, the situation is launching(fork & exec).
419            else the situation is being received a reset event(old relaunch evet)
420          */
421         if (is_reset == 0) {
422                 __app_init_with_bundle(data);   /*(fork & exec) */
423                 is_reset = 1;
424         } else
425                 update_app_list(data);  /*(reset event) */
426
427         return 0;
428 }
429
430 EXPORT_API int main(int argc, char *argv[])
431 {
432         struct appdata ad;
433         struct appcore_ops ops = {
434                 .create = __app_create,
435                 .terminate = __app_terminate,
436                 .pause = __app_pause,
437                 .resume = __app_resume,
438                 .reset = __app_reset,
439         };
440
441         memset(&ad, 0x0, sizeof(struct appdata));
442         ops.data = &ad;
443
444         return appcore_efl_main(PACKAGE, &argc, &argv, &ops);
445 }