Make menu-screen not dependent of utilx.
[apps/native/menu-screen.git] / src / menu_screen.c
1  /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.1 (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://floralicense.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
19 #include <ail.h>
20 #include <app.h>
21 #include <aul.h>
22 #include <Ecore_X.h>
23 #include <Elementary.h>
24 #include <stdbool.h>
25 #include <system_info.h>
26 #include <vconf.h>
27
28 #include "conf.h"
29 #include "item.h"
30 #include "layout.h"
31 #include "mapbuf.h"
32 #include "menu_screen.h"
33 #include "mouse.h"
34 #include "page.h"
35 #include "page_scroller.h"
36 #include "util.h"
37
38 #define MENU_SCREEN_ENGINE "file/private/org.tizen.menu-screen/engine"
39
40 #define LAYOUT_EDJE_PORTRAIT EDJEDIR"/layout_portrait.edj"
41 #define LAYOUT_GROUP_NAME "layout"
42
43
44
45 // Define prototype of the "hidden API of AUL"
46 extern int aul_listen_app_dead_signal(int (*func)(int signal, void *data), void *data);
47 static struct {
48         int state;
49         Evas_Object *win;
50         Elm_Theme *theme;
51         bool is_done;
52 } menu_screen_info = {
53         .state = APP_STATE_PAUSE,
54         .win = NULL,
55         .theme = NULL,
56         .is_done = false,
57 };
58
59
60
61 HAPI Evas *menu_screen_get_evas(void)
62 {
63         return evas_object_evas_get(menu_screen_info.win);
64 }
65
66
67 HAPI int menu_screen_get_root_width(void)
68 {
69         int width = 0;
70         elm_win_screen_size_get(menu_screen_get_win(), NULL, NULL, &width, NULL);
71         return width;
72 }
73
74
75
76 HAPI int menu_screen_get_root_height(void)
77 {
78         int height = 0;
79         elm_win_screen_size_get(menu_screen_get_win(), NULL, NULL, NULL, &height);
80         return height;
81 }
82
83
84
85 HAPI Evas_Object *menu_screen_get_win(void)
86 {
87         return menu_screen_info.win;
88 }
89
90
91
92 HAPI Elm_Theme *menu_screen_get_theme(void)
93 {
94         return menu_screen_info.theme;
95 }
96
97
98
99 HAPI bool menu_screen_get_done(void)
100 {
101         return menu_screen_info.is_done;
102 }
103
104
105
106 HAPI void menu_screen_set_done(bool is_done)
107 {
108         menu_screen_info.is_done = is_done;
109 }
110
111
112
113 static menu_screen_error_e _create_canvas(char *name, char *title)
114 {
115         Ecore_X_Atom ATOM_WM_WINDOW_ROLE;
116
117         menu_screen_info.win = elm_win_add(NULL, name, ELM_WIN_BASIC);
118         retv_if(NULL == menu_screen_info.win, MENU_SCREEN_ERROR_FAIL);
119
120         if (title) {
121                 elm_win_title_set(menu_screen_info.win, title);
122         }
123         elm_win_borderless_set(menu_screen_info.win, EINA_TRUE);
124
125         ecore_x_icccm_name_class_set(elm_win_xwindow_get(menu_screen_info.win), "MENU_SCREEN", "MENU_SCREEN");
126         ATOM_WM_WINDOW_ROLE = ecore_x_atom_get("WM_WINDOW_ROLE");
127         if (ATOM_WM_WINDOW_ROLE) {
128                 ecore_x_window_prop_string_set(elm_win_xwindow_get(menu_screen_info.win), ATOM_WM_WINDOW_ROLE, "MENU_SCREEN");
129         } else {
130                 _D("Failed to set the window role as MENU_SCREEN");
131         }
132
133         evas_object_show(menu_screen_info.win);
134
135         return MENU_SCREEN_ERROR_OK;
136 }
137
138
139
140 static void _destroy_canvas(void)
141 {
142         evas_object_del(menu_screen_info.win);
143 }
144
145
146
147 static int _dead_cb(int pid, void *data)
148 {
149         evas_object_show(menu_screen_get_win());
150         return EXIT_SUCCESS;
151 }
152
153
154
155 static void _create_bg(void)
156 {
157         char *buf;
158         Evas_Coord w;
159         Evas_Coord h;
160         Evas_Object *bg;
161         double f, wf, hf;
162         static int trigger = 0;
163         const char *key;
164         int width;
165         int height;
166
167         buf = vconf_get_str(VCONFKEY_BGSET);
168         ret_if(NULL == buf);
169
170         width = menu_screen_get_root_width();
171         height = menu_screen_get_root_height();
172
173         bg = evas_object_data_get(menu_screen_get_win(), "bg");
174         if (NULL == bg) {
175                 Evas_Object *rect;
176
177                 rect = evas_object_rectangle_add(menu_screen_get_evas());
178                 ret_if(NULL == rect);
179                 evas_object_data_set(menu_screen_get_win(), "rect", rect);
180                 evas_object_color_set(rect, 0, 0, 0, 255);
181                 evas_object_size_hint_min_set(rect, width, height);
182                 evas_object_size_hint_max_set(rect, width, height);
183                 evas_object_resize(rect, width, height);
184                 evas_object_show(rect);
185
186                 bg = evas_object_image_add(menu_screen_get_evas());
187                 if (NULL == bg) {
188                         free(buf);
189                         return;
190                 }
191                 evas_object_image_load_orientation_set(bg, EINA_TRUE);
192                 evas_object_data_set(menu_screen_get_win(), "bg", bg);
193         }
194
195         if (trigger == 0) {
196                 key = "/";
197                 trigger = 1;
198         } else {
199                 key = NULL;
200                 trigger = 0;
201         }
202
203         evas_object_image_file_set(bg, buf, key);
204         evas_object_image_size_get(bg, &w, &h);
205         evas_object_image_filled_set(bg, 1);
206
207         wf = (double) width / (double) w;
208         hf = (double) height / (double) h;
209
210         f = wf < hf ? hf : wf;
211
212         w = (int) ((double) f * (double) w);
213         h = (int) ((double) f * (double) h);
214
215         evas_object_image_load_size_set(bg, w, h);
216         evas_object_image_fill_set(bg, 0, 0, w, h);
217         evas_object_move(bg, (width - w) / 2, (height - h) / 2);
218         evas_object_resize(bg, w, h);
219         evas_object_show(bg);
220
221         free(buf);
222 }
223
224
225
226
227 static void _destroy_bg()
228 {
229         Evas_Object *rect;
230         Evas_Object *bg;
231
232         rect = evas_object_data_del(menu_screen_get_win(), "rect");
233         evas_object_del(rect);
234
235         bg = evas_object_data_del(menu_screen_get_win(), "bg");
236         evas_object_del(bg);
237 }
238
239
240
241 static void _change_bg_cb(keynode_t *node, void *data)
242 {
243         _D("Background image is changed.");
244         _create_bg();
245 }
246
247
248
249 static void _init_theme(void)
250 {
251         menu_screen_info.theme = elm_theme_new();
252         elm_theme_ref_set(menu_screen_info.theme, NULL);
253         elm_theme_extension_add(menu_screen_info.theme, EDJEDIR"/index.edj");
254 }
255
256
257
258 static void _fini_theme(void)
259 {
260         elm_theme_extension_del(menu_screen_info.theme, EDJEDIR"/index.edj");
261         elm_theme_free(menu_screen_info.theme);
262         menu_screen_info.theme = NULL;
263
264 }
265
266
267
268 static Evas_Object *_create_conformant(Evas_Object *win)
269 {
270         Evas_Object *conformant;
271
272         conformant = elm_conformant_add(win);
273         retv_if(NULL == conformant, NULL);
274
275         elm_object_style_set(conformant, "nokeypad");
276         evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
277         evas_object_data_set(conformant, "win", win);
278         evas_object_show(conformant);
279
280         elm_win_resize_object_add(win, conformant);
281         elm_win_conformant_set(win, EINA_TRUE);
282
283         return conformant;
284 }
285
286
287
288 static void _destroy_conformant(Evas_Object *conformant)
289 {
290         evas_object_data_del(conformant, "win");
291         evas_object_del(conformant);
292 }
293
294
295
296 static bool _create_cb(void *data)
297 {
298         Evas_Object *conformant;
299
300         _init_theme();
301         retv_if(MENU_SCREEN_ERROR_FAIL == _create_canvas(PACKAGE, PACKAGE), false);
302         elm_win_indicator_mode_set(menu_screen_info.win, ELM_WIN_INDICATOR_SHOW);
303
304         if (vconf_notify_key_changed(VCONFKEY_BGSET, _change_bg_cb, NULL) < 0) {
305                 _E("Failed to register a vconf cb for %s\n", VCONFKEY_BGSET);
306         }
307         _create_bg();
308
309         conformant = _create_conformant(menu_screen_info.win);
310         retv_if(NULL == conformant, false);
311         evas_object_data_set(menu_screen_info.win, "conformant", conformant);
312
313         Evas_Object *layout;
314         layout = layout_create(conformant, LAYOUT_EDJE_PORTRAIT,
315                                 LAYOUT_GROUP_NAME, MENU_SCREEN_ROTATE_PORTRAIT);
316         if (NULL == layout) {
317                 _E("Failed to load an edje object");
318                 evas_object_del(menu_screen_info.win);
319                 return false;
320         }
321         evas_object_data_set(menu_screen_info.win, "layout", layout);
322
323         elm_object_content_set(conformant, layout);
324         mouse_register();
325         aul_listen_app_dead_signal(_dead_cb, NULL);
326
327         return true;
328 }
329
330
331
332 static void _terminate_cb(void *data)
333 {
334         Evas_Object *conformant;
335         Evas_Object *layout;
336
337         if (vconf_ignore_key_changed(VCONFKEY_BGSET, _change_bg_cb) < 0) {
338                 _E("Failed to remove bgset [%s]\n", VCONFKEY_BGSET);
339         }
340
341         evas_object_hide(menu_screen_info.win);
342
343         mouse_unregister();
344
345         layout = evas_object_data_del(menu_screen_info.win, "layout");
346         if (layout) layout_destroy(layout);
347
348         conformant = evas_object_data_del(menu_screen_info.win, "conformant");
349         if (conformant) _destroy_conformant(conformant);
350
351         _destroy_bg();
352         _destroy_canvas();
353         _fini_theme();
354         evas_object_del(menu_screen_info.win);
355 }
356
357
358
359 static void _pause_cb(void *data)
360 {
361         _D("Pause start");
362
363         if (vconf_set_int(VCONFKEY_IDLE_SCREEN_TOP, VCONFKEY_IDLE_SCREEN_TOP_FALSE) < 0) {
364                 _E("Failed to set %s to 0", VCONFKEY_IDLE_SCREEN_TOP);
365         }
366
367         menu_screen_info.state = APP_STATE_PAUSE;
368 }
369
370
371
372 static void _resume_cb(void *data)
373 {
374         _D("START RESUME");
375
376         if (vconf_set_int(VCONFKEY_IDLE_SCREEN_TOP, VCONFKEY_IDLE_SCREEN_TOP_TRUE) < 0) {
377                 _E("Failed to set %s to 1", VCONFKEY_IDLE_SCREEN_TOP);
378         }
379
380         evas_object_show(menu_screen_get_win());
381
382         menu_screen_info.state = APP_STATE_RESUME;
383 }
384
385
386
387 static void _service_cb(service_h service, void *data)
388 {
389         _D("START RESET : %d", menu_screen_info.state);
390
391         if (vconf_set_int(VCONFKEY_IDLE_SCREEN_TOP, VCONFKEY_IDLE_SCREEN_TOP_TRUE) < 0) {
392                 _E("Failed to set %s to 1", VCONFKEY_IDLE_SCREEN_TOP);
393         }
394
395         evas_object_show(menu_screen_get_win());
396 }
397
398
399
400 static void _language_changed_cb(void *data)
401 {
402         register unsigned int i;
403         register unsigned int j;
404         unsigned int count;
405         Evas_Object *layout;
406         Evas_Object *all_apps;
407         Evas_Object *scroller;
408         Evas_Object *page;
409         Evas_Object *item;
410         unsigned int page_max_app;
411
412         _D("Language is changed");
413
414         if (false == menu_screen_info.is_done) {
415                 elm_exit();
416         }
417
418         layout = evas_object_data_get(menu_screen_info.win, "layout");
419         ret_if(NULL == layout);
420         all_apps = evas_object_data_get(layout, "all_apps");
421         ret_if(NULL == all_apps);
422         scroller = elm_object_part_content_get(all_apps, "content");
423         ret_if(NULL == scroller);
424
425         count = page_scroller_count_page(scroller);
426         page_max_app = (unsigned int) evas_object_data_get(scroller, "page_max_app");
427         for (i = 0; i < count; i ++) {
428                 page = page_scroller_get_page_at(scroller, i);
429                 if (!page) continue;
430                 if (mapbuf_is_enabled(page)) {
431                         mapbuf_disable(page, 1);
432                 }
433
434                 for (j = 0; j < page_max_app; j ++) {
435                         ail_appinfo_h ai;
436                         char *name;
437
438                         item = page_get_item_at(page, j);
439                         if (!item) continue;
440
441                         if (ail_get_appinfo(item_get_package(item), &ai) < 0) continue;
442                         if (ail_appinfo_get_str(ai, AIL_PROP_NAME_STR, &name) < 0) {
443                                 ail_destroy_appinfo(ai);
444                                 continue;
445                         }
446
447                         if (!name) {
448                                 _D("Failed to get name for %s", item_get_package(item));
449                                 ail_destroy_appinfo(ai);
450                                 continue;
451                         }
452
453                         item_set_name(item, name, 0);
454                         ail_destroy_appinfo(ai);
455                 }
456
457                 mapbuf_enable(page, 1);
458         }
459 }
460
461
462
463 static void _init(app_event_callback_s *event_callback)
464 {
465         event_callback->create = _create_cb;
466         event_callback->terminate = _terminate_cb;
467         event_callback->pause = _pause_cb;
468         event_callback->resume = _resume_cb;
469         event_callback->service = _service_cb;
470         event_callback->low_memory = NULL;
471         event_callback->low_battery = NULL;
472         event_callback->device_orientation = NULL;
473         event_callback->language_changed = _language_changed_cb;
474         event_callback->region_format_changed = NULL;
475 }
476
477
478
479 static void _fini(void)
480 {
481 }
482
483
484
485 #define QP_EMUL_STR             "Emulator"
486 static bool _is_emulator_on(void)
487 {
488         char *info;
489
490         if (system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &info) == 0) {
491                 if (info == NULL) return false;
492                 if (!strncmp(QP_EMUL_STR, info, strlen(info))) {
493                         return true;
494                 }
495         }
496
497         return false;
498 }
499
500
501
502 int main(int argc, char *argv[])
503 {
504         char *buf;
505         app_event_callback_s event_callback;
506
507         if (_is_emulator_on()) {
508                 _D("ELM_ENGINE is set as [software_x11]");
509                 setenv("ELM_ENGINE", "software_x11", 1);
510         } else {
511                 buf = vconf_get_str(MENU_SCREEN_ENGINE);
512                 if (buf) {
513                         _D("ELM_ENGINE is set as [%s]", buf);
514                         setenv("ELM_ENGINE", buf, 1);
515                         free(buf);
516                 } else {
517                         _D("ELM_ENGINE is set as [gl]");
518                         setenv("ELM_ENGINE", "gl", 1);
519                 }
520         }
521
522         _init(&event_callback);
523         app_efl_main(&argc, &argv, &event_callback, NULL);
524         _fini();
525
526         return EXIT_SUCCESS;
527 }
528
529
530
531
532
533 // End of a file