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