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