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