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