e_main: removed E_START env var check because we are executing e directly.
[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
842 EINTERN void
843 _e_main_cb_x_fatal(void *data EINA_UNUSED)
844 {
845    e_error_message_show("Lost X Connection.\n");
846    ecore_main_loop_quit();
847    if (!x_fatal)
848      {
849         x_fatal = EINA_TRUE;
850         if (inloop) longjmp(x_fatal_buff, -99);
851      }
852 }
853
854 static Eina_Bool
855 _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
856 {
857    /* called on ctrl-c, kill (pid) (also SIGINT, SIGTERM and SIGQIT) */
858    ecore_main_loop_quit();
859    return ECORE_CALLBACK_RENEW;
860 }
861
862 static Eina_Bool
863 _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
864 {
865    restart = 1;
866    ecore_main_loop_quit();
867    return ECORE_CALLBACK_RENEW;
868 }
869
870 static Eina_Bool
871 _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
872 {
873    Ecore_Event_Signal_User *e = ev;
874
875    if (e->number == 1)
876      {
877 //        E_Action *a = e_action_find("configuration");
878 //        if ((a) && (a->func.go)) a->func.go(NULL, NULL);
879      }
880    else if (e->number == 2)
881      {
882         // comp module has its own handler for this for enabling/disabling fps debug
883      }
884    return ECORE_CALLBACK_RENEW;
885
886 }
887
888 static int
889 _e_main_dirs_init(void)
890 {
891    const char *base;
892    const char *dirs[] =
893    {
894       "backgrounds",
895       "config",
896       "themes",
897       NULL
898    };
899
900    base = e_user_dir_get();
901    if (ecore_file_mksubdirs(base, dirs) != sizeof(dirs) / sizeof(dirs[0]) - 1)
902      {
903         e_error_message_show("Could not create one of the required "
904                              "subdirectories of '%s'\n", base);
905         return 0;
906      }
907
908    return 1;
909 }
910
911 static int
912 _e_main_dirs_shutdown(void)
913 {
914    return 1;
915 }
916
917 static int
918 _e_main_path_init(void)
919 {
920    char buf[PATH_MAX];
921
922    /* setup data paths */
923    path_data = e_path_new();
924    if (!path_data)
925      {
926         e_error_message_show("Cannot allocate path for path_data\n");
927         return 0;
928      }
929    e_prefix_data_concat_static(buf, "data");
930    e_path_default_path_append(path_data, buf);
931
932    /* setup image paths */
933    path_images = e_path_new();
934    if (!path_images)
935      {
936         e_error_message_show("Cannot allocate path for path_images\n");
937         return 0;
938      }
939    e_user_dir_concat_static(buf, "/images");
940    e_path_default_path_append(path_images, buf);
941    e_prefix_data_concat_static(buf, "data/images");
942    e_path_default_path_append(path_images, buf);
943
944    /* setup font paths */
945    path_fonts = e_path_new();
946    if (!path_fonts)
947      {
948         e_error_message_show("Cannot allocate path for path_fonts\n");
949         return 0;
950      }
951    e_user_dir_concat_static(buf, "/fonts");
952    e_path_default_path_append(path_fonts, buf);
953    e_prefix_data_concat_static(buf, "data/fonts");
954    e_path_default_path_append(path_fonts, buf);
955
956    /* setup icon paths */
957    path_icons = e_path_new();
958    if (!path_icons)
959      {
960         e_error_message_show("Cannot allocate path for path_icons\n");
961         return 0;
962      }
963    e_user_dir_concat_static(buf, "/icons");
964    e_path_default_path_append(path_icons, buf);
965    e_prefix_data_concat_static(buf, "data/icons");
966    e_path_default_path_append(path_icons, buf);
967
968    /* setup module paths */
969    path_modules = e_path_new();
970    if (!path_modules)
971      {
972         e_error_message_show("Cannot allocate path for path_modules\n");
973         return 0;
974      }
975    e_user_dir_concat_static(buf, "/modules");
976    e_path_default_path_append(path_modules, buf);
977    snprintf(buf, sizeof(buf), "%s/enlightenment/modules", e_prefix_lib_get());
978    e_path_default_path_append(path_modules, buf);
979    /* FIXME: eventually this has to go - moduels should have installers that
980     * add appropriate install paths (if not installed to user homedir) to
981     * e's module search dirs
982     */
983    snprintf(buf, sizeof(buf), "%s/enlightenment/modules_extra", e_prefix_lib_get());
984    e_path_default_path_append(path_modules, buf);
985
986    /* setup background paths */
987    path_backgrounds = e_path_new();
988    if (!path_backgrounds)
989      {
990         e_error_message_show("Cannot allocate path for path_backgrounds\n");
991         return 0;
992      }
993    e_user_dir_concat_static(buf, "/backgrounds");
994    e_path_default_path_append(path_backgrounds, buf);
995    e_prefix_data_concat_static(buf, "data/backgrounds");
996    e_path_default_path_append(path_backgrounds, buf);
997
998    path_messages = e_path_new();
999    if (!path_messages)
1000      {
1001         e_error_message_show("Cannot allocate path for path_messages\n");
1002         return 0;
1003      }
1004    e_user_dir_concat_static(buf, "/locale");
1005    e_path_default_path_append(path_messages, buf);
1006    e_path_default_path_append(path_messages, e_prefix_locale_get());
1007
1008    return 1;
1009 }
1010
1011 static int
1012 _e_main_path_shutdown(void)
1013 {
1014    if (path_data)
1015      {
1016         e_object_del(E_OBJECT(path_data));
1017         path_data = NULL;
1018      }
1019    if (path_images)
1020      {
1021         e_object_del(E_OBJECT(path_images));
1022         path_images = NULL;
1023      }
1024    if (path_fonts)
1025      {
1026         e_object_del(E_OBJECT(path_fonts));
1027         path_fonts = NULL;
1028      }
1029    if (path_icons)
1030      {
1031         e_object_del(E_OBJECT(path_icons));
1032         path_icons = NULL;
1033      }
1034    if (path_modules)
1035      {
1036         e_object_del(E_OBJECT(path_modules));
1037         path_modules = NULL;
1038      }
1039    if (path_backgrounds)
1040      {
1041         e_object_del(E_OBJECT(path_backgrounds));
1042         path_backgrounds = NULL;
1043      }
1044    if (path_messages)
1045      {
1046         e_object_del(E_OBJECT(path_messages));
1047         path_messages = NULL;
1048      }
1049    return 1;
1050 }
1051
1052 static int
1053 _e_main_screens_init(void)
1054 {
1055    TS("\tscreens: client");
1056    if (!e_client_init()) return 0;
1057
1058    TS("Compositor Init");
1059    PRCTL("[Winsys] start of compositor init");
1060    if (!e_comp_init())
1061      {
1062         e_error_message_show(_("Enlightenment cannot create a compositor.\n"));
1063         _e_main_shutdown(-1);
1064      }
1065
1066    PRCTL("[Winsys] end of compositor init");
1067    _e_main_desk_restore();
1068
1069    return 1;
1070 }
1071
1072 static int
1073 _e_main_screens_shutdown(void)
1074 {
1075    e_win_shutdown();
1076    e_comp_shutdown();
1077    e_client_shutdown();
1078
1079    e_desk_shutdown();
1080    e_zone_shutdown();
1081    return 1;
1082 }
1083
1084 static void
1085 _e_main_desk_save(void)
1086 {
1087    const Eina_List *l;
1088    char env[1024], name[1024];
1089    E_Zone *zone;
1090
1091    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1092      {
1093         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1094         snprintf(env, sizeof(env), "%d,%d", zone->desk_x_current, zone->desk_y_current);
1095         e_util_env_set(name, env);
1096      }
1097 }
1098
1099 static void
1100 _e_main_desk_restore(void)
1101 {
1102    const Eina_List *l;
1103    E_Zone *zone;
1104    E_Client *ec;
1105    char *env;
1106    char name[1024];
1107
1108    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1109      {
1110         E_Desk *desk;
1111         int desk_x, desk_y;
1112         char buf_e[64];
1113
1114         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1115         env = getenv(name);
1116         if (!env) continue;
1117         snprintf(buf_e, sizeof(buf_e), "%s", env);
1118         if (!sscanf(buf_e, "%d,%d", &desk_x, &desk_y)) continue;
1119         desk = e_desk_at_xy_get(zone, desk_x, desk_y);
1120         if (!desk) continue;
1121         e_desk_show(desk);
1122      }
1123
1124    E_CLIENT_REVERSE_FOREACH(ec)
1125      if ((!e_client_util_ignored_get(ec)) && e_client_util_desk_visible(ec, e_desk_current_get(ec->zone)))
1126        {
1127           ec->want_focus = ec->take_focus = 1;
1128           break;
1129        }
1130 }
1131
1132 static Eina_Bool
1133 _e_main_modules_load_after(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
1134 {
1135    E_FREE_FUNC(mod_init_end, ecore_event_handler_del);
1136    return ECORE_CALLBACK_RENEW;
1137 }
1138
1139 static void
1140 _e_main_modules_load(Eina_Bool safe_mode)
1141 {
1142    if (!safe_mode)
1143      e_module_all_load();
1144    else
1145      {
1146         E_Module *m;
1147         char *crashmodule;
1148
1149         crashmodule = getenv("E_MODULE_LOAD");
1150         if (crashmodule) m = e_module_new(crashmodule);
1151
1152         if ((crashmodule) && (m))
1153           {
1154              e_module_disable(m);
1155              e_object_del(E_OBJECT(m));
1156
1157              e_error_message_show
1158                (_("Enlightenment crashed early on start and has<br>"
1159                   "been restarted. There was an error loading the<br>"
1160                   "module named: %s. This module has been disabled<br>"
1161                   "and will not be loaded."), crashmodule);
1162              e_util_dialog_show
1163                (_("Enlightenment crashed early on start and has been restarted"),
1164                _("Enlightenment crashed early on start and has been restarted.<br>"
1165                  "There was an error loading the module named: %s<br><br>"
1166                  "This module has been disabled and will not be loaded."), crashmodule);
1167              e_module_all_load();
1168           }
1169         else
1170           {
1171              e_error_message_show
1172                (_("Enlightenment crashed early on start and has<br>"
1173                   "been restarted. All modules have been disabled<br>"
1174                   "and will not be loaded to help remove any problem<br>"
1175                   "modules from your configuration. The module<br>"
1176                   "configuration dialog should let you select your<br>"
1177                   "modules again.\n"));
1178              e_util_dialog_show
1179                (_("Enlightenment crashed early on start and has been restarted"),
1180                _("Enlightenment crashed early on start and has been restarted.<br>"
1181                  "All modules have been disabled and will not be loaded to help<br>"
1182                  "remove any problem modules from your configuration.<br><br>"
1183                  "The module configuration dialog should let you select your<br>"
1184                  "modules again."));
1185           }
1186         mod_init_end = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_modules_load_after, NULL);
1187      }
1188 }
1189
1190 static Eina_Bool
1191 _e_main_cb_idle_before(void *data EINA_UNUSED)
1192 {
1193    e_client_idler_before();
1194    e_pointer_idler_before();
1195    edje_thaw();
1196    return ECORE_CALLBACK_RENEW;
1197 }
1198
1199 static Eina_Bool
1200 _e_main_cb_idle_after(void *data EINA_UNUSED)
1201 {
1202    static int first_idle = 1;
1203
1204    eet_clearcache();
1205    edje_freeze();
1206
1207 #ifdef E_RELEASE_BUILD
1208    if (first_idle)
1209      {
1210         TS("SLEEP");
1211         first_idle = 0;
1212         e_precache_end = EINA_TRUE;
1213      }
1214 #else
1215    if (first_idle++ < 60)
1216      {
1217         TS("SLEEP");
1218         if (!first_idle)
1219           e_precache_end = EINA_TRUE;
1220      }
1221 #endif
1222
1223    return ECORE_CALLBACK_RENEW;
1224 }
1225
1226 static void
1227 _e_main_create_wm_ready(void)
1228 {
1229    FILE *_wmready_checker = NULL;
1230
1231    _wmready_checker = fopen("/run/.wm_ready", "wb");
1232    if (_wmready_checker)
1233      {
1234         TS("[WM] WINDOW MANAGER is READY!!!");
1235         PRCTL("[Winsys] WINDOW MANAGER is READY!!!");
1236         fclose(_wmready_checker);
1237
1238         /*TODO: Next lines should be removed. */
1239         FILE *_tmp_wm_ready_checker;
1240         _tmp_wm_ready_checker = fopen("/tmp/.wm_ready", "wb");
1241
1242         if (_tmp_wm_ready_checker)
1243           {
1244              TS("[WM] temporary wm_ready path is created.");
1245              PRCTL("[Winsys] temporary wm_ready path is created.");
1246              fclose(_tmp_wm_ready_checker);
1247           }
1248         else
1249           {
1250              TS("[WM] temporary wm_ready path create failed.");
1251              PRCTL("[Winsys] temporary wm_ready path create failed.");
1252           }
1253      }
1254    else
1255      {
1256         TS("[WM] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1257         PRCTL("[Winsys] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1258      }
1259 }