e_main: removed e_first_frame feature.
[platform/upstream/enlightenment.git] / src / bin / e_main.c
1 #include "e.h"
2 #ifdef __linux__
3 # include <sys/prctl.h>
4 #endif
5 #ifdef HAVE_SYSTEMD
6 # include <systemd/sd-daemon.h>
7 #endif
8
9 #define MAX_LEVEL 80
10
11 #define TS_DO
12 #ifdef TS_DO
13 # define TS(x)                                                    \
14   {                                                               \
15      t1 = ecore_time_unix_get();                                  \
16      printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, x); \
17      t2 = t1;                                                     \
18   }
19
20 # define TSB(x)                                                  \
21   do {                                                           \
22      TRACE_DS_BEGIN(ESTART: %s, x);                              \
23      TS(x);                                                      \
24   } while (0)
25 # define TSE(x)                                                  \
26   do {                                                           \
27      TRACE_DS_END();                                             \
28      TS(x);                                                      \
29   } while (0)
30 # define TSM(x)                                                  \
31   do {                                                           \
32      TRACE_DS_MARK(ESTART: %s, x);                               \
33      TS(x);                                                      \
34   } while (0)
35 static double t0, t1, t2;
36 #else
37 # define TS(x)
38 # define TSB(x)
39 # define TSE(x)
40 # define TSM(x)
41 #endif
42 /*
43  * i need to make more use of these when i'm baffled as to when something is
44  * up. other hooks:
45  *
46  *      void *(*__malloc_hook)(size_t size, const void *caller);
47  *
48  *      void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
49  *
50  *      void *(*__memalign_hook)(size_t alignment, size_t size,
51  *                               const void *caller);
52  *
53  *      void (*__free_hook)(void *ptr, const void *caller);
54  *
55  *      void (*__malloc_initialize_hook)(void);
56  *
57  *      void (*__after_morecore_hook)(void);
58  *
59
60    static void my_init_hook(void);
61    static void my_free_hook(void *p, const void *caller);
62
63    static void (*old_free_hook)(void *ptr, const void *caller) = NULL;
64    void (*__free_hook)(void *ptr, const void *caller);
65
66    void (*__malloc_initialize_hook) (void) = my_init_hook;
67    static void
68    my_init_hook(void)
69    {
70    old_free_hook = __free_hook;
71    __free_hook = my_free_hook;
72    }
73
74    //void *magicfree = NULL;
75
76    static void
77    my_free_hook(void *p, const void *caller)
78    {
79    __free_hook = old_free_hook;
80    //   if ((p) && (p == magicfree))
81    //     {
82    //   printf("CAUGHT!!!!! %p ...\n", p);
83    //   abort();
84    //     }
85    free(p);
86    __free_hook = my_free_hook;
87    }
88  */
89
90 /* local function prototypes */
91 static void      _e_main_shutdown(int errcode);
92 static void      _e_main_shutdown_push(int (*func)(void));
93 static void      _e_main_parse_arguments(int argc, char **argv);
94 static Eina_Bool _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED);
95 static Eina_Bool _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED);
96 static Eina_Bool _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev);
97 static int       _e_main_dirs_init(void);
98 static int       _e_main_dirs_shutdown(void);
99 static int       _e_main_path_init(void);
100 static int       _e_main_path_shutdown(void);
101 static int       _e_main_screens_init(void);
102 static int       _e_main_screens_shutdown(void);
103 static void      _e_main_desk_save(void);
104 static void      _e_main_desk_restore(void);
105 static void      _e_main_modules_load(Eina_Bool safe_mode);
106 static Eina_Bool _e_main_cb_idle_before(void *data EINA_UNUSED);
107 static Eina_Bool _e_main_cb_idle_after(void *data EINA_UNUSED);
108 static void      _e_main_create_wm_ready(void);
109 static void      _e_main_hooks_clean(void);
110 static void      _e_main_hook_call(E_Main_Hook_Point hookpoint, void *data EINA_UNUSED);
111
112 /* local variables */
113 static Eina_Bool really_know = EINA_FALSE;
114 static Eina_Bool inloop = EINA_FALSE;
115
116 static int _e_main_lvl = 0;
117 static int(*_e_main_shutdown_func[MAX_LEVEL]) (void);
118
119 static Ecore_Idle_Enterer *_idle_before = NULL;
120 static Ecore_Idle_Enterer *_idle_after = NULL;
121
122 static Ecore_Event_Handler *mod_init_end = NULL;
123
124 static Eina_List *hooks = NULL;
125
126 static int _e_main_hooks_delete = 0;
127 static int _e_main_hooks_walking = 0;
128
129 static Eina_Inlist *_e_main_hooks[] =
130 {
131    [E_MAIN_HOOK_MODULE_LOAD_DONE] = NULL,
132    [E_MAIN_HOOK_E_INFO_READY] = NULL
133 };
134
135 /* external variables */
136 E_API Eina_Bool e_precache_end = EINA_FALSE;
137 E_API Eina_Bool good = EINA_FALSE;
138 E_API Eina_Bool evil = EINA_FALSE;
139 E_API Eina_Bool starting = EINA_TRUE;
140 E_API Eina_Bool stopping = EINA_FALSE;
141 E_API Eina_Bool restart = EINA_FALSE;
142 E_API Eina_Bool e_nopause = EINA_FALSE;
143
144 static Eina_Bool
145 _xdg_check_str(const char *env, const char *str)
146 {
147    const char *p;
148    size_t len;
149
150    len = strlen(str);
151    for (p = strstr(env, str); p; p++, p = strstr(p, str))
152      {
153         if ((!p[len]) || (p[len] == ':')) return EINA_TRUE;
154      }
155    return EINA_FALSE;
156 }
157
158 static void
159 _xdg_data_dirs_augment(void)
160 {
161    const char *s;
162    const char *p = e_prefix_get();
163    char newpath[4096], buf[4096];
164
165    if (!p) return;
166
167    s = getenv("XDG_DATA_DIRS");
168    if (s)
169      {
170         Eina_Bool pfxdata, pfx;
171
172         pfxdata = !_xdg_check_str(s, e_prefix_data_get());
173         snprintf(newpath, sizeof(newpath), "%s/share", p);
174         pfx = !_xdg_check_str(s, newpath);
175         if (pfxdata || pfx)
176           {
177              snprintf(buf, sizeof(buf), "%s%s%s%s%s",
178                pfxdata ? e_prefix_data_get() : "",
179                pfxdata ? ":" : "",
180                pfx ? newpath : "",
181                pfx ? ":" : "",
182                s);
183              e_util_env_set("XDG_DATA_DIRS", buf);
184           }
185      }
186    else
187      {
188         snprintf(buf, sizeof(buf), "%s:%s/share:/usr/local/share:/usr/share", e_prefix_data_get(), p);
189         e_util_env_set("XDG_DATA_DIRS", buf);
190      }
191
192    s = getenv("XDG_CONFIG_DIRS");
193    snprintf(newpath, sizeof(newpath), "%s/etc/xdg", p);
194    if (s)
195      {
196         if (!_xdg_check_str(s, newpath))
197           {
198              snprintf(buf, sizeof(buf), "%s:%s", newpath, s);
199              e_util_env_set("XDG_CONFIG_DIRS", buf);
200           }
201      }
202    else
203      {
204         snprintf(buf, sizeof(buf), "%s:/etc/xdg", newpath);
205         e_util_env_set("XDG_CONFIG_DIRS", buf);
206      }
207
208    if (!getenv("XDG_RUNTIME_DIR"))
209      {
210         const char *dir;
211
212         snprintf(buf, sizeof(buf), "/tmp/xdg-XXXXXX");
213         dir = mkdtemp(buf);
214         if (!dir) dir = "/tmp";
215         else
216           {
217              e_util_env_set("XDG_RUNTIME_DIR", dir);
218              snprintf(buf, sizeof(buf), "%s/.e-deleteme", dir);
219              ecore_file_mkdir(buf);
220           }
221      }
222
223    /* set menu prefix so we get our e menu */
224    if (!getenv("XDG_MENU_PREFIX"))
225      {
226         e_util_env_set("XDG_MENU_PREFIX", "e-");
227      }
228 }
229
230 static Eina_Bool
231 _e_main_subsystem_defer(void *data EINA_UNUSED)
232 {
233    int argc;
234    char **argv;
235
236    TRACE_DS_BEGIN(MAIN:SUBSYSTEMS DEFER);
237
238    ecore_app_args_get(&argc, &argv);
239
240    /* try to init delayed subsystems */
241
242    TRACE_DS_BEGIN(MAIN:DEFERRED INTERNAL SUBSYSTEMS INIT);
243
244    TSB("[DEFERRED] DPMS Init");
245    if (!e_dpms_init())
246      {
247         e_error_message_show(_("Enlightenment cannot set up dpms.\n"));
248         goto failed;
249      }
250    TSE("[DEFERRED] DPMS Init Done");
251    _e_main_shutdown_push(e_dpms_shutdown);
252
253    TSB("[DEFERRED] Screens Init: win");
254    if (!e_win_init())
255      {
256         e_error_message_show(_("Enlightenment cannot setup elementary trap!\n"));
257         goto failed;
258      }
259    TSE("[DEFERRED] Screens Init: win Done");
260
261    TSB("[DEFERRED] E_Dnd Init");
262    if (!e_dnd_init())
263      {
264         e_error_message_show(_("Enlightenment cannot set up its dnd system.\n"));
265         goto failed;
266      }
267    TSE("[DEFERRED] E_Dnd Init Done");
268    _e_main_shutdown_push(e_dnd_shutdown);
269
270    TSB("[DEFERRED] E_Scale Init");
271    if (!e_scale_init())
272      {
273         e_error_message_show(_("Enlightenment cannot set up its scale system.\n"));
274         goto failed;
275      }
276    TSE("[DEFERRED] E_Scale Init Done");
277    _e_main_shutdown_push(e_scale_shutdown);
278
279    TSB("[DEFERRED] E_Test_Helper Init");
280    e_test_helper_init();
281    _e_main_shutdown_push(e_test_helper_shutdown);
282    TSE("[DEFERRED] E_Test_Helper Done");
283
284    TSB("[DEFERRED] E_INFO_SERVER Init");
285    e_info_server_init();
286    _e_main_shutdown_push(e_info_server_shutdown);
287    TSE("[DEFERRED] E_INFO_SERVER Done");
288
289    TRACE_DS_END();
290    TRACE_DS_BEGIN(MAIN:DEFERRED COMP JOB);
291
292    /* try to do deferred job of any subsystems*/
293    TSB("[DEFERRED] Compositor's deferred job");
294    e_comp_deferred_job();
295    TSE("[DEFERRED] Compositor's deferred job Done");
296
297    if (e_config->use_e_policy)
298      {
299         TSB("[DEFERRED] E_Policy's deferred job");
300         e_policy_deferred_job();
301         TSE("[DEFERRED] E_Policy's deferred job Done");
302      }
303
304    TSB("[DEFERRED] E_Module's deferred job");
305    e_module_deferred_job();
306    TSE("[DEFERRED] E_Module's deferred job Done");
307
308    TRACE_DS_END();
309    TRACE_DS_END();
310    return ECORE_CALLBACK_DONE;
311
312 failed:
313    TSE("INIT FAILED");
314    TRACE_DS_END();
315    TRACE_DS_END();
316    _e_main_shutdown(-1);
317    return ECORE_CALLBACK_DONE;
318 }
319
320 static Eina_Bool
321 _e_main_deferred_job_schedule(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
322 {
323    PRCTL("[Winsys] all modules loaded");
324    ecore_idler_add(_e_main_subsystem_defer, NULL);
325    return ECORE_CALLBACK_DONE;
326 }
327
328 /* externally accessible functions */
329 int
330 main(int argc, char **argv)
331 {
332    Eina_Bool safe_mode = EINA_FALSE;
333    double t = 0.0, tstart = 0.0;
334    char *s = NULL, buff[32];
335    struct sigaction action;
336
337 #ifdef __linux__
338 # ifdef PR_SET_PTRACER
339 #  ifdef PR_SET_PTRACER_ANY
340    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
341 #  endif
342 # endif
343 #endif
344 #ifdef TS_DO
345    t0 = t1 = t2 = ecore_time_unix_get();
346    printf("ESTART(main) %1.5f\n", t0);
347 #endif
348    TRACE_DS_BEGIN(MAIN:BEGIN STARTUP);
349    TSB("Begin Startup");
350    PRCTL("[Winsys] start of main");
351
352    /* trap deadly bug signals and allow some form of sane recovery */
353    /* or ability to gdb attach and debug at this point - better than your */
354    /* wm/desktop vanishing and not knowing what happened */
355
356    /* don't install SIGBUS handler */
357    /* Wayland shm sets up a sigbus handler for catching invalid shm region */
358    /* access. If we setup our sigbus handler here, then the wl-shm sigbus */
359    /* handler will not function properly */
360    if (!getenv("NOTIFY_SOCKET"))
361      {
362         TSB("Signal Trap");
363         action.sa_sigaction = e_sigseg_act;
364         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
365         sigemptyset(&action.sa_mask);
366         sigaction(SIGSEGV, &action, NULL);
367
368         action.sa_sigaction = e_sigill_act;
369         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
370         sigemptyset(&action.sa_mask);
371         sigaction(SIGILL, &action, NULL);
372
373         action.sa_sigaction = e_sigfpe_act;
374         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
375         sigemptyset(&action.sa_mask);
376         sigaction(SIGFPE, &action, NULL);
377
378         action.sa_sigaction = e_sigabrt_act;
379         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
380         sigemptyset(&action.sa_mask);
381         sigaction(SIGABRT, &action, NULL);
382         TSE("Signal Trap Done");
383      }
384
385    t = ecore_time_unix_get();
386    s = getenv("E_START_TIME");
387    if ((s) && (!getenv("E_RESTART_OK")))
388      {
389         tstart = atof(s);
390         if ((t - tstart) < 5.0) safe_mode = EINA_TRUE;
391      }
392    tstart = t;
393    snprintf(buff, sizeof(buff), "%1.1f", tstart);
394    e_util_env_set("E_START_TIME", buff);
395
396    if (getenv("E_START_MTRACK"))
397      e_util_env_set("MTRACK", NULL);
398    TSB("Eina Init");
399    if (!eina_init())
400      {
401         e_error_message_show(_("Enlightenment cannot initialize Eina!\n"));
402         goto failed;
403      }
404    TSE("Eina Init Done");
405    _e_main_shutdown_push(eina_shutdown);
406
407 #ifdef OBJECT_HASH_CHECK
408    TSB("E_Object Hash Init");
409    e_object_hash_init();
410    TSE("E_Object Hash Init Done");
411 #endif
412
413    TSB("E_Log Init");
414    if (!e_log_init())
415      {
416         e_error_message_show(_("Enlightenment could not create a logging domain!\n"));
417         goto failed;
418      }
419    TSE("E_Log Init Done");
420    _e_main_shutdown_push(e_log_shutdown);
421
422    TSB("Determine Prefix");
423    if (!e_prefix_determine(argv[0]))
424      {
425         fprintf(stderr,
426                 "ERROR: Enlightenment cannot determine it's installed\n"
427                 "       prefix from the system or argv[0].\n"
428                 "       This is because it is not on Linux AND has been\n"
429                 "       executed strangely. This is unusual.\n");
430      }
431    TSE("Determine Prefix Done");
432
433    /* for debugging by redirecting stdout of e to a log file to tail */
434    setvbuf(stdout, NULL, _IONBF, 0);
435
436    TSB("Parse Arguments");
437    _e_main_parse_arguments(argc, argv);
438    TSE("Parse Arguments Done");
439
440    /*** Initialize Core EFL Libraries We Need ***/
441
442    TSB("Eet Init");
443    if (!eet_init())
444      {
445         e_error_message_show(_("Enlightenment cannot initialize Eet!\n"));
446         goto failed;
447      }
448    TSE("Eet Init Done");
449    _e_main_shutdown_push(eet_shutdown);
450
451    /* Allow ecore to not load system modules.
452     * Without it ecore_init will block until dbus authentication
453     * and registration are complete.
454     */
455    ecore_app_no_system_modules();
456
457    TSB("Ecore Init");
458    if (!ecore_init())
459      {
460         e_error_message_show(_("Enlightenment cannot initialize Ecore!\n"));
461         goto failed;
462      }
463    TSE("Ecore Init Done");
464    _e_main_shutdown_push(ecore_shutdown);
465
466    TSB("EIO Init");
467    if (!eio_init())
468      {
469         e_error_message_show(_("Enlightenment cannot initialize EIO!\n"));
470         goto failed;
471      }
472    TSE("EIO Init Done");
473    _e_main_shutdown_push(eio_shutdown);
474
475    ecore_app_args_set(argc, (const char **)argv);
476
477    TSB("Ecore Event Handlers");
478    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT,
479                                 _e_main_cb_signal_exit, NULL))
480      {
481         e_error_message_show(_("Enlightenment cannot set up an exit signal handler.\n"
482                                "Perhaps you are out of memory?"));
483         goto failed;
484      }
485    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_HUP,
486                                 _e_main_cb_signal_hup, NULL))
487      {
488         e_error_message_show(_("Enlightenment cannot set up a HUP signal handler.\n"
489                                "Perhaps you are out of memory?"));
490         goto failed;
491      }
492    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
493                                 _e_main_cb_signal_user, NULL))
494      {
495         e_error_message_show(_("Enlightenment cannot set up a USER signal handler.\n"
496                                "Perhaps you are out of memory?"));
497         goto failed;
498      }
499    TSE("Ecore Event Handlers Done");
500
501    TSB("Ecore_File Init");
502    if (!ecore_file_init())
503      {
504         e_error_message_show(_("Enlightenment cannot initialize Ecore_File!\n"));
505         goto failed;
506      }
507    TSE("Ecore_File Init Done");
508    _e_main_shutdown_push(ecore_file_shutdown);
509
510    _idle_before = ecore_idle_enterer_before_add(_e_main_cb_idle_before, NULL);
511
512    TSB("XDG_DATA_DIRS Init");
513    _xdg_data_dirs_augment();
514    TSE("XDG_DATA_DIRS Init Done");
515
516    TSB("Ecore_Evas Init");
517    if (!ecore_evas_init())
518      {
519         e_error_message_show(_("Enlightenment cannot initialize Ecore_Evas!\n"));
520         goto failed;
521      }
522    TSE("Ecore_Evas Init Done");
523
524    /* e doesn't sync to compositor - it should be one */
525    ecore_evas_app_comp_sync_set(0);
526
527    TSB("Edje Init");
528    if (!edje_init())
529      {
530         e_error_message_show(_("Enlightenment cannot initialize Edje!\n"));
531         goto failed;
532      }
533    TSE("Edje Init Done");
534    _e_main_shutdown_push(edje_shutdown);
535
536    /*** Initialize E Subsystems We Need ***/
537
538    TSB("E Directories Init");
539    /* setup directories we will be using for configurations storage etc. */
540    if (!_e_main_dirs_init())
541      {
542         e_error_message_show(_("Enlightenment cannot create directories in your home directory.\n"
543                                "Perhaps you have no home directory or the disk is full?"));
544         goto failed;
545      }
546    TSE("E Directories Init Done");
547    _e_main_shutdown_push(_e_main_dirs_shutdown);
548
549    TSB("E_Config Init");
550    if (!e_config_init())
551      {
552         e_error_message_show(_("Enlightenment cannot set up its config system.\n"));
553         goto failed;
554      }
555    TSE("E_Config Init Done");
556    _e_main_shutdown_push(e_config_shutdown);
557
558    TSB("E_Env Init");
559    if (!e_env_init())
560      {
561         e_error_message_show(_("Enlightenment cannot set up its environment.\n"));
562         goto failed;
563      }
564    TSE("E_Env Init Done");
565    _e_main_shutdown_push(e_env_shutdown);
566
567    ecore_exe_run_priority_set(e_config->priority);
568
569    TSB("E Paths Init");
570    if (!_e_main_path_init())
571      {
572         e_error_message_show(_("Enlightenment cannot set up paths for finding files.\n"
573                                "Perhaps you are out of memory?"));
574         goto failed;
575      }
576    TSE("E Paths Init Done");
577    _e_main_shutdown_push(_e_main_path_shutdown);
578
579    ecore_animator_frametime_set(1.0 / e_config->framerate);
580
581    TSB("E_Theme Init");
582    if (!e_theme_init())
583      {
584         e_error_message_show(_("Enlightenment cannot set up its theme system.\n"));
585         goto failed;
586      }
587    TSE("E_Theme Init Done");
588    _e_main_shutdown_push(e_theme_shutdown);
589
590    TSB("E_Actions Init");
591    if (!e_actions_init())
592      {
593         e_error_message_show(_("Enlightenment cannot set up its actions system.\n"));
594         goto failed;
595      }
596    TSE("E_Actions Init Done");
597    _e_main_shutdown_push(e_actions_shutdown);
598
599    /* these just add event handlers and can't fail
600     * timestamping them is dumb.
601     */
602    e_screensaver_preinit();
603    e_zone_init();
604    e_desk_init();
605    e_slot_init();
606
607    TRACE_DS_BEGIN(MAIN:WAIT /dev/dri/card0);
608    if (e_config->sleep_for_dri)
609      {
610         while(access("/dev/dri/card0", F_OK) != 0)
611           {
612              struct timespec req, rem;
613              req.tv_sec = 0;
614              req.tv_nsec = 50000000L;
615              nanosleep(&req, &rem);
616           }
617      }
618    TRACE_DS_END();
619
620    e_module_event_init();
621
622    TSB("E_Pointer Init");
623    if (!e_pointer_init())
624      {
625         e_error_message_show(_("Enlightenment cannot set up its pointer system.\n"));
626         goto failed;
627      }
628    TSE("E_Pointer Init Done");
629    _e_main_shutdown_push(e_pointer_shutdown);
630
631    TRACE_DS_BEGIN(MAIN:SCREEN INIT);
632    TSB("Screens Init");
633    if (!_e_main_screens_init())
634      {
635         e_error_message_show(_("Enlightenment set up window management for all the screens on your system\n"
636                                "failed. Perhaps another window manager is running?\n"));
637         goto failed;
638      }
639    TSE("Screens Init Done");
640    _e_main_shutdown_push(_e_main_screens_shutdown);
641    TRACE_DS_END();
642
643    if (e_config->eom_enable)
644      {
645         TSB("Eom Init");
646         if (!e_eom_init())
647           {
648              e_error_message_show(_("Enlightenment cannot set up eom.\n"));
649              goto failed;
650           }
651         TSE("Eom Init Done");
652         _e_main_shutdown_push(e_eom_shutdown);
653      }
654
655    TSB("E_Screensaver Init");
656    if (!e_screensaver_init())
657      {
658         e_error_message_show(_("Enlightenment cannot configure the X screensaver.\n"));
659         goto failed;
660      }
661    TSE("E_Screensaver Init Done");
662    _e_main_shutdown_push(e_screensaver_shutdown);
663
664    TSB("E_Comp Freeze");
665    e_comp_all_freeze();
666    TSE("E_Comp Freeze Done");
667
668    TSB("E_Grabinput Init");
669    if (!e_grabinput_init())
670      {
671         e_error_message_show(_("Enlightenment cannot set up its grab input handling system.\n"));
672         goto failed;
673      }
674    TSE("E_Grabinput Init Done");
675    _e_main_shutdown_push(e_grabinput_shutdown);
676
677    TS("E_Gesture Init");
678    e_gesture_init();
679    _e_main_shutdown_push(e_gesture_shutdown);
680
681    ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_deferred_job_schedule, NULL);
682
683    TSB("E_Module Init");
684    if (!e_module_init())
685      {
686         e_error_message_show(_("Enlightenment cannot set up its module system.\n"));
687         goto failed;
688      }
689    TSE("E_Module Init Done");
690    _e_main_shutdown_push(e_module_shutdown);
691
692    TSB("E_Mouse Init");
693    if (!e_mouse_update())
694      {
695         e_error_message_show(_("Enlightenment cannot configure the mouse settings.\n"));
696         goto failed;
697      }
698    TSE("E_Mouse Init Done");
699
700    TSB("E_Icon Init");
701    if (!e_icon_init())
702      {
703         e_error_message_show(_("Enlightenment cannot initialize the Icon Cache system.\n"));
704         goto failed;
705      }
706    TSE("E_Icon Init Done");
707    _e_main_shutdown_push(e_icon_shutdown);
708
709    if (e_config->use_e_policy)
710      {
711         TSB("E_Policy Init");
712         if (!e_policy_init())
713           {
714              e_error_message_show(_("Enlightenment cannot setup policy system!\n"));
715              goto failed;
716           }
717         TSE("E_Policy Init Done");
718         _e_main_shutdown_push(e_policy_shutdown);
719      }
720
721    TSB("E_Process Init");
722    if (!e_process_init())
723      {
724         e_error_message_show(_("Enlightenment cannot setup process managing system!\n"));
725         goto failed;
726      }
727    TSE("E_Process Init Done");
728    _e_main_shutdown_push(e_process_shutdown);
729
730    TSB("E_Security Init");
731    if (!e_security_init())
732      {
733         e_error_message_show(_("Enlightenment cannot setup security system!\n"));
734         goto failed;
735      }
736    TSE("E_Security Init Done");
737    _e_main_shutdown_push(e_security_shutdown);
738
739    TSB("Load Modules");
740    _e_main_modules_load(safe_mode);
741    TSE("Load Modules Done");
742
743    TSB("E_Comp Thaw");
744    e_comp_all_thaw();
745    TSE("E_Comp Thaw Done");
746
747    _idle_after = ecore_idle_enterer_add(_e_main_cb_idle_after, NULL);
748
749    starting = EINA_FALSE;
750    inloop = EINA_TRUE;
751
752    e_util_env_set("E_RESTART", "1");
753
754    TSM("MAIN LOOP AT LAST");
755
756    if (e_config->create_wm_ready)
757      _e_main_create_wm_ready();
758
759    TRACE_DS_END();
760
761 #ifdef HAVE_SYSTEMD
762    TSM("[WM] Send start-up completion");
763    sd_notify(0, "READY=1");
764 #else
765    TSM("[WM] Skip sending start-up completion. (no systemd)");
766 #endif
767    ecore_main_loop_begin();
768
769    inloop = EINA_FALSE;
770
771    ELOGF("COMP", "STOPPING enlightenment...", NULL, NULL);
772    stopping = EINA_TRUE;
773
774    _e_main_desk_save();
775    e_comp_internal_save();
776
777    _e_main_shutdown(0);
778
779    if (restart)
780      {
781         e_util_env_set("E_RESTART_OK", "1");
782         if (getenv("E_START_MTRACK"))
783           e_util_env_set("MTRACK", "track");
784         ecore_app_restart();
785      }
786
787    e_prefix_shutdown();
788
789    return 0;
790
791 failed:
792    TSE("INIT FAILED");
793    TRACE_DS_END();
794    _e_main_shutdown(-1);
795 }
796
797 E_API double
798 e_main_ts(const char *str)
799 {
800    double ret;
801    t1 = ecore_time_unix_get();
802    printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, str);
803    ret = t1 - t2;
804    t2 = t1;
805    return ret;
806 }
807
808 E_API double
809 e_main_ts_begin(const char *str)
810 {
811    TRACE_DS_BEGIN(ESTART: %s, str);
812    return e_main_ts(str);
813 }
814
815 E_API double
816 e_main_ts_end(const char *str)
817 {
818    TRACE_DS_END();
819    return e_main_ts(str);
820 }
821
822 /* local functions */
823 static void
824 _e_main_shutdown(int errcode)
825 {
826    int i = 0;
827    char buf[PATH_MAX];
828    const char *dir;
829
830    printf("E: Begin Shutdown Procedure!\n");
831
832    E_FREE_LIST(hooks, e_main_hook_del);
833
834    if (_idle_before) ecore_idle_enterer_del(_idle_before);
835    _idle_before = NULL;
836    if (_idle_after) ecore_idle_enterer_del(_idle_after);
837    _idle_after = NULL;
838
839    dir = getenv("XDG_RUNTIME_DIR");
840    if (dir)
841      {
842         char buf_env[PATH_MAX];
843         snprintf(buf_env, sizeof(buf_env), "%s", dir);
844         snprintf(buf, sizeof(buf), "%s/.e-deleteme", buf_env);
845         if (ecore_file_exists(buf)) ecore_file_recursive_rm(buf_env);
846      }
847    for (i = (_e_main_lvl - 1); i >= 0; i--)
848      (*_e_main_shutdown_func[i])();
849 #ifdef OBJECT_HASH_CHECK
850    e_object_hash_shutdown();
851 #endif
852    if (errcode < 0) exit(errcode);
853 }
854
855 static void
856 _e_main_shutdown_push(int (*func)(void))
857 {
858    _e_main_lvl++;
859    if (_e_main_lvl > MAX_LEVEL)
860      {
861         _e_main_lvl--;
862         e_error_message_show("WARNING: too many init levels. MAX = %i\n",
863                              MAX_LEVEL);
864         return;
865      }
866    _e_main_shutdown_func[_e_main_lvl - 1] = func;
867 }
868
869 static void
870 _e_main_parse_arguments(int argc, char **argv)
871 {
872    int i = 0;
873
874    /* handle some command-line parameters */
875    for (i = 1; i < argc; i++)
876      {
877         if (!strcmp(argv[i], "-good"))
878           {
879              good = EINA_TRUE;
880              evil = EINA_FALSE;
881              printf("LA LA LA\n");
882           }
883         else if (!strcmp(argv[i], "-evil"))
884           {
885              good = EINA_FALSE;
886              evil = EINA_TRUE;
887              printf("MUHAHAHAHHAHAHAHAHA\n");
888           }
889         else if (!strcmp(argv[i], "-psychotic"))
890           {
891              good = EINA_TRUE;
892              evil = EINA_TRUE;
893              printf("MUHAHALALALALALALALA\n");
894           }
895         else if ((!strcmp(argv[i], "-profile")) && (i < (argc - 1)))
896           {
897              i++;
898              if (!getenv("E_CONF_PROFILE"))
899                e_util_env_set("E_CONF_PROFILE", argv[i]);
900           }
901         else if (!strcmp(argv[i], "-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it"))
902           really_know = EINA_TRUE;
903         else if (!strcmp(argv[i], "-nopause"))
904           e_nopause = EINA_TRUE;
905         else if ((!strcmp(argv[i], "-version")) ||
906                  (!strcmp(argv[i], "--version")))
907           {
908              printf(_("Version: %s\n"), PACKAGE_VERSION);
909              _e_main_shutdown(-1);
910           }
911         else if ((!strcmp(argv[i], "-h")) ||
912                  (!strcmp(argv[i], "-help")) ||
913                  (!strcmp(argv[i], "--help")))
914           {
915              printf
916                (_(
917                  "Options:\n"
918                  "\t-display DISPLAY\n"
919                  "\t\tConnect to display named DISPLAY.\n"
920                  "\t\tEG: -display :1.0\n"
921                  "\t-fake-xinerama-screen WxH+X+Y\n"
922                  "\t\tAdd a FAKE xinerama screen (instead of the real ones)\n"
923                  "\t\tgiven the geometry. Add as many as you like. They all\n"
924                  "\t\treplace the real xinerama screens, if any. This can\n"
925                  "\t\tbe used to simulate xinerama.\n"
926                  "\t\tEG: -fake-xinerama-screen 800x600+0+0 -fake-xinerama-screen 800x600+800+0\n"
927                  "\t-profile CONF_PROFILE\n"
928                  "\t\tUse the configuration profile CONF_PROFILE instead of the user selected default or just \"default\".\n"
929                  "\t-good\n"
930                  "\t\tBe good.\n"
931                  "\t-evil\n"
932                  "\t\tBe evil.\n"
933                  "\t-psychotic\n"
934                  "\t\tBe psychotic.\n"
935                  "\t-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it\n"
936                  "\t\tIf you need this help, you don't need this option.\n"
937                  "\t-version\n"
938                  )
939                );
940              _e_main_shutdown(-1);
941           }
942      }
943 }
944
945 static Eina_Bool
946 _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
947 {
948    /* called on ctrl-c, kill (pid) (also SIGINT, SIGTERM and SIGQIT) */
949    ecore_main_loop_quit();
950    return ECORE_CALLBACK_RENEW;
951 }
952
953 static Eina_Bool
954 _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
955 {
956    restart = 1;
957    ecore_main_loop_quit();
958    return ECORE_CALLBACK_RENEW;
959 }
960
961 static Eina_Bool
962 _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
963 {
964    Ecore_Event_Signal_User *e = ev;
965
966    if (e->number == 1)
967      {
968 //        E_Action *a = e_action_find("configuration");
969 //        if ((a) && (a->func.go)) a->func.go(NULL, NULL);
970      }
971    else if (e->number == 2)
972      {
973         // comp module has its own handler for this for enabling/disabling fps debug
974      }
975    return ECORE_CALLBACK_RENEW;
976
977 }
978
979 static int
980 _e_main_dirs_init(void)
981 {
982    if(getenv("E_CONF_RO"))
983      {
984         return 1;
985      }
986
987    const char *base;
988    const char *dirs[] =
989    {
990       "backgrounds",
991       "config",
992       "themes",
993       NULL
994    };
995
996    base = e_user_dir_get();
997    if (ecore_file_mksubdirs(base, dirs) != sizeof(dirs) / sizeof(dirs[0]) - 1)
998      {
999         e_error_message_show("Could not create one of the required "
1000                              "subdirectories of '%s'\n", base);
1001         return 0;
1002      }
1003
1004    return 1;
1005 }
1006
1007 static int
1008 _e_main_dirs_shutdown(void)
1009 {
1010    return 1;
1011 }
1012
1013 static int
1014 _e_main_path_init(void)
1015 {
1016    char buf[PATH_MAX];
1017
1018    /* setup data paths */
1019    path_data = e_path_new();
1020    if (!path_data)
1021      {
1022         e_error_message_show("Cannot allocate path for path_data\n");
1023         return 0;
1024      }
1025    e_prefix_data_concat_static(buf, "data");
1026    e_path_default_path_append(path_data, buf);
1027
1028    /* setup image paths */
1029    path_images = e_path_new();
1030    if (!path_images)
1031      {
1032         e_error_message_show("Cannot allocate path for path_images\n");
1033         return 0;
1034      }
1035    e_user_dir_concat_static(buf, "/images");
1036    e_path_default_path_append(path_images, buf);
1037    e_prefix_data_concat_static(buf, "data/images");
1038    e_path_default_path_append(path_images, buf);
1039
1040    /* setup font paths */
1041    path_fonts = e_path_new();
1042    if (!path_fonts)
1043      {
1044         e_error_message_show("Cannot allocate path for path_fonts\n");
1045         return 0;
1046      }
1047    e_user_dir_concat_static(buf, "/fonts");
1048    e_path_default_path_append(path_fonts, buf);
1049    e_prefix_data_concat_static(buf, "data/fonts");
1050    e_path_default_path_append(path_fonts, buf);
1051
1052    /* setup icon paths */
1053    path_icons = e_path_new();
1054    if (!path_icons)
1055      {
1056         e_error_message_show("Cannot allocate path for path_icons\n");
1057         return 0;
1058      }
1059    e_user_dir_concat_static(buf, "/icons");
1060    e_path_default_path_append(path_icons, buf);
1061    e_prefix_data_concat_static(buf, "data/icons");
1062    e_path_default_path_append(path_icons, buf);
1063
1064    /* setup module paths */
1065    path_modules = e_path_new();
1066    if (!path_modules)
1067      {
1068         e_error_message_show("Cannot allocate path for path_modules\n");
1069         return 0;
1070      }
1071    e_user_dir_concat_static(buf, "/modules");
1072    e_path_default_path_append(path_modules, buf);
1073    snprintf(buf, sizeof(buf), "%s/enlightenment/modules", e_prefix_lib_get());
1074    e_path_default_path_append(path_modules, buf);
1075    /* FIXME: eventually this has to go - moduels should have installers that
1076     * add appropriate install paths (if not installed to user homedir) to
1077     * e's module search dirs
1078     */
1079    snprintf(buf, sizeof(buf), "%s/enlightenment/modules_extra", e_prefix_lib_get());
1080    e_path_default_path_append(path_modules, buf);
1081
1082    /* setup background paths */
1083    path_backgrounds = e_path_new();
1084    if (!path_backgrounds)
1085      {
1086         e_error_message_show("Cannot allocate path for path_backgrounds\n");
1087         return 0;
1088      }
1089    e_user_dir_concat_static(buf, "/backgrounds");
1090    e_path_default_path_append(path_backgrounds, buf);
1091    e_prefix_data_concat_static(buf, "data/backgrounds");
1092    e_path_default_path_append(path_backgrounds, buf);
1093
1094    path_messages = e_path_new();
1095    if (!path_messages)
1096      {
1097         e_error_message_show("Cannot allocate path for path_messages\n");
1098         return 0;
1099      }
1100    e_user_dir_concat_static(buf, "/locale");
1101    e_path_default_path_append(path_messages, buf);
1102    e_path_default_path_append(path_messages, e_prefix_locale_get());
1103
1104    return 1;
1105 }
1106
1107 static int
1108 _e_main_path_shutdown(void)
1109 {
1110    if (path_data)
1111      {
1112         e_object_del(E_OBJECT(path_data));
1113         path_data = NULL;
1114      }
1115    if (path_images)
1116      {
1117         e_object_del(E_OBJECT(path_images));
1118         path_images = NULL;
1119      }
1120    if (path_fonts)
1121      {
1122         e_object_del(E_OBJECT(path_fonts));
1123         path_fonts = NULL;
1124      }
1125    if (path_icons)
1126      {
1127         e_object_del(E_OBJECT(path_icons));
1128         path_icons = NULL;
1129      }
1130    if (path_modules)
1131      {
1132         e_object_del(E_OBJECT(path_modules));
1133         path_modules = NULL;
1134      }
1135    if (path_backgrounds)
1136      {
1137         e_object_del(E_OBJECT(path_backgrounds));
1138         path_backgrounds = NULL;
1139      }
1140    if (path_messages)
1141      {
1142         e_object_del(E_OBJECT(path_messages));
1143         path_messages = NULL;
1144      }
1145    return 1;
1146 }
1147
1148 static int
1149 _e_main_screens_init(void)
1150 {
1151    TSB("\tscreens: client");
1152    if (!e_client_init()) return 0;
1153    TSE("\tscreens: client Done");
1154
1155    TSB("Compositor Init");
1156    PRCTL("[Winsys] start of compositor init");
1157    if (!e_comp_init())
1158      {
1159         e_error_message_show(_("Enlightenment cannot create a compositor.\n"));
1160         _e_main_shutdown(-1);
1161      }
1162    TSE("Compositor Init Done");
1163
1164    PRCTL("[Winsys] end of compositor init");
1165    _e_main_desk_restore();
1166
1167    return 1;
1168 }
1169
1170 static int
1171 _e_main_screens_shutdown(void)
1172 {
1173    e_win_shutdown();
1174    e_comp_shutdown();
1175    e_client_shutdown();
1176
1177    e_slot_shutdown();
1178    e_desk_shutdown();
1179    e_zone_shutdown();
1180    return 1;
1181 }
1182
1183 static void
1184 _e_main_desk_save(void)
1185 {
1186    const Eina_List *l;
1187    char env[1024], name[1024];
1188    E_Zone *zone;
1189
1190    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1191      {
1192         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1193         snprintf(env, sizeof(env), "%d,%d", zone->desk_x_current, zone->desk_y_current);
1194         e_util_env_set(name, env);
1195      }
1196 }
1197
1198 static void
1199 _e_main_desk_restore(void)
1200 {
1201    E_Client *ec;
1202
1203    E_CLIENT_REVERSE_FOREACH(ec)
1204      if ((!e_client_util_ignored_get(ec)) && e_client_util_desk_visible(ec, e_desk_current_get(ec->zone)))
1205        {
1206           ec->want_focus = ec->take_focus = 1;
1207           break;
1208        }
1209 }
1210
1211 static Eina_Bool
1212 _e_main_modules_load_after(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
1213 {
1214    E_FREE_FUNC(mod_init_end, ecore_event_handler_del);
1215    return ECORE_CALLBACK_RENEW;
1216 }
1217
1218 static void
1219 _e_main_modules_load(Eina_Bool safe_mode)
1220 {
1221    if (!safe_mode)
1222      e_module_all_load();
1223    else
1224      {
1225         E_Module *m;
1226         char *crashmodule;
1227
1228         crashmodule = getenv("E_MODULE_LOAD");
1229         if (crashmodule) m = e_module_new(crashmodule);
1230
1231         if ((crashmodule) && (m))
1232           {
1233              e_module_disable(m);
1234              e_object_del(E_OBJECT(m));
1235
1236              e_error_message_show
1237                (_("Enlightenment crashed early on start and has<br>"
1238                   "been restarted. There was an error loading the<br>"
1239                   "module named: %s. This module has been disabled<br>"
1240                   "and will not be loaded."), crashmodule);
1241              e_util_dialog_show
1242                (_("Enlightenment crashed early on start and has been restarted"),
1243                _("Enlightenment crashed early on start and has been restarted.<br>"
1244                  "There was an error loading the module named: %s<br><br>"
1245                  "This module has been disabled and will not be loaded."), crashmodule);
1246              e_module_all_load();
1247           }
1248         else
1249           {
1250              e_error_message_show
1251                (_("Enlightenment crashed early on start and has<br>"
1252                   "been restarted. All modules have been disabled<br>"
1253                   "and will not be loaded to help remove any problem<br>"
1254                   "modules from your configuration. The module<br>"
1255                   "configuration dialog should let you select your<br>"
1256                   "modules again.\n"));
1257              e_util_dialog_show
1258                (_("Enlightenment crashed early on start and has been restarted"),
1259                _("Enlightenment crashed early on start and has been restarted.<br>"
1260                  "All modules have been disabled and will not be loaded to help<br>"
1261                  "remove any problem modules from your configuration.<br><br>"
1262                  "The module configuration dialog should let you select your<br>"
1263                  "modules again."));
1264           }
1265         mod_init_end = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_modules_load_after, NULL);
1266      }
1267 }
1268
1269 static Eina_Bool
1270 _e_main_cb_idle_before(void *data EINA_UNUSED)
1271 {
1272    e_client_idler_before();
1273    edje_thaw();
1274    return ECORE_CALLBACK_RENEW;
1275 }
1276
1277 static Eina_Bool
1278 _e_main_cb_idle_after(void *data EINA_UNUSED)
1279 {
1280    static int first_idle = 1;
1281
1282    eet_clearcache();
1283    edje_freeze();
1284
1285 #ifdef E_RELEASE_BUILD
1286    if (first_idle)
1287      {
1288         TSM("SLEEP");
1289         first_idle = 0;
1290         e_precache_end = EINA_TRUE;
1291      }
1292 #else
1293    if (first_idle++ < 60)
1294      {
1295         TSM("SLEEP");
1296         if (!first_idle)
1297           e_precache_end = EINA_TRUE;
1298      }
1299 #endif
1300
1301    return ECORE_CALLBACK_RENEW;
1302 }
1303
1304 static void
1305 _e_main_create_wm_ready(void)
1306 {
1307    FILE *_wmready_checker = NULL;
1308    const char *path_wm_ready = "/run/.wm_ready";
1309
1310    if (!e_util_file_realpath_check(path_wm_ready, EINA_TRUE))
1311      {
1312         WRN("%s is maybe link, so delete it\n", path_wm_ready);
1313      }
1314
1315    _wmready_checker = fopen(path_wm_ready, "wb");
1316    if (_wmready_checker)
1317      {
1318         TSM("[WM] WINDOW MANAGER is READY!!!");
1319         PRCTL("[Winsys] WINDOW MANAGER is READY!!!");
1320         fclose(_wmready_checker);
1321
1322         /*TODO: Next lines should be removed. */
1323         FILE *_tmp_wm_ready_checker;
1324
1325         _tmp_wm_ready_checker = fopen(path_wm_ready, "wb");
1326
1327         if (_tmp_wm_ready_checker)
1328           {
1329              TSM("[WM] temporary wm_ready path is created.");
1330              PRCTL("[Winsys] temporary wm_ready path is created.");
1331              fclose(_tmp_wm_ready_checker);
1332           }
1333         else
1334           {
1335              TSM("[WM] temporary wm_ready path create failed.");
1336              PRCTL("[Winsys] temporary wm_ready path create failed.");
1337           }
1338      }
1339    else
1340      {
1341         TSM("[WM] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1342         PRCTL("[Winsys] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1343      }
1344 }
1345
1346 static void
1347 _e_main_hooks_clean(void)
1348 {
1349    Eina_Inlist *l;
1350    E_Main_Hook *mh;
1351    unsigned int x;
1352
1353    for (x = 0; x < E_MAIN_HOOK_LAST; x++)
1354      EINA_INLIST_FOREACH_SAFE(_e_main_hooks[x], l, mh)
1355        {
1356           if (!mh->delete_me) continue;
1357           _e_main_hooks[x] = eina_inlist_remove(_e_main_hooks[x],
1358                                                 EINA_INLIST_GET(mh));
1359           free(mh);
1360        }
1361 }
1362
1363 static void
1364 _e_main_hook_call(E_Main_Hook_Point hookpoint, void *data EINA_UNUSED)
1365 {
1366    E_Main_Hook *mh;
1367
1368    _e_main_hooks_walking++;
1369    EINA_INLIST_FOREACH(_e_main_hooks[hookpoint], mh)
1370      {
1371         if (mh->delete_me) continue;
1372         mh->func(mh->data);
1373      }
1374    _e_main_hooks_walking--;
1375    if ((_e_main_hooks_walking == 0) && (_e_main_hooks_delete > 0))
1376      _e_main_hooks_clean();
1377 }
1378
1379 E_API E_Main_Hook *
1380 e_main_hook_add(E_Main_Hook_Point hookpoint, E_Main_Hook_Cb func, const void *data)
1381 {
1382    E_Main_Hook *mh;
1383
1384    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_MAIN_HOOK_LAST, NULL);
1385    mh = E_NEW(E_Main_Hook, 1);
1386    EINA_SAFETY_ON_NULL_RETURN_VAL(mh, NULL);
1387    mh->hookpoint = hookpoint;
1388    mh->func = func;
1389    mh->data = (void*)data;
1390    _e_main_hooks[hookpoint] = eina_inlist_append(_e_main_hooks[hookpoint],
1391                                                  EINA_INLIST_GET(mh));
1392    return mh;
1393 }
1394
1395 E_API void
1396 e_main_hook_del(E_Main_Hook *mh)
1397 {
1398    mh->delete_me = 1;
1399    if (_e_main_hooks_walking == 0)
1400      {
1401         _e_main_hooks[mh->hookpoint] = eina_inlist_remove(_e_main_hooks[mh->hookpoint],
1402                                                           EINA_INLIST_GET(mh));
1403         free(mh);
1404      }
1405    else
1406      _e_main_hooks_delete++;
1407 }
1408
1409 E_API void
1410 e_main_hook_call(E_Main_Hook_Point hookpoint)
1411 {
1412    if ((hookpoint < 0) || (hookpoint >= E_MAIN_HOOK_LAST)) return;
1413
1414    _e_main_hook_call(hookpoint, NULL);
1415 }