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