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