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