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