e_policy/e_service: added policy system and tizen_ws_shell interfaces
[platform/upstream/enlightenment.git] / src / bin / e_main.c
1 #include "e.h"
2 #ifdef __linux__
3 # include <sys/prctl.h>
4 #endif
5
6 #define MAX_LEVEL 80
7
8 #define TS_DO
9 #ifdef TS_DO
10 # define TS(x)                                                    \
11   {                                                               \
12      t1 = ecore_time_unix_get();                                  \
13      printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, x); \
14      t2 = t1;                                                     \
15   }
16 static double t0, t1, t2;
17 #else
18 # define TS(x)
19 #endif
20 /*
21  * i need to make more use of these when i'm baffled as to when something is
22  * up. other hooks:
23  *
24  *      void *(*__malloc_hook)(size_t size, const void *caller);
25  *
26  *      void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
27  *
28  *      void *(*__memalign_hook)(size_t alignment, size_t size,
29  *                               const void *caller);
30  *
31  *      void (*__free_hook)(void *ptr, const void *caller);
32  *
33  *      void (*__malloc_initialize_hook)(void);
34  *
35  *      void (*__after_morecore_hook)(void);
36  *
37
38    static void my_init_hook(void);
39    static void my_free_hook(void *p, const void *caller);
40
41    static void (*old_free_hook)(void *ptr, const void *caller) = NULL;
42    void (*__free_hook)(void *ptr, const void *caller);
43
44    void (*__malloc_initialize_hook) (void) = my_init_hook;
45    static void
46    my_init_hook(void)
47    {
48    old_free_hook = __free_hook;
49    __free_hook = my_free_hook;
50    }
51
52    //void *magicfree = NULL;
53
54    static void
55    my_free_hook(void *p, const void *caller)
56    {
57    __free_hook = old_free_hook;
58    //   if ((p) && (p == magicfree))
59    //     {
60    //   printf("CAUGHT!!!!! %p ...\n", p);
61    //   abort();
62    //     }
63    free(p);
64    __free_hook = my_free_hook;
65    }
66  */
67
68 /* local function prototypes */
69 static void      _e_main_shutdown(int errcode);
70 static void      _e_main_shutdown_push(int (*func)(void));
71 static void      _e_main_parse_arguments(int argc, char **argv);
72 static Eina_Bool _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED);
73 static Eina_Bool _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED);
74 static Eina_Bool _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev);
75 static int       _e_main_dirs_init(void);
76 static int       _e_main_dirs_shutdown(void);
77 static int       _e_main_path_init(void);
78 static int       _e_main_path_shutdown(void);
79 static int       _e_main_screens_init(void);
80 static int       _e_main_screens_shutdown(void);
81 static void      _e_main_desk_save(void);
82 static void      _e_main_desk_restore(void);
83 static void      _e_main_modules_load(Eina_Bool safe_mode);
84 static Eina_Bool _e_main_cb_idle_before(void *data EINA_UNUSED);
85 static Eina_Bool _e_main_cb_idle_after(void *data EINA_UNUSED);
86 static void      _e_main_create_wm_ready(void);
87
88 /* local variables */
89 static Eina_Bool really_know = EINA_FALSE;
90 static Eina_Bool inloop = EINA_FALSE;
91 static jmp_buf x_fatal_buff;
92
93 static int _e_main_lvl = 0;
94 static int(*_e_main_shutdown_func[MAX_LEVEL]) (void);
95
96 static Ecore_Idle_Enterer *_idle_before = NULL;
97 static Ecore_Idle_Enterer *_idle_after = NULL;
98
99 static Ecore_Event_Handler *mod_init_end = NULL;
100
101 /* external variables */
102 E_API Eina_Bool e_precache_end = EINA_FALSE;
103 E_API Eina_Bool x_fatal = EINA_FALSE;
104 E_API Eina_Bool good = EINA_FALSE;
105 E_API Eina_Bool evil = EINA_FALSE;
106 E_API Eina_Bool starting = EINA_TRUE;
107 E_API Eina_Bool stopping = EINA_FALSE;
108 E_API Eina_Bool restart = EINA_FALSE;
109 E_API Eina_Bool e_nopause = EINA_FALSE;
110 EINTERN const char *e_first_frame = NULL;
111 EINTERN double e_first_frame_start_time = -1;
112
113 static Eina_Bool
114 _xdg_check_str(const char *env, const char *str)
115 {
116    const char *p;
117    size_t len;
118
119    len = strlen(str);
120    for (p = strstr(env, str); p; p++, p = strstr(p, str))
121      {
122         if ((!p[len]) || (p[len] == ':')) return EINA_TRUE;
123      }
124    return EINA_FALSE;
125 }
126
127 static void
128 _xdg_data_dirs_augment(void)
129 {
130    const char *s;
131    const char *p = e_prefix_get();
132    char newpath[4096], buf[4096];
133
134    if (!p) return;
135
136    s = getenv("XDG_DATA_DIRS");
137    if (s)
138      {
139         Eina_Bool pfxdata, pfx;
140
141         pfxdata = !_xdg_check_str(s, e_prefix_data_get());
142         snprintf(newpath, sizeof(newpath), "%s/share", p);
143         pfx = !_xdg_check_str(s, newpath);
144         if (pfxdata || pfx)
145           {
146              snprintf(buf, sizeof(buf), "%s%s%s%s%s",
147                pfxdata ? e_prefix_data_get() : "",
148                pfxdata ? ":" : "",
149                pfx ? newpath : "",
150                pfx ? ":" : "",
151                s);
152              e_util_env_set("XDG_DATA_DIRS", buf);
153           }
154      }
155    else
156      {
157         snprintf(buf, sizeof(buf), "%s:%s/share:/usr/local/share:/usr/share", e_prefix_data_get(), p);
158         e_util_env_set("XDG_DATA_DIRS", buf);
159      }
160
161    s = getenv("XDG_CONFIG_DIRS");
162    snprintf(newpath, sizeof(newpath), "%s/etc/xdg", p);
163    if (s)
164      {
165         if (!_xdg_check_str(s, newpath))
166           {
167              snprintf(buf, sizeof(buf), "%s:%s", newpath, s);
168              e_util_env_set("XDG_CONFIG_DIRS", buf);
169           }
170      }
171    else
172      {
173         snprintf(buf, sizeof(buf), "%s:/etc/xdg", newpath);
174         e_util_env_set("XDG_CONFIG_DIRS", buf);
175      }
176
177    if (!getenv("XDG_RUNTIME_DIR"))
178      {
179         const char *dir;
180
181         snprintf(buf, sizeof(buf), "/tmp/xdg-XXXXXX");
182         dir = mkdtemp(buf);
183         if (!dir) dir = "/tmp";
184         else
185           {
186              e_util_env_set("XDG_RUNTIME_DIR", dir);
187              snprintf(buf, sizeof(buf), "%s/.e-deleteme", dir);
188              ecore_file_mkdir(buf);
189           }
190      }
191
192    /* set menu prefix so we get our e menu */
193    if (!getenv("XDG_MENU_PREFIX"))
194      {
195         e_util_env_set("XDG_MENU_PREFIX", "e-");
196      }
197 }
198
199 static Eina_Bool
200 _e_main_subsystem_defer(void *data EINA_UNUSED)
201 {
202    int argc;
203    char **argv;
204
205    TRACE_DS_BEGIN(MAIN:SUBSYSTEMS DEFER);
206
207    ecore_app_args_get(&argc, &argv);
208
209    /* try to init delayed subsystems */
210
211    TRACE_DS_BEGIN(MAIN:DEFFERED EFL INIT);
212
213    TS("[DEFERRED] Edje Init");
214    if (!edje_init())
215      {
216         e_error_message_show(_("Enlightenment cannot initialize Edje!\n"));
217         TRACE_DS_END();
218         _e_main_shutdown(-1);
219      }
220    TS("[DEFERRED] Edje Init Done");
221    _e_main_shutdown_push(edje_shutdown);
222
223    TRACE_DS_END();
224    TRACE_DS_BEGIN(MAIN:DEFERRED INTERNAL SUBSYSTEMS INIT);
225
226    TS("[DEFERRED] Screens Init: win");
227    if (!e_win_init())
228      {
229         e_error_message_show(_("Enlightenment cannot setup elementary trap!\n"));
230         TRACE_DS_END();
231         _e_main_shutdown(-1);
232      }
233    TS("[DEFERRED] Screens Init: win Done");
234
235    TS("[DEFERRED] E_Dnd Init");
236    if (!e_dnd_init())
237      {
238         e_error_message_show(_("Enlightenment cannot set up its dnd system.\n"));
239         _e_main_shutdown(-1);
240      }
241    TS("[DEFERRED] E_Dnd Init Done");
242    _e_main_shutdown_push(e_dnd_shutdown);
243
244    TS("[DEFERRED] E_Pointer Init");
245    if (!e_pointer_init())
246      {
247         e_error_message_show(_("Enlightenment cannot set up its pointer system.\n"));
248         TRACE_DS_END();
249         _e_main_shutdown(-1);
250      }
251
252    TS("[DEFERRED] E_Pointer Init Done");
253    _e_main_shutdown_push(e_pointer_shutdown);
254
255    TS("[DEFERRED] E_Scale Init");
256    if (!e_scale_init())
257      {
258         e_error_message_show(_("Enlightenment cannot set up its scale system.\n"));
259         TRACE_DS_END();
260         _e_main_shutdown(-1);
261      }
262    TS("[DEFERRED] E_Scale Init Done");
263    _e_main_shutdown_push(e_scale_shutdown);
264
265    TS("[DEFERRED] E_Test_Helper Init");
266    e_test_helper_init();
267    _e_main_shutdown_push(e_test_helper_shutdown);
268    TS("[DEFERRED] E_Test_Helper Done");
269
270    TS("[DEFERRED] E_INFO_SERVER Init");
271    e_info_server_init();
272    _e_main_shutdown_push(e_info_server_shutdown);
273    TS("[DEFERRED] E_INFO_SERVER Done");
274
275    TRACE_DS_END();
276    TRACE_DS_BEGIN(MAIN:DEFERRED COMP JOB);
277
278    /* try to do deferred job of any subsystems*/
279    TS("[DEFERRED] Compositor's deferred job");
280    e_comp_deferred_job();
281    TS("[DEFERRED] Compositor's deferred job Done");
282
283    TRACE_DS_END();
284    if (e_config->use_e_policy)
285      {
286         TRACE_DS_BEGIN(MAIN:DEFERRED POLICY JOB);
287
288         TS("[DEFERRED] E_Policy's deferred job");
289         e_policy_deferred_job();
290         TS("[DEFERRED] E_Policy's deferred job Done");
291
292         TRACE_DS_END();
293      }
294    TRACE_DS_BEGIN(MAIN:DEFERRED MODULE JOB);
295
296    TS("[DEFERRED] E_Module's deferred job");
297    e_module_deferred_job();
298    TS("[DEFERRED] E_Module's deferred job Done");
299
300    TRACE_DS_END();
301    TRACE_DS_END();
302
303    return ECORE_CALLBACK_DONE;
304 }
305
306 static Eina_Bool
307 _e_main_deferred_job_schedule(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
308 {
309    PRCTL("[Winsys] all modules loaded");
310    ecore_idler_add(_e_main_subsystem_defer, NULL);
311    return ECORE_CALLBACK_DONE;
312 }
313
314 /* externally accessible functions */
315 int
316 main(int argc, char **argv)
317 {
318    Eina_Bool safe_mode = EINA_FALSE;
319    double t = 0.0, tstart = 0.0;
320    char *s = NULL, buff[32];
321    struct sigaction action;
322
323 #ifdef __linux__
324 # ifdef PR_SET_PTRACER
325 #  ifdef PR_SET_PTRACER_ANY
326    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
327 #  endif
328 # endif
329 #endif
330 #ifdef TS_DO
331    t0 = t1 = t2 = ecore_time_unix_get();
332    printf("ESTART(main) %1.5f\n", t0);
333 #endif
334    TRACE_DS_BEGIN(MAIN:BEGIN STARTUP);
335    TS("Begin Startup");
336    PRCTL("[Winsys] start of main");
337
338    /* trap deadly bug signals and allow some form of sane recovery */
339    /* or ability to gdb attach and debug at this point - better than your */
340    /* wm/desktop vanishing and not knowing what happened */
341
342    /* don't install SIGBUS handler */
343    /* Wayland shm sets up a sigbus handler for catching invalid shm region */
344    /* access. If we setup our sigbus handler here, then the wl-shm sigbus */
345    /* handler will not function properly */
346    if (!getenv("NOTIFY_SOCKET"))
347      {
348         TS("Signal Trap");
349         action.sa_sigaction = e_sigseg_act;
350         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
351         sigemptyset(&action.sa_mask);
352         sigaction(SIGSEGV, &action, NULL);
353
354         action.sa_sigaction = e_sigill_act;
355         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
356         sigemptyset(&action.sa_mask);
357         sigaction(SIGILL, &action, NULL);
358
359         action.sa_sigaction = e_sigfpe_act;
360         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
361         sigemptyset(&action.sa_mask);
362         sigaction(SIGFPE, &action, NULL);
363
364         action.sa_sigaction = e_sigabrt_act;
365         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
366         sigemptyset(&action.sa_mask);
367         sigaction(SIGABRT, &action, NULL);
368         TS("Signal Trap Done");
369      }
370
371    t = ecore_time_unix_get();
372    s = getenv("E_START_TIME");
373    if ((s) && (!getenv("E_RESTART_OK")))
374      {
375         tstart = atof(s);
376         if ((t - tstart) < 5.0) safe_mode = EINA_TRUE;
377      }
378    tstart = t;
379    snprintf(buff, sizeof(buff), "%1.1f", tstart);
380    e_util_env_set("E_START_TIME", buff);
381
382    if (getenv("E_START_MTRACK"))
383      e_util_env_set("MTRACK", NULL);
384    TS("Eina Init");
385    if (!eina_init())
386      {
387         e_error_message_show(_("Enlightenment cannot initialize Eina!\n"));
388         _e_main_shutdown(-1);
389      }
390    TS("Eina Init Done");
391    _e_main_shutdown_push(eina_shutdown);
392
393 #ifdef OBJECT_HASH_CHECK
394    TS("E_Object Hash Init");
395    e_object_hash_init();
396    TS("E_Object Hash Init Done");
397 #endif
398
399    TS("E_Log Init");
400    if (!e_log_init())
401      {
402         e_error_message_show(_("Enlightenment could not create a logging domain!\n"));
403         _e_main_shutdown(-1);
404      }
405    TS("E_Log Init Done");
406    _e_main_shutdown_push(e_log_shutdown);
407
408    TS("Determine Prefix");
409    if (!e_prefix_determine(argv[0]))
410      {
411         fprintf(stderr,
412                 "ERROR: Enlightenment cannot determine it's installed\n"
413                 "       prefix from the system or argv[0].\n"
414                 "       This is because it is not on Linux AND has been\n"
415                 "       executed strangely. This is unusual.\n");
416      }
417    TS("Determine Prefix Done");
418
419    /* for debugging by redirecting stdout of e to a log file to tail */
420    setvbuf(stdout, NULL, _IONBF, 0);
421
422    TS("Parse Arguments");
423    _e_main_parse_arguments(argc, argv);
424    TS("Parse Arguments Done");
425
426    /*** Initialize Core EFL Libraries We Need ***/
427
428    TS("Eet Init");
429    if (!eet_init())
430      {
431         e_error_message_show(_("Enlightenment cannot initialize Eet!\n"));
432         _e_main_shutdown(-1);
433      }
434    TS("Eet Init Done");
435    _e_main_shutdown_push(eet_shutdown);
436
437    /* Allow ecore to not load system modules.
438     * Without it ecore_init will block until dbus authentication
439     * and registration are complete.
440     */
441    ecore_app_no_system_modules();
442
443    TS("Ecore Init");
444    if (!ecore_init())
445      {
446         e_error_message_show(_("Enlightenment cannot initialize Ecore!\n"));
447         _e_main_shutdown(-1);
448      }
449    TS("Ecore Init Done");
450    _e_main_shutdown_push(ecore_shutdown);
451
452    e_first_frame = getenv("E_FIRST_FRAME");
453    if (e_first_frame && e_first_frame[0])
454      e_first_frame_start_time = ecore_time_get();
455    else
456      e_first_frame = NULL;
457
458    TS("EIO Init");
459    if (!eio_init())
460      {
461         e_error_message_show(_("Enlightenment cannot initialize EIO!\n"));
462         _e_main_shutdown(-1);
463      }
464    TS("EIO Init Done");
465    _e_main_shutdown_push(eio_shutdown);
466
467    ecore_app_args_set(argc, (const char **)argv);
468
469    TS("Ecore Event Handlers");
470    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT,
471                                 _e_main_cb_signal_exit, NULL))
472      {
473         e_error_message_show(_("Enlightenment cannot set up an exit signal handler.\n"
474                                "Perhaps you are out of memory?"));
475         _e_main_shutdown(-1);
476      }
477    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_HUP,
478                                 _e_main_cb_signal_hup, NULL))
479      {
480         e_error_message_show(_("Enlightenment cannot set up a HUP signal handler.\n"
481                                "Perhaps you are out of memory?"));
482         _e_main_shutdown(-1);
483      }
484    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
485                                 _e_main_cb_signal_user, NULL))
486      {
487         e_error_message_show(_("Enlightenment cannot set up a USER signal handler.\n"
488                                "Perhaps you are out of memory?"));
489         _e_main_shutdown(-1);
490      }
491    TS("Ecore Event Handlers Done");
492
493    TS("Ecore_File Init");
494    if (!ecore_file_init())
495      {
496         e_error_message_show(_("Enlightenment cannot initialize Ecore_File!\n"));
497         _e_main_shutdown(-1);
498      }
499    TS("Ecore_File Init Done");
500    _e_main_shutdown_push(ecore_file_shutdown);
501
502    _idle_before = ecore_idle_enterer_before_add(_e_main_cb_idle_before, NULL);
503
504    TS("XDG_DATA_DIRS Init");
505    _xdg_data_dirs_augment();
506    TS("XDG_DATA_DIRS Init Done");
507
508    TS("Ecore_Evas Init");
509    if (!ecore_evas_init())
510      {
511         e_error_message_show(_("Enlightenment cannot initialize Ecore_Evas!\n"));
512         _e_main_shutdown(-1);
513      }
514    TS("Ecore_Evas Init Done");
515
516    /* e doesn't sync to compositor - it should be one */
517    ecore_evas_app_comp_sync_set(0);
518
519
520    /*** Initialize E Subsystems We Need ***/
521
522    TS("E Directories Init");
523    /* setup directories we will be using for configurations storage etc. */
524    if (!_e_main_dirs_init())
525      {
526         e_error_message_show(_("Enlightenment cannot create directories in your home directory.\n"
527                                "Perhaps you have no home directory or the disk is full?"));
528         _e_main_shutdown(-1);
529      }
530    TS("E Directories Init Done");
531    _e_main_shutdown_push(_e_main_dirs_shutdown);
532
533    TS("E_Config Init");
534    if (!e_config_init())
535      {
536         e_error_message_show(_("Enlightenment cannot set up its config system.\n"));
537         _e_main_shutdown(-1);
538      }
539    TS("E_Config Init Done");
540    _e_main_shutdown_push(e_config_shutdown);
541
542    TS("E_Env Init");
543    if (!e_env_init())
544      {
545         e_error_message_show(_("Enlightenment cannot set up its environment.\n"));
546         _e_main_shutdown(-1);
547      }
548    TS("E_Env Init Done");
549    _e_main_shutdown_push(e_env_shutdown);
550
551    ecore_exe_run_priority_set(e_config->priority);
552
553    TS("E Paths Init");
554    if (!_e_main_path_init())
555      {
556         e_error_message_show(_("Enlightenment cannot set up paths for finding files.\n"
557                                "Perhaps you are out of memory?"));
558         _e_main_shutdown(-1);
559      }
560    TS("E Paths Init Done");
561    _e_main_shutdown_push(_e_main_path_shutdown);
562
563    ecore_animator_frametime_set(1.0 / e_config->framerate);
564
565    TS("E_Theme Init");
566    if (!e_theme_init())
567      {
568         e_error_message_show(_("Enlightenment cannot set up its theme system.\n"));
569         _e_main_shutdown(-1);
570      }
571    TS("E_Theme Init Done");
572    _e_main_shutdown_push(e_theme_shutdown);
573
574    TS("E_Actions Init");
575    if (!e_actions_init())
576      {
577         e_error_message_show(_("Enlightenment cannot set up its actions system.\n"));
578         _e_main_shutdown(-1);
579      }
580    TS("E_Actions Init Done");
581    _e_main_shutdown_push(e_actions_shutdown);
582
583    /* these just add event handlers and can't fail
584     * timestamping them is dumb.
585     */
586    e_screensaver_preinit();
587    e_zone_init();
588    e_desk_init();
589
590    TRACE_DS_BEGIN(MAIN:WAIT /dev/dri/card0);
591    if (e_config->sleep_for_dri)
592      {
593         while(access("/dev/dri/card0", F_OK) != 0)
594           {
595              struct timespec req, rem;
596              req.tv_sec = 0;
597              req.tv_nsec = 50000000L;
598              nanosleep(&req, &rem);
599           }
600      }
601    TRACE_DS_END();
602
603    TRACE_DS_BEGIN(MAIN:SCREEN INIT);
604    TS("Screens Init");
605    if (!_e_main_screens_init())
606      {
607         e_error_message_show(_("Enlightenment set up window management for all the screens on your system\n"
608                                "failed. Perhaps another window manager is running?\n"));
609         _e_main_shutdown(-1);
610      }
611    TS("Screens Init Done");
612    _e_main_shutdown_push(_e_main_screens_shutdown);
613    TRACE_DS_END();
614
615    TS("E_Screensaver Init");
616    if (!e_screensaver_init())
617      {
618         e_error_message_show(_("Enlightenment cannot configure the X screensaver.\n"));
619         _e_main_shutdown(-1);
620      }
621    TS("E_Screensaver Init Done");
622    _e_main_shutdown_push(e_screensaver_shutdown);
623
624    TS("E_Comp Freeze");
625    e_comp_all_freeze();
626    TS("E_Comp Freeze Done");
627
628    TS("E_Grabinput Init");
629    if (!e_grabinput_init())
630      {
631         e_error_message_show(_("Enlightenment cannot set up its grab input handling system.\n"));
632         _e_main_shutdown(-1);
633      }
634    TS("E_Grabinput Init Done");
635    _e_main_shutdown_push(e_grabinput_shutdown);
636
637    ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_deferred_job_schedule, NULL);
638
639    TS("E_Module Init");
640    if (!e_module_init())
641      {
642         e_error_message_show(_("Enlightenment cannot set up its module system.\n"));
643         _e_main_shutdown(-1);
644      }
645    TS("E_Module Init Done");
646    _e_main_shutdown_push(e_module_shutdown);
647
648    TS("E_Remember Init");
649    if (!e_remember_init())
650      {
651         e_error_message_show(_("Enlightenment cannot setup remember settings.\n"));
652         _e_main_shutdown(-1);
653      }
654    TS("E_Remember Init Done");
655    _e_main_shutdown_push(e_remember_shutdown);
656
657    TS("E_Mouse Init");
658    if (!e_mouse_update())
659      {
660         e_error_message_show(_("Enlightenment cannot configure the mouse settings.\n"));
661         _e_main_shutdown(-1);
662      }
663    TS("E_Mouse Init Done");
664
665    TS("E_Icon Init");
666    if (!e_icon_init())
667      {
668         e_error_message_show(_("Enlightenment cannot initialize the Icon Cache system.\n"));
669         _e_main_shutdown(-1);
670      }
671    TS("E_Icon Init Done");
672    _e_main_shutdown_push(e_icon_shutdown);
673
674    if (e_config->use_e_policy)
675      {
676         TS("E_Policy Init");
677         if (!e_policy_init())
678           {
679              e_error_message_show(_("Enlightenment cannot setup policy system!\n"));
680              _e_main_shutdown(-1);
681           }
682         TS("E_Policy Init Done");
683         _e_main_shutdown_push(e_policy_shutdown);
684      }
685
686    TS("Load Modules");
687    _e_main_modules_load(safe_mode);
688    TS("Load Modules Done");
689
690    TS("E_Comp Thaw");
691    e_comp_all_thaw();
692    TS("E_Comp Thaw Done");
693
694    _idle_after = ecore_idle_enterer_add(_e_main_cb_idle_after, NULL);
695
696    starting = EINA_FALSE;
697    inloop = EINA_TRUE;
698
699    e_util_env_set("E_RESTART", "1");
700
701    TS("MAIN LOOP AT LAST");
702
703    if (e_config->create_wm_ready)
704      _e_main_create_wm_ready();
705
706    TRACE_DS_END();
707    if (!setjmp(x_fatal_buff))
708      ecore_main_loop_begin();
709    else
710      CRI("FATAL: X Died. Connection gone. Abbreviated Shutdown\n");
711
712    inloop = EINA_FALSE;
713    stopping = EINA_TRUE;
714
715    _e_main_desk_save();
716    e_remember_internal_save();
717    e_comp_internal_save();
718
719    _e_main_shutdown(0);
720
721    if (restart)
722      {
723         e_util_env_set("E_RESTART_OK", "1");
724         if (getenv("E_START_MTRACK"))
725           e_util_env_set("MTRACK", "track");
726         ecore_app_restart();
727      }
728
729    e_prefix_shutdown();
730
731    return 0;
732 }
733
734 E_API double
735 e_main_ts(const char *str)
736 {
737    double ret;
738    t1 = ecore_time_unix_get();
739    printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, str);
740    ret = t1 - t2;
741    t2 = t1;
742    return ret;
743 }
744
745 /* local functions */
746 static void
747 _e_main_shutdown(int errcode)
748 {
749    int i = 0;
750    char buf[PATH_MAX];
751    const char *dir;
752
753    printf("E: Begin Shutdown Procedure!\n");
754
755    if (_idle_before) ecore_idle_enterer_del(_idle_before);
756    _idle_before = NULL;
757    if (_idle_after) ecore_idle_enterer_del(_idle_after);
758    _idle_after = NULL;
759
760    dir = getenv("XDG_RUNTIME_DIR");
761    if (dir)
762      {
763         char buf_env[PATH_MAX];
764         snprintf(buf_env, sizeof(buf_env), "%s", dir);
765         snprintf(buf, sizeof(buf), "%s/.e-deleteme", buf_env);
766         if (ecore_file_exists(buf)) ecore_file_recursive_rm(buf_env);
767      }
768    for (i = (_e_main_lvl - 1); i >= 0; i--)
769      (*_e_main_shutdown_func[i])();
770 #ifdef OBJECT_HASH_CHECK
771    e_object_hash_shutdown();
772 #endif
773    if (errcode < 0) exit(errcode);
774 }
775
776 static void
777 _e_main_shutdown_push(int (*func)(void))
778 {
779    _e_main_lvl++;
780    if (_e_main_lvl > MAX_LEVEL)
781      {
782         _e_main_lvl--;
783         e_error_message_show("WARNING: too many init levels. MAX = %i\n",
784                              MAX_LEVEL);
785         return;
786      }
787    _e_main_shutdown_func[_e_main_lvl - 1] = func;
788 }
789
790 static void
791 _e_main_parse_arguments(int argc, char **argv)
792 {
793    int i = 0;
794
795    /* handle some command-line parameters */
796    for (i = 1; i < argc; i++)
797      {
798         if (!strcmp(argv[i], "-good"))
799           {
800              good = EINA_TRUE;
801              evil = EINA_FALSE;
802              printf("LA LA LA\n");
803           }
804         else if (!strcmp(argv[i], "-evil"))
805           {
806              good = EINA_FALSE;
807              evil = EINA_TRUE;
808              printf("MUHAHAHAHHAHAHAHAHA\n");
809           }
810         else if (!strcmp(argv[i], "-psychotic"))
811           {
812              good = EINA_TRUE;
813              evil = EINA_TRUE;
814              printf("MUHAHALALALALALALALA\n");
815           }
816         else if ((!strcmp(argv[i], "-profile")) && (i < (argc - 1)))
817           {
818              i++;
819              if (!getenv("E_CONF_PROFILE"))
820                e_util_env_set("E_CONF_PROFILE", argv[i]);
821           }
822         else if (!strcmp(argv[i], "-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it"))
823           really_know = EINA_TRUE;
824         else if (!strcmp(argv[i], "-nopause"))
825           e_nopause = EINA_TRUE;
826         else if ((!strcmp(argv[i], "-version")) ||
827                  (!strcmp(argv[i], "--version")))
828           {
829              printf(_("Version: %s\n"), PACKAGE_VERSION);
830              _e_main_shutdown(-1);
831           }
832         else if ((!strcmp(argv[i], "-h")) ||
833                  (!strcmp(argv[i], "-help")) ||
834                  (!strcmp(argv[i], "--help")))
835           {
836              printf
837                (_(
838                  "Options:\n"
839                  "\t-display DISPLAY\n"
840                  "\t\tConnect to display named DISPLAY.\n"
841                  "\t\tEG: -display :1.0\n"
842                  "\t-fake-xinerama-screen WxH+X+Y\n"
843                  "\t\tAdd a FAKE xinerama screen (instead of the real ones)\n"
844                  "\t\tgiven the geometry. Add as many as you like. They all\n"
845                  "\t\treplace the real xinerama screens, if any. This can\n"
846                  "\t\tbe used to simulate xinerama.\n"
847                  "\t\tEG: -fake-xinerama-screen 800x600+0+0 -fake-xinerama-screen 800x600+800+0\n"
848                  "\t-profile CONF_PROFILE\n"
849                  "\t\tUse the configuration profile CONF_PROFILE instead of the user selected default or just \"default\".\n"
850                  "\t-good\n"
851                  "\t\tBe good.\n"
852                  "\t-evil\n"
853                  "\t\tBe evil.\n"
854                  "\t-psychotic\n"
855                  "\t\tBe psychotic.\n"
856                  "\t-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it\n"
857                  "\t\tIf you need this help, you don't need this option.\n"
858                  "\t-version\n"
859                  )
860                );
861              _e_main_shutdown(-1);
862           }
863      }
864 }
865
866 EINTERN void
867 _e_main_cb_x_fatal(void *data EINA_UNUSED)
868 {
869    e_error_message_show("Lost X Connection.\n");
870    ecore_main_loop_quit();
871    if (!x_fatal)
872      {
873         x_fatal = EINA_TRUE;
874         if (inloop) longjmp(x_fatal_buff, -99);
875      }
876 }
877
878 static Eina_Bool
879 _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
880 {
881    /* called on ctrl-c, kill (pid) (also SIGINT, SIGTERM and SIGQIT) */
882    ecore_main_loop_quit();
883    return ECORE_CALLBACK_RENEW;
884 }
885
886 static Eina_Bool
887 _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
888 {
889    restart = 1;
890    ecore_main_loop_quit();
891    return ECORE_CALLBACK_RENEW;
892 }
893
894 static Eina_Bool
895 _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
896 {
897    Ecore_Event_Signal_User *e = ev;
898
899    if (e->number == 1)
900      {
901 //        E_Action *a = e_action_find("configuration");
902 //        if ((a) && (a->func.go)) a->func.go(NULL, NULL);
903      }
904    else if (e->number == 2)
905      {
906         // comp module has its own handler for this for enabling/disabling fps debug
907      }
908    return ECORE_CALLBACK_RENEW;
909
910 }
911
912 static int
913 _e_main_dirs_init(void)
914 {
915    const char *base;
916    const char *dirs[] =
917    {
918       "backgrounds",
919       "config",
920       "themes",
921       NULL
922    };
923
924    base = e_user_dir_get();
925    if (ecore_file_mksubdirs(base, dirs) != sizeof(dirs) / sizeof(dirs[0]) - 1)
926      {
927         e_error_message_show("Could not create one of the required "
928                              "subdirectories of '%s'\n", base);
929         return 0;
930      }
931
932    return 1;
933 }
934
935 static int
936 _e_main_dirs_shutdown(void)
937 {
938    return 1;
939 }
940
941 static int
942 _e_main_path_init(void)
943 {
944    char buf[PATH_MAX];
945
946    /* setup data paths */
947    path_data = e_path_new();
948    if (!path_data)
949      {
950         e_error_message_show("Cannot allocate path for path_data\n");
951         return 0;
952      }
953    e_prefix_data_concat_static(buf, "data");
954    e_path_default_path_append(path_data, buf);
955
956    /* setup image paths */
957    path_images = e_path_new();
958    if (!path_images)
959      {
960         e_error_message_show("Cannot allocate path for path_images\n");
961         return 0;
962      }
963    e_user_dir_concat_static(buf, "/images");
964    e_path_default_path_append(path_images, buf);
965    e_prefix_data_concat_static(buf, "data/images");
966    e_path_default_path_append(path_images, buf);
967
968    /* setup font paths */
969    path_fonts = e_path_new();
970    if (!path_fonts)
971      {
972         e_error_message_show("Cannot allocate path for path_fonts\n");
973         return 0;
974      }
975    e_user_dir_concat_static(buf, "/fonts");
976    e_path_default_path_append(path_fonts, buf);
977    e_prefix_data_concat_static(buf, "data/fonts");
978    e_path_default_path_append(path_fonts, buf);
979
980    /* setup icon paths */
981    path_icons = e_path_new();
982    if (!path_icons)
983      {
984         e_error_message_show("Cannot allocate path for path_icons\n");
985         return 0;
986      }
987    e_user_dir_concat_static(buf, "/icons");
988    e_path_default_path_append(path_icons, buf);
989    e_prefix_data_concat_static(buf, "data/icons");
990    e_path_default_path_append(path_icons, buf);
991
992    /* setup module paths */
993    path_modules = e_path_new();
994    if (!path_modules)
995      {
996         e_error_message_show("Cannot allocate path for path_modules\n");
997         return 0;
998      }
999    e_user_dir_concat_static(buf, "/modules");
1000    e_path_default_path_append(path_modules, buf);
1001    snprintf(buf, sizeof(buf), "%s/enlightenment/modules", e_prefix_lib_get());
1002    e_path_default_path_append(path_modules, buf);
1003    /* FIXME: eventually this has to go - moduels should have installers that
1004     * add appropriate install paths (if not installed to user homedir) to
1005     * e's module search dirs
1006     */
1007    snprintf(buf, sizeof(buf), "%s/enlightenment/modules_extra", e_prefix_lib_get());
1008    e_path_default_path_append(path_modules, buf);
1009
1010    /* setup background paths */
1011    path_backgrounds = e_path_new();
1012    if (!path_backgrounds)
1013      {
1014         e_error_message_show("Cannot allocate path for path_backgrounds\n");
1015         return 0;
1016      }
1017    e_user_dir_concat_static(buf, "/backgrounds");
1018    e_path_default_path_append(path_backgrounds, buf);
1019    e_prefix_data_concat_static(buf, "data/backgrounds");
1020    e_path_default_path_append(path_backgrounds, buf);
1021
1022    path_messages = e_path_new();
1023    if (!path_messages)
1024      {
1025         e_error_message_show("Cannot allocate path for path_messages\n");
1026         return 0;
1027      }
1028    e_user_dir_concat_static(buf, "/locale");
1029    e_path_default_path_append(path_messages, buf);
1030    e_path_default_path_append(path_messages, e_prefix_locale_get());
1031
1032    return 1;
1033 }
1034
1035 static int
1036 _e_main_path_shutdown(void)
1037 {
1038    if (path_data)
1039      {
1040         e_object_del(E_OBJECT(path_data));
1041         path_data = NULL;
1042      }
1043    if (path_images)
1044      {
1045         e_object_del(E_OBJECT(path_images));
1046         path_images = NULL;
1047      }
1048    if (path_fonts)
1049      {
1050         e_object_del(E_OBJECT(path_fonts));
1051         path_fonts = NULL;
1052      }
1053    if (path_icons)
1054      {
1055         e_object_del(E_OBJECT(path_icons));
1056         path_icons = NULL;
1057      }
1058    if (path_modules)
1059      {
1060         e_object_del(E_OBJECT(path_modules));
1061         path_modules = NULL;
1062      }
1063    if (path_backgrounds)
1064      {
1065         e_object_del(E_OBJECT(path_backgrounds));
1066         path_backgrounds = NULL;
1067      }
1068    if (path_messages)
1069      {
1070         e_object_del(E_OBJECT(path_messages));
1071         path_messages = NULL;
1072      }
1073    return 1;
1074 }
1075
1076 static int
1077 _e_main_screens_init(void)
1078 {
1079    TS("\tscreens: client");
1080    if (!e_client_init()) return 0;
1081
1082    TS("Compositor Init");
1083    PRCTL("[Winsys] start of compositor init");
1084    if (!e_comp_init())
1085      {
1086         e_error_message_show(_("Enlightenment cannot create a compositor.\n"));
1087         _e_main_shutdown(-1);
1088      }
1089
1090    PRCTL("[Winsys] end of compositor init");
1091    _e_main_desk_restore();
1092
1093    return 1;
1094 }
1095
1096 static int
1097 _e_main_screens_shutdown(void)
1098 {
1099    e_win_shutdown();
1100    e_comp_shutdown();
1101    e_client_shutdown();
1102
1103    e_desk_shutdown();
1104    e_zone_shutdown();
1105    return 1;
1106 }
1107
1108 static void
1109 _e_main_desk_save(void)
1110 {
1111    const Eina_List *l;
1112    char env[1024], name[1024];
1113    E_Zone *zone;
1114
1115    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1116      {
1117         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1118         snprintf(env, sizeof(env), "%d,%d", zone->desk_x_current, zone->desk_y_current);
1119         e_util_env_set(name, env);
1120      }
1121 }
1122
1123 static void
1124 _e_main_desk_restore(void)
1125 {
1126    const Eina_List *l;
1127    E_Zone *zone;
1128    E_Client *ec;
1129    char *env;
1130    char name[1024];
1131
1132    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1133      {
1134         E_Desk *desk;
1135         int desk_x, desk_y;
1136         char buf_e[64];
1137
1138         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1139         env = getenv(name);
1140         if (!env) continue;
1141         snprintf(buf_e, sizeof(buf_e), "%s", env);
1142         if (!sscanf(buf_e, "%d,%d", &desk_x, &desk_y)) continue;
1143         desk = e_desk_at_xy_get(zone, desk_x, desk_y);
1144         if (!desk) continue;
1145         e_desk_show(desk);
1146      }
1147
1148    E_CLIENT_REVERSE_FOREACH(ec)
1149      if ((!e_client_util_ignored_get(ec)) && e_client_util_desk_visible(ec, e_desk_current_get(ec->zone)))
1150        {
1151           ec->want_focus = ec->take_focus = 1;
1152           break;
1153        }
1154 }
1155
1156 static Eina_Bool
1157 _e_main_modules_load_after(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
1158 {
1159    E_FREE_FUNC(mod_init_end, ecore_event_handler_del);
1160    return ECORE_CALLBACK_RENEW;
1161 }
1162
1163 static void
1164 _e_main_modules_load(Eina_Bool safe_mode)
1165 {
1166    if (!safe_mode)
1167      e_module_all_load();
1168    else
1169      {
1170         E_Module *m;
1171         char *crashmodule;
1172
1173         crashmodule = getenv("E_MODULE_LOAD");
1174         if (crashmodule) m = e_module_new(crashmodule);
1175
1176         if ((crashmodule) && (m))
1177           {
1178              e_module_disable(m);
1179              e_object_del(E_OBJECT(m));
1180
1181              e_error_message_show
1182                (_("Enlightenment crashed early on start and has<br>"
1183                   "been restarted. There was an error loading the<br>"
1184                   "module named: %s. This module has been disabled<br>"
1185                   "and will not be loaded."), crashmodule);
1186              e_util_dialog_show
1187                (_("Enlightenment crashed early on start and has been restarted"),
1188                _("Enlightenment crashed early on start and has been restarted.<br>"
1189                  "There was an error loading the module named: %s<br><br>"
1190                  "This module has been disabled and will not be loaded."), crashmodule);
1191              e_module_all_load();
1192           }
1193         else
1194           {
1195              e_error_message_show
1196                (_("Enlightenment crashed early on start and has<br>"
1197                   "been restarted. All modules have been disabled<br>"
1198                   "and will not be loaded to help remove any problem<br>"
1199                   "modules from your configuration. The module<br>"
1200                   "configuration dialog should let you select your<br>"
1201                   "modules again.\n"));
1202              e_util_dialog_show
1203                (_("Enlightenment crashed early on start and has been restarted"),
1204                _("Enlightenment crashed early on start and has been restarted.<br>"
1205                  "All modules have been disabled and will not be loaded to help<br>"
1206                  "remove any problem modules from your configuration.<br><br>"
1207                  "The module configuration dialog should let you select your<br>"
1208                  "modules again."));
1209           }
1210         mod_init_end = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_modules_load_after, NULL);
1211      }
1212 }
1213
1214 static Eina_Bool
1215 _e_main_cb_idle_before(void *data EINA_UNUSED)
1216 {
1217    e_client_idler_before();
1218    e_pointer_idler_before();
1219    edje_thaw();
1220    return ECORE_CALLBACK_RENEW;
1221 }
1222
1223 static Eina_Bool
1224 _e_main_cb_idle_after(void *data EINA_UNUSED)
1225 {
1226    static int first_idle = 1;
1227
1228    eet_clearcache();
1229    edje_freeze();
1230
1231 #ifdef E_RELEASE_BUILD
1232    if (first_idle)
1233      {
1234         TS("SLEEP");
1235         first_idle = 0;
1236         e_precache_end = EINA_TRUE;
1237      }
1238 #else
1239    if (first_idle++ < 60)
1240      {
1241         TS("SLEEP");
1242         if (!first_idle)
1243           e_precache_end = EINA_TRUE;
1244      }
1245 #endif
1246
1247    return ECORE_CALLBACK_RENEW;
1248 }
1249
1250 static void
1251 _e_main_create_wm_ready(void)
1252 {
1253    FILE *_wmready_checker = NULL;
1254
1255    _wmready_checker = fopen("/run/.wm_ready", "wb");
1256    if (_wmready_checker)
1257      {
1258         TS("[WM] WINDOW MANAGER is READY!!!");
1259         PRCTL("[Winsys] WINDOW MANAGER is READY!!!");
1260         fclose(_wmready_checker);
1261
1262         /*TODO: Next lines should be removed. */
1263         FILE *_tmp_wm_ready_checker;
1264         _tmp_wm_ready_checker = fopen("/tmp/.wm_ready", "wb");
1265
1266         if (_tmp_wm_ready_checker)
1267           {
1268              TS("[WM] temporary wm_ready path is created.");
1269              PRCTL("[Winsys] temporary wm_ready path is created.");
1270              fclose(_tmp_wm_ready_checker);
1271           }
1272         else
1273           {
1274              TS("[WM] temporary wm_ready path create failed.");
1275              PRCTL("[Winsys] temporary wm_ready path create failed.");
1276           }
1277      }
1278    else
1279      {
1280         TS("[WM] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1281         PRCTL("[Winsys] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1282      }
1283 }