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