70a24218e3f2baba419197ff0c4c6edf5633a56d
[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 static void                                                                             
321 _set_elm_module()                                                                
322 {                                                                                
323    char *buf = NULL;
324
325    buf = getenv("ELM_THEME");
326    if (buf != NULL && ((!strcmp(buf, "beat") || !strcmp(buf, "kessler"))))
327       setenv("ELM_MODULES","ctxpopup_copypasteUI>entry/api",1);
328 }
329
330 /**
331  * @defgroup General General
332  * @ingroup Main
333  */
334
335 /**
336  * Inititalise Elementary
337  *
338  * This call is exported only for use by the ELM_MAIN() macro. There is no
339  * need to use this if you use this macro (which is highly advisable).
340  * @ingroup General
341  */
342 EAPI void
343 elm_init(int argc, char **argv)
344 {
345    _elm_init_count++;
346    if (_elm_init_count != 1) return;
347    _set_elm_module();
348    elm_quicklaunch_init(argc, argv);
349    elm_quicklaunch_sub_init(argc, argv);
350 }
351
352 /**
353  * Shut down Elementary
354  *
355  * This should be called at the end of your application just before it ceases
356  * to do any more processing. This will clean up any permanent resources your
357  * application may have allocated via Elementary that would otherwise persist
358  * on an exit without this call.
359  * @ingroup General
360  */
361 EAPI void
362 elm_shutdown(void)
363 {
364    _elm_init_count--;
365    if (_elm_init_count != 0) return;
366    elm_quicklaunch_sub_shutdown();
367    elm_quicklaunch_shutdown();
368 }
369
370 #ifdef ELM_EDBUS
371 static Eina_Bool _elm_need_e_dbus = EINA_FALSE;
372 #endif
373 EAPI void
374 elm_need_e_dbus(void)
375 {
376 #ifdef ELM_EDBUS
377    if (_elm_need_e_dbus) return;
378    _elm_need_e_dbus = 1;
379    e_dbus_init();
380    e_hal_init();
381 #endif   
382 }
383
384 static void
385 _elm_unneed_e_dbus(void)
386 {
387 #ifdef ELM_EDBUS
388    if (_elm_need_e_dbus)
389      {
390         _elm_need_e_dbus = 0;
391    e_hal_shutdown();
392         e_dbus_shutdown();
393      }
394 #endif   
395 }
396
397 #ifdef ELM_EFREET
398 static Eina_Bool _elm_need_efreet = EINA_FALSE;
399 #endif
400 EAPI void
401 elm_need_efreet(void)
402 {
403 #ifdef ELM_EFREET
404    if (_elm_need_efreet) return;
405    _elm_need_efreet = 1;
406    efreet_init();
407    efreet_mime_init();
408    efreet_trash_init();
409    /*
410      {
411         Eina_List **list;
412         
413         list = efreet_icon_extra_list_get();
414         if (list)
415           {
416              e_user_dir_concat_static(buf, "icons");
417              *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
418              e_prefix_data_concat_static(buf, "data/icons");
419              *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
420           }
421      }
422    */
423 #endif
424 }
425
426 static void
427 _elm_unneed_efreet(void)
428 {
429 #ifdef ELM_EFREET
430    if (_elm_need_efreet)
431      {
432         _elm_need_efreet = 0;
433         efreet_trash_shutdown();
434         efreet_mime_shutdown();
435         efreet_shutdown();
436      }
437 #endif   
438 }
439
440 EAPI void
441 elm_quicklaunch_init(int argc, char **argv)
442 {
443    char buf[PATH_MAX], *s;
444    
445    eina_init();
446    _elm_log_dom = eina_log_domain_register("elementary", EINA_COLOR_LIGHTBLUE);
447    if (!_elm_log_dom)
448      {
449    EINA_LOG_ERR("could not register elementary log domain.");
450    _elm_log_dom = EINA_LOG_DOMAIN_GLOBAL;
451      }
452
453    eet_init();
454    ecore_init();
455    ecore_app_args_set(argc, (const char **)argv);
456
457    memset(_elm_policies, 0, sizeof(_elm_policies));
458    if (ELM_EVENT_POLICY_CHANGED == 0)
459      ELM_EVENT_POLICY_CHANGED = ecore_event_type_new();
460
461    ecore_file_init();
462    evas_init();
463    edje_init();
464    ecore_evas_init(); // FIXME: check errors
465    ecore_imf_init();
466    _elm_module_init();
467
468    _elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
469
470    if (argv) _elm_appname = strdup(ecore_file_file_get(argv[0]));
471
472    if (!_elm_data_dir)
473      {
474    s = getenv("ELM_DATA_DIR");
475    _elm_data_dir = eina_stringshare_add(s);
476      }
477    if (!_elm_data_dir)
478      {
479    s = getenv("ELM_PREFIX");
480    if (s)
481      {
482         snprintf(buf, sizeof(buf), "%s/share/elementary", s);
483         _elm_data_dir = eina_stringshare_add(buf);
484      }
485      }
486    if (!_elm_lib_dir)
487      {
488    s = getenv("ELM_LIB_DIR");
489    _elm_lib_dir = eina_stringshare_add(s);
490      }
491    if (!_elm_lib_dir)
492      {
493    s = getenv("ELM_PREFIX");
494    if (s)
495      {
496         snprintf(buf, sizeof(buf), "%s/lib", s);
497         _elm_lib_dir = eina_stringshare_add(buf);
498      }
499      }
500 #ifdef HAVE_DLADDR
501    if ((!_elm_data_dir) || (!_elm_lib_dir))
502      {
503    Dl_info elementary_dl;
504    // libelementary.so/../../share/elementary/
505    if (dladdr(elm_init, &elementary_dl))
506      {
507         char *dir, *dir2;
508
509         dir = ecore_file_dir_get(elementary_dl.dli_fname);
510         if (dir)
511           {
512                   if (!_elm_lib_dir)
513                     {
514                        if (ecore_file_is_dir(dir))
515                          _elm_lib_dir = eina_stringshare_add(dir);
516                     }
517                   if (!_elm_data_dir)
518                     {
519                        dir2 = ecore_file_dir_get(dir);
520                        if (dir2)
521                          {
522                             snprintf(buf, sizeof(buf), "%s/share/elementary", dir2);
523                             if (ecore_file_is_dir(buf))
524                               _elm_data_dir = eina_stringshare_add(buf);
525                             free(dir2);
526                          }
527                     }
528         free(dir);
529           }
530      }
531      }
532 #endif
533    if (!_elm_data_dir)
534      _elm_data_dir = eina_stringshare_add(PACKAGE_DATA_DIR);
535   if (!_elm_data_dir)
536      _elm_data_dir = eina_stringshare_add("/");
537    if (!_elm_lib_dir)
538      _elm_lib_dir = eina_stringshare_add(PACKAGE_LIB_DIR);
539    if (!_elm_lib_dir)
540      _elm_lib_dir = eina_stringshare_add("/");
541
542    _elm_config_init();
543 }
544
545 EAPI void
546 elm_quicklaunch_sub_init(int argc, char **argv)
547 {
548    ecore_app_args_set(argc, (const char **)argv);
549    _elm_config_sub_init();
550 }
551
552 EAPI void
553 elm_quicklaunch_sub_shutdown(void)
554 {
555    _elm_win_shutdown();
556    if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
557        (_elm_config->engine == ELM_SOFTWARE_16_X11) ||
558        (_elm_config->engine == ELM_XRENDER_X11) ||
559        (_elm_config->engine == ELM_OPENGL_X11) ||
560        (_elm_config->engine == ELM_SOFTWARE_SDL) ||
561        (_elm_config->engine == ELM_SOFTWARE_16_SDL) ||
562        (_elm_config->engine == ELM_OPENGL_SDL) ||
563        (_elm_config->engine == ELM_SOFTWARE_WIN32) ||
564        (_elm_config->engine == ELM_SOFTWARE_16_WINCE))
565      {
566 #ifdef HAVE_ELEMENTARY_X
567    ecore_x_disconnect();
568 #endif
569    evas_cserve_disconnect();
570      }
571 }
572
573 EAPI void
574 elm_quicklaunch_shutdown(void)
575 {
576    eina_stringshare_del(_elm_data_dir);
577    _elm_data_dir = NULL;
578    eina_stringshare_del(_elm_lib_dir);
579    _elm_lib_dir = NULL;
580
581    free(_elm_appname);
582    _elm_appname = NULL;
583    
584    _elm_config_shutdown();
585    
586    ecore_event_handler_del(_elm_exit_handler);
587    _elm_exit_handler = NULL;
588
589    _elm_theme_shutdown();
590    _elm_unneed_efreet();
591    _elm_unneed_e_dbus();
592    _elm_unneed_ethumb();
593    _elm_module_shutdown();
594    ecore_imf_shutdown();
595    ecore_evas_shutdown();
596    edje_shutdown();
597    evas_shutdown();
598    ecore_file_shutdown();
599    ecore_shutdown();
600    eet_shutdown();
601
602    if ((_elm_log_dom > -1) && (_elm_log_dom != EINA_LOG_DOMAIN_GLOBAL))
603      {
604    eina_log_domain_unregister(_elm_log_dom);
605    _elm_log_dom = -1;
606      }
607
608    _elm_widtype_clear();
609    
610    eina_shutdown();
611 }
612
613 EAPI void
614 elm_quicklaunch_seed(void)
615 {
616    Evas_Object *win, *bg, *bt;
617
618    win = elm_win_add(NULL, "seed", ELM_WIN_BASIC);
619    bg = elm_bg_add(win);
620    elm_win_resize_object_add(win, bg);
621    evas_object_show(bg);
622    bt = elm_button_add(win);
623    elm_button_label_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?");
624    elm_win_resize_object_add(win, bt);
625    ecore_main_loop_iterate();
626    evas_object_del(win);
627    ecore_main_loop_iterate();
628    if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
629        (_elm_config->engine == ELM_SOFTWARE_16_X11) ||
630        (_elm_config->engine == ELM_XRENDER_X11) ||
631        (_elm_config->engine == ELM_OPENGL_X11))
632      {
633 #ifdef HAVE_ELEMENTARY_X
634    ecore_x_sync();
635 #endif
636       }
637    ecore_main_loop_iterate();
638 }
639
640 static void *qr_handle = NULL;
641 static int (*qr_main) (int argc, char **argv) = NULL;
642
643 EAPI Eina_Bool
644 elm_quicklaunch_prepare(int argc __UNUSED__, char **argv)
645 {
646 #ifdef HAVE_FORK
647    char *exe = elm_quicklaunch_exe_path_get(argv[0]);
648    if (!exe)
649      {
650    ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]);
651    return EINA_FALSE;
652      }
653    else
654      {
655    char *exe2, *p;
656    char *exename;
657
658    exe2 = malloc(strlen(exe) + 1 + 10);
659    strcpy(exe2, exe);
660    p = strrchr(exe2, '/');
661    if (p) p++;
662    else p = exe2;
663    exename = alloca(strlen(p) + 1);
664    strcpy(exename, p);
665    *p = 0;
666    strcat(p, "../lib/");
667    strcat(p, exename);
668    strcat(p, ".so");
669    if (access(exe2, R_OK | X_OK) == 0)
670      {
671         free(exe);
672         exe = exe2;
673      }
674    else
675      free(exe2);
676      }
677    qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL);
678    if (!qr_handle)
679      {
680         fprintf(stderr, "dlerr: %s\n", dlerror());
681    WRN("dlopen('%s') failed: %s", exe, dlerror());
682    free(exe);
683    return EINA_FALSE;
684      }
685    INF("dlopen('%s') = %p", exe, qr_handle);
686    free(exe);
687    qr_main = dlsym(qr_handle, "elm_main");
688    INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main);
689    if (!qr_main)
690      {
691    WRN("not quicklauncher capable: no elm_main in '%s'", exe);
692    dlclose(qr_handle);
693    qr_handle = NULL;
694    return EINA_FALSE;
695      }
696    return EINA_TRUE;
697 #else
698    return EINA_FALSE;
699 #endif
700 }
701
702 #ifdef HAVE_FORK
703 static void
704 save_env(void)
705 {
706    int i, size;
707    extern char **environ;
708    char **oldenv, **p;
709
710    oldenv = environ;
711
712    for (i = 0, size = 0; environ[i] != NULL; i++)
713      size += strlen(environ[i]) + 1;
714
715    p = malloc((i + 1) * sizeof(char *));
716    if (!p) return;
717
718    environ = p;
719
720    for (i = 0; oldenv[i] != NULL; i++)
721      environ[i] = strdup(oldenv[i]);
722    environ[i] = NULL;
723 }
724 #endif
725
726 EAPI Eina_Bool
727 elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data)
728 {
729 #ifdef HAVE_FORK
730    pid_t child;
731    int ret;
732    int real_argc;
733    char **real_argv;
734
735    // FIXME:
736    // need to accept current environment from elementary_run
737    if (!qr_main)
738      {
739    int i;
740    char **args;
741
742    child = fork();
743    if (child > 0) return EINA_TRUE;
744    else if (child < 0)
745      {
746         perror("could not fork");
747         return EINA_FALSE;
748      }
749    setsid();
750    if (chdir(cwd) != 0)
751      perror("could not chdir");
752    args = alloca((argc + 1) * sizeof(char *));
753    for (i = 0; i < argc; i++) args[i] = argv[i];
754    args[argc] = NULL;
755    WRN("%s not quicklaunch capable, fallback...", argv[0]);
756    execvp(argv[0], args);
757    ERR("failed to execute '%s': %s", argv[0], strerror(errno));
758    exit(-1);
759      }
760    child = fork();
761    if (child > 0) return EINA_TRUE;
762    else if (child < 0)
763      {
764    perror("could not fork");
765    return EINA_FALSE;
766      }
767    if (postfork_func) postfork_func(postfork_data);
768
769    setsid();
770    if (chdir(cwd) != 0)
771      perror("could not chdir");
772    // FIXME: this is very linux specific. it changes argv[0] of the process
773    // so ps etc. report what you'd expect. for other unixes and os's this
774    // may just not work
775    save_env();
776    if (argv)
777      {
778    char *lastarg, *p;
779
780    ecore_app_args_get(&real_argc, &real_argv);
781    lastarg = real_argv[real_argc - 1] + strlen(real_argv[real_argc - 1]);
782    for (p = real_argv[0]; p < lastarg; p++) *p = 0;
783    strcpy(real_argv[0], argv[0]);
784      }
785    ecore_app_args_set(argc, (const char **)argv);
786    ret = qr_main(argc, argv);
787    exit(ret);
788    return EINA_TRUE;
789 #else
790    return EINA_FALSE;
791 #endif
792 }
793
794 EAPI void
795 elm_quicklaunch_cleanup(void)
796 {
797 #ifdef HAVE_FORK
798    if (qr_handle)
799      {
800    dlclose(qr_handle);
801    qr_handle = NULL;
802    qr_main = NULL;
803      }
804 #endif
805 }
806
807 EAPI int
808 elm_quicklaunch_fallback(int argc, char **argv)
809 {
810    int ret;
811    elm_quicklaunch_init(argc, argv);
812    elm_quicklaunch_sub_init(argc, argv);
813    elm_quicklaunch_prepare(argc, argv);
814    ret = qr_main(argc, argv);
815    exit(ret);
816    return ret;
817 }
818
819 EAPI char *
820 elm_quicklaunch_exe_path_get(const char *exe)
821 {
822    static char *path = NULL;
823    static Eina_List *pathlist = NULL;
824    const char *pathitr;
825    const Eina_List *l;
826    char buf[PATH_MAX];
827    if (exe[0] == '/') return strdup(exe);
828    if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe);
829    if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe);
830    if (!path)
831      {
832    const char *p, *pp;
833    char *buf2;
834    path = getenv("PATH");
835    buf2 = alloca(strlen(path) + 1);
836    p = path;
837    pp = p;
838    for (;;)
839      {
840         if ((*p == ':') || (*p == 0))
841           {
842         int len;
843
844         len = p - pp;
845         strncpy(buf2, pp, len);
846         buf2[len] = 0;
847         pathlist = eina_list_append(pathlist, eina_stringshare_add(buf2));
848         if (*p == 0) break;
849         p++;
850         pp = p;
851           }
852         else
853           {
854         if (*p == 0) break;
855         p++;
856           }
857      }
858      }
859    EINA_LIST_FOREACH(pathlist, l, pathitr)
860      {
861    snprintf(buf, sizeof(buf), "%s/%s", pathitr, exe);
862    if (access(buf, R_OK | X_OK) == 0) return strdup(buf);
863      }
864    return NULL;
865 }
866
867 /**
868  * Run the main loop
869  *
870  * This call should be called just after all initialization is complete. This
871  * function will not return until elm_exit() is called. It will keep looping
872  * running the main event/processing loop for Elementary.
873  * @ingroup General
874  */
875 EAPI void
876 elm_run(void)
877 {
878    ecore_main_loop_begin();
879 }
880
881 /**
882  * Exit the main loop
883  *
884  * If this call is called, it will flag the main loop to cease processing and
885  * return back to its parent function.
886  * @ingroup General
887  */
888 EAPI void
889 elm_exit(void)
890 {
891    ecore_main_loop_quit();
892 }
893
894
895 /**
896  * Set new policy value.
897  *
898  * This will emit the ecore event ELM_EVENT_POLICY_CHANGED in the main
899  * loop giving the event information Elm_Event_Policy_Changed with
900  * policy identifier, new and old values.
901  *
902  * @param policy policy identifier as in Elm_Policy.
903  * @param value policy value, depends on identifiers, usually there is
904  *        an enumeration with the same prefix as the policy name, for
905  *        example: ELM_POLICY_QUIT and Elm_Policy_Quit
906  *        (ELM_POLICY_QUIT_NONE, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED).
907  *
908  * @return @c EINA_TRUE on success or @c EINA_FALSE on error (right
909  *         now just invalid policy identifier, but in future policy
910  *         value might be enforced).
911  */
912 EAPI Eina_Bool
913 elm_policy_set(unsigned int policy, int value)
914 {
915    Elm_Event_Policy_Changed *ev;
916
917    if (policy >= ELM_POLICY_LAST)
918      return EINA_FALSE;
919
920    if (value == _elm_policies[policy])
921      return EINA_TRUE;
922
923    /* TODO: validade policy? */
924
925    ev = malloc(sizeof(*ev));
926    ev->policy = policy;
927    ev->new_value = value;
928    ev->old_value = _elm_policies[policy];
929
930    _elm_policies[policy] = value;
931
932    ecore_event_add(ELM_EVENT_POLICY_CHANGED, ev, NULL, NULL);
933
934    return EINA_TRUE;
935 }
936
937 /**
938  * Gets the policy value set for given identifier.
939  *
940  * @param policy policy identifier as in Elm_Policy.
941  *
942  * @return policy value. Will be 0 if policy identifier is invalid.
943  */
944 EAPI int
945 elm_policy_get(unsigned int policy)
946 {
947    if (policy >= ELM_POLICY_LAST)
948      return 0;
949    return _elm_policies[policy];
950 }
951
952 /**
953  * Flush all caches & dump all data that can be to lean down to use less memory
954  */
955 EAPI void
956 elm_all_flush(void)
957 {
958    const Eina_List *l;
959    Evas_Object *obj;
960    
961    EINA_LIST_FOREACH(_elm_win_list, l, obj)
962      {
963         Evas *e = evas_object_evas_get(obj);
964         edje_file_cache_flush();
965         edje_collection_cache_flush();
966         evas_image_cache_flush(e);
967         evas_font_cache_flush(e);
968         evas_render_dump(e);
969      }
970 }
971
972 /**
973  * @defgroup Scaling Selective Widget Scaling
974  * @ingroup Main
975  *
976  * Different widgets can be scaled independently. These functions allow you to
977  * manipulate this scaling on a per-widget basis. The object and all its
978  * children get their scaling factors multiplied by the scale factor set.
979  * This is multiplicative, in that if a child also has a scale size set it is
980  * in turn multiplied by its parent's scale size. 1.0 means “don't scale”,
981  * 2.0 is double size, 0.5 is half etc.
982  */
983
984 /**
985  * Set the scaling factor
986  *
987  * @param obj The object
988  * @param scale Scale factor (from 0.0 up, with 1.0 == no scaling)
989  * @ingroup Scaling
990  */
991 EAPI void
992 elm_object_scale_set(Evas_Object *obj, double scale)
993 {
994    elm_widget_scale_set(obj, scale);
995 }
996
997 /**
998  * Get the scaling factor
999  *
1000  * @param obj The object
1001  * @return The scaling factor set by elm_object_scale_set()
1002  * @ingroup Scaling
1003  */
1004 EAPI double
1005 elm_object_scale_get(const Evas_Object *obj)
1006 {
1007    return elm_widget_scale_get(obj);
1008 }
1009
1010 /**
1011  * @defgroup Styles Styles
1012  * @ingroup Main
1013  *
1014  * Widgets can have different styles of look. These generic API's set
1015  * styles of widgets, if they support them (and if the theme(s) do).
1016  */
1017
1018 /**
1019  * Set the style
1020  *
1021  * This sets the name of the style
1022  * @param obj The object
1023  * @param style The style name to use
1024  * @ingroup Styles
1025  */
1026 EAPI void
1027 elm_object_style_set(Evas_Object *obj, const char *style)
1028 {
1029    elm_widget_style_set(obj, style);
1030 }
1031
1032 /**
1033  * Get the style
1034  *
1035  * This gets the style being used for that widget. Note that the string
1036  * pointer is only valid as longas the object is valid and the style doesn't
1037  * change.
1038  *
1039  * @param obj The object
1040  * @return The style name
1041  * @ingroup Styles
1042  */
1043 EAPI const char *
1044 elm_object_style_get(const Evas_Object *obj)
1045 {
1046    return elm_widget_style_get(obj);
1047 }
1048
1049 /**
1050  * Set the disable state
1051  *
1052  * This sets the disable state for the widget.
1053  *
1054  * @param obj The object
1055  * @param disabled The state
1056  * @ingroup Styles
1057  */
1058 EAPI void
1059 elm_object_disabled_set(Evas_Object *obj, Eina_Bool disabled)
1060 {
1061    elm_widget_disabled_set(obj, disabled);
1062 }
1063
1064 /**
1065  * Get the disable state
1066  *
1067  * This gets the disable state for the widget.
1068  *
1069  * @param obj The object
1070  * @return True, if the widget is disabled
1071  * @ingroup Styles
1072  */
1073 EAPI Eina_Bool
1074 elm_object_disabled_get(const Evas_Object *obj)
1075 {
1076    return elm_widget_disabled_get(obj);
1077 }
1078
1079 /**
1080  * Get the global scaling factor
1081  *
1082  * This gets the globally configured scaling factor that is applied to all
1083  * objects.
1084  *
1085  * @return The scaling factor
1086  * @ingroup Scaling
1087  */
1088 EAPI double
1089 elm_scale_get(void)
1090 {
1091    return _elm_config->scale;
1092 }
1093
1094 /**
1095  * Set the global scaling factor
1096  *
1097  * This sets the globally configured scaling factor that is applied to all
1098  * objects.
1099  *
1100  * @param scale The scaling factor to set
1101  * @ingroup Scaling
1102  */
1103 EAPI void
1104 elm_scale_set(double scale)
1105 {
1106    if (_elm_config->scale == scale) return;
1107    _elm_config->scale = scale;
1108    _elm_rescale();
1109 }
1110
1111 /**
1112  * Set the global scaling factor for all applications on the display
1113  * 
1114  * This sets the globally configured scaling factor that is applied to all
1115  * objects for all applications.
1116  * @param scale The scaling factor to set
1117  * @ingroup Scaling
1118  */
1119 EAPI void
1120 elm_scale_all_set(double scale)
1121 {
1122 #ifdef HAVE_ELEMENTARY_X
1123    static Ecore_X_Atom atom = 0;
1124    unsigned int scale_i = (unsigned int)(scale * 1000.0);
1125
1126    if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_SCALE");
1127    ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
1128                                   atom, &scale_i, 1);
1129 #endif   
1130 }
1131
1132 /**
1133  * @defgroup Fingers Fingers
1134  * @ingroup Main
1135  *
1136  * Elementary is designed to be finger-friendly for touchscreens, and so in
1137  * addition to scaling for display resolution, it can also scale based on
1138  * finger "resolution" (or size).
1139  */
1140
1141 /**
1142  * Get the configured finger size
1143  *
1144  * This gets the globally configured finger size in pixels
1145  *
1146  * @return The finger size
1147  * @ingroup Fingers
1148  */
1149 EAPI Evas_Coord
1150 elm_finger_size_get(void)
1151 {
1152    return _elm_config->finger_size;
1153 }
1154
1155 /**
1156  * Set the configured finger size
1157  *
1158  * This sets the globally configured finger size in pixels
1159  *
1160  * @param size The finger size
1161  * @ingroup Fingers
1162  */
1163 EAPI void
1164 elm_finger_size_set(Evas_Coord size)
1165 {
1166    if (_elm_config->finger_size == size) return;
1167    _elm_config->finger_size = size;
1168    _elm_rescale();
1169 }
1170
1171 /**
1172  * Set the configured finger size for all applications on the display
1173  *
1174  * This sets the globally configured finger size in pixels for all applications
1175  * on the display
1176  *
1177  * @param size The finger size
1178  * @ingroup Fingers
1179  */
1180 EAPI void
1181 elm_finger_size_all_set(Evas_Coord size)
1182 {
1183 #ifdef HAVE_ELEMENTARY_X
1184    static Ecore_X_Atom atom = 0;
1185    unsigned int size_i = (unsigned int)size;
1186
1187    if (!atom) atom = ecore_x_atom_get("ENLIGHTENMENT_FINGER_SIZE");
1188    ecore_x_window_prop_card32_set(ecore_x_window_root_first_get(),
1189                                   atom, &size_i, 1);
1190 #endif   
1191 }
1192
1193 /**
1194  * Adjust size of an element for finger usage
1195  *
1196  * This takes width and height sizes (in pixels) as input and a size multiple
1197  * (which is how many fingers you want to place within the area), and adjusts
1198  * the size tobe large enough to accomodate finger. On return the w and h
1199  * sizes poiner do by these parameters will be modified.
1200  *
1201  * @param times_w How many fingers should fit horizontally
1202  * @param w Pointer to the width size to adjust
1203  * @param times_h How many fingers should fit vertically
1204  * @param h Pointer to the height size to adjust
1205  * @ingroup Fingers
1206  */
1207 EAPI void
1208 elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h)
1209 {
1210    if ((w) && (*w < (_elm_config->finger_size * times_w)))
1211      *w = _elm_config->finger_size * times_w;
1212    if ((h) && (*h < (_elm_config->finger_size * times_h)))
1213      *h = _elm_config->finger_size * times_h;
1214 }
1215
1216 /**
1217  * @defgroup Focus Focus
1218  * @ingroup Main
1219  *
1220  * Objects have focus. This is what determines where the keyboard input goes to
1221  * within the application window.
1222  */
1223
1224 /**
1225  * Get the focus of the object
1226  *
1227  * This gets the focused property of the object.
1228  *
1229  * @param obj The object
1230  * @return 1 if the object is focused, 0 if not.
1231  * @ingroup Focus
1232  */
1233 EAPI Eina_Bool
1234 elm_object_focus_get(Evas_Object *obj)
1235 {
1236    return elm_widget_focus_get(obj);
1237 }
1238
1239 /**
1240  * Set the focus to the object
1241  *
1242  * This sets the focus target for keyboard input to be the object indicated.
1243  *
1244  * @param obj The object
1245  * @ingroup Focus
1246  */
1247 EAPI void
1248 elm_object_focus(Evas_Object *obj)
1249 {
1250    if (!elm_widget_can_focus_get(obj)) return;
1251    elm_widget_focus_steal(obj);
1252 }
1253
1254 /**
1255  * Remove the focus from the object
1256  *
1257  * This removes the focus target for keyboard input from be the object
1258  * indicated.
1259  *
1260  * @param obj The object
1261  * @ingroup Focus
1262  */
1263 EAPI void
1264 elm_object_unfocus(Evas_Object *obj)
1265 {
1266    if (!elm_widget_can_focus_get(obj)) return;
1267    elm_widget_focused_object_clear(obj);
1268 }
1269
1270 /**
1271  * Set the ability for the object to focus
1272  *
1273  * This sets the ability for the object to be able to get keyboard focus or
1274  * not. By default all objects are able to be focused.
1275  *
1276  * @param obj The object
1277  * @param enable 1 if the object can be focused, 0 if not
1278  * @ingroup Focus
1279  */
1280 EAPI void
1281 elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable)
1282 {
1283    elm_widget_can_focus_set(obj, enable);
1284 }
1285
1286 /**
1287  * Get the ability for the object to focus
1288  *
1289  * This gets the ability for the object to be able to get keyboard focus or
1290  * not. By default all objects are able to be focused.
1291  *
1292  * @param obj The object
1293  * @return 1 if the object is allowed to be focused, 0 if not.
1294  * @ingroup Focus
1295  */
1296 EAPI Eina_Bool
1297 elm_object_focus_allow_get(const Evas_Object *obj)
1298 {
1299    return elm_widget_can_focus_get(obj);
1300 }
1301
1302 /**
1303  * @defgroup Scrollhints Scrollhints
1304  * @ingroup Main
1305  *
1306  * Objects when inside a scroller can scroll, but this may not always be
1307  * desireable in certain situations. This allows an object to hint to itself
1308  * and parents to "not scroll" in one of 2 ways.
1309  * 
1310  * 1. To hold on scrolling. This means just flicking and dragging may no
1311  * longer scroll, but pressing/dragging near an edge of the scroller will
1312  * still scroll. This is automastically used by the entry object when
1313  * selecting text.
1314  * 2. To totally freeze scrolling. This means it stops. until popped/released.
1315  */
1316
1317 /**
1318  * Push the scroll hold by 1
1319  *
1320  * This increments the scroll hold count by one. If it is more than 0 it will
1321  * take effect on the parents of the indicated object.
1322  *
1323  * @param obj The object
1324  * @ingroup Scrollhints
1325  */
1326 EAPI void
1327 elm_object_scroll_hold_push(Evas_Object *obj)
1328 {
1329    elm_widget_scroll_hold_push(obj);
1330 }
1331
1332 /**
1333  * Pop the scroll hold by 1
1334  *
1335  * This decrements the scroll hold count by one. If it is more than 0 it will
1336  * take effect on the parents of the indicated object.
1337  *
1338  * @param obj The object
1339  * @ingroup Scrollhints
1340  */
1341 EAPI void
1342 elm_object_scroll_hold_pop(Evas_Object *obj)
1343 {
1344    elm_widget_scroll_hold_pop(obj);
1345 }
1346
1347 /**
1348  * Push the scroll freeze by 1
1349  *
1350  * This increments the scroll freeze count by one. If it is more than 0 it will
1351  * take effect on the parents of the indicated object.
1352  *
1353  * @param obj The object
1354  * @ingroup Scrollhints
1355  */
1356 EAPI void
1357 elm_object_scroll_freeze_push(Evas_Object *obj)
1358 {
1359    elm_widget_scroll_freeze_push(obj);
1360 }
1361
1362 /**
1363  * Lock the scrolling of the given widget (and thus all parents)
1364  *
1365  * This locks the given object from scrolling in the X axis (and implicitly
1366  * also locks all parent scrollers too from doing the same).
1367  *
1368  * @param obj The object
1369  * @param lock The lock state (1 == locked, 0 == unlocked)
1370  * @ingroup Scrollhints
1371  */
1372 EAPI void
1373 elm_object_scroll_lock_x_set(Evas_Object *obj, Eina_Bool lock)
1374 {
1375    elm_widget_drag_lock_x_set(obj, lock);
1376 }
1377
1378 /**
1379  * Lock the scrolling of the given widget (and thus all parents)
1380  *
1381  * This locks the given object from scrolling in the Y axis (and implicitly
1382  * also locks all parent scrollers too from doing the same).
1383  *
1384  * @param obj The object
1385  * @param lock The lock state (1 == locked, 0 == unlocked)
1386  * @ingroup Scrollhints
1387  */
1388 EAPI void
1389 elm_object_scroll_lock_y_set(Evas_Object *obj, Eina_Bool lock)
1390 {
1391    elm_widget_drag_lock_y_set(obj, lock);
1392 }
1393
1394 /**
1395  * Get the scrolling lock of the given widget
1396  *
1397  * This gets the lock for X axis scrolling.
1398  *
1399  * @param obj The object
1400  * @ingroup Scrollhints
1401  */
1402 EAPI Eina_Bool
1403 elm_object_scroll_lock_x_get(const Evas_Object *obj)
1404 {
1405    return elm_widget_drag_lock_x_get(obj);
1406 }
1407
1408 /**
1409  * Get the scrolling lock of the given widget
1410  *
1411  * This gets the lock for X axis scrolling.
1412  *
1413  * @param obj The object
1414  * @ingroup Scrollhints
1415  */
1416 EAPI Eina_Bool
1417 elm_object_scroll_lock_y_get(const Evas_Object *obj)
1418 {
1419    return elm_widget_drag_lock_y_get(obj);
1420 }
1421
1422 /**
1423  * Pop the scroll freeze by 1
1424  *
1425  * This decrements the scroll freeze count by one. If it is more than 0 it will
1426  * take effect on the parents of the indicated object.
1427  *
1428  * @param obj The object
1429  * @ingroup Scrollhints
1430  */
1431 EAPI void
1432 elm_object_scroll_freeze_pop(Evas_Object *obj)
1433 {
1434    elm_widget_scroll_freeze_pop(obj);
1435 }
1436
1437
1438 /**
1439  * Check if the given Evas Object is an Elementary widget.
1440  *
1441  * @param obj the object to query.
1442  * @return @c EINA_TRUE if it is an elementary widget variant,
1443  *         @c EINA_FALSE otherwise
1444  */
1445 EAPI Eina_Bool
1446 elm_object_widget_check(const Evas_Object *obj)
1447 {
1448    return elm_widget_is(obj);
1449 }
1450
1451 /**
1452  * Get the first parent of the given object that is an Elementary widget.
1453  *
1454  * @param obj the object to query.
1455  * @return the parent object that is an Elementary widget, or @c NULL
1456  *         if no parent is, or no parents at all.
1457  */
1458 EAPI Evas_Object *
1459 elm_object_parent_widget_get(const Evas_Object *obj)
1460 {
1461    return elm_widget_parent_widget_get(obj);
1462 }
1463
1464 /**
1465  * Get the string that represents this Elementary widget.
1466  *
1467  * @note Elementary is weird and exposes itself as a single
1468  *       Evas_Object_Smart_Class of type "elm_widget", so
1469  *       evas_object_type_get() always return that, making debug and
1470  *       language bindings hard. This function tries to mitigate this
1471  *       problem, but the solution is to change Elementary to use
1472  *       proper inheritance.
1473  *
1474  * @param obj the object to query.
1475  * @return Elementary widget name, or @c NULL if not a valid widget.
1476  */
1477 EAPI const char *
1478 elm_object_widget_type_get(const Evas_Object *obj)
1479 {
1480    return elm_widget_type_get(obj);
1481 }