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