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