[src/lib/elm_main.c] Added comments to temporary codes.
[framework/uifw/elementary.git] / src / lib / elm_main.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #ifndef _GNU_SOURCE
6 # define _GNU_SOURCE
7 #endif
8
9 #include <dlfcn.h>      /* dlopen,dlclose,etc */
10
11 #ifdef HAVE_CRT_EXTERNS_H
12 # include <crt_externs.h>
13 #endif
14
15 #ifdef HAVE_EVIL
16 # include <Evil.h>
17 #endif
18
19 #include <Elementary.h>
20 #include "elm_priv.h"
21
22 static Elm_Version _version = { VMAJ, VMIN, VMIC, VREV };
23 EAPI Elm_Version *elm_version = &_version;
24 /**
25  * @defgroup Main Main
26  * @ingroup Elementary
27  *
28  * This group includes functions of elm_main.c
29  */
30
31
32 /**
33  * @defgroup Start Getting Started
34  * @ingroup Main
35  *
36  * To write an Elementary app, you can get started with the following:
37  *
38  * @code
39  * #include <Elementary.h>
40  * #ifndef ELM_LIB_QUICKLAUNCH
41  * EAPI int
42  * elm_main(int argc, char **argv)
43  * {
44  *    // create window(s) here and do any application init
45  *    elm_run(); // run main loop
46  *    elm_shutdown(); // after mainloop finishes running, shutdown
47  *    return 0; // exit 0 for exit code
48  * }
49  * #endif
50  * ELM_MAIN()
51  * @endcode
52  *
53  * To take full advantage of the quicklaunch architecture for launching
54  * processes as quickly as possible (saving time at startup time like
55  * connecting to X11, loading and linking shared libraries) you may want to
56  * use the following configure.in/configure.ac and Makefile.am and autogen.sh
57  * script to generate your files. It is assumed your application uses the
58  * main.c file for its code.
59  *
60  * configure.in/configure.ac:
61  *
62 @verbatim
63 AC_INIT(myapp, 0.0.0, myname@mydomain.com)
64 AC_PREREQ(2.52)
65 AC_CONFIG_SRCDIR(configure.in)
66
67 AM_INIT_AUTOMAKE(1.6 dist-bzip2)
68 AM_CONFIG_HEADER(config.h)
69
70 AC_C_BIGENDIAN
71 AC_ISC_POSIX
72 AC_PROG_CC
73 AM_PROG_CC_STDC
74 AC_HEADER_STDC
75 AC_C_CONST
76
77 AC_LIBTOOL_WIN32_DLL
78 define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
79 define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
80 AC_PROG_LIBTOOL
81
82 PKG_CHECK_MODULES([ELEMENTARY], elementary)
83
84 AC_OUTPUT(Makefile)
85 @endverbatim
86  *
87  * Makefile.am:
88  *
89 @verbatim
90 AUTOMAKE_OPTIONS     = 1.4 foreign
91 MAINTAINERCLEANFILES = Makefile.in
92
93 INCLUDES = -I$(top_srcdir) @ELEMENTARY_CFLAGS@
94
95 bin_PROGRAMS      = myapp
96 myapp_LTLIBRARIES = myapp.la
97
98 myappdir = $(libdir)
99
100 myapp_la_SOURCES = main.c
101 myapp_la_LIBADD = @ELEMENTARY_LIBS@
102 myapp_la_CFLAGS =
103 myapp_la_LDFLAGS = -module -avoid-version -no-undefined
104
105 myapp_SOURCES = main.c
106 myapp_LDADD = @ELEMENTARY_LIBS@
107 myapp_CFLAGS = -DELM_LIB_QUICKLAUNCH=1
108 @endverbatim
109  *
110  * autogen.sh:
111  *
112 @verbatim
113 #!/bin/sh
114 rm -rf autom4te.cache
115 rm -f aclocal.m4 ltmain.sh
116 rm -rf m4
117 mkdir m4
118
119 touch README
120 echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1
121 echo "Running autoheader..." ; autoheader || exit 1
122 echo "Running autoconf..." ; autoconf || exit 1
123 echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
124 echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
125
126 if [ -z "$NOCONFIGURE" ]; then
127   ./configure "$@"
128 fi
129 @endverbatim
130  *
131  * To gnerate all the things needed to bootstrap just run:
132  *
133 @verbatim
134 ./autogen.sh
135 @endverbatim
136  *
137  * This will generate Makefile.in's, the confgure script and everything else.
138  * After this it works like all normal autotools projects:
139 @verbatim
140 ./configure
141 make
142 sudo make install
143 @endverbatim
144  *
145  * Note sudo was assumed to get root permissions, as this would install in
146  * /usr/local which is system-owned. Ue any way you like to gain root, or
147  * specify a different prefix with configure:
148  *
149 @verbatim
150 ./confiugre --prefix=$HOME/mysoftware
151 @endverbatim
152  *
153  * Also remember that autotools buys you some useful commands like:
154 @verbatim
155 make uninstall
156 @endverbatim
157  *
158  * This uninstalls the software after it was installed with "make install".
159  * It is very useful to clear up what you built if you wish to clean the
160  * system.
161  *
162 @verbatim
163 make distcheck
164 @endverbatim
165  *
166  * This firstly checks if your build tree is "clean" and ready for
167  * distribution. It also builds a tarball (myapp-0.0.0.tar.gz) that is
168  * ready to upload and distribute to the world, that contains the generated
169  * Makefile.in's and configure script. The users do not need to run
170  * autogen.sh - just configure and on. They don't need autotools installed.
171  * This tarball also builds cleanly, has all the sources it needs to build
172  * included (that is sources for your application, not libraries it depends
173  * on like Elementary). It builds cleanly in a buildroot and does not
174  * contain any files that are temporarily generated like binaries and other
175  * build-gnerated files, so the tarball is clean, and no need to worry
176  * about cleaning up your tree before packaging.
177  *
178 @verbatim
179 make clean
180 @endverbatim
181  *
182  * This cleans up all build files (binaries, objects etc.) from the tree.
183  *
184 @verbatim
185 make distclean
186 @endverbatim
187  *
188  * This cleans out all files from the build and from configure's output too.
189  *
190 @verbatim
191 make maintainer-clean
192 @endverbatim
193  *
194  * This deletes all the files autogen.sh will produce so the tree is clean
195  * to be put into a revision-control system (like CVS, SVN or GIT for example).
196  *
197  * The above will build a library - libmyapp.so and install in the target
198  * library directory (default is /usr/local/lib). You will also get a
199  * myapp.a and myapp.la - these are useless and can be deleted. Libtool likes
200  * to generate these all the time. You will also get a binary in the target
201  * binary directory (default is /usr/local/bin). This is a "debug binary".
202  * This will run and dlopen() the myapp.so and then jump to it's elm_main
203  * function. This allows for easy debugging with GDB and Valgrind. When you
204  * are ready to go to production do the following:
205  *
206  * 1. delete the myapp binary. i.e. rm /usr/local/bin/myapp
207  *
208  * 2. symlink the myapp binary to elementary_run (supplied by elementary).
209  * i.e. ln -s elmentary_run /usr/local/bin/myapp
210  *
211  * 3. run elementary_quicklaunch as part of your graphical login session and
212  * keep it running.
213  *
214  * This will man elementary_quicklaunch does pre-initialization before the
215  * application needs to be run, saving the effort at the time the application
216  * is needed, thus speeding up the time it takes to appear.
217  *
218  * If you don't want to use the quicklaunch infrastructure (which is
219  * optional), you can execute the old fashioned way by just running the
220  * myapp binary loader than will load the myapp.so for you, or you can
221  * remove the split-file binary and put it into one binary as things always
222  * have been with the following configure.in/configure.ac and Makfile.am
223  * files:
224  *
225  * configure.in/configure.ac:
226  *
227 @verbatim
228 AC_INIT(myapp, 0.0.0, myname@mydomain.com)
229 AC_PREREQ(2.52)
230 AC_CONFIG_SRCDIR(configure.in)
231
232 AM_INIT_AUTOMAKE(1.6 dist-bzip2)
233 AM_CONFIG_HEADER(config.h)
234
235 AC_C_BIGENDIAN
236 AC_ISC_POSIX
237 AC_PROG_CC
238 AM_PROG_CC_STDC
239 AC_HEADER_STDC
240 AC_C_CONST
241
242 PKG_CHECK_MODULES([ELEMENTARY], elementary)
243
244 AC_OUTPUT(Makefile)
245 @endverbatim
246  *
247  * Makefile.am:
248  *
249 @verbatim
250 AUTOMAKE_OPTIONS     = 1.4 foreign
251 MAINTAINERCLEANFILES = Makefile.in
252
253 INCLUDES = -I$(top_srcdir) @ELEMENTARY_CFLAGS@
254
255 bin_PROGRAMS      = myapp
256
257 myapp_SOURCES = main.c
258 myapp_LDADD = @ELEMENTARY_LIBS@
259 myapp_CFLAGS =
260 @endverbatim
261  *
262  * Notice that they are the same as before, just with libtool and library
263  * building sections removed. Both ways work for building elementary
264  * applications. It is up to you to decide what is best for you. If you just
265  * follow the template above, you can do it both ways and can decide at build
266  * time. The more advanced of you may suggest making it a configure option.
267  * That is perfectly valid, bu has been left out here for simplicity, as our
268  * aim to have an Elementary (and EFL) tutorial, not an autoconf & automake
269  * document.
270  *
271  */
272
273 static int _elm_signal_exit(void *data, int ev_type, void *ev);
274
275 char *_elm_appname = NULL;
276 const char *_elm_data_dir = NULL;
277 const char *_elm_lib_dir = NULL;
278 int _elm_log_dom = -1;
279
280 EAPI int ELM_EVENT_POLICY_CHANGED = 0;
281
282 static int _elm_init_count = 0;
283 static int _elm_policies[ELM_POLICY_LAST];
284 static Ecore_Event_Handler *_elm_exit_handler = NULL;
285
286 static int
287 _elm_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__)
288 {
289    elm_exit();
290    return 1;
291 }
292
293 void
294 _elm_rescale(void)
295 {
296    edje_scale_set(_elm_config->scale);
297    _elm_win_rescale();
298 }
299
300 static Eina_List *widtypes = NULL;
301
302 void
303 _elm_widtype_register(const char **ptr)
304 {
305    widtypes = eina_list_append(widtypes, (void *)ptr);
306 }
307
308 static void
309 _elm_widtype_clear(void)
310 {
311    const char **ptr;
312    
313    EINA_LIST_FREE(widtypes, ptr)
314      {
315         eina_stringshare_del(*ptr);
316         *ptr = NULL;
317      }
318 }
319
320 // This code is just for temporary usage.
321 // This needs to be included into AUL avatar.
322 static void                                                                             
323 _set_elm_module()                                                                
324 {                                                                                
325    char *buf = NULL;
326
327    buf = getenv("ELM_THEME");
328    if (buf != NULL && ((!strcmp(buf, "beat") || !strcmp(buf, "kessler"))))
329       setenv("ELM_MODULES","ctxpopup_copypasteUI>entry/api",1);
330 }
331
332 /**
333  * @defgroup General General
334  * @ingroup Main
335  */
336
337 /**
338  * Inititalise Elementary
339  *
340  * This call is exported only for use by the ELM_MAIN() macro. There is no
341  * need to use this if you use this macro (which is highly advisable).
342  * @ingroup General
343  */
344 EAPI void
345 elm_init(int argc, char **argv)
346 {
347    _elm_init_count++;
348    if (_elm_init_count != 1) return;
349    _set_elm_module();
350    elm_quicklaunch_init(argc, argv);
351    elm_quicklaunch_sub_init(argc, argv);
352 }
353
354 /**
355  * Shut down Elementary
356  *
357  * This should be called at the end of your application just before it ceases
358  * to do any more processing. This will clean up any permanent resources your
359  * application may have allocated via Elementary that would otherwise persist
360  * on an exit without this call.
361  * @ingroup General
362  */
363 EAPI void
364 elm_shutdown(void)
365 {
366    _elm_init_count--;
367    if (_elm_init_count != 0) return;
368    elm_quicklaunch_sub_shutdown();
369    elm_quicklaunch_shutdown();
370 }
371
372 #ifdef ELM_EDBUS
373 static Eina_Bool _elm_need_e_dbus = EINA_FALSE;
374 #endif
375 EAPI void
376 elm_need_e_dbus(void)
377 {
378 #ifdef ELM_EDBUS
379    if (_elm_need_e_dbus) return;
380    _elm_need_e_dbus = 1;
381    e_dbus_init();
382    e_hal_init();
383 #endif   
384 }
385
386 static void
387 _elm_unneed_e_dbus(void)
388 {
389 #ifdef ELM_EDBUS
390    if (_elm_need_e_dbus)
391      {
392         _elm_need_e_dbus = 0;
393    e_hal_shutdown();
394         e_dbus_shutdown();
395      }
396 #endif   
397 }
398
399 #ifdef ELM_EFREET
400 static Eina_Bool _elm_need_efreet = EINA_FALSE;
401 #endif
402 EAPI void
403 elm_need_efreet(void)
404 {
405 #ifdef ELM_EFREET
406    if (_elm_need_efreet) return;
407    _elm_need_efreet = 1;
408    efreet_init();
409    efreet_mime_init();
410    efreet_trash_init();
411    /*
412      {
413         Eina_List **list;
414         
415         list = efreet_icon_extra_list_get();
416         if (list)
417           {
418              e_user_dir_concat_static(buf, "icons");
419              *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
420              e_prefix_data_concat_static(buf, "data/icons");
421              *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
422           }
423      }
424    */
425 #endif
426 }
427
428 static void
429 _elm_unneed_efreet(void)
430 {
431 #ifdef ELM_EFREET
432    if (_elm_need_efreet)
433      {
434         _elm_need_efreet = 0;
435         efreet_trash_shutdown();
436         efreet_mime_shutdown();
437         efreet_shutdown();
438      }
439 #endif   
440 }
441
442 EAPI void
443 elm_quicklaunch_init(int argc, char **argv)
444 {
445    char buf[PATH_MAX], *s;
446    
447    eina_init();
448    _elm_log_dom = eina_log_domain_register("elementary", EINA_COLOR_LIGHTBLUE);
449    if (!_elm_log_dom)
450      {
451    EINA_LOG_ERR("could not register elementary log domain.");
452    _elm_log_dom = EINA_LOG_DOMAIN_GLOBAL;
453      }
454
455    eet_init();
456    ecore_init();
457    ecore_app_args_set(argc, (const char **)argv);
458
459    memset(_elm_policies, 0, sizeof(_elm_policies));
460    if (ELM_EVENT_POLICY_CHANGED == 0)
461      ELM_EVENT_POLICY_CHANGED = ecore_event_type_new();
462
463    ecore_file_init();
464    evas_init();
465    edje_init();
466    ecore_evas_init(); // FIXME: check errors
467    ecore_imf_init();
468    _elm_module_init();
469
470    _elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
471
472    if (argv) _elm_appname = strdup(ecore_file_file_get(argv[0]));
473
474    if (!_elm_data_dir)
475      {
476    s = getenv("ELM_DATA_DIR");
477    _elm_data_dir = eina_stringshare_add(s);
478      }
479    if (!_elm_data_dir)
480      {
481    s = getenv("ELM_PREFIX");
482    if (s)
483      {
484         snprintf(buf, sizeof(buf), "%s/share/elementary", s);
485         _elm_data_dir = eina_stringshare_add(buf);
486      }
487      }
488    if (!_elm_lib_dir)
489      {
490    s = getenv("ELM_LIB_DIR");
491    _elm_lib_dir = eina_stringshare_add(s);
492      }
493    if (!_elm_lib_dir)
494      {
495    s = getenv("ELM_PREFIX");
496    if (s)
497      {
498         snprintf(buf, sizeof(buf), "%s/lib", s);
499         _elm_lib_dir = eina_stringshare_add(buf);
500      }
501      }
502 #ifdef HAVE_DLADDR
503    if ((!_elm_data_dir) || (!_elm_lib_dir))
504      {
505    Dl_info elementary_dl;
506    // libelementary.so/../../share/elementary/
507    if (dladdr(elm_init, &elementary_dl))
508      {
509         char *dir, *dir2;
510
511         dir = ecore_file_dir_get(elementary_dl.dli_fname);
512         if (dir)
513           {
514                   if (!_elm_lib_dir)
515                     {
516                        if (ecore_file_is_dir(dir))
517                          _elm_lib_dir = eina_stringshare_add(dir);
518                     }
519                   if (!_elm_data_dir)
520                     {
521                        dir2 = ecore_file_dir_get(dir);
522                        if (dir2)
523                          {
524                             snprintf(buf, sizeof(buf), "%s/share/elementary", dir2);
525                             if (ecore_file_is_dir(buf))
526                               _elm_data_dir = eina_stringshare_add(buf);
527                             free(dir2);
528                          }
529                     }
530         free(dir);
531           }
532      }
533      }
534 #endif
535    if (!_elm_data_dir)
536      _elm_data_dir = eina_stringshare_add(PACKAGE_DATA_DIR);
537   if (!_elm_data_dir)
538      _elm_data_dir = eina_stringshare_add("/");
539    if (!_elm_lib_dir)
540      _elm_lib_dir = eina_stringshare_add(PACKAGE_LIB_DIR);
541    if (!_elm_lib_dir)
542      _elm_lib_dir = eina_stringshare_add("/");
543
544    _elm_config_init();
545 }
546
547 EAPI void
548 elm_quicklaunch_sub_init(int argc, char **argv)
549 {
550    ecore_app_args_set(argc, (const char **)argv);
551    _elm_config_sub_init();
552 }
553
554 EAPI void
555 elm_quicklaunch_sub_shutdown(void)
556 {
557    _elm_win_shutdown();
558    if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
559        (_elm_config->engine == ELM_SOFTWARE_16_X11) ||
560        (_elm_config->engine == ELM_XRENDER_X11) ||
561        (_elm_config->engine == ELM_OPENGL_X11) ||
562        (_elm_config->engine == ELM_SOFTWARE_SDL) ||
563        (_elm_config->engine == ELM_SOFTWARE_16_SDL) ||
564        (_elm_config->engine == ELM_OPENGL_SDL) ||
565        (_elm_config->engine == ELM_SOFTWARE_WIN32) ||
566        (_elm_config->engine == ELM_SOFTWARE_16_WINCE))
567      {
568 #ifdef HAVE_ELEMENTARY_X
569    ecore_x_disconnect();
570 #endif
571    evas_cserve_disconnect();
572      }
573 }
574
575 EAPI void
576 elm_quicklaunch_shutdown(void)
577 {
578    eina_stringshare_del(_elm_data_dir);
579    _elm_data_dir = NULL;
580    eina_stringshare_del(_elm_lib_dir);
581    _elm_lib_dir = NULL;
582
583    free(_elm_appname);
584    _elm_appname = NULL;
585    
586    _elm_config_shutdown();
587    
588    ecore_event_handler_del(_elm_exit_handler);
589    _elm_exit_handler = NULL;
590
591    _elm_theme_shutdown();
592    _elm_unneed_efreet();
593    _elm_unneed_e_dbus();
594    _elm_unneed_ethumb();
595    _elm_module_shutdown();
596    ecore_imf_shutdown();
597    ecore_evas_shutdown();
598    edje_shutdown();
599    evas_shutdown();
600    ecore_file_shutdown();
601    ecore_shutdown();
602    eet_shutdown();
603
604    if ((_elm_log_dom > -1) && (_elm_log_dom != EINA_LOG_DOMAIN_GLOBAL))
605      {
606    eina_log_domain_unregister(_elm_log_dom);
607    _elm_log_dom = -1;
608      }
609
610    _elm_widtype_clear();
611    
612    eina_shutdown();
613 }
614
615 EAPI void
616 elm_quicklaunch_seed(void)
617 {
618    Evas_Object *win, *bg, *bt;
619
620    win = elm_win_add(NULL, "seed", ELM_WIN_BASIC);
621    bg = elm_bg_add(win);
622    elm_win_resize_object_add(win, bg);
623    evas_object_show(bg);
624    bt = elm_button_add(win);
625    elm_button_label_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?");
626    elm_win_resize_object_add(win, bt);
627    ecore_main_loop_iterate();
628    evas_object_del(win);
629    ecore_main_loop_iterate();
630    if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
631        (_elm_config->engine == ELM_SOFTWARE_16_X11) ||
632        (_elm_config->engine == ELM_XRENDER_X11) ||
633        (_elm_config->engine == ELM_OPENGL_X11))
634      {
635 #ifdef HAVE_ELEMENTARY_X
636    ecore_x_sync();
637 #endif
638       }
639    ecore_main_loop_iterate();
640 }
641
642 static void *qr_handle = NULL;
643 static int (*qr_main) (int argc, char **argv) = NULL;
644
645 EAPI Eina_Bool
646 elm_quicklaunch_prepare(int argc __UNUSED__, char **argv)
647 {
648 #ifdef HAVE_FORK
649    char *exe = elm_quicklaunch_exe_path_get(argv[0]);
650    if (!exe)
651      {
652    ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]);
653    return EINA_FALSE;
654      }
655    else
656      {
657    char *exe2, *p;
658    char *exename;
659
660    exe2 = malloc(strlen(exe) + 1 + 10);
661    strcpy(exe2, exe);
662    p = strrchr(exe2, '/');
663    if (p) p++;
664    else p = exe2;
665    exename = alloca(strlen(p) + 1);
666    strcpy(exename, p);
667    *p = 0;
668    strcat(p, "../lib/");
669    strcat(p, exename);
670    strcat(p, ".so");
671    if (access(exe2, R_OK | X_OK) == 0)
672      {
673         free(exe);
674         exe = exe2;
675      }
676    else
677      free(exe2);
678      }
679    qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL);
680    if (!qr_handle)
681      {
682         fprintf(stderr, "dlerr: %s\n", dlerror());
683    WRN("dlopen('%s') failed: %s", exe, dlerror());
684    free(exe);
685    return EINA_FALSE;
686      }
687    INF("dlopen('%s') = %p", exe, qr_handle);
688    free(exe);
689    qr_main = dlsym(qr_handle, "elm_main");
690    INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main);
691    if (!qr_main)
692      {
693    WRN("not quicklauncher capable: no elm_main in '%s'", exe);
694    dlclose(qr_handle);
695    qr_handle = NULL;
696    return EINA_FALSE;
697      }
698    return EINA_TRUE;
699 #else
700    return EINA_FALSE;
701 #endif
702 }
703
704 #ifdef HAVE_FORK
705 static void
706 save_env(void)
707 {
708    int i, size;
709    extern char **environ;
710    char **oldenv, **p;
711
712    oldenv = environ;
713
714    for (i = 0, size = 0; environ[i] != NULL; i++)
715      size += strlen(environ[i]) + 1;
716
717    p = malloc((i + 1) * sizeof(char *));
718    if (!p) return;
719
720    environ = p;
721
722    for (i = 0; oldenv[i] != NULL; i++)
723      environ[i] = strdup(oldenv[i]);
724    environ[i] = NULL;
725 }
726 #endif
727
728 EAPI Eina_Bool
729 elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data)
730 {
731 #ifdef HAVE_FORK
732    pid_t child;
733    int ret;
734    int real_argc;
735    char **real_argv;
736
737    // FIXME:
738    // need to accept current environment from elementary_run
739    if (!qr_main)
740      {
741    int i;
742    char **args;
743
744    child = fork();
745    if (child > 0) return EINA_TRUE;
746    else if (child < 0)
747      {
748         perror("could not fork");
749         return EINA_FALSE;
750      }
751    setsid();
752    if (chdir(cwd) != 0)
753      perror("could not chdir");
754    args = alloca((argc + 1) * sizeof(char *));
755    for (i = 0; i < argc; i++) args[i] = argv[i];
756    args[argc] = NULL;
757    WRN("%s not quicklaunch capable, fallback...", argv[0]);
758    execvp(argv[0], args);
759    ERR("failed to execute '%s': %s", argv[0], strerror(errno));
760    exit(-1);
761      }
762    child = fork();
763    if (child > 0) return EINA_TRUE;
764    else if (child < 0)
765      {
766    perror("could not fork");
767    return EINA_FALSE;
768      }
769    if (postfork_func) postfork_func(postfork_data);
770
771    setsid();
772    if (chdir(cwd) != 0)
773      perror("could not chdir");
774    // FIXME: this is very linux specific. it changes argv[0] of the process
775    // so ps etc. report what you'd expect. for other unixes and os's this
776    // may just not work
777    save_env();
778    if (argv)
779      {
780    char *lastarg, *p;
781
782    ecore_app_args_get(&real_argc, &real_argv);
783    lastarg = real_argv[real_argc - 1] + strlen(real_argv[real_argc - 1]);
784    for (p = real_argv[0]; p < lastarg; p++) *p = 0;
785    strcpy(real_argv[0], argv[0]);
786      }
787    ecore_app_args_set(argc, (const char **)argv);
788    ret = qr_main(argc, argv);
789    exit(ret);
790    return EINA_TRUE;
791 #else
792    return EINA_FALSE;
793 #endif
794 }
795
796 EAPI void
797 elm_quicklaunch_cleanup(void)
798 {
799 #ifdef HAVE_FORK
800    if (qr_handle)
801      {
802    dlclose(qr_handle);
803    qr_handle = NULL;
804    qr_main = NULL;
805      }
806 #endif
807 }
808
809 EAPI int
810 elm_quicklaunch_fallback(int argc, char **argv)
811 {
812    int ret;
813    elm_quicklaunch_init(argc, argv);
814    elm_quicklaunch_sub_init(argc, argv);
815    elm_quicklaunch_prepare(argc, argv);
816    ret = qr_main(argc, argv);
817    exit(ret);
818    return ret;
819 }
820
821 EAPI char *
822 elm_quicklaunch_exe_path_get(const char *exe)
823 {
824    static char *path = NULL;
825    static Eina_List *pathlist = NULL;
826    const char *pathitr;
827    const Eina_List *l;
828    char buf[PATH_MAX];
829    if (exe[0] == '/') return strdup(exe);
830    if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe);
831    if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe);
832    if (!path)
833      {
834    const char *p, *pp;
835    char *buf2;
836    path = getenv("PATH");
837    buf2 = alloca(strlen(path) + 1);
838    p = path;
839    pp = p;
840    for (;;)
841      {
842         if ((*p == ':') || (*p == 0))
843           {
844         int len;
845
846         len = p - pp;
847         strncpy(buf2, pp, len);
848         buf2[len] = 0;
849         pathlist = eina_list_append(pathlist, eina_stringshare_add(buf2));
850         if (*p == 0) break;
851         p++;
852         pp = p;
853           }
854         else
855           {
856         if (*p == 0) break;
857         p++;
858           }
859      }
860      }
861    EINA_LIST_FOREACH(pathlist, l, pathitr)
862      {
863    snprintf(buf, sizeof(buf), "%s/%s", pathitr, exe);
864    if (access(buf, R_OK | X_OK) == 0) return strdup(buf);
865      }
866    return NULL;
867 }
868
869 /**
870  * Run the main loop
871  *
872  * This call should be called just after all initialization is complete. This
873  * function will not return until elm_exit() is called. It will keep looping
874  * running the main event/processing loop for Elementary.
875  * @ingroup General
876  */
877 EAPI void
878 elm_run(void)
879 {
880    ecore_main_loop_begin();
881 }
882
883 /**
884  * Exit the main loop
885  *
886  * If this call is called, it will flag the main loop to cease processing and
887  * return back to its parent function.
888  * @ingroup General
889  */
890 EAPI void
891 elm_exit(void)
892 {
893    ecore_main_loop_quit();
894 }
895
896
897 /**
898  * Set new policy value.
899  *
900  * This will emit the ecore event ELM_EVENT_POLICY_CHANGED in the main
901  * loop giving the event information Elm_Event_Policy_Changed with
902  * policy identifier, new and old values.
903  *
904  * @param policy policy identifier as in Elm_Policy.
905  * @param value policy value, depends on identifiers, usually there is
906  *        an enumeration with the same prefix as the policy name, for
907  *        example: ELM_POLICY_QUIT and Elm_Policy_Quit
908  *        (ELM_POLICY_QUIT_NONE, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED).
909  *
910  * @return @c EINA_TRUE on success or @c EINA_FALSE on error (right
911  *         now just invalid policy identifier, but in future policy
912  *         value might be enforced).
913  */
914 EAPI Eina_Bool
915 elm_policy_set(unsigned int policy, int value)
916 {
917    Elm_Event_Policy_Changed *ev;
918
919    if (policy >= ELM_POLICY_LAST)
920      return EINA_FALSE;
921
922    if (value == _elm_policies[policy])
923      return EINA_TRUE;
924
925    /* TODO: validade policy? */
926
927    ev = malloc(sizeof(*ev));
928    ev->policy = policy;
929    ev->new_value = value;
930    ev->old_value = _elm_policies[policy];
931
932    _elm_policies[policy] = value;
933
934    ecore_event_add(ELM_EVENT_POLICY_CHANGED, ev, NULL, NULL);
935
936    return EINA_TRUE;
937 }
938
939 /**
940  * Gets the policy value set for given identifier.
941  *
942  * @param policy policy identifier as in Elm_Policy.
943  *
944  * @return policy value. Will be 0 if policy identifier is invalid.
945  */
946 EAPI int
947 elm_policy_get(unsigned int policy)
948 {
949    if (policy >= ELM_POLICY_LAST)
950      return 0;
951    return _elm_policies[policy];
952 }
953
954 /**
955  * Flush all caches & dump all data that can be to lean down to use less memory
956  */
957 EAPI void
958 elm_all_flush(void)
959 {
960    const Eina_List *l;
961    Evas_Object *obj;
962    
963    EINA_LIST_FOREACH(_elm_win_list, l, obj)
964      {
965         Evas *e = evas_object_evas_get(obj);
966         edje_file_cache_flush();
967         edje_collection_cache_flush();
968         evas_image_cache_flush(e);
969         evas_font_cache_flush(e);
970         evas_render_dump(e);
971      }
972 }
973
974 /**
975  * @defgroup Scaling Selective Widget Scaling
976  * @ingroup Main
977  *
978  * Different widgets can be scaled independently. These functions allow you to
979  * manipulate this scaling on a per-widget basis. The object and all its
980  * children get their scaling factors multiplied by the scale factor set.
981  * This is multiplicative, in that if a child also has a scale size set it is
982  * in turn multiplied by its parent's scale size. 1.0 means “don't scale”,
983  * 2.0 is double size, 0.5 is half etc.
984  */
985
986 /**
987  * Set the scaling factor
988  *
989  * @param obj The object
990  * @param scale Scale factor (from 0.0 up, with 1.0 == no scaling)
991  * @ingroup Scaling
992  */
993 EAPI void
994 elm_object_scale_set(Evas_Object *obj, double scale)
995 {
996    elm_widget_scale_set(obj, scale);
997 }
998
999 /**
1000  * Get the scaling factor
1001  *
1002  * @param obj The object
1003  * @return The scaling factor set by elm_object_scale_set()
1004  * @ingroup Scaling
1005  */
1006 EAPI double
1007 elm_object_scale_get(const Evas_Object *obj)
1008 {
1009    return elm_widget_scale_get(obj);
1010 }
1011
1012 /**
1013  * @defgroup Styles Styles
1014  * @ingroup Main
1015  *
1016  * Widgets can have different styles of look. These generic API's set
1017  * styles of widgets, if they support them (and if the theme(s) do).
1018  */
1019
1020 /**
1021  * Set the style
1022  *
1023  * This sets the name of the style
1024  * @param obj The object
1025  * @param style The style name to use
1026  * @ingroup Styles
1027  */
1028 EAPI void
1029 elm_object_style_set(Evas_Object *obj, const char *style)
1030 {
1031    elm_widget_style_set(obj, style);
1032 }
1033
1034 /**
1035  * Get the style
1036  *
1037  * This gets the style being used for that widget. Note that the string
1038  * pointer is only valid as longas the object is valid and the style doesn't
1039  * change.
1040  *
1041  * @param obj The object
1042  * @return The style name
1043  * @ingroup Styles
1044  */
1045 EAPI const char *
1046 elm_object_style_get(const Evas_Object *obj)
1047 {
1048    return elm_widget_style_get(obj);
1049 }
1050
1051 /**
1052  * Set the disable state
1053  *
1054  * This sets the disable state for the widget.
1055  *
1056  * @param obj The object
1057  * @param disabled The state
1058  * @ingroup Styles
1059  */
1060 EAPI void
1061 elm_object_disabled_set(Evas_Object *obj, Eina_Bool disabled)
1062 {
1063    elm_widget_disabled_set(obj, disabled);
1064 }
1065
1066 /**
1067  * Get the disable state
1068  *
1069  * This gets the disable state for the widget.
1070  *
1071  * @param obj The object
1072  * @return True, if the widget is disabled
1073  * @ingroup Styles
1074  */
1075 EAPI Eina_Bool
1076 elm_object_disabled_get(const Evas_Object *obj)
1077 {
1078    return elm_widget_disabled_get(obj);
1079 }
1080
1081 /**
1082  * Get the global scaling factor
1083  *
1084  * This gets the globally configured scaling factor that is applied to all
1085  * objects.
1086  *
1087  * @return The scaling factor
1088  * @ingroup Scaling
1089  */
1090 EAPI double
1091 elm_scale_get(void)
1092 {
1093    return _elm_config->scale;
1094 }
1095
1096 /**
1097  * Set the global scaling factor
1098  *
1099  * This sets the globally configured scaling factor that is applied to all
1100  * objects.
1101  *
1102  * @param scale The scaling factor to set
1103  * @ingroup Scaling
1104  */
1105 EAPI void
1106 elm_scale_set(double scale)
1107 {
1108    if (_elm_config->scale == scale) return;
1109    _elm_config->scale = scale;
1110    _elm_rescale();
1111 }
1112
1113 /**
1114  * Set the global scaling factor for all applications on the display
1115  * 
1116  * This sets the globally configured scaling factor that is applied to all
1117  * objects for all applications.
1118  * @param scale The scaling factor to set
1119  * @ingroup Scaling
1120  */
1121 EAPI void
1122 elm_scale_all_set(double scale)
1123 {
1124 #ifdef HAVE_ELEMENTARY_X
1125    static Ecore_X_Atom atom = 0;
1126    unsigned int scale_i = (unsigned int)(scale * 1000.0);
1127
1128    if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_SCALE");
1129    ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
1130                                   atom, &scale_i, 1);
1131 #endif   
1132 }
1133
1134 /**
1135  * @defgroup Fingers Fingers
1136  * @ingroup Main
1137  *
1138  * Elementary is designed to be finger-friendly for touchscreens, and so in
1139  * addition to scaling for display resolution, it can also scale based on
1140  * finger "resolution" (or size).
1141  */
1142
1143 /**
1144  * Get the configured finger size
1145  *
1146  * This gets the globally configured finger size in pixels
1147  *
1148  * @return The finger size
1149  * @ingroup Fingers
1150  */
1151 EAPI Evas_Coord
1152 elm_finger_size_get(void)
1153 {
1154    return _elm_config->finger_size;
1155 }
1156
1157 /**
1158  * Set the configured finger size
1159  *
1160  * This sets the globally configured finger size in pixels
1161  *
1162  * @param size The finger size
1163  * @ingroup Fingers
1164  */
1165 EAPI void
1166 elm_finger_size_set(Evas_Coord size)
1167 {
1168    if (_elm_config->finger_size == size) return;
1169    _elm_config->finger_size = size;
1170    _elm_rescale();
1171 }
1172
1173 /**
1174  * Set the configured finger size for all applications on the display
1175  *
1176  * This sets the globally configured finger size in pixels for all applications
1177  * on the display
1178  *
1179  * @param size The finger size
1180  * @ingroup Fingers
1181  */
1182 EAPI void
1183 elm_finger_size_all_set(Evas_Coord size)
1184 {
1185 #ifdef HAVE_ELEMENTARY_X
1186    static Ecore_X_Atom atom = 0;
1187    unsigned int size_i = (unsigned int)size;
1188
1189    if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_FINGER_SIZE");
1190    ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
1191                                   atom, &size_i, 1);
1192 #endif   
1193 }
1194
1195 /**
1196  * Adjust size of an element for finger usage
1197  *
1198  * This takes width and height sizes (in pixels) as input and a size multiple
1199  * (which is how many fingers you want to place within the area), and adjusts
1200  * the size tobe large enough to accomodate finger. On return the w and h
1201  * sizes poiner do by these parameters will be modified.
1202  *
1203  * @param times_w How many fingers should fit horizontally
1204  * @param w Pointer to the width size to adjust
1205  * @param times_h How many fingers should fit vertically
1206  * @param h Pointer to the height size to adjust
1207  * @ingroup Fingers
1208  */
1209 EAPI void
1210 elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h)
1211 {
1212    if ((w) && (*w < (_elm_config->finger_size * times_w)))
1213      *w = _elm_config->finger_size * times_w;
1214    if ((h) && (*h < (_elm_config->finger_size * times_h)))
1215      *h = _elm_config->finger_size * times_h;
1216 }
1217
1218 /**
1219  * @defgroup Focus Focus
1220  * @ingroup Main
1221  *
1222  * Objects have focus. This is what determines where the keyboard input goes to
1223  * within the application window.
1224  */
1225
1226 /**
1227  * Get the focus of the object
1228  *
1229  * This gets the focused property of the object.
1230  *
1231  * @param obj The object
1232  * @return 1 if the object is focused, 0 if not.
1233  * @ingroup Focus
1234  */
1235 EAPI Eina_Bool
1236 elm_object_focus_get(Evas_Object *obj)
1237 {
1238    return elm_widget_focus_get(obj);
1239 }
1240
1241 /**
1242  * Set the focus to the object
1243  *
1244  * This sets the focus target for keyboard input to be the object indicated.
1245  *
1246  * @param obj The object
1247  * @ingroup Focus
1248  */
1249 EAPI void
1250 elm_object_focus(Evas_Object *obj)
1251 {
1252    if (!elm_widget_can_focus_get(obj)) return;
1253    elm_widget_focus_steal(obj);
1254 }
1255
1256 /**
1257  * Remove the focus from the object
1258  *
1259  * This removes the focus target for keyboard input from be the object
1260  * indicated.
1261  *
1262  * @param obj The object
1263  * @ingroup Focus
1264  */
1265 EAPI void
1266 elm_object_unfocus(Evas_Object *obj)
1267 {
1268    if (!elm_widget_can_focus_get(obj)) return;
1269    elm_widget_focused_object_clear(obj);
1270 }
1271
1272 /**
1273  * Set the ability for the object to focus
1274  *
1275  * This sets the ability for the object to be able to get keyboard focus or
1276  * not. By default all objects are able to be focused.
1277  *
1278  * @param obj The object
1279  * @param enable 1 if the object can be focused, 0 if not
1280  * @ingroup Focus
1281  */
1282 EAPI void
1283 elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable)
1284 {
1285    elm_widget_can_focus_set(obj, enable);
1286 }
1287
1288 /**
1289  * Get the ability for the object to focus
1290  *
1291  * This gets the ability for the object to be able to get keyboard focus or
1292  * not. By default all objects are able to be focused.
1293  *
1294  * @param obj The object
1295  * @return 1 if the object is allowed to be focused, 0 if not.
1296  * @ingroup Focus
1297  */
1298 EAPI Eina_Bool
1299 elm_object_focus_allow_get(const Evas_Object *obj)
1300 {
1301    return elm_widget_can_focus_get(obj);
1302 }
1303
1304 /**
1305  * @defgroup Scrollhints Scrollhints
1306  * @ingroup Main
1307  *
1308  * Objects when inside a scroller can scroll, but this may not always be
1309  * desireable in certain situations. This allows an object to hint to itself
1310  * and parents to "not scroll" in one of 2 ways.
1311  * 
1312  * 1. To hold on scrolling. This means just flicking and dragging may no
1313  * longer scroll, but pressing/dragging near an edge of the scroller will
1314  * still scroll. This is automastically used by the entry object when
1315  * selecting text.
1316  * 2. To totally freeze scrolling. This means it stops. until popped/released.
1317  */
1318
1319 /**
1320  * Push the scroll hold by 1
1321  *
1322  * This increments the scroll hold count by one. If it is more than 0 it will
1323  * take effect on the parents of the indicated object.
1324  *
1325  * @param obj The object
1326  * @ingroup Scrollhints
1327  */
1328 EAPI void
1329 elm_object_scroll_hold_push(Evas_Object *obj)
1330 {
1331    elm_widget_scroll_hold_push(obj);
1332 }
1333
1334 /**
1335  * Pop the scroll hold by 1
1336  *
1337  * This decrements the scroll hold count by one. If it is more than 0 it will
1338  * take effect on the parents of the indicated object.
1339  *
1340  * @param obj The object
1341  * @ingroup Scrollhints
1342  */
1343 EAPI void
1344 elm_object_scroll_hold_pop(Evas_Object *obj)
1345 {
1346    elm_widget_scroll_hold_pop(obj);
1347 }
1348
1349 /**
1350  * Push the scroll freeze by 1
1351  *
1352  * This increments the scroll freeze count by one. If it is more than 0 it will
1353  * take effect on the parents of the indicated object.
1354  *
1355  * @param obj The object
1356  * @ingroup Scrollhints
1357  */
1358 EAPI void
1359 elm_object_scroll_freeze_push(Evas_Object *obj)
1360 {
1361    elm_widget_scroll_freeze_push(obj);
1362 }
1363
1364 /**
1365  * Lock the scrolling of the given widget (and thus all parents)
1366  *
1367  * This locks the given object from scrolling in the X axis (and implicitly
1368  * also locks all parent scrollers too from doing the same).
1369  *
1370  * @param obj The object
1371  * @param lock The lock state (1 == locked, 0 == unlocked)
1372  * @ingroup Scrollhints
1373  */
1374 EAPI void
1375 elm_object_scroll_lock_x_set(Evas_Object *obj, Eina_Bool lock)
1376 {
1377    elm_widget_drag_lock_x_set(obj, lock);
1378 }
1379
1380 /**
1381  * Lock the scrolling of the given widget (and thus all parents)
1382  *
1383  * This locks the given object from scrolling in the Y axis (and implicitly
1384  * also locks all parent scrollers too from doing the same).
1385  *
1386  * @param obj The object
1387  * @param lock The lock state (1 == locked, 0 == unlocked)
1388  * @ingroup Scrollhints
1389  */
1390 EAPI void
1391 elm_object_scroll_lock_y_set(Evas_Object *obj, Eina_Bool lock)
1392 {
1393    elm_widget_drag_lock_y_set(obj, lock);
1394 }
1395
1396 /**
1397  * Get the scrolling lock of the given widget
1398  *
1399  * This gets the lock for X axis scrolling.
1400  *
1401  * @param obj The object
1402  * @ingroup Scrollhints
1403  */
1404 EAPI Eina_Bool
1405 elm_object_scroll_lock_x_get(const Evas_Object *obj)
1406 {
1407    return elm_widget_drag_lock_x_get(obj);
1408 }
1409
1410 /**
1411  * Get the scrolling lock of the given widget
1412  *
1413  * This gets the lock for X axis scrolling.
1414  *
1415  * @param obj The object
1416  * @ingroup Scrollhints
1417  */
1418 EAPI Eina_Bool
1419 elm_object_scroll_lock_y_get(const Evas_Object *obj)
1420 {
1421    return elm_widget_drag_lock_y_get(obj);
1422 }
1423
1424 /**
1425  * Pop the scroll freeze by 1
1426  *
1427  * This decrements the scroll freeze count by one. If it is more than 0 it will
1428  * take effect on the parents of the indicated object.
1429  *
1430  * @param obj The object
1431  * @ingroup Scrollhints
1432  */
1433 EAPI void
1434 elm_object_scroll_freeze_pop(Evas_Object *obj)
1435 {
1436    elm_widget_scroll_freeze_pop(obj);
1437 }
1438
1439
1440 /**
1441  * Check if the given Evas Object is an Elementary widget.
1442  *
1443  * @param obj the object to query.
1444  * @return @c EINA_TRUE if it is an elementary widget variant,
1445  *         @c EINA_FALSE otherwise
1446  */
1447 EAPI Eina_Bool
1448 elm_object_widget_check(const Evas_Object *obj)
1449 {
1450    return elm_widget_is(obj);
1451 }
1452
1453 /**
1454  * Get the first parent of the given object that is an Elementary widget.
1455  *
1456  * @param obj the object to query.
1457  * @return the parent object that is an Elementary widget, or @c NULL
1458  *         if no parent is, or no parents at all.
1459  */
1460 EAPI Evas_Object *
1461 elm_object_parent_widget_get(const Evas_Object *obj)
1462 {
1463    return elm_widget_parent_widget_get(obj);
1464 }
1465
1466 /**
1467  * Get the string that represents this Elementary widget.
1468  *
1469  * @note Elementary is weird and exposes itself as a single
1470  *       Evas_Object_Smart_Class of type "elm_widget", so
1471  *       evas_object_type_get() always return that, making debug and
1472  *       language bindings hard. This function tries to mitigate this
1473  *       problem, but the solution is to change Elementary to use
1474  *       proper inheritance.
1475  *
1476  * @param obj the object to query.
1477  * @return Elementary widget name, or @c NULL if not a valid widget.
1478  */
1479 EAPI const char *
1480 elm_object_widget_type_get(const Evas_Object *obj)
1481 {
1482    return elm_widget_type_get(obj);
1483 }