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