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