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