e_main: remove build warning
[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    TSB("E_Pointer Init");
629    if (!e_pointer_init())
630      {
631         e_error_message_show(_("Enlightenment cannot set up its pointer system.\n"));
632         goto failed;
633      }
634    TSE("E_Pointer Init Done");
635    _e_main_shutdown_push(e_pointer_shutdown);
636
637    TRACE_DS_BEGIN(MAIN:SCREEN INIT);
638    TSB("Screens Init");
639    if (!_e_main_screens_init())
640      {
641         e_error_message_show(_("Enlightenment set up window management for all the screens on your system\n"
642                                "failed. Perhaps another window manager is running?\n"));
643         goto failed;
644      }
645    TSE("Screens Init Done");
646    _e_main_shutdown_push(_e_main_screens_shutdown);
647    TRACE_DS_END();
648
649    if (e_config->eom_enable)
650      {
651         TSB("Eom Init");
652         if (!e_eom_init())
653           {
654              e_error_message_show(_("Enlightenment cannot set up eom.\n"));
655              goto failed;
656           }
657         TSE("Eom Init Done");
658         _e_main_shutdown_push(e_eom_shutdown);
659      }
660
661    TSB("E_Screensaver Init");
662    if (!e_screensaver_init())
663      {
664         e_error_message_show(_("Enlightenment cannot configure the X screensaver.\n"));
665         goto failed;
666      }
667    TSE("E_Screensaver Init Done");
668    _e_main_shutdown_push(e_screensaver_shutdown);
669
670    TSB("E_Comp Freeze");
671    e_comp_all_freeze();
672    TSE("E_Comp Freeze Done");
673
674    TSB("E_Grabinput Init");
675    if (!e_grabinput_init())
676      {
677         e_error_message_show(_("Enlightenment cannot set up its grab input handling system.\n"));
678         goto failed;
679      }
680    TSE("E_Grabinput Init Done");
681    _e_main_shutdown_push(e_grabinput_shutdown);
682
683    TS("E_Gesture Init");
684    e_gesture_init();
685    _e_main_shutdown_push(e_gesture_shutdown);
686
687    ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_deferred_job_schedule, NULL);
688
689    TSB("E_Module Init");
690    if (!e_module_init())
691      {
692         e_error_message_show(_("Enlightenment cannot set up its module system.\n"));
693         goto failed;
694      }
695    TSE("E_Module Init Done");
696    _e_main_shutdown_push(e_module_shutdown);
697
698    TSB("E_Mouse Init");
699    if (!e_mouse_update())
700      {
701         e_error_message_show(_("Enlightenment cannot configure the mouse settings.\n"));
702         goto failed;
703      }
704    TSE("E_Mouse Init Done");
705
706    TSB("E_Icon Init");
707    if (!e_icon_init())
708      {
709         e_error_message_show(_("Enlightenment cannot initialize the Icon Cache system.\n"));
710         goto failed;
711      }
712    TSE("E_Icon Init Done");
713    _e_main_shutdown_push(e_icon_shutdown);
714
715    if (e_config->use_e_policy)
716      {
717         TSB("E_Policy Init");
718         if (!e_policy_init())
719           {
720              e_error_message_show(_("Enlightenment cannot setup policy system!\n"));
721              goto failed;
722           }
723         TSE("E_Policy Init Done");
724         _e_main_shutdown_push(e_policy_shutdown);
725      }
726
727    TSB("E_Process Init");
728    if (!e_process_init())
729      {
730         e_error_message_show(_("Enlightenment cannot setup process managing system!\n"));
731         goto failed;
732      }
733    TSE("E_Process Init Done");
734    _e_main_shutdown_push(e_process_shutdown);
735
736    TSB("E_Security Init");
737    if (!e_security_init())
738      {
739         e_error_message_show(_("Enlightenment cannot setup security system!\n"));
740         goto failed;
741      }
742    TSE("E_Security Init Done");
743    _e_main_shutdown_push(e_security_shutdown);
744
745    TSB("Load Modules");
746    _e_main_modules_load(safe_mode);
747    TSE("Load Modules Done");
748
749    TSB("E_Comp Thaw");
750    e_comp_all_thaw();
751    TSE("E_Comp Thaw Done");
752
753    _idle_after = ecore_idle_enterer_add(_e_main_cb_idle_after, NULL);
754
755    starting = EINA_FALSE;
756    inloop = EINA_TRUE;
757
758    e_util_env_set("E_RESTART", "1");
759
760    TSM("MAIN LOOP AT LAST");
761
762    if (e_config->create_wm_ready)
763      _e_main_create_wm_ready();
764
765    TRACE_DS_END();
766
767 #ifdef HAVE_SYSTEMD
768    TSM("[WM] Send start-up completion");
769    sd_notify(0, "READY=1");
770 #else
771    TSM("[WM] Skip sending start-up completion. (no systemd)");
772 #endif
773    ecore_main_loop_begin();
774
775    inloop = EINA_FALSE;
776
777    ELOGF("COMP", "STOPPING enlightenment...", NULL, NULL);
778    stopping = EINA_TRUE;
779
780    _e_main_desk_save();
781    e_comp_internal_save();
782
783    _e_main_shutdown(0);
784
785    if (restart)
786      {
787         e_util_env_set("E_RESTART_OK", "1");
788         if (getenv("E_START_MTRACK"))
789           e_util_env_set("MTRACK", "track");
790         ecore_app_restart();
791      }
792
793    e_prefix_shutdown();
794
795    return 0;
796
797 failed:
798    TSE("INIT FAILED");
799    TRACE_DS_END();
800    _e_main_shutdown(-1);
801 }
802
803 E_API double
804 e_main_ts(const char *str)
805 {
806    double ret;
807    t1 = ecore_time_unix_get();
808    printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, str);
809    ret = t1 - t2;
810    t2 = t1;
811    return ret;
812 }
813
814 E_API double
815 e_main_ts_begin(const char *str)
816 {
817    TRACE_DS_BEGIN(ESTART: %s, str);
818    return e_main_ts(str);
819 }
820
821 E_API double
822 e_main_ts_end(const char *str)
823 {
824    TRACE_DS_END();
825    return e_main_ts(str);
826 }
827
828 /* local functions */
829 static void
830 _e_main_shutdown(int errcode)
831 {
832    int i = 0;
833    char buf[PATH_MAX];
834    const char *dir;
835
836    printf("E: Begin Shutdown Procedure!\n");
837
838    E_FREE_LIST(hooks, e_main_hook_del);
839
840    if (_idle_before) ecore_idle_enterer_del(_idle_before);
841    _idle_before = NULL;
842    if (_idle_after) ecore_idle_enterer_del(_idle_after);
843    _idle_after = NULL;
844
845    dir = getenv("XDG_RUNTIME_DIR");
846    if (dir)
847      {
848         char buf_env[PATH_MAX];
849         snprintf(buf_env, sizeof(buf_env), "%s", dir);
850         snprintf(buf, sizeof(buf), "%s/.e-deleteme", buf_env);
851         if (ecore_file_exists(buf)) ecore_file_recursive_rm(buf_env);
852      }
853    for (i = (_e_main_lvl - 1); i >= 0; i--)
854      (*_e_main_shutdown_func[i])();
855 #ifdef OBJECT_HASH_CHECK
856    e_object_hash_shutdown();
857 #endif
858    if (errcode < 0) exit(errcode);
859 }
860
861 static void
862 _e_main_shutdown_push(int (*func)(void))
863 {
864    _e_main_lvl++;
865    if (_e_main_lvl > MAX_LEVEL)
866      {
867         _e_main_lvl--;
868         e_error_message_show("WARNING: too many init levels. MAX = %i\n",
869                              MAX_LEVEL);
870         return;
871      }
872    _e_main_shutdown_func[_e_main_lvl - 1] = func;
873 }
874
875 static void
876 _e_main_parse_arguments(int argc, char **argv)
877 {
878    int i = 0;
879
880    /* handle some command-line parameters */
881    for (i = 1; i < argc; i++)
882      {
883         if (!strcmp(argv[i], "-good"))
884           {
885              good = EINA_TRUE;
886              evil = EINA_FALSE;
887              printf("LA LA LA\n");
888           }
889         else if (!strcmp(argv[i], "-evil"))
890           {
891              good = EINA_FALSE;
892              evil = EINA_TRUE;
893              printf("MUHAHAHAHHAHAHAHAHA\n");
894           }
895         else if (!strcmp(argv[i], "-psychotic"))
896           {
897              good = EINA_TRUE;
898              evil = EINA_TRUE;
899              printf("MUHAHALALALALALALALA\n");
900           }
901         else if ((!strcmp(argv[i], "-profile")) && (i < (argc - 1)))
902           {
903              i++;
904              if (!getenv("E_CONF_PROFILE"))
905                e_util_env_set("E_CONF_PROFILE", argv[i]);
906           }
907         else if (!strcmp(argv[i], "-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it"))
908           really_know = EINA_TRUE;
909         else if (!strcmp(argv[i], "-nopause"))
910           e_nopause = EINA_TRUE;
911         else if ((!strcmp(argv[i], "-version")) ||
912                  (!strcmp(argv[i], "--version")))
913           {
914              printf(_("Version: %s\n"), PACKAGE_VERSION);
915              _e_main_shutdown(-1);
916           }
917         else if ((!strcmp(argv[i], "-h")) ||
918                  (!strcmp(argv[i], "-help")) ||
919                  (!strcmp(argv[i], "--help")))
920           {
921              printf
922                (_(
923                  "Options:\n"
924                  "\t-display DISPLAY\n"
925                  "\t\tConnect to display named DISPLAY.\n"
926                  "\t\tEG: -display :1.0\n"
927                  "\t-fake-xinerama-screen WxH+X+Y\n"
928                  "\t\tAdd a FAKE xinerama screen (instead of the real ones)\n"
929                  "\t\tgiven the geometry. Add as many as you like. They all\n"
930                  "\t\treplace the real xinerama screens, if any. This can\n"
931                  "\t\tbe used to simulate xinerama.\n"
932                  "\t\tEG: -fake-xinerama-screen 800x600+0+0 -fake-xinerama-screen 800x600+800+0\n"
933                  "\t-profile CONF_PROFILE\n"
934                  "\t\tUse the configuration profile CONF_PROFILE instead of the user selected default or just \"default\".\n"
935                  "\t-good\n"
936                  "\t\tBe good.\n"
937                  "\t-evil\n"
938                  "\t\tBe evil.\n"
939                  "\t-psychotic\n"
940                  "\t\tBe psychotic.\n"
941                  "\t-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it\n"
942                  "\t\tIf you need this help, you don't need this option.\n"
943                  "\t-version\n"
944                  )
945                );
946              _e_main_shutdown(-1);
947           }
948      }
949 }
950
951 static Eina_Bool
952 _e_main_cb_signal_exit(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
953 {
954    /* called on ctrl-c, kill (pid) (also SIGINT, SIGTERM and SIGQIT) */
955    ecore_main_loop_quit();
956    return ECORE_CALLBACK_RENEW;
957 }
958
959 static Eina_Bool
960 _e_main_cb_signal_hup(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
961 {
962    restart = 1;
963    ecore_main_loop_quit();
964    return ECORE_CALLBACK_RENEW;
965 }
966
967 static Eina_Bool
968 _e_main_cb_signal_user(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
969 {
970    Ecore_Event_Signal_User *e = ev;
971
972    if (e->number == 1)
973      {
974 //        E_Action *a = e_action_find("configuration");
975 //        if ((a) && (a->func.go)) a->func.go(NULL, NULL);
976      }
977    else if (e->number == 2)
978      {
979         // comp module has its own handler for this for enabling/disabling fps debug
980      }
981    return ECORE_CALLBACK_RENEW;
982
983 }
984
985 static int
986 _e_main_dirs_init(void)
987 {
988    if(getenv("E_CONF_RO"))
989      {
990         return 1;
991      }
992
993    const char *base;
994    const char *dirs[] =
995    {
996       "backgrounds",
997       "config",
998       "themes",
999       NULL
1000    };
1001
1002    base = e_user_dir_get();
1003    if (ecore_file_mksubdirs(base, dirs) != sizeof(dirs) / sizeof(dirs[0]) - 1)
1004      {
1005         e_error_message_show("Could not create one of the required "
1006                              "subdirectories of '%s'\n", base);
1007         return 0;
1008      }
1009
1010    return 1;
1011 }
1012
1013 static int
1014 _e_main_dirs_shutdown(void)
1015 {
1016    return 1;
1017 }
1018
1019 static int
1020 _e_main_path_init(void)
1021 {
1022    char buf[PATH_MAX];
1023
1024    /* setup data paths */
1025    path_data = e_path_new();
1026    if (!path_data)
1027      {
1028         e_error_message_show("Cannot allocate path for path_data\n");
1029         return 0;
1030      }
1031    e_prefix_data_concat_static(buf, "data");
1032    e_path_default_path_append(path_data, buf);
1033
1034    /* setup image paths */
1035    path_images = e_path_new();
1036    if (!path_images)
1037      {
1038         e_error_message_show("Cannot allocate path for path_images\n");
1039         return 0;
1040      }
1041    e_user_dir_concat_static(buf, "/images");
1042    e_path_default_path_append(path_images, buf);
1043    e_prefix_data_concat_static(buf, "data/images");
1044    e_path_default_path_append(path_images, buf);
1045
1046    /* setup font paths */
1047    path_fonts = e_path_new();
1048    if (!path_fonts)
1049      {
1050         e_error_message_show("Cannot allocate path for path_fonts\n");
1051         return 0;
1052      }
1053    e_user_dir_concat_static(buf, "/fonts");
1054    e_path_default_path_append(path_fonts, buf);
1055    e_prefix_data_concat_static(buf, "data/fonts");
1056    e_path_default_path_append(path_fonts, buf);
1057
1058    /* setup icon paths */
1059    path_icons = e_path_new();
1060    if (!path_icons)
1061      {
1062         e_error_message_show("Cannot allocate path for path_icons\n");
1063         return 0;
1064      }
1065    e_user_dir_concat_static(buf, "/icons");
1066    e_path_default_path_append(path_icons, buf);
1067    e_prefix_data_concat_static(buf, "data/icons");
1068    e_path_default_path_append(path_icons, buf);
1069
1070    /* setup module paths */
1071    path_modules = e_path_new();
1072    if (!path_modules)
1073      {
1074         e_error_message_show("Cannot allocate path for path_modules\n");
1075         return 0;
1076      }
1077    e_user_dir_concat_static(buf, "/modules");
1078    e_path_default_path_append(path_modules, buf);
1079    snprintf(buf, sizeof(buf), "%s/enlightenment/modules", e_prefix_lib_get());
1080    e_path_default_path_append(path_modules, buf);
1081    /* FIXME: eventually this has to go - moduels should have installers that
1082     * add appropriate install paths (if not installed to user homedir) to
1083     * e's module search dirs
1084     */
1085    snprintf(buf, sizeof(buf), "%s/enlightenment/modules_extra", e_prefix_lib_get());
1086    e_path_default_path_append(path_modules, buf);
1087
1088    /* setup background paths */
1089    path_backgrounds = e_path_new();
1090    if (!path_backgrounds)
1091      {
1092         e_error_message_show("Cannot allocate path for path_backgrounds\n");
1093         return 0;
1094      }
1095    e_user_dir_concat_static(buf, "/backgrounds");
1096    e_path_default_path_append(path_backgrounds, buf);
1097    e_prefix_data_concat_static(buf, "data/backgrounds");
1098    e_path_default_path_append(path_backgrounds, buf);
1099
1100    path_messages = e_path_new();
1101    if (!path_messages)
1102      {
1103         e_error_message_show("Cannot allocate path for path_messages\n");
1104         return 0;
1105      }
1106    e_user_dir_concat_static(buf, "/locale");
1107    e_path_default_path_append(path_messages, buf);
1108    e_path_default_path_append(path_messages, e_prefix_locale_get());
1109
1110    return 1;
1111 }
1112
1113 static int
1114 _e_main_path_shutdown(void)
1115 {
1116    if (path_data)
1117      {
1118         e_object_del(E_OBJECT(path_data));
1119         path_data = NULL;
1120      }
1121    if (path_images)
1122      {
1123         e_object_del(E_OBJECT(path_images));
1124         path_images = NULL;
1125      }
1126    if (path_fonts)
1127      {
1128         e_object_del(E_OBJECT(path_fonts));
1129         path_fonts = NULL;
1130      }
1131    if (path_icons)
1132      {
1133         e_object_del(E_OBJECT(path_icons));
1134         path_icons = NULL;
1135      }
1136    if (path_modules)
1137      {
1138         e_object_del(E_OBJECT(path_modules));
1139         path_modules = NULL;
1140      }
1141    if (path_backgrounds)
1142      {
1143         e_object_del(E_OBJECT(path_backgrounds));
1144         path_backgrounds = NULL;
1145      }
1146    if (path_messages)
1147      {
1148         e_object_del(E_OBJECT(path_messages));
1149         path_messages = NULL;
1150      }
1151    return 1;
1152 }
1153
1154 static int
1155 _e_main_screens_init(void)
1156 {
1157    TSB("\tscreens: client");
1158    if (!e_client_init()) return 0;
1159    TSE("\tscreens: client Done");
1160
1161    TSB("Compositor Init");
1162    PRCTL("[Winsys] start of compositor init");
1163    if (!e_comp_init())
1164      {
1165         e_error_message_show(_("Enlightenment cannot create a compositor.\n"));
1166         _e_main_shutdown(-1);
1167      }
1168    TSE("Compositor Init Done");
1169
1170    PRCTL("[Winsys] end of compositor init");
1171    _e_main_desk_restore();
1172
1173    return 1;
1174 }
1175
1176 static int
1177 _e_main_screens_shutdown(void)
1178 {
1179    e_win_shutdown();
1180    e_comp_shutdown();
1181    e_client_shutdown();
1182
1183    e_slot_shutdown();
1184    e_desk_shutdown();
1185    e_zone_shutdown();
1186    return 1;
1187 }
1188
1189 static void
1190 _e_main_desk_save(void)
1191 {
1192    const Eina_List *l;
1193    char env[1024], name[1024];
1194    E_Zone *zone;
1195
1196    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1197      {
1198         snprintf(name, sizeof(name), "DESK_%d_%d", 0, zone->num);
1199         snprintf(env, sizeof(env), "%d,%d", zone->desk_x_current, zone->desk_y_current);
1200         e_util_env_set(name, env);
1201      }
1202 }
1203
1204 static void
1205 _e_main_desk_restore(void)
1206 {
1207    E_Client *ec;
1208
1209    E_CLIENT_REVERSE_FOREACH(ec)
1210      if ((!e_client_util_ignored_get(ec)) && e_client_util_desk_visible(ec, e_desk_current_get(ec->zone)))
1211        {
1212           ec->want_focus = ec->take_focus = 1;
1213           break;
1214        }
1215 }
1216
1217 static Eina_Bool
1218 _e_main_modules_load_after(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
1219 {
1220    E_FREE_FUNC(mod_init_end, ecore_event_handler_del);
1221    return ECORE_CALLBACK_RENEW;
1222 }
1223
1224 static void
1225 _e_main_modules_load(Eina_Bool safe_mode)
1226 {
1227    if (!safe_mode)
1228      e_module_all_load();
1229    else
1230      {
1231         E_Module *m;
1232         char *crashmodule;
1233
1234         crashmodule = getenv("E_MODULE_LOAD");
1235         if (crashmodule) m = e_module_new(crashmodule);
1236
1237         if ((crashmodule) && (m))
1238           {
1239              e_module_disable(m);
1240              e_object_del(E_OBJECT(m));
1241
1242              e_error_message_show
1243                (_("Enlightenment crashed early on start and has<br>"
1244                   "been restarted. There was an error loading the<br>"
1245                   "module named: %s. This module has been disabled<br>"
1246                   "and will not be loaded."), crashmodule);
1247              e_util_dialog_show
1248                (_("Enlightenment crashed early on start and has been restarted"),
1249                _("Enlightenment crashed early on start and has been restarted.<br>"
1250                  "There was an error loading the module named: %s<br><br>"
1251                  "This module has been disabled and will not be loaded."), crashmodule);
1252              e_module_all_load();
1253           }
1254         else
1255           {
1256              e_error_message_show
1257                (_("Enlightenment crashed early on start and has<br>"
1258                   "been restarted. All modules have been disabled<br>"
1259                   "and will not be loaded to help remove any problem<br>"
1260                   "modules from your configuration. The module<br>"
1261                   "configuration dialog should let you select your<br>"
1262                   "modules again.\n"));
1263              e_util_dialog_show
1264                (_("Enlightenment crashed early on start and has been restarted"),
1265                _("Enlightenment crashed early on start and has been restarted.<br>"
1266                  "All modules have been disabled and will not be loaded to help<br>"
1267                  "remove any problem modules from your configuration.<br><br>"
1268                  "The module configuration dialog should let you select your<br>"
1269                  "modules again."));
1270           }
1271         mod_init_end = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_modules_load_after, NULL);
1272      }
1273 }
1274
1275 static Eina_Bool
1276 _e_main_cb_idle_before(void *data EINA_UNUSED)
1277 {
1278    e_client_idler_before();
1279    edje_thaw();
1280    return ECORE_CALLBACK_RENEW;
1281 }
1282
1283 static Eina_Bool
1284 _e_main_cb_idle_after(void *data EINA_UNUSED)
1285 {
1286    static int first_idle = 1;
1287
1288    eet_clearcache();
1289    edje_freeze();
1290
1291 #ifdef E_RELEASE_BUILD
1292    if (first_idle)
1293      {
1294         TSM("SLEEP");
1295         first_idle = 0;
1296         e_precache_end = EINA_TRUE;
1297      }
1298 #else
1299    if (first_idle++ < 60)
1300      {
1301         TSM("SLEEP");
1302         if (!first_idle)
1303           e_precache_end = EINA_TRUE;
1304      }
1305 #endif
1306
1307    return ECORE_CALLBACK_RENEW;
1308 }
1309
1310 static void
1311 _e_main_create_wm_ready(void)
1312 {
1313    FILE *_wmready_checker = NULL;
1314    const char *path_wm_ready = "/run/.wm_ready";
1315
1316    if (!e_util_file_realpath_check(path_wm_ready, EINA_TRUE))
1317      {
1318         WRN("%s is maybe link, so delete it\n", path_wm_ready);
1319      }
1320
1321    _wmready_checker = fopen(path_wm_ready, "wb");
1322    if (_wmready_checker)
1323      {
1324         TSM("[WM] WINDOW MANAGER is READY!!!");
1325         PRCTL("[Winsys] WINDOW MANAGER is READY!!!");
1326         fclose(_wmready_checker);
1327
1328         /*TODO: Next lines should be removed. */
1329         FILE *_tmp_wm_ready_checker;
1330
1331         _tmp_wm_ready_checker = fopen(path_wm_ready, "wb");
1332
1333         if (_tmp_wm_ready_checker)
1334           {
1335              TSM("[WM] temporary wm_ready path is created.");
1336              PRCTL("[Winsys] temporary wm_ready path is created.");
1337              fclose(_tmp_wm_ready_checker);
1338           }
1339         else
1340           {
1341              TSM("[WM] temporary wm_ready path create failed.");
1342              PRCTL("[Winsys] temporary wm_ready path create failed.");
1343           }
1344      }
1345    else
1346      {
1347         TSM("[WM] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1348         PRCTL("[Winsys] WINDOW MANAGER is READY. BUT, failed to create .wm_ready file.");
1349      }
1350 }
1351
1352 static void
1353 _e_main_hooks_clean(void)
1354 {
1355    Eina_Inlist *l;
1356    E_Main_Hook *mh;
1357    unsigned int x;
1358
1359    for (x = 0; x < E_MAIN_HOOK_LAST; x++)
1360      EINA_INLIST_FOREACH_SAFE(_e_main_hooks[x], l, mh)
1361        {
1362           if (!mh->delete_me) continue;
1363           _e_main_hooks[x] = eina_inlist_remove(_e_main_hooks[x],
1364                                                 EINA_INLIST_GET(mh));
1365           free(mh);
1366        }
1367 }
1368
1369 static void
1370 _e_main_hook_call(E_Main_Hook_Point hookpoint, void *data EINA_UNUSED)
1371 {
1372    E_Main_Hook *mh;
1373
1374    _e_main_hooks_walking++;
1375    EINA_INLIST_FOREACH(_e_main_hooks[hookpoint], mh)
1376      {
1377         if (mh->delete_me) continue;
1378         mh->func(mh->data);
1379      }
1380    _e_main_hooks_walking--;
1381    if ((_e_main_hooks_walking == 0) && (_e_main_hooks_delete > 0))
1382      _e_main_hooks_clean();
1383 }
1384
1385 E_API E_Main_Hook *
1386 e_main_hook_add(E_Main_Hook_Point hookpoint, E_Main_Hook_Cb func, const void *data)
1387 {
1388    E_Main_Hook *mh;
1389
1390    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_MAIN_HOOK_LAST, NULL);
1391    mh = E_NEW(E_Main_Hook, 1);
1392    EINA_SAFETY_ON_NULL_RETURN_VAL(mh, NULL);
1393    mh->hookpoint = hookpoint;
1394    mh->func = func;
1395    mh->data = (void*)data;
1396    _e_main_hooks[hookpoint] = eina_inlist_append(_e_main_hooks[hookpoint],
1397                                                  EINA_INLIST_GET(mh));
1398    return mh;
1399 }
1400
1401 E_API void
1402 e_main_hook_del(E_Main_Hook *mh)
1403 {
1404    mh->delete_me = 1;
1405    if (_e_main_hooks_walking == 0)
1406      {
1407         _e_main_hooks[mh->hookpoint] = eina_inlist_remove(_e_main_hooks[mh->hookpoint],
1408                                                           EINA_INLIST_GET(mh));
1409         free(mh);
1410      }
1411    else
1412      _e_main_hooks_delete++;
1413 }
1414
1415 E_API void
1416 e_main_hook_call(E_Main_Hook_Point hookpoint)
1417 {
1418    if ((hookpoint < 0) || (hookpoint >= E_MAIN_HOOK_LAST)) return;
1419
1420    _e_main_hook_call(hookpoint, NULL);
1421 }