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