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