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