block system_settings
[apps/native/menu-screen.git] / src / menu_screen.c
1 /*
2  * MENU-SCREEN
3  *
4  * Copyright (c) 2009-2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Jin Yoon <jinny.yoon@samsung.com>
7  *          Junkyu Han <junkyu.han@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 #include <ail.h>
24 #include <app.h>
25 #include <appcore-efl.h>
26 #include <aul.h>
27 //#include <Ecore_X.h>
28 #include <Elementary.h>
29 #include <stdbool.h>
30 #include <system_info.h>
31 #include <vconf.h>
32 #include <app_preference.h>
33 //#include <system_info_internal.h>
34 #include <system_settings.h>
35 #include <pkgmgr-info.h>
36
37 #include "conf.h"
38 #include "item.h"
39 #include "key.h"
40 #include "layout.h"
41 #include "mapbuf.h"
42 #include "menu_screen.h"
43 #include "mouse.h"
44 #include "page.h"
45 #include "page_scroller.h"
46 #include "pkgmgr.h"
47 #include "util.h"
48
49 #define MENU_SCREEN_ENGINE "file/private/org.tizen.menu-screen/engine"
50
51 #define LAYOUT_EDJE_PORTRAIT EDJEDIR"/layout_portrait.edj"
52 #define LAYOUT_GROUP_NAME "layout"
53
54
55
56 // Define prototype of the "hidden API of AUL"
57 extern int aul_listen_app_dead_signal(int (*func)(int signal, void *data), void *data);
58 static struct {
59         int state;
60         int root_width;
61         int root_height;
62         int is_tts;
63         int booting_state;
64         Evas *evas;
65         Ecore_Evas *ee;
66         Evas_Object *win;
67         Elm_Theme *theme;
68         bool is_done;
69 } menu_screen_info = {
70         .state = APP_STATE_PAUSE,
71         .is_tts = false,
72         .booting_state = 0,
73         .evas = NULL,
74         .ee = NULL,
75         .win = NULL,
76         .theme = NULL,
77         .is_done = false,
78 };
79
80
81
82 HAPI Evas *menu_screen_get_evas(void)
83 {
84         return menu_screen_info.evas;
85 }
86
87
88
89 HAPI int menu_screen_get_root_width(void)
90 {
91         return menu_screen_info.root_width;
92 }
93
94
95
96 HAPI int menu_screen_get_root_height(void)
97 {
98         return menu_screen_info.root_height;
99 }
100
101
102
103 HAPI Evas_Object *menu_screen_get_win(void)
104 {
105         return menu_screen_info.win;
106 }
107
108
109
110 HAPI Elm_Theme *menu_screen_get_theme(void)
111 {
112         return menu_screen_info.theme;
113 }
114
115
116
117 HAPI bool menu_screen_get_done(void)
118 {
119         return menu_screen_info.is_done;
120 }
121
122
123
124 HAPI void menu_screen_set_done(bool is_done)
125 {
126         menu_screen_info.is_done = is_done;
127 }
128
129
130
131 HAPI int menu_screen_get_state(void)
132 {
133         return menu_screen_info.state;
134 }
135
136
137
138 HAPI int menu_screen_is_tts(void)
139 {
140         return menu_screen_info.is_tts;
141 }
142
143
144 static Eina_Bool _appcore_flush_cb(void *data)
145 {
146         if (APP_STATE_PAUSE != menu_screen_info.state) return ECORE_CALLBACK_CANCEL;
147         if (0 != appcore_flush_memory()) _E("Cannot flush memory");
148         return ECORE_CALLBACK_CANCEL;
149 }
150
151
152
153 HAPI void menu_screen_inc_booting_state(void)
154 {
155         menu_screen_info.booting_state++;
156         if (BOOTING_STATE_DONE > menu_screen_info.booting_state) return;
157
158         menu_screen_error_e ret = MENU_SCREEN_ERROR_OK;
159         do {
160                 ret = pkgmgr_reserve_list_pop_request();
161         } while (MENU_SCREEN_ERROR_OK == ret);
162
163         /*  Cache memory is cleared when the application paused (every time, after 5 seconds (in appcore)),
164         *  but after running in a minimized mode (HIDE_LAUNCH) application have status AS_RUNNING.
165         *  Application have status AS_PAUSED only after change of visibility to hidden condition by user (on hiding window)
166         *  Cleaning must be performed only once after application loading in hidden condition
167         *  (and stay in a hidden condition at time of cleaning).
168         */
169         if (APP_STATE_PAUSE == menu_screen_info.state)
170                 ecore_timer_add(5, _appcore_flush_cb, NULL);
171 }
172
173
174
175 HAPI void menu_screen_dec_booting_state(void)
176 {
177         menu_screen_info.booting_state --;
178 }
179
180
181
182 HAPI int menu_screen_get_booting_state(void)
183 {
184         return menu_screen_info.booting_state;
185 }
186
187
188
189 static bool _is_emulator_on(void)
190 {
191         int ret;
192         char *model;
193
194         ret = system_info_get_platform_string("tizen.org/system/model_name", &model);
195         if (SYSTEM_INFO_ERROR_NONE != ret) {
196                 if (model) {
197                         free(model);
198                 }
199                 return false;
200         }
201
202         if (!strncmp(model, "Emulator", strlen(model))) {
203                 _D("This model is on Emulator");
204                 free(model);
205                 return true;
206         }
207
208         _D("This model is NOT on Emulator");
209         free(model);
210         return false;
211 }
212
213
214
215 static menu_screen_error_e _create_canvas(char *name, char *title)
216 {
217         //Ecore_X_Atom ATOM_WM_WINDOW_ROLE;
218         char *buf;
219
220         if (_is_emulator_on()) {
221                 _D("ELM_ENGINE is set as [software_x11]");
222                 elm_config_accel_preference_set("opengl");
223         } else {
224                 buf = vconf_get_str(MENU_SCREEN_ENGINE);
225                 if (buf) {
226                         _D("ELM_ENGINE is set as [%s]", buf);
227                         elm_config_accel_preference_set(buf);
228                         free(buf);
229                 } else {
230                         _D("ELM_ENGINE is set as [gl]");
231                         elm_config_accel_preference_set("gl");
232                 }
233         }
234
235         menu_screen_info.win = elm_win_add(NULL, name, ELM_WIN_BASIC);
236         retv_if(NULL == menu_screen_info.win, MENU_SCREEN_ERROR_FAIL);
237
238         if (title) {
239                 elm_win_title_set(menu_screen_info.win, title);
240         }
241         elm_win_borderless_set(menu_screen_info.win, EINA_TRUE);
242         elm_win_screen_size_get(menu_screen_info.win, NULL, NULL, &menu_screen_info.root_width, &menu_screen_info.root_height);
243
244         //ecore_x_icccm_name_class_set(elm_win_xwindow_get(menu_screen_info.win), "MENU_SCREEN", "MENU_SCREEN");
245         //ATOM_WM_WINDOW_ROLE = ecore_x_atom_get("WM_WINDOW_ROLE");
246         //if (ATOM_WM_WINDOW_ROLE) {
247 //              ecore_x_window_prop_string_set(elm_win_xwindow_get(menu_screen_info.win), ATOM_WM_WINDOW_ROLE, "MENU_SCREEN");
248 //      } else {
249 //              _D("Failed to set the window role as MENU_SCREEN");
250 //      }
251
252         //elm_win_role_set(menu_screen_info.win, "MENU_SCREEN");
253         //evas_object_resize(menu_screen_info.win, menu_screen_get_root_width(), menu_screen_get_root_height());
254
255         menu_screen_info.evas = evas_object_evas_get(menu_screen_info.win);
256         if (!menu_screen_info.evas) {
257                 _E("[%s] Failed to get the evas object", __func__);
258         }
259
260         menu_screen_info.ee = ecore_evas_ecore_evas_get(menu_screen_info.evas);
261         if (!menu_screen_info.ee) {
262                 _E("[%s] Failed to get ecore_evas object", __func__);
263         }
264
265         evas_object_size_hint_min_set(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
266         evas_object_size_hint_max_set(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
267         evas_object_resize(menu_screen_info.win, menu_screen_info.root_width, menu_screen_info.root_height);
268         evas_object_show(menu_screen_info.win);
269
270         return MENU_SCREEN_ERROR_OK;
271 }
272
273
274
275 static void _destroy_canvas(void)
276 {
277         evas_object_del(menu_screen_info.win);
278 }
279
280
281
282 static int _dead_cb(int pid, void *data)
283 {
284         return EXIT_SUCCESS;
285 }
286
287
288
289 static void _create_bg(void)
290 {
291         _D("Create BG");
292         char *buf;
293         Evas_Coord w;
294         Evas_Coord h;
295         Evas_Object *bg;
296         double f, wf, hf;
297         static int trigger = 0;
298         const char *key;
299         int width;
300         int height;
301         int ret = SYSTEM_SETTINGS_ERROR_NONE;
302
303         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &buf);
304         _D("result: %d, value: %s", ret, buf);
305         ret_if(NULL == buf);
306
307         width = menu_screen_get_root_width();
308         height = menu_screen_get_root_height();
309
310         bg = evas_object_data_get(menu_screen_get_win(), "bg");
311         if (NULL == bg) {
312                 Evas_Object *rect;
313
314                 rect = evas_object_rectangle_add(menu_screen_get_evas());
315                 ret_if(NULL == rect);
316                 evas_object_data_set(menu_screen_get_win(), "rect", rect);
317                 evas_object_color_set(rect, 0, 0, 0, 255);
318                 evas_object_size_hint_min_set(rect, width, height);
319                 evas_object_size_hint_max_set(rect, width, height);
320                 elm_win_resize_object_add(menu_screen_get_win(), rect);
321                 evas_object_show(rect);
322
323                 bg = evas_object_image_add(menu_screen_get_evas());
324                 if (NULL == bg) {
325                         free(buf);
326                         return;
327                 }
328                 evas_object_image_load_orientation_set(bg, EINA_TRUE);
329                 evas_object_data_set(menu_screen_get_win(), "bg", bg);
330         }
331
332         if (trigger == 0) {
333                 key = "/";
334                 trigger = 1;
335         } else {
336                 key = NULL;
337                 trigger = 0;
338         }
339
340         evas_object_image_file_set(bg, buf, key);
341         evas_object_image_size_get(bg, &w, &h);
342         evas_object_image_filled_set(bg, 1);
343
344         wf = (double) width / (double) w;
345         hf = (double) height / (double) h;
346
347         f = wf < hf ? hf : wf;
348
349         w = (int) ((double) f * (double) w);
350         h = (int) ((double) f * (double) h);
351
352         evas_object_image_load_size_set(bg, w, h);
353         evas_object_image_fill_set(bg, 0, 0, w, h);
354         elm_win_resize_object_add(menu_screen_get_win(), bg);
355         evas_object_show(bg);
356
357         free(buf);
358 }
359
360
361
362
363 static void _destroy_bg()
364 {
365         Evas_Object *rect;
366         Evas_Object *bg;
367
368         rect = evas_object_data_del(menu_screen_get_win(), "rect");
369         evas_object_del(rect);
370
371         bg = evas_object_data_del(menu_screen_get_win(), "bg");
372         evas_object_del(bg);
373 }
374
375
376
377 static void _change_bg_cb(system_settings_key_e key, void *data)
378 {
379         _D("Background image is changed.");
380         _create_bg();
381 }
382
383
384
385 static void _init_theme(void)
386 {
387         menu_screen_info.theme = elm_theme_new();
388         elm_theme_ref_set(menu_screen_info.theme, NULL);
389         elm_theme_extension_add(menu_screen_info.theme, EDJEDIR"/index.edj");
390 }
391
392
393
394 static void _fini_theme(void)
395 {
396         elm_theme_extension_del(menu_screen_info.theme, EDJEDIR"/index.edj");
397         elm_theme_free(menu_screen_info.theme);
398         menu_screen_info.theme = NULL;
399
400 }
401
402
403
404 static Evas_Object *_create_conformant(Evas_Object *win)
405 {
406         Evas_Object *conformant;
407
408         conformant = elm_conformant_add(win);
409         retv_if(NULL == conformant, NULL);
410
411         evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
412         elm_win_indicator_mode_set(menu_screen_info.win, ELM_WIN_INDICATOR_SHOW);
413         elm_object_signal_emit(conformant, "elm,state,indicator,overlap", "elm");
414         evas_object_data_set(conformant, "win", win);
415         evas_object_show(conformant);
416
417         elm_win_resize_object_add(win, conformant);
418         elm_win_conformant_set(win, EINA_TRUE);
419
420         return conformant;
421 }
422
423
424
425 static void _destroy_conformant(Evas_Object *conformant)
426 {
427         evas_object_data_del(conformant, "win");
428         evas_object_del(conformant);
429 }
430
431
432 static char *_replace_str(char *str, const char *before, const char *after)
433 {
434         retv_if(NULL == str, NULL);
435         retv_if(NULL == before, NULL);
436         retv_if(NULL == after, NULL);
437
438         size_t before_len = strlen(before);
439         retv_if(before_len < 1, str);
440
441         size_t after_len = strlen(after);
442         size_t i, count = 0;
443         if (after_len != before_len) {
444                 for (i = 0; str[i] != '\0';) {
445                         if (0 == memcmp(&str[i], before, before_len)) {
446                                 count++;
447                                 i += before_len;
448                         } else {
449                                 i++;
450                         }
451                 }
452         } else {
453                 i = strlen(str);
454         }
455
456         char *result;
457         result = malloc(i + 1 + count * (after_len - before_len));
458         retv_if(result == NULL, NULL);
459
460         char *sr;
461         sr = result;
462         while (*str) {
463                 if (0 == memcmp(str, before, before_len)) {
464                         memcpy(sr, after, after_len);
465                         sr += after_len;
466                         str += before_len;
467                 } else {
468                         *sr++ = *str++;
469                 }
470         }
471         *sr = '\0';
472
473         return result;
474 }
475
476
477
478 static bool _create_cb(void *data)
479 {
480         Evas_Object *conformant;
481
482         _init_theme();
483         retv_if(MENU_SCREEN_ERROR_FAIL == _create_canvas(PACKAGE, PACKAGE), false);
484
485         //if (system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, _change_bg_cb, NULL) < 0) {
486         //      _E("Failed to register a settings change cb for %s\n", SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN);
487         //}
488         _create_bg();
489
490         conformant = _create_conformant(menu_screen_info.win);
491         retv_if(NULL == conformant, false);
492         evas_object_data_set(menu_screen_info.win, "conformant", conformant);
493
494         Evas_Object *layout;
495         layout = layout_create(conformant, LAYOUT_EDJE_PORTRAIT,
496                                 LAYOUT_GROUP_NAME, MENU_SCREEN_ROTATE_PORTRAIT);
497         if (NULL == layout) {
498                 _E("Failed to load an edje object");
499                 evas_object_del(menu_screen_info.win);
500                 return false;
501         }
502         evas_object_data_set(menu_screen_info.win, "layout", layout);
503
504         elm_object_content_set(conformant, layout);
505
506         mouse_register();
507         aul_listen_app_dead_signal(_dead_cb, NULL);
508         key_register();
509
510         // FIXME : This will be enabled after rebuilding the routine for appid <-> pkgid.
511         pkgmgr_init();
512
513         return true;
514 }
515
516
517
518 static void _terminate_cb(void *data)
519 {
520         Evas_Object *conformant;
521         Evas_Object *layout;
522
523         // FIXME : This will be enabled after rebuilding the routine for appid <-> pkgid.
524         pkgmgr_fini();
525
526         if (system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN) < 0) {
527                 _E("Failed to remove bgset [%s]\n", SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN);
528         }
529
530         evas_object_hide(menu_screen_info.win);
531
532         key_unregister();
533         mouse_unregister();
534
535         layout = evas_object_data_del(menu_screen_info.win, "layout");
536         if (layout) layout_destroy(layout);
537
538         conformant = evas_object_data_del(menu_screen_info.win, "conformant");
539         if (conformant) _destroy_conformant(conformant);
540
541         _destroy_bg();
542         _destroy_canvas();
543         _fini_theme();
544         evas_object_del(menu_screen_info.win);
545 }
546
547
548
549 static void _pause_cb(void *data)
550 {
551         _D("Pause start");
552
553         menu_screen_info.state = APP_STATE_PAUSE;
554 }
555
556
557
558 static void _resume_cb(void *data)
559 {
560         _D("START RESUME");
561
562         do { // Focus
563                 Evas_Object *layout = evas_object_data_get(menu_screen_info.win, "layout");
564                 break_if(NULL == layout);
565
566                 Evas_Object *all_apps = evas_object_data_get(layout, "all_apps");
567                 break_if(NULL == all_apps);
568
569                 Evas_Object *scroller = elm_object_part_content_get(all_apps, "content");
570                 break_if(NULL == scroller);
571
572                 page_scroller_focus(scroller);
573         } while (0);
574
575         menu_screen_info.state = APP_STATE_RESUME;
576 }
577
578
579
580 static void _app_control_cb(app_control_h service, void *data)
581 {
582         _D("START RESET : %d", menu_screen_info.state);
583
584         do { // Focus
585                 Evas_Object *layout = evas_object_data_get(menu_screen_info.win, "layout");
586                 break_if(NULL == layout);
587
588                 Evas_Object *all_apps = evas_object_data_get(layout, "all_apps");
589                 break_if(NULL == all_apps);
590
591                 Evas_Object *scroller = elm_object_part_content_get(all_apps, "content");
592                 break_if(NULL == scroller);
593
594                 page_scroller_focus(scroller);
595         } while (0);
596 }
597
598
599
600 static void _language_changed_cb(app_event_info_h event_info, void *data)
601 {
602         register unsigned int i;
603         register unsigned int j;
604         unsigned int count;
605         Evas_Object *layout;
606         Evas_Object *all_apps;
607         Evas_Object *scroller;
608         Evas_Object *page;
609         Evas_Object *item;
610         unsigned int page_max_app;
611
612         _D("Language is changed");
613
614         if (false == menu_screen_info.is_done) {
615                 elm_exit();
616         }
617
618         layout = evas_object_data_get(menu_screen_info.win, "layout");
619         ret_if(NULL == layout);
620         all_apps = evas_object_data_get(layout, "all_apps");
621         ret_if(NULL == all_apps);
622         scroller = elm_object_part_content_get(all_apps, "content");
623         ret_if(NULL == scroller);
624
625         count = page_scroller_count_page(scroller);
626         page_max_app = (unsigned int) evas_object_data_get(scroller, "page_max_app");
627         for (i = 0; i < count; i ++) {
628                 page = page_scroller_get_page_at(scroller, i);
629                 if (!page) continue;
630                 if (mapbuf_is_enabled(page)) {
631                         mapbuf_disable(page, 1);
632                 }
633
634                 for (j = 0; j < page_max_app; j ++) {
635                         pkgmgrinfo_appinfo_h appinfo_h = NULL;
636                         char *name;
637
638                         item = page_get_item_at(page, j);
639                         if (!item) continue;
640
641                         if (pkgmgrinfo_appinfo_get_appinfo(item_get_package(item), &appinfo_h) < 0) {
642                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
643                                 continue;
644                         }
645                         if (pkgmgrinfo_appinfo_get_label(appinfo_h, &name) < 0) {
646                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
647                                 continue;
648                         }
649
650                         if (!name) {
651                                 _D("Failed to get name for %s", item_get_package(item));
652                                 pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
653                                 continue;
654                         }
655
656                         item_set_name(item, name, 0);
657                         pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h);
658                 }
659
660                 mapbuf_enable(page, 1);
661         }
662 }
663
664
665
666 static void _init(ui_app_lifecycle_callback_s *lifecycle_callback, app_event_handler_h *event_handlers)
667 {
668         lifecycle_callback->create = _create_cb;
669         lifecycle_callback->terminate = _terminate_cb;
670         lifecycle_callback->pause = _pause_cb;
671         lifecycle_callback->resume = _resume_cb;
672         lifecycle_callback->app_control = _app_control_cb;
673
674         ui_app_add_event_handler(&event_handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, NULL, NULL);
675         ui_app_add_event_handler(&event_handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, NULL, NULL);
676         ui_app_add_event_handler(&event_handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, NULL, NULL);
677         ui_app_add_event_handler(&event_handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, _language_changed_cb, NULL);
678         ui_app_add_event_handler(&event_handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, NULL, NULL);
679
680 }
681
682
683
684 static void _fini(app_event_handler_h *event_handlers)
685 {
686         ui_app_remove_event_handler(event_handlers[APP_EVENT_LOW_BATTERY]);
687         ui_app_remove_event_handler(event_handlers[APP_EVENT_LOW_MEMORY]);
688         ui_app_remove_event_handler(event_handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED]);
689         ui_app_remove_event_handler(event_handlers[APP_EVENT_LANGUAGE_CHANGED]);
690         ui_app_remove_event_handler(event_handlers[APP_EVENT_REGION_FORMAT_CHANGED]);
691
692 }
693
694
695
696 static void _init_reference_value(void)
697 {
698         preference_set_string(MENU_SCREEN_ENGINE, "gl");
699 }
700
701
702 int main(int argc, char *argv[])
703 {
704         char *buf;
705         ui_app_lifecycle_callback_s lifecycle_callback = {0, };
706         app_event_handler_h event_handlers[5] = {NULL, };
707
708         _init(&lifecycle_callback, event_handlers);
709         ui_app_main(argc, argv, &lifecycle_callback, NULL);
710         _fini(event_handlers);
711
712         return EXIT_SUCCESS;
713 }
714
715
716
717 // End of a file