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